private Split newSplitLeft(Node newNode) { Split split = new Split(false, newNode); // New left node cannot be a high extremity, and this node cannot be a low extremity. newNode.type((byte) (type() & ~HIGH_EXTREMITY)); type((byte) (type() & ~LOW_EXTREMITY)); return split; }
/** * Performs a binary search against the split, returning the position * within the original node as if it had not split. */ final int binarySearchLeaf(Node node, byte[] key) throws IOException { Node sibling = latchSibling(); Node left, right; if (mSplitRight) { left = node; right = sibling; } else { left = sibling; right = node; } int searchPos; if (compare(key) < 0) { searchPos = left.binarySearch(key); } else { int highestPos = left.highestLeafPos(); searchPos = right.binarySearch(key); if (searchPos < 0) { searchPos = searchPos - highestPos - 2; } else { searchPos = highestPos + 2 + searchPos; } } sibling.releaseShared(); return searchPos; }
private void cleanupSplit(Throwable cause, Node newNode, Split split) { if (split != null) { cleanupFragments(cause, split.fragmentedKey()); } try { getDatabase().deleteNode(newNode); } catch (Throwable e) { cause.addSuppressed(e); panic(cause); } }
/** * Rebind cursor frames affected by split to correct node and * position. Caller must hold exclusive latch. * * @return latched sibling */ private Node rebindSplitFrames(Split split) { final Node sibling = split.latchSiblingEx(); try { for (CursorFrame frame = mLastCursorFrame; frame != null; ) { // Capture previous frame from linked list before changing the links. CursorFrame prev = frame.mPrevCousin; split.rebindFrame(frame, sibling); frame = prev; } return sibling; } catch (Throwable e) { sibling.releaseExclusive(); throw e; } }
createInternalEntry(frame, result, tree, keyPos, split.splitKeyEncodedLength(), newChildPos << 3, true); } catch (Throwable e) { mSplit.setKey(split); } else { split.copySplitKeyToParent(result.mPage, entryLoc);
} else { try { pos = node.mSplit.binarySearchLeaf(node, key); } catch (Throwable e) { node.releaseShared(); final Node sibling = split.latchSibling(); if (split.compare(key) < 0) { selected = left; selectedPos = Node.internalPos(left.binarySearch(key));
node = childNode; if (node.mSplit != null) { node = node.mSplit.selectNode(node, key); node = node.mSplit.selectNode(node, key); int pos = midPos - node.searchVecStart(); if (node.mSplit != null) { pos = node.mSplit.adjustBindPosition(pos); int pos = lowPos - node.searchVecStart(); if (node.mSplit != null) { pos = node.mSplit.adjustBindPosition(pos); return node.retrieveLeafValue(pos); } else { return node.mSplit.retrieveLeafValue(node, pos);
Split split = new Split(lowTree == survivor, victimNode); split.setKey(survivor, midKey); survivorNode = survivorFrame.acquireExclusive(); survivorNode.mSplit = split; survivorNode.cleanupFragments(e, survivorNode.mSplit.fragmentedKey()); throw e;
/** * When binding to a node which is in a split state, the position must be adjusted in order * for rebindFrame to work properly. The position cannot be used for accessing entries * until after rebindFrame is called, or if retrieveLeafValue is called. * * @param pos non-negative bind position * @return adjusted bind position */ final int adjustBindPosition(int pos) { if (!mSplitRight) { // To prevent the rebind operation from breaking things, the position must be // defined as though it was created before the node was split. When rebindFrame is // called, the position is moved to the correct location. Node sibling = latchSibling(); pos += sibling.highestPos() + 2; sibling.releaseShared(); } return pos; }
node = node.mSplit.selectNode(node, key); pos = node.mSplit.adjustBindPosition(pos); pos = ~node.mSplit.adjustBindPosition(~pos);
/** * Allows a search to continue into a split node by selecting the original node or the * sibling. If the original node is returned, its shared lock is still held. If the * sibling is returned, it will have a shared latch held and the original node's latch * is released. * * @param node node which was split; shared latch must be held * @return original node or sibling */ final Node selectNode(Node node, byte[] key) { Node sibling = mSibling; sibling.acquireShared(); Node left, right; if (mSplitRight) { left = node; right = sibling; } else { left = sibling; right = node; } if (compare(key) < 0) { right.releaseShared(); return left; } else { left.releaseShared(); return right; } }
if (split != null) { frame.bind(node, split.highestPos(node)); node = finishSplitShared(frame, node);
int leftSegTail = split.copySplitKeyToParent(newRootPage, TN_HEADER_SIZE);
createInternalEntry(frame, result, tree, keyPos, split.splitKeyEncodedLength(), newChildPos << 3, true); } catch (Throwable e) { mSplit.setKey(split); } else { split.copySplitKeyToParent(result.mPage, entryLoc);
} else { try { pos = node.mSplit.binarySearchLeaf(node, key); } catch (Throwable e) { node.releaseShared(); final Node sibling = split.latchSibling(); if (split.compare(key) < 0) { selected = left; selectedPos = Node.internalPos(left.binarySearch(key));
node = node.mSplit.selectNode(node, key); int pos = midPos - node.searchVecStart(); if (node.mSplit != null) { pos = node.mSplit.adjustBindPosition(pos); int pos = lowPos - node.searchVecStart(); if (node.mSplit != null) { pos = node.mSplit.adjustBindPosition(pos); return node.retrieveLeafValue(pos); } else { return node.mSplit.retrieveLeafValue(node, pos);
/** * Rebind cursor frames affected by split to correct node and * position. Caller must hold exclusive latch. * * @return latched sibling */ private Node rebindSplitFrames(Split split) { final Node sibling = split.latchSiblingEx(); try { for (CursorFrame frame = mLastCursorFrame; frame != null; ) { // Capture previous frame from linked list before changing the links. CursorFrame prev = frame.mPrevCousin; split.rebindFrame(frame, sibling); frame = prev; } return sibling; } catch (Throwable e) { sibling.releaseExclusive(); throw e; } }
/** * When binding to a node which is in a split state, the position must be adjusted in order * for rebindFrame to work properly. The position cannot be used for accessing entries * until after rebindFrame is called, or if retrieveLeafValue is called. * * @param pos non-negative bind position * @return adjusted bind position */ final int adjustBindPosition(int pos) { if (!mSplitRight) { // To prevent the rebind operation from breaking things, the position must be // defined as though it was created before the node was split. When rebindFrame is // called, the position is moved to the correct location. Node sibling = latchSibling(); pos += sibling.highestPos() + 2; sibling.releaseShared(); } return pos; }
/** * Allows a search to continue into a split node by selecting the original node or the * sibling. If the original node is returned, its shared lock is still held. If the * sibling is returned, it will have a shared latch held and the original node's latch * is released. * * @param node node which was split; shared latch must be held * @return original node or sibling */ final Node selectNode(Node node, byte[] key) { Node sibling = mSibling; sibling.acquireShared(); Node left, right; if (mSplitRight) { left = node; right = sibling; } else { left = sibling; right = node; } if (compare(key) < 0) { right.releaseShared(); return left; } else { left.releaseShared(); return right; } }
if (split != null) { frame.bind(node, split.highestPos(node)); node = finishSplitShared(frame, node);