Esempio n. 1
0
        /// <summary>
        /// Creates a tree from the given chunks. Children are grouped to increase the likelihood of node reuse.
        /// </summary>
        private static DedupNode CreateRollingHashTree(IReadOnlyList <DedupNode> chunks)
        {
            // If we do need to make a tree, then we'll want to use a rolling hash function to ensure
            // that we get consistent groupings of children nodes even with insertions/removals
            // of children (i.e. changes to the underlying file).
            var rolling = new RollingHash(
                windowLength: 4,
                bitMask: VariableChildCountBitMask,
                minCount: MinVariableChildCount);
            var thisLevel = new Queue <DedupNode>(chunks);

            while (thisLevel.Count > DedupNode.MaxDirectChildrenPerNode)
            {
                var nextLevel = new Queue <DedupNode>();
                while (thisLevel.Any())
                {
                    rolling.Reset();
                    var nodesForChild = new List <DedupNode>();
                    while (thisLevel.Any() && nodesForChild.Count < DedupNode.MaxDirectChildrenPerNode && !rolling.IsAtBoundary)
                    {
                        var node = thisLevel.Dequeue();

                        ulong nodeHash = 0;
                        nodeHash ^= BitConverter.ToUInt64(node.Hash, 0);
                        nodeHash ^= BitConverter.ToUInt64(node.Hash, 8);
                        nodeHash ^= BitConverter.ToUInt64(node.Hash, 16);
                        nodeHash ^= BitConverter.ToUInt64(node.Hash, 24);

                        rolling.Add(nodeHash);

                        nodesForChild.Add(node);
                    }

                    var newNode = new DedupNode(nodesForChild);
                    nextLevel.Enqueue(newNode);
                }

                thisLevel = nextLevel;
            }

            var root = new DedupNode(thisLevel.ToList());

            return(root);
        }