Moved databases to sdcard.
Added InMemoryBlockStore android implementation.
This commit is contained in:
parent
232b25eb85
commit
7481fcc816
|
@ -61,7 +61,7 @@ public class LevelDbDataSource implements KeyValueDataSource {
|
||||||
options.logger(logger1);
|
options.logger(logger1);
|
||||||
try {
|
try {
|
||||||
logger.debug("Opening database");
|
logger.debug("Opening database");
|
||||||
File dbLocation = context.getDir(SystemProperties.CONFIG.databaseDir(), 0);
|
File dbLocation = new File(SystemProperties.CONFIG.databaseDir());
|
||||||
File fileLocation = new File(dbLocation, name);
|
File fileLocation = new File(dbLocation, name);
|
||||||
|
|
||||||
if (SystemProperties.CONFIG.databaseReset()) {
|
if (SystemProperties.CONFIG.databaseReset()) {
|
||||||
|
|
|
@ -31,4 +31,6 @@ public interface BlockStoreDatabase {
|
||||||
public void save(TransactionReceiptVO transactionReceiptVO);
|
public void save(TransactionReceiptVO transactionReceiptVO);
|
||||||
|
|
||||||
public TransactionReceipt getTransactionReceiptByHash(byte[] hash);
|
public TransactionReceipt getTransactionReceiptByHash(byte[] hash);
|
||||||
|
|
||||||
|
public boolean flush(List<Block> blocks);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ public class BlockStoreImpl implements BlockStore {
|
||||||
|
|
||||||
public Block getBlockByNumber(long blockNumber) {
|
public Block getBlockByNumber(long blockNumber) {
|
||||||
|
|
||||||
|
|
||||||
List result = database.getByNumber(blockNumber);
|
List result = database.getByNumber(blockNumber);
|
||||||
if (result.size() == 0) return null;
|
if (result.size() == 0) return null;
|
||||||
BlockVO vo = (BlockVO) result.get(0);
|
BlockVO vo = (BlockVO) result.get(0);
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
package org.ethereum.android.db;
|
||||||
|
|
||||||
|
|
||||||
|
import org.ethereum.core.Block;
|
||||||
|
import org.ethereum.core.TransactionReceipt;
|
||||||
|
import org.ethereum.db.BlockStore;
|
||||||
|
import org.ethereum.db.ByteArrayWrapper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static java.math.BigInteger.ZERO;
|
||||||
|
import static org.ethereum.util.ByteUtil.wrap;
|
||||||
|
|
||||||
|
|
||||||
|
public class InMemoryBlockStore implements BlockStore {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger("general");
|
||||||
|
|
||||||
|
Map<ByteArrayWrapper, Block> hashIndex = new HashMap<>();
|
||||||
|
Map<Long, Block> numberIndex = new HashMap<>();
|
||||||
|
List<Block> blocks = new ArrayList<>();
|
||||||
|
|
||||||
|
private BlockStoreDatabase database;
|
||||||
|
|
||||||
|
BigInteger totalDifficulty = ZERO;
|
||||||
|
|
||||||
|
public InMemoryBlockStore(BlockStoreDatabase database) {
|
||||||
|
|
||||||
|
this.database = database;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getBlockHashByNumber(long blockNumber) {
|
||||||
|
|
||||||
|
Block block = numberIndex.get(blockNumber);
|
||||||
|
|
||||||
|
if (block == null)
|
||||||
|
return dbGetBlockHashByNumber(blockNumber);
|
||||||
|
else
|
||||||
|
return block.getHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block getBlockByNumber(long blockNumber) {
|
||||||
|
|
||||||
|
Block block = numberIndex.get(blockNumber);
|
||||||
|
|
||||||
|
if (block == null)
|
||||||
|
return dbGetBlockByNumber(blockNumber);
|
||||||
|
else
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block getBlockByHash(byte[] hash) {
|
||||||
|
|
||||||
|
Block block = hashIndex.get(wrap(hash));
|
||||||
|
|
||||||
|
if (block == null)
|
||||||
|
return dbGetBlockByHash(hash);
|
||||||
|
else
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty) {
|
||||||
|
|
||||||
|
Block startBlock = hashIndex.get(wrap(hash));
|
||||||
|
|
||||||
|
long endIndex = startBlock.getNumber() + qty;
|
||||||
|
endIndex = getBestBlock().getNumber() < endIndex ? getBestBlock().getNumber() : endIndex;
|
||||||
|
|
||||||
|
List<byte[]> hashes = new ArrayList<>();
|
||||||
|
|
||||||
|
for (long i = startBlock.getNumber(); i <= endIndex; ++i){
|
||||||
|
Block block = getBlockByNumber(i);
|
||||||
|
hashes.add(block.getHash() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteBlocksSince(long number) {
|
||||||
|
|
||||||
|
// todo: delete blocks sinse
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveBlock(Block block, List<TransactionReceipt> receipts) {
|
||||||
|
ByteArrayWrapper wHash = wrap(block.getHash());
|
||||||
|
blocks.add(block);
|
||||||
|
hashIndex.put(wHash, block);
|
||||||
|
numberIndex.put(block.getNumber(), block);
|
||||||
|
totalDifficulty = totalDifficulty.add(block.getCumulativeDifficulty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getTotalDifficultySince(long number) {
|
||||||
|
|
||||||
|
// todo calculate from db + from cache
|
||||||
|
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getTotalDifficulty() {
|
||||||
|
return totalDifficulty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block getBestBlock() {
|
||||||
|
if (blocks.size() == 0) return null;
|
||||||
|
return blocks.get(blocks.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Block> getAllBlocks() {
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
blocks.clear();
|
||||||
|
hashIndex.clear();
|
||||||
|
numberIndex.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: wrap from here in to db class
|
||||||
|
|
||||||
|
public byte[] dbGetBlockHashByNumber(long blockNumber) {
|
||||||
|
|
||||||
|
Block block = getBlockByNumber(blockNumber);
|
||||||
|
if (block != null) return block.getHash();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block dbGetBlockByNumber(long blockNumber) {
|
||||||
|
|
||||||
|
List result = database.getByNumber(blockNumber);
|
||||||
|
if (result.size() == 0) return null;
|
||||||
|
BlockVO vo = (BlockVO) result.get(0);
|
||||||
|
|
||||||
|
return new Block(vo.rlp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block dbGetBlockByHash(byte[] hash) {
|
||||||
|
|
||||||
|
List result = database.getByHash(hash);
|
||||||
|
|
||||||
|
if (result.size() == 0) return null;
|
||||||
|
BlockVO vo = (BlockVO) result.get(0);
|
||||||
|
|
||||||
|
return new Block(vo.rlp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush(){
|
||||||
|
|
||||||
|
long t_ = System.nanoTime();
|
||||||
|
|
||||||
|
database.flush(blocks);
|
||||||
|
Block block = getBestBlock();
|
||||||
|
|
||||||
|
blocks.clear();
|
||||||
|
hashIndex.clear();
|
||||||
|
numberIndex.clear();
|
||||||
|
|
||||||
|
saveBlock(block, null);
|
||||||
|
|
||||||
|
long t__ = System.nanoTime();
|
||||||
|
logger.info("Flush block store in: {} ms", ((float) (t__ - t_) / 1_000_000));
|
||||||
|
|
||||||
|
totalDifficulty = (BigInteger) database.getTotalDifficulty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(){
|
||||||
|
|
||||||
|
logger.info("loading db");
|
||||||
|
|
||||||
|
long t = System.nanoTime();
|
||||||
|
|
||||||
|
Block bestBlock = database.getBestBlock();
|
||||||
|
if (bestBlock == null) return;
|
||||||
|
saveBlock(bestBlock, null);
|
||||||
|
|
||||||
|
totalDifficulty = database.getTotalDifficulty();
|
||||||
|
|
||||||
|
long t_ = System.nanoTime();
|
||||||
|
|
||||||
|
logger.info("Loaded db in: {} ms", ((float)(t_ - t) / 1_000_000));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,11 +2,13 @@ package org.ethereum.android.db;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.os.Environment;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
|
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
|
||||||
import com.j256.ormlite.dao.Dao;
|
import com.j256.ormlite.dao.Dao;
|
||||||
import com.j256.ormlite.dao.GenericRawResults;
|
import com.j256.ormlite.dao.GenericRawResults;
|
||||||
|
import com.j256.ormlite.misc.TransactionManager;
|
||||||
import com.j256.ormlite.stmt.DeleteBuilder;
|
import com.j256.ormlite.stmt.DeleteBuilder;
|
||||||
import com.j256.ormlite.support.ConnectionSource;
|
import com.j256.ormlite.support.ConnectionSource;
|
||||||
import com.j256.ormlite.table.TableUtils;
|
import com.j256.ormlite.table.TableUtils;
|
||||||
|
@ -14,10 +16,12 @@ import com.j256.ormlite.table.TableUtils;
|
||||||
import org.ethereum.core.Block;
|
import org.ethereum.core.Block;
|
||||||
import org.ethereum.core.TransactionReceipt;
|
import org.ethereum.core.TransactionReceipt;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
public class OrmLiteBlockStoreDatabase extends OrmLiteSqliteOpenHelper implements BlockStoreDatabase {
|
public class OrmLiteBlockStoreDatabase extends OrmLiteSqliteOpenHelper implements BlockStoreDatabase {
|
||||||
|
|
||||||
|
@ -28,7 +32,8 @@ public class OrmLiteBlockStoreDatabase extends OrmLiteSqliteOpenHelper implement
|
||||||
private Dao<TransactionReceiptVO, Integer> transactionDao = null;
|
private Dao<TransactionReceiptVO, Integer> transactionDao = null;
|
||||||
|
|
||||||
public OrmLiteBlockStoreDatabase(Context context) {
|
public OrmLiteBlockStoreDatabase(Context context) {
|
||||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
super(context, Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||||
|
+ File.separator + DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -252,4 +257,27 @@ public class OrmLiteBlockStoreDatabase extends OrmLiteSqliteOpenHelper implement
|
||||||
return new TransactionReceipt(vo.rlp);
|
return new TransactionReceipt(vo.rlp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean flush(final List<Block> blocks) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
TransactionManager.callInTransaction(getBlockDao().getConnectionSource(),
|
||||||
|
new Callable<Void>() {
|
||||||
|
public Void call() throws Exception {
|
||||||
|
for (Block block : blocks) {
|
||||||
|
BlockVO blockVO = new BlockVO(block.getNumber(), block.getHash(), block.getEncoded(), block.getCumulativeDifficulty());
|
||||||
|
save(blockVO);
|
||||||
|
}
|
||||||
|
// you could pass back an object here
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch(java.sql.SQLException e) {
|
||||||
|
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error querying for hash", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.content.Context;
|
||||||
import com.j256.ormlite.android.apptools.OpenHelperManager;
|
import com.j256.ormlite.android.apptools.OpenHelperManager;
|
||||||
|
|
||||||
import org.ethereum.android.datasource.LevelDbDataSource;
|
import org.ethereum.android.datasource.LevelDbDataSource;
|
||||||
|
import org.ethereum.android.db.InMemoryBlockStore;
|
||||||
import org.ethereum.android.db.OrmLiteBlockStoreDatabase;
|
import org.ethereum.android.db.OrmLiteBlockStoreDatabase;
|
||||||
import org.ethereum.android.db.BlockStoreImpl;
|
import org.ethereum.android.db.BlockStoreImpl;
|
||||||
import org.ethereum.config.SystemProperties;
|
import org.ethereum.config.SystemProperties;
|
||||||
|
@ -76,7 +77,7 @@ public class EthereumModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
BlockStore provideBlockStore() {
|
BlockStore provideBlockStore() {
|
||||||
OrmLiteBlockStoreDatabase database = OpenHelperManager.getHelper(context, OrmLiteBlockStoreDatabase.class);
|
OrmLiteBlockStoreDatabase database = OpenHelperManager.getHelper(context, OrmLiteBlockStoreDatabase.class);
|
||||||
return new BlockStoreImpl(database);
|
return new InMemoryBlockStore(database);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -90,7 +90,7 @@ samples.dir = samples
|
||||||
database.reset = false
|
database.reset = false
|
||||||
|
|
||||||
# place to save physical storage files
|
# place to save physical storage files
|
||||||
database.dir = database
|
database.dir = /mnt/sdcard
|
||||||
|
|
||||||
# this string is computed
|
# this string is computed
|
||||||
# to be eventually the address
|
# to be eventually the address
|
||||||
|
|
Loading…
Reference in New Issue