Skip to content

Commit f29b8ae

Browse files
author
chaosfox
committed
code cleanup
1 parent 5579108 commit f29b8ae

File tree

5 files changed

+124
-87
lines changed

5 files changed

+124
-87
lines changed

nbproject/project.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ includes=**
3030
jar.compress=false
3131
javac.classpath=
3232
# Space-separated list of extra javac options
33-
javac.compilerargs=
33+
javac.compilerargs=-Xlint
3434
javac.deprecation=false
3535
javac.processorpath=\
3636
${javac.classpath}
37-
javac.source=1.5
38-
javac.target=1.5
37+
javac.source=1.6
38+
javac.target=1.6
3939
javac.test.classpath=\
4040
${javac.classpath}:\
4141
${build.classes.dir}:\

src/org/voile/MemoryPool.java

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ public class MemoryPool {
1212
private final TreeSet<Block> freeSpace;
1313

1414
private int limit;
15-
private final boolean growable;
15+
private final boolean canGrow;
1616

1717
/** creates a new pool of space
1818
* @param offset where to start the count
1919
* @param length the size of the pool
20-
* @param growable grow as needed when allocate
20+
* @param canGrow grow as needed when allocate
2121
*/
22-
public MemoryPool(int offset, int length, boolean growable) {
22+
public MemoryPool(int offset, int length, boolean canGrow) {
2323
this.limit = length;
24-
this.growable = growable;
24+
this.canGrow = canGrow;
2525

2626
freeSpace = new TreeSet<Block>();
2727
free(new Block(offset, limit-offset));
@@ -38,7 +38,7 @@ public Block allocate(int size) {
3838
Block b = findFreeBlock(size);
3939

4040
if (b == null) {
41-
if (!growable) return null;
41+
if (!canGrow) return null;
4242

4343
// create more space
4444
free(new Block(limit, size));
@@ -54,7 +54,7 @@ public Block allocate(int size) {
5454
* @return whether it have the block
5555
*/
5656
public boolean checkSpace(int size) {
57-
if (growable) return true;
57+
if (canGrow) return true;
5858

5959
Block b = findFreeBlock(size);
6060
return b != null;
@@ -69,9 +69,13 @@ public boolean checkSpace(int size) {
6969
*/
7070
private Block checkout(Block b, int size) {
7171
freeSpace.remove(b);
72-
Block nb = b.split(size);
73-
if(b.length>0)freeSpace.add(b);
74-
return nb;
72+
73+
// split b size bytes
74+
Block [] ab = Block.splitBlock(b, size);
75+
76+
// if there is extra space, add it back
77+
if(ab[1].length>0)freeSpace.add(ab[1]);
78+
return ab[0];
7579
}
7680

7781
/**
@@ -81,7 +85,7 @@ private Block checkout(Block b, int size) {
8185
*/
8286
private Block findFreeBlock(int size) {
8387

84-
// iterate in order min~max
88+
// iteration is ordered min ~ max
8589
for (Block b : freeSpace) {
8690
if (b.length >= size)
8791
return b;
@@ -117,37 +121,41 @@ public void free(Block b) {
117121

118122
if (b.start + b.length > limit) limit = b.start + b.length; // grows with free
119123

124+
// query adjacent blocks
120125
Block prev = freeSpace.floor(b);
121126
Block next = freeSpace.higher(b);
122127

123128
if (prev != null && prev.start + prev.length > b.start) {
124-
new RuntimeException("DEBUG PRV " + prev.start + "+" + prev.length + ">" + b.start).printStackTrace();
125-
System.exit(1);
129+
throw new RuntimeException("Corrupted. DEBUG PRV " + prev.start + "+" + prev.length + ">" + b.start);
126130
}
127131
if (next != null && next.start < b.start + b.length) {
128-
new RuntimeException("DEBUG NEX " + next.start + "<" + b.start + "+" + b.length).printStackTrace();
129-
System.exit(1);
132+
throw new RuntimeException("Corrupted. DEBUG NEX " + next.start + "<" + b.start + "+" + b.length);
130133
}
131134

132-
if(b.merge(prev))freeSpace.remove(prev);
133-
if(b.merge(next))freeSpace.remove(next);
135+
// merge them if possible
136+
137+
Block n = Block.mergeBlocks(b, prev);
138+
if(n != null) { freeSpace.remove(prev); b = n; }
139+
140+
n = Block.mergeBlocks(b, next);
141+
if(n != null) { freeSpace.remove(next); b = n; }
134142

135143
freeSpace.add(b);
136144
}
137145

138146
@Override
139147
public String toString() {
140-
String s = "";
148+
StringBuilder sb = new StringBuilder();
141149
for (Block b : freeSpace) {
142-
s += "BLOCK [" + b.start + "] ~ " + b.length + "\n";
150+
sb.append(b).append("\n");
143151
}
144-
return s;
152+
return sb.toString();
145153
}
146154

147155
public static class Block implements Comparable<Block> {
148156

149-
int start;
150-
int length;
157+
final int start;
158+
final int length;
151159

152160
public Block(int start, int length) {
153161
this.start = start;
@@ -173,26 +181,46 @@ public int hashCode() {
173181
hash = 53 * hash + this.length;
174182
return hash;
175183
}
176-
public boolean merge(Block b) {
177-
if(b == null)return false;
184+
185+
@Override
186+
public String toString() {
187+
return "BLOCK["+start+":"+length+"]";
188+
}
189+
190+
/**
191+
* merge 2 blocks into one IF their positions
192+
* are adjacent to each other, otherwise NULL
193+
* @param a block to merge
194+
* @param b another block to merge
195+
* @return merged block or NULL if merge is not possible
196+
*/
197+
public static Block mergeBlocks(Block a, Block b) {
198+
if(a == null || b == null)return null;
199+
178200
// left merge
179-
if(b.start + b.length == this.start) {
180-
this.start = b.start;
181-
this.length += b.length;
182-
return true;
201+
if(b.start + b.length == a.start) {
202+
return new Block(b.start, a.length + b.length);
183203
}
204+
184205
// right merge
185-
if (b.start == this.start + this.length) {
186-
this.length += b.length;
187-
return true;
206+
if (b.start == a.start + a.length) {
207+
return new Block(a.start, a.length + b.length);
188208
}
189-
return false;
209+
return null;
190210
}
191-
public Block split(int size) {
192-
Block b = new Block(this.start, size);
193-
this.start += size;
194-
this.length -= size;
195-
return b;
211+
212+
/**
213+
* split a block into
214+
* a block with size bytes from the start of the original
215+
* a block with the extra bytes from the original
216+
* @param b the original block
217+
* @param size to split the first block
218+
* @return an array with the 2 new blocks
219+
*/
220+
public static Block[] splitBlock(Block b, int size) {
221+
Block nb = new Block(b.start, size);
222+
b = new Block(b.start + size, b.length - size);
223+
return new Block[]{nb, b};
196224
}
197225
}
198226
}

src/org/voile/VoileFile.java

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
11
package org.voile;
22

3-
import java.io.*;
3+
import java.io.ByteArrayOutputStream;
4+
import java.io.File;
5+
import java.io.IOException;
6+
import java.io.ObjectInputStream;
7+
import java.io.ObjectOutputStream;
8+
import java.io.RandomAccessFile;
9+
import java.io.Serializable;
410
import java.nio.ByteBuffer;
511
import java.nio.channels.FileChannel;
6-
import java.util.*;
12+
import java.util.ArrayList;
13+
import java.util.Collections;
14+
import java.util.Comparator;
15+
import java.util.HashMap;
16+
import java.util.Set;
17+
import java.util.logging.Level;
18+
import java.util.logging.Logger;
19+
720
import org.voile.MemoryPool.Block;
821

922
/**
@@ -12,9 +25,9 @@
1225
public class VoileFile<K extends Serializable, V extends Serializable> {
1326

1427
private static final int INT_SIZE = Integer.SIZE / Byte.SIZE;
15-
private static final int INDEX_ENTRY_SIZE = INT_SIZE + INT_SIZE + INT_SIZE;
28+
private static final int INDEX_ENTRY_SIZE = 3 * INT_SIZE;
1629

17-
private static final int INDEX_START = INT_SIZE + INT_SIZE;
30+
private static final int INDEX_START = 2 * INT_SIZE;
1831

1932
private static final Comparator<Entry> dataPointerComparator = new Comparator<Entry>() {
2033
@Override
@@ -43,11 +56,13 @@ public VoileFile(File f) throws IOException {
4356
updateMainHeader();
4457
}
4558
else {
59+
// read existing file
4660
final int numEntries = file.readInt();
4761
final int dataStartPointer = file.readInt();
4862

4963
ArrayList<Entry> entry_list = new ArrayList<Entry>(numEntries);
5064

65+
// read index, numEntries x (dataPointer, dataLength, keySize)
5166
for (int i = 0; i < numEntries; i++) {
5267
Block header = new Block((int) file.getFilePointer(), INDEX_ENTRY_SIZE);
5368
Block data = new Block(file.readInt(), file.readInt());
@@ -65,6 +80,8 @@ public VoileFile(File f) throws IOException {
6580
int end = (int) file.length();
6681
dataSpace = new MemoryPool(end, end, true);
6782

83+
// re-construct the free space pool based on the
84+
// holes missing between the index entries
6885
Collections.sort(entry_list, dataPointerComparator);
6986
int d_pos = dataStartPointer;
7087
for (Entry e : entry_list) {
@@ -92,30 +109,34 @@ public V put(K key, V value) throws IOException {
92109
Entry e = index.get(key);
93110
ByteBuffer key_data = object2bin(key);
94111
ByteBuffer value_data = object2bin(value);
95-
System.err.println("put key[" + key + "] [" + value + "]");
96-
V old_value = null;
97112

98-
if (e != null) { // update
113+
Logger.getLogger(this.getClass().getName()).log(Level.INFO, "put key[{0}] [{1}]", new Object[]{key, value});
99114

100-
//noinspection unchecked
101-
old_value = (V) bin2object(readValue(e));
115+
V old_value = null;
102116

103-
// we got enough space to update ?
117+
// if there's already a entry at this key
118+
if (e != null) {
119+
120+
// if we got enough space, update
104121
if (value_data.remaining() + e.keySize <= e.data.length) {
105122

106-
// split the block
107-
Block nb = e.data.split(value_data.remaining() + e.keySize);
123+
//noinspection unchecked
124+
old_value = (V) bin2object(readValue(e)); // get old value first
125+
126+
// split the data block
127+
Block[] split_block = Block.splitBlock(e.data, value_data.remaining() + e.keySize);
108128

109-
dataSpace.free(e.data); // free old
110-
e.data = nb; // store new block
111-
129+
dataSpace.free(split_block[1]); // free extra space
130+
e.data = split_block[0]; // store new block
131+
132+
// write new data
112133
chan.write(value_data, e.data.start + e.keySize);
113134
writeEntry(e);
135+
114136
return old_value;
115137
}
116-
// else, need remove-insert again
117-
System.err.print("put--");
118-
remove(key);
138+
// else, we need to remove and then insert again
139+
old_value = remove(key);
119140
}
120141
// insert new
121142

@@ -148,7 +169,7 @@ public V remove(K key) throws IOException {
148169
final Entry e = index.get(key);
149170
if (e == null) return null;
150171

151-
System.err.println("remove [" + key + "]");
172+
Logger.getLogger(this.getClass().getName()).log(Level.INFO, "remove [{0}]", key);
152173

153174
@SuppressWarnings({"unchecked"})
154175
V old_value = (V) bin2object(readValue(e));
@@ -186,6 +207,7 @@ private void removeEntry(Entry e) throws IOException {
186207
headerSpace.free(last_p);
187208
}
188209

210+
189211
private void updateMainHeader() throws IOException {
190212
file.seek(0);
191213
file.writeInt(index.size());
@@ -199,33 +221,26 @@ private Entry allocate(int keySize, int valueSize) throws IOException {
199221
freeHeaderSpace();
200222
Block header = headerSpace.allocate(INDEX_ENTRY_SIZE);
201223
Block data = dataSpace.allocate(size);
202-
Entry e = new Entry(header, data, keySize);
203-
//e.header = header;
204-
//e.data = data;
205-
return e;
224+
return new Entry(header, data, keySize);
206225
}
207226

208227
private void freeHeaderSpace() throws IOException {
209228
while (!headerSpace.checkSpace(INDEX_ENTRY_SIZE)) {
210229
Entry f = findBlockAt(headerSpace.getLimit());
211230

212231
if (f == null) { // freed maybe ?
213-
System.err.println(dataSpace);
214-
System.err.println(headerSpace);
215232
Block b = dataSpace.allocateAt(headerSpace.getLimit());
216233

217234
if (b != null) {
218235
headerSpace.free(b); // pass the space to the header
219-
System.err.println("found on data " + b);
220236
continue;
221237
} else {
222-
throw new IOException("LOL ");
238+
throw new IOException("Corrupted: Couldn't get extra space for the header.");
223239
}
224240
}
225241

226242
// find a new place to the data
227243
Block data = dataSpace.allocate(f.data.length);
228-
int dp = data.start;
229244

230245
// read the data
231246
ByteBuffer key_data = readKey(f);
@@ -243,9 +258,7 @@ private void freeHeaderSpace() throws IOException {
243258
}
244259

245260
private Entry findBlockAt(int targetFp) {
246-
System.err.println("target " + targetFp);
247261
for (Entry e : index.values()) {
248-
System.err.println(e.data.start + " " + e.data.length);
249262
if (e.data.start == targetFp) return e;
250263
}
251264
return null;
@@ -277,12 +290,12 @@ private ByteBuffer readValue(Entry e) throws IOException {
277290
return value_data;
278291
}
279292

280-
private ByteBuffer object2bin(Serializable o) {
293+
private ByteBuffer object2bin(Serializable o) throws IOException {
281294
ByteArrayOutputStream bao = new ByteArrayOutputStream();
282295
try {
283296
new ObjectOutputStream(bao).writeObject(o);
284-
} catch (IOException ignored) {
285-
return null;
297+
} catch (IOException ex) {
298+
throw ex;
286299
}
287300
return ByteBuffer.wrap(bao.toByteArray());
288301
}
@@ -292,10 +305,9 @@ private Serializable bin2object(ByteBuffer blob) throws IOException {
292305

293306
try {
294307
return (Serializable) new ObjectInputStream(new ByteBufferInputStream(blob)).readObject();
295-
} catch (ClassNotFoundException ignored) {
296-
ignored.printStackTrace(); //TODO: is this a problem ?
308+
} catch (ClassNotFoundException cnfe) {
309+
throw new RuntimeException(cnfe);
297310
}
298-
return null;
299311
}
300312

301313
static class Entry {

0 commit comments

Comments
 (0)