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) {
var index = 0;
var data, bytes;
@ -1271,7 +1280,7 @@ BlockData.prototype._readSync = function _readSync(size, offset) {
this._free(data);
throw new Error('_readSync() failed.');
throw this._ioError('_readSync', size, offset);
};
BlockData.prototype._readAsync = function _readAsync(size, offset, callback) {
@ -1297,7 +1306,7 @@ BlockData.prototype._readAsync = function _readAsync(size, offset, callback) {
}
if (!bytes)
return callback(new Error('_readAsync() failed at offset ' + offset + ' ' + size + ' to go'));
return callback(self._ioError('_readAsync', size, offset));
index += bytes;
size -= bytes;
@ -1342,7 +1351,9 @@ BlockData.prototype._writeSync = function _writeSync(data, offset) {
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) {
@ -1372,7 +1383,7 @@ BlockData.prototype._writeAsync = function _writeAsync(data, offset, callback) {
}
if (!bytes)
return callback(new Error('_writeAsync() failed.'));
return callback(self._ioError('_writeAsync', size, offset));
index += bytes;
size -= bytes;

View File

@ -47,6 +47,8 @@ function Chain(options) {
this.pendingLimit = options.pendingLimit || 10 * 1024 * 1024;
this.invalid = {};
this.bestHeight = -1;
this.lastUpdate = utils.now();
this.blockDelta = 0;
this.orphan = {
map: {},
@ -716,7 +718,7 @@ Chain.prototype._fillBlock = function _fillBlock(block, callback) {
Chain.prototype._addEntry = function _addEntry(entry, block, callback) {
var self = this;
var existing;
var existing, now;
callback = utils.asyncify(callback);
@ -731,6 +733,10 @@ Chain.prototype._addEntry = function _addEntry(entry, block, callback) {
if (existing && existing.hash === entry.hash)
return callback(null, false);
now = utils.now();
this.blockDelta = now - this.lastUpdate;
this.lastUpdate = now;
this._saveBlock(block, function(err) {
if (err)
return callback(err);
@ -1539,6 +1545,14 @@ Chain.prototype.isFull = function isFull() {
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() {
if (!this.tip)
return 0;

View File

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