Node cloneNode() { Node newNode = new Node(mUsageList, mPage); newNode.mId = mId; newNode.mCachedState = mCachedState; /*P*/ // [ newNode.type(type()); newNode.garbage(garbage()); newNode.leftSegTail(leftSegTail()); newNode.rightSegTail(rightSegTail()); newNode.searchVecStart(searchVecStart()); newNode.searchVecEnd(searchVecEnd()); /*P*/ // ] return newNode; }
/** * Acquire an exclusive latch on this frame's bound node. * * @return frame node */ final Node acquireExclusive() { Node node = mNode; while (true) { node.acquireExclusive(); Node actualNode = mNode; if (actualNode == node) { return actualNode; } node.releaseExclusive(); node = actualNode; } }
/** * Acquire a shared latch on this frame's bound node. * * @return frame node */ final Node acquireShared() { Node node = mNode; while (true) { node.acquireShared(); Node actualNode = mNode; if (actualNode == node) { return actualNode; } node.releaseShared(); node = actualNode; } }
/** * Must be called when object is no longer referenced. */ void delete(LocalDatabase db) { acquireExclusive(); try { doDelete(db); } finally { releaseExclusive(); } }
/** * Caller must hold any latch. */ int availableBytes() { return isLeaf() ? availableLeafBytes() : availableInternalBytes(); }
/** * Returns true if non-leaf is not split and underutilized. If so, it should be * merged with its neighbors, and possibly deleted. Caller must hold any latch. */ boolean shouldInternalMerge() { return shouldMerge(availableInternalBytes()); }
final int searchVecStart = searchVecStart(); int loc; start = loc = p_ushortGetLE(page, searchVecStart + pos); loc += keyLengthAtLoc(page, loc); garbage = garbage() + loc + len - start; break quick; garbage(garbage() + loc + len - copyToLeafValue (page, vfrag, value, valueHeaderLoc) - valueLen); int searchVecEnd = searchVecEnd(); int leftSpace = searchVecStart - leftSegTail(); int rightSpace = rightSegTail() - searchVecEnd - 1; encodedLen = keyLen + calculateFragmentedValueLength(value); } else { LocalDatabase db = tree.mDatabase; encodedLen = keyLen + calculateLeafValueLength(value); if (encodedLen > db.mMaxEntrySize) { value = db.fragment(value, value.length, db.mMaxFragmentedEntrySize - keyLen); encodedLen = keyLen + calculateFragmentedValueLength(value); vfrag = ENTRY_FRAGMENTED; if ((entryLoc = allocPageEntry(encodedLen, leftSpace, rightSpace)) >= 0) { pos += searchVecStart;
int searchVecStart = searchVecStart() + pos; int searchVecLoc = searchVecEnd(); int encodedLen = leafEntryLengthAtLoc(leftPage, entryLoc); if (childPos >= parent.highestInternalPos() || parent.mSplit != null || parent.mCachedState != mCachedState) parent.releaseExclusive(); return 0; right = parent.tryLatchChildNotSplit(childPos + 2); } catch (IOException e) { return 0; parent.releaseExclusive(); return 0; int rightAvail = right.availableLeafBytes(); if (rightAvail >= moveAmount) { int highPos = firstSearchVecLoc - searchVecStart(); newKey = midKey(highPos - 2, this, highPos); newKeyLen = calculateAllowedKeyLength(tree.mDatabase, newKey); if (newKeyLen > 0) { parentPage = parent.mPage; parentKeyLoc = p_ushortGetLE
int type = type() & ~(LOW_EXTREMITY | HIGH_EXTREMITY); if (type != TYPE_TN_IN && type != TYPE_TN_BIN && !isLeaf()) { return verifyFailed(level, observer, "Not a tree node: " + type); if (leftSegTail() < TN_HEADER_SIZE) { return verifyFailed(level, observer, "Left segment tail: " + leftSegTail()); if (searchVecStart() < leftSegTail()) { return verifyFailed(level, observer, "Search vector start: " + searchVecStart()); if (searchVecEnd() < (searchVecStart() - 2)) { return verifyFailed(level, observer, "Search vector end: " + searchVecEnd()); if (rightSegTail() < searchVecEnd() || rightSegTail() > (pageSize(page) - 1)) { return verifyFailed(level, observer, "Right segment tail: " + rightSegTail()); if (!isLeaf()) { int childIdsStart = searchVecEnd() + 2; int childIdsEnd = childIdsStart + ((childIdsStart - searchVecStart()) << 2) + 8; if (childIdsEnd > (rightSegTail() + 1)) { return verifyFailed(level, observer, "Child ids end: " + childIdsEnd); long childId = p_uint48GetLE(page, i); if (mId > 1 && childId <= 1) { // stubs don't have a valid child id return verifyFailed(level, observer, "Illegal child id: " + childId); return verifyFailed(level, observer, "Duplicate child id: " + childId); int used = TN_HEADER_SIZE + rightSegTail() + 1 - leftSegTail();
newRootPage = child.mPage; child.mPage = mPage; child.type(type()); child.garbage(garbage()); child.leftSegTail(leftSegTail()); child.rightSegTail(rightSegTail()); child.searchVecStart(searchVecStart()); child.searchVecEnd(searchVecEnd()); /*P*/ // | /*P*/ // if (db.mFullyMapped) { final Node sibling = rebindSplitFrames(split); mSplit = null; final int searchVecStart = pageSize(newRootPage) - (((pageSize(newRootPage) - leftSegTail + (2 + 8 + 8)) >> 1) & ~1); p_shortPutLE(newRootPage, searchVecStart, TN_HEADER_SIZE); p_longPutLE(newRootPage, searchVecStart + 2, left.mId); p_longPutLE(newRootPage, searchVecStart + 2 + 8, right.mId); byte newType = isLeaf() ? (byte) (TYPE_TN_BIN | LOW_EXTREMITY | HIGH_EXTREMITY) : (byte) (TYPE_TN_IN | LOW_EXTREMITY | HIGH_EXTREMITY); type(newType); garbage(0); /*P*/ // | /*P*/ // p_intPutLE(newRootPage, 0, newType & 0xff); // type, reserved byte, and garbage /*P*/ // ] leftSegTail(leftSegTail);
Node highNode = highCursor.notSplitDirty(highFrame); try { midKey = lowNode.midKey(lowNode.highestLeafPos(), highNode, 0); } finally { highNode.releaseExclusive(); lowNode.releaseExclusive(); survivorNode.mSplit = split; } finally { victimNode.releaseExclusive(); survivor.finishSplit(survivorFrame, survivorNode).releaseExclusive(); } catch (Throwable e) { survivorNode.cleanupFragments(e, survivorNode.mSplit.fragmentedKey()); throw e; rootNode.acquireExclusive(); if (rootNode.numKeys() == 1 && rootNode.isInternal()) { rightNode = db.latchChildRetainParentEx(rootNode, 2, true); } catch (Throwable e) { leftNode.releaseExclusive(); throw e; if (leftNode.isLeaf()) { int leftAvail = leftNode.availableLeafBytes();
if (!node.shouldInternalMerge()) { childNode.releaseExclusive(); node.releaseExclusive(); return; if (!node.hasKeys() && node == mTree.mRoot) { childNode.releaseExclusive(); node.releaseExclusive(); if (parentNode.isLeaf()) { throw new AssertionError("Parent node is a leaf"); if (!node.shouldMerge(nodeAvail = node.availableInternalBytes())) { node.releaseExclusive(); parentNode.releaseExclusive(); return; leftNode = latchChildRetainParentEx(parentNode, pos - 2, false); } catch (Throwable e) { node.releaseExclusive(); throw e; node.releaseExclusive(); parentNode.insertSplitChildRef(parentFrame, mTree, pos - 2, leftNode); continue; if (pos >= parentNode.highestInternalPos()) {
int searchVecStart = searchVecStart(); int searchVecEnd = searchVecEnd(); int leftSpace = searchVecStart - leftSegTail(); int rightSpace = rightSegTail() - searchVecEnd - ((searchVecEnd - searchVecStart) << 2) - 17; (entryLoc = allocPageEntry(encodedLen, leftSpace, rightSpace)) >= 0) page, searchVecStart + keyPos - 8, searchVecEnd - searchVecStart + 2 - keyPos + newChildPos); searchVecStart(searchVecStart -= 10); keyPos += searchVecStart; searchVecEnd(searchVecEnd -= 8); newChildPos += searchVecEnd + 2; break alloc; (entryLoc = allocPageEntry(encodedLen, leftSpace, rightSpace)) >= 0) searchVecStart(searchVecStart); keyPos += searchVecStart; p_copy(page, searchVecEnd + newChildPos + 2, if (garbage() > remaining) { compact: { if ((garbage() + remaining) < 0) { int adjust = tryRebalanceInternalLeft
lock = new Node(childId); releaseEither(); throw e; childNode.acquireShared(); if (childId == childNode.mId) { return childNode; childNode.releaseShared(); } else { childNode.acquireExclusive(); if (childId == childNode.mId) { return childNode; childNode.releaseExclusive(); releaseShared(); childNode.read(db, childId); } catch (Throwable e) { childNode.type(TYPE_NONE); childNode.releaseExclusive(); throw e; childNode.downgrade(); releaseEither();
node.releaseExclusive(); if (!node.shouldMerge(nodeAvail = node.availableLeafBytes())) { node.releaseExclusive(); parentNode.releaseExclusive(); return; leftNode = latchChildRetainParentEx(parentNode, pos - 2, false); } catch (Throwable e) { node.releaseExclusive(); throw e; node.releaseExclusive(); parentNode.insertSplitChildRef(parentFrame, mTree, pos - 2, leftNode); continue; if (pos >= parentNode.highestInternalPos()) { rightNode = null; } else { } catch (Throwable e) { if (leftNode != null) { leftNode.releaseExclusive(); node.releaseExclusive(); throw e; leftNode.releaseExclusive();
if (childPos >= parent.highestInternalPos() || parent.mSplit != null || parent.mCachedState != mCachedState) parent.releaseExclusive(); return false; int searchVecStart = searchVecStart() + keyPos; int searchVecLoc = searchVecEnd(); int len = keyLengthAtLoc(leftPage, keyLoc) + (2 + 8); keyLoc = p_ushortGetLE(parentPage, parent.searchVecStart() + childPos); rightGrowth += keyLengthAtLoc(parentPage, keyLoc) + (2 + 8); parent.releaseExclusive(); return false; right = parent.tryLatchChildNotSplit(childPos + 2); } catch (IOException e) { return false; parent.releaseExclusive(); return false; int rightAvail = right.availableInternalBytes(); if (rightAvail >= rightGrowth) { searchKeyLen = keyLengthAtLoc(leftPage, searchKeyLoc);
int searchVecStart = searchVecStart(); int searchVecEnd = searchVecEnd(); int leftSpace = searchVecStart - leftSegTail(); int rightSpace = rightSegTail() - searchVecEnd - 1; (entryLoc = allocPageEntry(encodedLen, leftSpace, rightSpace)) >= 0) searchVecStart(searchVecStart); break alloc; (entryLoc = allocPageEntry(encodedLen, leftSpace, rightSpace)) >= 0) searchVecEnd(searchVecEnd); break alloc; if (garbage() > remaining) { if (garbage() + remaining >= 0) { return compactLeaf(encodedLen, pos, true); int result = tryRebalanceLeaf(tree, parentFrame, pos, encodedLen, -remaining); if (result > 0) { return ~(garbage() + leftSpace + rightSpace); if (remaining > 0 || (rightSegTail() & 1) != 0) { newSearchVecStart = (rightSegTail() - vecLen + (1 - 2) - (remaining >> 1)) & ~1;
int garbage = garbage() + encodedLen - growth; int searchVecStart = searchVecStart(); int searchVecEnd = searchVecEnd(); int leftSpace = searchVecStart - leftSegTail(); int rightSpace = rightSegTail() - searchVecEnd - ((searchVecEnd - searchVecStart) << 2) - 17; if ((entryLoc = allocPageEntry(encodedLen, leftSpace, rightSpace)) >= 0) { pos += searchVecStart; break alloc; if (remaining > 0 || (rightSegTail() & 1) != 0) { (rightSegTail() - vecLen - childIdsLen + (1 - 0) - (remaining >> 1)) & ~1; entryLoc = leftSegTail(); leftSegTail(entryLoc + encodedLen); } else if ((leftSegTail() & 1) == 0) { newSearchVecStart = leftSegTail() + ((remaining >> 1) & ~1); entryLoc = rightSegTail() - encodedLen + 1; rightSegTail(entryLoc - 1); } else { searchVecStart(newSearchVecStart); searchVecEnd(newSearchVecStart + vecLen - 2);
long avail = node.availableLeafBytes() - growth; if (avail < 0) { throw new Error("split 1: " + node.availableLeafBytes() + ", " + growth); int searchVecStart = node.searchVecStart(); final int len = Node.keyLengthAtLoc(page, loc); key = new byte[len]; p_copyToArray(page, loc, key, 0, len); int newValueLen = Node.calculateFragmentedValueLength(value.length + igrowth); /*P*/ byte[] upage = upper.mPage; p_int48PutLE(upage, 0, inode.mId); inode.releaseExclusive(); inode.releaseExclusive(); newValueLen = Node.calculateFragmentedValueLength(value.length); igrowth = 0; node.finishDeleteLeafEntry(pos, loc - entryLoc); entryLoc = node.createLeafEntry(null, tree, pos, key.length + newValueLen); entryLoc = Node.encodeLeafValueHeader (page, Node.ENTRY_FRAGMENTED, value.length + igrowth, entryLoc);
node.asTrimmedRoot(); } finally { node.releaseExclusive(); Node parentNode = parentFrame.acquireExclusive(); if (parentNode.hasKeys()) { parentNode.deleteRightChildRef(parentNode.highestInternalPos()); } else { if (!deleteHighestNode(parentFrame, parentNode)) { int pos = parentNode.highestInternalPos(); Node previous = mTree.mDatabase.latchChildRetainParentEx(parentNode, pos, true); parentNode.updateChildRefId(pos, previous.mId); parentNode.releaseExclusive(); frame.mNodePos = previous.highestPos(); previous.mLastCursorFrame = frame; previous.type((byte) (previous.type() | Node.HIGH_EXTREMITY)); previous.releaseExclusive();