aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/io/trygvis/btree/HeapPage.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/io/trygvis/btree/HeapPage.java')
-rw-r--r--src/main/java/io/trygvis/btree/HeapPage.java123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/main/java/io/trygvis/btree/HeapPage.java b/src/main/java/io/trygvis/btree/HeapPage.java
new file mode 100644
index 0000000..499a244
--- /dev/null
+++ b/src/main/java/io/trygvis/btree/HeapPage.java
@@ -0,0 +1,123 @@
+package io.trygvis.btree;
+
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+public class HeapPage {
+ public static final int headerSize = 4;
+ public static final int FREE_POSITION_INDEX = 0;
+
+ public static final int itemSize = 4;
+
+ // The page number in a heap file
+ final long pageNumber;
+ final ByteBuffer bytes;
+ int freePosition;
+
+ private HeapPage(long pageNumber, ByteBuffer bytes, int freePosition) {
+ this.pageNumber = pageNumber;
+ this.bytes = bytes;
+ this.freePosition = freePosition;
+ }
+
+ public static HeapPage heapPageFromBytes(int pageNumber, ByteBuffer bytes) {
+ int freePosition = bytes.getInt();
+ return new HeapPage(pageNumber, bytes, freePosition);
+ }
+
+ public static HeapPage blankHeapPage(ByteBuffer bytes) {
+ return new HeapPage(-1, bytes, bytes.capacity());
+ }
+
+ public void append(byte[] item) {
+// System.out.println("io.trygvis.btree.HeapPage.append");
+
+ int bytesFree = bytesFree();
+ int bytesRequested = item.length;
+
+ if (bytesRequested > bytesFree) {
+ throw new PageOverflowException(bytesFree, bytesRequested);
+ }
+
+ freePosition -= itemSize;
+ bytes.position(freePosition);
+ bytes.putInt(item.length);
+ freePosition -= bytesRequested;
+ bytes.position(freePosition);
+ bytes.put(item);
+
+ bytes.putInt(FREE_POSITION_INDEX, freePosition);
+ }
+
+ public int bytesFree() {
+ return freePosition - headerSize;
+ }
+
+ public Iterable<ByteBuffer> bufferIterator() {
+ return new Iterable<ByteBuffer>() {
+ @Override
+ public Iterator<ByteBuffer> iterator() {
+ return new Iterator<ByteBuffer>() {
+ private int position;
+
+ private ByteBuffer next;
+
+ {
+ position = bytes.capacity();
+ next = findNext();
+ }
+
+ private ByteBuffer findNext() {
+ if (position == headerSize) {
+ return null;
+ }
+
+ int size = bytes.getInt(position - itemSize);
+
+ if (size == 0) {
+ return null;
+ }
+
+ position -= itemSize + size;
+ ByteBuffer copy = bytes.duplicate();
+ copy.position(position);
+ copy.limit(position + size);
+ return copy.slice();
+ }
+
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ @Override
+ public ByteBuffer next() {
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+
+ ByteBuffer n = next;
+ next = findNext();
+ return n;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ };
+ }
+
+ public static class PageOverflowException extends RuntimeException {
+ public final int bytesFree;
+ public final int bytesRequested;
+
+ public PageOverflowException(int bytesFree, int bytesRequested) {
+ super("Not enough room on page, bytes free=" + bytesFree + ", requested = " + bytesRequested);
+ this.bytesFree = bytesFree;
+ this.bytesRequested = bytesRequested;
+ }
+ }
+}