Skip to content

Commit

Permalink
test: POC for using string as B+Tree index manager
Browse files Browse the repository at this point in the history
  • Loading branch information
sepgh committed Jun 14, 2024
1 parent c50ed70 commit db4b02d
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.util.Optional;
import java.util.concurrent.ExecutionException;

import static com.github.sepgh.internal.index.tree.node.AbstractTreeNode.TYPE_LEAF_NODE_BIT;

public class BPlusTreeIndexManager<K extends Comparable<K>, V extends Comparable<V>> implements IndexManager<K, V> {
private final IndexStorageManager indexStorageManager;
private final IndexIOSessionFactory indexIOSessionFactory;
Expand All @@ -39,6 +41,29 @@ public BPlusTreeIndexManager(int degree, IndexStorageManager indexStorageManager
this(degree, indexStorageManager, ImmediateCommitIndexIOSession.Factory.getInstance(), keyBinaryObjectWrapper, valueBinaryObjectWrapper, nodeFactory);
}

public BPlusTreeIndexManager(int degree, IndexStorageManager indexStorageManager, IndexIOSessionFactory indexIOSessionFactory, BinaryObjectWrapper<K> keyBinaryObjectWrapper, BinaryObjectWrapper<V> valueBinaryObjectWrapper){
this(degree, indexStorageManager, indexIOSessionFactory, keyBinaryObjectWrapper, valueBinaryObjectWrapper, new NodeFactory<K>() {
@Override
public AbstractTreeNode<K> fromBytes(byte[] bytes) {
if ((bytes[0] & TYPE_LEAF_NODE_BIT) == TYPE_LEAF_NODE_BIT)
return new AbstractLeafTreeNode<>(bytes, keyBinaryObjectWrapper, valueBinaryObjectWrapper);
return new InternalTreeNode<>(bytes, keyBinaryObjectWrapper);
}

@Override
public AbstractTreeNode<K> fromBytes(byte[] bytes, AbstractTreeNode.Type type) {
if (type.equals(AbstractTreeNode.Type.LEAF))
return new AbstractLeafTreeNode<>(bytes, keyBinaryObjectWrapper, valueBinaryObjectWrapper);
return new InternalTreeNode<>(bytes, keyBinaryObjectWrapper);
}
});

}

public BPlusTreeIndexManager(int degree, IndexStorageManager indexStorageManager, BinaryObjectWrapper<K> keyBinaryObjectWrapper, BinaryObjectWrapper<V> valueBinaryObjectWrapper){
this(degree, indexStorageManager, ImmediateCommitIndexIOSession.Factory.getInstance(), keyBinaryObjectWrapper, valueBinaryObjectWrapper);
}

@Override
public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws ExecutionException, InterruptedException, IOException, BinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
IndexIOSession<K> indexIOSession = this.indexIOSessionFactory.create(indexStorageManager, table, nodeFactory);
Expand Down Expand Up @@ -100,7 +125,7 @@ private AbstractTreeNode<K> getRoot(IndexIOSession<K> indexIOSession) throws Exe
}

byte[] emptyNode = indexStorageManager.getEmptyNode();
LeafClusterTreeNode<K> leafTreeNode = (LeafClusterTreeNode<K>) nodeFactory.fromBytes(emptyNode, AbstractTreeNode.Type.LEAF);
AbstractLeafTreeNode<K, ?> leafTreeNode = (AbstractLeafTreeNode<K, ?>) nodeFactory.fromBytes(emptyNode, AbstractTreeNode.Type.LEAF);
leafTreeNode.setAsRoot();

IndexStorageManager.NodeData nodeData = indexIOSession.write(leafTreeNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.github.sepgh.internal.index.tree.node.AbstractTreeNode;
import com.github.sepgh.internal.index.tree.node.InternalTreeNode;
import com.github.sepgh.internal.index.tree.node.data.BinaryObjectWrapper;
import com.google.common.hash.HashCode;

import java.util.AbstractMap;
import java.util.Map;
Expand Down Expand Up @@ -151,6 +152,7 @@ public static <K extends Comparable<K>, V extends Comparable<V>> void setKeyValu
keyInnerObj.size()
);


