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
}