Use a single handler (per wallet) for all tx notifications.

This commit is contained in:
Josh Rickmar 2013-09-05 11:19:48 -04:00
parent 897fa1448b
commit 019df772b1
2 changed files with 132 additions and 112 deletions

42
cmd.go
View file

@ -81,6 +81,7 @@ type BtcWallet struct {
*wallet.Wallet
mtx sync.RWMutex
dirty bool
NewBlockTxSeqN uint64
UtxoStore struct {
sync.RWMutex
dirty bool
@ -183,13 +184,35 @@ func OpenWallet(cfg *config, account string) (*BtcWallet, error) {
}
func (w *BtcWallet) Track() {
seq.Lock()
n := seq.n
seq.n++
seq.Unlock()
// Use goroutines and a WaitGroup to prevent unnecessary waiting for
// released locks.
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
wallets.Lock()
name := w.Name()
if wallets.m[name] == nil {
wallets.m[name] = w
}
wallets.Unlock()
}()
go func() {
defer wg.Done()
w.mtx.Lock()
w.NewBlockTxSeqN = n
w.mtx.Unlock()
}()
wg.Wait()
replyHandlers.Lock()
replyHandlers.m[n] = w.NewBlockTxHandler
replyHandlers.Unlock()
for _, addr := range w.GetActiveAddresses() {
go w.ReqNewTxsForAddress(addr)
}
@ -231,10 +254,9 @@ func (w *BtcWallet) RescanForAddress(addr string, blocks ...int) {
}
func (w *BtcWallet) ReqNewTxsForAddress(addr string) {
seq.Lock()
n := seq.n
seq.n++
seq.Unlock()
w.mtx.RLock()
n := w.NewBlockTxSeqN
w.mtx.RUnlock()
m := &btcjson.Message{
Jsonrpc: "1.0",
@ -244,8 +266,10 @@ func (w *BtcWallet) ReqNewTxsForAddress(addr string) {
}
msg, _ := json.Marshal(m)
replyHandlers.Lock()
replyHandlers.m[n] = func(result interface{}) bool {
btcdMsgs <- msg
}
func (w *BtcWallet) NewBlockTxHandler(result interface{}) bool {
// TODO(jrick): btcd also sends the block hash in the reply.
// Do we want it saved as well?
v, ok := result.(map[string]interface{})
@ -289,7 +313,7 @@ func (w *BtcWallet) ReqNewTxsForAddress(addr string) {
return false
}
// btcd sends the tx hashe as a BE string. Convert to a
// btcd sends the tx hash as a BE string. Convert to a
// LE ShaHash.
txhash, err := btcwire.NewShaHashFromStr(txhashBE)
if err != nil {
@ -340,7 +364,3 @@ func (w *BtcWallet) ReqNewTxsForAddress(addr string) {
// Never remove this handler.
return false
}
replyHandlers.Unlock()
btcdMsgs <- msg
}

View file

@ -319,7 +319,7 @@ func ListenAndServe() error {
// requests for each channel in the set.
go frontendListenerDuplicator()
// XXX(jrick): We need some sort of authentication before websocket
// TODO(jrick): We need some sort of authentication before websocket
// connections are allowed, and perhaps TLS on the server as well.
http.Handle("/frontend", websocket.Handler(frontendReqsNotifications))
if err := http.ListenAndServe(fmt.Sprintf(":%d", cfg.SvrPort), nil); err != nil {