comparison src/org/dancres/blitz/entry/EntrySleeveImpl.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.Logger;
4
5 import org.dancres.struct.LinkedInstance;
6
7 import org.dancres.blitz.mangler.MangledEntry;
8 import org.dancres.blitz.mangler.EntryMangler;
9
10 import org.dancres.blitz.oid.OID;
11 import org.dancres.blitz.oid.OIDFactory;
12
13 import org.dancres.blitz.cache.Identifiable;
14 import org.dancres.blitz.cache.Identifier;
15
16 import org.dancres.blitz.test.DummyEntry;
17
18 import org.dancres.blitz.Logging;
19 import org.dancres.blitz.entry.ci.CacheIndexer;
20
21 /**
22 <p> The in-memory representation of an Entry (as in record sleeve) -
23 includes transient caching state as well as persistent information. </p>
24
25 <p> Call flatten to render an instance into a byte[] suitable for disk
26 storage and invoke the constructor EntrySleeveImpl(byte[]) to reconstitute
27 the flattened form from disk. </p>
28
29 <p>We track dirty state explicitly on the sleeve and it's managed in the
30 layers above the WriteBuffer which only concerns itself with PersistentEntry
31 instances and getting them to disk.</p>
32 */
33 final class EntrySleeveImpl implements EntrySleeve, Identifiable,
34 LinkedInstance {
35
36 static final Logger theLogger =
37 Logging.newLogger("org.dancres.blitz.entry.EntrySleeveImpl");
38
39 private transient SleeveState theState = new SleeveState();
40
41 private transient LinkedInstance theNext;
42 private transient LinkedInstance thePrev;
43
44 private transient PersistentEntry theEntry;
45
46 private transient boolean isDirty;
47
48 private EntrySleeveImpl() {
49 }
50
51 /**
52 Use this constructor ONLY for EntrySleeveImpls that have never been
53 written to disk. Typically this constructor is called for
54 space::write() or recovery processing.
55 */
56 EntrySleeveImpl(OID anId, MangledEntry anEntry, long anExpiry) {
57 theEntry = new PersistentEntry(anId, anEntry, anExpiry);
58 getState().set(SleeveState.NOT_ON_DISK | SleeveState.PINNED);
59 }
60
61 /**
62 Take a byte[] as returned by flatten and re-constitute an
63 EntrySleeveImpl from it. Use this constructor for rebuilding state
64 saved to disk.
65 */
66 EntrySleeveImpl(byte[] aBytes) {
67 theEntry = new PersistentEntry(aBytes);
68 }
69
70 EntrySleeveImpl(PersistentEntry anEntry) {
71 theEntry = anEntry;
72 }
73
74 /**
75 @return a deep duplicate of this EntrySleeveImpl, including current
76 SleeveState
77 */
78 EntrySleeveImpl duplicate() {
79 EntrySleeveImpl myDupe = new EntrySleeveImpl();
80
81 // Copy status flags
82 myDupe.getState().set(getState().get());
83
84 myDupe.theEntry = new PersistentEntry(theEntry.flatten());
85
86 return myDupe;
87 }
88
89 byte[] flatten() {
90 return theEntry.flatten();
91 }
92
93 SleeveState getState() {
94 synchronized(this) {
95 if (theState == null)
96 theState = new SleeveState();
97 }
98
99 return theState;
100 }
101
102 public boolean isDeleted() {
103 return getState().test(SleeveState.DELETED);
104 }
105
106 boolean hasExpired(long aTime) {
107 return theEntry.hasExpired(aTime);
108 }
109
110 void setExpiry(long anExpiry) {
111 theEntry.setExpiry(anExpiry);
112 }
113
114 long getExpiry() {
115 return theEntry.getExpiry();
116 }
117
118 public int getHashCodeForField(int anOffset) {
119 return theEntry.getHashCodeForField(anOffset);
120 }
121
122 byte[] getKey() {
123 return theEntry.getKey();
124 }
125
126 public void setNext(LinkedInstance anInstance) {
127 theNext = anInstance;
128 }
129
130 public void setPrev(LinkedInstance anInstance) {
131 thePrev = anInstance;
132 }
133
134 public LinkedInstance getNext() {
135 return theNext;
136 }
137
138 public LinkedInstance getPrev() {
139 return thePrev;
140 }
141
142 /**
143 Ensure we only ever hand out one ID whilst we are cached so, should
144 someone wish to WeakRef the ID, it can. Id will be re-constituted
145 from key only when we've been reloaded from disk causing theId to
146 be null and flatten to have converted theId to a key made of bytes held
147 in theKey.
148 */
149 public OID getOID() {
150 return theEntry.getOID();
151 }
152
153 public Identifier getId() {
154 return getOID();
155 }
156
157 public String getType() {
158 return getEntry().getType();
159 }
160
161 public MangledEntry getEntry() {
162 return theEntry.getEntry();
163 }
164
165 public boolean equals(Object anObject) {
166 if (anObject instanceof EntrySleeveImpl) {
167 EntrySleeveImpl myOther = (EntrySleeveImpl) anObject;
168
169 return myOther.getOID().equals(getOID());
170 }
171
172 return false;
173 }
174
175 public String toString() {
176 return "ES: " + getOID() + " - state: " + getState().toString();
177
178 }
179
180 void markDirty() {
181 isDirty = true;
182
183 if (isDeleted()) {
184 CacheIndexer.getIndexer(getType()).flushed(this);
185 }
186 }
187
188 void clearDirty() {
189 isDirty = false;
190 }
191
192 boolean isDirty() {
193 return isDirty;
194 }
195
196 public static void main(String args[]) {
197 try {
198 EntryMangler myMangler = EntryMangler.getMangler();
199
200 DummyEntry myEntry = new DummyEntry("rhubarb");
201
202 MangledEntry myMangled = myMangler.mangle(myEntry);
203
204 EntrySleeveImpl mySleeve =
205 new EntrySleeveImpl(OIDFactory.newOID(10, 21), myMangled,
206 Long.MAX_VALUE);
207
208 byte[] myFlatten = mySleeve.flatten();
209
210 mySleeve = new EntrySleeveImpl(myFlatten);
211
212 System.out.println(mySleeve.getEntry());
213
214 System.out.println(mySleeve.getOID());
215
216 mySleeve = new EntrySleeveImpl(myFlatten);
217
218 mySleeve = mySleeve.duplicate();
219
220 myFlatten = mySleeve.flatten();
221
222 mySleeve = new EntrySleeveImpl(myFlatten);
223
224 System.out.println(mySleeve.getEntry());
225
226 System.out.println(mySleeve.getOID());
227
228 } catch (Exception anE) {
229 anE.printStackTrace(System.err);
230 }
231 }
232
233 PersistentEntry getPersistentRep() {
234 return theEntry;
235 }
236 }