-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFileManager.java
361 lines (331 loc) · 10.5 KB
/
FileManager.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
package storage;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import storage.SlottedPage.IndexOutOfBoundsException;
import storage.SlottedPage.OverflowException;
/**
* A {@code FileManager} manages a storage space using the slotted page format.
*
* @author Jeong-Hyon Hwang (jhh@cs.albany.edu)
*/
public class FileManager implements StorageManager<Long, Object> {
/**
* A map that associates the ID of each file with a {@code SlottedPageFile} for accessing that file.
*/
Map<Integer, SlottedPageFile> id2file = new HashMap<Integer, SlottedPageFile>();
/**
* The size (in bytes) of {@code SlottedPage}s.
*/
int slottedPageSize;
/**
* Constructs a {@code FileManager}.
*
* @param slottedPageSize
* the size (in bytes) of {@code SlottedPage}s
*/
public FileManager(int slottedPageSize) {
this.slottedPageSize = slottedPageSize;
}
/**
* Returns the first location in any file.
*
* @return the first location in any file.
*/
@Override
public Long first() {
return 0L;
}
/**
* Shuts down this {@code FileManager} after saving all of the essential in-memory data on disk.
*
* @throws IOException
* if an I/O error occurs
*/
public void shutdown() throws IOException {
for (SlottedPageFile f : id2file.values())
f.close(); // closes each data file
}
@Override
public String toString() {
return id2file.values().toString();
}
/**
* Adds the specified object at the end of the specified file.
*
* @param fileID
* the ID of the file
* @param o
* the object to add
* @return the location of the object in the specified file
* @throws IOException
* if an I/O error occurs
*/
@Override
public Long add(int fileID, Object o) throws IOException {
int size = size(fileID); // the number of pages in the data file
SlottedPage p;
long location;
try {
if (size == 0) { // if no page yet
p = new SlottedPage(0, slottedPageSize); // create page 0
location = concatenate(p.pageID(), p.add(o)); // add the object in the page
} else { // existing page
p = page(fileID, size - 1); // get last page
try {
location = concatenate(p.pageID(), p.add(o)); // add the object in the page
} catch (OverflowException e) { // if the object cannot fit into the page
p = new SlottedPage(p.pageID() + 1, slottedPageSize); // create a new page
location = concatenate(p.pageID(), p.add(o)); // add the object in the new page
}
}
} catch (OverflowException e) {
throw new IOException(e);
}
updated(p, fileID); // inform that the page is updated (and thus the page will eventually be saved in the file)
return location; // return the location of the object
}
/**
* Puts the specified object at the specified location in the specified file.
*
* @param fileID
* the ID of the file
* @param location
* the location of the object
* @param o
* the object to put
* @return the object stored previously at the specified location in the specified file; {@code null} if no such
* object
* @throws IOException
* if an I/O error occurs
* @throws InvalidLocationException
* if an invalid location is given
*/
@Override
public Object put(int fileID, Long location, Object o) throws IOException, InvalidLocationException {
//SlottedPage p = page(fileID, first(location)); // the page specified by the 1st half of the location
// TODO complete this method (10 points)
int id = first(location);
int index = second(location);
SlottedPage p = page(fileID, id);
if(index < 0 || id < 0)
throw new InvalidLocationException();
if(p == null){
SlottedPage p2 = new SlottedPage(id, slottedPageSize);
try {
p2.put(index, o);
} catch (OverflowException e) {
} catch (storage.SlottedPage.IndexOutOfBoundsException e) {
e.printStackTrace();
}
updated(p2, fileID);
return null;
} else {
try {
Object obj = p.put(index, o);
updated(p, fileID);
return obj;
} catch (OverflowException e) {
e.printStackTrace();
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
return null;
}
/**
* Returns the object at the specified location in the specified file.
*
* @param fileID
* the ID of the file
* @param location
* the location of the object
* @return the object at the specified location in the specified file
* @throws IOException
* if an I/O error occurs
* @throws InvalidLocationException
* if an if an invalid location is given
*/
@Override
public Object get(int fileID, Long location) throws IOException, InvalidLocationException {
int id = first(location);
int index = second(location);
if (id < 0 || index < 0) {
throw new InvalidLocationException();
}
SlottedPage p = page(fileID, id);
if (p == null) {
// Page does not exist, return null
return null;
} else {
// Get object from page
try {
return p.get(index);
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
return null;
}
/**
* Removes the specified object at the specified location in the specified file.
*
* @param fileID
* the ID of the file
* @param location
* the location of the object
* @return the object stored previously at the specified location in the specified file; {@code null} if no such
* object
* @throws IOException
* if an I/O error occurs
* @throws InvalidLocationException
* if an if an invalid location is given
*/
@Override
public Object remove(int fileID, Long location) throws IOException, InvalidLocationException {
// SlottedPage p = page(fileID, first(location)); // the page specified by the 1st half of the location
// TODO complete this method (5 points)
int id = first(location);
int index = second(location);
SlottedPage p = page(fileID, id);
if(p == null)
throw new InvalidLocationException();
if(index < 0 || id < 0 )
throw new InvalidLocationException();
try {
Object o = p.remove(index);
updated(p, fileID);
return o;
} catch (Exception e) {
throw new InvalidLocationException();
}
}
/**
* Removes all data from the specified file.
*
* @param fileID
* the ID of the file
* @throws IOException
* if an I/O error occurs
*/
@Override
public void clear(int fileID) throws IOException {
SlottedPageFile f = file(fileID);
f.clear();
}
/**
* Returns an iterator over all objects stored in the the specified file.
*
* @param fileID
* the ID of the file
*/
@Override
public Iterator<Object> iterator(int fileID) {
return null;
// TODO complete this method (5 points)
// List<Object> objectList = new ArrayList<Object>();
// List<SlottedPage> pagesList = pages(fileID);
// for (SlottedPage p : pagesList) {
// List<Object> pageObjects = p.get();
// objectList.addAll();
// }
// return objectList.iterator();
// COULDNT FIGURE OUT
}
/**
* Returns the number of {@code SlottedPage}s in the specified {@code SlottedPageFile}.
*
* @param fileID
* the ID of the {@code SlottedPageFile}
* @return the number of {@code SlottedPage}s in the specified {@code SlottedPageFile}
* @throws IOException
* if an I/O error occurs
*/
int size(int fileID) throws IOException {
return file(fileID).size();
}
/**
* Returns the specified {@code SlottedPage} ({@code null} if no such {@code SlottedPage}).
*
* @param fileID
* the ID of the file containing the {@code SlottedPage}
* @param pageID
* the ID of the {@code SlottedPage}
* @return the specified {@code SlottedPage}; {@code null} if no such {@code SlottedPage}
* @throws IOException
* if an I/O error occurs
*/
SlottedPage page(int fileID, int pageID) throws IOException {
SlottedPageFile f = file(fileID);
return f.get(pageID);
}
/**
* Is invoked when the specified {@code SlottedPage} is updated.
*
* @param p
* a {@code SlottedPage}
* @param fileID
* the ID of the file containing the {@code SlottedPage}
* @throws IOException
* if an I/O error occurs
*/
void updated(SlottedPage p, int fileID) throws IOException {
SlottedPageFile f = file(fileID);
f.save(p);
}
/**
* Returns a {@code long} value obtaining by concatenating the given {@code int} values
*
* @param i
* an {@code int} value
* @param j
* an {@code int} value
* @return a {@code long} value obtaining by concatenating the given {@code int} values
*/
protected long concatenate(int i, int j) {
return (((long) i) << 32) | j;
}
/**
* Returns an {@code int} value obtained from the first 4 bytes of the given {@code long} value.
*
* @param l
* a {@code long} value.
* @return an {@code int} value obtained from the first 4 bytes of the given {@code long} value
*/
protected int first(long l) {
return (int) (l >> 32);
}
/**
* Returns an {@code int} value obtained from the last 4 bytes of the given {@code long} value.
*
* @param l
* a {@code long} value.
* @return an {@code int} value obtained from the last 4 bytes of the given {@code long} value
*/
protected int second(long l) {
return (int) l;
}
/**
* Returns the {@code SlottedPageFile} corresponding to the specified file ID.
*
* @param fileID
* the ID of a {@code SlottedPageFile}
* @return the {@code SlottedPageFile} corresponding to the specified file ID
* @throws FileNotFoundException
* if the specified file cannot be found/created
* @throws IOException
* if an IO error occurs
*/
protected SlottedPageFile file(int fileID) throws FileNotFoundException, IOException {
SlottedPageFile file = id2file.get(fileID);
if (file == null) {
file = new SlottedPageFile(fileID + ".dat", slottedPageSize);
id2file.put(fileID, file);
}
return file;
}
}