uint CreateKeyIndexFile(IBTreeRootNode root, CancellationToken cancellation)
{
var start = DateTime.UtcNow;
var file = FileCollection.AddFile("kvi");
var writer = file.GetAppenderWriter();
var keyCount = root.CalcKeyCount();
if (root.TrLogFileId != 0)
{
FileCollection.ConcurentTemporaryTruncate(root.TrLogFileId, root.TrLogOffset);
}
var keyIndex = new FileKeyIndex(FileCollection.NextGeneration(), FileCollection.Guid, root.TrLogFileId, root.TrLogOffset, keyCount, root.CommitUlong, KeyIndexCompression.None);
keyIndex.WriteHeader(writer);
if (keyCount > 0)
{
var stack = new List <NodeIdxPair>();
var prevKey = ByteBuffer.NewEmpty();
root.FillStackByIndex(stack, 0);
do
{
cancellation.ThrowIfCancellationRequested();
var nodeIdxPair = stack[stack.Count - 1];
var memberValue = ((IBTreeLeafNode)nodeIdxPair.Node).GetMemberValue(nodeIdxPair.Idx);
var key = ((IBTreeLeafNode)nodeIdxPair.Node).GetKey(nodeIdxPair.Idx);
var prefixLen = 0;
var minLen = Math.Min(prevKey.Length, key.Length);
for (int i = 0; i < minLen; i++)
{
if (prevKey[i] != key[i])
{
prefixLen = i;
break;
}
}
writer.WriteVUInt32((uint)prefixLen);
writer.WriteVUInt32((uint)(key.Length - prefixLen));
writer.WriteBlock(key.SubBuffer(prefixLen));
writer.WriteVUInt32(memberValue.ValueFileId);
writer.WriteVUInt32(memberValue.ValueOfs);
writer.WriteVInt32(memberValue.ValueSize);
prevKey = key;
} while (root.FindNextKey(stack));
}
writer.FlushBuffer();
file.HardFlush();
writer.WriteInt32(EndOfIndexFileMarker);
writer.FlushBuffer();
file.HardFlush();
file.Truncate();
FileCollection.SetInfo(file.Index, keyIndex);
Logger?.KeyValueIndexCreated(file.Index, keyIndex.KeyValueCount, file.GetSize(), DateTime.UtcNow - start);
return(file.Index);
}