private List<SplitTreeNode> UpdateBlock(BlockBatch blockBatch)
        {
            Block block = dictionary.Container.ReadBlock(blockBatch.BlockOffset);

            //todo: review types
            List<Record> records = MergeRecords(block.Records, blockBatch.Records, blockBatch.MaskOffset/8);

            SplitTreeNode splitTreeRoot = new SplitTreeNode(null, -1, blockBatch.MaskOffset, blockBatch.NodeIndex, blockBatch.BlockOffset, records);

            List<SplitTreeNode> updatedTreeNodes = new List<SplitTreeNode>();
            updatedTreeNodes.Add(splitTreeRoot);

            List<SplitTreeNode> unsplitTreeNodes = new List<SplitTreeNode>();
            if (splitTreeRoot.Records.Count > dictionary.Container.RecordsPerBlock)
            {
                unsplitTreeNodes.Add(splitTreeRoot);
            }

            while (unsplitTreeNodes.Count != 0)
            {
                SplitTreeNode nodeToSplit = unsplitTreeNodes[unsplitTreeNodes.Count - 1];
                unsplitTreeNodes.RemoveAt(unsplitTreeNodes.Count - 1);

                List<SplitTreeNode> newNodes = Split(nodeToSplit);
                foreach (SplitTreeNode treeNode in newNodes)
                {
                    updatedTreeNodes.Add(treeNode);
                    if (treeNode.Records.Count > dictionary.Container.RecordsPerBlock)
                    {
                        unsplitTreeNodes.Add(treeNode);
                    }
                }
            }

            return updatedTreeNodes;
        }
        private List<BlockBatch> SplitByBlock(List<Record> records, bool addMissingBranches)
        {
            Dictionary<long, BlockBatch> blockBatches = new Dictionary<long, BlockBatch>();

            foreach (var record in records)
            {
                int maskOffset = 0;
                int nodeIndex = 0;
                CompactTreeNode node = dictionary.Container.GetTreeNode(nodeIndex);
                int childNum = 0;
                while (node.IsSplitNode)
                {
                    bool left = (record.Key.GetByteAt(maskOffset/8) & (1 << (7 - maskOffset%8))) == 0;
                    childNum = left ? 0 : 1;
                    int childIndex = node.GetChild(childNum);
                    if (childIndex == 0)
                    {
                        break;
                    }
                    nodeIndex = childIndex;
                    node = dictionary.Container.GetTreeNode(nodeIndex);
                    maskOffset++;
                }

                if (node.IsSplitNode)
                {
                    if (addMissingBranches)
                    {
                        //todo: test this branch
                        long blockOffset = dictionary.Container.AllocateBlock();
                        nodeIndex = dictionary.Container.AddDataNode(nodeIndex, childNum, blockOffset);
                        node = dictionary.Container.GetTreeNode(nodeIndex);
                        maskOffset++;
                    }
                }

                if (node.IsDataNode)
                {
                    long blockOffset = node.Value;

                    BlockBatch blockBatch;
                    if (!blockBatches.TryGetValue(blockOffset, out blockBatch))
                    {
                        blockBatch = new BlockBatch(blockOffset, maskOffset, nodeIndex);
                        blockBatches.Add(blockOffset, blockBatch);
                    }

                    blockBatch.Records.Add(record);
                }
            }

            List<BlockBatch> batchesList = blockBatches.Values.ToList();

            foreach (BlockBatch batch in batchesList)
            {
                batch.Records.Sort((recordA, recordB) => CompareKeys(recordA.Key, recordB.Key, batch.MaskOffset/8));
            }

            return batchesList;
        }