Added missing merge files.

This commit is contained in:
Adrian Tiberius 2015-07-08 14:25:18 +02:00
parent 74eca228dc
commit e376bfc922
8 changed files with 1375 additions and 0 deletions

View File

@ -0,0 +1,16 @@
package org.ethereum.datasource;
/**
* @author Mikhail Kalinin
* @since 07.07.2015
*/
public interface DataSource {
void init();
void setName(String name);
String getName();
void close();
}

View File

@ -0,0 +1,22 @@
package org.ethereum.datasource;
/**
* @author Mikhail Kalinin
* @since 07.07.2015
*/
public interface QueueDataSource extends DataSource {
void offerFirst(byte[] e);
byte[] peekFirst();
byte[] pollFirst();
void offerLast(byte[] e);
byte[] peekLast();
byte[] pollLast();
boolean isEmpty();
}

View File

@ -0,0 +1,117 @@
package org.ethereum.datasource.mapdb;
import org.ethereum.config.SystemProperties;
import org.ethereum.datasource.QueueDataSource;
import org.mapdb.BTreeMap;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.Serializer;
import java.io.File;
import static java.lang.System.getProperty;
/**
* @author Mikhail Kalinin
* @since 07.07.2015
*/
public class MapDBQueueDataSource implements QueueDataSource {
private DB db;
private BTreeMap<Long, byte[]> map;
private String name;
@Override
public void init() {
File dbFile = new File(getProperty("user.dir") + "/" + SystemProperties.CONFIG.databaseDir() + "/" + name);
if (!dbFile.getParentFile().exists()) dbFile.getParentFile().mkdirs();
db = DBMaker.fileDB(dbFile)
.transactionDisable()
.closeOnJvmShutdown()
.make();
map = db.treeMapCreate(name)
.keySerializer(Serializer.LONG)
.valueSerializer(Serializer.BYTE_ARRAY)
.makeOrGet();
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public void close() {
db.close();
}
@Override
public synchronized void offerFirst(byte[] e) {
if(map.isEmpty()) {
offerEmpty(e);
} else {
map.put(map.firstKey() - 1, e);
}
}
@Override
public synchronized byte[] peekFirst() {
if(map.isEmpty()) {
return null;
} else {
return map.firstEntry().getValue();
}
}
@Override
public synchronized byte[] pollFirst() {
if(map.isEmpty()) {
return null;
} else {
return map.pollFirstEntry().getValue();
}
}
@Override
public synchronized void offerLast(byte[] e) {
if(map.isEmpty()) {
offerEmpty(e);
} else {
map.put(map.lastKey() + 1, e);
}
}
@Override
public synchronized byte[] peekLast() {
if(map.isEmpty()) {
return null;
} else {
return map.lastEntry().getValue();
}
}
@Override
public synchronized byte[] pollLast() {
if(map.isEmpty()) {
return null;
} else {
return map.pollLastEntry().getValue();
}
}
@Override
public boolean isEmpty() {
return map.isEmpty();
}
private void offerEmpty(byte[] e) {
map.put(0L, e);
}
}

View File

@ -0,0 +1,67 @@
package org.ethereum.db;
import org.ethereum.datasource.QueueDataSource;
import org.ethereum.datasource.mapdb.MapDBQueueDataSource;
import java.util.Collection;
/**
* @author Mikhail Kalinin
* @since 07.07.2015
*/
public class HashStore {
private static final String DEFAULT_NAME = "hashstore";
private QueueDataSource hashes;
private HashStore() {
}
public void add(byte[] hash) {
hashes.offerLast(hash);
}
public byte[] peek() {
return hashes.peekFirst();
}
public byte[] poll() {
return hashes.pollFirst();
}
public void addFirst(byte[] hash) {
hashes.offerFirst(hash);
}
public boolean isEmpty() {
return hashes.isEmpty();
}
public void close() {
hashes.close();
}
static class Builder {
private String name = DEFAULT_NAME;
private Class<? extends QueueDataSource> dataSourceClass = MapDBQueueDataSource.class;
public Builder withDataSource(Class<? extends QueueDataSource> dataSourceClass) {
this.dataSourceClass = dataSourceClass;
return this;
}
public Builder withName(String name) {
this.name = name;
return this;
}
public HashStore build() throws IllegalAccessException, InstantiationException {
HashStore store = new HashStore();
store.hashes = dataSourceClass.newInstance();
store.hashes.setName(name);
store.hashes.init();
return store;
}
}
}

View File

@ -0,0 +1,275 @@
package org.ethereum.db;
import org.ethereum.core.Block;
import org.ethereum.datasource.KeyValueDataSource;
import org.mapdb.DataIO;
import org.mapdb.Serializer;
import java.io.*;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class IndexedBlockStore {
IndexedBlockStore cache;
Map<Long, List<BlockInfo>> index;
KeyValueDataSource blocks;
public IndexedBlockStore(){
}
public void init(Map<Long, List<BlockInfo>> index, KeyValueDataSource blocks, IndexedBlockStore cache) {
this.cache = cache;
this.index = index;
this.blocks = blocks;
}
public void flush(){
for (byte[] hash : cache.blocks.keys()){
blocks.put(hash, cache.blocks.get(hash));
}
index.putAll( cache.index );
cache.blocks.close();
cache.index.clear();
}
public void addBlock(Block block, BigInteger cummDifficulty, boolean mainChain){
if (cache == null)
addInternalBlock(block, cummDifficulty, mainChain);
else
cache.addBlock(block, cummDifficulty, mainChain);
}
private void addInternalBlock(Block block, BigInteger cummDifficulty, boolean mainChain){
List<BlockInfo> blockInfos = index.get(block.getNumber());
if (blockInfos == null){
blockInfos = new ArrayList<>();
}
BlockInfo blockInfo = new BlockInfo();
blockInfo.setCummDifficulty(cummDifficulty);
blockInfo.setHash(block.getHash());
blockInfo.setMainChain(mainChain); // FIXME:maybe here I should force reset main chain for all uncles on that level
blockInfos.add(blockInfo);
index.put(block.getNumber(), blockInfos);
blocks.put(block.getHash(), block.getEncoded());
}
public List<Block> getBlocksByNumber(long number){
List<Block> result = new ArrayList<>();
if (cache != null)
result = cache.getBlocksByNumber(number);
List<BlockInfo> blockInfos = index.get(number);
if (blockInfos == null){
return result;
}
for (BlockInfo blockInfo : blockInfos){
byte[] hash = blockInfo.getHash();
byte[] blockRlp = blocks.get(hash);
result.add(new Block(blockRlp));
}
return result;
}
public Block getChainBlockByNumber(long number){
if (cache != null) {
Block block = cache.getChainBlockByNumber(number);
if (block != null) return block;
}
List<BlockInfo> blockInfos = index.get(number);
if (blockInfos == null){
return null;
}
for (BlockInfo blockInfo : blockInfos){
if (blockInfo.isMainChain()){
byte[] hash = blockInfo.getHash();
byte[] blockRlp = blocks.get(hash);
return new Block(blockRlp);
}
}
return null;
}
public Block getBlockByHash(byte[] hash) {
if (cache != null) {
Block cachedBlock = cache.getBlockByHash(hash);
if (cachedBlock != null) return cachedBlock;
}
byte[] blockRlp = blocks.get(hash);
if (blockRlp == null)
return null;
return new Block(blockRlp);
}
public BigInteger getTotalDifficulty(){
BigInteger cacheTotalDifficulty = BigInteger.ZERO;
long maxNumber = getMaxNumber();
if (cache != null) {
List<BlockInfo> infos = cache.index.get(maxNumber);
if (infos != null){
for (BlockInfo blockInfo : infos){
if (blockInfo.isMainChain()){
return blockInfo.getCummDifficulty();
}
}
}
}
List<BlockInfo> blockInfos = index.get(maxNumber);
for (BlockInfo blockInfo : blockInfos){
if (blockInfo.isMainChain()){
return blockInfo.getCummDifficulty();
}
}
return cacheTotalDifficulty;
}
public long getMaxNumber(){
Long bestIndex = 0L;
if (index.size() > 0){
bestIndex = (long) index.size();
}
if (cache != null){
return bestIndex + cache.index.size() - 1L;
} else
return bestIndex - 1L;
}
public List<byte[]> getNHashesEndWith(byte[] hash, long number){
List<byte[]> cachedHashes = new ArrayList<>();
if (cache != null)
cachedHashes = cache.getNHashesEndWith(hash, number);
byte[] rlp = blocks.get(hash);
if (rlp == null) return cachedHashes;
for (int i = 0; i < number; ++i){
Block block = new Block(rlp);
cachedHashes.add(block.getHash());
rlp = blocks.get(block.getParentHash());
if (rlp == null) break;
}
return cachedHashes;
}
public List<byte[]> getNHashesStartWith(long number, long maxBlocks){
List<byte[]> result = new ArrayList<>();
int i;
for ( i = 0; i < maxBlocks; ++i){
List<BlockInfo> blockInfos = index.get(number);
if (blockInfos == null) break;
for (BlockInfo blockInfo : blockInfos)
if (blockInfo.isMainChain()){
result.add(blockInfo.getHash());
break;
}
++number;
}
maxBlocks -= i;
if (cache != null)
result.addAll( cache.getNHashesStartWith(number, maxBlocks) );
return result;
}
public static class BlockInfo implements Serializable {
byte[] hash;
BigInteger cummDifficulty;
boolean mainChain;
public byte[] getHash() {
return hash;
}
public void setHash(byte[] hash) {
this.hash = hash;
}
public BigInteger getCummDifficulty() {
return cummDifficulty;
}
public void setCummDifficulty(BigInteger cummDifficulty) {
this.cummDifficulty = cummDifficulty;
}
public boolean isMainChain() {
return mainChain;
}
public void setMainChain(boolean mainChain) {
this.mainChain = mainChain;
}
}
public static final Serializer<List<BlockInfo>> BLOCK_INFO_SERIALIZER = new Serializer<List<BlockInfo>>(){
@Override
public void serialize(DataOutput out, List<BlockInfo> value) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(value);
byte[] data = bos.toByteArray();
DataIO.packInt(out, data.length);
out.write(data);
}
@Override
public List<BlockInfo> deserialize(DataInput in, int available) throws IOException {
List<BlockInfo> value = null;
try {
int size = DataIO.unpackInt(in);
byte[] data = new byte[size];
in.readFully(data);
ByteArrayInputStream bis = new ByteArrayInputStream(data, 0, data.length);
ObjectInputStream ois = new ObjectInputStream(bis);
value = (List<BlockInfo>)ois.readObject();
} catch (ClassNotFoundException e) {e.printStackTrace();}
return value;
}
};
}

