Mercurial > hg > blitz_condensed
diff src/org/dancres/blitz/entry/PersistentEntry.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/dancres/blitz/entry/PersistentEntry.java Sat Mar 21 11:00:06 2009 +0000 @@ -0,0 +1,163 @@ +package org.dancres.blitz.entry; + +import java.util.logging.Level; + +import org.dancres.blitz.mangler.MangledEntry; +import org.dancres.blitz.oid.OIDFactory; +import org.dancres.blitz.oid.OID; +import org.dancres.util.ObjectTransformer; +import org.dancres.util.BytePacker; + +/** + */ +public class PersistentEntry { + private static final int EXPIRY_LENGTH = 8; + + private static final int HASH_COUNT_LENGTH = 4; + + /* + All disk-structures are kept "simple" - this removes the need for + costly (in terms of time to do it and space on disk) serialization + */ + private byte[] theEntryBytes; + private long theExpiry; + private byte[] theKey; + private byte[] theHashCodes; + + private transient MangledEntry theEntry; + private transient OID theId; + + PersistentEntry(OID anId, MangledEntry anEntry, long anExpiry) { + theEntry = anEntry; + theId = anId; + theExpiry = anExpiry; + } + + PersistentEntry(byte[] aBytes) { + BytePacker myPacker = BytePacker.getMSBPacker(aBytes); + + theExpiry = myPacker.getLong(0); + theKey = myPacker.getArray(EXPIRY_LENGTH, OIDFactory.KEY_SIZE); + + int myHashCodesLength = + myPacker.getInt(EXPIRY_LENGTH + OIDFactory.KEY_SIZE); + + theHashCodes = myPacker.getArray(EXPIRY_LENGTH + OIDFactory.KEY_SIZE + + HASH_COUNT_LENGTH, myHashCodesLength); + + int myRemainder = aBytes.length - EXPIRY_LENGTH - OIDFactory.KEY_SIZE - + myHashCodesLength - HASH_COUNT_LENGTH; + + theEntryBytes = myPacker.getArray(EXPIRY_LENGTH + OIDFactory.KEY_SIZE + + myHashCodesLength + + HASH_COUNT_LENGTH, + myRemainder); + } + + /** + * Convert EntrySleeveImpl into a byte representation suitable for + * saving to disk. + */ + byte[] flatten() { + if (theEntryBytes == null) { + try { + theEntryBytes = ObjectTransformer.toByte(theEntry); + } catch (Exception anE) { + EntrySleeveImpl.theLogger.log( + Level.SEVERE, "Couldn't flatten entry!", anE); + } + } + + byte[] myArray = new byte[theEntryBytes.length + OIDFactory.KEY_SIZE + + EXPIRY_LENGTH + HASH_COUNT_LENGTH + + getHashCodes().length]; + + BytePacker myPacker = BytePacker.getMSBPacker(myArray); + myPacker.putLong(theExpiry, 0); + myPacker.putArray(getKey(), EXPIRY_LENGTH); + myPacker.putInt(getHashCodes().length, EXPIRY_LENGTH + + OIDFactory.KEY_SIZE); + myPacker.putArray(getHashCodes(), EXPIRY_LENGTH + OIDFactory.KEY_SIZE + + HASH_COUNT_LENGTH); + myPacker.putArray(theEntryBytes, EXPIRY_LENGTH + OIDFactory.KEY_SIZE + + HASH_COUNT_LENGTH + getHashCodes().length); + + return myArray; + } + + PersistentEntry duplicate() { + return new PersistentEntry(getOID(), getEntry(), getExpiry()); + } + + private synchronized byte[] getHashCodes() { + /* + Should only happen if we've been newly created and never been + flattened + */ + if (theHashCodes == null) { + MangledEntry myEntry = getEntry(); + + theHashCodes = new byte[myEntry.getFields().length * 4]; + + BytePacker myPacker = BytePacker.getMSBPacker(theHashCodes); + + for (int i = 0; i < myEntry.getFields().length; i++) { + myPacker.putInt(myEntry.getField(i).hashCode(), i * 4); + } + } + + return theHashCodes; + } + + synchronized int getHashCodeForField(int anOffset) { + BytePacker myPacker = BytePacker.getMSBPacker(getHashCodes()); + + return myPacker.getInt(anOffset * 4); + } + + synchronized MangledEntry getEntry() { + if (theEntry == null) { + try { + theEntry = + (MangledEntry) ObjectTransformer.toObject(theEntryBytes); + } catch (Exception anE) { + EntrySleeveImpl.theLogger.log( + Level.SEVERE, "Couldn't recover entry", anE); + } + } + + return theEntry; + } + + synchronized byte[] getKey() { + + /* + Should only happen if we've been newly created and never been + flattened + */ + if (theKey == null) + theKey = OIDFactory.getKey(theId); + + return theKey; + } + + synchronized OID getOID() { + if (theId == null) { + theId = OIDFactory.newOID(theKey); + } + + return theId; + } + + synchronized boolean hasExpired(long aTime) { + return (theExpiry < aTime); + } + + synchronized void setExpiry(long anExpiry) { + theExpiry = anExpiry; + } + + synchronized long getExpiry() { + return theExpiry; + } +}