blob: 0c569f25ba5b8fdad1da1084e6efed8189b8d1e8 [file] [log] [blame]
/*
* Copyright 2009-2010 by The Regents of the University of California
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may obtain a copy of the License from
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.uci.ics.hyracks.dataflow.std.sort;
import java.nio.ByteBuffer;
import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAccessor;
import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAppender;
/**
* @author pouria Implements Memory Manager based on creating Binary Search Tree
* (BST) while Free slot size is the key for the BST nodes. Each node in
* BST shows a class of free slots, while all the free slots within a
* class have same lengths. Slots in a class are stored as a LinkedList,
* whose head is the BST node, corresponding to that class. BST is not
* stored as a separate data structure, but the free slots in the memory
* are used to hold BST nodes. Each BST node has the logical structure,
* defined in the BSTNodeUtil class.
*/
public class BSTMemMgr implements IMemoryManager {
private final IHyracksTaskContext ctx;
public static int frameSize;
private ByteBuffer[] frames;
private ByteBuffer convertBuffer;
private Slot root;
private Slot result; // A reusable object to hold one node returned as
// method result
private Slot insertSlot; // A reusable object to hold one node within insert
// process
private Slot lastLeftParent; // A reusable object for the search process
private Slot lastLeft; // A reusable object for the search process
private Slot parent; // A reusable object for the search process
private Slot[] parentRes;
private int lastFrame;
public BSTMemMgr(IHyracksTaskContext ctx, int memSize) {
this.ctx = ctx;
frameSize = ctx.getFrameSize();
convertBuffer = ByteBuffer.allocate(4);
frames = new ByteBuffer[memSize];
lastFrame = -1;
root = new Slot();
insertSlot = new Slot();
result = new Slot();
lastLeftParent = new Slot();
lastLeft = new Slot();
parent = new Slot();
parentRes = new Slot[] { new Slot(), new Slot() };
}
/**
* result is the container sent by the caller to hold the results
*/
@Override
public void allocate(int length, Slot result) throws HyracksDataException {
search(length, parentRes);
if (parentRes[1].isNull()) {
addFrame(parentRes);
if (parentRes[1].isNull()) {
return;
}
}
int sl = BSTNodeUtil.getLength(parentRes[1], frames, convertBuffer);
int acLen = BSTNodeUtil.getActualLength(length);
if (shouldSplit(sl, acLen)) {
int[] s = split(parentRes[1], parentRes[0], acLen);
int insertLen = BSTNodeUtil.getLength(s[2], s[3], frames, convertBuffer);
insert(s[2], s[3], insertLen); // inserting second half of the split
// slot
BSTNodeUtil.setHeaderFooter(s[0], s[1], length, false, frames);
result.set(s[0], s[1]);
return;
}
allocate(parentRes[1], parentRes[0], length, result);
}
@Override
public int unallocate(Slot s) throws HyracksDataException {
int usedLen = BSTNodeUtil.getLength(s, frames, convertBuffer);
int actualLen = BSTNodeUtil.getActualLength(usedLen);
int fix = s.getFrameIx();
int off = s.getOffset();
int prevMemSlotFooterOffset = ((off - BSTNodeUtil.HEADER_SIZE) >= 0 ? (off - BSTNodeUtil.HEADER_SIZE)
: BSTNodeUtil.INVALID_INDEX);
int t = off + 2 * BSTNodeUtil.HEADER_SIZE + actualLen;
int nextMemSlotHeaderOffset = (t < frameSize ? t : BSTNodeUtil.INVALID_INDEX);
// Remember: next and prev memory slots have the same frame index as the
// unallocated slot
if (!isNodeNull(fix, prevMemSlotFooterOffset) && BSTNodeUtil.isFree(fix, prevMemSlotFooterOffset, frames)) {
int leftLength = BSTNodeUtil.getLength(fix, prevMemSlotFooterOffset, frames, convertBuffer);
removeFromList(fix, prevMemSlotFooterOffset - leftLength - BSTNodeUtil.HEADER_SIZE);
int concatLength = actualLen + leftLength + 2 * BSTNodeUtil.HEADER_SIZE;
if (!isNodeNull(fix, nextMemSlotHeaderOffset) && BSTNodeUtil.isFree(fix, nextMemSlotHeaderOffset, frames)) {
removeFromList(fix, nextMemSlotHeaderOffset);
concatLength += BSTNodeUtil.getLength(fix, nextMemSlotHeaderOffset, frames, convertBuffer) + 2
* BSTNodeUtil.HEADER_SIZE;
}
insert(fix, prevMemSlotFooterOffset - leftLength - BSTNodeUtil.HEADER_SIZE, concatLength); // newly
// (merged)
// slot
// starts
// at
// the
// prev
// slot
// offset
return concatLength;
} else if (!isNodeNull(fix, nextMemSlotHeaderOffset)
&& BSTNodeUtil.isFree(fix, nextMemSlotHeaderOffset, frames)) {
removeFromList(fix, nextMemSlotHeaderOffset);
int concatLength = actualLen + BSTNodeUtil.getLength(fix, nextMemSlotHeaderOffset, frames, convertBuffer)
+ 2 * BSTNodeUtil.HEADER_SIZE;
insert(fix, off, concatLength); // newly (merged) slot starts at the
// unallocated slot offset
return concatLength;
}
// unallocated slot is not merging with any neighbor
insert(fix, off, actualLen);
return actualLen;
}
@Override
public boolean readTuple(int frameIx, int offset, FrameTupleAppender dest) {
int offToRead = offset + BSTNodeUtil.HEADER_SIZE;
int length = BSTNodeUtil.getLength(frameIx, offset, frames, convertBuffer);
return dest.append(frames[frameIx].array(), offToRead, length);
}
@Override
public boolean writeTuple(int frameIx, int offset, FrameTupleAccessor src, int tIndex) {
int offToCopy = offset + BSTNodeUtil.HEADER_SIZE;
int tStartOffset = src.getTupleStartOffset(tIndex);
int tEndOffset = src.getTupleEndOffset(tIndex);
int tupleLength = tEndOffset - tStartOffset;
ByteBuffer srcBuffer = src.getBuffer();
System.arraycopy(srcBuffer.array(), tStartOffset, frames[frameIx].array(), offToCopy, tupleLength);
return true;
}
@Override
public ByteBuffer getFrame(int frameIndex) {
return frames[frameIndex];
}
@Override
public void close() {
//clean up all frames
for (int i = 0; i < frames.length; i++)
frames[i] = null;
}
/**
* @param parentResult
* is the container passed by the caller to contain the results
* @throws HyracksDataException
*/
private void addFrame(Slot[] parentResult) throws HyracksDataException {
clear(parentResult);
if ((lastFrame + 1) >= frames.length) {
return;
}
frames[++lastFrame] = allocateFrame();
int l = frameSize - 2 * BSTNodeUtil.HEADER_SIZE;
BSTNodeUtil.setHeaderFooter(lastFrame, 0, l, true, frames);
initNewNode(lastFrame, 0);
parentResult[1].copy(root);
if (parentResult[1].isNull()) { // root is null
root.set(lastFrame, 0);
initNewNode(root.getFrameIx(), root.getOffset());
parentResult[1].copy(root);
return;
}
while (!parentResult[1].isNull()) {
if (BSTNodeUtil.getLength(parentResult[1], frames, convertBuffer) == l) {
append(parentResult[1].getFrameIx(), parentResult[1].getOffset(), lastFrame, 0);
parentResult[1].set(lastFrame, 0);
return;
}
if (l < BSTNodeUtil.getLength(parentResult[1], frames, convertBuffer)) {
if (isNodeNull(BSTNodeUtil.getLeftChildFrameIx(parentResult[1], frames, convertBuffer),
BSTNodeUtil.getLeftChildOffset(parentResult[1], frames, convertBuffer))) {
BSTNodeUtil.setLeftChild(parentResult[1].getFrameIx(), parentResult[1].getOffset(), lastFrame, 0,
frames);
parentResult[0].copy(parentResult[1]);
parentResult[1].set(lastFrame, 0);
return;
} else {
parentResult[0].copy(parentResult[1]);
parentResult[1].set(BSTNodeUtil.getLeftChildFrameIx(parentResult[1], frames, convertBuffer),
BSTNodeUtil.getLeftChildOffset(parentResult[1], frames, convertBuffer));
}
} else {
if (isNodeNull(BSTNodeUtil.getRightChildFrameIx(parentResult[1], frames, convertBuffer),
BSTNodeUtil.getRightChildOffset(parentResult[1], frames, convertBuffer))) {
BSTNodeUtil.setRightChild(parentResult[1].getFrameIx(), parentResult[1].getOffset(), lastFrame, 0,
frames);
parentResult[0].copy(parentResult[1]);
parentResult[1].set(lastFrame, 0);
return;
} else {
parentResult[0].copy(parentResult[1]);
parentResult[1].set(BSTNodeUtil.getRightChildFrameIx(parentResult[1], frames, convertBuffer),
BSTNodeUtil.getRightChildOffset(parentResult[1], frames, convertBuffer));
}
}
}
throw new HyracksDataException("New Frame could not be added to BSTMemMgr");
}
private void insert(int fix, int off, int length) throws HyracksDataException {
BSTNodeUtil.setHeaderFooter(fix, off, length, true, frames);
initNewNode(fix, off);
if (root.isNull()) {
root.set(fix, off);
return;
}
insertSlot.clear();
insertSlot.copy(root);
while (!insertSlot.isNull()) {
int curSlotLen = BSTNodeUtil.getLength(insertSlot, frames, convertBuffer);
if (curSlotLen == length) {
append(insertSlot.getFrameIx(), insertSlot.getOffset(), fix, off);
return;
}
if (length < curSlotLen) {
int leftChildFIx = BSTNodeUtil.getLeftChildFrameIx(insertSlot, frames, convertBuffer);
int leftChildOffset = BSTNodeUtil.getLeftChildOffset(insertSlot, frames, convertBuffer);
if (isNodeNull(leftChildFIx, leftChildOffset)) {
initNewNode(fix, off);
BSTNodeUtil.setLeftChild(insertSlot.getFrameIx(), insertSlot.getOffset(), fix, off, frames);
return;
} else {
insertSlot.set(leftChildFIx, leftChildOffset);
}
} else {
int rightChildFIx = BSTNodeUtil.getRightChildFrameIx(insertSlot, frames, convertBuffer);
int rightChildOffset = BSTNodeUtil.getRightChildOffset(insertSlot, frames, convertBuffer);
if (isNodeNull(rightChildFIx, rightChildOffset)) {
initNewNode(fix, off);
BSTNodeUtil.setRightChild(insertSlot.getFrameIx(), insertSlot.getOffset(), fix, off, frames);
return;
} else {
insertSlot.set(rightChildFIx, rightChildOffset);
}
}
}
throw new HyracksDataException("Failure in node insertion into BST in BSTMemMgr");
}
/**
* @param length
* @param target
* is the container sent by the caller to hold the results
*/
private void search(int length, Slot[] target) {
clear(target);
result.clear();
if (root.isNull()) {
return;
}
lastLeftParent.clear();
lastLeft.clear();
parent.clear();
result.copy(root);
while (!result.isNull()) {
if (BSTNodeUtil.getLength(result, frames, convertBuffer) == length) {
target[0].copy(parent);
target[1].copy(result);
return;
}
if (length < BSTNodeUtil.getLength(result, frames, convertBuffer)) {
lastLeftParent.copy(parent);
lastLeft.copy(result);
parent.copy(result);
int fix = BSTNodeUtil.getLeftChildFrameIx(result, frames, convertBuffer);
int off = BSTNodeUtil.getLeftChildOffset(result, frames, convertBuffer);
result.set(fix, off);
} else {
parent.copy(result);
int fix = BSTNodeUtil.getRightChildFrameIx(result, frames, convertBuffer);
int off = BSTNodeUtil.getRightChildOffset(result, frames, convertBuffer);
result.set(fix, off);
}
}
target[0].copy(lastLeftParent);
target[1].copy(lastLeft);
}
private void append(int headFix, int headOff, int nodeFix, int nodeOff) {
initNewNode(nodeFix, nodeOff);
int fix = BSTNodeUtil.getNextFrameIx(headFix, headOff, frames, convertBuffer); // frameIx
// for
// the
// current
// next
// of
// head
int off = BSTNodeUtil.getNextOffset(headFix, headOff, frames, convertBuffer); // offset
// for
// the
// current
// next
// of
// head
BSTNodeUtil.setNext(nodeFix, nodeOff, fix, off, frames);
if (!isNodeNull(fix, off)) {
BSTNodeUtil.setPrev(fix, off, nodeFix, nodeOff, frames);
}
BSTNodeUtil.setPrev(nodeFix, nodeOff, headFix, headOff, frames);
BSTNodeUtil.setNext(headFix, headOff, nodeFix, nodeOff, frames);
}
private int[] split(Slot listHead, Slot parent, int length) {
int l2 = BSTNodeUtil.getLength(listHead, frames, convertBuffer) - length - 2 * BSTNodeUtil.HEADER_SIZE;
// We split the node after slots-list head
if (!isNodeNull(BSTNodeUtil.getNextFrameIx(listHead, frames, convertBuffer),
BSTNodeUtil.getNextOffset(listHead, frames, convertBuffer))) {
int afterHeadFix = BSTNodeUtil.getNextFrameIx(listHead, frames, convertBuffer);
int afterHeadOff = BSTNodeUtil.getNextOffset(listHead, frames, convertBuffer);
int afHNextFix = BSTNodeUtil.getNextFrameIx(afterHeadFix, afterHeadOff, frames, convertBuffer);
int afHNextOff = BSTNodeUtil.getNextOffset(afterHeadFix, afterHeadOff, frames, convertBuffer);
BSTNodeUtil.setNext(listHead.getFrameIx(), listHead.getOffset(), afHNextFix, afHNextOff, frames);
if (!isNodeNull(afHNextFix, afHNextOff)) {
BSTNodeUtil.setPrev(afHNextFix, afHNextOff, listHead.getFrameIx(), listHead.getOffset(), frames);
}
int secondOffset = afterHeadOff + length + 2 * BSTNodeUtil.HEADER_SIZE;
BSTNodeUtil.setHeaderFooter(afterHeadFix, afterHeadOff, length, true, frames);
BSTNodeUtil.setHeaderFooter(afterHeadFix, secondOffset, l2, true, frames);
return new int[] { afterHeadFix, afterHeadOff, afterHeadFix, secondOffset };
}
// We split the head
int secondOffset = listHead.getOffset() + length + 2 * BSTNodeUtil.HEADER_SIZE;
BSTNodeUtil.setHeaderFooter(listHead.getFrameIx(), listHead.getOffset(), length, true, frames);
BSTNodeUtil.setHeaderFooter(listHead.getFrameIx(), secondOffset, l2, true, frames);
fixTreePtrs(listHead.getFrameIx(), listHead.getOffset(), parent.getFrameIx(), parent.getOffset());
return new int[] { listHead.getFrameIx(), listHead.getOffset(), listHead.getFrameIx(), secondOffset };
}
private void fixTreePtrs(int nodeFrameIx, int nodeOffset, int parentFrameIx, int parentOffset) {
int nodeLeftChildFrameIx = BSTNodeUtil.getLeftChildFrameIx(nodeFrameIx, nodeOffset, frames, convertBuffer);
int nodeLeftChildOffset = BSTNodeUtil.getLeftChildOffset(nodeFrameIx, nodeOffset, frames, convertBuffer);
int nodeRightChildFrameIx = BSTNodeUtil.getRightChildFrameIx(nodeFrameIx, nodeOffset, frames, convertBuffer);
int nodeRightChildOffset = BSTNodeUtil.getRightChildOffset(nodeFrameIx, nodeOffset, frames, convertBuffer);
int status = -1; // (status==0 if node is left child of parent)
// (status==1 if node is right child of parent)
if (!isNodeNull(parentFrameIx, parentOffset)) {
int nlen = BSTNodeUtil.getActualLength(BSTNodeUtil
.getLength(nodeFrameIx, nodeOffset, frames, convertBuffer));
int plen = BSTNodeUtil.getActualLength(BSTNodeUtil.getLength(parentFrameIx, parentOffset, frames,
convertBuffer));
status = ((nlen < plen) ? 0 : 1);
}
if (!isNodeNull(nodeLeftChildFrameIx, nodeLeftChildOffset)
&& !isNodeNull(nodeRightChildFrameIx, nodeRightChildOffset)) { // Node
// has
// two
// children
int pMinFIx = nodeFrameIx;
int pMinOff = nodeOffset;
int minFIx = nodeRightChildFrameIx;
int minOff = nodeRightChildOffset;
int nextLeftFIx = BSTNodeUtil.getLeftChildFrameIx(minFIx, minOff, frames, convertBuffer);
int nextLeftOff = BSTNodeUtil.getLeftChildOffset(minFIx, minOff, frames, convertBuffer);
while (!isNodeNull(nextLeftFIx, nextLeftOff)) {
pMinFIx = minFIx;
pMinOff = minOff;
minFIx = nextLeftFIx;
minOff = nextLeftOff;
nextLeftFIx = BSTNodeUtil.getLeftChildFrameIx(minFIx, minOff, frames, convertBuffer); // min
// is
// now
// pointing
// to
// current
// (old)
// next
// left
nextLeftOff = BSTNodeUtil.getLeftChildOffset(minFIx, minOff, frames, convertBuffer); // min
// is
// now
// pointing
// to
// current
// (old)
// next
// left
}
if ((nodeRightChildFrameIx == minFIx) && (nodeRightChildOffset == minOff)) { // nrc
// is
// the
// same as min
BSTNodeUtil.setLeftChild(nodeRightChildFrameIx, nodeRightChildOffset, nodeLeftChildFrameIx,
nodeLeftChildOffset, frames);
} else { // min is different from nrc
int minRightFIx = BSTNodeUtil.getRightChildFrameIx(minFIx, minOff, frames, convertBuffer);
int minRightOffset = BSTNodeUtil.getRightChildOffset(minFIx, minOff, frames, convertBuffer);
BSTNodeUtil.setRightChild(minFIx, minOff, nodeRightChildFrameIx, nodeRightChildOffset, frames);
BSTNodeUtil.setLeftChild(minFIx, minOff, nodeLeftChildFrameIx, nodeLeftChildOffset, frames);
BSTNodeUtil.setLeftChild(pMinFIx, pMinOff, minRightFIx, minRightOffset, frames);
}
// Now dealing with the parent
if (!isNodeNull(parentFrameIx, parentOffset)) {
if (status == 0) {
BSTNodeUtil.setLeftChild(parentFrameIx, parentOffset, minFIx, minOff, frames);
} else if (status == 1) {
BSTNodeUtil.setRightChild(parentFrameIx, parentOffset, minFIx, minOff, frames);
}
} else { // No parent (node was the root)
root.set(minFIx, minOff);
}
return;
}
else if (!isNodeNull(nodeLeftChildFrameIx, nodeLeftChildOffset)) { // Node
// has
// only
// left
// child
if (status == 0) {
BSTNodeUtil
.setLeftChild(parentFrameIx, parentOffset, nodeLeftChildFrameIx, nodeLeftChildOffset, frames);
} else if (status == 1) {
BSTNodeUtil.setRightChild(parentFrameIx, parentOffset, nodeLeftChildFrameIx, nodeLeftChildOffset,
frames);
} else if (status == -1) { // No parent, so node is root
root.set(nodeLeftChildFrameIx, nodeLeftChildOffset);
}
return;
}
else if (!isNodeNull(nodeRightChildFrameIx, nodeRightChildOffset)) { // Node
// has
// only
// right
// child
if (status == 0) {
BSTNodeUtil.setLeftChild(parentFrameIx, parentOffset, nodeRightChildFrameIx, nodeRightChildOffset,
frames);
} else if (status == 1) {
BSTNodeUtil.setRightChild(parentFrameIx, parentOffset, nodeRightChildFrameIx, nodeRightChildOffset,
frames);
} else if (status == -1) { // No parent, so node is root
root.set(nodeRightChildFrameIx, nodeRightChildOffset);
}
return;
}
else { // Node is leaf (no children)
if (status == 0) {
BSTNodeUtil.setLeftChild(parentFrameIx, parentOffset, BSTNodeUtil.INVALID_INDEX,
BSTNodeUtil.INVALID_INDEX, frames);
} else if (status == 1) {
BSTNodeUtil.setRightChild(parentFrameIx, parentOffset, BSTNodeUtil.INVALID_INDEX,
BSTNodeUtil.INVALID_INDEX, frames);
} else { // node was the only node in the tree
root.clear();
}
return;
}
}
/**
* Allocation with no splitting but padding
*
* @param node
* @param parent
* @param result
* is the container sent by the caller to hold the results
*/
private void allocate(Slot node, Slot parent, int length, Slot result) {
int nextFix = BSTNodeUtil.getNextFrameIx(node, frames, convertBuffer);
int nextOff = BSTNodeUtil.getNextOffset(node, frames, convertBuffer);
if (!isNodeNull(nextFix, nextOff)) {
int nextOfNextFIx = BSTNodeUtil.getNextFrameIx(nextFix, nextOff, frames, convertBuffer);
int nextOfNextOffset = BSTNodeUtil.getNextOffset(nextFix, nextOff, frames, convertBuffer);
BSTNodeUtil.setNext(node.getFrameIx(), node.getOffset(), nextOfNextFIx, nextOfNextOffset, frames);
if (!isNodeNull(nextOfNextFIx, nextOfNextOffset)) {
BSTNodeUtil.setPrev(nextOfNextFIx, nextOfNextOffset, node.getFrameIx(), node.getOffset(), frames);
}
BSTNodeUtil.setHeaderFooter(nextFix, nextOff, length, false, frames);
result.set(nextFix, nextOff);
return;
}
fixTreePtrs(node.getFrameIx(), node.getOffset(), parent.getFrameIx(), parent.getOffset());
BSTNodeUtil.setHeaderFooter(node.getFrameIx(), node.getOffset(), length, false, frames);
result.copy(node);
}
private void removeFromList(int fix, int off) {
int nextFIx = BSTNodeUtil.getNextFrameIx(fix, off, frames, convertBuffer);
int nextOffset = BSTNodeUtil.getNextOffset(fix, off, frames, convertBuffer);
int prevFIx = BSTNodeUtil.getPrevFrameIx(fix, off, frames, convertBuffer);
int prevOffset = BSTNodeUtil.getPrevOffset(fix, off, frames, convertBuffer);
if (!isNodeNull(prevFIx, prevOffset) && !isNodeNull(nextFIx, nextOffset)) {
BSTNodeUtil.setNext(prevFIx, prevOffset, nextFIx, nextOffset, frames);
BSTNodeUtil.setPrev(nextFIx, nextOffset, prevFIx, prevOffset, frames);
BSTNodeUtil.setNext(fix, off, BSTNodeUtil.INVALID_INDEX, BSTNodeUtil.INVALID_INDEX, frames);
BSTNodeUtil.setPrev(fix, off, BSTNodeUtil.INVALID_INDEX, BSTNodeUtil.INVALID_INDEX, frames);
return;
}
if (!isNodeNull(prevFIx, prevOffset)) {
BSTNodeUtil.setNext(prevFIx, prevOffset, BSTNodeUtil.INVALID_INDEX, BSTNodeUtil.INVALID_INDEX, frames);
BSTNodeUtil.setPrev(fix, off, BSTNodeUtil.INVALID_INDEX, BSTNodeUtil.INVALID_INDEX, frames);
return;
}
// We need to find the parent, so we can fix the tree
int parentFIx = BSTNodeUtil.INVALID_INDEX;
int parentOffset = BSTNodeUtil.INVALID_INDEX;
int length = BSTNodeUtil.getActualLength(BSTNodeUtil.getLength(fix, off, frames, convertBuffer));
fix = root.getFrameIx();
off = root.getOffset();
int curLen = BSTNodeUtil.getLength(fix, off, frames, convertBuffer);
while (length != curLen) {
parentFIx = fix;
parentOffset = off;
if (length < curLen) {
fix = BSTNodeUtil.getLeftChildFrameIx(parentFIx, parentOffset, frames, convertBuffer); // parentFIx
// is
// now
// the
// old(current)
// fix
off = BSTNodeUtil.getLeftChildOffset(parentFIx, parentOffset, frames, convertBuffer); // parentOffset
// is
// now
// the
// old(current)
// off
} else {
fix = BSTNodeUtil.getRightChildFrameIx(parentFIx, parentOffset, frames, convertBuffer); // parentFIx
// is
// now
// the
// old(current)
// fix
off = BSTNodeUtil.getRightChildOffset(parentFIx, parentOffset, frames, convertBuffer); // parentOffset
// is
// now
// the
// old(current)
// off
}
curLen = BSTNodeUtil.getLength(fix, off, frames, convertBuffer);
}
if (!isNodeNull(nextFIx, nextOffset)) { // it is head of the list (in
// the
// tree)
BSTNodeUtil.setPrev(nextFIx, nextOffset, BSTNodeUtil.INVALID_INDEX, BSTNodeUtil.INVALID_INDEX, frames);
int nodeLeftChildFIx = BSTNodeUtil.getLeftChildFrameIx(fix, off, frames, convertBuffer);
int nodeLeftChildOffset = BSTNodeUtil.getLeftChildOffset(fix, off, frames, convertBuffer);
int nodeRightChildFix = BSTNodeUtil.getRightChildFrameIx(fix, off, frames, convertBuffer);
int nodeRightChildOffset = BSTNodeUtil.getRightChildOffset(fix, off, frames, convertBuffer);
BSTNodeUtil.setLeftChild(nextFIx, nextOffset, nodeLeftChildFIx, nodeLeftChildOffset, frames);
BSTNodeUtil.setRightChild(nextFIx, nextOffset, nodeRightChildFix, nodeRightChildOffset, frames);
if (!isNodeNull(parentFIx, parentOffset)) {
int parentLength = BSTNodeUtil.getLength(parentFIx, parentOffset, frames, convertBuffer);
if (length < parentLength) {
BSTNodeUtil.setLeftChild(parentFIx, parentOffset, nextFIx, nextOffset, frames);
} else {
BSTNodeUtil.setRightChild(parentFIx, parentOffset, nextFIx, nextOffset, frames);
}
}
if ((root.getFrameIx() == fix) && (root.getOffset() == off)) {
root.set(nextFIx, nextOffset);
}
return;
}
fixTreePtrs(fix, off, parentFIx, parentOffset);
}
private void clear(Slot[] s) {
s[0].clear();
s[1].clear();
}
private boolean isNodeNull(int frameIx, int offset) {
return ((frameIx == BSTNodeUtil.INVALID_INDEX) || (offset == BSTNodeUtil.INVALID_INDEX) || (frames[frameIx] == null));
}
private boolean shouldSplit(int slotLength, int reqLength) {
return ((slotLength - reqLength) >= BSTNodeUtil.MINIMUM_FREE_SLOT_SIZE);
}
private void initNewNode(int frameIx, int offset) {
BSTNodeUtil.setLeftChild(frameIx, offset, BSTNodeUtil.INVALID_INDEX, BSTNodeUtil.INVALID_INDEX, frames);
BSTNodeUtil.setRightChild(frameIx, offset, BSTNodeUtil.INVALID_INDEX, BSTNodeUtil.INVALID_INDEX, frames);
BSTNodeUtil.setNext(frameIx, offset, BSTNodeUtil.INVALID_INDEX, BSTNodeUtil.INVALID_INDEX, frames);
BSTNodeUtil.setPrev(frameIx, offset, BSTNodeUtil.INVALID_INDEX, BSTNodeUtil.INVALID_INDEX, frames);
}
private ByteBuffer allocateFrame() {
return ctx.allocateFrame();
}
public String debugPrintMemory() {
Slot s = new Slot(0, 0);
if (s.isNull()) {
return "memory:\tNull";
}
String m = "memory:\n" + debugPrintSlot(0, 0) + "\n";
int length = BSTNodeUtil.getActualLength(BSTNodeUtil.getLength(0, 0, frames, convertBuffer));
int noff = (length + 2 * BSTNodeUtil.HEADER_SIZE >= frameSize ? BSTNodeUtil.INVALID_INDEX : length + 2
* BSTNodeUtil.HEADER_SIZE);
int nfix = (noff == BSTNodeUtil.INVALID_INDEX ? ((frames.length == 1) ? BSTNodeUtil.INVALID_INDEX : 1) : 0);
if (noff == BSTNodeUtil.INVALID_INDEX && nfix != BSTNodeUtil.INVALID_INDEX) {
noff = 0;
}
s.set(nfix, noff);
while (!isNodeNull(s.getFrameIx(), s.getOffset())) {
m += debugPrintSlot(s.getFrameIx(), s.getOffset()) + "\n";
length = BSTNodeUtil.getActualLength(BSTNodeUtil.getLength(s.getFrameIx(), s.getOffset(), frames,
convertBuffer));
noff = (s.getOffset() + length + 2 * BSTNodeUtil.HEADER_SIZE >= frameSize ? BSTNodeUtil.INVALID_INDEX : s
.getOffset() + length + 2 * BSTNodeUtil.HEADER_SIZE);
nfix = (noff == BSTNodeUtil.INVALID_INDEX ? ((frames.length - 1 == s.getFrameIx()) ? BSTNodeUtil.INVALID_INDEX
: s.getFrameIx() + 1)
: s.getFrameIx());
if (noff == BSTNodeUtil.INVALID_INDEX && nfix != BSTNodeUtil.INVALID_INDEX) {
noff = 0;
}
s.set(nfix, noff);
}
return m;
}
public String debugPrintTree() {
Slot node = new Slot();
node.copy(root);
if (!node.isNull()) {
return debugPrintSubTree(node);
}
return "Null";
}
private String debugPrintSubTree(Slot r) {
Slot node = new Slot();
node.copy(r);
int fix = node.getFrameIx();
int off = node.getOffset();
int lfix = BSTNodeUtil.getLeftChildFrameIx(node, frames, convertBuffer);
int loff = BSTNodeUtil.getLeftChildOffset(node, frames, convertBuffer);
int rfix = BSTNodeUtil.getRightChildFrameIx(node, frames, convertBuffer);
int roff = BSTNodeUtil.getRightChildOffset(node, frames, convertBuffer);
int nfix = BSTNodeUtil.getNextFrameIx(node, frames, convertBuffer);
int noff = BSTNodeUtil.getNextOffset(node, frames, convertBuffer);
int pfix = BSTNodeUtil.getPrevFrameIx(node, frames, convertBuffer);
int poff = BSTNodeUtil.getPrevOffset(node, frames, convertBuffer);
String s = "{" + r.getFrameIx() + ", " + r.getOffset() + " (Len: "
+ BSTNodeUtil.getLength(fix, off, frames, convertBuffer) + ") - " + "(LC: "
+ debugPrintSlot(lfix, loff) + ") - " + "(RC: " + debugPrintSlot(rfix, roff) + ") - " + "(NX: "
+ debugPrintSlot(nfix, noff) + ") - " + "(PR: " + debugPrintSlot(pfix, poff) + ") }\n";
if (!isNodeNull(lfix, loff)) {
s += debugPrintSubTree(new Slot(lfix, loff)) + "\n";
}
if (!isNodeNull(rfix, roff)) {
s += debugPrintSubTree(new Slot(rfix, roff)) + "\n";
}
return s;
}
private String debugPrintSlot(int fix, int off) {
if (isNodeNull(fix, off)) {
return BSTNodeUtil.INVALID_INDEX + ", " + BSTNodeUtil.INVALID_INDEX;
}
int l = BSTNodeUtil.getLength(fix, off, frames, convertBuffer);
int al = BSTNodeUtil.getActualLength(l);
boolean f = BSTNodeUtil.isFree(fix, off, frames);
return fix + ", " + off + " (free: " + f + ") (Len: " + l + ") (actual len: " + al + ") ";
}
}