1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 package jdbm.recman;
49
50 import java.io.*;
51
52
53
54
55 final class PageManager {
56
57 private RecordFile file;
58
59 private FileHeader header;
60 private BlockIo headerBuf;
61
62
63
64
65 PageManager(RecordFile file) throws IOException {
66 this.file = file;
67
68
69
70 headerBuf = file.get(0);
71 if (headerBuf.readShort(0) == 0)
72 header = new FileHeader(headerBuf, true);
73 else
74 header = new FileHeader(headerBuf, false);
75 }
76
77
78
79
80
81 long allocate(short type) throws IOException {
82
83 if (type == Magic.FREE_PAGE)
84 throw new Error("allocate of free page?");
85
86
87 long retval = header.getFirstOf(Magic.FREE_PAGE);
88 boolean isNew = false;
89 if (retval != 0) {
90
91
92 header.setFirstOf(Magic.FREE_PAGE, getNext(retval));
93 }
94 else {
95
96 retval = header.getLastOf(Magic.FREE_PAGE);
97 if (retval == 0)
98
99 retval = 1;
100 header.setLastOf(Magic.FREE_PAGE, retval + 1);
101 isNew = true;
102 }
103
104
105 BlockIo buf = file.get(retval);
106 PageHeader pageHdr = isNew ? new PageHeader(buf, type)
107 : PageHeader.getView(buf);
108 long oldLast = header.getLastOf(type);
109
110
111 System.arraycopy(RecordFile.cleanData, 0,
112 buf.getData(), 0,
113 RecordFile.BLOCK_SIZE);
114 pageHdr.setType(type);
115 pageHdr.setPrev(oldLast);
116 pageHdr.setNext(0);
117
118
119 if (oldLast == 0)
120
121 header.setFirstOf(type, retval);
122 header.setLastOf(type, retval);
123 file.release(retval, true);
124
125
126 if (oldLast != 0) {
127 buf = file.get(oldLast);
128 pageHdr = PageHeader.getView(buf);
129 pageHdr.setNext(retval);
130 file.release(oldLast, true);
131 }
132
133
134 buf.setView(null);
135
136 return retval;
137 }
138
139
140
141
142 void free(short type, long recid) throws IOException {
143 if (type == Magic.FREE_PAGE)
144 throw new Error("free free page?");
145 if (recid == 0)
146 throw new Error("free header page?");
147
148
149 BlockIo buf = file.get(recid);
150 PageHeader pageHdr = PageHeader.getView(buf);
151 long prev = pageHdr.getPrev();
152 long next = pageHdr.getNext();
153
154
155 pageHdr.setType(Magic.FREE_PAGE);
156 pageHdr.setNext(header.getFirstOf(Magic.FREE_PAGE));
157 pageHdr.setPrev(0);
158
159 header.setFirstOf(Magic.FREE_PAGE, recid);
160 file.release(recid, true);
161
162
163 if (prev != 0) {
164 buf = file.get(prev);
165 pageHdr = PageHeader.getView(buf);
166 pageHdr.setNext(next);
167 file.release(prev, true);
168 }
169 else {
170 header.setFirstOf(type, next);
171 }
172 if (next != 0) {
173 buf = file.get(next);
174 pageHdr = PageHeader.getView(buf);
175 pageHdr.setPrev(prev);
176 file.release(next, true);
177 }
178 else {
179 header.setLastOf(type, prev);
180 }
181
182 }
183
184
185
186
187
188 long getNext(long block) throws IOException {
189 try {
190 return PageHeader.getView(file.get(block)).getNext();
191 } finally {
192 file.release(block, false);
193 }
194 }
195
196
197
198
199 long getPrev(long block) throws IOException {
200 try {
201 return PageHeader.getView(file.get(block)).getPrev();
202 } finally {
203 file.release(block, false);
204 }
205 }
206
207
208
209
210 long getFirst(short type) throws IOException {
211 return header.getFirstOf(type);
212 }
213
214
215
216
217 long getLast(short type) throws IOException {
218 return header.getLastOf(type);
219 }
220
221
222
223
224
225
226
227 void commit() throws IOException {
228
229 file.release(headerBuf);
230 file.commit();
231
232
233 headerBuf = file.get(0);
234 header = new FileHeader(headerBuf, false);
235 }
236
237
238
239
240
241 void rollback() throws IOException {
242
243 file.discard(headerBuf);
244 file.rollback();
245
246 headerBuf = file.get(0);
247 if (headerBuf.readShort(0) == 0)
248 header = new FileHeader(headerBuf, true);
249 else
250 header = new FileHeader(headerBuf, false);
251 }
252
253
254
255
256
257 void close() throws IOException {
258 file.release(headerBuf);
259 file.commit();
260 headerBuf = null;
261 header = null;
262 file = null;
263 }
264
265
266
267
268 FileHeader getFileHeader() {
269 return header;
270 }
271
272 }