@Override public TreeBlock createBlock(long parentBlock, DataBlock dataBlock) throws JasDBStorageException { return new TreeBlock(persister, dataBlock, parentBlock, true); } }
@Override public LeaveBlock findFirstLeaveBlock(LockIntentType intentType) throws JasDBStorageException { if(isLeave) { return this; } else { return super.findFirstLeaveBlock(intentType); } }
@Override public LeaveBlock findLeaveBlock(LockIntentType intent, Key key) throws JasDBStorageException { if(isLeave) { return this; } else { return super.findLeaveBlock(intent, key); } }
private void handleBorrowRight(TreeBlock parentBlock, TreeBlock rightSibbling) throws JasDBStorageException { //we can borrow from right TreeNode rightFirstNode = rightSibbling.getNodes().first(); IndexBlock danglingBlock = persister.loadBlock(rightFirstNode.getLeft()); danglingBlock.setParentPointer(getPosition()); Key newKey = getMax(); rightSibbling.removeNodeInternal(rightFirstNode); TreeNode newNode = new TreeNode(newKey, treeNodes.last().getRight(), danglingBlock.getPosition()); treeNodes.put(newKey, newNode); Key parentKey = getMax(); parentBlock.updateBlockPointer(parentKey, getPosition(), rightSibbling.getPosition()); }
protected void handleBlockUnderflow() throws JasDBStorageException { if(treeNodes.size() < persister.getMinKeys()) { LOG.debug("Handling block underflow"); TreeBlock parentBlock = (TreeBlock) persister.loadBlock(parentPointer); long leftSibblingPointer = parentBlock.getLeftSibbling(this); long rightSibblingPointer = parentBlock.getRightSibbling(this); TreeBlock leftSibbling = null; TreeBlock rightSibbling = null; if(leftSibblingPointer != -1) { leftSibbling = (TreeBlock) persister.loadBlock(leftSibblingPointer); } if(rightSibblingPointer != -1) { rightSibbling = (TreeBlock) persister.loadBlock(rightSibblingPointer); } if(leftSibbling != null && leftSibbling.size() > persister.getMinKeys()) { handleBorrowLeft(parentBlock, leftSibbling); } else if(rightSibbling != null && rightSibbling.size() > persister.getMinKeys()) { handleBorrowRight(parentBlock, rightSibbling); } else { //nothing to borrow we need to merge handleMerge(parentBlock, leftSibbling, rightSibbling); } } }
private void handleMerge(TreeBlock parentBlock, TreeBlock leftSibbling, TreeBlock rightSibbling) throws JasDBStorageException { Key removeKey; if(leftSibbling != null) { Key mergeKey = leftSibbling.getMax(); TreeNode leftSibblingLastNode = leftSibbling.getNodes().last(); TreeNode currentFirstNode = treeNodes.first(); removeKey = currentFirstNode.getKey(); TreeNode mergeNode = new TreeNode(mergeKey, leftSibblingLastNode.getRight(), currentFirstNode.getLeft()); leftSibbling.addKey(mergeNode); leftSibbling.addNodes(treeNodes.values(), null, leftSibbling.getPosition()); } else if(rightSibbling != null) { Key mergeKey = getMax(); TreeNode rightFirstNode = rightSibbling.getNodes().first(); TreeNode currentLastNode = treeNodes.last(); removeKey = currentLastNode.getKey(); TreeNode mergeNode = new TreeNode(mergeKey, currentLastNode.getRight(), rightFirstNode.getLeft()); rightSibbling.addKey(mergeNode); rightSibbling.addNodes(treeNodes.values(), null, rightSibbling.getPosition()); } else { throw new JasDBStorageException("Invalid index state there should always be a sibbling tree block"); } treeNodes.reset(); persister.markDeleted(this); parentBlock.removeBlockPointer(removeKey, this); }
@Override public void persistBlock(TreeBlock treeBlock) throws JasDBStorageException { if(treeBlock.isModified()) { LOG.debug("Persisting block at position: {}", treeBlock.getPosition()); List<TreeNode> treeNodes = treeBlock.getNodes().values(); DataBlock dataBlock = treeBlock.getDataBlock(); dataBlock.reset(); dataBlock.getHeader().putLong(PARENTPOINTER_INDEX, treeBlock.getParentPointer()); dataBlock.getHeader().putInt(NODEAMOUNT_INDEX, treeNodes.size()); for(TreeNode treeNode : treeNodes) { dataBlock = writeKey(treeBlock, treeNode.getKey(), dataBlock); dataBlock = dataBlock.writeLong(treeNode.getLeft()).getDataBlock(); dataBlock = dataBlock.writeLong(treeNode.getRight()).getDataBlock(); } } }
private void handleBlockOverflow() throws JasDBStorageException { if(treeNodes.size() > persister.getMaxKeys()) { List<TreeNode>[] blockNodeSplit = treeNodes.split(); List<TreeNode> leftBlockNodes = blockNodeSplit[0]; List<TreeNode> rightBlockNodes = blockNodeSplit[1]; treeNodes.reset(); Key promoteKey = rightBlockNodes.get(0).getKey(); TreeBlock leftBlock = (TreeBlock) persister.createBlock(BlockTypes.NODEBLOCK, getParentPointer()); leftBlock.addNodes(leftBlockNodes, null, leftBlock.getPosition()); if(parentPointer != -1) { //add the nodes, we use -1 as parent does not need to be changed addNodes(rightBlockNodes, promoteKey, getPosition()); TreeBlock parentBlock = (TreeBlock) persister.loadBlock(parentPointer); parentBlock.insertBlock(promoteKey, leftBlock, this); } else { //we are at the root TreeBlock rightBlock = (TreeBlock) persister.createBlock(BlockTypes.NODEBLOCK, getPosition()); rightBlock.addNodes(rightBlockNodes, promoteKey, rightBlock.getPosition()); TreeNode node = new TreeNode(promoteKey, leftBlock.getPosition(), rightBlock.getPosition()); treeNodes.put(node.getKey(), node); } } }
@Override public TreeBlock loadBlock(DataBlock dataBlock) throws JasDBStorageException { TreeBlock treeBlock = createBlock(-1, dataBlock); treeBlock.setModified(false); treeBlock.setParentPointer(dataBlock.getHeader().getLong(PARENTPOINTER_INDEX)); int nrNodes = dataBlock.getHeader().getInt(NODEAMOUNT_INDEX); int offset = 0; DataBlock currentBlock = dataBlock; for(int i=0; i<nrNodes; i++) { KeyLoadResult loadedKeyResult = loadKeyResult(treeBlock, offset, currentBlock); DataBlockResult<Long> leftPointerResult = loadedKeyResult.getEndBlock().loadLong(loadedKeyResult.getNextOffset()); DataBlockResult<Long> rightPointerResult = leftPointerResult.getEndBlock().loadLong(leftPointerResult.getNextOffset()); TreeNode node = new TreeNode(loadedKeyResult.getLoadedKey(), leftPointerResult.getValue(), rightPointerResult.getValue()); treeBlock.addKey(node); LOG.trace("Loaded Key: {} with left: {} and right: {} on block: {}", node.getKey(), node.getLeft(), node.getRight(), treeBlock.getPosition()); offset = rightPointerResult.getNextOffset(); currentBlock = rightPointerResult.getEndBlock(); } return treeBlock; }
protected long getLeftSibbling(TreeBlock block) { TreeNode beforeNode = treeNodes.getBefore(block.getFirst()); if(beforeNode.getLeft() != block.getPosition()) { return beforeNode.getLeft(); } else { return -1; } }
protected long getRightSibbling(TreeBlock block) { TreeNode beforeNode = treeNodes.getBefore(block.getLast()); if(beforeNode.getRight() == block.getPosition()) { TreeNode nextNode = treeNodes.next(beforeNode.getKey()); return nextNode != null ? nextNode.getRight() : -1; } else { //this only happens with one node return beforeNode.getRight(); } }
@Override public void persistBlock(TreeBlock treeBlock) throws JasDBStorageException { writeHeader(treeBlock.getDataBlock(), ((RootBlock)treeBlock).isLeave()); super.persistBlock(treeBlock); }
protected Key getMax() throws JasDBStorageException { TreeNode node = treeNodes.last(); IndexBlock rightBlock = persister.loadBlock(node.getRight()); if(rightBlock instanceof TreeBlock) { return ((TreeBlock) rightBlock).getMax(); } else { return rightBlock.getLast(); } } }
private void handleBorrowLeft(TreeBlock parentBlock, TreeBlock leftSibbling) throws JasDBStorageException { //we can borrow from left TreeNode node = leftSibbling.getNodes().last(); //this block needs relinking IndexBlock danglingBlock = persister.loadBlock(node.getRight()); danglingBlock.setParentPointer(getPosition()); Key newKey = leftSibbling.getMax(); leftSibbling.removeNodeInternal(node); TreeNode newNode = new TreeNode(newKey, danglingBlock.getPosition(), treeNodes.first().getLeft()); treeNodes.put(newKey, newNode); parentBlock.updateBlockPointer(leftSibbling.getMax(), leftSibbling.getPosition(), getPosition()); }