View File

@ -0,0 +1,28 @@
package org.ethereum.util;
import java.io.File;
public class FileUtil {
public static boolean recursiveDelete(String fileName) {
File file = new File(fileName);
if (file.exists()) {
//check if the file is a directory
if (file.isDirectory()) {
if ((file.list()).length > 0) {
for(String s:file.list()){
//call deletion of file individually
recursiveDelete(fileName + System.getProperty("file.separator") + s);
}
}
}
file.setWritable(true);
boolean result = file.delete();
return result;
} else {
return false;
}
}
}

View File

@ -0,0 +1,141 @@
package org.ethereum.db;
import org.ethereum.config.SystemProperties;
import org.ethereum.util.FileUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
/**
* @author Mikhail Kalinin
* @since 07.07.2015
*/
public class HashStoreTest {
private static final Logger logger = LoggerFactory.getLogger("test");
private List<byte[]> hashes = new ArrayList<>();
private HashStore hashStore;
private String testDb;
@Before
public void setup() throws InstantiationException, IllegalAccessException {
Random rnd = new Random(System.currentTimeMillis());
for(int i = 0; i < 50; i++) {
byte[] hash = new byte[32];
rnd.nextBytes(hash);
hashes.add(hash);
}
BigInteger bi = new BigInteger(32, new Random());
testDb = "test_db_" + bi;
SystemProperties.CONFIG.setDataBaseDir(testDb);
hashStore = new HashStore.Builder().build();
}
@After
public void cleanup() {
hashStore.close();
FileUtil.recursiveDelete(testDb);
}
@Test // FIFO, add first
public void test1() throws InstantiationException, IllegalAccessException {
for(byte[] hash : hashes) {
hashStore.add(hash);
}
// testing peek and poll
assertArrayEquals(hashes.get(0), hashStore.peek());
for(byte[] hash : hashes) {
assertArrayEquals(hash, hashStore.poll());
}
assertEquals(true, hashStore.isEmpty());
assertNull(hashStore.peek());
assertNull(hashStore.poll());
// testing addFirst
for(int i = 0; i < 10; i++) {
hashStore.add(hashes.get(i));
}
for(int i = 10; i < 20; i++) {
hashStore.addFirst(hashes.get(i));
}
for(int i = 19; i >= 10; i--) {
assertArrayEquals(hashes.get(i), hashStore.poll());
}
}
@Test // concurrency
public void test2() throws InstantiationException, IllegalAccessException, InterruptedException {
new Thread(new Writer(1)).start();
new Thread(new Writer(2)).start();
new Thread(new Writer(3)).start();
new Thread(new Reader(1)).start();
Thread r2 = new Thread(new Reader(2));
r2.start();
r2.join();
}
private class Reader implements Runnable {
private int index;
public Reader(int index) {
this.index = index;
}
@Override
public void run() {
try {
int nullsCount = 0;
while (nullsCount < 5) {
byte[] hash = hashStore.poll();
logger.info("reader {}: {}", index, hash == null ? null : Hex.toHexString(hash));
if(hash == null) {
nullsCount++;
} else {
nullsCount = 0;
}
Thread.sleep(50);
}
} catch (InterruptedException e) {
logger.error(e.getMessage());
}
}
}
private class Writer implements Runnable {
private int index;
public Writer(int index) {
this.index = index;
}
@Override
public void run() {
try {
for(byte[] hash : hashes) {
hashStore.add(hash);
logger.info("writer {}: {}", index, Hex.toHexString(hash));
Thread.sleep(50);
}
} catch (InterruptedException e) {
logger.error(e.getMessage());
}
}
}
}

