lib: searialize searches

This commit is contained in:
Fedor Indutny 2014-05-14 15:01:37 +04:00
parent 66d920df0e
commit 8535fa6fa7
2 changed files with 69 additions and 18 deletions

View File

@ -299,9 +299,14 @@ Chain.prototype.has = function has(hash, noProbe, cb) {
return cb(!!this.orphan.map[hash]);
};
Chain.prototype.get = function get(hash, cb) {
Chain.prototype.get = function get(hash, force, cb) {
if (typeof force === 'function') {
cb = force;
force = false;
}
// Cached block found
if (this.block.bloom.test(hash, 'hex')) {
if (!force && this.block.bloom.test(hash, 'hex')) {
for (var i = 0; i < this.block.list.length; i++) {
if (this.block.list[i].hash('hex') === hash) {
// NOTE: we return right after the statement - so `block` should be
@ -317,6 +322,7 @@ Chain.prototype.get = function get(hash, cb) {
}
if (this.request.add(hash, cb))
false;
this.emit('missing', hash, null, null);
};
@ -344,7 +350,21 @@ Chain.prototype.hashesInRange = function hashesInRange(start, end, cb) {
start--;
end = utils.binaryInsert(ts, end, compareTs, true);
return cb(this.index.hashes.slice(start, end));
// Zip hashes and heights together and sort them by height
var hashes = this.index.hashes.slice(start, end);
var heights = this.index.heights.slice(start, end);
var zip = [];
for (var i = 0; i < hashes.length; i++)
zip.push({ hash: hashes[i], height: heights[i] });
zip = zip.sort(function(a, b) {
return a.height - b.height;
});
var hashes = zip.map(function(a) {
return a.hash;
});
var count = zip[zip.length - 1].height - zip[0].height + 1;
return cb(hashes, count);
};
Chain.prototype.getLast = function getLast(cb) {

View File

@ -62,6 +62,7 @@ function Pool(options) {
// getTX map
map: {}
};
this.searching = false;
// Currently broadcasted TXs
this.tx = {
@ -355,7 +356,18 @@ Pool.prototype.unwatch = function unwatch(id) {
this.peers.block[i].updateWatch();
};
Pool.prototype.search = function search(id, range) {
Pool.prototype.search = function search(id, range, e) {
e = e || new EventEmitter();
// Serialize searches
if (this.searching) {
this.once('_searchEnd', function() {
this.search(id, range, e);
});
return e;
}
this.searching = true;
// Optional id argument
if (typeof id === 'object' && !Array.isArray(id) ||
typeof id === 'number') {
@ -378,33 +390,52 @@ Pool.prototype.search = function search(id, range) {
range.start = +new Date() / 1000 - 432000;
var self = this;
var e = new EventEmitter();
this.chain.hashesInRange(range.start, range.end, function(hashes) {
var waiting = hashes.length;
this.chain.hashesInRange(range.start, range.end, function(hashes, count) {
var waiting = count;
if (id)
self.watch(id);
self._loadRange(hashes, true);
hashes.slice().reverse().forEach(function(hash) {
hashes = hashes.slice().reverse();
hashes.forEach(function(hash, i) {
// Get the block that is in index
self.chain.get(hash, loadBlock);
self.chain.get(hash, true, function(block) {
loadBlock(block, hashes[i + 1]);
});
});
function loadBlock(block) {
function loadBlock(block, stop) {
// Stop block reached
if (block.hash('hex') === stop)
return;
// Get block's prev and request it and all of it's parents up to
// the next known block hash
self.chain.get(block.prevBlock, function() {
waiting--;
e.emit('progress', hashes.length - waiting, hashes.length);
if (waiting === 0) {
if (id)
self.unwatch(id);
e.emit('end');
}
self.chain.get(block.prevBlock, block.prevBlock !== stop, function(prev) {
done();
// First hash loaded
if (!stop)
return;
// Continue loading blocks
loadBlock(prev, stop);
});
}
function done() {
waiting--;
e.emit('progress', count - waiting, count);
if (waiting === 0) {
if (id)
self.unwatch(id);
self.searching = false;
self.emit('_searchEnd');
e.emit('end');
}
}
// Empty search
if (hashes.length === 0) {
bcoin.utils.nextTick(function() {