/// <summary> /// Create a node out of the list of chunks. /// </summary> protected internal virtual DedupNode CreateNode() { if (SingleChunkHotPath) { Contract.Assert(_chunks.Count == 0); Contract.Check(_bytesChunked == _sizeHint)?.Assert($"_bytesChunked != _sizeHint. _bytesChunked={_bytesChunked} _sizeHint={_sizeHint}"); Contract.Assert(_session == null); byte[] chunkHash = _chunkHasher.HashFinalInternal(); return(new DedupNode(DedupNode.NodeType.ChunkLeaf, (ulong)_sizeHint, chunkHash, 0)); } else { _session?.Dispose(); _session = null; if (_chunks.Count == 0) { return(new DedupNode(new ChunkInfo(0, 0, DedupChunkHashInfo.Instance.EmptyHash.ToHashByteArray()))); } else if (_chunks.Count == 1) { // Content is small enough to track as a chunk. var node = new DedupNode(_chunks.Single()); Contract.Assert(node.Type == DedupNode.NodeType.ChunkLeaf); return(node); } else { return(DedupNodeTree.Create(_chunks, _treeAlgorithm)); } } }
/// <summary> /// Create a node out of the list of chunks. /// </summary> protected internal virtual DedupNode CreateNode() { if (SingleChunkHotPath) { Contract.Check(_chunks.Count == 0)?.Assert($"Chunk count: {_chunks.Count} sizehint: {_sizeHint} chunker min chunk size: {_chunker.Configuration.MinChunkSize}"); Contract.Check(_bytesChunked == _sizeHint)?.Assert($"_bytesChunked != _sizeHint. _bytesChunked={_bytesChunked} _sizeHint={_sizeHint}"); Contract.Assert(_session == null, "Dedup session cannot be null."); byte[] chunkHash = _chunkHasher.HashFinalInternal(); return(new DedupNode(DedupNode.NodeType.ChunkLeaf, (ulong)_sizeHint, chunkHash, 0)); } else { _session?.Dispose(); _session = null; if (_chunks.Count == 0) { return(new DedupNode(new ChunkInfo(0, 0, DedupSingleChunkHashInfo.Instance.EmptyHash.ToHashByteArray()))); } else if (_chunks.Count == 1) { // Content is small enough to track as a chunk. var node = new DedupNode(_chunks.Single()); Contract.Check(node.Type == DedupNode.NodeType.ChunkLeaf)?.Assert($"{nameof(CreateNode)}: expected chunk leaf: {DedupNode.NodeType.ChunkLeaf} got {node.Type} instead."); return(node); } else { return(DedupNodeTree.Create(_chunks)); } } }
/// <inheritdoc /> protected override byte[] HashFinal() { _session.Dispose(); if (_chunker.TotalBytes == 0) { _chunks.Add(new ChunkInfo(0, 0, DedupChunkHashInfo.Instance.EmptyHash.ToHashByteArray())); } _lastNode = DedupNodeTree.Create(_chunks, _treeAlgorithm); // The array returned by this function will be cleared when this is disposed, so clone it. return(_lastNode.Value.Hash.ToArray()); }
/// <inheritdoc /> /// <remarks> /// Extends DedupNode algorithm to tag hash as DedupChunk or DedupNode. /// </remarks> protected override byte[] HashFinal() { _session.Dispose(); if (_chunker.TotalBytes == 0) { _chunks.Add(new ChunkInfo(0, 0, DedupChunkHashInfo.Instance.EmptyHash.ToHashByteArray())); } _lastNode = DedupNodeTree.Create(_chunks, _treeAlgorithm); if (_lastNode.Value.ChildNodes.Count == 1) { // Content is small enough to track as a chunk. _lastNode = _lastNode.Value.ChildNodes.Single(); } return(SerializeHashAndId()); }
/// <summary> /// Creates a tree or a single node containing the given chunk(s). /// </summary> /// <returns> /// The root of the tree, or a single chunk node encapsulating the chunk. /// </returns> public static DedupNode Create(IList <ChunkInfo> chunks) { if (chunks.Count == 0) { return(new DedupNode(new ChunkInfo(0, 0, DedupSingleChunkHashInfo.Instance.EmptyHash.ToHashByteArray()))); } else if (chunks.Count == 1) { // Content is small enough to track as a chunk. var node = new DedupNode(chunks.Single()); Contract.Check(node.Type == DedupNode.NodeType.ChunkLeaf)?.Assert( $"{nameof(Create)}: expected chunk leaf: {DedupNode.NodeType.ChunkLeaf} got {node.Type} instead."); return(node); } else { return(DedupNodeTree.Create(chunks)); } }
/// <inheritdoc /> /// <remarks> /// Extends DedupNode algorithm to tag hash as DedupChunk or DedupNode. /// </remarks> protected override byte[] HashFinal() { _session.Dispose(); if (_chunks.Count == 0) { _chunks.Add(new ChunkInfo(0, 0, DedupChunkHashInfo.Instance.EmptyHash.ToHashByteArray())); } if (_chunks.Count == 1) { // Content is small enough to track as a chunk. _lastNode = new DedupNode(_chunks.Single()); Contract.Assert(_lastNode.Value.Type == DedupNode.NodeType.ChunkLeaf); } else { _lastNode = DedupNodeTree.Create(_chunks, _treeAlgorithm); } return(SerializeHashAndId()); }