blockstore: recover from block write interrupt
This commit is contained in:
parent
64fb7c1d88
commit
2d08b296f7
@ -191,9 +191,12 @@ class FileBlockStore extends AbstractBlockStore {
|
||||
|
||||
const rec = await this.db.get(layout.f.encode(fileno));
|
||||
|
||||
let touch = false;
|
||||
|
||||
if (rec) {
|
||||
filerecord = FileRecord.fromRaw(rec);
|
||||
} else {
|
||||
touch = true;
|
||||
filerecord = new FileRecord({
|
||||
blocks: 0,
|
||||
used: 0,
|
||||
@ -204,6 +207,7 @@ class FileBlockStore extends AbstractBlockStore {
|
||||
if (filerecord.used + length > filerecord.length) {
|
||||
fileno += 1;
|
||||
filepath = this.filepath(fileno);
|
||||
touch = true;
|
||||
filerecord = new FileRecord({
|
||||
blocks: 0,
|
||||
used: 0,
|
||||
@ -211,6 +215,11 @@ class FileBlockStore extends AbstractBlockStore {
|
||||
});
|
||||
}
|
||||
|
||||
if (touch) {
|
||||
const fd = await fs.open(filepath, 'w');
|
||||
await fs.close(fd);
|
||||
}
|
||||
|
||||
return {fileno, filerecord, filepath};
|
||||
}
|
||||
|
||||
@ -240,7 +249,7 @@ class FileBlockStore extends AbstractBlockStore {
|
||||
bwm.writeU32(blength);
|
||||
const magic = bwm.render();
|
||||
|
||||
const fd = await fs.open(filepath, 'a');
|
||||
const fd = await fs.open(filepath, 'r+');
|
||||
|
||||
const mwritten = await fs.write(fd, magic, 0, mlength, mposition);
|
||||
const bwritten = await fs.write(fd, data, 0, blength, bposition);
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
'use strict';
|
||||
|
||||
const Logger = require('blgr');
|
||||
const bio = require('bufio');
|
||||
const assert = require('./util/assert');
|
||||
const common = require('./util/common');
|
||||
const {resolve} = require('path');
|
||||
@ -428,6 +429,54 @@ describe('BlockStore', function() {
|
||||
}
|
||||
});
|
||||
|
||||
it('will recover from interrupt during block write', async () => {
|
||||
{
|
||||
const block = random.randomBytes(128);
|
||||
const hash = random.randomBytes(32);
|
||||
await store.write(hash, block);
|
||||
|
||||
const block2 = await store.read(hash);
|
||||
assert.bufferEqual(block2, block);
|
||||
}
|
||||
|
||||
// Manually insert a partially written block to the
|
||||
// end of file as would be the case of an untimely
|
||||
// interrupted write of a block. The file record
|
||||
// would not be updated to include the used bytes and
|
||||
// thus this data should be overwritten.
|
||||
{
|
||||
const filepath = store.filepath(0);
|
||||
|
||||
const fd = await fs.open(filepath, 'a');
|
||||
|
||||
const bw = bio.write(8);
|
||||
bw.writeU32(store.network.magic);
|
||||
bw.writeU32(73);
|
||||
const magic = bw.render();
|
||||
|
||||
const failblock = random.randomBytes(73);
|
||||
|
||||
const mwritten = await fs.write(fd, magic, 0, 8);
|
||||
const bwritten = await fs.write(fd, failblock, 0, 73);
|
||||
|
||||
await fs.close(fd);
|
||||
|
||||
assert.equal(mwritten, 8);
|
||||
assert.equal(bwritten, 73);
|
||||
}
|
||||
|
||||
// Now check that this block has the correct position
|
||||
// in the file and that it can be read correctly.
|
||||
{
|
||||
const block = random.randomBytes(128);
|
||||
const hash = random.randomBytes(32);
|
||||
await store.write(hash, block);
|
||||
|
||||
const block2 = await store.read(hash);
|
||||
assert.bufferEqual(block2, block);
|
||||
}
|
||||
});
|
||||
|
||||
it('will return null if block not found', async () => {
|
||||
const hash = random.randomBytes(32);
|
||||
const block = await store.read(hash);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user