This commit is contained in:
Christopher Jeffrey 2016-02-19 11:18:35 -08:00
parent 53158edf4f
commit 348049a5c3

View File

@ -181,6 +181,62 @@ Chain.prototype.__defineGetter__('height', function() {
return this.db.height;
});
// Maybe do this:
// Chain.prototype._lock = function _lock(func, args, callback, force) {
// And return wrapped callback with an unlock call in it
Chain.prototype._lock = function _lock(func, args, force) {
var self = this;
var block;
if (force) {
assert(this.busy);
return function() {};
}
if (this.busy) {
if (func === Chain.prototype.add) {
block = args[0];
this.pending.push(block);
this.pendingBlocks[block.hash('hex')] = true;
this.pendingSize += block.getSize();
if (this.pendingSize > this.pendingLimit) {
this.purgePending();
return;
}
}
this.jobs.push([func, args]);
return;
}
this.busy = true;
return function unlock() {
var item, block;
self.busy = false;
if (func === Chain.prototype.add) {
if (self.pending.length === 0)
self.emit('flush');
}
if (self.jobs.length === 0)
return;
item = self.jobs.shift();
if (item[0] === Chain.prototype.add) {
block = item[1][0];
assert(block === self.pending.shift());
delete self.pendingBlocks[block.hash('hex')];
self.pendingSize -= block.getSize();
}
item[0].apply(self, item[1]);
};
};
Chain.prototype._ensureGenesis = function _ensureGenesis(callback) {
var self = this;
@ -707,129 +763,6 @@ Chain.prototype.resetHeight = function resetHeight(height, force) {
unlock();
};
Chain.prototype.purgePending = function purgePending() {
var self = this;
this.pending.forEach(function(block) {
delete self.pendingBlocks[block.hash('hex')];
self.pendingSize -= block.getSize();
});
this.pending.length = 0;
this.jobs = this.jobs.filter(function(item) {
return item[0] !== Chain.prototype.add;
});
};
// Maybe do this:
// Chain.prototype._lock = function _lock(func, args, callback, force) {
// And return wrapped callback with an unlock call in it
Chain.prototype._lock = function _lock(func, args, force) {
var self = this;
var block;
if (force) {
assert(this.busy);
return function() {};
}
if (this.busy) {
if (func === Chain.prototype.add) {
block = args[0];
this.pending.push(block);
this.pendingBlocks[block.hash('hex')] = true;
this.pendingSize += block.getSize();
if (this.pendingSize > this.pendingLimit) {
utils.debug('Warning: %dmb of pending blocks. Purging.',
utils.mb(this.pendingSize));
this.purgePending();
return;
}
}
this.jobs.push([func, args]);
return;
}
this.busy = true;
return function unlock() {
var item, block;
self.busy = false;
if (func === Chain.prototype.add) {
if (self.pending.length === 0)
self.emit('flush');
}
if (self.jobs.length === 0)
return;
item = self.jobs.shift();
if (item[0] === Chain.prototype.add) {
block = item[1][0];
assert(block === self.pending.shift());
delete self.pendingBlocks[block.hash('hex')];
self.pendingSize -= block.getSize();
}
item[0].apply(self, item[1]);
};
};
Chain.prototype.purgeOrphans = function purgeOrphans() {
this.emit('purge', this.orphan.count, this.orphan.size);
this.orphan.map = {};
this.orphan.bmap = {};
this.orphan.count = 0;
this.orphan.size = 0;
};
Chain.prototype.pruneOrphans = function pruneOrphans() {
var self = this;
var best, last;
best = Object.keys(this.orphan.map).reduce(function(best, prevBlock, i) {
var orphan = self.orphan.map[prevBlock];
var height = orphan.getCoinbaseHeight();
last = orphan;
if (!best || height > best.getCoinbaseHeight())
return orphan;
return best;
}, null);
// Save the best for last... or the
// last for the best in this case.
if (!best || best.getCoinbaseHeight() <= 0)
best = last;
this.emit('purge',
this.orphan.count - (best ? 1 : 0),
this.orphan.size - (best ? best.getSize() : 0));
Object.keys(this.orphan.bmap).forEach(function(hash) {
var orphan = self.orphan.bmap[hash];
if (orphan !== best)
self.emit('unresolved', orphan, peer);
});
this.orphan.map = {};
this.orphan.bmap = {};
this.orphan.count = 0;
this.orphan.size = 0;
if (!best)
return;
this.orphan.map[best.prevBlock] = best;
this.orphan.bmap[best.hash('hex')] = best;
this.orphan.count++;
this.orphan.size += best.getSize();
};
Chain.prototype.resetHeightAsync = function resetHeightAsync(height, callback, force) {
var self = this;
@ -1349,6 +1282,77 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
}
};
Chain.prototype.purgeOrphans = function purgeOrphans() {
this.emit('purge', this.orphan.count, this.orphan.size);
this.orphan.map = {};
this.orphan.bmap = {};
this.orphan.count = 0;
this.orphan.size = 0;
};
Chain.prototype.pruneOrphans = function pruneOrphans() {
var self = this;
var best, last;
best = Object.keys(this.orphan.map).reduce(function(best, prevBlock, i) {
var orphan = self.orphan.map[prevBlock];
var height = orphan.getCoinbaseHeight();
last = orphan;
if (!best || height > best.getCoinbaseHeight())
return orphan;
return best;
}, null);
// Save the best for last... or the
// last for the best in this case.
if (!best || best.getCoinbaseHeight() <= 0)
best = last;
this.emit('purge',
this.orphan.count - (best ? 1 : 0),
this.orphan.size - (best ? best.getSize() : 0));
Object.keys(this.orphan.bmap).forEach(function(hash) {
var orphan = self.orphan.bmap[hash];
if (orphan !== best)
self.emit('unresolved', orphan, peer);
});
this.orphan.map = {};
this.orphan.bmap = {};
this.orphan.count = 0;
this.orphan.size = 0;
if (!best)
return;
this.orphan.map[best.prevBlock] = best;
this.orphan.bmap[best.hash('hex')] = best;
this.orphan.count++;
this.orphan.size += best.getSize();
};
Chain.prototype.purgePending = function purgePending() {
var self = this;
utils.debug('Warning: %dmb of pending blocks. Purging.',
utils.mb(this.pendingSize));
this.pending.forEach(function(block) {
delete self.pendingBlocks[block.hash('hex')];
});
this.pending.length = 0;
this.pendingSize = 0;
this.jobs = this.jobs.filter(function(item) {
return item[0] !== Chain.prototype.add;
});
};
Chain.prototype.has = function has(hash) {
if (this.hasBlock(hash))
return true;