Mercurial > hg > blitz_condensed
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 } |