sync resetHeight

This commit is contained in:
Christopher Jeffrey 2016-02-19 05:38:02 -08:00
parent 9ff7e93c71
commit 053775ffac

View File

@ -39,9 +39,6 @@ function Chain(options) {
this.loading = false; this.loading = false;
this.mempool = options.mempool; this.mempool = options.mempool;
this.blockdb = options.blockdb; this.blockdb = options.blockdb;
this.resetting = false;
this.reverting = false;
this.syncing = false;
this.locked = false; this.locked = false;
this.pending = []; this.pending = [];
this.pendingBlocks = {}; this.pendingBlocks = {};
@ -249,7 +246,7 @@ Chain.prototype._preload = function _preload(callback) {
stream.on('error', function(err) { stream.on('error', function(err) {
var start = Math.max(0, height - 2); var start = Math.max(0, height - 2);
self.resetHeightSync(start); self.resetHeight(start);
return callback(err, start + 1); return callback(err, start + 1);
}); });
@ -285,7 +282,7 @@ Chain.prototype._preload = function _preload(callback) {
if (lastEntry && entry.prevBlock !== lastEntry.hash) { if (lastEntry && entry.prevBlock !== lastEntry.hash) {
start = Math.max(0, height - 2); start = Math.max(0, height - 2);
stream.destroy(); stream.destroy();
self.resetHeightSync(start); self.resetHeight(start);
return callback(new Error('Corrupt headers.'), start + 1); return callback(new Error('Corrupt headers.'), start + 1);
} }
@ -294,7 +291,7 @@ Chain.prototype._preload = function _preload(callback) {
if (!block.verify()) { if (!block.verify()) {
start = Math.max(0, height - 2); start = Math.max(0, height - 2);
stream.destroy(); stream.destroy();
self.resetHeightSync(start); self.resetHeight(start);
return callback(new Error('Bad headers.'), start + 1); return callback(new Error('Bad headers.'), start + 1);
} }
@ -689,10 +686,11 @@ Chain.prototype.resetHeight = function resetHeight(height) {
var self = this; var self = this;
var i, existing; var i, existing;
assert(!this.resetting);
assert(height <= count - 1); assert(height <= count - 1);
assert(this.tip); assert(this.tip);
this._clearPending();
if (height === count - 1) if (height === count - 1)
return; return;
@ -710,22 +708,26 @@ Chain.prototype.resetHeight = function resetHeight(height) {
Chain.prototype.resetHeightAsync = function resetHeightAsync(height, callback) { Chain.prototype.resetHeightAsync = function resetHeightAsync(height, callback) {
var self = this; var self = this;
var i, lock; var lock = this.lock;
var i;
assert(!this.resetting);
assert(height <= count - 1); assert(height <= count - 1);
assert(this.tip); assert(this.tip);
if (height === count - 1) this.lock = true;
return utils.nextTick(callback);
this.resetting = true; function done(err, result) {
self.lock = lock;
self._clearPending();
callback(err, result);
}
if (height === count - 1)
return utils.nextTick(done);
this.db.resetHeightAsync(height, function(err) { this.db.resetHeightAsync(height, function(err) {
self.resetting = false;
if (err) if (err)
return callback(err); return done(err);
// Reset the orphan map completely. There may // Reset the orphan map completely. There may
// have been some orphans on a forked chain we // have been some orphans on a forked chain we
@ -736,22 +738,22 @@ Chain.prototype.resetHeightAsync = function resetHeightAsync(height, callback) {
self.orphan.count = 0; self.orphan.count = 0;
self.orphan.size = 0; self.orphan.size = 0;
return callback(); return done();
}); });
}; };
Chain.prototype.revertHeight = function revertHeight(height, callback) { Chain.prototype.revertHeight = function revertHeight(height, callback) {
var self = this; var self = this;
var chainHeight; var chainHeight;
var lock = this.lock;
assert(!this.reverting);
callback = utils.asyncify(callback); callback = utils.asyncify(callback);
this.reverting = true; this.lock = true;
function done(err, result) { function done(err, result) {
self.reverting = false; self.lock = lock;
self._clearPending();
callback(err, result); callback(err, result);
} }
@ -760,11 +762,16 @@ Chain.prototype.revertHeight = function revertHeight(height, callback) {
if (chainHeight < 0) if (chainHeight < 0)
return done(new Error('Bad chain height.')); return done(new Error('Bad chain height.'));
if (!this.blockdb) { if (chainHeight < height)
if (height > chainHeight) return done(new Error('Cannot reset height.'));
return done(new Error('Cannot reset height.'));
return this.resetHeightAsync(height, done); if (chainHeight === height)
} return done();
this.resetHeight(height);
if (!this.blockdb)
return done();
this.blockdb.getHeight(function(err, blockHeight) { this.blockdb.getHeight(function(err, blockHeight) {
if (err) if (err)
@ -773,20 +780,17 @@ Chain.prototype.revertHeight = function revertHeight(height, callback) {
if (blockHeight < 0) if (blockHeight < 0)
return done(new Error('Bad block height.')); return done(new Error('Bad block height.'));
if (chainHeight !== blockHeight) if (blockHeight < height)
return done(new Error('ChainDB and BlockDB are out of sync.'));
if (height === chainHeight)
return done();
if (height > chainHeight)
return done(new Error('Cannot reset height.')); return done(new Error('Cannot reset height.'));
if (blockHeight === height)
return done();
self.blockdb.resetHeight(height, function(err) { self.blockdb.resetHeight(height, function(err) {
if (err) if (err)
return done(err); return done(err);
self.resetHeightAsync(height, done); return done();
}, function(block) { }, function(block) {
self.emit('remove block', block); self.emit('remove block', block);
}); });
@ -795,34 +799,41 @@ Chain.prototype.revertHeight = function revertHeight(height, callback) {
Chain.prototype._revertLast = function _revertLast(existing, callback) { Chain.prototype._revertLast = function _revertLast(existing, callback) {
var self = this; var self = this;
var lock = this.lock;
this.lock = true;
function done(err, result) {
self.lock = lock;
self._clearPending();
callback(err, result);
}
this.resetHeight(existing.height - 1);
this._removeBlock(existing.hash, function(err, existingBlock) { this._removeBlock(existing.hash, function(err, existingBlock) {
if (err) if (err)
return callback(err); return done(err);
self.resetHeightAsync(existing.height - 1, function(err) { if (existingBlock)
if (err) self.emit('remove block', existingBlock);
return callback(err);
if (existingBlock) return done();
self.emit('remove block', existingBlock);
return callback();
});
}); });
}; };
Chain.prototype.syncHeight = function syncHeight(callback) { Chain.prototype.syncHeight = function syncHeight(callback) {
var self = this; var self = this;
var chainHeight; var chainHeight;
var lock = this.lock;
callback = utils.asyncify(callback); callback = utils.asyncify(callback);
assert(!this.syncing); this.lock = true;
this.syncing = true;
function done(err, result) { function done(err, result) {
self.syncing = false; self.lock = lock;
self._clearPending();
callback(err, result); callback(err, result);
} }
@ -848,7 +859,8 @@ Chain.prototype.syncHeight = function syncHeight(callback) {
if (blockHeight < chainHeight) { if (blockHeight < chainHeight) {
utils.debug('BlockDB is higher than ChainDB. Syncing...'); utils.debug('BlockDB is higher than ChainDB. Syncing...');
return self.resetHeightAsync(blockHeight, done); self.resetHeight(blockHeight);
return done();
} }
if (blockHeight > chainHeight) { if (blockHeight > chainHeight) {
@ -869,7 +881,7 @@ Chain.prototype.resetTime = function resetTime(ts) {
var entry = this.byTime(ts); var entry = this.byTime(ts);
if (!entry) if (!entry)
return; return;
return this.resetHeightSync(entry.height); return this.resetHeight(entry.height);
}; };
Chain.prototype.resetTimeAsync = function resetTimeAsync(ts, callback) { Chain.prototype.resetTimeAsync = function resetTimeAsync(ts, callback) {
@ -903,9 +915,6 @@ Chain.prototype.add = function add(initial, peer, callback) {
return; return;
} }
if (this.resetting || this.reverting || this.syncing)
return callback();
this.locked = true; this.locked = true;
(function next(block) { (function next(block) {
@ -969,7 +978,7 @@ Chain.prototype.add = function add(initial, peer, callback) {
// Clear the queue. No telling what other // Clear the queue. No telling what other
// blocks we're going to get after this. // blocks we're going to get after this.
self.pending.length = 0; self._clearPending();
return done(); return done();
} }
@ -1042,7 +1051,7 @@ Chain.prototype.add = function add(initial, peer, callback) {
// Clear the queue. No telling what other // Clear the queue. No telling what other
// blocks we're going to get after this. // blocks we're going to get after this.
self.pending.length = 0; self._clearPending();
return done(); return done();
} }
@ -1103,7 +1112,7 @@ Chain.prototype.add = function add(initial, peer, callback) {
// Clear the queue. No telling what other // Clear the queue. No telling what other
// blocks we're going to get after this. // blocks we're going to get after this.
self.pending.length = 0; self._clearPending();
return done(); return done();
}); });
@ -1234,6 +1243,15 @@ Chain.prototype.add = function add(initial, peer, callback) {
} }
}; };
Chain.prototype._clearPending = function _clearPending() {
var item;
while (this.pending.length) {
item = this.pending.pop();
delete this.pendingBlocks[item[0].hash('hex')];
this.pendingSize -= item[0].getSize();
}
};
Chain.prototype.has = function has(hash) { Chain.prototype.has = function has(hash) {
if (this.hasBlock(hash)) if (this.hasBlock(hash))
return true; return true;