public int removeLeafEntry()

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;
  }