blockdb improvements.

This commit is contained in:
Christopher Jeffrey 2016-03-10 14:39:37 -08:00
parent 419ba83058
commit f09a4dc8f7

View File

@ -76,9 +76,9 @@ BlockDB.prototype.close = function close(callback) {
}; };
BlockDB.prototype.migrate = function migrate(blockSize, compression, 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); options = utils.merge({}, this.db.options);
if (blockSize != null) if (blockSize != null)
@ -89,43 +89,48 @@ BlockDB.prototype.migrate = function migrate(blockSize, compression, callback) {
options.maxOpenFiles = 60000; options.maxOpenFiles = 60000;
utils.print('Migrating DB with options:'); utils.debug('Migrating DB with options:');
utils.print(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; total = 0;
function onPut(err) { iter = this.db.db.iterator({
if (err) keys: true,
return callback(err); values: true,
fillCache: false,
if (++total % 10000 === 0) keyAsBuffer: false,
utils.print('%d written.', total); valueAsBuffer: true
pending--;
if (done && !pending)
callback();
}
stream.on('data', function(data) {
pending++;
db.put(data.key, data.value, onPut);
}); });
stream.on('error', function(err) { (function next() {
callback(err); iter.next(function(err, key, value) {
}); var height;
stream.on('end', function() { if (err) {
done = true; return iter.end(function() {
if (!pending) callback(err);
callback(); });
}); }
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) { BlockDB.prototype.saveBlock = function saveBlock(block, callback) {
@ -169,6 +174,8 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch) {
var self = this; var self = this;
this._getCoinBlock(block, function(err, block) { this._getCoinBlock(block, function(err, block) {
var height;
if (err) if (err)
return callback(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()); 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) { block.txs.forEach(function(tx, i) {
var hash = tx.hash('hex'); var hash = tx.hash('hex');
var uniq = {}; var uniq = {};
@ -262,6 +273,7 @@ BlockDB.prototype.disconnectBlock = function disconnectBlock(hash, callback, bat
if (typeof hash === 'string') if (typeof hash === 'string')
assert(block.hash('hex') === hash); assert(block.hash('hex') === hash);
batch.del('b/t');
batch.del('b/h/' + pad32(block.height)); batch.del('b/h/' + pad32(block.height));
block.txs.forEach(function(tx, i) { block.txs.forEach(function(tx, i) {
@ -937,43 +949,36 @@ BlockDB.prototype.isSpent = function isSpent(hash, index, callback) {
BlockDB.prototype.getHeight = function getHeight(callback) { BlockDB.prototype.getHeight = function getHeight(callback) {
var self = this; var self = this;
var maxHeight = -1;
var iter;
iter = this.db.db.iterator({ return this.db.get('b/t', function(err, height) {
gte: 'b/h', if (err && err.type !== 'NotFoundError')
lte: 'b/h~', return callback(err);
keys: true,
values: false, if (!height)
fillCache: false, return callback(null, -1);
keyAsBuffer: false
return callback(null, utils.readU32(height, 0));
}); });
};
(function next() { BlockDB.prototype.getTipHash = function getTipHash(callback) {
iter.next(function(err, key, value) { return this.getHeight(function(err, height) {
var height; if (err)
return callback(err);
if (err) { if (height === -1)
return iter.end(function() { return callback();
callback(err);
});
}
if (key === undefined) { return self.db.get('b/h/' + pad32(height), function(err, hash) {
return iter.end(function(err) { if (err && err.type !== 'NotFoundError')
if (err) return callback(err);
return callback(err);
callback(null, maxHeight);
});
}
height = +key.split('/')[2]; if (!hash)
if (height > maxHeight) return callback();
maxHeight = height;
next(); return callback(null, utils.toHex(hash));
}); });
})(); });
}; };
BlockDB.prototype.reset = function reset(height, callback, emit) { BlockDB.prototype.reset = function reset(height, callback, emit) {