add some async functions.
This commit is contained in:
parent
469d3c35d0
commit
d2a4f995fd
@ -753,10 +753,13 @@ Chain.prototype.resetHeight = function resetHeight(height) {
|
|||||||
for (i = height + 1; i < count; i++) {
|
for (i = height + 1; i < count; i++) {
|
||||||
existing = this.db.get(i);
|
existing = this.db.get(i);
|
||||||
assert(existing);
|
assert(existing);
|
||||||
|
// this.db.remove(i);
|
||||||
|
this.db.drop(i);
|
||||||
delete this.heightLookup[existing.hash];
|
delete this.heightLookup[existing.hash];
|
||||||
this.db.remove(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.db.truncate(height);
|
||||||
|
|
||||||
// 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
|
||||||
// no longer need.
|
// no longer need.
|
||||||
@ -772,6 +775,63 @@ Chain.prototype.resetHeight = function resetHeight(height) {
|
|||||||
this.emit('tip', this.tip);
|
this.emit('tip', this.tip);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Chain.prototype.resetHeightAsync = function resetHeightAsync(height, callback) {
|
||||||
|
var self = this;
|
||||||
|
var count = this.db.count();
|
||||||
|
var i, lock;
|
||||||
|
|
||||||
|
assert(height <= count - 1);
|
||||||
|
assert(this.tip);
|
||||||
|
|
||||||
|
if (height === count - 1)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
lock = this.locked;
|
||||||
|
this.locked = true;
|
||||||
|
|
||||||
|
i = height + 1;
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
if (i === count)
|
||||||
|
return self.db.truncateAsync(height, done);
|
||||||
|
|
||||||
|
self.db.getAsync(i, function(err, existing) {
|
||||||
|
if (err)
|
||||||
|
return done(err);
|
||||||
|
|
||||||
|
assert(existing);
|
||||||
|
|
||||||
|
delete self.heightLookup[existing.hash];
|
||||||
|
self.db.drop(i);
|
||||||
|
i++;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function done(err) {
|
||||||
|
self.locked = lock;
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
// Reset the orphan map completely. There may
|
||||||
|
// have been some orphans on a forked chain we
|
||||||
|
// no longer need.
|
||||||
|
self.emit('purge', self.orphan.count, self.orphan.size);
|
||||||
|
self.orphan.map = {};
|
||||||
|
self.orphan.bmap = {};
|
||||||
|
self.orphan.count = 0;
|
||||||
|
self.orphan.size = 0;
|
||||||
|
|
||||||
|
self.tip = self.db.get(height);
|
||||||
|
assert(self.tip);
|
||||||
|
self.height = self.tip.height;
|
||||||
|
self.emit('tip', self.tip);
|
||||||
|
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Chain.prototype.revertHeight = function revertHeight(height, callback) {
|
Chain.prototype.revertHeight = function revertHeight(height, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var chainHeight;
|
var chainHeight;
|
||||||
@ -1399,6 +1459,94 @@ Chain.prototype.getLocator = function getLocator(start) {
|
|||||||
return hashes;
|
return hashes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Chain.prototype.getLocatorAsync = function getLocatorAsync(start, callback) {
|
||||||
|
var self = this;
|
||||||
|
var hashes = [];
|
||||||
|
var top = this.height;
|
||||||
|
var step = 1;
|
||||||
|
var i, called;
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
if (utils.isBuffer(start))
|
||||||
|
start = utils.toHex(start);
|
||||||
|
else if (start.hash)
|
||||||
|
start = start.hash('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof start === 'string') {
|
||||||
|
top = this.heightLookup[start];
|
||||||
|
if (top == null) {
|
||||||
|
// We could simply `return [start]` here,
|
||||||
|
// but there is no standardized "spacing"
|
||||||
|
// for locator hashes. Pretend this hash
|
||||||
|
// is our tip. This is useful for getheaders
|
||||||
|
// when not using headers-first.
|
||||||
|
hashes.push(start);
|
||||||
|
top = this.db.count() - 1;
|
||||||
|
}
|
||||||
|
} else if (typeof start === 'number') {
|
||||||
|
top = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
function done(err) {
|
||||||
|
if (called)
|
||||||
|
return;
|
||||||
|
|
||||||
|
called = true;
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
return callback(null, hashes);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.db.hasAsync(top, function(err, has) {
|
||||||
|
var pending;
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return done(err);
|
||||||
|
|
||||||
|
if (!has)
|
||||||
|
return done(new Error('Potential reset.'));
|
||||||
|
|
||||||
|
i = top;
|
||||||
|
for (;;) {
|
||||||
|
hashes.push(i);
|
||||||
|
i = i - step;
|
||||||
|
if (i <= 0) {
|
||||||
|
if (i + step !== 0)
|
||||||
|
hashes.push(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hashes.length >= 10)
|
||||||
|
step *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pending = hashes.length;
|
||||||
|
|
||||||
|
hashes.forEach(function(height, i) {
|
||||||
|
if (typeof height === 'string') {
|
||||||
|
if (!--pending)
|
||||||
|
done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.db.getAsync(height, function(err, existing) {
|
||||||
|
if (err)
|
||||||
|
return done(err);
|
||||||
|
|
||||||
|
if (!existing)
|
||||||
|
return done(new Error('Potential reset.'));
|
||||||
|
|
||||||
|
hashes[i] = existing.hash;
|
||||||
|
|
||||||
|
if (!--pending)
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) {
|
Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var root;
|
var root;
|
||||||
|
|||||||
@ -323,7 +323,7 @@ ChainDB.prototype.saveAsync = function saveAsync(entry, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.remove = function remove(height) {
|
ChainDB.prototype.drop = function drop(height) {
|
||||||
assert(height >= 0);
|
assert(height >= 0);
|
||||||
|
|
||||||
// Potential race condition here. Not sure how
|
// Potential race condition here. Not sure how
|
||||||
@ -333,8 +333,17 @@ ChainDB.prototype.remove = function remove(height) {
|
|||||||
delete this._queue[height];
|
delete this._queue[height];
|
||||||
}
|
}
|
||||||
|
|
||||||
this._writeSync(this._nullBlock, height * BLOCK_SIZE);
|
|
||||||
delete this._cache[height];
|
delete this._cache[height];
|
||||||
|
};
|
||||||
|
|
||||||
|
ChainDB.prototype.remove = function remove(height) {
|
||||||
|
assert(height >= 0);
|
||||||
|
|
||||||
|
// Drop the queue and cache
|
||||||
|
this.drop(height);
|
||||||
|
|
||||||
|
// Write a null block
|
||||||
|
this._writeSync(this._nullBlock, height * BLOCK_SIZE);
|
||||||
|
|
||||||
// If we deleted several blocks at the end, go back
|
// If we deleted several blocks at the end, go back
|
||||||
// to the last non-null block and truncate the file
|
// to the last non-null block and truncate the file
|
||||||
@ -345,13 +354,13 @@ ChainDB.prototype.remove = function remove(height) {
|
|||||||
|
|
||||||
assert(height >= 0);
|
assert(height >= 0);
|
||||||
|
|
||||||
this.truncateSync(height);
|
this.truncate(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.truncateSync = function truncateSync(height) {
|
ChainDB.prototype.truncate = function truncate(height) {
|
||||||
var size = (height + 1) * BLOCK_SIZE;
|
var size = (height + 1) * BLOCK_SIZE;
|
||||||
|
|
||||||
if (!bcoin.fs) {
|
if (!bcoin.fs) {
|
||||||
@ -417,6 +426,31 @@ ChainDB.prototype.has = function has(height) {
|
|||||||
return utils.read32(data, 0) !== 0;
|
return utils.read32(data, 0) !== 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ChainDB.prototype.hasAsync = function hasAsync(height, callback) {
|
||||||
|
var data;
|
||||||
|
|
||||||
|
callback = utils.asyncify(callback);
|
||||||
|
|
||||||
|
if (this._queue[height] || this._cache[height])
|
||||||
|
return callback(null, true);
|
||||||
|
|
||||||
|
if (height < 0 || height == null)
|
||||||
|
return callback(null, false);
|
||||||
|
|
||||||
|
if ((height + 1) * BLOCK_SIZE > this.size)
|
||||||
|
return callback(null, false);
|
||||||
|
|
||||||
|
this._readAsync(4, height * BLOCK_SIZE, function(err, data) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return callback(null, false);
|
||||||
|
|
||||||
|
return callback(null, utils.read32(data, 0) !== 0);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
ChainDB.prototype._readSync = function _readSync(size, offset) {
|
ChainDB.prototype._readSync = function _readSync(size, offset) {
|
||||||
var index = 0;
|
var index = 0;
|
||||||
var data, bytes;
|
var data, bytes;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user