locker: automatically wrap callbacks.

This commit is contained in:
Christopher Jeffrey 2016-08-17 22:27:53 -07:00
parent 7c73d2a898
commit cdbf7c1e8c
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
8 changed files with 118 additions and 158 deletions

View File

@ -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');

View File

@ -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;

View File

@ -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);
};
};

View File

@ -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);

View File

@ -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();

View File

@ -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.'));

View File

@ -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;

View File

@ -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);
};
};