From 36f14deae7f1ccf297e7297c68f8ede4e025d1c9 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 15 Sep 2013 01:03:55 +0200 Subject: o Adding a more comprehensive test of the heap file. Still needs a lot more work. --- src/main/java/io/trygvis/btree/HeapFile.java | 7 +- src/main/java/io/trygvis/btree/HeapPage.java | 17 +++- src/test/java/io/trygvis/btree/HeapFileTest.java | 11 +-- src/test/java/io/trygvis/btree/HeapTest.java | 103 +++++++++++++++++++++++ src/test/java/io/trygvis/btree/TestUtils.java | 15 ++++ 5 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 src/test/java/io/trygvis/btree/HeapTest.java create mode 100644 src/test/java/io/trygvis/btree/TestUtils.java 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() { @Override public Iterator iterator() { + System.out.println("io.trygvis.btree.HeapPage.iterator"); + return new Iterator() { 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; + } +} -- cgit v1.2.3