From f09a4dc8f70f8d90ec599e8af162d25652651822 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 10 Mar 2016 14:39:37 -0800 Subject: [PATCH] blockdb improvements. --- lib/bcoin/blockdb.js | 127 ++++++++++++++++++++++--------------------- 1 file changed, 66 insertions(+), 61 deletions(-) diff --git a/lib/bcoin/blockdb.js b/lib/bcoin/blockdb.js index 9908d95c..2f659342 100644 --- a/lib/bcoin/blockdb.js +++ b/lib/bcoin/blockdb.js @@ -76,9 +76,9 @@ BlockDB.prototype.close = function close(callback) { }; BlockDB.prototype.migrate = function migrate(blockSize, compression, callback) { - var options, db, pending, stream, total, done; + var options, db, iter, total; - callback = utils.once(callback); + callback = utils.ensure(callback); options = utils.merge({}, this.db.options); if (blockSize != null) @@ -89,43 +89,48 @@ BlockDB.prototype.migrate = function migrate(blockSize, compression, callback) { options.maxOpenFiles = 60000; - utils.print('Migrating DB with options:'); - utils.print(options); + utils.debug('Migrating DB with options:'); + utils.debug(options); - db = levelup(this.file + '.migrated', options); + db = new levelup(this.file + '.migrated', options); - stream = this.db.createReadStream(); - - pending = 0; total = 0; - function onPut(err) { - if (err) - return callback(err); - - if (++total % 10000 === 0) - utils.print('%d written.', total); - - pending--; - - if (done && !pending) - callback(); - } - - stream.on('data', function(data) { - pending++; - db.put(data.key, data.value, onPut); + iter = this.db.db.iterator({ + keys: true, + values: true, + fillCache: false, + keyAsBuffer: false, + valueAsBuffer: true }); - stream.on('error', function(err) { - callback(err); - }); + (function next() { + iter.next(function(err, key, value) { + var height; - stream.on('end', function() { - done = true; - if (!pending) - callback(); - }); + if (err) { + return iter.end(function() { + callback(err); + }); + } + + if (key === undefined) + return iter.end(callback); + + db.put(key, value, function(err) { + if (err) { + return iter.end(function() { + callback(err); + }); + } + + if (++total % 10000 === 0) + utils.print('%d written.', total); + + next(); + }); + }); + })(); }; BlockDB.prototype.saveBlock = function saveBlock(block, callback) { @@ -169,6 +174,8 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch) { var self = this; this._getCoinBlock(block, function(err, block) { + var height; + if (err) return callback(err); @@ -182,6 +189,10 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch) { batch.put('b/h/' + pad32(block.height), block.hash()); + height = new Buffer(4); + utils.writeU32(height, block.height, 0); + batch.put('b/t', height); + block.txs.forEach(function(tx, i) { var hash = tx.hash('hex'); var uniq = {}; @@ -262,6 +273,7 @@ BlockDB.prototype.disconnectBlock = function disconnectBlock(hash, callback, bat if (typeof hash === 'string') assert(block.hash('hex') === hash); + batch.del('b/t'); batch.del('b/h/' + pad32(block.height)); block.txs.forEach(function(tx, i) { @@ -937,43 +949,36 @@ BlockDB.prototype.isSpent = function isSpent(hash, index, callback) { BlockDB.prototype.getHeight = function getHeight(callback) { var self = this; - var maxHeight = -1; - var iter; - iter = this.db.db.iterator({ - gte: 'b/h', - lte: 'b/h~', - keys: true, - values: false, - fillCache: false, - keyAsBuffer: false + return this.db.get('b/t', function(err, height) { + if (err && err.type !== 'NotFoundError') + return callback(err); + + if (!height) + return callback(null, -1); + + return callback(null, utils.readU32(height, 0)); }); +}; - (function next() { - iter.next(function(err, key, value) { - var height; +BlockDB.prototype.getTipHash = function getTipHash(callback) { + return this.getHeight(function(err, height) { + if (err) + return callback(err); - if (err) { - return iter.end(function() { - callback(err); - }); - } + if (height === -1) + return callback(); - if (key === undefined) { - return iter.end(function(err) { - if (err) - return callback(err); - callback(null, maxHeight); - }); - } + return self.db.get('b/h/' + pad32(height), function(err, hash) { + if (err && err.type !== 'NotFoundError') + return callback(err); - height = +key.split('/')[2]; - if (height > maxHeight) - maxHeight = height; + if (!hash) + return callback(); - next(); + return callback(null, utils.toHex(hash)); }); - })(); + }); }; BlockDB.prototype.reset = function reset(height, callback, emit) {