Skip to content

Commit

Permalink
fix: remove TreeNodeUtils.addKeyAndGetIndex method
Browse files Browse the repository at this point in the history
  • Loading branch information
sepgh committed May 25, 2024
1 parent ef43262 commit 618bdcf
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ public BaseTreeNode addIndex(int table, long identifier, Pointer pointer) throws
InternalTreeNode currentInternalTreeNode = (InternalTreeNode) currentNode;
if (currentInternalTreeNode.getKeyList(degree).size() < degree - 1) {
/* current internal node can store the key */
currentInternalTreeNode.addChildPointers(idForParentToStore, null, newChildForParent.getPointer(), degree, false);
int indexOfAddedKey = currentInternalTreeNode.addKey(idForParentToStore, degree);
if (newChildForParent.getKeyList(degree).getFirst() < idForParentToStore){
currentInternalTreeNode.addChildAtIndex(indexOfAddedKey, newChildForParent.getPointer());
} else {
currentInternalTreeNode.addChildAtIndex(indexOfAddedKey + 1, newChildForParent.getPointer());
}
TreeNodeIO.write(currentInternalTreeNode, indexStorageManager, table).get();
return answer;
}
Expand Down
69 changes: 0 additions & 69 deletions src/main/java/com/github/sepgh/internal/tree/TreeNodeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -247,75 +247,6 @@ public static void removeKeyValueAtIndex(BaseTreeNode treeNode, int index) {
}
}

/**
* @param treeNode to read/write from/to
* @param key to add
* @return index which key is added to
* Todo: performance improvements may be possible
* linear search is used to sort the keys
* binary search could be used
* alternatively, we can hold a space for metadata which keeps track of the number of keys or values stored
*/
public static int addKeyAndGetIndex(BaseTreeNode treeNode, long key, int degree) {
// Shall only be called on internal nodes
if (treeNode.isLeaf()){
throw new RuntimeException(); // Todo: not runtime
}

int indexToFill = 0;
long keyAtIndex = 0;
for (int i = 0; i < degree - 1; i++){
keyAtIndex = getKeyAtIndex(treeNode, i);
if (keyAtIndex == 0 || keyAtIndex > key){
indexToFill = i;
break;
}
}

if (keyAtIndex == 0){
System.arraycopy(
Longs.toByteArray(key),
0,
treeNode.getData(),
OFFSET_INTERNAL_NODE_KEY_BEGIN + (indexToFill * (SIZE_INTERNAL_NODE_KEY_POINTER)),
Long.BYTES
);
return indexToFill;
}


int max = degree - 1;
int fullSize = (max * SIZE_INTERNAL_NODE_KEY_POINTER) + OFFSET_INTERNAL_NODE_KEY_BEGIN;
int bufferSize = fullSize - ((indexToFill + 1) * SIZE_INTERNAL_NODE_KEY_POINTER) - OFFSET_INTERNAL_NODE_KEY_BEGIN;

byte[] temp = new byte[bufferSize];
System.arraycopy(
treeNode.getData(),
OFFSET_INTERNAL_NODE_KEY_BEGIN + (indexToFill * SIZE_INTERNAL_NODE_KEY_POINTER),
temp,
0,
temp.length
);

System.arraycopy(
Longs.toByteArray(key),
0,
treeNode.getData(),
OFFSET_INTERNAL_NODE_KEY_BEGIN + (indexToFill * SIZE_INTERNAL_NODE_KEY_POINTER),
Long.BYTES
);

System.arraycopy(
temp,
0,
treeNode.getData(),
OFFSET_INTERNAL_NODE_KEY_BEGIN + ((indexToFill + 1) * SIZE_INTERNAL_NODE_KEY_POINTER),
temp.length
);

return indexToFill;
}

