public long save()

in environment/src/main/java/jetbrains/exodus/tree/btree/BTreeDupMutable.java [66:125]


    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;
        long startAddress = log.getWrittenHighAddress(); // remember high address before saving the data
        final ByteIterable rootDataIterable = rootPage.getData();
        ByteIterable[] iterables;
        long result;
        final boolean canRetry;
        var expired = getExpiredLoggables();

        if (log.isLastWrittenFileAddress(startAddress)) {
            sizeIterable = CompressedUnsignedLongByteIterable.getIterable(size << 1);
            iterables = new ByteIterable[]{keyIterable, key, sizeIterable, rootDataIterable};
            result = log.tryWrite(type, structureId, new CompoundByteIterable(iterables), expired);
            if (result >= 0) {
                address = result;
                return result;
            } else {
                canRetry = false;
            }
        } else {
            canRetry = true;
        }
        if (!log.isLastWrittenFileAddress(startAddress)) {
            final byte writtenType = log.getWrittenLoggableType(startAddress, BTreeBase.DUP_LEAF);
            if (NullLoggable.isNullLoggable(writtenType)) {
                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, expired) : log.writeContinuously(type, structureId, data, expired);
        if (result < 0) {
            if (canRetry) {
                iterables[3] = CompressedUnsignedLongByteIterable.getIterable(log.getWrittenHighAddress() - startAddress);
                result = log.writeContinuously(type, structureId, new CompoundByteIterable(iterables), expired);

                if (result < 0) {
                    throw new TooBigLoggableException();
                }
            } else {
                throw new TooBigLoggableException();
            }
        }
        address = result;
        return result;
    }