package edu.berkeley.thebes.common.persistence.memory; import java.nio.ByteBuffer; import java.util.Map; import java.util.concurrent.TimeUnit; import com.google.common.collect.Maps; import com.yammer.metrics.Metrics; import com.yammer.metrics.core.Gauge; import com.yammer.metrics.core.Meter; import com.yammer.metrics.core.Timer; import com.yammer.metrics.core.TimerContext; import edu.berkeley.thebes.common.data.DataItem; import edu.berkeley.thebes.common.data.Version; import edu.berkeley.thebes.common.persistence.IPersistenceEngine; import edu.berkeley.thebes.common.persistence.disk.WALBackedPersistenceEngine; public class MemoryPersistenceEngine implements IPersistenceEngine { private final Timer forcePutsTimer = Metrics.newTimer(MemoryPersistenceEngine.class, "force-put-latencies"); private final Timer putsTimer = Metrics.newTimer(MemoryPersistenceEngine.class, "put-latencies"); private final Timer getsTimer = Metrics.newTimer(MemoryPersistenceEngine.class, "get-latencies"); private final Timer deletesTimer = Metrics.newTimer(MemoryPersistenceEngine.class, "delete-latencies"); private Map<String, DataItem> map; private DataItem nullItem = new DataItem(ByteBuffer.allocate(0), Version.NULL_VERSION); public void open() { map = Maps.newConcurrentMap(); Metrics.newGauge(MemoryPersistenceEngine.class, "num-keys", new Gauge<Integer>() { @Override public Integer value() { return map.size(); } }); } public void force_put(String key, DataItem value) { TimerContext context = forcePutsTimer.time(); try { map.put(key, value); } finally { context.stop(); } } /** * Puts the given value for our key. * Does not update the value if the key already exists with a later timestamp. */ @Override public void put_if_newer(String key, DataItem value) { TimerContext context = putsTimer.time(); try { // TODO: Some form of synchronization is necessary // synchronized (map) { // If we already have this key, ensure new item is a more recent version if (map.containsKey(key)) { DataItem curItem = map.get(key); if (curItem.getVersion().compareTo(value.getVersion()) > 0) { return; } } // New key or newer timestamp. map.put(key, value); // } } finally { context.stop(); } } public DataItem get(String key) { TimerContext context = getsTimer.time(); try { DataItem ret = map.get(key); if(ret == null) ret = nullItem; return ret; } finally { context.stop(); } } public void delete(String key) { TimerContext context = deletesTimer.time(); try { map.remove(key); } finally { context.stop(); } } public void close() { return; } }