Example #1
0
 /// <summary>
 ///     Calculate content hash of content in a stream.
 /// </summary>
 public static async Task <ContentHash> CalculateHashAsync(this StreamWithLength stream, HashType hashType)
 {
     using (var hasher = HashInfoLookup.Find(hashType).CreateContentHasher())
     {
         return(await hasher.GetContentHashAsync(stream));
     }
 }
Example #2
0
        /// <inheritdoc />
        public async Task <ContentHash> GetContentHashAsync(StreamWithLength content)
        {
            var stopwatch = Stopwatch.StartNew();

            try
            {
                using (var hasherHandle = CreateToken())
                {
                    var hasher = hasherHandle.Hasher;

                    IPoolHandle <byte[]> bufferHandle;
                    if (hasher is IHashAlgorithmBufferPool bufferPool)
                    {
                        bufferHandle = bufferPool.GetBufferFromPool();
                    }
                    else
                    {
                        bufferHandle = _bufferPool.Get();
                    }

                    using (bufferHandle)
                    {
                        var buffer = bufferHandle.Value;

                        if (hasher is IHashAlgorithmInputLength sizeHint)
                        {
                            sizeHint.SetInputLength(content.Length - content.Stream.Position);
                        }

                        int bytesJustRead;

                        do
                        {
                            int totalBytesRead = 0;
                            int bytesNeeded    = buffer.Length - totalBytesRead;
                            do
                            {
                                bytesJustRead = await content.Stream.ReadAsync(buffer, totalBytesRead, buffer.Length - totalBytesRead).ConfigureAwait(false);

                                totalBytesRead += bytesJustRead;
                                bytesNeeded    -= bytesJustRead;
                            } while (bytesNeeded > 0 && bytesJustRead != 0);

                            hasher.TransformBlock(buffer, 0, totalBytesRead, null, 0);
                        } while (bytesJustRead > 0);

                        hasher.TransformFinalBlock(buffer, 0, 0);
                        var hashBytes = hasher.Hash;
                        return(new ContentHash(Info.HashType, hashBytes));
                    }
                }
            }
            finally
            {
                stopwatch.Stop();
                Interlocked.Add(ref _ticks, stopwatch.Elapsed.Ticks);
                Interlocked.Increment(ref _calls);
            }
        }
Example #3
0
        /// <nodoc />
        public async Task <DedupNode> HashContentAndGetDedupNodeAsync(StreamWithLength content)
        {
            var contentHashDedupNodeTuple = await GetContentHashInternalAsync(content); // filestream has length so this is okay?

            if (contentHashDedupNodeTuple.Item2 == null)
            {
                throw new InvalidOperationException($"{nameof(HashContentAndGetDedupNodeAsync)}: dedup node was not retrievable after hashing content - incompatible hash type.");
            }
            return((DedupNode)contentHashDedupNodeTuple.Item2);
        }
Example #4
0
        /// <summary>
        ///     Calculate content hash of content in a stream.
        /// </summary>
        public static Task <ContentHash> CalculateHashAsync(this StreamWithLength stream, HashType hashType)
        {
#if NET_COREAPP
            if (stream.Stream is FileStream fileStream)
            {
                return(Task.FromResult(fileStream.HashFile(hashType)));
            }
#endif // NET_COREAPP

            var hasher = HashInfoLookup.GetContentHasher(hashType);
            return(hasher.GetContentHashAsync(stream));
        }
Example #5
0
        /// <summary>
        /// GetContentHashInternalAsync - for internal use only.
        /// </summary>
        /// <param name="content">Content stream with length.</param>
        /// <returns>A tuple of content hash and dedup node.</returns>
        protected async Task <(ContentHash, DedupNode?)> GetContentHashInternalAsync(StreamWithLength content)
        {
            var stopwatch = Stopwatch.StartNew();

            try
            {
                using var hasherHandle = CreateToken();
                var hasher = hasherHandle.Hasher;

                IPoolHandle <byte[]> bufferHandle;
                if (hasher is IHashAlgorithmBufferPool bufferPool)
                {
                    bufferHandle = bufferPool.GetBufferFromPool();
                }
                else
                {
                    bufferHandle = _bufferPool.Get();
                }

                using (bufferHandle)
                {
                    var buffer = bufferHandle.Value;

                    if (hasher is IHashAlgorithmInputLength sizeHint)
                    {
                        sizeHint.SetInputLength(content.Length - content.Stream.Position);
                    }

                    int bytesJustRead;

                    do
                    {
                        int totalBytesRead = 0;
                        int bytesNeeded    = buffer.Length - totalBytesRead;
                        do
                        {
                            bytesJustRead = await content.Stream.ReadAsync(buffer, totalBytesRead, buffer.Length - totalBytesRead).ConfigureAwait(false);

                            totalBytesRead += bytesJustRead;
                            bytesNeeded    -= bytesJustRead;
                        } while (bytesNeeded > 0 && bytesJustRead != 0);

                        hasher.TransformBlock(buffer, 0, totalBytesRead, null, 0);
                    } while (bytesJustRead > 0);

                    hasher.TransformFinalBlock(buffer, 0, 0);
                    var hashBytes = hasher.Hash !;

                    // Retrieve the DedupNode before losing the hasher token.
                    switch (Info.HashType)
                    {
                    case HashType.Dedup64K:
                    case HashType.Dedup1024K:
                        var contentHasher = (DedupNodeOrChunkHashAlgorithm)hasher;
                        return(new ContentHash(Info.HashType, hashBytes), contentHasher.GetNode());

                    case HashType.SHA1:
                    case HashType.SHA256:
                    case HashType.MD5:
                    case HashType.Vso0:
                    case HashType.DedupSingleChunk:
                    case HashType.DedupNode:
                    case HashType.Murmur:
                        return(new ContentHash(Info.HashType, hashBytes), null);

                    default:
                        throw new NotImplementedException($"Unsupported hashtype: {Info.HashType} encountered when hashing content.");
                    }
                }
            }
            finally
            {
                stopwatch.Stop();
                Interlocked.Add(ref _ticks, stopwatch.Elapsed.Ticks);
                Interlocked.Increment(ref _calls);
            }
        }
Example #6
0
 /// <inheritdoc />
 public HashingStream CreateWriteHashingStream(StreamWithLength stream, long parallelHashingFileSizeBoundary = -1)
 {
     return(CreateWriteHashingStream(stream.Length, stream, parallelHashingFileSizeBoundary));
 }
Example #7
0
        /// <inheritdoc />
        public async Task <ContentHash> GetContentHashAsync(StreamWithLength content)
        {
            var(contentHash, _) = await GetContentHashInternalAsync(content);

            return(contentHash);
        }
        /// <summary>
        ///     Calculate content hash of content in a stream.
        /// </summary>
        public static Task <ContentHash> CalculateHashAsync(this StreamWithLength stream, HashType hashType)
        {
            var hasher = HashInfoLookup.GetContentHasher(hashType);

            return(hasher.GetContentHashAsync(stream));
        }
Example #9
0
 /// <summary>
 /// Casts <see cref="StreamWithLength"/> to <see cref="FileStream"/>.
 /// </summary>
 public static FileStream ToFileStream(this StreamWithLength streamWithLength) => (FileStream)streamWithLength.Stream;