From cdbf7c1e8c26a34e656c367e86a82f2e9cb7adec Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 17 Aug 2016 22:27:53 -0700 Subject: [PATCH] locker: automatically wrap callbacks. --- lib/bcoin/async.js | 16 ++------ lib/bcoin/chain.js | 29 ++++++-------- lib/bcoin/locker.js | 22 +++++++++-- lib/bcoin/mempool.js | 27 ++++++------- lib/bcoin/pool.js | 14 +++---- lib/bcoin/txdb.js | 27 +++++-------- lib/bcoin/wallet.js | 90 +++++++++++++++---------------------------- lib/bcoin/walletdb.js | 51 +++++++++++++----------- 8 files changed, 118 insertions(+), 158 deletions(-) diff --git a/lib/bcoin/async.js b/lib/bcoin/async.js index 37a67213..ae22963b 100644 --- a/lib/bcoin/async.js +++ b/lib/bcoin/async.js @@ -39,7 +39,6 @@ utils.inherits(AsyncObject, EventEmitter); AsyncObject.prototype.open = function open(callback) { var self = this; - var unlock; callback = utils.ensure(callback); @@ -52,11 +51,8 @@ AsyncObject.prototype.open = function open(callback) { return this.once('open', callback); if (this.locker) { - unlock = this.locker.lock(utils.nop, []); - - assert(unlock, 'Cannot call methods before load.'); - - callback = utils.wrap(callback, unlock); + callback = this.locker.lock(open, [callback]); + assert(callback, 'Cannot call methods before load.'); } this.emit('preopen'); @@ -87,7 +83,6 @@ AsyncObject.prototype.open = function open(callback) { AsyncObject.prototype.close = function close(callback) { var self = this; - var unlock; callback = utils.ensure(callback); @@ -100,12 +95,9 @@ AsyncObject.prototype.close = function close(callback) { return this.on('close', callback); if (this.locker) { - unlock = this.locker.lock(close, [callback]); - - if (!unlock) + callback = this.locker.lock(close, [callback]); + if (!callback) return; - - callback = utils.wrap(callback, unlock); } this.emit('preclose'); diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 8dc2a098..6f27c3f5 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -1099,13 +1099,12 @@ Chain.prototype.setBestChain = function setBestChain(entry, block, prev, callbac Chain.prototype.reset = function reset(height, callback, force) { var self = this; - var unlock = this._lock(reset, [height, callback], force); - if (!unlock) + callback = this._lock(reset, [height, callback], force); + + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.db.reset(height, function(err, result) { if (err) return callback(err); @@ -1129,13 +1128,12 @@ Chain.prototype.reset = function reset(height, callback, force) { Chain.prototype.resetTime = function resetTime(ts, callback, force) { var self = this; - var unlock = this._lock(resetTime, [ts, callback], force); - if (!unlock) + callback = this._lock(resetTime, [ts, callback], force); + + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.byTime(ts, function(err, entry) { if (err) return callback(err); @@ -1177,17 +1175,14 @@ Chain.prototype.isBusy = function isBusy() { Chain.prototype.add = function add(block, callback, force) { var self = this; var ret = {}; - var unlock; assert(this.loaded); - unlock = this._lock(add, [block, callback], force); + callback = this._lock(add, [block, callback], force); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - (function next(block, initial) { var hash = block.hash('hex'); var prevBlock = block.prevBlock; @@ -1717,15 +1712,13 @@ Chain.prototype.getLocator = function getLocator(start, callback, force) { var self = this; var hashes = []; var step = 1; - var unlock, height; + var height; - unlock = this._lock(getLocator, [start, callback], force); + callback = this._lock(getLocator, [start, callback], force); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - if (start == null) start = this.tip.hash; diff --git a/lib/bcoin/locker.js b/lib/bcoin/locker.js index a6aa1a3e..49573ead 100644 --- a/lib/bcoin/locker.js +++ b/lib/bcoin/locker.js @@ -60,13 +60,21 @@ Locker.prototype.hasPending = function hasPending(key) { Locker.prototype.lock = function lock(func, args, force) { var self = this; - var obj, called; + var obj, called, arg, callback; + + if (args.length > 0) { + arg = args[args.length - 1]; + if (typeof arg === 'function') + callback = arg; + } if (force) { assert(this.busy); - return function unlock() { + return function unlock(err, res1, res2) { assert(!called); called = true; + if (callback) + callback(err, res1, res2); }; } @@ -82,7 +90,7 @@ Locker.prototype.lock = function lock(func, args, force) { this.busy = true; - return function unlock() { + return function unlock(err, res1, res2) { var item, obj; assert(!called); @@ -95,8 +103,11 @@ Locker.prototype.lock = function lock(func, args, force) { self.emit('drain'); } - if (self.jobs.length === 0) + if (self.jobs.length === 0) { + if (callback) + callback(err, res1, res2); return; + } item = self.jobs.shift(); @@ -107,6 +118,9 @@ Locker.prototype.lock = function lock(func, args, force) { } item[0].apply(self.parent, item[1]); + + if (callback) + callback(err, res1, res2); }; }; diff --git a/lib/bcoin/mempool.js b/lib/bcoin/mempool.js index 8b2d14df..43dc8ad4 100644 --- a/lib/bcoin/mempool.js +++ b/lib/bcoin/mempool.js @@ -201,15 +201,13 @@ Mempool.prototype.addBlock = function addBlock(block, callback) { Mempool.prototype.removeBlock = function removeBlock(block, callback, force) { var self = this; - var unlock, entry; + var entry; - unlock = this._lock(removeBlock, [block, callback], force); + callback = this._lock(removeBlock, [block, callback], force); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - utils.forEachSerial(block.txs, function(tx, next) { var hash = tx.hash('hex'); @@ -519,18 +517,17 @@ Mempool.prototype.addTX = function addTX(tx, callback, force) { var lockFlags = constants.flags.STANDARD_LOCKTIME_FLAGS; var hash = tx.hash('hex'); var ret = {}; - var unlock, entry; + var entry; - unlock = this._lock(addTX, [tx, callback], force); + callback = this._lock(addTX, [tx, callback], force); - if (!unlock) + if (!callback) return; - assert(!tx.mutable, 'Cannot add mutable TX to mempool.'); - - callback = utils.wrap(callback, unlock); callback = utils.asyncify(callback); + assert(!tx.mutable, 'Cannot add mutable TX to mempool.'); + if (tx.ts !== 0) { return callback(new VerifyError(tx, 'alreadyknown', @@ -661,15 +658,13 @@ Mempool.prototype.addTX = function addTX(tx, callback, force) { Mempool.prototype.addUnchecked = function addUnchecked(entry, callback, force) { var self = this; - var unlock, resolved; + var resolved; - unlock = this._lock(addUnchecked, [entry, callback], force); + callback = this._lock(addUnchecked, [entry, callback], force); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.trackEntry(entry); this.emit('tx', entry.tx); diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index 7a63a631..5f037791 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -690,13 +690,12 @@ Pool.prototype.stopSync = function stopSync() { Pool.prototype._handleHeaders = function _handleHeaders(headers, peer, callback) { var self = this; var ret = {}; - var unlock = this.locker.lock(_handleHeaders, [headers, peer, callback]); var last; - if (!unlock) - return; + callback = this.locker.lock(_handleHeaders, [headers, peer, callback]); - callback = utils.wrap(callback, unlock); + if (!callback) + return; if (!this.options.headers) return callback(); @@ -841,13 +840,12 @@ Pool.prototype._handleBlocks = function _handleBlocks(hashes, peer, callback) { Pool.prototype._handleInv = function _handleInv(hashes, peer, callback) { var self = this; - var unlock = this.locker.lock(_handleInv, [hashes, peer, callback]); - if (!unlock) + callback = this.locker.lock(_handleInv, [hashes, peer, callback]); + + if (!callback) return; - callback = utils.wrap(callback, unlock); - // Ignore for now if we're still syncing if (!this.synced && peer !== this.peers.load) return callback(); diff --git a/lib/bcoin/txdb.js b/lib/bcoin/txdb.js index ca99579c..cadd487b 100644 --- a/lib/bcoin/txdb.js +++ b/lib/bcoin/txdb.js @@ -680,13 +680,12 @@ TXDB.prototype._resolveOrphans = function _resolveOrphans(tx, index, callback) { TXDB.prototype.add = function add(tx, info, callback) { var self = this; - var unlock = this._lock(add, [tx, info, callback]); var hash, i, path, account; - if (!unlock) - return; + callback = this._lock(add, [tx, info, callback]); - callback = utils.wrap(callback, unlock); + if (!callback) + return; assert(!tx.mutable, 'Cannot add mutable TX to wallet.'); @@ -1074,13 +1073,11 @@ TXDB.prototype._confirm = function _confirm(tx, info, callback) { */ TXDB.prototype.remove = function remove(hash, callback, force) { - var unlock = this._lock(remove, [hash, callback], force); + callback = this._lock(remove, [hash, callback], force); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - this._removeRecursive(hash, function(err, result, info) { if (err) return callback(err); @@ -1211,13 +1208,12 @@ TXDB.prototype._remove = function remove(tx, info, callback) { TXDB.prototype.unconfirm = function unconfirm(hash, callback, force) { var self = this; - var unlock = this._lock(unconfirm, [hash, callback], force); - if (!unlock) + callback = this._lock(unconfirm, [hash, callback], force); + + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.getTX(hash, function(err, tx) { if (err) return callback(err); @@ -2271,7 +2267,6 @@ TXDB.prototype.getAccountBalance = function getBalance(account, callback) { TXDB.prototype.zap = function zap(account, age, callback, force) { var self = this; - var unlock; if (typeof age === 'function') { force = callback; @@ -2280,13 +2275,11 @@ TXDB.prototype.zap = function zap(account, age, callback, force) { account = null; } - unlock = this._lock(zap, [account, age, callback], force); + callback = this._lock(zap, [account, age, callback], force); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - if (!utils.isUInt32(age)) return callback(new Error('Age must be a number.')); diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index d3c0c5ee..76fae68c 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -238,7 +238,6 @@ Wallet.prototype.destroy = function destroy(callback) { Wallet.prototype.addKey = function addKey(account, key, callback) { var self = this; - var unlock; if (typeof key === 'function') { callback = key; @@ -246,13 +245,11 @@ Wallet.prototype.addKey = function addKey(account, key, callback) { account = 0; } - unlock = this.writeLock.lock(addKey, [account, key, callback]); + callback = this.writeLock.lock(addKey, [account, key, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.getAccount(account, function(err, account) { if (err) return callback(err); @@ -285,7 +282,6 @@ Wallet.prototype.addKey = function addKey(account, key, callback) { Wallet.prototype.removeKey = function removeKey(account, key, callback) { var self = this; - var unlock; if (typeof key === 'function') { callback = key; @@ -293,13 +289,11 @@ Wallet.prototype.removeKey = function removeKey(account, key, callback) { account = 0; } - unlock = this.writeLock.lock(removeKey, [account, key, callback]); + callback = this.writeLock.lock(removeKey, [account, key, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.getAccount(account, function(err, account) { if (err) return callback(err); @@ -332,7 +326,6 @@ Wallet.prototype.removeKey = function removeKey(account, key, callback) { Wallet.prototype.setPassphrase = function setPassphrase(old, new_, callback) { var self = this; - var unlock; if (typeof new_ === 'function') { callback = new_; @@ -340,13 +333,11 @@ Wallet.prototype.setPassphrase = function setPassphrase(old, new_, callback) { old = null; } - unlock = this.writeLock.lock(setPassphrase, [old, new_, callback]); + callback = this.writeLock.lock(setPassphrase, [old, new_, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.master.decrypt(old, function(err) { if (err) return callback(err); @@ -370,20 +361,17 @@ Wallet.prototype.setPassphrase = function setPassphrase(old, new_, callback) { Wallet.prototype.retoken = function retoken(passphrase, callback) { var self = this; - var unlock; if (typeof passphrase === 'function') { callback = passphrase; passphrase = null; } - unlock = this.writeLock.lock(retoken, [passphrase, callback]); + callback = this.writeLock.lock(retoken, [passphrase, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.unlock(passphrase, null, function(err, master) { if (err) return callback(err); @@ -482,15 +470,13 @@ Wallet.prototype.getToken = function getToken(master, nonce) { Wallet.prototype.createAccount = function createAccount(options, callback, force) { var self = this; - var key, unlock; + var key; - unlock = this.writeLock.lock(createAccount, [options, callback], force); + callback = this.writeLock.lock(createAccount, [options, callback], force); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.unlock(options.passphrase, options.timeout, function(err, master) { if (err) return callback(err); @@ -647,7 +633,6 @@ Wallet.prototype.createChange = function createChange(account, callback) { Wallet.prototype.createAddress = function createAddress(account, change, callback) { var self = this; - var unlock; if (typeof change === 'function') { callback = change; @@ -655,13 +640,11 @@ Wallet.prototype.createAddress = function createAddress(account, change, callbac account = 0; } - unlock = this.writeLock.lock(createAddress, [account, change, callback]); + callback = this.writeLock.lock(createAddress, [account, change, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.getAccount(account, function(err, account) { if (err) return callback(err); @@ -815,7 +798,7 @@ Wallet.prototype.getPaths = function getPaths(account, callback) { Wallet.prototype.fund = function fund(tx, options, callback, force) { var self = this; - var unlock, rate; + var rate; if (typeof options === 'function') { callback = options; @@ -827,13 +810,11 @@ Wallet.prototype.fund = function fund(tx, options, callback, force) { // We use a lock here to ensure we // don't end up double spending coins. - unlock = this.fundLock.lock(fund, [tx, options, callback], force); + callback = this.fundLock.lock(fund, [tx, options, callback], force); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - if (!this.initialized) return callback(new Error('Wallet is not initialized.')); @@ -965,13 +946,12 @@ Wallet.prototype.createTX = function createTX(options, callback, force) { Wallet.prototype.send = function send(options, callback) { var self = this; - var unlock = this.fundLock.lock(send, [options, callback]); - if (!unlock) + callback = this.fundLock.lock(send, [options, callback]); + + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.createTX(options, function(err, tx) { if (err) return callback(err); @@ -1195,15 +1175,13 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(info, callback) { var self = this; var receive = []; var accounts = {}; - var i, path, unlock; + var i, path; - unlock = this.writeLock.lock(syncOutputDepth, [info, callback]); + callback = this.writeLock.lock(syncOutputDepth, [info, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.start(); for (i = 0; i < info.paths.length; i++) { @@ -2912,17 +2890,14 @@ MasterKey.fromOptions = function fromOptions(options) { * @param {Function} callback - Returns [Error, {@link HDPrivateKey}]. */ -MasterKey.prototype.unlock = function _unlock(passphrase, timeout, callback) { +MasterKey.prototype.unlock = function unlock(passphrase, timeout, callback) { var self = this; - var unlock; - unlock = this.locker.lock(_unlock, [passphrase, timeout, callback]); + callback = this.locker.lock(unlock, [passphrase, timeout, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - if (this.key) return callback(null, this.key); @@ -3008,15 +2983,12 @@ MasterKey.prototype.destroy = function destroy() { MasterKey.prototype.decrypt = function decrypt(passphrase, callback) { var self = this; - var unlock; - unlock = this.locker.lock(decrypt, [passphrase, callback]); + callback = this.locker.lock(decrypt, [passphrase, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - if (!this.encrypted) { assert(this.key); return callback(); @@ -3053,15 +3025,13 @@ MasterKey.prototype.decrypt = function decrypt(passphrase, callback) { MasterKey.prototype.encrypt = function encrypt(passphrase, callback) { var self = this; - var unlock, data, iv; + var data, iv; - unlock = this.locker.lock(encrypt, [passphrase, callback]); + callback = this.locker.lock(encrypt, [passphrase, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - if (this.encrypted) return; diff --git a/lib/bcoin/walletdb.js b/lib/bcoin/walletdb.js index 92b734db..1d06ac71 100644 --- a/lib/bcoin/walletdb.js +++ b/lib/bcoin/walletdb.js @@ -537,15 +537,13 @@ WalletDB.prototype.get = function get(wid, callback) { WalletDB.prototype._get = function get(wid, callback) { var self = this; - var unlock, wallet; + var wallet; - unlock = this.readLock.lock(wid, get, [wid, callback]); + callback = this.readLock.lock(wid, get, [wid, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - wallet = this.wallets[wid]; if (wallet) @@ -615,13 +613,11 @@ WalletDB.prototype.create = function create(options, callback) { options = {}; } - unlock = this.writeLock.lock(options.id, create, [options, callback]); + callback = this.writeLock.lock(options.id, create, [options, callback]); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - this.has(options.id, function(err, exists) { if (err) return callback(err); @@ -1343,15 +1339,13 @@ WalletDB.prototype.getWalletsByTX = function getWalletsByTX(hash, callback) { WalletDB.prototype.addBlock = function addBlock(entry, txs, callback, force) { var self = this; - var block, matches, hash, unlock; + var block, matches, hash; - unlock = this.txLock.lock(addBlock, [entry, txs, callback], force); + callback = this.txLock.lock(addBlock, [entry, txs, callback], force); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - if (this.options.useCheckpoints) { if (entry.height <= this.network.checkpoints.lastHeight) return this.setTip(entry.hash, entry.height, callback); @@ -1399,15 +1393,12 @@ WalletDB.prototype.addBlock = function addBlock(entry, txs, callback, force) { WalletDB.prototype.removeBlock = function removeBlock(entry, callback, force) { var self = this; - var unlock; - unlock = this.txLock.lock(removeBlock, [entry, callback], force); + callback = this.txLock.lock(removeBlock, [entry, callback], force); - if (!unlock) + if (!callback) return; - callback = utils.wrap(callback, unlock); - // Note: // If we crash during a reorg, there's not much to do. // Reorgs cannot be rescanned. The database will be @@ -2052,13 +2043,21 @@ function MappedLock(parent) { MappedLock.prototype.lock = function lock(key, func, args, force) { var self = this; - var called; + var called, arg, callback; + + if (args.length > 0) { + arg = args[args.length - 1]; + if (typeof arg === 'function') + callback = arg; + } if (force || key == null) { assert(key == null || this.busy[key]); - return function unlock() { + return function unlock(err, res1, res2) { assert(!called); called = true; + if (callback) + callback(err, res1, res2); }; } @@ -2069,7 +2068,7 @@ MappedLock.prototype.lock = function lock(key, func, args, force) { this.busy[key] = true; - return function unlock() { + return function unlock(err, res1, res2) { var item; assert(!called); @@ -2077,12 +2076,18 @@ MappedLock.prototype.lock = function lock(key, func, args, force) { delete self.busy[key]; - if (self.jobs.length === 0) + if (self.jobs.length === 0) { + if (callback) + callback(err, res1, res2); return; + } item = self.jobs.shift(); item[0].apply(self.parent, item[1]); + + if (callback) + callback(err, res1, res2); }; };