From acbb9076cd9b8b794f3c6a8836d5fd96be3786ba Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Mon, 14 Oct 2013 18:45:48 -0400 Subject: [PATCH] Use a generator goroutine and chan to create new JSON IDs --- cmd.go | 37 ++++++++++++++++++++++--------------- cmdmgr.go | 44 ++++---------------------------------------- sockets.go | 16 +++++++++++----- 3 files changed, 37 insertions(+), 60 deletions(-) diff --git a/cmd.go b/cmd.go index 142a2bc..6bf2b90 100644 --- a/cmd.go +++ b/cmd.go @@ -215,11 +215,7 @@ func getCurHeight() (height int64) { return height } - seq.Lock() - n := seq.n - seq.n++ - seq.Unlock() - + n := <-NewJsonID m, err := btcjson.CreateMessageWithId("getblockcount", fmt.Sprintf("btcwallet(%v)", n)) if err != nil { @@ -285,11 +281,7 @@ func (w *BtcWallet) CalculateBalance(confirmations int) float64 { // each address stored in a wallet and sets up a new reply handler for // these notifications. func (w *BtcWallet) Track() { - seq.Lock() - n := seq.n - seq.n++ - seq.Unlock() - + n := <-NewJsonID w.mtx.Lock() w.NewBlockTxSeqN = n w.mtx.Unlock() @@ -310,11 +302,7 @@ func (w *BtcWallet) Track() { // blocks[0]. If len(blocks) is 2 or greater, the rescan will be // performed for the block range blocks[0]...blocks[1] (inclusive). func (w *BtcWallet) RescanForAddress(addr string, blocks ...int) { - seq.Lock() - n := seq.n - seq.n++ - seq.Unlock() - + n := <-NewJsonID params := []interface{}{addr} if len(blocks) > 0 { params = append(params, blocks[0]) @@ -493,6 +481,22 @@ func (w *BtcWallet) newBlockTxHandler(result interface{}, e *btcjson.Error) bool return false } +// NewJsonID is used to receive the next unique JSON ID for btcd +// requests, starting from zero and incrementing by one after each +// read. +var NewJsonID = make(chan uint64) + +// JsonIDGenerator sends incremental integers across a channel. This +// is meant to provide a unique value for the JSON ID field for btcd +// messages. +func JsonIDGenerator(c chan uint64) { + var n uint64 + for { + c <- n + n++ + } +} + func main() { tcfg, _, err := loadConfig() if err != nil { @@ -523,6 +527,9 @@ func main() { } }() + // Begin generating new IDs for JSON calls. + go JsonIDGenerator(NewJsonID) + for { replies := make(chan error) done := make(chan int) diff --git a/cmdmgr.go b/cmdmgr.go index 0f34a48..f8b2e44 100644 --- a/cmdmgr.go +++ b/cmdmgr.go @@ -23,7 +23,6 @@ import ( "github.com/conformal/btcjson" "github.com/conformal/btcwallet/wallet" "github.com/conformal/btcwire" - "sync" "time" ) @@ -127,25 +126,6 @@ var ( } ) -var ( - // seq holds the btcwallet sequence number for frontend messages - // which must be sent to and received from btcd. A Mutex protects - // against concurrent access. - seq = struct { - sync.Mutex - n uint64 - }{} - - // replyRouter maps uint64 ids to reply channels, so btcd replies can - // be routed to the correct frontend. - replyRouter = struct { - sync.Mutex - m map[uint64]chan []byte - }{ - m: make(map[uint64]chan []byte), - } -) - // ProcessFrontendMsg checks the message sent from a frontend. If the // message method is one that must be handled by btcwallet, the request // is processed here. Otherwise, the message is sent to btcd. @@ -190,11 +170,7 @@ func ProcessFrontendMsg(reply chan []byte, msg []byte) { default: // btcwallet does not understand method. Pass to btcd. - seq.Lock() - n := seq.n - seq.n++ - seq.Unlock() - + n := <-NewJsonID var id interface{} = fmt.Sprintf("btcwallet(%v)-%v", n, jsonMsg.Id) jsonMsg.Id = &id @@ -489,11 +465,7 @@ func SendFrom(reply chan []byte, msg *btcjson.Message) { } // Send rawtx off to btcd - seq.Lock() - n := seq.n - seq.n++ - seq.Unlock() - + n := <-NewJsonID var id interface{} = fmt.Sprintf("btcwallet(%v)-%v", n, msg.Id) m, err := btcjson.CreateMessageWithId("sendrawtransaction", id, hex.EncodeToString(rawtx)) @@ -606,11 +578,7 @@ func SendMany(reply chan []byte, msg *btcjson.Message) { } // Send rawtx off to btcd - seq.Lock() - n := seq.n - seq.n++ - seq.Unlock() - + n := <-NewJsonID var id interface{} = fmt.Sprintf("btcwallet(%v)-%v", n, msg.Id) m, err := btcjson.CreateMessageWithId("sendrawtransaction", id, hex.EncodeToString(rawtx)) @@ -734,11 +702,7 @@ func CreateEncryptedWallet(reply chan []byte, msg *btcjson.Message) { } // Grab a new unique sequence number for tx notifications in new blocks. - seq.Lock() - n := seq.n - seq.n++ - seq.Unlock() - + n := <-NewJsonID bw := &BtcWallet{ Wallet: w, name: wname, diff --git a/sockets.go b/sockets.go index a6b1574..429f079 100644 --- a/sockets.go +++ b/sockets.go @@ -58,7 +58,7 @@ var ( // Messages sent to this channel are sent to each connected frontend. frontendNotificationMaster = make(chan []byte, 100) - // replyHandlers maps between a sequence number (passed as part of + // replyHandlers maps between a unique number (passed as part of // the JSON Id field) and a function to handle a reply or notification // from btcd. As requests are received, this map is checked for a // handler function to route the reply to. If the function returns @@ -69,6 +69,15 @@ var ( }{ m: make(map[uint64]func(interface{}, *btcjson.Error) bool), } + + // replyRouter maps unique uint64 ids to reply channels, so btcd + // replies can be routed to the correct frontend. + replyRouter = struct { + sync.Mutex + m map[uint64]chan []byte + }{ + m: make(map[uint64]chan []byte), + } ) // frontendListenerDuplicator listens for new wallet listener channels @@ -484,10 +493,7 @@ func BtcdConnect(reply chan error) { // Bitcoin networks). If the sanity checks pass, all wallets are set to // be tracked against chain notifications from this btcd connection. func BtcdHandshake(ws *websocket.Conn) { - seq.Lock() - n := seq.n - seq.n++ - seq.Unlock() + n := <-NewJsonID msg := btcjson.Message{ Method: "getcurrentnet", Id: fmt.Sprintf("btcwallet(%v)", n),