Mercurial > hg > blitz_condensed
comparison src/org/dancres/blitz/entry/EntryReposImpl.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.io.IOException; | |
4 | |
5 import java.util.logging.*; | |
6 | |
7 import net.jini.config.ConfigurationException; | |
8 | |
9 import org.dancres.blitz.mangler.MangledField; | |
10 import org.dancres.blitz.mangler.MangledEntry; | |
11 | |
12 import org.dancres.blitz.Logging; | |
13 import org.dancres.blitz.config.EntryConstraints; | |
14 | |
15 import org.dancres.blitz.oid.OID; | |
16 | |
17 import org.dancres.blitz.arc.CacheBlockDescriptor; | |
18 import org.dancres.blitz.arc.RecoverySummary; | |
19 | |
20 import org.dancres.blitz.lease.Reapable; | |
21 import org.dancres.blitz.lease.ReapFilter; | |
22 | |
23 import org.dancres.blitz.txn.TxnManager; | |
24 | |
25 class EntryReposImpl implements EntryReposRecovery, Reapable { | |
26 private static Logger theLogger = | |
27 Logging.newLogger("org.dancres.disk.EntryRepository"); | |
28 | |
29 private Storage theStore; | |
30 private SleeveCache theSleeveCache; | |
31 | |
32 private boolean haveLoggedCount = false; | |
33 | |
34 private EntryConstraints theConstraints; | |
35 | |
36 EntryReposImpl(Storage aStore) throws IOException { | |
37 try { | |
38 theConstraints = EntryConstraints.getConstraints(aStore.getType()); | |
39 } catch (ConfigurationException aCE) { | |
40 IOException myIOE = new IOException("Couldn't load constraints"); | |
41 myIOE.initCause(aCE); | |
42 throw myIOE; | |
43 } | |
44 | |
45 theStore = aStore; | |
46 theSleeveCache = new SleeveCache(theStore); | |
47 | |
48 // Don't configure for reaping if it's configured off | |
49 if (EntryRepositoryFactory.getReaper().isActive()) | |
50 EntryRepositoryFactory.getReaper().add(this); | |
51 } | |
52 | |
53 /** | |
54 This method is designed to log a record of the number of instances of | |
55 this repository's type the first time the repository is updated. | |
56 | |
57 It's expected that checkpoints will store instance counts for all | |
58 repositories loaded at that time. This code ensures that any | |
59 repositories that come into being between checkpoints also have an | |
60 appropriate record to which following logged actions can be applied. | |
61 | |
62 We only need to log the record once because at the next checkpoint | |
63 it's counts will be in the checkpoint record. This step is the | |
64 responsibility of <code>EntryRepositoryFactory</code> | |
65 */ | |
66 private void logInstanceBarrier() { | |
67 if (TxnManager.get().isRecovery()) { | |
68 return; | |
69 } | |
70 | |
71 if (EntryRepositoryFactory.get().isDebugLogging()) { | |
72 synchronized(this) { | |
73 if (haveLoggedCount) | |
74 return; | |
75 | |
76 try { | |
77 /* | |
78 We must use the live stats for this count as the | |
79 storage's count may not be up-to-date due to actions | |
80 performed during recovery still sitting in cache. | |
81 I _think_ the fact that we checkpoint should prevent | |
82 this from actually happening but better safe than sorry. | |
83 | |
84 We only attempt to log this - we can fail due to being | |
85 blocked on the transaction log lock for too long. | |
86 If that has happened, chances are we've done a checkpoint | |
87 and a record will have been emitted anyways. | |
88 */ | |
89 TxnManager.get().tryLog(new CountAction(theStore.getType(), | |
90 theSleeveCache.getCounters().getInstanceCount()), 100); | |
91 } catch (Exception anE) { | |
92 theLogger.log(Level.SEVERE, "Failed to log instance count", | |
93 anE); | |
94 } | |
95 | |
96 haveLoggedCount = true; | |
97 } | |
98 } | |
99 } | |
100 | |
101 public String getType() { | |
102 return theStore.getName(); | |
103 } | |
104 | |
105 public int getTotalStoredEntries() throws IOException { | |
106 return theStore.getNumEntries(); | |
107 } | |
108 | |
109 public int getTotalLiveEntries() { | |
110 return theSleeveCache.getCounters().getInstanceCount(); | |
111 } | |
112 | |
113 public void reap(ReapFilter aFilter) { | |
114 logInstanceBarrier(); | |
115 | |
116 try { | |
117 theStore.bringOutTheDead(new CleanerImpl(theSleeveCache, aFilter)); | |
118 } catch (IOException anIOE) { | |
119 theLogger.log(Level.SEVERE, "Couldn't bring out the dead", | |
120 anIOE); | |
121 } | |
122 } | |
123 | |
124 public boolean renew(OID aOID, long anExpiry) throws IOException { | |
125 logInstanceBarrier(); | |
126 | |
127 return theSleeveCache.renew(aOID, anExpiry); | |
128 } | |
129 | |
130 public boolean cancel(OID aOID) throws IOException { | |
131 logInstanceBarrier(); | |
132 | |
133 return theSleeveCache.cancel(aOID); | |
134 } | |
135 | |
136 /* | |
137 These methods are only used during commit/abort and thus there will | |
138 have been activity previously generating a log entry for instance counts. | |
139 | |
140 If there hasn't been activity, this operation is coming from the log | |
141 file which means there's been activity in the previous run and so | |
142 either we have an instance count in the checkpoint record or we'll have | |
143 logged one ourselves as part of activity prior to logging the transaction | |
144 which has generated these operations. | |
145 */ | |
146 public CacheBlockDescriptor load(OID aOID) throws IOException { | |
147 return theSleeveCache.load(aOID); | |
148 } | |
149 | |
150 public void flush(CacheBlockDescriptor aCBD) throws IOException { | |
151 theSleeveCache.forceSync(aCBD); | |
152 } | |
153 | |
154 CacheBlockDescriptor add(EntrySleeveImpl aSleeve) throws IOException { | |
155 return theSleeveCache.add(aSleeve); | |
156 } | |
157 | |
158 public RecoverySummary recover(EntrySleeveImpl aSleeve) | |
159 throws IOException { | |
160 return theSleeveCache.recover(aSleeve); | |
161 } | |
162 | |
163 public Counters getCounters() { | |
164 return theSleeveCache.getCounters(); | |
165 } | |
166 | |
167 /* | |
168 These methods indicate new activity and we want to make sure we have | |
169 an up-to-date instance count | |
170 */ | |
171 public void write(MangledEntry anEntry, long anExpiry, | |
172 WriteEscort anEscort) | |
173 throws IOException { | |
174 logInstanceBarrier(); | |
175 theSleeveCache.write(anEntry, anExpiry, anEscort); | |
176 } | |
177 | |
178 public void find(MangledEntry aTemplate, SearchVisitor aVisitor) | |
179 throws IOException { | |
180 logInstanceBarrier(); | |
181 theSleeveCache.find(aTemplate, aVisitor); | |
182 } | |
183 | |
184 public boolean find(SearchVisitor aVisitor, OID aOID, MangledEntry aPreload) | |
185 throws IOException { | |
186 logInstanceBarrier(); | |
187 return theSleeveCache.find(aVisitor, aOID, aPreload); | |
188 } | |
189 | |
190 public LongtermOffer getOffer(OID anOID) throws IOException { | |
191 logInstanceBarrier(); | |
192 return theSleeveCache.getOffer(anOID); | |
193 } | |
194 | |
195 public EntryConstraints getConstraints() { | |
196 return theConstraints; | |
197 } | |
198 | |
199 public void setFields(MangledField[] aListOfFields) | |
200 throws IOException { | |
201 theStore.setFields(aListOfFields); | |
202 } | |
203 | |
204 public boolean noSchemaDefined() { | |
205 return theStore.noSchemaDefined(); | |
206 } | |
207 | |
208 public void addSubtype(String aType) throws IOException { | |
209 theStore.addSubtype(aType); | |
210 } | |
211 | |
212 public String[] getSubtypes() { | |
213 return theStore.getSubtypes(); | |
214 } | |
215 | |
216 void deleteAllEntrys() throws IOException { | |
217 theSleeveCache.deleteAll(); | |
218 } | |
219 | |
220 void delete() throws IOException { | |
221 theStore.delete(); | |
222 } | |
223 | |
224 void sync() throws IOException { | |
225 theLogger.log(Level.FINE, "Syncing to disk: " + theStore.getType()); | |
226 // System.err.println("Syncing to disk: " + theStore.getType()); | |
227 theSleeveCache.sync(); | |
228 } | |
229 | |
230 void close() throws IOException { | |
231 theLogger.log(Level.FINE, "Closing: " + theStore.getType()); | |
232 // System.err.println("Closing: " + theStore.getType()); | |
233 theSleeveCache.close(); | |
234 theStore.close(); | |
235 } | |
236 | |
237 public String toString() { | |
238 return "EntryReposImpl: " + theStore.getType() + ", " | |
239 + theStore.getClass(); | |
240 } | |
241 } |