Пример #1
0
        private static BlobIdentifier ComputeIdentifierBasedOnBlocks(IEnumerable <BlobBlockHash> blocks)
        {
            var rollingId = new VsoHash.RollingBlobIdentifier();

            // ReSharper disable once GenericEnumeratorNotDisposed
            IEnumerator <BlobBlockHash> enumerator = blocks.GetEnumerator();

            bool isLast = !enumerator.MoveNext();

            if (isLast)
            {
                throw new InvalidDataException("Blob must have at least one block.");
            }

            BlobBlockHash current = enumerator.Current;

            isLast = !enumerator.MoveNext();
            while (!isLast)
            {
                rollingId.Update(current);
                current = enumerator.Current;
                isLast  = !enumerator.MoveNext();
            }

            return(rollingId.Finalize(current));
        }
Пример #2
0
            public BlobIdentifierWithBlocks Finalize(BlobBlockHash currentBlockIdentifier)
            {
                _blockHashes.Add(currentBlockIdentifier);
                var blobId = _inner.Finalize(currentBlockIdentifier);

                return(new BlobIdentifierWithBlocks(blobId, _blockHashes));
            }
Пример #3
0
        private static async Task ReadBlockAsync(
            Stream stream,
            SemaphoreSlim?blockActionSemaphore,
            long bytesLeftInBlob,
            BlockReadCompleteAsync readCallback)
        {
            if (blockActionSemaphore != null)
            {
                await blockActionSemaphore.WaitAsync().ConfigureAwait(false);
            }

            bool disposeNeeded = true;

            try
            {
                Pool <byte[]> .PoolHandle blockBufferHandle = GlobalObjectPools.TwoMbByteArrayPool.Get();
                try
                {
                    byte[] blockBuffer  = blockBufferHandle.Value;
                    int    bytesToRead  = (int)Math.Min(BlockSize, bytesLeftInBlob);
                    int    bufferOffset = 0;
                    while (bytesToRead > 0)
                    {
                        int bytesRead = await stream.ReadAsync(blockBuffer, bufferOffset, bytesToRead).ConfigureAwait(false);

                        bytesToRead  -= bytesRead;
                        bufferOffset += bytesRead;
                        if (bytesRead == 0)
                        {
                            // ReadAsync returns 0 when the stream has ended.
                            if (bytesToRead > 0)
                            {
                                throw new EndOfStreamException();
                            }
                        }
                    }

                    BlobBlockHash blockHash = HashBlock(blockBuffer, bufferOffset);
                    disposeNeeded = false; // readCallback is now responsible for disposing the blockBufferHandle
                    await readCallback(blockBufferHandle, bufferOffset, blockHash).ConfigureAwait(false);
                }
                finally
                {
                    if (disposeNeeded)
                    {
                        blockBufferHandle.Dispose();
                    }
                }
            }
            finally
            {
                if (disposeNeeded)
                {
                    blockActionSemaphore?.Release();
                }
            }
        }
Пример #4
0
 public BlobIdentifier Finalize(BlobBlockHash currentBlockIdentifier)
 {
     // TODO:if we want to enforce this we should implement BlobBlockHash.BlockSize (bug 1365340)
     //
     // if (blockSize > BlockSize)
     // {
     //     throw new InvalidOperationException("Blocks cannot be bigger than BlockSize.");
     // }
     UpdateInternal(currentBlockIdentifier, true);
     return(new BlobIdentifier(_rollingId, VsoAlgorithmId));
 }
Пример #5
0
 public void Update(BlobBlockHash currentBlockIdentifier)
 {
     // TODO:if we want to enforce this we should implement BlobBlockHash.BlockSize (bug 1365340)
     //
     // var currentBlockSize = currentBlockIdentifier.BlockSize;
     // if (currentBlockSize != BlockSize)
     // {
     //     throw new InvalidOperationException($"Non-final blocks must be of size {BlockSize}; but the given block has size {currentBlockSize}");
     // }
     UpdateInternal(currentBlockIdentifier, false);
 }
Пример #6
0
        private static void ReadBlock(Stream stream, SemaphoreSlim?blockActionSemaphore, long bytesLeftInBlob, BlockReadComplete readCallback)
        {
            blockActionSemaphore?.Wait();

            bool disposeNeeded = true;

            try
            {
                Pool <byte[]> .PoolHandle blockBufferHandle = GlobalObjectPools.TwoMbByteArrayPool.Get();
                try
                {
                    byte[] blockBuffer  = blockBufferHandle.Value;
                    int    bytesToRead  = (int)Math.Min(BlockSize, bytesLeftInBlob);
                    int    bufferOffset = 0;
                    while (bytesToRead > 0)
                    {
                        int bytesRead = stream.Read(blockBuffer, bufferOffset, bytesToRead);
                        bytesToRead  -= bytesRead;
                        bufferOffset += bytesRead;
                        if (bytesRead == 0)
                        {
                            // ReadAsync returns 0 when the stream has ended.
                            if (bytesToRead > 0)
                            {
                                throw new EndOfStreamException();
                            }
                        }
                    }

                    BlobBlockHash blockHash = HashBlock(blockBuffer, bufferOffset);
                    disposeNeeded = false;
                    readCallback(blockBufferHandle, bufferOffset, blockHash);
                }
                finally
                {
                    if (disposeNeeded)
                    {
                        blockBufferHandle.Dispose();
                    }
                }
            }
            finally
            {
                if (disposeNeeded)
                {
                    blockActionSemaphore?.Release();
                }
            }
        }
Пример #7
0
            private void UpdateInternal(BlobBlockHash currentBlockIdentifier, bool isFinalBlock)
            {
                if (_finalAdded && isFinalBlock)
                {
                    throw new InvalidOperationException("Final block already added.");
                }

                int combinedBufferLength = _rollingId.Length + currentBlockIdentifier.HashBytes.Length + 1;
                var combinedBuffer       = new byte[combinedBufferLength];

                Array.Copy(_rollingId, combinedBuffer, _rollingId.Length);
                Array.Copy(currentBlockIdentifier.HashBytes, 0, combinedBuffer, _rollingId.Length, currentBlockIdentifier.HashBytes.Length);
                combinedBuffer[combinedBufferLength - 1] = Convert.ToByte(isFinalBlock);
                _rollingId = ComputeSHA256Hash(combinedBuffer);

                if (isFinalBlock)
                {
                    _finalAdded = true;
                }
            }
Пример #8
0
 public void Update(BlobBlockHash currentBlockIdentifier)
 {
     _blockHashes.Add(currentBlockIdentifier);
     _inner.Update(currentBlockIdentifier);
 }