lru: better atomicity for chain and walletdb.

This commit is contained in:
Christopher Jeffrey 2016-10-23 04:54:45 -07:00
parent 0ebeb1e643
commit 331daf0f6a
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
3 changed files with 52 additions and 19 deletions

View File

@ -274,8 +274,14 @@ ChainDB.prototype._close = function close() {
ChainDB.prototype.start = function start() {
assert(!this.current);
assert(!this.pending);
this.current = this.db.batch();
this.pending = this.state.clone();
this.coinCache.start();
this.cacheHash.start();
this.cacheHeight.start();
return this.current;
};
@ -316,11 +322,19 @@ ChainDB.prototype.batch = function batch() {
*/
ChainDB.prototype.drop = function drop() {
var batch = this.current;
assert(this.current);
assert(this.pending);
this.current.clear();
this.current = null;
this.pending = null;
this.coinCache.drop();
this.cacheHash.drop();
this.cacheHeight.drop();
batch.clear();
};
/**
@ -337,11 +351,12 @@ ChainDB.prototype.commit = co(function* commit() {
} catch (e) {
this.current = null;
this.pending = null;
this.coinCache.drop();
this.cacheHash.drop();
this.cacheHeight.drop();
throw e;
}
this.current = null;
// Overwrite the entire state
// with our new best state
// only if it is committed.
@ -350,7 +365,12 @@ ChainDB.prototype.commit = co(function* commit() {
if (this.pending.committed)
this.state = this.pending;
this.current = null;
this.pending = null;
this.coinCache.commit();
this.cacheHash.commit();
this.cacheHeight.commit();
});
/**
@ -1167,14 +1187,14 @@ ChainDB.prototype._save = co(function* save(entry, block, view) {
this.put(layout.h(hash), U32(entry.height));
this.put(layout.e(hash), entry.toRaw());
this.cacheHash.set(entry.hash, entry);
this.cacheHash.push(entry.hash, entry);
if (!view) {
yield this.saveBlock(block);
return;
}
this.cacheHeight.set(entry.height, entry);
this.cacheHeight.push(entry.height, entry);
this.put(layout.n(entry.prevBlock), hash);
this.put(layout.H(entry.height), hash);
@ -1218,8 +1238,8 @@ ChainDB.prototype._reconnect = co(function* reconnect(entry, block, view) {
this.put(layout.n(entry.prevBlock), hash);
this.put(layout.H(entry.height), hash);
this.cacheHash.set(entry.hash, entry);
this.cacheHeight.set(entry.height, entry);
this.cacheHash.push(entry.hash, entry);
this.cacheHeight.push(entry.height, entry);
yield this.connectBlock(block, view);
@ -1262,7 +1282,7 @@ ChainDB.prototype._disconnect = co(function* disconnect(entry) {
this.del(layout.n(entry.prevBlock));
this.del(layout.H(entry.height));
this.cacheHeight.remove(entry.height);
this.cacheHeight.unpush(entry.height);
block = yield this.getBlock(entry.hash);
@ -1457,10 +1477,10 @@ ChainDB.prototype.connectBlock = co(function* connectBlock(block, view) {
raw = coins.toRaw();
if (!raw) {
this.del(layout.c(coins.hash));
this.coinCache.remove(coins.hash);
this.coinCache.unpush(coins.hash);
} else {
this.put(layout.c(coins.hash), raw);
this.coinCache.set(coins.hash, raw);
this.coinCache.push(coins.hash, raw);
}
}
@ -1553,10 +1573,10 @@ ChainDB.prototype.disconnectBlock = co(function* disconnectBlock(block) {
raw = coins.toRaw();
if (!raw) {
this.del(layout.c(coins.hash));
this.coinCache.remove(coins.hash);
this.coinCache.unpush(coins.hash);
} else {
this.put(layout.c(coins.hash), raw);
this.coinCache.set(coins.hash, raw);
this.coinCache.push(coins.hash, raw);
}
}

View File

@ -262,6 +262,7 @@ TXDB.prototype.open = co(function* open() {
TXDB.prototype.start = function start() {
this.pending = this.state.clone();
this.coinCache.start();
return this.wallet.start();
};
@ -273,6 +274,7 @@ TXDB.prototype.start = function start() {
TXDB.prototype.drop = function drop() {
this.pending = null;
this.events.length = 0;
this.coinCache.drop();
return this.wallet.drop();
};
@ -284,6 +286,7 @@ TXDB.prototype.drop = function drop() {
TXDB.prototype.clear = function clear() {
this.pending = this.state.clone();
this.events.length = 0;
this.coinCache.clear();
return this.wallet.clear();
};
@ -300,6 +303,7 @@ TXDB.prototype.commit = co(function* commit() {
} catch (e) {
this.pending = null;
this.events.length = 0;
this.coinCache.drop();
throw e;
}
@ -319,6 +323,7 @@ TXDB.prototype.commit = co(function* commit() {
this.pending = null;
this.events.length = 0;
this.coinCache.commit();
});
/**
@ -677,7 +682,7 @@ TXDB.prototype.saveCredit = function saveCredit(credit, path) {
var raw = credit.toRaw();
this.put(layout.c(prevout.hash, prevout.index), raw);
this.put(layout.C(path.account, prevout.hash, prevout.index), DUMMY);
this.coinCache.set(key, raw);
this.coinCache.push(key, raw);
};
/**
@ -691,7 +696,7 @@ TXDB.prototype.removeCredit = function removeCredit(credit, path) {
var key = prevout.hash + prevout.index;
this.del(layout.c(prevout.hash, prevout.index));
this.del(layout.C(path.account, prevout.hash, prevout.index));
this.coinCache.remove(key);
this.coinCache.unpush(key);
};
/**

View File

@ -369,6 +369,8 @@ WalletDB.prototype.getHeight = co(function* getHeight() {
WalletDB.prototype.start = function start(wallet) {
assert(!wallet.current, 'Batch already started.');
wallet.current = this.db.batch();
wallet.accountCache.start();
wallet.pathCache.start();
return wallet.current;
};
@ -381,6 +383,8 @@ WalletDB.prototype.start = function start(wallet) {
WalletDB.prototype.drop = function drop(wallet) {
var batch = this.batch(wallet);
wallet.current = null;
wallet.accountCache.drop();
wallet.pathCache.drop();
batch.clear();
};
@ -392,6 +396,8 @@ WalletDB.prototype.drop = function drop(wallet) {
WalletDB.prototype.clear = function clear(wallet) {
var batch = this.batch(wallet);
wallet.accountCache.clear();
wallet.pathCache.clear();
batch.clear();
};
@ -414,11 +420,13 @@ WalletDB.prototype.batch = function batch(wallet) {
* @returns {Promise}
*/
WalletDB.prototype.commit = function commit(wallet) {
WalletDB.prototype.commit = co(function* commit(wallet) {
var batch = wallet.current;
wallet.current = null;
return batch.write();
};
yield batch.write();
wallet.accountCache.commit();
wallet.pathCache.commit();
});
/**
* Load the bloom filter into memory.
@ -862,7 +870,7 @@ WalletDB.prototype.saveAccount = function saveAccount(account) {
batch.put(layout.a(wid, index), account.toRaw());
batch.put(layout.i(wid, name), U32(index));
wallet.accountCache.set(index, account);
wallet.accountCache.push(index, account);
};
/**
@ -947,7 +955,7 @@ WalletDB.prototype.savePath = co(function* savePath(wallet, path) {
return;
this.pathMapCache.set(hash, wids);
wallet.pathCache.set(hash, path);
wallet.pathCache.push(hash, path);
batch.put(layout.p(hash), serializeWallets(wids));
batch.put(layout.P(wid, hash), path.toRaw());