Mercurial > hg > blitz_condensed
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3dc0c5604566 |
---|---|
1 package org.dancres.blitz.entry; | |
2 | |
3 import java.util.logging.Level; | |
4 | |
5 import org.dancres.blitz.mangler.MangledEntry; | |
6 import org.dancres.blitz.oid.OIDFactory; | |
7 import org.dancres.blitz.oid.OID; | |
8 import org.dancres.util.ObjectTransformer; | |
9 import org.dancres.util.BytePacker; | |
10 | |
11 /** | |
12 */ | |
13 public class PersistentEntry { | |
14 private static final int EXPIRY_LENGTH = 8; | |
15 | |
16 private static final int HASH_COUNT_LENGTH = 4; | |
17 | |
18 /* | |
19 All disk-structures are kept "simple" - this removes the need for | |
20 costly (in terms of time to do it and space on disk) serialization | |
21 */ | |
22 private byte[] theEntryBytes; | |
23 private long theExpiry; | |
24 private byte[] theKey; | |
25 private byte[] theHashCodes; | |
26 | |
27 private transient MangledEntry theEntry; | |
28 private transient OID theId; | |
29 | |
30 PersistentEntry(OID anId, MangledEntry anEntry, long anExpiry) { | |
31 theEntry = anEntry; | |
32 theId = anId; | |
33 theExpiry = anExpiry; | |
34 } | |
35 | |
36 PersistentEntry(byte[] aBytes) { | |
37 BytePacker myPacker = BytePacker.getMSBPacker(aBytes); | |
38 | |
39 theExpiry = myPacker.getLong(0); | |
40 theKey = myPacker.getArray(EXPIRY_LENGTH, OIDFactory.KEY_SIZE); | |
41 | |
42 int myHashCodesLength = | |
43 myPacker.getInt(EXPIRY_LENGTH + OIDFactory.KEY_SIZE); | |
44 | |
45 theHashCodes = myPacker.getArray(EXPIRY_LENGTH + OIDFactory.KEY_SIZE + | |
46 HASH_COUNT_LENGTH, myHashCodesLength); | |
47 | |
48 int myRemainder = aBytes.length - EXPIRY_LENGTH - OIDFactory.KEY_SIZE - | |
49 myHashCodesLength - HASH_COUNT_LENGTH; | |
50 | |
51 theEntryBytes = myPacker.getArray(EXPIRY_LENGTH + OIDFactory.KEY_SIZE + | |
52 myHashCodesLength + | |
53 HASH_COUNT_LENGTH, | |
54 myRemainder); | |
55 } | |
56 | |
57 /** | |
58 * Convert EntrySleeveImpl into a byte representation suitable for | |
59 * saving to disk. | |
60 */ | |
61 byte[] flatten() { | |
62 if (theEntryBytes == null) { | |
63 try { | |
64 theEntryBytes = ObjectTransformer.toByte(theEntry); | |
65 } catch (Exception anE) { | |
66 EntrySleeveImpl.theLogger.log( | |
67 Level.SEVERE, "Couldn't flatten entry!", anE); | |
68 } | |
69 } | |
70 | |
71 byte[] myArray = new byte[theEntryBytes.length + OIDFactory.KEY_SIZE | |
72 + EXPIRY_LENGTH + HASH_COUNT_LENGTH + | |
73 getHashCodes().length]; | |
74 | |
75 BytePacker myPacker = BytePacker.getMSBPacker(myArray); | |
76 myPacker.putLong(theExpiry, 0); | |
77 myPacker.putArray(getKey(), EXPIRY_LENGTH); | |
78 myPacker.putInt(getHashCodes().length, EXPIRY_LENGTH + | |
79 OIDFactory.KEY_SIZE); | |
80 myPacker.putArray(getHashCodes(), EXPIRY_LENGTH + OIDFactory.KEY_SIZE + | |
81 HASH_COUNT_LENGTH); | |
82 myPacker.putArray(theEntryBytes, EXPIRY_LENGTH + OIDFactory.KEY_SIZE + | |
83 HASH_COUNT_LENGTH + getHashCodes().length); | |
84 | |
85 return myArray; | |
86 } | |
87 | |
88 PersistentEntry duplicate() { | |
89 return new PersistentEntry(getOID(), getEntry(), getExpiry()); | |
90 } | |
91 | |
92 private synchronized byte[] getHashCodes() { | |
93 /* | |
94 Should only happen if we've been newly created and never been | |
95 flattened | |
96 */ | |
97 if (theHashCodes == null) { | |
98 MangledEntry myEntry = getEntry(); | |
99 | |
100 theHashCodes = new byte[myEntry.getFields().length * 4]; | |
101 | |
102 BytePacker myPacker = BytePacker.getMSBPacker(theHashCodes); | |
103 | |
104 for (int i = 0; i < myEntry.getFields().length; i++) { | |
105 myPacker.putInt(myEntry.getField(i).hashCode(), i * 4); | |
106 } | |
107 } | |
108 | |
109 return theHashCodes; | |
110 } | |
111 | |
112 synchronized int getHashCodeForField(int anOffset) { | |
113 BytePacker myPacker = BytePacker.getMSBPacker(getHashCodes()); | |
114 | |
115 return myPacker.getInt(anOffset * 4); | |
116 } | |
117 | |
118 synchronized MangledEntry getEntry() { | |
119 if (theEntry == null) { | |
120 try { | |
121 theEntry = | |
122 (MangledEntry) ObjectTransformer.toObject(theEntryBytes); | |
123 } catch (Exception anE) { | |
124 EntrySleeveImpl.theLogger.log( | |
125 Level.SEVERE, "Couldn't recover entry", anE); | |
126 } | |
127 } | |
128 | |
129 return theEntry; | |
130 } | |
131 | |
132 synchronized byte[] getKey() { | |
133 | |
134 /* | |
135 Should only happen if we've been newly created and never been | |
136 flattened | |
137 */ | |
138 if (theKey == null) | |
139 theKey = OIDFactory.getKey(theId); | |
140 | |
141 return theKey; | |
142 } | |
143 | |
144 synchronized OID getOID() { | |
145 if (theId == null) { | |
146 theId = OIDFactory.newOID(theKey); | |
147 } | |
148 | |
149 return theId; | |
150 } | |
151 | |
152 synchronized boolean hasExpired(long aTime) { | |
153 return (theExpiry < aTime); | |
154 } | |
155 | |
156 synchronized void setExpiry(long anExpiry) { | |
157 theExpiry = anExpiry; | |
158 } | |
159 | |
160 synchronized long getExpiry() { | |
161 return theExpiry; | |
162 } | |
163 } |