func (s *WorkerState) offer(log bitwrk.Logger) { defer log.Printf("Stopped offering") s.cond.L.Lock() defer s.cond.L.Unlock() interrupt := make(chan bool, 1) for { // Interrupt if unregistered, stop iterating if s.Unregistered { log.Printf("No longer registered") interrupt <- true break } if s.Blockers == 0 { s.LastError = "" if sell, err := s.m.activityManager.NewSell(s); err != nil { s.LastError = fmt.Sprintf("Error creating sell: %v", err) log.Println(s.LastError) s.blockFor(20 * time.Second) } else { s.Blockers++ go s.executeSell(log, sell, interrupt) } } s.cond.Wait() } }
// Manages the complete lifecycle of a sell func (a *SellActivity) PerformSell(log bitwrk.Logger, receiveManager *ReceiveManager, interrupt <-chan bool) error { defer log.Println("Sell finished") err := a.doPerformSell(log, receiveManager, interrupt) if err != nil { a.lastError = err } a.alive = false return err }
func (s *WorkerState) executeSell(log bitwrk.Logger, sell *SellActivity, interrupt <-chan bool) { defer func() { s.cond.L.Lock() s.Blockers-- s.cond.Broadcast() s.cond.L.Unlock() }() defer sell.Dispose() if err := sell.PerformSell(log.Newf("Sell #%v", sell.GetKey()), s.m.receiveManager, interrupt); err != nil { s.LastError = fmt.Sprintf("Error performing sell (delaying next sell by 20s): %v", err) log.Println(s.LastError) s.cond.L.Lock() s.blockFor(20 * time.Second) s.cond.L.Unlock() } else { log.Printf("Returned from PerformSell successfully") } }
func (a *SellActivity) HandleWork(log bitwrk.Logger, workFile cafs.File, buyerSecret bitwrk.Thash) (io.ReadCloser, error) { // Wait for buyer to establish active := true var workHash, workSecretHash *bitwrk.Thash log.Printf("Watching transaction state...") a.waitWhile(func() bool { active = a.tx.State == bitwrk.StateActive workHash, workSecretHash = a.tx.WorkHash, a.tx.WorkSecretHash log.Printf(" state: %v phase: %v", a.tx.State, a.tx.Phase) return active && a.tx.Phase != bitwrk.PhaseTransmitting }) if !active { return nil, fmt.Errorf("Transaction timed out waiting for buyer to establish") } // Verify work hash if *workHash != bitwrk.Thash(workFile.Key()) { return nil, fmt.Errorf("WorkHash and received data do not match") } if err := verifyBuyerSecret(workHash, workSecretHash, &buyerSecret); err != nil { return nil, err } log.Println("Got valid work data. Publishing buyer's secret.") if err := SendTxMessagePublishBuyerSecret(a.txId, a.identity, &buyerSecret); err != nil { return nil, fmt.Errorf("Error publishing buyer's secret: %v", err) } log.Println("Starting to work...") r, err := a.dispatchWork(log, workFile) if err != nil { log.Printf("Rejecting work because of error '%v'", err) if err := SendTxMessageRejectWork(a.txId, a.identity); err != nil { log.Printf("Rejecting work failed: %v", err) } } return r, err }
func (a *Trade) beginTrade(log bitwrk.Logger, interrupt <-chan bool) error { // wait for grant or reject log.Println("Waiting for permission") // Get a permission for the sell if err := a.awaitPermission(interrupt); err != nil { return fmt.Errorf("Error awaiting permission: %v", err) } log.Printf("Got permission. Price: %v", a.price) // Prevent too many unmatched bids on server key := fmt.Sprintf("%v-%v", a.bidType, a.article) if err := a.manager.checkoutToken(key, NumUnmatchedBids, interrupt); err != nil { return err } defer a.manager.returnToken(key) if err := a.awaitBid(); err != nil { return fmt.Errorf("Error awaiting bid: %v", err) } log.Printf("Got bid id: %v", a.bidId) if err := a.awaitTransaction(log); err != nil { return fmt.Errorf("Error awaiting transaction: %v", err) } log.Printf("Got transaction id: %v", a.txId) if tx, etag, err := FetchTx(a.txId, ""); err != nil { return err } else { a.tx = tx a.txETag = etag } return nil }