aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/io/trygvis/btree/HeapFile.java7
-rw-r--r--src/main/java/io/trygvis/btree/HeapPage.java17
-rw-r--r--src/test/java/io/trygvis/btree/HeapFileTest.java11
-rw-r--r--src/test/java/io/trygvis/btree/HeapTest.java103
-rw-r--r--src/test/java/io/trygvis/btree/TestUtils.java15
5 files changed, 141 insertions, 12 deletions
diff --git a/src/main/java/io/trygvis/btree/HeapFile.java b/src/main/java/io/trygvis/btree/HeapFile.java
index 7a960c8..6bd0451 100644
--- a/src/main/java/io/trygvis/btree/HeapFile.java
+++ b/src/main/java/io/trygvis/btree/HeapFile.java
@@ -37,15 +37,18 @@ public class HeapFile implements Closeable {
return HeapPage.heapPageFromBytes(page, buffer);
}
- public void writePage(HeapPage page) throws IOException {
+ public long writePage(HeapPage page) throws IOException {
long position;
if (page.pageNumber == -1) {
- position = file.length();
+ position = channel.size();
} else {
position = page.pageNumber * PAGE_SIZE;
}
+ page.bytes.rewind();
channel.write(page.bytes, position);
channel.force(true);
+
+ return position / PAGE_SIZE;
}
public long pageCount() throws IOException {
diff --git a/src/main/java/io/trygvis/btree/HeapPage.java b/src/main/java/io/trygvis/btree/HeapPage.java
index 499a244..a931260 100644
--- a/src/main/java/io/trygvis/btree/HeapPage.java
+++ b/src/main/java/io/trygvis/btree/HeapPage.java
@@ -22,7 +22,12 @@ public class HeapPage {
}
public static HeapPage heapPageFromBytes(int pageNumber, ByteBuffer bytes) {
- int freePosition = bytes.getInt();
+ int freePosition = bytes.getInt(FREE_POSITION_INDEX);
+
+ if (freePosition > bytes.capacity() || freePosition < headerSize) {
+ throw new RuntimeException("Invalid free position: " + freePosition);
+ }
+
return new HeapPage(pageNumber, bytes, freePosition);
}
@@ -31,8 +36,6 @@ public class HeapPage {
}
public void append(byte[] item) {
-// System.out.println("io.trygvis.btree.HeapPage.append");
-
int bytesFree = bytesFree();
int bytesRequested = item.length;
@@ -58,6 +61,8 @@ public class HeapPage {
return new Iterable<ByteBuffer>() {
@Override
public Iterator<ByteBuffer> iterator() {
+ System.out.println("io.trygvis.btree.HeapPage.iterator");
+
return new Iterator<ByteBuffer>() {
private int position;
@@ -65,21 +70,27 @@ public class HeapPage {
{
position = bytes.capacity();
+ System.out.println("position = " + position);
next = findNext();
}
private ByteBuffer findNext() {
+ System.out.println("io.trygvis.btree.HeapPage.findNext");
if (position == headerSize) {
+ System.out.println("at end");
return null;
}
int size = bytes.getInt(position - itemSize);
if (size == 0) {
+ System.out.println("at end");
return null;
}
position -= itemSize + size;
+
+ System.out.println("item: size: " + size + ", new position: " + position);
ByteBuffer copy = bytes.duplicate();
copy.position(position);
copy.limit(position + size);
diff --git a/src/test/java/io/trygvis/btree/HeapFileTest.java b/src/test/java/io/trygvis/btree/HeapFileTest.java
index a9105bb..558f192 100644
--- a/src/test/java/io/trygvis/btree/HeapFileTest.java
+++ b/src/test/java/io/trygvis/btree/HeapFileTest.java
@@ -4,6 +4,7 @@ import org.junit.Test;
import java.io.File;
+import static io.trygvis.btree.TestUtils.deleteFile;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -12,16 +13,12 @@ public class HeapFileTest {
@Test
public void testBasic() throws Exception {
int pageSize = 128;
- File f = new File("target/heap");
- if (f.exists()) {
- assertTrue(f.delete());
- }
-
- HeapFile file = new HeapFile(pageSize, f);
+ HeapFile file = new HeapFile(pageSize, deleteFile(new File("target/heap")));
assertEquals(0, file.pageCount());
HeapPage page = file.blankPage();
- file.writePage(page);
+ long pageNumber = file.writePage(page);
+ assertEquals(0, pageNumber);
assertEquals(1, file.pageCount());
}
}
diff --git a/src/test/java/io/trygvis/btree/HeapTest.java b/src/test/java/io/trygvis/btree/HeapTest.java
new file mode 100644
index 0000000..1d724f4
--- /dev/null
+++ b/src/test/java/io/trygvis/btree/HeapTest.java
@@ -0,0 +1,103 @@
+package io.trygvis.btree;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.Random;
+
+import static io.trygvis.btree.HeapTest.Person.randomPerson;
+import static io.trygvis.btree.TestUtils.deleteFile;
+import static org.junit.Assert.assertEquals;
+
+public class HeapTest {
+
+ @Test
+ public void testHeap() throws Exception {
+ File f = new File("target/heapTest");
+
+ HeapFile file = new HeapFile(128, deleteFile(f));
+
+ HeapPage page = file.blankPage();
+
+ int pageNo = 0;
+ for (int i = 0; i < 10; i++) {
+ Person p = randomPerson();
+
+ byte[] bytes = p.toBytes();
+
+ System.out.println("p = " + p + ", size = " + bytes.length);
+
+ if (page.bytesFree() < bytes.length) {
+ System.out.println("Flushing page");
+ long actualPageNo = file.writePage(page);
+ assertEquals(pageNo++, actualPageNo);
+ page = file.blankPage();
+ }
+
+ page.append(bytes);
+ }
+
+ long actualPageNo = file.writePage(page);
+ assertEquals(pageNo, actualPageNo);
+ file.close();
+
+ System.out.println("-------------------------------------------------------");
+ file = new HeapFile(128, f);
+
+ System.out.println("file.pageCount() = " + file.pageCount());
+
+ for (int i = 0; i < file.pageCount(); i++) {
+ System.out.println("page #" + i);
+ page = file.loadPage(i);
+
+ for (ByteBuffer buffer : page.bufferIterator()) {
+ Person p = Person.fromBytes(buffer);
+ System.out.println("p = " + p);
+ }
+ }
+ }
+
+ public static class Person {
+ private final String name;
+ private final int age;
+
+ public Person(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public byte[] toBytes() {
+ byte[] s = name.getBytes();
+ ByteBuffer buffer = ByteBuffer.allocate(s.length + 8);
+ buffer.putInt(s.length);
+ buffer.put(s);
+ buffer.putInt(age);
+ return buffer.array();
+ }
+
+ public static Person fromBytes(ByteBuffer buffer) {
+ int stringSize = buffer.getInt();
+ byte[] s = new byte[stringSize];
+ buffer.get(s);
+ return new Person(new String(s), buffer.getInt());
+ }
+
+ @Override
+ public String toString() {
+ return "Person{" +
+ "name='" + name + '\'' +
+ ", age=" + age +
+ '}';
+ }
+
+ private final static Random r = new Random(0);
+ private final static String[] names = new String[]{
+ "Lukas", "Emil", "Mathias", "Jonas", "Aleksander", "William", "Oskar", "Magnus", "Markus", "Oliver",
+ "Nora", "Emma", "Sofie", "Linnea", "Sara", "Emilie", "Ingrid", "Thea", "Leah", "Sofia"};
+
+ public static Person randomPerson() {
+ return new Person(names[r.nextInt(names.length)], r.nextInt(80) + 20);
+ }
+ }
+}
diff --git a/src/test/java/io/trygvis/btree/TestUtils.java b/src/test/java/io/trygvis/btree/TestUtils.java
new file mode 100644
index 0000000..92565e5
--- /dev/null
+++ b/src/test/java/io/trygvis/btree/TestUtils.java
@@ -0,0 +1,15 @@
+package io.trygvis.btree;
+
+import java.io.File;
+
+import static org.junit.Assert.assertTrue;
+
+public class TestUtils {
+ public static File deleteFile(File file) {
+ if (file.exists()) {
+ assertTrue(file.delete());
+ }
+
+ return file;
+ }
+}