mirror of
https://github.com/status-im/ethereumj-personal.git
synced 2025-02-17 22:27:13 +00:00
Pending Transaction - save in external datasource
This commit is contained in:
parent
1ee5629fe4
commit
40e1019d5b
@ -9,19 +9,19 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public interface KeyValueDataSource {
|
public interface KeyValueDataSource {
|
||||||
|
|
||||||
public void init();
|
void init();
|
||||||
|
|
||||||
public void setName(String name);
|
void setName(String name);
|
||||||
|
|
||||||
public byte[] get(byte[] key);
|
byte[] get(byte[] key);
|
||||||
|
|
||||||
public void put(byte[] key, byte[] value);
|
byte[] put(byte[] key, byte[] value);
|
||||||
|
|
||||||
public void delete(byte[] key);
|
void delete(byte[] key);
|
||||||
|
|
||||||
public Set<byte[]> keys();
|
Set<byte[]> keys();
|
||||||
|
|
||||||
public void updateBatch(Map<byte[], byte[]> rows);
|
void updateBatch(Map<byte[], byte[]> rows);
|
||||||
|
|
||||||
public void close();
|
void close();
|
||||||
}
|
}
|
||||||
|
@ -88,8 +88,9 @@ public class LevelDbDataSource implements KeyValueDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void put(byte[] key, byte[] value) {
|
public byte[] put(byte[] key, byte[] value) {
|
||||||
db.put(key, value);
|
db.put(key, value);
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
package org.ethereum.datasource;
|
|
||||||
|
|
||||||
import redis.clients.jedis.Jedis;
|
|
||||||
import redis.clients.jedis.Pipeline;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author: Roman Mandeleil
|
|
||||||
* Created on: 18/01/2015 21:48
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class RedisDataSource implements KeyValueDataSource{
|
|
||||||
|
|
||||||
String name;
|
|
||||||
int index;
|
|
||||||
|
|
||||||
Jedis jedis;
|
|
||||||
|
|
||||||
public RedisDataSource() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public RedisDataSource(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init() {
|
|
||||||
|
|
||||||
if (name == null) throw new NullPointerException("no name set to the db");
|
|
||||||
|
|
||||||
this.jedis = RedisPool.getResource(name);
|
|
||||||
if (jedis == null) this.jedis = new Jedis("localhost");
|
|
||||||
|
|
||||||
if (CONFIG.databaseReset())
|
|
||||||
this.jedis.flushAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
index = nameToIndex(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] get(byte[] key) {
|
|
||||||
return jedis.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void put(byte[] key, byte[] value) {
|
|
||||||
jedis.set(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete(byte[] key) {
|
|
||||||
jedis.del(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<byte[]> keys() {
|
|
||||||
return jedis.keys("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateBatch(Map<byte[], byte[]> rows) {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
jedis.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
package org.ethereum.datasource;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import redis.clients.jedis.Jedis;
|
|
||||||
import redis.clients.jedis.JedisPool;
|
|
||||||
import redis.clients.jedis.JedisPoolConfig;
|
|
||||||
import redis.clients.jedis.Protocol;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author: Roman Mandeleil
|
|
||||||
* Created on: 20/01/2015 13:27
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class RedisPool {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger("db");
|
|
||||||
private static JedisPool state;
|
|
||||||
private static JedisPool details;
|
|
||||||
|
|
||||||
static {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (System.getenv("REDIS_STATE") != null) {
|
|
||||||
URI redisUri = new URI(System.getenv("REDIS_STATE"));
|
|
||||||
logger.info("Init redis pool: " + redisUri.toString());
|
|
||||||
state = new JedisPool(new JedisPoolConfig(),
|
|
||||||
redisUri.getHost(),
|
|
||||||
redisUri.getPort(),
|
|
||||||
Protocol.DEFAULT_TIMEOUT,
|
|
||||||
redisUri.getUserInfo().split(":",2)[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (System.getenv("REDIS_DETAILS") != null) {
|
|
||||||
URI redisUri = new URI(System.getenv("REDIS_DETAILS"));
|
|
||||||
logger.info("Init redis pool: " + redisUri.toString());
|
|
||||||
details = new JedisPool(new JedisPoolConfig(),
|
|
||||||
redisUri.getHost(),
|
|
||||||
redisUri.getPort(),
|
|
||||||
Protocol.DEFAULT_TIMEOUT,
|
|
||||||
redisUri.getUserInfo().split(":",2)[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
logger.info("Pool is not available");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Jedis getResource(String name){
|
|
||||||
if (state == null) return null;
|
|
||||||
|
|
||||||
if (name.equals("state")) return state.getResource();
|
|
||||||
if (name.equals("details")) return details.getResource();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,5 +13,5 @@ public interface RedisConnection {
|
|||||||
|
|
||||||
Set<Transaction> createTransactionSet(String name);
|
Set<Transaction> createTransactionSet(String name);
|
||||||
|
|
||||||
KeyValueDataSource createKeyValueDataSource(String name);
|
KeyValueDataSource createDataSource(String name);
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ public class RedisConnectionImpl implements RedisConnection {
|
|||||||
private JedisPool jedisPool;
|
private JedisPool jedisPool;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void tryConnect() {
|
||||||
if (!SystemProperties.CONFIG.isRedisEnabled()) return;
|
if (!SystemProperties.CONFIG.isRedisEnabled()) return;
|
||||||
|
|
||||||
String redisCloudUrl = System.getenv("REDISCLOUD_URL");
|
String redisCloudUrl = System.getenv("REDISCLOUD_URL");
|
||||||
@ -97,8 +97,7 @@ public class RedisConnectionImpl implements RedisConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyValueDataSource createKeyValueDataSource(String name) {
|
public KeyValueDataSource createDataSource(String name) {
|
||||||
return new RedisKeyValueDataSource(name, jedisPool, null);
|
return new RedisDataSource(name, jedisPool);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
package org.ethereum.datasource.redis;
|
||||||
|
|
||||||
|
import org.ethereum.datasource.KeyValueDataSource;
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
|
import static org.ethereum.util.Functional.Consumer;
|
||||||
|
|
||||||
|
public class RedisDataSource extends RedisMap<byte[], byte[]> implements KeyValueDataSource {
|
||||||
|
|
||||||
|
RedisDataSource(String namespace, JedisPool pool) {
|
||||||
|
super(namespace, pool, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte[] serializeKey(byte[] key) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte[] deserializeKey(byte[] bytes) {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte[] serialize(byte[] value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte[] deserialize(byte[] bytes) {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
if (CONFIG.databaseReset()) {
|
||||||
|
pooled(new Consumer<Jedis>() {
|
||||||
|
@Override
|
||||||
|
public void accept(Jedis jedis) {
|
||||||
|
jedis.flushAll();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
super.setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] get(byte[] key) {
|
||||||
|
return super.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(final byte[] key) {
|
||||||
|
remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<byte[]> keys() {
|
||||||
|
return super.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBatch(final Map<byte[], byte[]> rows) {
|
||||||
|
putAll(rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,91 +0,0 @@
|
|||||||
package org.ethereum.datasource.redis;
|
|
||||||
|
|
||||||
import org.ethereum.datasource.KeyValueDataSource;
|
|
||||||
import redis.clients.jedis.Jedis;
|
|
||||||
import redis.clients.jedis.JedisPool;
|
|
||||||
import redis.clients.jedis.Pipeline;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
|
||||||
import static org.ethereum.util.Functional.*;
|
|
||||||
|
|
||||||
public class RedisKeyValueDataSource extends RedisStorage<byte[]> implements KeyValueDataSource {
|
|
||||||
|
|
||||||
RedisKeyValueDataSource(String namespace, JedisPool pool, RedisSerializer<byte[]> serializer) {
|
|
||||||
super(namespace, pool, serializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init() {
|
|
||||||
if (CONFIG.databaseReset()) {
|
|
||||||
pooled(new Consumer<Jedis>() {
|
|
||||||
@Override
|
|
||||||
public void accept(Jedis jedis) {
|
|
||||||
jedis.flushAll();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
|
||||||
setNamespace(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] get(final byte[] key) {
|
|
||||||
return pooledWithResult(new Function<Jedis, byte[]>() {
|
|
||||||
@Override
|
|
||||||
public byte[] apply(Jedis jedis) {
|
|
||||||
return jedis.get(getNamespace());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void put(final byte[] key, final byte[] value) {
|
|
||||||
pooled(new Consumer<Jedis>() {
|
|
||||||
@Override
|
|
||||||
public void accept(Jedis jedis) {
|
|
||||||
jedis.set(formatKey(key), value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete(final byte[] key) {
|
|
||||||
pooled(new Consumer<Jedis>() {
|
|
||||||
@Override
|
|
||||||
public void accept(Jedis jedis) {
|
|
||||||
jedis.del(formatKey(key));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<byte[]> keys() {
|
|
||||||
return pooledWithResult(new Function<Jedis, Set<byte[]>>() {
|
|
||||||
@Override
|
|
||||||
public Set<byte[]> apply(Jedis jedis) {
|
|
||||||
return jedis.keys(formatKey("*".getBytes()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateBatch(final Map<byte[], byte[]> rows) {
|
|
||||||
doInPipeline(rows.entrySet(), new BiConsumer<Map.Entry<byte[], byte[]>, Pipeline>() {
|
|
||||||
@Override
|
|
||||||
public void accept(Map.Entry<byte[], byte[]> entry, Pipeline pipeline) {
|
|
||||||
pipeline.set(formatKey(entry.getKey()), entry.getValue());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,10 +5,7 @@ import org.apache.commons.collections4.keyvalue.AbstractMapEntry;
|
|||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.JedisPool;
|
import redis.clients.jedis.JedisPool;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.apache.commons.collections4.CollectionUtils.collect;
|
import static org.apache.commons.collections4.CollectionUtils.collect;
|
||||||
import static org.ethereum.util.Functional.Consumer;
|
import static org.ethereum.util.Functional.Consumer;
|
||||||
@ -18,17 +15,25 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
|
|||||||
|
|
||||||
private final RedisSerializer<K> keySerializer;
|
private final RedisSerializer<K> keySerializer;
|
||||||
|
|
||||||
RedisMap(String namespace, JedisPool pool, RedisSerializer<K> keySerializer, RedisSerializer<V> valueSerializer) {
|
public RedisMap(String namespace, JedisPool pool, RedisSerializer<K> keySerializer, RedisSerializer<V> valueSerializer) {
|
||||||
super(namespace, pool, valueSerializer);
|
super(namespace, pool, valueSerializer);
|
||||||
this.keySerializer = keySerializer;
|
this.keySerializer = keySerializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected byte[] serializeKey(K key) {
|
||||||
|
return keySerializer.serialize(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected K deserializeKey(byte[] input) {
|
||||||
|
return keySerializer.deserialize(input);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return pooledWithResult(new Function<Jedis, Integer>() {
|
return pooledWithResult(new Function<Jedis, Integer>() {
|
||||||
@Override
|
@Override
|
||||||
public Integer apply(Jedis jedis) {
|
public Integer apply(Jedis jedis) {
|
||||||
return jedis.hlen(getNamespace()).intValue();
|
return jedis.hlen(getName()).intValue();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -43,14 +48,14 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
|
|||||||
return pooledWithResult(new Function<Jedis, Boolean>() {
|
return pooledWithResult(new Function<Jedis, Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean apply(Jedis jedis) {
|
public Boolean apply(Jedis jedis) {
|
||||||
return jedis.hexists(getNamespace(), keySerializer.serialize((K) key));
|
return jedis.hexists(getName(), serializeKey((K) key));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsValue(Object value) {
|
public boolean containsValue(Object value) {
|
||||||
return false;
|
return values().contains(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -58,33 +63,50 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
|
|||||||
return pooledWithResult(new Function<Jedis, V>() {
|
return pooledWithResult(new Function<Jedis, V>() {
|
||||||
@Override
|
@Override
|
||||||
public V apply(Jedis jedis) {
|
public V apply(Jedis jedis) {
|
||||||
byte[] value = jedis.hget(getNamespace(), keySerializer.serialize((K) key));
|
byte[] value = jedis.hget(getName(), serializeKey((K) key));
|
||||||
return deserialize(value);
|
return deserialize(value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V put(K key, V value) {
|
public V put(final K key, final V value) {
|
||||||
/*
|
|
||||||
return pooledWithResult(new Function<Jedis, V>() {
|
return pooledWithResult(new Function<Jedis, V>() {
|
||||||
@Override
|
@Override
|
||||||
public V apply(Jedis jedis) {
|
public V apply(Jedis jedis) {
|
||||||
return jedis.hset(getNamespace(), keySerializer.serialize(key), serialize(value));
|
byte[] serializedKey = serializeKey(key);
|
||||||
|
byte[] oldValue = jedis.hget(getName(), serializedKey);
|
||||||
|
jedis.hset(getName(), serializedKey, serialize(value));
|
||||||
|
return deserialize(oldValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V remove(Object key) {
|
public V remove(final Object key) {
|
||||||
return null;
|
return pooledWithResult(new Function<Jedis, V>() {
|
||||||
|
@Override
|
||||||
|
public V apply(Jedis jedis) {
|
||||||
|
byte[] serializedKey = serializeKey((K) key);
|
||||||
|
byte[] oldValue = jedis.hget(getName(), serializedKey);
|
||||||
|
jedis.hdel(getName(), serializedKey);
|
||||||
|
return deserialize(oldValue);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putAll(Map<? extends K, ? extends V> m) {
|
public void putAll(final Map<? extends K, ? extends V> m) {
|
||||||
|
pooled(new Consumer<Jedis>() {
|
||||||
|
@Override
|
||||||
|
public void accept(Jedis jedis) {
|
||||||
|
Map<byte[], byte[]> map = new HashMap<byte[], byte[]>();
|
||||||
|
for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
|
||||||
|
map.put(serializeKey(entry.getKey()), serialize(entry.getValue()));
|
||||||
|
}
|
||||||
|
jedis.hmset(getName(), map);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -92,7 +114,7 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
|
|||||||
pooled(new Consumer<Jedis>() {
|
pooled(new Consumer<Jedis>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(Jedis jedis) {
|
public void accept(Jedis jedis) {
|
||||||
jedis.del(getNamespace());
|
jedis.del(getName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -103,10 +125,10 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
|
|||||||
@Override
|
@Override
|
||||||
public Set<K> apply(Jedis jedis) {
|
public Set<K> apply(Jedis jedis) {
|
||||||
Set<K> result = new HashSet<K>();
|
Set<K> result = new HashSet<K>();
|
||||||
collect(jedis.hkeys(getNamespace()), new Transformer<byte[], K>() {
|
collect(jedis.hkeys(getName()), new Transformer<byte[], K>() {
|
||||||
@Override
|
@Override
|
||||||
public K transform(byte[] input) {
|
public K transform(byte[] input) {
|
||||||
return keySerializer.deserialize(input);
|
return deserializeKey(input);
|
||||||
}
|
}
|
||||||
}, result);
|
}, result);
|
||||||
return result;
|
return result;
|
||||||
@ -119,7 +141,7 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
|
|||||||
return pooledWithResult(new Function<Jedis, Collection<V>>() {
|
return pooledWithResult(new Function<Jedis, Collection<V>>() {
|
||||||
@Override
|
@Override
|
||||||
public Collection<V> apply(Jedis jedis) {
|
public Collection<V> apply(Jedis jedis) {
|
||||||
return deserialize(jedis.hvals(getNamespace()));
|
return deserialize(jedis.hvals(getName()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -130,10 +152,10 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
|
|||||||
@Override
|
@Override
|
||||||
public Set<Entry<K, V>> apply(Jedis jedis) {
|
public Set<Entry<K, V>> apply(Jedis jedis) {
|
||||||
Set<Entry<K, V>> result = new HashSet<Entry<K, V>>();
|
Set<Entry<K, V>> result = new HashSet<Entry<K, V>>();
|
||||||
collect(jedis.hgetAll(getNamespace()).entrySet(), new Transformer<Entry<byte[], byte[]>, Entry<K, V>>() {
|
collect(jedis.hgetAll(getName()).entrySet(), new Transformer<Entry<byte[], byte[]>, Entry<K, V>>() {
|
||||||
@Override
|
@Override
|
||||||
public Entry<K, V> transform(Entry<byte[], byte[]> input) {
|
public Entry<K, V> transform(Entry<byte[], byte[]> input) {
|
||||||
K key = keySerializer.deserialize(input.getKey());
|
K key = deserializeKey(input.getKey());
|
||||||
V value = deserialize(input.getValue());
|
V value = deserialize(input.getValue());
|
||||||
return new RedisMapEntry<K, V>(key, value);
|
return new RedisMapEntry<K, V>(key, value);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
|
|||||||
return pooledWithResult(new Function<Jedis, Integer>() {
|
return pooledWithResult(new Function<Jedis, Integer>() {
|
||||||
@Override
|
@Override
|
||||||
public Integer apply(Jedis jedis) {
|
public Integer apply(Jedis jedis) {
|
||||||
return jedis.scard(getNamespace()).intValue();
|
return jedis.scard(getName()).intValue();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -37,30 +37,34 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
|
|||||||
return pooledWithResult(new Function<Jedis, Boolean>() {
|
return pooledWithResult(new Function<Jedis, Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean apply(Jedis jedis) {
|
public Boolean apply(Jedis jedis) {
|
||||||
return jedis.sismember(getNamespace(), serialize(o));
|
return jedis.sismember(getName(), serialize((T) o));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
|
return asCollection().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<T> asCollection() {
|
||||||
Set<byte[]> members = pooledWithResult(new Function<Jedis, Set<byte[]>>() {
|
Set<byte[]> members = pooledWithResult(new Function<Jedis, Set<byte[]>>() {
|
||||||
@Override
|
@Override
|
||||||
public Set<byte[]> apply(Jedis jedis) {
|
public Set<byte[]> apply(Jedis jedis) {
|
||||||
return jedis.smembers(getNamespace());
|
return jedis.smembers(getName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return deserialize(members).iterator();
|
return deserialize(members);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] toArray() {
|
public Object[] toArray() {
|
||||||
throw new UnsupportedOperationException();
|
return asCollection().toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T1> T1[] toArray(T1[] a) {
|
public <T1> T1[] toArray(T1[] a) {
|
||||||
throw new UnsupportedOperationException();
|
return asCollection().toArray(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -83,7 +87,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
|
|||||||
return pooledWithResult(new Function<Jedis, Boolean>() {
|
return pooledWithResult(new Function<Jedis, Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean apply(Jedis jedis) {
|
public Boolean apply(Jedis jedis) {
|
||||||
return jedis.sadd(getNamespace(), serialize(c)) == 1;
|
return jedis.sadd(getName(), serialize(c)) == 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -93,7 +97,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
|
|||||||
return pooledWithResult(new Function<Jedis, Boolean>() {
|
return pooledWithResult(new Function<Jedis, Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean apply(Jedis jedis) {
|
public Boolean apply(Jedis jedis) {
|
||||||
return jedis.sinterstore(getNamespace(), serialize(c)) == c.size();
|
return jedis.sinterstore(getName(), serialize(c)) == c.size();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -103,7 +107,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
|
|||||||
return pooledWithResult(new Function<Jedis, Boolean>() {
|
return pooledWithResult(new Function<Jedis, Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean apply(Jedis jedis) {
|
public Boolean apply(Jedis jedis) {
|
||||||
return jedis.srem(getNamespace(), serialize(c)) == 1;
|
return jedis.srem(getName(), serialize(c)) == 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -113,7 +117,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
|
|||||||
pooled(new Consumer<Jedis>() {
|
pooled(new Consumer<Jedis>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(Jedis jedis) {
|
public void accept(Jedis jedis) {
|
||||||
jedis.del(getNamespace());
|
jedis.del(getName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -16,49 +16,33 @@ public abstract class RedisStorage<T> {
|
|||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger("db");
|
private static final Logger logger = LoggerFactory.getLogger("db");
|
||||||
|
|
||||||
private String namespace;
|
private byte[] name;
|
||||||
private final JedisPool pool;
|
private final JedisPool pool;
|
||||||
private final RedisSerializer<T> serializer;
|
private final RedisSerializer<T> serializer;
|
||||||
|
|
||||||
RedisStorage(String namespace, JedisPool pool, RedisSerializer<T> serializer) {
|
RedisStorage(String name, JedisPool pool, RedisSerializer<T> serializer) {
|
||||||
|
this.name = name.getBytes();
|
||||||
this.pool = pool;
|
this.pool = pool;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
|
|
||||||
setNamespace(namespace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] getNamespace() {
|
protected byte[] getName() {
|
||||||
return namespace.getBytes();
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setNamespace(String namespace) {
|
protected void setName(String name) {
|
||||||
this.namespace = namespace + ":";
|
this.name = name.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] formatKey(byte[] key) {
|
protected byte[] serialize(T o) {
|
||||||
byte[] prefix = getNamespace();
|
return serializer.serialize(o);
|
||||||
|
|
||||||
int length = prefix.length + key.length;
|
|
||||||
byte[] result = new byte[length];
|
|
||||||
System.arraycopy(prefix, 0, result, 0, prefix.length);
|
|
||||||
System.arraycopy(key, 0, result, prefix.length, key.length);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte[] serialize(Object o) {
|
|
||||||
if (serializer.canSerialize(o)) {
|
|
||||||
return serializer.serialize((T) o);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.warn("Cannot serialize '%s'.", o.getClass());
|
|
||||||
return new byte[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[][] serialize(Collection<?> collection) {
|
protected byte[][] serialize(Collection<?> collection) {
|
||||||
return collect(collection, new Transformer<Object, byte[]>() {
|
return collect(collection, new Transformer<Object, byte[]>() {
|
||||||
@Override
|
@Override
|
||||||
public byte[] transform(Object input) {
|
public byte[] transform(Object input) {
|
||||||
return serialize(input);
|
return serialize((T) input);
|
||||||
}
|
}
|
||||||
}).toArray(new byte[][]{});
|
}).toArray(new byte[][]{});
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,11 @@ package org.ethereum.datasource.redis;
|
|||||||
import com.fasterxml.jackson.databind.JavaType;
|
import com.fasterxml.jackson.databind.JavaType;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||||
|
import org.ethereum.core.AccountState;
|
||||||
|
import org.ethereum.core.Block;
|
||||||
import org.ethereum.core.Transaction;
|
import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.core.TransactionReceipt;
|
import org.ethereum.core.TransactionReceipt;
|
||||||
|
import org.ethereum.db.ContractDetails;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -68,12 +71,12 @@ public final class Serializers {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] serialize(TransactionReceipt transactionReceipt) {
|
public byte[] serialize(TransactionReceipt transactionReceipt) {
|
||||||
return transactionReceipt.getEncoded();
|
return (transactionReceipt == null) ? EMPTY_ARRAY : transactionReceipt.getEncoded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TransactionReceipt deserialize(byte[] bytes) {
|
public TransactionReceipt deserialize(byte[] bytes) {
|
||||||
return new TransactionReceipt(bytes);
|
return isEmpty(bytes) ? null : new TransactionReceipt(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,12 +89,66 @@ public final class Serializers {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] serialize(Transaction transaction) {
|
public byte[] serialize(Transaction transaction) {
|
||||||
return transaction.getEncoded();
|
return (transaction == null) ? EMPTY_ARRAY : transaction.getEncoded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transaction deserialize(byte[] bytes) {
|
public Transaction deserialize(byte[] bytes) {
|
||||||
return new Transaction(bytes);
|
return isEmpty(bytes) ? null : new Transaction(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AccountStateSerializer extends BaseRedisSerializer<AccountState> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(Class<?> aClass) {
|
||||||
|
return AccountState.class.isAssignableFrom(aClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serialize(AccountState accountState) {
|
||||||
|
return (accountState == null) ? EMPTY_ARRAY : accountState.getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccountState deserialize(byte[] bytes) {
|
||||||
|
return isEmpty(bytes) ? null : new AccountState(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BlockSerializer extends BaseRedisSerializer<Block> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(Class<?> aClass) {
|
||||||
|
return Block.class.isAssignableFrom(aClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serialize(Block block) {
|
||||||
|
return (block == null) ? EMPTY_ARRAY : block.getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block deserialize(byte[] bytes) {
|
||||||
|
return isEmpty(bytes) ? null : new Block(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ContractDetailsSerializer extends BaseRedisSerializer<ContractDetails> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(Class<?> aClass) {
|
||||||
|
return ContractDetails.class.isAssignableFrom(aClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serialize(ContractDetails contractDetails) {
|
||||||
|
return (contractDetails == null) ? EMPTY_ARRAY : contractDetails.getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContractDetails deserialize(byte[] bytes) {
|
||||||
|
return isEmpty(bytes) ? null : new ContractDetails(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +157,9 @@ public final class Serializers {
|
|||||||
private static final Set<? extends BaseRedisSerializer> SERIALIZERS = new HashSet<BaseRedisSerializer>() {{
|
private static final Set<? extends BaseRedisSerializer> SERIALIZERS = new HashSet<BaseRedisSerializer>() {{
|
||||||
add(new TransactionSerializer());
|
add(new TransactionSerializer());
|
||||||
add(new TransactionReceiptSerializer());
|
add(new TransactionReceiptSerializer());
|
||||||
|
add(new AccountStateSerializer());
|
||||||
|
add(new BlockSerializer());
|
||||||
|
add(new ContractDetailsSerializer());
|
||||||
}};
|
}};
|
||||||
|
|
||||||
public static <T> RedisSerializer<T> forClass(Class<T> clazz) {
|
public static <T> RedisSerializer<T> forClass(Class<T> clazz) {
|
||||||
|
@ -1,16 +1,11 @@
|
|||||||
package org.ethereum.db;
|
package org.ethereum.db;
|
||||||
|
|
||||||
import org.ethereum.datasource.KeyValueDataSource;
|
import org.ethereum.datasource.KeyValueDataSource;
|
||||||
import org.ethereum.facade.EthereumFactory;
|
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
import javax.xml.crypto.dsig.keyinfo.KeyValue;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -71,6 +66,7 @@ public class DatabaseImpl implements Database {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
|
||||||
keyValueDataSource.close();
|
keyValueDataSource.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,123 @@
|
|||||||
|
package org.ethereum.facade;
|
||||||
|
|
||||||
|
import org.ethereum.config.SystemProperties;
|
||||||
|
import org.ethereum.core.Transaction;
|
||||||
|
import org.ethereum.datasource.KeyValueDataSource;
|
||||||
|
import org.ethereum.datasource.LevelDbDataSource;
|
||||||
|
import org.ethereum.datasource.redis.RedisConnection;
|
||||||
|
import org.ethereum.db.RepositoryImpl;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||||
|
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||||
|
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableTransactionManagement
|
||||||
|
@ComponentScan(basePackages = "org.ethereum")
|
||||||
|
public class CommonConfig {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger("general");
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisConnection redisConnection;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
Repository repository(){
|
||||||
|
return new RepositoryImpl(keyValueDataSource(), keyValueDataSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Scope("prototype")
|
||||||
|
public KeyValueDataSource keyValueDataSource(){
|
||||||
|
if (CONFIG.getKeyValueDataSource().equals("redis")) {
|
||||||
|
if (redisConnection.isAvailable()) {
|
||||||
|
// Name will be defined before initialization
|
||||||
|
return redisConnection.createDataSource("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LevelDbDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Set<Transaction> pendingTransactions() {
|
||||||
|
return redisConnection.isAvailable()
|
||||||
|
? redisConnection.createTransactionSet("pendingTransactions")
|
||||||
|
: Collections.synchronizedSet(new HashSet<Transaction>());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SessionFactory sessionFactory() throws SQLException {
|
||||||
|
LocalSessionFactoryBuilder builder =
|
||||||
|
new LocalSessionFactoryBuilder(dataSource());
|
||||||
|
builder.scanPackages("org.ethereum.db")
|
||||||
|
.addProperties(getHibernateProperties());
|
||||||
|
|
||||||
|
return builder.buildSessionFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Properties getHibernateProperties() {
|
||||||
|
|
||||||
|
Properties prop = new Properties();
|
||||||
|
|
||||||
|
if (SystemProperties.CONFIG.databaseReset())
|
||||||
|
prop.put("hibernate.hbm2ddl.auto", "create");
|
||||||
|
|
||||||
|
prop.put("hibernate.format_sql", "true");
|
||||||
|
|
||||||
|
// todo: useful but annoying consider define by system.properties
|
||||||
|
// prop.put("hibernate.show_sql", "true");
|
||||||
|
prop.put("hibernate.dialect",
|
||||||
|
"org.hibernate.dialect.HSQLDialect");
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DataSourceTransactionManager transactionManager() {
|
||||||
|
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
|
||||||
|
dataSourceTransactionManager.setDataSource(dataSource());
|
||||||
|
|
||||||
|
return dataSourceTransactionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "dataSource")
|
||||||
|
public DriverManagerDataSource dataSource() {
|
||||||
|
|
||||||
|
logger.info("Connecting to the block store");
|
||||||
|
|
||||||
|
System.setProperty("hsqldb.reconfig_logging", "false");
|
||||||
|
|
||||||
|
String url =
|
||||||
|
String.format("jdbc:hsqldb:file:./%s/blockchain/blockchain.db;" +
|
||||||
|
"create=%s;hsqldb.default_table_type=cached",
|
||||||
|
|
||||||
|
SystemProperties.CONFIG.databaseDir(),
|
||||||
|
SystemProperties.CONFIG.databaseReset());
|
||||||
|
|
||||||
|
DriverManagerDataSource ds = new DriverManagerDataSource();
|
||||||
|
ds.setDriverClassName("org.hsqldb.jdbcDriver");
|
||||||
|
ds.setUrl(url);
|
||||||
|
ds.setUsername("sa");
|
||||||
|
|
||||||
|
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,147 +1,29 @@
|
|||||||
package org.ethereum.facade;
|
package org.ethereum.facade;
|
||||||
|
|
||||||
import org.ethereum.config.SystemProperties;
|
|
||||||
import org.ethereum.core.Transaction;
|
|
||||||
import org.ethereum.datasource.KeyValueDataSource;
|
|
||||||
import org.ethereum.datasource.LevelDbDataSource;
|
|
||||||
import org.ethereum.datasource.RedisDataSource;
|
|
||||||
import org.ethereum.datasource.redis.RedisConnection;
|
|
||||||
import org.ethereum.datasource.redis.RedisConnectionImpl;
|
|
||||||
import org.ethereum.db.BlockStore;
|
import org.ethereum.db.BlockStore;
|
||||||
import org.ethereum.db.BlockStoreImpl;
|
import org.ethereum.db.BlockStoreImpl;
|
||||||
import org.ethereum.db.RepositoryImpl;
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
|
||||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
|
||||||
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
|
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author: Roman Mandeleil
|
* @author: Roman Mandeleil
|
||||||
* Created on: 27/01/2015 01:05
|
* Created on: 27/01/2015 01:05
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableTransactionManagement
|
@Import(CommonConfig.class)
|
||||||
@ComponentScan(basePackages = "org.ethereum")
|
|
||||||
public class DefaultConfig {
|
public class DefaultConfig {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger("general");
|
@Autowired CommonConfig commonConfig;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
Ethereum eth;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
Repository repository(){
|
|
||||||
return new RepositoryImpl(keyValueDataSource(), keyValueDataSource());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@Scope("prototype")
|
|
||||||
public KeyValueDataSource keyValueDataSource(){
|
|
||||||
|
|
||||||
if (CONFIG.getKeyValueDataSource().equals("redis")) {
|
|
||||||
return new RedisDataSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new LevelDbDataSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public RedisConnection redisConnection() {
|
|
||||||
RedisConnectionImpl connection = new RedisConnectionImpl();
|
|
||||||
connection.init();
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Set<Transaction> pendingTransactions() {
|
|
||||||
RedisConnection connection = redisConnection();
|
|
||||||
return connection.isAvailable()
|
|
||||||
? connection.createTransactionSet("pendingTransactions")
|
|
||||||
: Collections.synchronizedSet(new HashSet<Transaction>());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Transactional(propagation = Propagation.SUPPORTS)
|
@Transactional(propagation = Propagation.SUPPORTS)
|
||||||
public BlockStore blockStore(SessionFactory sessionFactory){
|
public BlockStore blockStore(SessionFactory sessionFactory){
|
||||||
return new BlockStoreImpl(sessionFactory);
|
return new BlockStoreImpl(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SessionFactory sessionFactory() throws SQLException {
|
|
||||||
LocalSessionFactoryBuilder builder =
|
|
||||||
new LocalSessionFactoryBuilder(dataSource());
|
|
||||||
builder.scanPackages("org.ethereum.db")
|
|
||||||
.addProperties(getHibernateProperties());
|
|
||||||
|
|
||||||
return builder.buildSessionFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Properties getHibernateProperties() {
|
|
||||||
|
|
||||||
Properties prop = new Properties();
|
|
||||||
|
|
||||||
if (SystemProperties.CONFIG.databaseReset())
|
|
||||||
prop.put("hibernate.hbm2ddl.auto", "create");
|
|
||||||
|
|
||||||
prop.put("hibernate.format_sql", "true");
|
|
||||||
|
|
||||||
// todo: useful but annoying consider define by system.properties
|
|
||||||
// prop.put("hibernate.show_sql", "true");
|
|
||||||
prop.put("hibernate.dialect",
|
|
||||||
"org.hibernate.dialect.HSQLDialect");
|
|
||||||
return prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public DataSourceTransactionManager transactionManager() {
|
|
||||||
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
|
|
||||||
dataSourceTransactionManager.setDataSource(dataSource());
|
|
||||||
|
|
||||||
return dataSourceTransactionManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean(name = "dataSource")
|
|
||||||
public DriverManagerDataSource dataSource() {
|
|
||||||
|
|
||||||
logger.info("Connecting to the block store");
|
|
||||||
|
|
||||||
System.setProperty("hsqldb.reconfig_logging", "false");
|
|
||||||
|
|
||||||
String url =
|
|
||||||
String.format("jdbc:hsqldb:file:./%s/blockchain/blockchain.db;" +
|
|
||||||
"create=%s;hsqldb.default_table_type=cached",
|
|
||||||
|
|
||||||
SystemProperties.CONFIG.databaseDir(),
|
|
||||||
SystemProperties.CONFIG.databaseReset());
|
|
||||||
|
|
||||||
DriverManagerDataSource ds = new DriverManagerDataSource();
|
|
||||||
ds.setDriverClassName("org.hsqldb.jdbcDriver");
|
|
||||||
ds.setUrl(url);
|
|
||||||
ds.setUsername("sa");
|
|
||||||
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,25 +12,20 @@ import org.ethereum.net.server.PeerServer;
|
|||||||
import org.ethereum.net.submit.TransactionExecutor;
|
import org.ethereum.net.submit.TransactionExecutor;
|
||||||
import org.ethereum.net.submit.TransactionTask;
|
import org.ethereum.net.submit.TransactionTask;
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
|
|
||||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,150 +1,32 @@
|
|||||||
package org.ethereum.facade;
|
package org.ethereum.facade;
|
||||||
|
|
||||||
import org.ethereum.config.SystemProperties;
|
|
||||||
import org.ethereum.core.Transaction;
|
|
||||||
import org.ethereum.datasource.KeyValueDataSource;
|
|
||||||
import org.ethereum.datasource.LevelDbDataSource;
|
|
||||||
import org.ethereum.datasource.RedisDataSource;
|
|
||||||
import org.ethereum.datasource.redis.RedisConnection;
|
|
||||||
import org.ethereum.datasource.redis.RedisConnectionImpl;
|
|
||||||
import org.ethereum.db.BlockStore;
|
import org.ethereum.db.BlockStore;
|
||||||
import org.ethereum.db.InMemoryBlockStore;
|
import org.ethereum.db.InMemoryBlockStore;
|
||||||
import org.ethereum.db.RepositoryImpl;
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
|
||||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
|
||||||
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
|
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author: Roman Mandeleil
|
* @author: Roman Mandeleil
|
||||||
* Created on: 27/01/2015 01:05
|
* Created on: 27/01/2015 01:05
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableTransactionManagement
|
@Import(CommonConfig.class)
|
||||||
@ComponentScan(basePackages = "org.ethereum")
|
|
||||||
public class RemoteConfig {
|
public class RemoteConfig {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger("general");
|
@Autowired CommonConfig commonConfig;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
Ethereum eth;
|
|
||||||
|
|
||||||
// todo: init total difficulty
|
// todo: init total difficulty
|
||||||
// todo: init last 1000 blocks
|
// todo: init last 1000 blocks
|
||||||
|
|
||||||
@Bean
|
|
||||||
Repository repository(){
|
|
||||||
return new RepositoryImpl(keyValueDataSource(), keyValueDataSource());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@Scope("prototype")
|
|
||||||
public KeyValueDataSource keyValueDataSource(){
|
|
||||||
|
|
||||||
if (CONFIG.getKeyValueDataSource().equals("redis")) {
|
|
||||||
return new RedisDataSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new LevelDbDataSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public RedisConnection redisConnection() {
|
|
||||||
RedisConnectionImpl connection = new RedisConnectionImpl();
|
|
||||||
connection.init();
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Set<Transaction> pendingTransactions() {
|
|
||||||
RedisConnection connection = redisConnection();
|
|
||||||
return connection.isAvailable()
|
|
||||||
? connection.createTransactionSet("pendingTransactions")
|
|
||||||
: Collections.synchronizedSet(new HashSet<Transaction>());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Transactional(propagation = Propagation.SUPPORTS)
|
@Transactional(propagation = Propagation.SUPPORTS)
|
||||||
public BlockStore blockStore(SessionFactory sessionFactory){
|
public BlockStore blockStore(SessionFactory sessionFactory){
|
||||||
return new InMemoryBlockStore();
|
return new InMemoryBlockStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SessionFactory sessionFactory() throws SQLException {
|
|
||||||
LocalSessionFactoryBuilder builder =
|
|
||||||
new LocalSessionFactoryBuilder(dataSource());
|
|
||||||
builder.scanPackages("org.ethereum.db")
|
|
||||||
.addProperties(getHibernateProperties());
|
|
||||||
|
|
||||||
return builder.buildSessionFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Properties getHibernateProperties() {
|
|
||||||
|
|
||||||
Properties prop = new Properties();
|
|
||||||
|
|
||||||
if (SystemProperties.CONFIG.databaseReset())
|
|
||||||
prop.put("hibernate.hbm2ddl.auto", "create");
|
|
||||||
|
|
||||||
prop.put("hibernate.format_sql", "true");
|
|
||||||
|
|
||||||
// todo: useful but annoying consider define by system.properties
|
|
||||||
// prop.put("hibernate.show_sql", "true");
|
|
||||||
prop.put("hibernate.dialect",
|
|
||||||
"org.hibernate.dialect.HSQLDialect");
|
|
||||||
return prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public DataSourceTransactionManager transactionManager() {
|
|
||||||
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
|
|
||||||
dataSourceTransactionManager.setDataSource(dataSource());
|
|
||||||
|
|
||||||
return dataSourceTransactionManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean(name = "dataSource")
|
|
||||||
public DriverManagerDataSource dataSource() {
|
|
||||||
|
|
||||||
logger.info("Connecting to the block store");
|
|
||||||
|
|
||||||
System.setProperty("hsqldb.reconfig_logging", "false");
|
|
||||||
|
|
||||||
String url =
|
|
||||||
String.format("jdbc:hsqldb:file:./%s/blockchain/blockchain.db;" +
|
|
||||||
"create=%s;hsqldb.default_table_type=cached",
|
|
||||||
|
|
||||||
SystemProperties.CONFIG.databaseDir(),
|
|
||||||
SystemProperties.CONFIG.databaseReset());
|
|
||||||
|
|
||||||
DriverManagerDataSource ds = new DriverManagerDataSource();
|
|
||||||
ds.setDriverClassName("org.hsqldb.jdbcDriver");
|
|
||||||
ds.setUrl(url);
|
|
||||||
ds.setUsername("sa");
|
|
||||||
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package test.ethereum.datasource;
|
||||||
|
|
||||||
|
import org.ethereum.datasource.redis.RedisConnection;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||||
|
import test.ethereum.TestContext;
|
||||||
|
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||||
|
public class AbstractRedisTest {
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan(basePackages = "org.ethereum")
|
||||||
|
static class ContextConfiguration extends TestContext { }
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected RedisConnection redisConnection;
|
||||||
|
|
||||||
|
}
|
@ -3,33 +3,15 @@ package test.ethereum.datasource;
|
|||||||
import org.ethereum.core.Transaction;
|
import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.crypto.ECKey;
|
import org.ethereum.crypto.ECKey;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.datasource.redis.RedisConnection;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
|
||||||
import test.ethereum.TestContext;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
public class RedisConnectionTest extends AbstractRedisTest {
|
||||||
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
|
||||||
public class RedisConnectionTest {
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ComponentScan(basePackages = "org.ethereum")
|
|
||||||
static class ContextConfiguration extends TestContext { }
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RedisConnection redisConnection;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
|
@ -1,68 +1,69 @@
|
|||||||
package test.ethereum.datasource;
|
package test.ethereum.datasource;
|
||||||
|
|
||||||
import org.ethereum.datasource.RedisDataSource;
|
import org.ethereum.datasource.KeyValueDataSource;
|
||||||
|
import org.ethereum.datasource.redis.RedisDataSource;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Roman Mandeleil
|
* @author Roman Mandeleil
|
||||||
*/
|
*/
|
||||||
public class RedisDataSourceTest {
|
public class RedisDataSourceTest extends AbstractRedisTest {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSet1() {
|
public void testSet1() {
|
||||||
|
if (!redisConnection.isAvailable()) return;
|
||||||
|
|
||||||
|
KeyValueDataSource dataSource = createDataSource("test-state");
|
||||||
try {
|
try {
|
||||||
RedisDataSource redis = new RedisDataSource();
|
|
||||||
redis.setName("state");
|
|
||||||
redis.init();
|
|
||||||
|
|
||||||
byte[] key = Hex.decode("a1a2a3");
|
byte[] key = Hex.decode("a1a2a3");
|
||||||
byte[] val = Hex.decode("b1b2b3");
|
byte[] val = Hex.decode("b1b2b3");
|
||||||
|
|
||||||
redis.put(key, val);
|
dataSource.put(key, val);
|
||||||
byte[] val2 = redis.get(key);
|
byte[] val2 = dataSource.get(key);
|
||||||
|
|
||||||
Assert.assertEquals(Hex.toHexString(val), Hex.toHexString(val2));
|
Assert.assertEquals(Hex.toHexString(val), Hex.toHexString(val2));
|
||||||
} catch (JedisConnectionException e) {
|
} finally {
|
||||||
// no redis server consider test as pass
|
clear(dataSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSet2() {
|
public void testSet2() {
|
||||||
|
if (!redisConnection.isAvailable()) return;
|
||||||
|
|
||||||
|
KeyValueDataSource states = createDataSource("test-state");
|
||||||
|
KeyValueDataSource details = createDataSource("test-details");
|
||||||
|
|
||||||
try {
|
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[] key = Hex.decode("a1a2a3");
|
||||||
byte[] val1 = Hex.decode("b1b2b3");
|
byte[] val1 = Hex.decode("b1b2b3");
|
||||||
byte[] val2 = Hex.decode("c1c2c3");
|
byte[] val2 = Hex.decode("c1c2c3");
|
||||||
|
|
||||||
redis1.put(key, val1);
|
states.put(key, val1);
|
||||||
redis2.put(key, val2);
|
details.put(key, val2);
|
||||||
|
|
||||||
byte[] res1 = redis1.get(key);
|
byte[] res1 = states.get(key);
|
||||||
byte[] res2 = redis2.get(key);
|
byte[] res2 = details.get(key);
|
||||||
|
|
||||||
Assert.assertEquals(Hex.toHexString(val1), Hex.toHexString(res1));
|
Assert.assertEquals(Hex.toHexString(val1), Hex.toHexString(res1));
|
||||||
Assert.assertEquals(Hex.toHexString(val2), Hex.toHexString(res2));
|
Assert.assertEquals(Hex.toHexString(val2), Hex.toHexString(res2));
|
||||||
} catch (JedisConnectionException e) {
|
} finally {
|
||||||
// no redis server consider test as pass
|
clear(states);
|
||||||
|
clear(details);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private KeyValueDataSource createDataSource(String name) {
|
||||||
|
KeyValueDataSource result = redisConnection.createDataSource(name);
|
||||||
|
result.setName(name);
|
||||||
|
result.init();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clear(KeyValueDataSource dataSource) {
|
||||||
|
((RedisDataSource) dataSource).clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,15 +22,13 @@ public class MockDB implements KeyValueDataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] get(byte[] arg0) throws DBException {
|
public byte[] get(byte[] arg0) throws DBException {
|
||||||
|
|
||||||
return storage.get(new ByteArrayWrapper(arg0));
|
return storage.get(new ByteArrayWrapper(arg0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void put(byte[] key, byte[] value) throws DBException {
|
public byte[] put(byte[] key, byte[] value) throws DBException {
|
||||||
|
return storage.put(new ByteArrayWrapper(key), value);
|
||||||
storage.put(new ByteArrayWrapper(key), value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user