in core/src/main/java/com/jetbrains/youtrackdb/internal/core/storage/index/sbtree/multivalue/v2/CellBTreeMultiValueV2Bucket.java [180:434]
public int removeLeafEntry(final int entryIndex, final RID value) {
assert isLeaf();
final var entryPosition =
getIntValue(POSITIONS_ARRAY_OFFSET + entryIndex * IntegerSerializer.INT_SIZE);
var position = entryPosition;
var nextItem = getIntValue(position);
position += IntegerSerializer.INT_SIZE;
final var embeddedEntriesCountPosition = position;
final int embeddedEntriesCount = getByteValue(position);
position += ByteSerializer.BYTE_SIZE;
final var entriesCountPosition = position;
final var entriesCount = getIntValue(entriesCountPosition);
position += IntegerSerializer.INT_SIZE;
position += LongSerializer.LONG_SIZE; // mId
// only single element in list
if (nextItem == -1) {
final var collectionIdPosition = position;
final int collectionId = getShortValue(collectionIdPosition);
position += ShortSerializer.SHORT_SIZE;
final var collectionPosition = getLongValue(position);
if (collectionId != value.getCollectionId()) {
return -1;
}
if (collectionPosition == value.getCollectionPosition()) {
setShortValue(collectionIdPosition, (short) -1);
assert embeddedEntriesCount == 1;
setByteValue(embeddedEntriesCountPosition, (byte) (0));
setIntValue(entriesCountPosition, entriesCount - 1);
return entriesCount - 1;
}
} else {
int collectionId = getShortValue(position);
position += ShortSerializer.SHORT_SIZE;
var collectionPosition = getLongValue(position);
if (collectionId == value.getCollectionId() && collectionPosition == value.getCollectionPosition()) {
final var nextNextItem = getIntValue(nextItem);
final var nextItemSize = 0xFF & getByteValue(nextItem + IntegerSerializer.INT_SIZE);
final var nextValue =
getBinaryValue(
nextItem + IntegerSerializer.INT_SIZE + ByteSerializer.BYTE_SIZE, RID_SIZE);
assert nextItemSize > 0;
final var freePointer = getIntValue(FREE_POINTER_OFFSET);
if (nextItemSize == 1) {
setIntValue(entryPosition, nextNextItem);
setIntValue(
FREE_POINTER_OFFSET,
freePointer + IntegerSerializer.INT_SIZE + RID_SIZE + ByteSerializer.BYTE_SIZE);
} else {
setByteValue(nextItem + IntegerSerializer.INT_SIZE, (byte) (nextItemSize - 1));
setIntValue(FREE_POINTER_OFFSET, freePointer + RID_SIZE);
}
setBinaryValue(
entryPosition
+ 2 * IntegerSerializer.INT_SIZE
+ ByteSerializer.BYTE_SIZE
+ LongSerializer.LONG_SIZE,
nextValue);
if (nextItem > freePointer || nextItemSize > 1) {
if (nextItemSize == 1) {
moveData(
freePointer, freePointer + SINGLE_ELEMENT_LINKED_ITEM_SIZE, nextItem - freePointer);
} else {
moveData(
freePointer,
freePointer + RID_SIZE,
nextItem + IntegerSerializer.INT_SIZE + ByteSerializer.BYTE_SIZE - freePointer);
}
final var diff =
nextItemSize > 1
? RID_SIZE
: IntegerSerializer.INT_SIZE + ByteSerializer.BYTE_SIZE + RID_SIZE;
final var size = getIntValue(SIZE_OFFSET);
var currentPositionOffset = POSITIONS_ARRAY_OFFSET;
for (var i = 0; i < size; i++) {
final var currentEntryPosition = getIntValue(currentPositionOffset);
final int updatedEntryPosition;
if (currentEntryPosition < nextItem) {
updatedEntryPosition = currentEntryPosition + diff;
setIntValue(currentPositionOffset, updatedEntryPosition);
} else {
updatedEntryPosition = currentEntryPosition;
}
final var currentNextItem = getIntValue(updatedEntryPosition);
if (currentNextItem > 0 && currentNextItem < nextItem + diff) {
// update reference to the first item of linked list
setIntValue(updatedEntryPosition, currentNextItem + diff);
updateAllLinkedListReferences(currentNextItem, nextItem + diff, diff);
}
currentPositionOffset += IntegerSerializer.INT_SIZE;
}
}
setByteValue(embeddedEntriesCountPosition, (byte) (embeddedEntriesCount - 1));
setIntValue(entriesCountPosition, entriesCount - 1);
return entriesCount - 1;
} else {
var prevItem = entryPosition;
while (nextItem > 0) {
final var nextNextItem = getIntValue(nextItem);
final var nextItemSize = 0xFF & getByteValue(nextItem + IntegerSerializer.INT_SIZE);
if (nextItemSize == 1) {
collectionId =
getShortValue(nextItem + IntegerSerializer.INT_SIZE + ByteSerializer.BYTE_SIZE);
collectionPosition =
getLongValue(
nextItem
+ IntegerSerializer.INT_SIZE
+ ByteSerializer.BYTE_SIZE
+ ShortSerializer.SHORT_SIZE);
if (collectionId == value.getCollectionId()
&& collectionPosition == value.getCollectionPosition()) {
setIntValue(prevItem, nextNextItem);
final var freePointer = getIntValue(FREE_POINTER_OFFSET);
setIntValue(FREE_POINTER_OFFSET, freePointer + SINGLE_ELEMENT_LINKED_ITEM_SIZE);
if (nextItem > freePointer) {
moveData(
freePointer,
freePointer + SINGLE_ELEMENT_LINKED_ITEM_SIZE,
nextItem - freePointer);
final var size = getIntValue(SIZE_OFFSET);
var currentPositionOffset = POSITIONS_ARRAY_OFFSET;
for (var i = 0; i < size; i++) {
final var currentEntryPosition = getIntValue(currentPositionOffset);
final int updatedEntryPosition;
if (currentEntryPosition < nextItem) {
updatedEntryPosition = currentEntryPosition + SINGLE_ELEMENT_LINKED_ITEM_SIZE;
setIntValue(currentPositionOffset, updatedEntryPosition);
} else {
updatedEntryPosition = currentEntryPosition;
}
final var currentNextItem = getIntValue(updatedEntryPosition);
if (currentNextItem > 0 && currentNextItem < nextItem) {
// update reference to the first item of linked list
setIntValue(
updatedEntryPosition, currentNextItem + SINGLE_ELEMENT_LINKED_ITEM_SIZE);
updateAllLinkedListReferences(
currentNextItem, nextItem, SINGLE_ELEMENT_LINKED_ITEM_SIZE);
}
currentPositionOffset += IntegerSerializer.INT_SIZE;
}
}
setByteValue(embeddedEntriesCountPosition, (byte) (embeddedEntriesCount - 1));
setIntValue(entriesCountPosition, entriesCount - 1);
return entriesCount - 1;
}
} else {
for (var i = 0; i < nextItemSize; i++) {
collectionId =
getShortValue(
nextItem
+ IntegerSerializer.INT_SIZE
+ ByteSerializer.BYTE_SIZE
+ i * RID_SIZE);
collectionPosition =
getLongValue(
nextItem
+ IntegerSerializer.INT_SIZE
+ ShortSerializer.SHORT_SIZE
+ ByteSerializer.BYTE_SIZE
+ i * RID_SIZE);
if (collectionId == value.getCollectionId()
&& collectionPosition == value.getCollectionPosition()) {
final var freePointer = getIntValue(FREE_POINTER_OFFSET);
setIntValue(FREE_POINTER_OFFSET, freePointer + RID_SIZE);
setByteValue(nextItem + IntegerSerializer.INT_SIZE, (byte) (nextItemSize - 1));
moveData(
freePointer,
freePointer + RID_SIZE,
nextItem
+ IntegerSerializer.INT_SIZE
+ ByteSerializer.BYTE_SIZE
+ i * RID_SIZE
- freePointer);
final var size = getIntValue(SIZE_OFFSET);
var currentPositionOffset = POSITIONS_ARRAY_OFFSET;
for (var n = 0; n < size; n++) {
final var currentEntryPosition = getIntValue(currentPositionOffset);
final int updatedEntryPosition;
if (currentEntryPosition < nextItem) {
updatedEntryPosition = currentEntryPosition + RID_SIZE;
setIntValue(currentPositionOffset, updatedEntryPosition);
} else {
updatedEntryPosition = currentEntryPosition;
}
final var currentNextItem = getIntValue(updatedEntryPosition);
if (currentNextItem > 0 && currentNextItem < nextItem + RID_SIZE) {
// update reference to the first item of linked list
setIntValue(updatedEntryPosition, currentNextItem + RID_SIZE);
updateAllLinkedListReferences(currentNextItem, nextItem + RID_SIZE, RID_SIZE);
}
currentPositionOffset += IntegerSerializer.INT_SIZE;
}
setByteValue(embeddedEntriesCountPosition, (byte) (embeddedEntriesCount - 1));
setIntValue(entriesCountPosition, entriesCount - 1);
return entriesCount - 1;
}
}
}
prevItem = nextItem;
nextItem = nextNextItem;
}
}
}
return -1;
}