View File

@ -0,0 +1,709 @@
package org.ethereum.db;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.Block;
import org.ethereum.core.Genesis;
import org.ethereum.datasource.HashMapDB;
import org.ethereum.datasource.KeyValueDataSource;
import org.ethereum.datasource.LevelDbDataSource;
import org.ethereum.util.FileUtil;
import org.junit.Before;
import org.junit.Test;
import org.mapdb.DB;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import static java.math.BigInteger.ZERO;
import static org.ethereum.TestUtils.createIndexMap;
import static org.ethereum.TestUtils.createMapDB;
import static org.junit.Assert.assertEquals;
public class IndexedBlockStoreTest {
private static final Logger logger = LoggerFactory.getLogger("test");
private List<Block> blocks = new ArrayList<>();
private BigInteger cumDifficulty = ZERO;
@Before
public void setup() throws URISyntaxException, IOException {
URL scenario1 = ClassLoader
.getSystemResource("blockstore/load.dmp");
File file = new File(scenario1.toURI());
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
Block genesis = Genesis.getInstance();
blocks.add(genesis);
cumDifficulty = cumDifficulty.add(genesis.getCumulativeDifficulty());
for (String blockRLP : strData) {
Block block = new Block(
Hex.decode(blockRLP));
if (block.getNumber() % 1000 == 0)
logger.info("adding block.hash: [{}] block.number: [{}]",
block.getShortHash(),
block.getNumber());
blocks.add(block);
cumDifficulty = cumDifficulty.add(block.getCumulativeDifficulty());
}
logger.info("total difficulty: {}", cumDifficulty);
logger.info("total blocks loaded: {}", blocks.size());
}
@Test // no cache, save some load, and check it exist
public void test1(){
IndexedBlockStore indexedBlockStore = new IndexedBlockStore();
indexedBlockStore.init(new HashMap<Long, List<IndexedBlockStore.BlockInfo>>(), new HashMapDB(), null);
BigInteger cummDiff = BigInteger.ZERO;
for (Block block : blocks){
cummDiff = cummDiff.add( block.getCumulativeDifficulty() );
indexedBlockStore.addBlock(block, cummDiff, true);
}
// testing: getTotalDifficulty()
// testing: getMaxNumber()
long bestIndex = blocks.get(blocks.size() - 1).getNumber();
assertEquals(bestIndex, indexedBlockStore.getMaxNumber());
assertEquals(cumDifficulty, indexedBlockStore.getTotalDifficulty());
// testing: getBlockByHash(byte[])
Block block = blocks.get(50);
Block block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block_ = indexedBlockStore.getBlockByHash(Hex.decode("00112233"));
assertEquals(null, block_);
// testing: getChainBlockByNumber(long)
block = blocks.get(50);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block_ = indexedBlockStore.getChainBlockByNumber(10000);
assertEquals(null, block_);
// testing: getBlocksByNumber(long)
block = blocks.get(50);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
int blocksNum = indexedBlockStore.getBlocksByNumber(10000).size();
assertEquals(0, blocksNum);
// testing: getNHashesEndWith(byte[], long)
block = blocks.get(8003);
List<byte[]> hashList = indexedBlockStore.getNHashesEndWith(block.getHash(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(8003 - i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
// testing: getNHashesStartWith(long, long)
block = blocks.get(7003);
hashList = indexedBlockStore.getNHashesStartWith(block.getNumber(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(7003 + i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
}
@Test // predefined cache, save some load, and check it exist
public void test2(){
IndexedBlockStore cache = new IndexedBlockStore();
cache.init(new HashMap<Long, List<IndexedBlockStore.BlockInfo>>(), new HashMapDB(), null);
IndexedBlockStore indexedBlockStore = new IndexedBlockStore();
indexedBlockStore.init(new HashMap<Long, List<IndexedBlockStore.BlockInfo>>(), new HashMapDB(), cache);
BigInteger cummDiff = BigInteger.ZERO;
for (Block block : blocks){
cummDiff = cummDiff.add( block.getCumulativeDifficulty() );
indexedBlockStore.addBlock(block, cummDiff, true);
}
// testing: getTotalDifficulty()
// testing: getMaxNumber()
long bestIndex = blocks.get(blocks.size() - 1).getNumber();
assertEquals(bestIndex, indexedBlockStore.getMaxNumber());
assertEquals(cumDifficulty, indexedBlockStore.getTotalDifficulty());
// testing: getBlockByHash(byte[])
Block block = blocks.get(50);
Block block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block_ = indexedBlockStore.getBlockByHash(Hex.decode("00112233"));
assertEquals(null, block_);
// testing: getChainBlockByNumber(long)
block = blocks.get(50);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block_ = indexedBlockStore.getChainBlockByNumber(10000);
assertEquals(null, block_);
// testing: getBlocksByNumber(long)
block = blocks.get(50);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
int blocksNum = indexedBlockStore.getBlocksByNumber(10000).size();
assertEquals(0, blocksNum);
// testing: getNHashesEndWith(byte[], long)
block = blocks.get(8003);
List<byte[]> hashList = indexedBlockStore.getNHashesEndWith(block.getHash(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(8003 - i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
// testing: getNHashesStartWith(long, long)
block = blocks.get(7003);
hashList = indexedBlockStore.getNHashesStartWith(block.getNumber(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(7003 + i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
}
@Test // predefined cache loaded and flushed, check it exist
public void test3(){
IndexedBlockStore cache = new IndexedBlockStore();
cache.init(new HashMap<Long, List<IndexedBlockStore.BlockInfo>>(), new HashMapDB(), null);
IndexedBlockStore indexedBlockStore = new IndexedBlockStore();
indexedBlockStore.init(new HashMap<Long, List<IndexedBlockStore.BlockInfo>>(), new HashMapDB(), cache);
BigInteger cummDiff = BigInteger.ZERO;
for (Block block : blocks){
cummDiff = cummDiff.add( block.getCumulativeDifficulty() );
indexedBlockStore.addBlock(block, cummDiff, true);
}
indexedBlockStore.flush();
// testing: getTotalDifficulty()
// testing: getMaxNumber()
long bestIndex = blocks.get(blocks.size() - 1).getNumber();
assertEquals(bestIndex, indexedBlockStore.getMaxNumber());
assertEquals(cumDifficulty, indexedBlockStore.getTotalDifficulty());
// testing: getBlockByHash(byte[])
Block block = blocks.get(50);
Block block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block_ = indexedBlockStore.getBlockByHash(Hex.decode("00112233"));
assertEquals(null, block_);
// testing: getChainBlockByNumber(long)
block = blocks.get(50);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block_ = indexedBlockStore.getChainBlockByNumber(10000);
assertEquals(null, block_);
// testing: getBlocksByNumber(long)
block = blocks.get(50);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
int blocksNum = indexedBlockStore.getBlocksByNumber(10000).size();
assertEquals(0, blocksNum);
// testing: getNHashesEndWith(byte[], long)
block = blocks.get(8003);
List<byte[]> hashList = indexedBlockStore.getNHashesEndWith(block.getHash(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(8003 - i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
// testing: getNHashesStartWith(long, long)
block = blocks.get(7003);
hashList = indexedBlockStore.getNHashesStartWith(block.getNumber(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(7003 + i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
}
@Test // cache + leveldb + mapdb, save some load, flush to disk, and check it exist
public void test4() throws IOException {
BigInteger bi = new BigInteger(32, new Random());
String testDir = "test_db_" + bi;
SystemProperties.CONFIG.setDataBaseDir(testDir);
DB db = createMapDB(testDir);
Map<Long, List<IndexedBlockStore.BlockInfo>> indexDB = createIndexMap(db);
KeyValueDataSource blocksDB = new LevelDbDataSource("blocks");
blocksDB.init();
IndexedBlockStore indexedBlockStore = new IndexedBlockStore();
indexedBlockStore.init(indexDB, blocksDB, null);
BigInteger cummDiff = BigInteger.ZERO;
for (Block block : blocks){
cummDiff = cummDiff.add( block.getCumulativeDifficulty() );
indexedBlockStore.addBlock(block, cummDiff, true);
}
// testing: getTotalDifficulty()
// testing: getMaxNumber()
long bestIndex = blocks.get(blocks.size() - 1).getNumber();
assertEquals(bestIndex, indexedBlockStore.getMaxNumber());
assertEquals(cumDifficulty, indexedBlockStore.getTotalDifficulty());
// testing: getBlockByHash(byte[])
Block block = blocks.get(50);
Block block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block_ = indexedBlockStore.getBlockByHash(Hex.decode("00112233"));
assertEquals(null, block_);
// testing: getChainBlockByNumber(long)
block = blocks.get(50);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block_ = indexedBlockStore.getChainBlockByNumber(10000);
assertEquals(null, block_);
// testing: getBlocksByNumber(long)
block = blocks.get(50);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
int blocksNum = indexedBlockStore.getBlocksByNumber(10000).size();
assertEquals(0, blocksNum);
// testing: getNHashesEndWith(byte[], long)
block = blocks.get(8003);
List<byte[]> hashList = indexedBlockStore.getNHashesEndWith(block.getHash(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(8003 - i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
// testing: getNHashesStartWith(long, long)
block = blocks.get(7003);
hashList = indexedBlockStore.getNHashesStartWith(block.getNumber(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(7003 + i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
blocksDB.close();
db.close();
// testing after: REOPEN
db = createMapDB(testDir);
indexDB = createIndexMap(db);
blocksDB = new LevelDbDataSource("blocks");
blocksDB.init();
indexedBlockStore = new IndexedBlockStore();
indexedBlockStore.init(indexDB, blocksDB, null);
// testing: getNHashesStartWith(long, long)
block = blocks.get(7003);
hashList = indexedBlockStore.getNHashesStartWith(block.getNumber(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(7003 + i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
FileUtil.recursiveDelete(testDir);
}
@Test // cache + leveldb + mapdb, save part to disk part to cache, and check it exist
public void test5() throws IOException {
BigInteger bi = new BigInteger(32, new Random());
String testDir = "test_db_" + bi;
SystemProperties.CONFIG.setDataBaseDir(testDir);
DB db = createMapDB(testDir);
Map<Long, List<IndexedBlockStore.BlockInfo>> indexDB = createIndexMap(db);
KeyValueDataSource blocksDB = new LevelDbDataSource("blocks");
blocksDB.init();
try {
IndexedBlockStore cache = new IndexedBlockStore();
cache.init(new HashMap<Long, List<IndexedBlockStore.BlockInfo>>(), new HashMapDB(), null);
IndexedBlockStore indexedBlockStore = new IndexedBlockStore();
indexedBlockStore.init(indexDB, blocksDB, cache);
BigInteger cummDiff = BigInteger.ZERO;
int preloadSize = blocks.size() / 2;
for (int i = 0; i < preloadSize; ++i){
Block block = blocks.get(i);
cummDiff = cummDiff.add( block.getCumulativeDifficulty() );
indexedBlockStore.addBlock(block, cummDiff, true);
}
indexedBlockStore.flush();
for (int i = preloadSize; i < blocks.size(); ++i){
Block block = blocks.get(i);
cummDiff = cummDiff.add( block.getCumulativeDifficulty() );
indexedBlockStore.addBlock(block, cummDiff, true);
}
// testing: getTotalDifficulty()
// testing: getMaxNumber()
long bestIndex = blocks.get(blocks.size() - 1).getNumber();
assertEquals(bestIndex, indexedBlockStore.getMaxNumber());
assertEquals(cumDifficulty, indexedBlockStore.getTotalDifficulty());
// testing: getBlockByHash(byte[])
Block block = blocks.get(50);
Block block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getBlockByHash(block.getHash());
assertEquals(block.getNumber(), block_.getNumber());
block_ = indexedBlockStore.getBlockByHash(Hex.decode("00112233"));
assertEquals(null, block_);
// testing: getChainBlockByNumber(long)
block = blocks.get(50);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getChainBlockByNumber(block.getNumber());
assertEquals(block.getNumber(), block_.getNumber());
block_ = indexedBlockStore.getChainBlockByNumber(10000);
assertEquals(null, block_);
// testing: getBlocksByNumber(long)
block = blocks.get(50);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(150);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(0);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
block = blocks.get(8003);
block_ = indexedBlockStore.getBlocksByNumber(block.getNumber()).get(0);
assertEquals(block.getNumber(), block_.getNumber());
int blocksNum = indexedBlockStore.getBlocksByNumber(10000).size();
assertEquals(0, blocksNum);
// testing: getNHashesEndWith(byte[], long)
block = blocks.get(8003);
List<byte[]> hashList = indexedBlockStore.getNHashesEndWith(block.getHash(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(8003 - i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
// testing: getNHashesStartWith(long, long)
block = blocks.get(7003);
hashList = indexedBlockStore.getNHashesStartWith(block.getNumber(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(7003 + i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
indexedBlockStore.flush();
blocksDB.close();
db.close();
// testing after: REOPEN
db = createMapDB(testDir);
indexDB = createIndexMap(db);
blocksDB = new LevelDbDataSource("blocks");
blocksDB.init();
indexedBlockStore = new IndexedBlockStore();
indexedBlockStore.init(indexDB, blocksDB, null);
// testing: getNHashesStartWith(long, long)
block = blocks.get(7003);
hashList = indexedBlockStore.getNHashesStartWith(block.getNumber(), 100);
for (int i = 0; i < 100; ++i){
block = blocks.get(7003 + i);
String hash = Hex.toHexString(hashList.get(i));
String hash_ = Hex.toHexString( block.getHash() );
assertEquals(hash_, hash);
}
} finally {
blocksDB.close();
db.close();
FileUtil.recursiveDelete(testDir);
}
}
}