-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHeapPage.java
367 lines (332 loc) · 10.3 KB
/
HeapPage.java
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
package simpledb;
import java.util.*;
import java.io.*;
/**
* A {@code HeapPage} is a collection of {@code Tuple}s. A fixed-size memory space is used for each {@code HeapPage}. A
* {@code HeapFile} consists of {@code HeaPage}s. The {@code HeapPage} class implements the {@code Page} interface that
* is used by {@code BufferPool}.
*
* @see HeapFile
* @see BufferPool
*/
public class HeapPage implements Page {
/**
* The ID of this {@code HeapPage}.
*/
HeapPageId pid;
/**
* The {@code TupleDesc} representing the {@code Tuple}s stored in this {@code HeapPage}.
*/
TupleDesc td;
/**
* The current content of this {@code HeapPage}.
*/
byte[] data;
/**
* The previous image of this {@code HeapPage}.
*/
byte[] oldData;
/**
* Creates a {@code HeapPage} from a byte array storing data read from disk. This byte array contains (1) a 4-byte
* integer representing the number of {@code Tuple}s assigned to the {@code HeapPage}, (2) a sequence of integer
* values each of which indicates where the corresponding {@code Tuple} is stored in the byte array, (3) a free
* space reserved for storing additional {@code Tuple}s, and (4) a sequence of {@code Tuple}s.
*
* @param id
* the ID of the {@code HeapPage}.
* @param data
* a byte array storing the data to read.
* @see Database#getCatalog
* @see Catalog#getTupleDesc
* @see BufferPool#PAGE_SIZE
*/
public HeapPage(HeapPageId id, byte[] data) throws IOException {
this.pid = id;
this.td = Database.getCatalog().getTupleDesc(id.getTableId());
this.data = data;
setBeforeImage();
}
/**
* Generates a byte array representing the contents of this {@code HeapPage}. This method is used to serialize this
* {@code HeapPage} to disk.
* <p>
* The invariant here is that it should be possible to pass the byte array generated by this method to the
* {@code HeapPage} constructor and have it produce an identical {@code HeapPage}.
*
* @see #HeapPage
* @return a byte array correspond to the content of this {@code HeapPage}.
*/
public byte[] getPageData() {
return data;
}
/**
* @return an iterator over all {@code Tuple}s on this {@code HeapPage} (calling remove on this iterator throws an
* {@code UnsupportedOperationException}) (note that this iterator shouldn't return {@code Tuples} in empty
* slots!)
*/
public Iterator<Tuple> iterator() {
// some code goes here
return new Iterator<Tuple>() {
int location = 0;
public Tuple next(){
if(!hasNext())
throw new NoSuchElementException();
location = location + 4;
int entry = readInt(data, location);
if(entry != -1)
return getTuple(entry);
}
public boolean hasNext(){
return location < entryCount()*4;
}
public void remove(){
throw new UnsupportedOperationException("Cannot do this!");
}
};
throw new UnsupportedOperationException("Implement this");
}
/**
* @return the ID of this {@code HeapPage}.
*/
public HeapPageId getId() {
return pid;
}
/**
* Deletes the specified {@code Tuple} from this {@code HeapPage}; the {@code Tuple} should be updated to reflect
* that it is no longer stored on any page.
*
* @throws DbException
* if the {@code Tuple} is not on this {@code HeapPage}, or the {@code Tuple} slot is already empty.
* @param t
* the {@code Tuple} to delete
*/
public void deleteTuple(Tuple t) throws DbException {
// some code goes here
// not necessary for assignment1
throw new UnsupportedOperationException("Implement this");
}
/**
* Adds the specified {@code Tuple} to this {@code HeapPage}; the {@code Tuple} should be updated to reflect that it
* is now stored on this {@code HeapPage}.
*
* @throws DbException
* if this {@code HeapPage} is full (no empty slots).
* @param t
* the {@code Tuple} to add.
*/
public void addTuple(Tuple t) throws DbException {
// some code goes here
// not necessary for assignment1
throw new UnsupportedOperationException("Implement this");
}
/**
* Marks this {@code HeapPage} as dirty/not dirty and record that transaction that did the dirtying
*/
public void markDirty(boolean dirty, TransactionId tid) {
// some code goes here
// not necessary for assignment1
throw new UnsupportedOperationException("Implement this");
}
/**
* Returns the tid of the transaction that last dirtied this page, or null if the page is not dirty
*/
public TransactionId isDirty() {
// some code goes here
// Not necessary for assignment1
throw new UnsupportedOperationException("Implement this");
}
/**
* Returns {@code Tuple} at the specified entry.
*
* @param entryID
* the ID of the entry at which the {@code Tuple} is stored.
*/
public Tuple getTuple(int entryID) {
// some code goes here
int loc = tupleLocation(entryID);
DataInputStream in = new DataInputStream(new ByteArrayInputStream(data, loc, data.length));
Tuple t = createTuple(in);
t.setRecordId(new RecordId(pid,entryID));
return t;
throw new UnsupportedOperationException("Implement this");
}
/**
* Returns a view of this {@code HeapPage} before it was modified -- used by recovery
*/
public HeapPage getBeforeImage() {
try {
return new HeapPage(pid, oldData);
} catch (IOException e) {
e.printStackTrace();
// should never happen -- we parsed it OK before!
System.exit(1);
}
return null;
}
public void setBeforeImage() {
oldData = getPageData().clone();
}
/**
* Generates a byte array corresponding to an empty {@code HeapPage}. This method is used to add new, empty pages to
* the file. Passing the results of this method to the {@code HeapPage} constructor will create a {@code HeapPage}
* with no valid {@code Tuple}s in it.
*
* @return the created byte array.
*/
public static byte[] createEmptyPageData() {
int len = BufferPool.PAGE_SIZE;
return new byte[len]; // all 0
}
/**
* Writes an integer value at the specified location of a byte array.
*
* @param data
* a byte array.
* @param location
* a location in the byte array.
* @param value
* the value to write.
*/
protected void writeInt(byte[] data, int location, int value) {
data[location] = (byte) (value >>> 24);
data[location + 1] = (byte) (value >>> 16);
data[location + 2] = (byte) (value >>> 8);
data[location + 3] = (byte) value;
}
/**
* Reads an integer at the specified location of a byte array.
*
* @param data
* a byte array.
* @param location
* a location in the byte array.
* @return an integer read at the specified location of a byte array.
*/
protected int readInt(byte[] data, int location) {
return ((data[location]) << 24) + ((data[location + 1] & 0xFF) << 16) + ((data[location + 2] & 0xFF) << 8)
+ (data[location + 3] & 0xFF);
}
/**
* Returns a byte array representing the specified tuple.
*
* @param t
* a tuple.
* @return a byte array representing the specified tuple.
*/
protected byte[] toByteArray(Tuple t) {
ByteArrayOutputStream b = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(b);
try {
for (int j = 0; j < t.fields.length; j++) {
Field f = t.getField(j);
f.serialize(out);
}
out.flush();
b.flush();
} catch (IOException e) {
e.printStackTrace();
}
return b.toByteArray();
}
/**
* Constructs a tuple by reading data from the specified {@code DataInputStream}.
*
* @param in
* a {@code DataInputStream}.
* @return a tuple constructed from the specified {@code DataInputStream}.
*/
protected Tuple createTuple(DataInputStream in) {
try {
Tuple t = new Tuple(td);
for (int j = 0; j < td.numFields(); j++) {
Field f = td.getType(j).parse(in);
t.setField(j, f);
}
return t;
} catch (java.text.ParseException e) {
e.printStackTrace();
throw new NoSuchElementException("parsing error!");
}
}
/**
* Returns the end location of the free space in this {@code HeapPage}.
*
* @return the end location of the free space in this {@code HeapPage}.
*/
protected int endOfFreeSpace() {
// some code goes here
// not necessary for assignment1
throw new UnsupportedOperationException("Implement this");
}
/**
* Returns the number of entries in this {@code HeapPage}.
*
* @return the number of entries in this {@code HeapPage}.
*/
protected int entryCount() {
int count = readInt(data, 0);
return count;
throw new UnsupportedOperationException("Implement this");
}
/**
* Saves (in the header of this {@code HeapPage}) the number of entries managed by this {@code HeapPage}.
*
* @param count
* the number of entries in this {@code HeapPage}.
*/
protected void saveEntryCount(int count) {
// some code goes here
// not necessary for assignment1
throw new UnsupportedOperationException("Implement this");
}
/**
* Finds (by examining the header of this {@code HeapPage}) the location of the tuple at the specified entry.
*
* @param entryID
* the ID of the entry.
* @return the location of the tuple at the specified entry.
*/
protected int tupleLocation(int entryID) {
// some code goes here
int location = readInt(data, 4 + 4 * entryID);
return location;
throw new UnsupportedOperationException("Implement this");
}
/**
* Saves (in the header of this {@code HeapPage}) the location of the specified tuple.
*
* @param entryID
* the ID of the entry at which the tuple is stored.
* @param location
* the location of the tuple.
*/
protected void saveTupleLocation(int entryID, int location) {
// some code goes here
// not necessary for assignment1
throw new UnsupportedOperationException("Implement this");
}
/**
* Returns the size of free space in this {@code HeapPage}.
*
* @return the size of free space in this {@code HeapPage}.
*/
protected int sizeOfFreeSpace() {
return endOfFreeSpace() - sizeOfHeader();
}
/**
* Returns the size of the header in this {@code HeapPage}.
*
* @return the size of the header in this {@code HeapPage}.
*/
protected int sizeOfHeader() {
return 4 + 4 * entryCount();
}
/**
* Compacts this {@code HeapPage}.
*/
protected void compact() {
// some code goes here
// not necessary for assignment1
throw new UnsupportedOperationException("Implement this");
}
}