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 }