use of jetbrains.exodus.ByteIterable in project xodus by JetBrains.
the class BasePageMutable method save.
/**
* Save page to log
*
* @return address of this page after save
*/
protected long save() {
// save leaf nodes
ReclaimFlag flag = saveChildren();
// save self. complementary to {@link load()}
final byte type = getType();
final BTreeBase tree = getTree();
final int structureId = tree.structureId;
final Log log = tree.log;
if (flag == ReclaimFlag.PRESERVE) {
// there is a chance to update the flag to RECLAIM
if (log.getWrittenHighAddress() % log.getFileSize() == 0) {
// page will be exactly on file border
flag = ReclaimFlag.RECLAIM;
} else {
final ByteIterable[] iterables = getByteIterables(flag);
long result = log.tryWrite(type, structureId, new CompoundByteIterable(iterables));
if (result < 0) {
iterables[0] = CompressedUnsignedLongByteIterable.getIterable((size << 1) + ReclaimFlag.RECLAIM.value);
result = log.writeContinuously(type, structureId, new CompoundByteIterable(iterables));
if (result < 0) {
throw new TooBigLoggableException();
}
}
return result;
}
}
return log.write(type, structureId, new CompoundByteIterable(getByteIterables(flag)));
}
use of jetbrains.exodus.ByteIterable in project xodus by JetBrains.
the class LeafNode method reclaim.
protected void reclaim(@NotNull final BTreeReclaimTraverser context) {
final ByteIterable keyIterable = getKey();
if (!context.canMoveDown() && context.canMoveRight()) {
final int leafIndex;
final int cmp = context.compareCurrent(keyIterable);
if (cmp > 0) {
return;
}
if (cmp == 0) {
leafIndex = context.currentPos;
} else {
context.moveRight();
leafIndex = context.getNextSibling(keyIterable);
}
if (leafIndex >= 0) {
doReclaim(context, leafIndex);
context.moveTo(leafIndex + 1);
return;
} else if (context.canMoveTo(-leafIndex - 1)) {
return;
}
}
// go up
if (context.canMoveUp()) {
while (true) {
context.popAndMutate();
context.moveRight();
final int index = context.getNextSibling(keyIterable);
if (index < 0) {
if (context.canMoveTo(-index - 1) || !context.canMoveUp()) {
context.moveTo(Math.max(-index - 2, 0));
break;
}
} else {
// node is always internal
context.pushChild(index);
break;
}
}
}
// go down
while (context.canMoveDown()) {
int index = context.getNextSibling(keyIterable);
if (index < 0) {
index = Math.max(-index - 2, 0);
}
context.pushChild(index);
}
int leafIndex = context.getNextSibling(keyIterable);
if (leafIndex >= 0) {
doReclaim(context, leafIndex);
context.moveTo(leafIndex + 1);
} else {
context.moveTo(-leafIndex - 1);
}
}
use of jetbrains.exodus.ByteIterable in project xodus by JetBrains.
the class BTreeCursorDupMutable method getNextDup.
@Override
public boolean getNextDup() {
moveIfNecessary();
// move to next dup if in -1 position or dupCursor has next element
if (traverser.node == ILeafNode.EMPTY) {
if (wasDelete) {
// traverser was reset to root after delete
final BasePage root = traverser.currentNode;
final ByteIterable key = nextAfterRemovedKey;
final ByteIterable value = nextAfterRemovedValue;
if (getNext()) {
if (traverser.inDupTree) {
return true;
}
// not really a dup, rollback
// also restores state
reset((MutableTreeRoot) root);
wasDelete = true;
nextAfterRemovedKey = key;
nextAfterRemovedValue = value;
}
return false;
}
return getNext();
} else {
return hasNext() && traverser.inDupTree && getNext() && traverser.inDupTree;
}
}
use of jetbrains.exodus.ByteIterable in project xodus by JetBrains.
the class BTreeDupMutable method save.
@Override
public long save() {
if (address != Loggable.NULL_ADDRESS) {
throw new IllegalStateException("Duplicates sub-tree already saved");
}
final BasePageMutable rootPage = getRoot();
final byte type = rootPage.isBottom() ? BTreeBase.LEAF_DUP_BOTTOM_ROOT : BTreeBase.LEAF_DUP_INTERNAL_ROOT;
final ByteIterable keyIterable = CompressedUnsignedLongByteIterable.getIterable(key.getLength());
ByteIterable sizeIterable;
// remember high address before saving the data
long startAddress = log.getWrittenHighAddress();
final ByteIterable rootDataIterable = rootPage.getData();
ByteIterable[] iterables;
long result;
final boolean canRetry;
if (log.isLastWrittenFileAddress(startAddress)) {
sizeIterable = CompressedUnsignedLongByteIterable.getIterable(size << 1);
iterables = new ByteIterable[] { keyIterable, key, sizeIterable, rootDataIterable };
result = log.tryWrite(type, structureId, new CompoundByteIterable(iterables));
if (result >= 0) {
address = result;
return result;
} else {
canRetry = false;
}
} else {
canRetry = true;
}
if (NullLoggable.isNullLoggable(log.getWrittenLoggableType(startAddress))) {
final long lengthBound = log.getFileLengthBound();
final long alignment = startAddress % lengthBound;
startAddress += (lengthBound - alignment);
if (log.getWrittenHighAddress() < startAddress) {
throw new IllegalStateException("Address alignment underflow: start address " + startAddress + ", alignment " + alignment);
}
}
sizeIterable = CompressedUnsignedLongByteIterable.getIterable((size << 1) + 1);
final ByteIterable offsetIterable = CompressedUnsignedLongByteIterable.getIterable(log.getWrittenHighAddress() - startAddress);
iterables = new ByteIterable[] { keyIterable, key, sizeIterable, offsetIterable, rootDataIterable };
final ByteIterable data = new CompoundByteIterable(iterables);
result = canRetry ? log.tryWrite(type, structureId, data) : log.writeContinuously(type, structureId, data);
if (result < 0) {
if (canRetry) {
iterables[3] = CompressedUnsignedLongByteIterable.getIterable(log.getWrittenHighAddress() - startAddress);
result = log.writeContinuously(type, structureId, new CompoundByteIterable(iterables));
if (result < 0) {
throw new TooBigLoggableException();
}
} else {
throw new TooBigLoggableException();
}
}
address = result;
return result;
}
use of jetbrains.exodus.ByteIterable in project xodus by JetBrains.
the class TreeCursorMutable method deleteCurrent.
@Override
public boolean deleteCurrent() {
moveIfNecessary();
if (wasDelete) {
return false;
}
// delete and remember next
final ByteIterable key = getKey();
final ByteIterable value = getValue();
if (getNext()) {
nextAfterRemovedKey = traverser.getKey();
nextAfterRemovedValue = traverser.getValue();
} else {
nextAfterRemovedKey = null;
nextAfterRemovedValue = null;
}
// don't call back treeChanged() for current cursor
boolean result = tree.isAllowingDuplicates() ? tree.delete(key, value, this) : tree.delete(key, null, this);
assert result;
wasDelete = true;
// root may be changed by tree.delete, so reset cursor with new root
reset(tree.getRoot());
return true;
}
Aggregations