From 37586e5ad877b177b9e49000dc9133816b7ea8e5 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 23 Sep 2016 05:00:31 -0700 Subject: [PATCH] refactor: db. --- lib/db/lowlevelup.js | 116 +++++++++++++++++++++++++++++-------------- lib/net/pool.js | 3 +- lib/utils/spawn.js | 28 ++++++++--- package.json | 2 +- 4 files changed, 103 insertions(+), 46 deletions(-) diff --git a/lib/db/lowlevelup.js b/lib/db/lowlevelup.js index 6772d47c..ca200a04 100644 --- a/lib/db/lowlevelup.js +++ b/lib/db/lowlevelup.js @@ -144,18 +144,17 @@ LowlevelUp.prototype.backup = function backup(path) { /** * Retrieve a record from the database. - * @param {String} key - * @param {Object?} options + * @param {String|Buffer} key * @returns {Promise} - Returns Buffer. */ -LowlevelUp.prototype.get = function get(key, options) { +LowlevelUp.prototype.get = function get(key) { var self = this; assert(this.loaded, 'Cannot use database before it is loaded.'); return new Promise(function(resolve, reject) { - self.binding.get(key, options || {}, function(err, result) { + self.binding.get(key, function(err, result) { if (err) { if (isNotFound(err)) return resolve(); @@ -168,44 +167,40 @@ LowlevelUp.prototype.get = function get(key, options) { /** * Store a record in the database. - * @param {String} key + * @param {String|Buffer} key * @param {Buffer} value - * @param {Object?} options * @returns {Promise} */ -LowlevelUp.prototype.put = function put(key, value, options) { +LowlevelUp.prototype.put = function put(key, value) { var self = this; assert(this.loaded, 'Cannot use database before it is loaded.'); return new Promise(function(resolve, reject) { - self.binding.put(key, value, options || {}, wrap(resolve, reject)); + self.binding.put(key, value, wrap(resolve, reject)); }); }; /** * Remove a record from the database. - * @param {String} key - * @param {Object?} options + * @param {String|Buffer} key * @returns {Promise} */ -LowlevelUp.prototype.del = function del(key, options) { +LowlevelUp.prototype.del = function del(key) { var self = this; assert(this.loaded, 'Cannot use database before it is loaded.'); return new Promise(function(resolve, reject) { - self.binding.del(key, options || {}, wrap(resolve, reject)); + self.binding.del(key, wrap(resolve, reject)); }); }; /** * Create an atomic batch. * @param {Array?} ops - * @param {Object?} options - * @returns {Promise} - * @returns {Leveldown.Batch} + * @returns {Batch} */ -LowlevelUp.prototype.batch = function batch(ops, options) { +LowlevelUp.prototype.batch = function batch(ops) { var self = this; assert(this.loaded, 'Cannot use database before it is loaded.'); @@ -214,20 +209,22 @@ LowlevelUp.prototype.batch = function batch(ops, options) { return new Batch(this); return new Promise(function(resolve, reject) { - self.binding.batch(ops, options || {}, wrap(resolve, reject)); + self.binding.batch(ops, wrap(resolve, reject)); }); }; /** * Create an iterator. * @param {Object} options - * @returns {Leveldown.Iterator} + * @returns {Iterator} */ LowlevelUp.prototype.iterator = function iterator(options) { + var opt; + assert(this.loaded, 'Cannot use database before it is loaded.'); - var opt = { + opt = { gte: options.gte, lte: options.lte, keys: options.keys !== false, @@ -275,6 +272,7 @@ LowlevelUp.prototype.getProperty = function getProperty(name) { LowlevelUp.prototype.approximateSize = function approximateSize(start, end) { var self = this; + assert(this.loaded, 'Cannot use database before it is loaded.'); return new Promise(function(resolve, reject) { @@ -315,7 +313,7 @@ LowlevelUp.prototype.iterate = co(function* iterate(options) { result = yield iter.next(); if (!result) - return items; + break; data = parse(result.key, result.value); @@ -355,11 +353,11 @@ LowlevelUp.prototype.checkVersion = co(function* checkVersion(key, version) { */ LowlevelUp.prototype.clone = co(function* clone(path) { - var opt = { keys: true, values: true }; var options = utils.merge({}, this.options); + var opt = { keys: true, values: true }; var hwm = 256 << 20; var total = 0; - var tmp, batch, iter, items, key, value; + var tmp, batch, iter, result; assert(!this.loading); assert(!this.closing); @@ -376,22 +374,12 @@ LowlevelUp.prototype.clone = co(function* clone(path) { iter = this.iterator(opt); for (;;) { - items = yield iter.next(); + result = yield iter.next(); - if (!items) { - try { - yield batch.write(); - } catch (e) { - yield tmp.close(); - throw e; - } - return; - } + if (!result) + break; - key = items[0]; - value = items[0]; - - batch.put(key, value); + batch.put(result.key, result.value); total += value.length; if (total >= hwm) { @@ -405,23 +393,50 @@ LowlevelUp.prototype.clone = co(function* clone(path) { batch = tmp.batch(); } } + + try { + yield batch.write(); + } finally { + yield tmp.close(); + } }); +/** + * Batch + * @constructor + * @param {LowlevelUp} db + */ + function Batch(db) { - this.db = db; this.batch = db.binding.batch(); } +/** + * Write a value to the batch. + * @param {String|Buffer} key + * @param {Buffer} value + */ + Batch.prototype.put = function(key, value) { this.batch.put(key, value); return this; }; +/** + * Delete a value from the batch. + * @param {String|Buffer} key + */ + Batch.prototype.del = function del(key) { this.batch.del(key); return this; }; +/** + * Write batch to database. + * @returns {Promise} + */ + Batch.prototype.write = function write() { var self = this; return new Promise(function(resolve, reject) { @@ -429,16 +444,31 @@ Batch.prototype.write = function write() { }); }; +/** + * Clear the batch. + */ + Batch.prototype.clear = function clear() { this.batch.clear(); return this; }; +/** + * Iterator + * @constructor + * @param {LowlevelUp} db + * @param {Object} options + */ + function Iterator(db, options) { - this.db = db; this.iter = db.db.iterator(options); } +/** + * Seek to the next key. + * @returns {Promise} + */ + Iterator.prototype.next = function() { var self = this; return new Promise(function(resolve, reject) { @@ -460,10 +490,20 @@ Iterator.prototype.next = function() { }); }; +/** + * Seek to an arbitrary key. + * @param {String|Buffer} + */ + Iterator.prototype.seek = function seek(key) { this.iter.seek(key); }; +/** + * End the iterator. + * @returns {Promise} + */ + Iterator.prototype.end = function end() { var self = this; return new Promise(function(resolve, reject) { diff --git a/lib/net/pool.js b/lib/net/pool.js index 2bcd2ddc..b594d0c2 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -1668,6 +1668,7 @@ Pool.prototype.sendRequests = function sendRequests(peer) { if (this.options.spv) { if (this.activeBlocks >= 500) return; + items = peer.queueBlock.slice(); peer.queueBlock.length = 0; } else { @@ -1737,7 +1738,7 @@ Pool.prototype.broadcast = function broadcast(msg) { } return new Promise(function(resolve, reject) { - item.addCallback(utils.P(resolve, reject)); + item.addCallback(spawn.wrap(resolve, reject)); }); }; diff --git a/lib/utils/spawn.js b/lib/utils/spawn.js index 915e0b09..0b472fa5 100644 --- a/lib/utils/spawn.js +++ b/lib/utils/spawn.js @@ -35,17 +35,23 @@ function exec(gen) { return; } - if (!(next.value instanceof Promise)) { - step(next.value); + if (!isPromise(next.value)) { + step(next.value, false); return; } - next.value.then(step, function(e) { - step(e, true); - }); + next.value.then(succeed, fail); } - step(undefined); + function succeed(value) { + step(value, false); + } + + function fail(value) { + step(value, true); + } + + step(undefined, false); }); } @@ -77,6 +83,16 @@ function co(generator) { }; } +/** + * Test whether an object is a promise. + * @param {Object} obj + * @returns {Boolean} + */ + +function isPromise(obj) { + return obj && typeof obj.then === 'function'; +} + /** * Wrap a generator function to be * executed into a function that diff --git a/package.json b/package.json index b660a102..7359b5bd 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ }, "homepage": "https://github.com/bcoin-org/bcoin", "engines": { - "node": ">= 0.10.0" + "node": ">= 0.11.0" }, "dependencies": { "bn.js": "4.11.6",