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;
+    }
+}