diff --git a/cmd.go b/cmd.go index 4a16488..5e21c85 100644 --- a/cmd.go +++ b/cmd.go @@ -107,17 +107,15 @@ func (s *BtcWalletStore) Rollback(height int64, hash *btcwire.ShaHash) { func (w *BtcWallet) Rollback(height int64, hash *btcwire.ShaHash) { w.UtxoStore.Lock() w.UtxoStore.dirty = w.UtxoStore.dirty || w.UtxoStore.s.Rollback(height, hash) - if w.UtxoStore.dirty { - AddDirtyAccount(w) - } w.UtxoStore.Unlock() w.TxStore.Lock() w.TxStore.dirty = w.TxStore.dirty || w.TxStore.s.Rollback(height, hash) - if w.TxStore.dirty { - AddDirtyAccount(w) - } w.TxStore.Unlock() + + if err := w.writeDirtyToDisk(); err != nil { + log.Errorf("cannot sync dirty wallet: %v", err) + } } // walletdir returns the directory path which holds the wallet, utxo, @@ -455,8 +453,11 @@ func (w *BtcWallet) newBlockTxHandler(result interface{}, e *btcjson.Error) bool txs := w.TxStore.s w.TxStore.s = append(txs, t) w.TxStore.dirty = true - AddDirtyAccount(w) w.TxStore.Unlock() + + if err = w.writeDirtyToDisk(); err != nil { + log.Errorf("cannot sync dirty wallet: %v", err) + } }() // Do not add output to utxo store if spent. @@ -476,8 +477,11 @@ func (w *BtcWallet) newBlockTxHandler(result interface{}, e *btcjson.Error) bool w.UtxoStore.Lock() w.UtxoStore.s = append(w.UtxoStore.s, u) w.UtxoStore.dirty = true - AddDirtyAccount(w) w.UtxoStore.Unlock() + if err = w.writeDirtyToDisk(); err != nil { + log.Errorf("cannot sync dirty wallet: %v", err) + } + confirmed := w.CalculateBalance(6) unconfirmed := w.CalculateBalance(0) - confirmed NotifyWalletBalance(frontendNotificationMaster, w.name, confirmed) @@ -538,9 +542,6 @@ func main() { // Begin generating new IDs for JSON calls. go JSONIDGenerator(NewJSONID) - // Begin wallet to disk syncer. - go DirtyAccountUpdater() - for { replies := make(chan error) done := make(chan int) diff --git a/cmdmgr.go b/cmdmgr.go index 82f4cea..e0671db 100644 --- a/cmdmgr.go +++ b/cmdmgr.go @@ -334,6 +334,10 @@ func GetNewAddress(reply chan []byte, msg *btcjson.Message) { ReplyError(reply, msg.Id, &e) return } + w.dirty = true + if err = w.writeDirtyToDisk(); err != nil { + log.Errorf("cannot sync dirty wallet: %v", err) + } w.ReqNewTxsForAddress(addr) ReplySuccess(reply, msg.Id, addr) } else { @@ -493,8 +497,10 @@ func SendFrom(reply chan []byte, msg *btcjson.Message) { modified := w.UtxoStore.s.Remove(inputs) if modified { w.UtxoStore.dirty = true - AddDirtyAccount(w) w.UtxoStore.Unlock() + if err := w.writeDirtyToDisk(); err != nil { + log.Errorf("cannot sync dirty wallet: %v", err) + } // Notify all frontends of new account balances. confirmed := w.CalculateBalance(6) @@ -638,8 +644,10 @@ func SendMany(reply chan []byte, msg *btcjson.Message) { modified := w.UtxoStore.s.Remove(inputs) if modified { w.UtxoStore.dirty = true - AddDirtyAccount(w) w.UtxoStore.Unlock() + if err := w.writeDirtyToDisk(); err != nil { + log.Errorf("cannot sync dirty wallet: %v", err) + } // Notify all frontends of new account balances. confirmed := w.CalculateBalance(6) @@ -778,7 +786,9 @@ func CreateEncryptedWallet(reply chan []byte, msg *btcjson.Message) { bw.Track() wallets.m[wname] = bw - AddDirtyAccount(bw) + if err := bw.writeDirtyToDisk(); err != nil { + log.Errorf("cannot sync dirty wallet: %v", err) + } ReplySuccess(reply, msg.Id, nil) } diff --git a/disksync.go b/disksync.go index 798dc4b..5980ed3 100644 --- a/disksync.go +++ b/disksync.go @@ -23,43 +23,11 @@ import ( "time" ) -var dirtyAccountSet = make(map[*BtcWallet]bool) -var addDirtyAccount = make(chan *BtcWallet) - -// DirtyAccountUpdater is responsible for listening for listens for new -// dirty wallets (changed in memory with updaets not yet saved to disk) -// to add to dirtyAccountSet. This is designed to run as a single goroutine. -func DirtyAccountUpdater() { - timer := time.Tick(time.Minute) - for { - select { - case w := <-addDirtyAccount: - dirtyAccountSet[w] = true - - case <-timer: - for w := range dirtyAccountSet { - if err := w.writeDirtyToDisk(); err != nil { - log.Errorf("cannot sync dirty wallet '%v': %v", w.name, err) - } else { - delete(dirtyAccountSet, w) - log.Infof("removed dirty wallet '%v'", w.name) - } - } - } - } -} - -// AddDirtyAccount adds w to a set of items to be synced to disk. The -// dirty flag must still be set on the various dirty elements of the -// account (wallet, transactions, and/or utxos) or nothing will be -// written to disk during the next scheduled sync. -func AddDirtyAccount(w *BtcWallet) { - addDirtyAccount <- w -} - // writeDirtyToDisk checks for the dirty flag on an account's wallet, // txstore, and utxostore, writing them to disk if any are dirty. func (w *BtcWallet) writeDirtyToDisk() error { + fmt.Println("entered") + // Temporary files append the current time to the normal file name. // In caes of failure, the most recent temporary file can be inspected // for validity, and moved to replace the main file. @@ -72,8 +40,8 @@ func (w *BtcWallet) writeDirtyToDisk() error { // Wallet if w.dirty { - w.mtx.RLock() - defer w.mtx.RUnlock() + w.mtx.Lock() + defer w.mtx.Unlock() tmpfilepath := wfilepath + "-" + timeStr tmpfile, err := os.Create(tmpfilepath) if err != nil { @@ -88,12 +56,14 @@ func (w *BtcWallet) writeDirtyToDisk() error { if err = os.Rename(tmpfilepath, wfilepath); err != nil { return err } + + w.dirty = false } // Transactions if w.TxStore.dirty { - w.TxStore.RLock() - defer w.TxStore.RUnlock() + w.TxStore.Lock() + defer w.TxStore.Unlock() tmpfilepath := txfilepath + "-" + timeStr tmpfile, err := os.Create(tmpfilepath) if err != nil { @@ -108,12 +78,14 @@ func (w *BtcWallet) writeDirtyToDisk() error { if err = os.Rename(tmpfilepath, txfilepath); err != nil { return err } + + w.TxStore.dirty = false } // UTXOs if w.UtxoStore.dirty { - w.UtxoStore.RLock() - defer w.UtxoStore.RUnlock() + w.UtxoStore.Lock() + defer w.UtxoStore.Unlock() tmpfilepath := utxofilepath + "-" + timeStr tmpfile, err := os.Create(tmpfilepath) if err != nil { @@ -128,6 +100,8 @@ func (w *BtcWallet) writeDirtyToDisk() error { if err = os.Rename(tmpfilepath, utxofilepath); err != nil { return err } + + w.UtxoStore.dirty = false } return nil