System.arraycopy(
valueInnerObj.getBytes(),
0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public List<ChildPointers<K>> addAndSplit(K identifier, Pointer pointer, int deg
childPointersList.add(i, new ChildPointers<>(
0,
identifier,
childPointersList.get(i-1).getRight(),
childPointersList.get(i == 0 ? 0 : i-1).getRight(),
pointer // Setting right pointer at index
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@

public interface NodeFactory<K extends Comparable<K>> {
AbstractTreeNode<K> fromBytes(byte[] bytes);
AbstractTreeNode<K> fromBytes(byte[] bytes, Pointer pointer);
AbstractTreeNode<K> fromNodeData(IndexStorageManager.NodeData nodeData);
default AbstractTreeNode<K> fromBytes(byte[] bytes, Pointer pointer) {
AbstractTreeNode<K> treeNode = this.fromBytes(bytes);
treeNode.setPointer(pointer);
return treeNode;
}

default AbstractTreeNode<K> fromNodeData(IndexStorageManager.NodeData nodeData){
return this.fromBytes(nodeData.bytes(), nodeData.pointer());
}
AbstractTreeNode<K> fromBytes(byte[] emptyNode, AbstractTreeNode.Type type);

class ClusterNodeFactory<K extends Comparable<K>> implements NodeFactory<K> {
Expand All @@ -28,18 +35,6 @@ public AbstractTreeNode<K> fromBytes(byte[] bytes) {
return new InternalTreeNode<>(bytes, keyBinaryObjectWrapper);
}

@Override
public AbstractTreeNode<K> fromBytes(byte[] bytes, Pointer pointer) {
AbstractTreeNode<K> treeNode = this.fromBytes(bytes);
treeNode.setPointer(pointer);
return treeNode;
}

@Override
public AbstractTreeNode<K> fromNodeData(IndexStorageManager.NodeData nodeData) {
return this.fromBytes(nodeData.bytes(), nodeData.pointer());
}

@Override
public AbstractTreeNode<K> fromBytes(byte[] bytes, AbstractTreeNode.Type type) {
bytes[0] = type.getSign();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,36 @@
import com.github.sepgh.internal.EngineConfig;
import com.github.sepgh.internal.index.IndexManager;
import com.github.sepgh.internal.index.Pointer;
import com.github.sepgh.internal.index.tree.node.AbstractLeafTreeNode;
import com.github.sepgh.internal.index.tree.node.AbstractTreeNode;
import com.github.sepgh.internal.index.tree.node.InternalTreeNode;
import com.github.sepgh.internal.index.tree.node.NodeFactory;
import com.github.sepgh.internal.index.tree.node.cluster.ClusterBPlusTreeIndexManager;
import com.github.sepgh.internal.index.tree.node.cluster.LeafClusterTreeNode;
import com.github.sepgh.internal.index.tree.node.data.*;
import com.github.sepgh.internal.storage.BTreeSizeCalculator;
import com.github.sepgh.internal.storage.CompactFileIndexStorageManager;
import com.github.sepgh.internal.storage.InMemoryHeaderManager;
import com.github.sepgh.internal.storage.*;
import com.github.sepgh.internal.storage.header.Header;
import com.github.sepgh.internal.storage.header.HeaderManager;
import com.google.common.hash.HashCode;
import com.google.common.primitives.Longs;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;

import static com.github.sepgh.internal.index.tree.node.AbstractTreeNode.TYPE_LEAF_NODE_BIT;
import static com.github.sepgh.internal.storage.BaseFileIndexStorageManager.INDEX_FILE_NAME;

public class BinaryObjectWrapperTestCase {
Expand Down Expand Up @@ -162,5 +173,169 @@ public void test_NoZeroLongIdentifier() throws IOException, ExecutionException,

}

@Test
public void test_CustomBinaryObjectWrapper() throws IOException, ExecutionException, InterruptedException, BinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
HeaderManager headerManager = new InMemoryHeaderManager(header);
CompactFileIndexStorageManager compactFileIndexStorageManager = new CompactFileIndexStorageManager(dbPath, headerManager, engineConfig, new BTreeSizeCalculator(degree, 20, Pointer.BYTES).calculate());

BinaryObjectWrapper<String> keyBinaryObjectWrapper = new StringBinaryObjectWrapper();

NodeFactory<String> nodeFactory = new NodeFactory<>() {
@Override
public AbstractTreeNode<String> fromBytes(byte[] bytes) {
if ((bytes[0] & TYPE_LEAF_NODE_BIT) == TYPE_LEAF_NODE_BIT)
return new AbstractLeafTreeNode<>(bytes, keyBinaryObjectWrapper, new PointerBinaryObjectWrapper());
return new InternalTreeNode<>(bytes, keyBinaryObjectWrapper);
}

@Override
public AbstractTreeNode<String> fromBytes(byte[] bytes, AbstractTreeNode.Type type) {
if (type.equals(AbstractTreeNode.Type.LEAF))
return new AbstractLeafTreeNode<>(bytes, keyBinaryObjectWrapper, new PointerBinaryObjectWrapper());
return new InternalTreeNode<>(bytes, keyBinaryObjectWrapper);
}
};


IndexManager<String, Pointer> indexManager = new BPlusTreeIndexManager<>(degree, compactFileIndexStorageManager, keyBinaryObjectWrapper, new PointerBinaryObjectWrapper(), nodeFactory);


indexManager.addIndex(1, "AAA", Pointer.empty());
indexManager.addIndex(1, "BBB", Pointer.empty());
indexManager.addIndex(1, "CAB", Pointer.empty());
indexManager.addIndex(1, "AAC", Pointer.empty());
indexManager.addIndex(1, "BAC", Pointer.empty());
indexManager.addIndex(1, "CAA", Pointer.empty());

indexManager.addIndex(1, "AAB", Pointer.empty());
indexManager.addIndex(1, "AAD", Pointer.empty());

indexManager.addIndex(1, "ABA", Pointer.empty());
indexManager.addIndex(1, "ABB", Pointer.empty());
indexManager.addIndex(1, "ABC", Pointer.empty());

indexManager.addIndex(1, "ACA", Pointer.empty());
indexManager.addIndex(1, "ACB", Pointer.empty());
indexManager.addIndex(1, "ACC", Pointer.empty());

indexManager.addIndex(1, "BAA", Pointer.empty());
indexManager.addIndex(1, "BAB", Pointer.empty());
indexManager.addIndex(1, "BBA", Pointer.empty());
indexManager.addIndex(1, "BBC", Pointer.empty());


IndexStorageManager.NodeData rootNodeData = compactFileIndexStorageManager.getRoot(1).get().get();
InternalTreeNode<String> rootInternalTreeNode = new InternalTreeNode<>(rootNodeData.bytes(), keyBinaryObjectWrapper);
rootInternalTreeNode.setPointer(rootNodeData.pointer());


InternalTreeNode<String> internalNode1 = (InternalTreeNode<String>) IndexTreeNodeIO.read(compactFileIndexStorageManager, 1, rootInternalTreeNode.getChildrenList().getFirst(), nodeFactory);

AbstractLeafTreeNode<String, Pointer> leaf = (AbstractLeafTreeNode<String, Pointer>) IndexTreeNodeIO.read(compactFileIndexStorageManager, 1, internalNode1.getChildrenList().getFirst(), nodeFactory);
Assertions.assertEquals("AAA", leaf.getKeyList(degree).getFirst());
Assertions.assertEquals("AAB", leaf.getKeyList(degree).getLast());
leaf = (AbstractLeafTreeNode<String, Pointer>) IndexTreeNodeIO.read(compactFileIndexStorageManager, 1, leaf.getNextSiblingPointer(degree).get(), nodeFactory);
Assertions.assertEquals("AAC", leaf.getKeyList(degree).getFirst());
Assertions.assertEquals("AAD", leaf.getKeyList(degree).getLast());
leaf = (AbstractLeafTreeNode<String, Pointer>) IndexTreeNodeIO.read(compactFileIndexStorageManager, 1, leaf.getNextSiblingPointer(degree).get(), nodeFactory);
Assertions.assertEquals("ABA", leaf.getKeyList(degree).getFirst());
Assertions.assertEquals("ABB", leaf.getKeyList(degree).getLast());
leaf = (AbstractLeafTreeNode<String, Pointer>) IndexTreeNodeIO.read(compactFileIndexStorageManager, 1, leaf.getNextSiblingPointer(degree).get(), nodeFactory);
Assertions.assertEquals("ABC", leaf.getKeyList(degree).getFirst());
Assertions.assertEquals("ACA", leaf.getKeyList(degree).getLast());
leaf = (AbstractLeafTreeNode<String, Pointer>) IndexTreeNodeIO.read(compactFileIndexStorageManager, 1, leaf.getNextSiblingPointer(degree).get(), nodeFactory);
Assertions.assertEquals("ACB", leaf.getKeyList(degree).getFirst());
Assertions.assertEquals("ACC", leaf.getKeyList(degree).getLast());
leaf = (AbstractLeafTreeNode<String, Pointer>) IndexTreeNodeIO.read(compactFileIndexStorageManager, 1, leaf.getNextSiblingPointer(degree).get(), nodeFactory);
Assertions.assertEquals("BAA", leaf.getKeyList(degree).getFirst());
Assertions.assertEquals("BAB", leaf.getKeyList(degree).getLast());
leaf = (AbstractLeafTreeNode<String, Pointer>) IndexTreeNodeIO.read(compactFileIndexStorageManager, 1, leaf.getNextSiblingPointer(degree).get(), nodeFactory);
Assertions.assertEquals("BAC", leaf.getKeyList(degree).getFirst());
Assertions.assertEquals("BBA", leaf.getKeyList(degree).get(1));
Assertions.assertEquals("BBC", leaf.getKeyList(degree).getLast());
leaf = (AbstractLeafTreeNode<String, Pointer>) IndexTreeNodeIO.read(compactFileIndexStorageManager, 1, leaf.getNextSiblingPointer(degree).get(), nodeFactory);
Assertions.assertEquals("BBB", leaf.getKeyList(degree).getFirst());
Assertions.assertEquals("CAA", leaf.getKeyList(degree).get(1));
Assertions.assertEquals("CAB", leaf.getKeyList(degree).getLast());


}

private static class StringBinaryObjectWrapper implements BinaryObjectWrapper<String> {
private final int BYTES = 20;
private byte[] bytes;

public StringBinaryObjectWrapper() {
}

public StringBinaryObjectWrapper(byte[] bytes) {
this.bytes = bytes;
}

@Override
public BinaryObjectWrapper<String> load(String s) throws InvalidBinaryObjectWrapperValue {
byte[] temp = s.getBytes(StandardCharsets.UTF_8);
if (temp.length > BYTES) {
throw new InvalidBinaryObjectWrapperValue(s, this.getClass());
}

byte[] result = new byte[BYTES];

System.arraycopy(temp, 0, result, 0, temp.length);

for (int i = temp.length; i < BYTES; i++) {
result[i] = 0;
}

return new StringBinaryObjectWrapper(result);
}

@Override
public BinaryObjectWrapper<String> load(byte[] bytes, int beginning) {
this.bytes = new byte[BYTES];
System.arraycopy(
bytes,
beginning,
this.bytes,
0,
this.size()
);
return this;
}

@Override
public String asObject() {
int len = 0;
while (len < bytes.length && bytes[len] != 0) {
len++;
}
return new String(bytes, 0, len, StandardCharsets.UTF_8);
}

@Override
public Class<String> getObjectClass() {
return String.class;
}

@Override
public boolean hasValue() {
for (byte aByte : this.bytes) {
if (aByte != 0x00)
return true;
}
return false;
}

@Override
public int size() {
return BYTES;
}

@Override
public byte[] getBytes() {
return bytes;
}
}


}

0 comments on commit db4b02d

Please sign in to comment.