Mercurial > hg > blitz_condensed
comparison src/org/dancres/blitz/oid/AllocatorImpl.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.oid; | |
2 | |
3 import java.io.Serializable; | |
4 import java.io.IOException; | |
5 | |
6 import java.util.Random; | |
7 import java.util.ArrayList; | |
8 | |
9 import java.util.logging.*; | |
10 | |
11 import org.dancres.blitz.disk.DiskTxn; | |
12 import org.dancres.blitz.disk.Disk; | |
13 import org.dancres.blitz.disk.Syncable; | |
14 | |
15 import org.dancres.blitz.meta.Registry; | |
16 import org.dancres.blitz.meta.RegistryAccessor; | |
17 import org.dancres.blitz.meta.RegistryFactory; | |
18 import org.dancres.blitz.meta.MetaIterator; | |
19 import org.dancres.blitz.meta.MetaEntry; | |
20 import org.dancres.blitz.meta.Initializer; | |
21 | |
22 import org.dancres.blitz.Logging; | |
23 import org.dancres.blitz.BootContext; | |
24 | |
25 import org.dancres.blitz.txn.UnsyncdOps; | |
26 | |
27 /** | |
28 <p>Provides an OID allocation service using upto n zones where n is | |
29 the maximum number of zones as specified at construction time.</p> | |
30 | |
31 <p>AllocatorImpl's are checkpointed regularly as part of other checkpointing | |
32 operations. Thus, they can only be out of date by the maximum number of | |
33 operations possible between checkpoints so, on reload, a corrective jump | |
34 is applied determined by that maximum</p> | |
35 */ | |
36 class AllocatorImpl implements AllocatorAdmin, Syncable { | |
37 static Logger theLogger = | |
38 Logging.newLogger("org.dancres.blitz.oid.Allocator"); | |
39 | |
40 private OIDAllocator[] theAllocators; | |
41 private Random theAllocatorChooser = new Random(); | |
42 private int theMaxZones; | |
43 | |
44 private Registry theMetaData; | |
45 private String theName; | |
46 | |
47 AllocatorImpl(String aName, int anAllocSpaceSize) throws IOException { | |
48 theLogger.log(Level.INFO, "Allocator: " + aName); | |
49 | |
50 theMetaData = | |
51 RegistryFactory.get(getDbNameFor(aName), | |
52 new OIDInitializer(anAllocSpaceSize)); | |
53 theName = aName; | |
54 theMaxZones = anAllocSpaceSize; | |
55 theAllocators = new OIDAllocator[theMaxZones]; | |
56 | |
57 UnsyncdOps myBarrier = (UnsyncdOps) | |
58 BootContext.get(UnsyncdOps.class); | |
59 | |
60 if (myBarrier != null) { | |
61 theLogger.log(Level.INFO, theName + ":Resync'ing allocators: " + | |
62 myBarrier.getOpsSinceLastCheckpoint()); | |
63 } | |
64 | |
65 ArrayList myAllocators = loadAllocators(); | |
66 | |
67 /* | |
68 Make sure OIDAllocators go back into the correct slots within | |
69 the array. It's possible that they will have been read out of order | |
70 from the underlying storage | |
71 */ | |
72 long myMin = Long.MAX_VALUE; | |
73 | |
74 for (int i = 0; i < theMaxZones; i++) { | |
75 OIDAllocator myAllocator = (OIDAllocator) myAllocators.get(i); | |
76 theAllocators[myAllocator.getId()] = myAllocator; | |
77 | |
78 /* | |
79 Do we need to resync the oid allocator? | |
80 */ | |
81 if (myBarrier != null) { | |
82 long myNext = | |
83 myAllocator.jump(myBarrier.getOpsSinceLastCheckpoint()); | |
84 | |
85 if (myNext < myMin) | |
86 myMin = myNext; | |
87 } | |
88 } | |
89 | |
90 if (myBarrier != null) { | |
91 try { | |
92 theLogger.log(Level.INFO, "Minimum allocator oid for " + | |
93 theName + ": " + myMin); | |
94 sync(); | |
95 } catch (Exception anE) { | |
96 theLogger.log(Level.SEVERE, theName + | |
97 ":Failed to sync against barrier", | |
98 anE); | |
99 throw new IOException("Failed to sync against barrier"); | |
100 } | |
101 } | |
102 | |
103 Disk.add(this); | |
104 } | |
105 | |
106 private ArrayList loadAllocators() throws IOException { | |
107 ArrayList myAllocators = new ArrayList(); | |
108 | |
109 DiskTxn myStandalone = DiskTxn.newStandalone(); | |
110 | |
111 MetaIterator myAllocatorStates = | |
112 theMetaData.getAccessor(myStandalone).readAll(); | |
113 | |
114 MetaEntry myEntry; | |
115 | |
116 while ((myEntry = myAllocatorStates.fetch()) != null) { | |
117 OIDAllocator myAllocator = new OIDAllocator(); | |
118 myAllocator.setState(myEntry.getData()); | |
119 myAllocators.add(myAllocator); | |
120 } | |
121 | |
122 myAllocatorStates.release(); | |
123 myStandalone.commit(); | |
124 | |
125 return myAllocators; | |
126 } | |
127 | |
128 /** | |
129 Call this within an active DiskTxn | |
130 */ | |
131 public OID getNextId() throws IOException { | |
132 OIDAllocator myAllocator = | |
133 theAllocators[theAllocatorChooser.nextInt(theMaxZones)]; | |
134 | |
135 OID myID = null; | |
136 | |
137 synchronized(myAllocator) { | |
138 myID = myAllocator.newOID(); | |
139 } | |
140 | |
141 return myID; | |
142 } | |
143 | |
144 public int getMaxZoneId() { | |
145 return theMaxZones; | |
146 } | |
147 | |
148 public void sync() throws Exception { | |
149 DiskTxn myTxn = DiskTxn.newStandalone(); | |
150 | |
151 RegistryAccessor myAccessor = theMetaData.getAccessor(myTxn); | |
152 | |
153 for (int i = 0; i < theAllocators.length; i++) { | |
154 OIDAllocator myAlloc = theAllocators[i]; | |
155 | |
156 synchronized(myAlloc) { | |
157 myAccessor.save(myAlloc.getKey(), myAlloc.getState()); | |
158 } | |
159 } | |
160 | |
161 myTxn.commit(true); | |
162 } | |
163 | |
164 public void close() throws Exception { | |
165 theMetaData.close(); | |
166 } | |
167 | |
168 public void delete() throws IOException { | |
169 theMetaData.close(); | |
170 | |
171 RegistryFactory.delete(getDbNameFor(theName)); | |
172 | |
173 Disk.remove(this); | |
174 } | |
175 | |
176 private String getDbNameFor(String aName) { | |
177 return aName + "_oid"; | |
178 } | |
179 | |
180 private class OIDInitializer implements Initializer { | |
181 private int theNumAllocators; | |
182 | |
183 OIDInitializer(int aNumAllocators) { | |
184 theNumAllocators = aNumAllocators; | |
185 } | |
186 | |
187 public void execute(RegistryAccessor anAccessor) throws IOException { | |
188 for (int i = 0; i < theNumAllocators; i++) { | |
189 OIDAllocator myAlloc = new OIDAllocator(i, theNumAllocators); | |
190 anAccessor.save(myAlloc.getKey(), myAlloc.getState()); | |
191 } | |
192 } | |
193 } | |
194 } |