fsync all chain writes.

This commit is contained in:
Christopher Jeffrey 2016-02-22 04:50:47 -08:00
parent 0f4d2ca281
commit cbed3bbc4f
3 changed files with 58 additions and 11 deletions

View File

@ -1242,6 +1242,15 @@ BlockData.prototype.truncateAsync = function truncateAsync(size, callback) {
}); });
}; };
BlockData.prototype._ioError = function _ioError(name, size, offset) {
return new Error(name
+ '() failed at offset '
+ offset
+ ' with '
+ size
+ ' bytes left.');
};
BlockData.prototype._readSync = function _readSync(size, offset) { BlockData.prototype._readSync = function _readSync(size, offset) {
var index = 0; var index = 0;
var data, bytes; var data, bytes;
@ -1271,7 +1280,7 @@ BlockData.prototype._readSync = function _readSync(size, offset) {
this._free(data); this._free(data);
throw new Error('_readSync() failed.'); throw this._ioError('_readSync', size, offset);
}; };
BlockData.prototype._readAsync = function _readAsync(size, offset, callback) { BlockData.prototype._readAsync = function _readAsync(size, offset, callback) {
@ -1297,7 +1306,7 @@ BlockData.prototype._readAsync = function _readAsync(size, offset, callback) {
} }
if (!bytes) if (!bytes)
return callback(new Error('_readAsync() failed at offset ' + offset + ' ' + size + ' to go')); return callback(self._ioError('_readAsync', size, offset));
index += bytes; index += bytes;
size -= bytes; size -= bytes;
@ -1342,7 +1351,9 @@ BlockData.prototype._writeSync = function _writeSync(data, offset) {
throw e; throw e;
} }
throw new Error('_writeSync() failed.'); fs.fsyncSync(this.fd);
throw this._ioError('_writeSync', size, offset);
}; };
BlockData.prototype._writeAsync = function _writeAsync(data, offset, callback) { BlockData.prototype._writeAsync = function _writeAsync(data, offset, callback) {
@ -1372,7 +1383,7 @@ BlockData.prototype._writeAsync = function _writeAsync(data, offset, callback) {
} }
if (!bytes) if (!bytes)
return callback(new Error('_writeAsync() failed.')); return callback(self._ioError('_writeAsync', size, offset));
index += bytes; index += bytes;
size -= bytes; size -= bytes;

View File

@ -47,6 +47,8 @@ function Chain(options) {
this.pendingLimit = options.pendingLimit || 10 * 1024 * 1024; this.pendingLimit = options.pendingLimit || 10 * 1024 * 1024;
this.invalid = {}; this.invalid = {};
this.bestHeight = -1; this.bestHeight = -1;
this.lastUpdate = utils.now();
this.blockDelta = 0;
this.orphan = { this.orphan = {
map: {}, map: {},
@ -716,7 +718,7 @@ Chain.prototype._fillBlock = function _fillBlock(block, callback) {
Chain.prototype._addEntry = function _addEntry(entry, block, callback) { Chain.prototype._addEntry = function _addEntry(entry, block, callback) {
var self = this; var self = this;
var existing; var existing, now;
callback = utils.asyncify(callback); callback = utils.asyncify(callback);
@ -731,6 +733,10 @@ Chain.prototype._addEntry = function _addEntry(entry, block, callback) {
if (existing && existing.hash === entry.hash) if (existing && existing.hash === entry.hash)
return callback(null, false); return callback(null, false);
now = utils.now();
this.blockDelta = now - this.lastUpdate;
this.lastUpdate = now;
this._saveBlock(block, function(err) { this._saveBlock(block, function(err) {
if (err) if (err)
return callback(err); return callback(err);
@ -1539,6 +1545,14 @@ Chain.prototype.isFull = function isFull() {
return delta < 40 * 60; return delta < 40 * 60;
}; };
Chain.prototype.isInitial = function isInitial() {
if (!this.tip)
return true;
// Should mimic the original IsInitialBlockDownload() function
return this.blockDelta < 10 && this.tip.ts < utils.now() - 24 * 60 * 60;
};
Chain.prototype.getProgress = function getProgress() { Chain.prototype.getProgress = function getProgress() {
if (!this.tip) if (!this.tip)
return 0; return 0;

View File

@ -47,6 +47,7 @@ function ChainDB(chain, options) {
this.size = 0; this.size = 0;
this.fd = null; this.fd = null;
this.loading = false; this.loading = false;
this.loaded = false;
// Need to cache up to the retarget interval // Need to cache up to the retarget interval
// if we're going to be checking the damn // if we're going to be checking the damn
@ -122,6 +123,7 @@ ChainDB.prototype.load = function load(start, callback) {
function finish(err) { function finish(err) {
self.loading = false; self.loading = false;
self.loaded = true;
self.emit('load'); self.emit('load');
if (err) if (err)
@ -617,6 +619,15 @@ ChainDB.prototype.has = function has(height) {
return false; return false;
}; };
ChainDB.prototype._ioError = function _ioError(name, size, offset) {
return new Error(name
+ '() failed at offset '
+ offset
+ ' with '
+ size
+ ' bytes left.');
};
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;
@ -646,7 +657,7 @@ ChainDB.prototype._readSync = function _readSync(size, offset) {
this._free(data); this._free(data);
throw new Error('_readSync() failed.'); throw this._ioError('_readSync', size, offset);
}; };
ChainDB.prototype._readAsync = function _readAsync(size, offset, callback) { ChainDB.prototype._readAsync = function _readAsync(size, offset, callback) {
@ -672,7 +683,7 @@ ChainDB.prototype._readAsync = function _readAsync(size, offset, callback) {
} }
if (!bytes) if (!bytes)
return callback(new Error('_readAsync() failed.')); return callback(self._ioError('_readAsync', size, offset));
index += bytes; index += bytes;
size -= bytes; size -= bytes;
@ -717,7 +728,9 @@ ChainDB.prototype._writeSync = function _writeSync(data, offset) {
throw e; throw e;
} }
throw new Error('_writeSync() failed.'); fs.fsyncSync(this.fd);
throw this._ioError('_writeSync', size, offset);
}; };
ChainDB.prototype._writeAsync = function _writeAsync(data, offset, callback) { ChainDB.prototype._writeAsync = function _writeAsync(data, offset, callback) {
@ -747,14 +760,23 @@ ChainDB.prototype._writeAsync = function _writeAsync(data, offset, callback) {
} }
if (!bytes) if (!bytes)
return callback(new Error('_writeAsync() failed.')); return callback(self._ioError('_writeAsync', size, offset));
index += bytes; index += bytes;
size -= bytes; size -= bytes;
offset += bytes; offset += bytes;
if (index === data.length) if (index === data.length) {
return callback(null, true); // Don't fsync when we're
// potentially preloading headers.
if (!self.chain.loaded)
return callback(null, true);
return fs.fsync(self.fd, function(err) {
if (err)
return callback(err);
return callback(null, true);
});
}
next(); next();
}); });