Mercurial > hg > blitz_condensed
view src/org/dancres/blitz/entry/EntrySleeveImpl.java @ 34:6f68e94c1fb8 default tip
Add CondensedStats monitoring utility, equivalent to vmstat
author | Dominic Cleal <dominic-cleal@cdo2.com> |
---|---|
date | Thu, 05 Aug 2010 11:07:25 +0100 |
parents | 3dc0c5604566 |
children |
line wrap: on
line source
package org.dancres.blitz.entry; import java.util.logging.Logger; import org.dancres.struct.LinkedInstance; import org.dancres.blitz.mangler.MangledEntry; import org.dancres.blitz.mangler.EntryMangler; import org.dancres.blitz.oid.OID; import org.dancres.blitz.oid.OIDFactory; import org.dancres.blitz.cache.Identifiable; import org.dancres.blitz.cache.Identifier; import org.dancres.blitz.test.DummyEntry; import org.dancres.blitz.Logging; import org.dancres.blitz.entry.ci.CacheIndexer; /** <p> The in-memory representation of an Entry (as in record sleeve) - includes transient caching state as well as persistent information. </p> <p> Call flatten to render an instance into a byte[] suitable for disk storage and invoke the constructor EntrySleeveImpl(byte[]) to reconstitute the flattened form from disk. </p> <p>We track dirty state explicitly on the sleeve and it's managed in the layers above the WriteBuffer which only concerns itself with PersistentEntry instances and getting them to disk.</p> */ final class EntrySleeveImpl implements EntrySleeve, Identifiable, LinkedInstance { static final Logger theLogger = Logging.newLogger("org.dancres.blitz.entry.EntrySleeveImpl"); private transient SleeveState theState = new SleeveState(); private transient LinkedInstance theNext; private transient LinkedInstance thePrev; private transient PersistentEntry theEntry; private transient boolean isDirty; private EntrySleeveImpl() { } /** Use this constructor ONLY for EntrySleeveImpls that have never been written to disk. Typically this constructor is called for space::write() or recovery processing. */ EntrySleeveImpl(OID anId, MangledEntry anEntry, long anExpiry) { theEntry = new PersistentEntry(anId, anEntry, anExpiry); getState().set(SleeveState.NOT_ON_DISK | SleeveState.PINNED); } /** Take a byte[] as returned by flatten and re-constitute an EntrySleeveImpl from it. Use this constructor for rebuilding state saved to disk. */ EntrySleeveImpl(byte[] aBytes) { theEntry = new PersistentEntry(aBytes); } EntrySleeveImpl(PersistentEntry anEntry) { theEntry = anEntry; } /** @return a deep duplicate of this EntrySleeveImpl, including current SleeveState */ EntrySleeveImpl duplicate() { EntrySleeveImpl myDupe = new EntrySleeveImpl(); // Copy status flags myDupe.getState().set(getState().get()); myDupe.theEntry = new PersistentEntry(theEntry.flatten()); return myDupe; } byte[] flatten() { return theEntry.flatten(); } SleeveState getState() { synchronized(this) { if (theState == null) theState = new SleeveState(); } return theState; } public boolean isDeleted() { return getState().test(SleeveState.DELETED); } boolean hasExpired(long aTime) { return theEntry.hasExpired(aTime); } void setExpiry(long anExpiry) { theEntry.setExpiry(anExpiry); } long getExpiry() { return theEntry.getExpiry(); } public int getHashCodeForField(int anOffset) { return theEntry.getHashCodeForField(anOffset); } byte[] getKey() { return theEntry.getKey(); } public void setNext(LinkedInstance anInstance) { theNext = anInstance; } public void setPrev(LinkedInstance anInstance) { thePrev = anInstance; } public LinkedInstance getNext() { return theNext; } public LinkedInstance getPrev() { return thePrev; } /** Ensure we only ever hand out one ID whilst we are cached so, should someone wish to WeakRef the ID, it can. Id will be re-constituted from key only when we've been reloaded from disk causing theId to be null and flatten to have converted theId to a key made of bytes held in theKey. */ public OID getOID() { return theEntry.getOID(); } public Identifier getId() { return getOID(); } public String getType() { return getEntry().getType(); } public MangledEntry getEntry() { return theEntry.getEntry(); } public boolean equals(Object anObject) { if (anObject instanceof EntrySleeveImpl) { EntrySleeveImpl myOther = (EntrySleeveImpl) anObject; return myOther.getOID().equals(getOID()); } return false; } public String toString() { return "ES: " + getOID() + " - state: " + getState().toString(); } void markDirty() { isDirty = true; if (isDeleted()) { CacheIndexer.getIndexer(getType()).flushed(this); } } void clearDirty() { isDirty = false; } boolean isDirty() { return isDirty; } public static void main(String args[]) { try { EntryMangler myMangler = EntryMangler.getMangler(); DummyEntry myEntry = new DummyEntry("rhubarb"); MangledEntry myMangled = myMangler.mangle(myEntry); EntrySleeveImpl mySleeve = new EntrySleeveImpl(OIDFactory.newOID(10, 21), myMangled, Long.MAX_VALUE); byte[] myFlatten = mySleeve.flatten(); mySleeve = new EntrySleeveImpl(myFlatten); System.out.println(mySleeve.getEntry()); System.out.println(mySleeve.getOID()); mySleeve = new EntrySleeveImpl(myFlatten); mySleeve = mySleeve.duplicate(); myFlatten = mySleeve.flatten(); mySleeve = new EntrySleeveImpl(myFlatten); System.out.println(mySleeve.getEntry()); System.out.println(mySleeve.getOID()); } catch (Exception anE) { anE.printStackTrace(System.err); } } PersistentEntry getPersistentRep() { return theEntry; } }