fun save()

in environment/src/main/kotlin/jetbrains/exodus/tree/patricia/MutableNode.kt [220:302]


    fun save(tree: PatriciaTreeMutable, context: MutableNodeSaveContext): Long {
        val nodeStream = context.newNodeStream()
        // save key and value
        if (hasKey()) {
            fillBytes(keySequence.length.toLong(), nodeStream)
            ByteIterableBase.fillBytes(keySequence, nodeStream)
        }
        value?.let { value ->
            fillBytes(value.length.toLong(), nodeStream)
            ByteIterableBase.fillBytes(value, nodeStream)
        }
        val childrenCount = childrenCount
        if (childrenCount > 0) {
            // save references to children
            if (tree.useV1Format || childrenCount < 2 /* for single child, v2 format definitely wouldn't benefit */) {
                saveChildrenV1(childrenCount, nodeStream)
            } else {
                saveChildrenV2(childrenCount, nodeStream)
            }
        }
        // finally, write loggable
        val log = tree.getLog()
        var type = loggableType
        val structureId = tree.getStructureId()
        val mainIterable: ByteIterable = nodeStream.asArrayByteIterable()
        val startAddress = context.startAddress
        var result: Long
        val expiredLoggables = tree.getOrInitExperedLoggables()
        if (!isRoot) {
            result = log.write(type, structureId, mainIterable, expiredLoggables)
            // save address of the first saved loggable
            if (startAddress == Loggable.NULL_ADDRESS) {
                context.startAddress = result
            }
            return result
        }
        val iterables = arrayOfNulls<ByteIterable>(3)
        iterables[0] = context.preliminaryRootData
        // Save root without back reference if the tree consists of root only.
        // In that case, startAddress is undefined, i.e. no other child is saved before root.
        if (startAddress == Loggable.NULL_ADDRESS) {
            iterables[1] = mainIterable
            result = log.write(type, structureId, CompoundByteIterable(iterables, 2), expiredLoggables)
            return result
        }
        // Tree is saved with several loggables. Is it saved in a single file?
        val singleFile = log.isLastWrittenFileAddress(startAddress)
        val pos: Int // where the offset info will be inserted
        if (!singleFile) {
            pos = 1
            iterables[2] = mainIterable
        } else {
            iterables[1] = mainIterable
            result = log.tryWrite(type, structureId, CompoundByteIterable(iterables, 2), expiredLoggables)

            if (result >= 0) {
                return result
            }
            pos = 1
            iterables[2] = mainIterable
        }
        type = type plus PatriciaTreeBase.ROOT_BIT_WITH_BACKREF
        iterables[pos] = CompressedUnsignedLongByteIterable.getIterable(log.writtenHighAddress - startAddress)
        val data: ByteIterable = CompoundByteIterable(iterables, pos + 2)
        result =
            if (singleFile) {
                log.writeContinuously(type, structureId, data, expiredLoggables)
            } else {
                log.tryWrite(type, structureId, data, expiredLoggables)
            }
        if (result < 0) {
            if (!singleFile) {
                iterables[pos] = CompressedUnsignedLongByteIterable.getIterable(log.writtenHighAddress - startAddress)
                result =
                    log.writeContinuously(type, structureId, CompoundByteIterable(iterables, pos + 2), expiredLoggables)
                if (result >= 0) {
                    return result
                }
            }
            throw TooBigLoggableException()
        }
        return result
    }