comparison src/org/dancres/blitz/entry/EntryRepositoryFactory.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 import java.io.InputStream;
5 import java.io.InputStreamReader;
6 import java.io.Serializable;
7
8 import java.util.Map;
9 import java.util.HashMap;
10 import java.util.Collection;
11
12 import java.util.logging.*;
13
14 import net.jini.config.ConfigurationFile;
15 import net.jini.config.Configuration;
16 import net.jini.config.ConfigurationException;
17
18 import org.dancres.blitz.disk.Disk;
19 import org.dancres.blitz.disk.Syncable;
20
21 import org.dancres.blitz.config.ConfigurationFactory;
22
23 import org.dancres.blitz.Logging;
24
25 import org.dancres.blitz.lease.LeaseReaper;
26
27 import org.dancres.blitz.txn.TxnManager;
28
29 import org.prevayler.SnapshotContributor;
30
31 public class EntryRepositoryFactory implements Syncable, SnapshotContributor {
32 private static final String LOG_COUNTS = "logCounts";
33
34 private static LeaseReaper theReaper;
35
36 private static final Logger theLogger =
37 Logging.newLogger("org.dancres.blitz.entry.EntryRepositoryFactory");
38
39 private static EntryRepositoryFactory theReposFactory =
40 new EntryRepositoryFactory();
41
42 private Map theRepositories = new HashMap();
43
44 private boolean logCountOnBoot;
45 private boolean haveRegisteredForSnapshot = false;
46 private Object theLogLock = new Object();
47
48 private EntryRepositoryFactory() {
49 try {
50 long myReapTime =
51 ((Long)
52 ConfigurationFactory.getEntry("leaseReapInterval",
53 long.class,
54 new Long(0))).longValue();
55
56 InputStream myStream =
57 getClass().getResourceAsStream("filters.properties");
58
59 if (myStream == null)
60 throw new RuntimeException("Reap filters are missing!");
61 else {
62 Configuration myConfig =
63 new ConfigurationFile(new InputStreamReader(myStream),
64 null);
65
66 theReaper = new LeaseReaper(myConfig, myReapTime);
67 }
68
69 } catch (Exception anE) {
70 theLogger.log(Level.SEVERE, "Failed to init reaper", anE);
71 throw new RuntimeException("Critical failure starting reaper");
72 }
73
74 /*
75 Figure out if instance counts should be put into checkpoints and
76 log files. Note we don't actually do anymore work here. The
77 remainder is done using barrier methods in this class and in
78 EntryReposImpl.
79
80 EntryReposImpl is responsible for trapping "first use" and emitting
81 a record into the log.
82
83 EntryRepositoryFactory is responsible for placing similar records
84 into the checkpoint snapshot.
85 */
86 try {
87 logCountOnBoot =
88 ((Boolean)
89 ConfigurationFactory.getEntry(LOG_COUNTS,
90 Boolean.class,
91 new Boolean(false))).booleanValue();
92
93 } catch (ConfigurationException aCE) {
94 theLogger.log(Level.SEVERE,
95 "Failed to load logInstanceCounts setting", aCE);
96 }
97
98 Disk.add(this);
99 }
100
101 public static void reap() {
102 theReaper.reap();
103 }
104
105 public static EntryRepositoryFactory get() {
106 /*
107 Anyone wishing to access the factory's functions must go through
108 this method first so it's the ideal place to barrier for registering
109 with TxnManager to supply instance count records to checkpoints.
110 */
111 theReposFactory.registerBarrier();
112
113 return theReposFactory;
114 }
115
116 /*
117 Unfortunately, we may be instantiated during recovery at which point
118 the transaction manager is not available so we must stave off
119 registration of our SnapshotContributor until recovery is completed.
120 */
121 private void registerBarrier() {
122 synchronized(theLogLock) {
123 if (!logCountOnBoot || TxnManager.get().isRecovery())
124 return;
125 else if (!haveRegisteredForSnapshot) {
126 /*
127 If we have to log counts at boot we also need to log them at
128 checkpoints - register SnapshotContributor
129 */
130 TxnManager.get().add(this);
131 haveRegisteredForSnapshot = true;
132 }
133 }
134 }
135
136 public Serializable getContribution() {
137 EntryReposImpl[] myRepos = getRepositoriesSnapshot();
138
139 InstanceCheckpoint myContribution = new InstanceCheckpoint();
140
141 for (int i = 0; i < myRepos.length; i++) {
142 myContribution.add(myRepos[i].getType(),
143 myRepos[i].getTotalLiveEntries());
144 }
145
146 return myContribution;
147 }
148
149 public boolean isDebugLogging() {
150 return logCountOnBoot;
151 }
152
153 /**
154 Locate the EntryRepository instance for the specified type, creating
155 a new, empty one, if it's not already present
156 */
157 public synchronized EntryRepository get(String aType)
158 throws IOException {
159 EntryReposImpl myRepos = (EntryReposImpl) theRepositories.get(aType);
160
161 if (myRepos == null) {
162 Storage myStore = StorageFactory.getStorage(aType);
163 myStore.init(false);
164
165 myRepos = new EntryReposImpl(myStore);
166 theRepositories.put(aType, myRepos);
167 }
168
169 return myRepos;
170 }
171
172 /**
173 Locate the EntryRepository instance for the specified type.
174 If it doesn't already exist, return <code>null</code>.
175 */
176 public synchronized EntryRepository find(String aType)
177 throws IOException {
178
179 EntryReposImpl myRepos = (EntryReposImpl) theRepositories.get(aType);
180
181 if (myRepos == null) {
182 Storage myStore = StorageFactory.getStorage(aType);
183
184 if (myStore.init(true)) {
185 myRepos = new EntryReposImpl(myStore);
186 theRepositories.put(aType, myRepos);
187 }
188 }
189
190 return myRepos;
191 }
192
193 synchronized EntryReposRecovery getAdmin(String aType)
194 throws IOException {
195 return (EntryReposRecovery) get(aType);
196 }
197
198 public void sync() throws Exception {
199 EntryReposImpl[] myRepositories = getRepositoriesSnapshot();
200
201 for (int i = 0; i < myRepositories.length; i++) {
202 myRepositories[i].sync();
203 }
204 }
205
206 public void close() throws Exception {
207 EntryReposImpl[] myRepositories = getRepositoriesSnapshot();
208
209 for (int i = 0; i < myRepositories.length; i++) {
210 myRepositories[i].close();
211 }
212 }
213
214 private EntryReposImpl[] getRepositoriesSnapshot() {
215 synchronized(this) {
216 Collection myRepositories = theRepositories.values();
217
218 EntryReposImpl[] myResult =
219 new EntryReposImpl[myRepositories.size()];
220
221 return (EntryReposImpl[]) myRepositories.toArray(myResult);
222 }
223 }
224
225 public void deleteAllEntrys() throws IOException {
226 EntryReposImpl[] myRepos = getRepositoriesSnapshot();
227
228 for (int i = 0; i < myRepos.length; i++) {
229 myRepos[i].deleteAllEntrys();
230 }
231 }
232
233 public void deleteAllRepos() throws IOException {
234 // For each repository, close them and invoke delete
235 synchronized(this) {
236 EntryReposImpl[] myRepos = getRepositoriesSnapshot();
237
238 for (int i = 0; i < myRepos.length; i++) {
239 myRepos[i].close();
240 myRepos[i].delete();
241 }
242
243 theRepositories.clear();
244 }
245 }
246
247 static LeaseReaper getReaper() {
248 return theReaper;
249 }
250 }