LevelDbFullPrunedBlockStore: Reformat and rename class. It used Windows line endings.

This commit is contained in:
Andreas Schildbach
2016-01-25 22:51:47 +01:00
parent 08ab6a0da5
commit 59fa28ec70
3 changed files with 1148 additions and 1215 deletions

View File

@@ -51,22 +51,17 @@ import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
/**
*
* <p>
* An implementation of a Fully Pruned Block Store using a leveldb
* implementation as the backing data store.
* An implementation of a Fully Pruned Block Store using a leveldb implementation as the backing data store.
* <p>
*
* <p>
* Includes number of caches to optimise the initial blockchain download.
* </p>
*
*
*/
public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
private static final Logger log = LoggerFactory
.getLogger(LevelDbFullPrunedBlockStore.class);
public class LevelDBFullPrunedBlockStore implements FullPrunedBlockStore {
private static final Logger log = LoggerFactory.getLogger(LevelDBFullPrunedBlockStore.class);
NetworkParameters params;
@@ -170,8 +165,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
DBIterator iterator = db.iterator();
byte[] key = getKey(KeyType.OPENOUT_ALL);
for (iterator.seek(key); iterator.hasNext(); iterator.next()) {
ByteBuffer bbKey = ByteBuffer
.wrap(iterator.peekNext().getKey());
ByteBuffer bbKey = ByteBuffer.wrap(iterator.peekNext().getKey());
byte firstByte = bbKey.get(); // remove the KeyType.OPENOUT_ALL
// byte.
if (key[0] != firstByte) {
@@ -192,8 +186,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
public void printStat() {
log.info("Bloom Added: " + added + " T: " + returnedTrue + " F: "
+ returnedFalse);
log.info("Bloom Added: " + added + " T: " + returnedTrue + " F: " + returnedFalse);
}
// Add a txhash to the filter.
@@ -230,8 +223,8 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
private void setBit(byte[] entry) {
int arrayIndex = (entry[0] & 0x3F) << 21 | (entry[1] & 0xFF) << 13
| (entry[2] & 0xFF) << 5 | (entry[3] & 0xFF) >> 3;
int arrayIndex = (entry[0] & 0x3F) << 21 | (entry[1] & 0xFF) << 13 | (entry[2] & 0xFF) << 5
| (entry[3] & 0xFF) >> 3;
int bit = (entry[3] & 0x07);
int orBit = (0x1 << bit);
byte newEntry = (byte) ((int) cache[arrayIndex] | orBit);
@@ -239,8 +232,8 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
private boolean getBit(byte[] entry) {
int arrayIndex = (entry[0] & 0x3F) << 21 | (entry[1] & 0xFF) << 13
| (entry[2] & 0xFF) << 5 | (entry[3] & 0xFF) >> 3;
int arrayIndex = (entry[0] & 0x3F) << 21 | (entry[1] & 0xFF) << 13 | (entry[2] & 0xFF) << 5
| (entry[3] & 0xFF) >> 3;
int bit = (entry[3] & 0x07);
int orBit = (0x1 << bit);
byte arrayEntry = cache[arrayIndex];
@@ -255,18 +248,13 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
}
public LevelDbFullPrunedBlockStore(NetworkParameters params,
String filename, int blockCount) {
this(params, filename, blockCount, LEVELDB_READ_CACHE_DEFAULT,
LEVELDB_WRITE_CACHE_DEFAULT, OPENOUT_CACHE_DEFAULT, false,
Integer.MAX_VALUE);
public LevelDBFullPrunedBlockStore(NetworkParameters params, String filename, int blockCount) {
this(params, filename, blockCount, LEVELDB_READ_CACHE_DEFAULT, LEVELDB_WRITE_CACHE_DEFAULT,
OPENOUT_CACHE_DEFAULT, false, Integer.MAX_VALUE);
}
public LevelDbFullPrunedBlockStore(NetworkParameters params,
String filename, int blockCount, long leveldbReadCache,
int leveldbWriteCache, int openOutCache, boolean instrument,
int exitBlock) {
public LevelDBFullPrunedBlockStore(NetworkParameters params, String filename, int blockCount, long leveldbReadCache,
int leveldbWriteCache, int openOutCache, boolean instrument, int exitBlock) {
this.params = params;
fullStoreDepth = blockCount;
this.instrument = instrument;
@@ -275,8 +263,6 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
methodCalls = new HashMap<String, Long>();
methodTotalTime = new HashMap<String, Long>();
this.filename = filename;
this.leveldbReadCache = leveldbReadCache;
this.leveldbWriteCache = leveldbWriteCache;
@@ -319,40 +305,34 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
private void initFromDb() throws BlockStoreException {
Sha256Hash hash = Sha256Hash
.wrap(batchGet(getKey(KeyType.CHAIN_HEAD_SETTING)));
Sha256Hash hash = Sha256Hash.wrap(batchGet(getKey(KeyType.CHAIN_HEAD_SETTING)));
this.chainHeadBlock = get(hash);
this.chainHeadHash = hash;
if (this.chainHeadBlock == null) {
throw new BlockStoreException(
"corrupt database block store - head block not found");
throw new BlockStoreException("corrupt database block store - head block not found");
}
hash = Sha256Hash
.wrap(batchGet(getKey(KeyType.VERIFIED_CHAIN_HEAD_SETTING)));
hash = Sha256Hash.wrap(batchGet(getKey(KeyType.VERIFIED_CHAIN_HEAD_SETTING)));
this.verifiedChainHeadBlock = get(hash);
this.verifiedChainHeadHash = hash;
if (this.verifiedChainHeadBlock == null) {
throw new BlockStoreException(
"corrupt databse block store - verified head block not found");
throw new BlockStoreException("corrupt databse block store - verified head block not found");
}
}
private void createNewStore(NetworkParameters params)
throws BlockStoreException {
private void createNewStore(NetworkParameters params) throws BlockStoreException {
try {
// Set up the genesis block. When we start out fresh, it is by
// definition the top of the chain.
StoredBlock storedGenesisHeader = new StoredBlock(params
.getGenesisBlock().cloneAsHeader(), params
.getGenesisBlock().getWork(), 0);
StoredBlock storedGenesisHeader = new StoredBlock(params.getGenesisBlock().cloneAsHeader(),
params.getGenesisBlock().getWork(), 0);
// The coinbase in the genesis block is not spendable. This is
// because of how the reference client inits
// its database - the genesis transaction isn't actually in the db
// so its spent flags can never be updated.
List<Transaction> genesisTransactions = Lists.newLinkedList();
StoredUndoableBlock storedGenesis = new StoredUndoableBlock(params
.getGenesisBlock().getHash(), genesisTransactions);
StoredUndoableBlock storedGenesis = new StoredUndoableBlock(params.getGenesisBlock().getHash(),
genesisTransactions);
beginDatabaseBatchWrite();
put(storedGenesisHeader, storedGenesis);
setChainHead(storedGenesisHeader);
@@ -372,12 +352,10 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
if (methodCalls.containsKey(name)) {
methodCalls.put(name, methodCalls.get(name) + 1);
methodTotalTime.put(name,
methodTotalTime.get(name)
+ methodStartTime.get(name).elapsed(TimeUnit.NANOSECONDS));
methodTotalTime.get(name) + methodStartTime.get(name).elapsed(TimeUnit.NANOSECONDS));
} else {
methodCalls.put(name, 1l);
methodTotalTime.put(name,
methodStartTime.get(name).elapsed(TimeUnit.NANOSECONDS));
methodTotalTime.put(name, methodStartTime.get(name).elapsed(TimeUnit.NANOSECONDS));
}
}
@@ -392,23 +370,18 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
dbtime += time;
long average = time / calls;
double proportion = (time + 0.0) / (wallTimeNanos + 0.0);
log.info(name + " c:" + calls + " r:" + time + " a:" + average
+ " p:" + String.format("%.2f", proportion));
log.info(name + " c:" + calls + " r:" + time + " a:" + average + " p:" + String.format("%.2f", proportion));
}
double dbproportion = (dbtime + 0.0) / (wallTimeNanos + 0.0);
double hitrate = (hit + 0.0) / (hit + miss + 0.0);
log.info("Cache size:" + utxoCache.size() + " hit:" + hit + " miss:"
+ miss + " rate:" + String.format("%.2f", hitrate));
log.info("Cache size:" + utxoCache.size() + " hit:" + hit + " miss:" + miss + " rate:"
+ String.format("%.2f", hitrate));
bloom.printStat();
log.info("hasTxOut call:" + hasCall + " True:" + hasTrue + " False:"
+ hasFalse);
log.info("Wall:" + totalStopwatch + " percent:"
+ String.format("%.2f", dbproportion));
log.info("hasTxOut call:" + hasCall + " True:" + hasTrue + " False:" + hasFalse);
log.info("Wall:" + totalStopwatch + " percent:" + String.format("%.2f", dbproportion));
String stats = db.getProperty("leveldb.stats");
System.out.println(stats);
}
@Override
@@ -449,8 +422,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
@Override
public List<UTXO> getOpenTransactionOutputs(List<Address> addresses)
throws UTXOProviderException {
public List<UTXO> getOpenTransactionOutputs(List<Address> addresses) throws UTXOProviderException {
// Run this on a snapshot of database so internally consistent result
// This is critical or if one address paid another could get incorrect
// results
@@ -469,8 +441,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
DBIterator iterator = db.iterator(ro);
for (iterator.seek(bb.array()); iterator.hasNext(); iterator.next()) {
ByteBuffer bbKey = ByteBuffer
.wrap(iterator.peekNext().getKey());
ByteBuffer bbKey = ByteBuffer.wrap(iterator.peekNext().getKey());
bbKey.get(); // remove the address_hashindex byte.
byte[] addressKey = new byte[20];
bbKey.get(addressKey);
@@ -493,13 +464,10 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
if (txout != null) {
Script sc = txout.getScript();
Address address = sc.getToAddress(params, true);
UTXO output = new UTXO(txout.getHash(), txout.getIndex(),
txout.getValue(), txout.getHeight(),
txout.isCoinbase(), txout.getScript(),
address.toString());
UTXO output = new UTXO(txout.getHash(), txout.getIndex(), txout.getValue(), txout.getHeight(),
txout.isCoinbase(), txout.getScript(), address.toString());
results.add(output);
}
}
try {
iterator.close();
@@ -510,7 +478,6 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
} catch (IOException e) {
log.error("Error closing snapshot/iterator?", e);
}
}
return results;
}
@@ -524,8 +491,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
}
protected void putUpdateStoredBlock(StoredBlock storedBlock,
boolean wasUndoable) {
protected void putUpdateStoredBlock(StoredBlock storedBlock, boolean wasUndoable) {
// We put as one record as then the get is much faster.
if (instrument)
beginMethod("putUpdateStoredBlock");
@@ -539,8 +505,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
@Override
public void put(StoredBlock storedBlock, StoredUndoableBlock undoableBlock)
throws BlockStoreException {
public void put(StoredBlock storedBlock, StoredUndoableBlock undoableBlock) throws BlockStoreException {
if (instrument)
beginMethod("put");
int height = storedBlock.getHeight();
@@ -575,16 +540,14 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
batchPut(keyBuf.array(), new byte[1]);
if (transactions == null) {
ByteBuffer undoBuf = ByteBuffer.allocate(4 + 4
+ txOutChanges.length + 4 + 0);
ByteBuffer undoBuf = ByteBuffer.allocate(4 + 4 + txOutChanges.length + 4 + 0);
undoBuf.putInt(height);
undoBuf.putInt(txOutChanges.length);
undoBuf.put(txOutChanges);
undoBuf.putInt(0);
batchPut(getKey(KeyType.UNDOABLEBLOCKS_ALL, hash), undoBuf.array());
} else {
ByteBuffer undoBuf = ByteBuffer.allocate(4 + 4 + 0 + 4
+ transactions.length);
ByteBuffer undoBuf = ByteBuffer.allocate(4 + 4 + 0 + 4 + transactions.length);
undoBuf.putInt(height);
undoBuf.putInt(0);
undoBuf.putInt(transactions.length);
@@ -594,7 +557,6 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
if (instrument)
endMethod("put");
putUpdateStoredBlock(storedBlock, true);
}
// Since LevelDB is a key value store we do not have "tables".
@@ -647,8 +609,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
@Override
public StoredBlock getOnceUndoableStoredBlock(Sha256Hash hash)
throws BlockStoreException {
public StoredBlock getOnceUndoableStoredBlock(Sha256Hash hash) throws BlockStoreException {
return get(hash, true);
}
@@ -657,8 +618,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
return get(hash, false);
}
public StoredBlock get(Sha256Hash hash, boolean wasUndoableOnly)
throws BlockStoreException {
public StoredBlock get(Sha256Hash hash, boolean wasUndoableOnly) throws BlockStoreException {
// Optimize for chain head
if (chainHeadHash != null && chainHeadHash.equals(hash))
@@ -685,19 +645,16 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
// TODO Should I chop the last byte off? Seems to work with it left
// there...
StoredBlock stored = StoredBlock.deserializeCompact(params,
ByteBuffer.wrap(result));
StoredBlock stored = StoredBlock.deserializeCompact(params, ByteBuffer.wrap(result));
stored.getHeader().verifyHeader();
if (instrument)
endMethod("get");
return stored;
}
@Override
public StoredUndoableBlock getUndoBlock(Sha256Hash hash)
throws BlockStoreException {
public StoredUndoableBlock getUndoBlock(Sha256Hash hash) throws BlockStoreException {
try {
if (instrument)
beginMethod("getUndoBlock");
@@ -720,14 +677,11 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
byte[] transactions = new byte[txSize];
bb.get(transactions);
int offset = 0;
int numTxn = ((transactions[offset++] & 0xFF) << 0)
| ((transactions[offset++] & 0xFF) << 8)
| ((transactions[offset++] & 0xFF) << 16)
| ((transactions[offset++] & 0xFF) << 24);
int numTxn = ((transactions[offset++] & 0xFF) << 0) | ((transactions[offset++] & 0xFF) << 8)
| ((transactions[offset++] & 0xFF) << 16) | ((transactions[offset++] & 0xFF) << 24);
List<Transaction> transactionList = new LinkedList<Transaction>();
for (int i = 0; i < numTxn; i++) {
Transaction tx = new Transaction(params, transactions,
offset);
Transaction tx = new Transaction(params, transactions, offset);
transactionList.add(tx);
offset += tx.getMessageSize();
}
@@ -752,13 +706,11 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
@Override
public UTXO getTransactionOutput(Sha256Hash hash, long index)
throws BlockStoreException {
public UTXO getTransactionOutput(Sha256Hash hash, long index) throws BlockStoreException {
if (instrument)
beginMethod("getTransactionOutput");
try {
UTXO result = null;
byte[] key = getTxKey(KeyType.OPENOUT_ALL, hash, (int) index);
// Use cache
@@ -814,8 +766,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
@Override
public void addUnspentTransactionOutput(UTXO out)
throws BlockStoreException {
public void addUnspentTransactionOutput(UTXO out) throws BlockStoreException {
if (instrument)
beginMethod("addUnspentTransactionOutput");
@@ -830,8 +781,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
throw new BlockStoreException("problem serialising utxo");
}
byte[] key = getTxKey(KeyType.OPENOUT_ALL, out.getHash(),
(int) out.getIndex());
byte[] key = getTxKey(KeyType.OPENOUT_ALL, out.getHash(), (int) out.getIndex());
batchPut(key, bos.toByteArray());
if (autoCommit) {
@@ -885,8 +835,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
ByteBuffer bbKey = ByteBuffer.wrap(key);
// This is needed to cope with deletes that are not yet committed to db.
if (!autoCommit && uncommitedDeletes != null
&& uncommitedDeletes.contains(bbKey))
if (!autoCommit && uncommitedDeletes != null && uncommitedDeletes.contains(bbKey))
return null;
byte[] value = null;
@@ -917,17 +866,14 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
} else {
db.delete(key);
}
}
@Override
public void removeUnspentTransactionOutput(UTXO out)
throws BlockStoreException {
public void removeUnspentTransactionOutput(UTXO out) throws BlockStoreException {
if (instrument)
beginMethod("removeUnspentTransactionOutput");
byte[] key = getTxKey(KeyType.OPENOUT_ALL, out.getHash(),
(int) out.getIndex());
byte[] key = getTxKey(KeyType.OPENOUT_ALL, out.getHash(), (int) out.getIndex());
if (autoCommit) {
utxoCache.remove(ByteBuffer.wrap(key));
@@ -982,8 +928,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
long hasFalse;
@Override
public boolean hasUnspentOutputs(Sha256Hash hash, int numOutputs)
throws BlockStoreException {
public boolean hasUnspentOutputs(Sha256Hash hash, int numOutputs) throws BlockStoreException {
if (instrument)
beginMethod("hasUnspentOutputs");
hasCall++;
@@ -1032,7 +977,6 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
if (instrument)
endMethod("hasUnspentOutputs");
return false;
}
@Override
@@ -1041,8 +985,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
}
@Override
public void setVerifiedChainHead(StoredBlock chainHead)
throws BlockStoreException {
public void setVerifiedChainHead(StoredBlock chainHead) throws BlockStoreException {
if (instrument)
beginMethod("setVerifiedChainHead");
Sha256Hash hash = chainHead.getHeader().getHash();
@@ -1051,8 +994,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
batchPut(getKey(KeyType.VERIFIED_CHAIN_HEAD_SETTING), hash.getBytes());
if (this.chainHeadBlock.getHeight() < chainHead.getHeight())
setChainHead(chainHead);
removeUndoableBlocksWhereHeightIsLessThan(chainHead.getHeight()
- fullStoreDepth);
removeUndoableBlocksWhereHeightIsLessThan(chainHead.getHeight() - fullStoreDepth);
if (instrument)
endMethod("setVerifiedChainHead");
}
@@ -1079,9 +1021,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
break;
batchDelete(getKey(KeyType.UNDOABLEBLOCKS_ALL, hashbytes));
batchDelete(bytekey);
}
try {
iterator.close();
@@ -1095,7 +1035,6 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
@Override
public void beginDatabaseBatchWrite() throws BlockStoreException {
// This is often called twice in row! But they are not nested
// transactions!
// We just ignore the second call.
@@ -1126,8 +1065,7 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
// order of these is not important as we only allow entry to be in one
// or the other.
// must update cache with uncommitted adds/deletes.
for (Map.Entry<ByteBuffer, UTXO> entry : utxoUncommittedCache
.entrySet()) {
for (Map.Entry<ByteBuffer, UTXO> entry : utxoUncommittedCache.entrySet()) {
utxoCache.put(entry.getKey(), entry.getValue());
}
@@ -1158,12 +1096,10 @@ public class LevelDbFullPrunedBlockStore implements FullPrunedBlockStore {
System.exit(1);
}
}
}
@Override
public void abortDatabaseBatchWrite() throws BlockStoreException {
try {
uncommited = null;
uncommitedDeletes = null;

View File

@@ -17,8 +17,7 @@ package org.bitcoinj.core;
import org.bitcoinj.store.BlockStoreException;
import org.bitcoinj.store.FullPrunedBlockStore;
import org.bitcoinj.store.H2FullPrunedBlockStore;
import org.bitcoinj.store.LevelDbFullPrunedBlockStore;
import org.bitcoinj.store.LevelDBFullPrunedBlockStore;
import org.junit.After;
import java.io.File;
@@ -26,7 +25,7 @@ import java.io.File;
/**
* An H2 implementation of the FullPrunedBlockStoreTest
*/
public class LevelDbFullPrunedBlockChainTest extends
public class LevelDBFullPrunedBlockChainTest extends
AbstractFullPrunedBlockChainTest {
@After
public void tearDown() throws Exception {
@@ -37,7 +36,7 @@ public class LevelDbFullPrunedBlockChainTest extends
public FullPrunedBlockStore createStore(NetworkParameters params,
int blockCount) throws BlockStoreException {
deleteFiles();
return new LevelDbFullPrunedBlockStore(params, "test-leveldb",
return new LevelDBFullPrunedBlockStore(params, "test-leveldb",
blockCount);
}
@@ -52,6 +51,6 @@ public class LevelDbFullPrunedBlockChainTest extends
@Override
public void resetStore(FullPrunedBlockStore store)
throws BlockStoreException {
((LevelDbFullPrunedBlockStore) store).resetStore();
((LevelDBFullPrunedBlockStore) store).resetStore();
}
}

View File

@@ -20,15 +20,15 @@ import org.bitcoinj.core.FullPrunedBlockChain;
import org.bitcoinj.core.PeerGroup;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.store.FullPrunedBlockStore;
import org.bitcoinj.store.LevelDbFullPrunedBlockStore;
import org.bitcoinj.store.LevelDBFullPrunedBlockStore;
public class LevelDb {
public class LevelDB {
public static void main(String[] args) throws Exception {
/*
* This is just a test runner that will download blockchain till block
* 390000 then exit.
*/
FullPrunedBlockStore store = new LevelDbFullPrunedBlockStore(
FullPrunedBlockStore store = new LevelDBFullPrunedBlockStore(
MainNetParams.get(), args[0], 1000, 100 * 1024 * 1024l,
10 * 1024 * 1024, 100000, true, 390000);
@@ -42,7 +42,5 @@ public class LevelDb {
vPeerGroup.start();
vPeerGroup.downloadBlockChain();
}
}