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]); 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 // 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++) { for (var i = 0; i < this.block.list.length; i++) {
if (this.block.list[i].hash('hex') === hash) { if (this.block.list[i].hash('hex') === hash) {
// NOTE: we return right after the statement - so `block` should be // 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)) if (this.request.add(hash, cb))
false;
this.emit('missing', hash, null, null); this.emit('missing', hash, null, null);
}; };
@ -344,7 +350,21 @@ Chain.prototype.hashesInRange = function hashesInRange(start, end, cb) {
start--; start--;
end = utils.binaryInsert(ts, end, compareTs, true); 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) { Chain.prototype.getLast = function getLast(cb) {

View File

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