public static Optional<Pointer> getPreviousPointer(BaseTreeNode treeNode, int degree){
if (treeNode.getData()[OFFSET_LEAF_NODE_KEY_BEGIN + ((degree - 1) * SIZE_LEAF_NODE_KEY_POINTER)] == (byte) 0x0){
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ public int addKey(long identifier, int degree) {

public void addChildPointers(long identifier, @Nullable Pointer left, @Nullable Pointer right, int degree, boolean clearForNull){
modified();
// Todo: since we spotted an issue with (addKeyAndGetIndex), using this.addKey() should be feasible but using it would break some test cases and needs investigation to see if test is wrong or the implementation is wrong
int i = TreeNodeUtils.addKeyAndGetIndex(this, identifier, degree);
int i = this.addKey(identifier, degree);
if (left != null){
TreeNodeUtils.setPointerToChild(this, i, left);
}
Expand Down Expand Up @@ -92,6 +91,16 @@ public List<Pointer> getChildrenList(){
return ImmutableList.copyOf(getChildren());
}

public void addChildAtIndex(int index, Pointer pointer){
List<Pointer> childrenList = new ArrayList<>(this.getChildrenList());
childrenList.add(index, pointer);

for (int i = index; i < childrenList.size(); i++){
this.setChildAtIndex(i, childrenList.get(i));
}

}

public void setChildAtIndex(int index, Pointer pointer){
TreeNodeUtils.setPointerToChild(this, index, pointer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ private void printLeafNode(LeafTreeNode node, int offset){
}
System.out.println("Key Values:");
System.out.println(stringBuilder);
System.out.println("Prev: " + node.getPreviousSiblingPointer(engineConfig.getBTreeNodeMaxKey() + 1));
System.out.println("Next: " + node.getNextSiblingPointer(engineConfig.getBTreeNodeMaxKey() + 1));
System.out.println("===========================");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.sepgh.internal.tree.storing;

import com.github.sepgh.internal.EngineConfig;
import com.github.sepgh.internal.helper.IndexFileDescriptor;
import com.github.sepgh.internal.storage.FileIndexStorageManager;
import com.github.sepgh.internal.storage.InMemoryHeaderManager;
import com.github.sepgh.internal.storage.header.Header;
Expand All @@ -16,6 +17,7 @@
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
Expand Down Expand Up @@ -190,16 +192,28 @@ public void testMultiSplitAddIndex2() throws IOException, ExecutionException, In

List<Long> testIdentifiers = Arrays.asList(1L, 4L, 9L, 6L, 10L, 8L, 3L, 2L, 11L, 5L, 7L, 12L);
Pointer samplePointer = new Pointer(Pointer.TYPE_DATA, 100, 0);
HeaderManager headerManager = new InMemoryHeaderManager(header);
FileIndexStorageManager fileIndexStorageManager = new FileIndexStorageManager(dbPath, headerManager, engineConfig);
IndexManager indexManager = new BPlusTreeIndexManager(degree, fileIndexStorageManager);

IndexFileDescriptor indexFileDescriptor = new IndexFileDescriptor(
AsynchronousFileChannel.open(
Path.of(dbPath.toString(), String.format("%s.%d", INDEX_FILE_NAME, 0)),
StandardOpenOption.READ,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE
),
headerManager,
engineConfig
);

for (int tableId = 1; tableId <= 2; tableId++){
HeaderManager headerManager = new InMemoryHeaderManager(header);
FileIndexStorageManager fileIndexStorageManager = new FileIndexStorageManager(dbPath, headerManager, engineConfig);
IndexManager indexManager = new BPlusTreeIndexManager(degree, fileIndexStorageManager);


BaseTreeNode lastTreeNode = null;
for (long testIdentifier : testIdentifiers) {
lastTreeNode = indexManager.addIndex(tableId, testIdentifier, samplePointer);
System.out.println("Adding " + testIdentifier + " to table " + tableId);
indexFileDescriptor.describe();
}

Assertions.assertTrue(lastTreeNode.isLeaf());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static void testUnOrderedTreeStructure1(IndexStorageManager indexStorageM
// 2nd Leaf
Optional<Pointer> nextPointer = currentLeaf.getNextSiblingPointer(degree);
Assertions.assertTrue(nextPointer.isPresent());
Assertions.assertEquals(nextPointer.get(), leftChildInternalNode.getChildPointersList(degree).get(0).getRight());
Assertions.assertEquals(nextPointer.get(), leftChildInternalNode.getChildAtIndex(1));

currentLeaf = (LeafTreeNode) TreeNodeIO.read(indexStorageManager, table, leftChildInternalNode.getChildPointersList(degree).get(0).getRight());
currentLeafKeys = currentLeaf.getKeyList(degree);
Expand Down

0 comments on commit 618bdcf

Please sign in to comment.