package edu.berkeley.lipstick.backend; import edu.berkeley.lipstick.config.Config; import edu.berkeley.lipstick.localstore.ILocalStore; import edu.berkeley.lipstick.storage.IStorage; import edu.berkeley.lipstick.util.*; import edu.berkeley.lipstick.util.serializer.IDWSerializer; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicLong; public class AsynchronousReadExplicitBackend implements IExplicitBackend { IStorage storage; AtomicLong localSequenceNo; WriteRecorder localWriteRecorder; ILocalStore localStore; Iterable<DataWrapper> responseQueue; IDWSerializer DWserializer; AsynchronousResolver resolver; AtomicLong nullReads = new AtomicLong(0); Thread cleaner; String myPid; final int maxNumECDSreads; public AsynchronousReadExplicitBackend(IStorage storage) throws Exception { this.storage = storage; localWriteRecorder = new WriteRecorder(); localStore = Config.getLocalStore(); responseQueue = new ConcurrentLinkedQueue<DataWrapper>(); DWserializer = Config.getDWSerializer(); localSequenceNo = new AtomicLong(0); maxNumECDSreads = Config.getBackendMaxSyncECDSReads(); resolver = new AsynchronousResolver(localStore, storage, DWserializer); myPid = Config.getProcessID(); if(Config.doResolveInBackground()) { cleaner = new Thread(resolver); cleaner.setDaemon(true); cleaner.setPriority(Thread.MIN_PRIORITY); cleaner.start(); } } public void open() throws Exception { storage.open(); } public void close() throws Exception { resolver.close(); System.out.println("memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) + "; byteswritten: " + Config.getBytesWritten() + "; bytesread: " + Config.getBytesRead() + "; storagetotalwritelatency: "+Config.getStorageWriteLatency()+ "; storagetotalreadlatency: "+Config.getStorageReadLatency()+ "; totalvisibilitytime: "+localStore.getTotalVisiblityLatency()+ "; totalvisibilityresolvedreads: "+localStore.getNumResolvedReads()+ "; clientnullreads: "+nullReads.get()+ "; datastorereads: "+storage.getNumReads()+ "; datastorewrites: "+storage.getNumWrites()); storage.close(); } public DataWrapper get(String key) throws Exception { if(maxNumECDSreads == 0) { DataWrapper ret = localStore.get(key); resolver.addKeyToCheck(key); if(ret == null) nullReads.incrementAndGet(); return ret; } byte[] response = (byte [])storage.get(key, true); if(response != null && response.length != 0) { DataWrapper readResponse = Config.getDWSerializer().fromByteArray(key, response); if(resolver.checkSingleKey(readResponse, maxNumECDSreads-1)) return readResponse; else readResponse.markReadFromStorage(); } DataWrapper ret = localStore.get(key); if(ret == null) nullReads.incrementAndGet(); return ret; } public final DataWrapper put_at_start(String key, Object value) throws Exception { return put_after(key, value, new HashSet<DataWrapper>()); } public final DataWrapper put_after(String key, Object value, DataWrapper after) throws Exception { Set<DataWrapper> toPass = new HashSet<DataWrapper>(); if(after != null) { toPass.add(after); } return put_after(key, value, toPass); } public final DataWrapper put_after(String key, Object value, Set<DataWrapper> after) throws Exception { long timestamp = System.currentTimeMillis(); KeyDependencySet thisKDS = new KeyDependencySet(after); WriteClock thisWriteClock = new WriteClock(); for(DataWrapper dep : after) { if(dep.getKey().matches(key)) { thisWriteClock.mergeClock(dep.getDependency(key).getClock()); } } thisWriteClock.setValue(Config.getProcessID(), localSequenceNo.getAndIncrement()); thisKDS.putDependency(key, new KeyDependency(thisWriteClock)); DataWrapper toWrite = new DataWrapper(key, value, thisKDS, timestamp); storage.put(key, DWserializer.toByteArray(toWrite), timestamp, true); localStore.put(key, toWrite); return toWrite; } }