Introduce usage of key/val data source as abstraction
Implement Redis key/val datasource Implement LevelDb key/val datasource
This commit is contained in:
parent
5ead5a5da0
commit
38cf19015b
|
@ -75,6 +75,8 @@ dependencies {
|
|||
compile "org.hibernate:hibernate-core:${hibernateVersion}"
|
||||
compile "org.hibernate:hibernate-entitymanager:${hibernateVersion}"
|
||||
compile "commons-dbcp:commons-dbcp:1.4"
|
||||
compile "redis.clients:jedis:2.6.0"
|
||||
|
||||
compile("com.googlecode.json-simple:json-simple:1.1.1") {
|
||||
exclude group:'junit', module:'junit'
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package org.ethereum.datasource;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 18/01/2015 21:40
|
||||
*/
|
||||
|
||||
public interface KeyValueDataSource {
|
||||
|
||||
public void init();
|
||||
public void setName(String name);
|
||||
|
||||
public byte[] get(byte[] key);
|
||||
public void put(byte[] key, byte[] value);
|
||||
public void delete(byte[] key);
|
||||
public Set<byte[]> keys();
|
||||
public void setBatch( Map<byte[], byte[]> rows);
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package org.ethereum.datasource;
|
||||
|
||||
import org.ethereum.db.Database;
|
||||
import org.ethereum.db.DatabaseImpl;
|
||||
import org.iq80.leveldb.DB;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 18/01/2015 21:48
|
||||
*/
|
||||
|
||||
public class LevelDbDataSource implements KeyValueDataSource{
|
||||
|
||||
String name;
|
||||
Database db;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
if (name == null) throw new NullPointerException("no name set to the db");
|
||||
db = new DatabaseImpl(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] get(byte[] key) {
|
||||
return db.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte[] key, byte[] value) {
|
||||
db.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(byte[] key) {
|
||||
db.delete(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<byte[]> keys() {
|
||||
|
||||
// todo: re-modelling DataBase for that
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatch(Map<byte[], byte[]> rows) {
|
||||
// todo: re-modelling DataBase for that
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package org.ethereum.datasource;
|
||||
|
||||
import org.ethereum.db.Database;
|
||||
import org.ethereum.db.DatabaseImpl;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.Pipeline;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 18/01/2015 21:48
|
||||
*/
|
||||
|
||||
public class RedisDataSource implements KeyValueDataSource{
|
||||
|
||||
String name;
|
||||
int index;
|
||||
|
||||
Jedis jedis;
|
||||
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
if (name == null) throw new NullPointerException("no name set to the db");
|
||||
this.jedis = new Jedis("localhost"); // todo: config.redisHost, config.redisPort
|
||||
this.jedis.flushAll(); // todo: if config.reset so reset.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
index = nameToIndex(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] get(byte[] key) {
|
||||
jedis.select(index);
|
||||
return jedis.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte[] key, byte[] value) {
|
||||
jedis.select(index);
|
||||
jedis.set(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(byte[] key) {
|
||||
jedis.select(index);
|
||||
jedis.del(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<byte[]> keys() {
|
||||
return jedis.keys("*".getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatch(Map<byte[], byte[]> rows) {
|
||||
jedis.select(index);
|
||||
Pipeline pipeline = jedis.pipelined();
|
||||
|
||||
Iterator<Map.Entry<byte[], byte[]>> iterator = rows.entrySet().iterator();
|
||||
while(iterator.hasNext()){
|
||||
|
||||
Map.Entry<byte[], byte[]> row = iterator.next();
|
||||
byte[] key = row.getKey();
|
||||
byte[] val = row.getValue();
|
||||
pipeline.set(key, val);
|
||||
}
|
||||
pipeline.sync();
|
||||
}
|
||||
|
||||
|
||||
private static Integer nameToIndex(String name) {
|
||||
Integer index = DBNameScheme.get(name);
|
||||
if (index == null) {
|
||||
index = indexCounter.getAndIncrement();
|
||||
DBNameScheme.put(name, index);
|
||||
indexCounter.intValue();
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
private static Map<String, Integer> DBNameScheme = new HashMap<>();
|
||||
private static AtomicInteger indexCounter = new AtomicInteger(1);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package test.ethereum.datasource;
|
||||
|
||||
import org.ethereum.datasource.RedisDataSource;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||
|
||||
/**
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 18/01/2015 22:40
|
||||
*/
|
||||
|
||||
public class RedisDataSourceTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void testSet1(){
|
||||
|
||||
try {
|
||||
RedisDataSource redis = new RedisDataSource();
|
||||
redis.setName("state");
|
||||
redis.init();
|
||||
|
||||
byte[] key = Hex.decode("a1a2a3");
|
||||
byte[] val = Hex.decode("b1b2b3");
|
||||
|
||||
redis.put(key, val);
|
||||
byte[] val2 = redis.get(key);
|
||||
|
||||
Assert.assertEquals(Hex.toHexString(val), Hex.toHexString(val2));
|
||||
} catch (JedisConnectionException e) {
|
||||
// no redis server consider test as pass
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSet2(){
|
||||
|
||||
try {
|
||||
RedisDataSource redis1 = new RedisDataSource();
|
||||
redis1.setName("state");
|
||||
redis1.init();
|
||||
|
||||
RedisDataSource redis2 = new RedisDataSource();
|
||||
redis2.setName("details");
|
||||
redis2.init();
|
||||
|
||||
|
||||
byte[] key = Hex.decode("a1a2a3");
|
||||
byte[] val1 = Hex.decode("b1b2b3");
|
||||
byte[] val2 = Hex.decode("c1c2c3");
|
||||
|
||||
redis1.put(key, val1);
|
||||
redis2.put(key, val2);
|
||||
|
||||
byte[] res1 = redis1.get(key);
|
||||
byte[] res2 = redis2.get(key);
|
||||
|
||||
Assert.assertEquals(Hex.toHexString(val1), Hex.toHexString(res1));
|
||||
Assert.assertEquals(Hex.toHexString(val2), Hex.toHexString(res2));
|
||||
} catch (JedisConnectionException e) {
|
||||
// no redis server consider test as pass
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package test.ethereum.trie;
|
||||
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.Pipeline;
|
||||
import test.ethereum.db.MockDB;
|
||||
|
||||
import org.ethereum.core.AccountState;
|
||||
|
@ -32,13 +34,7 @@ import java.net.URL;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
|
||||
import static org.ethereum.crypto.HashUtil.EMPTY_TRIE_HASH;
|
||||
import static org.junit.Assert.*;
|
||||
|
@ -590,6 +586,45 @@ public class TrieTest {
|
|||
}
|
||||
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void reddisTest() throws URISyntaxException, IOException {
|
||||
|
||||
URL massiveUpload_1 = ClassLoader
|
||||
.getSystemResource("trie/massive-upload.dmp");
|
||||
|
||||
File file = new File(massiveUpload_1.toURI());
|
||||
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
|
||||
String dbName = "state";
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
Jedis jedis = new Jedis("localhost");
|
||||
jedis.flushAll();
|
||||
Pipeline pipeline = jedis.pipelined();
|
||||
Set<String> keys = jedis.keys("*");
|
||||
System.out.println("before: all " + keys.size());
|
||||
|
||||
for (String aStrData : strData) {
|
||||
String[] keyVal = aStrData.split("=");
|
||||
|
||||
if (keyVal[0].equals("*"))
|
||||
pipeline.del(keyVal[1].getBytes());
|
||||
else
|
||||
pipeline.set(keyVal[0].getBytes(), keyVal[1].getBytes());
|
||||
}
|
||||
|
||||
pipeline.sync();
|
||||
keys = jedis.keys("*");
|
||||
System.out.println("all " + keys.size());
|
||||
for (String key : keys)
|
||||
System.out.println(key + " -> " + jedis.get(key));
|
||||
|
||||
|
||||
System.out.println("time: " + (System.currentTimeMillis() - startTime));
|
||||
}
|
||||
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testMasiveDetermenisticUpdate() throws IOException, URISyntaxException {
|
||||
|
|
Loading…
Reference in New Issue