Author: toad
Date: 2008-02-07 14:37:39 +0000 (Thu, 07 Feb 2008)
New Revision: 17660
Added:
trunk/freenet/src/freenet/store/RAMFreenetStore.java
Log:
RAMFreenetStore: Keep everything in RAM, including the data. Useful for
many-nodes-one-VM simulations.
Added: trunk/freenet/src/freenet/store/RAMFreenetStore.java
===================================================================
--- trunk/freenet/src/freenet/store/RAMFreenetStore.java
(rev 0)
+++ trunk/freenet/src/freenet/store/RAMFreenetStore.java 2008-02-07
14:37:39 UTC (rev 17660)
@@ -0,0 +1,122 @@
+package freenet.store;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import com.sleepycat.je.DatabaseException;
+
+import freenet.keys.KeyVerifyException;
+import freenet.support.ByteArrayWrapper;
+import freenet.support.LRUHashtable;
+
+public class RAMFreenetStore implements FreenetStore {
+
+ private class Block {
+ byte[] header;
+ byte[] data;
+ byte[] fullKey;
+ }
+
+ private final LRUHashtable blocksByRoutingKey;
+
+ private final StoreCallback callback;
+
+ private int maxKeys;
+
+ private long hits;
+ private long misses;
+ private long writes;
+
+ public RAMFreenetStore(StoreCallback callback, int maxKeys) {
+ this.callback = callback;
+ this.blocksByRoutingKey = new LRUHashtable();
+ this.maxKeys = maxKeys;
+ }
+
+ public synchronized StorableBlock fetch(byte[] routingKey, byte[]
fullKey,
+ boolean dontPromote) throws IOException {
+ ByteArrayWrapper key = new ByteArrayWrapper(routingKey);
+ Block block = (Block) blocksByRoutingKey.get(key);
+ if(block == null) {
+ misses++;
+ return null;
+ }
+ try {
+ StorableBlock ret =
+ callback.construct(block.data, block.header,
routingKey, block.fullKey);
+ hits++;
+ if(!dontPromote)
+ blocksByRoutingKey.push(key, block);
+ return ret;
+ } catch (KeyVerifyException e) {
+ blocksByRoutingKey.removeKey(key);
+ misses++;
+ return null;
+ }
+ }
+
+ public synchronized long getMaxKeys() {
+ return (long) maxKeys;
+ }
+
+ public synchronized long hits() {
+ return hits;
+ }
+
+ public synchronized long keyCount() {
+ return blocksByRoutingKey.size();
+ }
+
+ public synchronized long misses() {
+ return misses;
+ }
+
+ public synchronized void put(StorableBlock block, byte[] routingkey,
byte[] fullKey,
+ byte[] data, byte[] header, boolean overwrite) throws
IOException,
+ KeyCollisionException {
+ writes++;
+ ByteArrayWrapper key = new ByteArrayWrapper(routingkey);
+ Block oldBlock = (Block) blocksByRoutingKey.get(key);
+ boolean storeFullKeys = callback.storeFullKeys();
+ if(oldBlock != null) {
+ if(callback.collisionPossible()) {
+ boolean equals = Arrays.equals(oldBlock.data,
data) &&
+ Arrays.equals(oldBlock.header, header)
&&
+ (storeFullKeys ?
Arrays.equals(oldBlock.fullKey, fullKey) : true);
+ if(equals) return;
+ if(overwrite) {
+ oldBlock.data = data;
+ oldBlock.header = header;
+ if(storeFullKeys)
+ oldBlock.fullKey = fullKey;
+ }
+ return;
+ } else {
+ return;
+ }
+ }
+ Block storeBlock = new Block();
+ storeBlock.data = data;
+ storeBlock.header = header;
+ if(storeFullKeys)
+ storeBlock.fullKey = fullKey;
+ blocksByRoutingKey.push(key, storeBlock);
+ while(blocksByRoutingKey.size() > maxKeys) {
+ blocksByRoutingKey.popKey();
+ }
+ }
+
+ public synchronized void setMaxKeys(long maxStoreKeys, boolean
shrinkNow)
+ throws DatabaseException, IOException {
+ this.maxKeys = (int)Math.min(Integer.MAX_VALUE, maxStoreKeys);
+ // Always shrink now regardless of parameter as we will shrink
on the next put() anyway.
+ while(blocksByRoutingKey.size() > maxKeys) {
+ blocksByRoutingKey.popKey();
+ }
+ }
+
+ public long writes() {
+ return writes;
+ }
+
+}