public async Task DownloadFile(string virtualPath, string systemPath, bool lowPriority = false) { var size = await GetFileSize(virtualPath).ConfigureAwait(false); long position = 0; if (size < 0) { throw new FileNotFoundException($"There is no {virtualPath} on the server"); } using (lowPriority ? ThreadUtility.EnterBackgroundProcessingMode() : null) using (var fs = File.OpenWrite(systemPath)) { while (position < size) { var chunkLength = (int)Math.Min(1024 * 1024, size - position); using (var bytes = await DownloadSegment(virtualPath, position, chunkLength).ConfigureAwait(false)) { if (bytes.Object == null) { throw new IOException(); } await fs.WriteAsync(bytes.Object, 0, chunkLength).ConfigureAwait(false); } position += chunkLength; } } }
private static byte[][] ReadLeafs(HashAlgorithm tg, string filePath, long start, long end) { using (ThreadUtility.EnterBackgroundProcessingMode()) using (var threadFilePtr = FileStreamFactory.CreateFileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 128 * 1024)) { var threadFileBlock = new FileBlock(start, end); var LeafSize = 1024; var DataBlockSize = LeafSize * 1024; var data = new byte[LeafSize + 1]; var totalLeafs = threadFileBlock.Length / LeafSize + threadFileBlock.Length % LeafSize > 0 ? 1 : 0; var result = new byte[totalLeafs][]; threadFilePtr.Position = threadFileBlock.Start; while (threadFilePtr.Position < threadFileBlock.End) { var leafIndex = (int)((threadFilePtr.Position - start) / 1024); var dataBlock = new byte[Math.Min(threadFileBlock.End - threadFilePtr.Position, DataBlockSize)]; threadFilePtr.Read(dataBlock, 0, dataBlock.Length); //read block var blockLeafs = dataBlock.Length / LeafSize; int i; for (i = 0; i < blockLeafs; i++) { Buffer.BlockCopy(dataBlock, i * LeafSize, data, 1, LeafSize); tg.Initialize(); result[leafIndex++] = tg.ComputeHash(data); } if (i * LeafSize < dataBlock.Length) { data = new byte[dataBlock.Length - blockLeafs * LeafSize + 1]; data[0] = LeafHash; Buffer.BlockCopy(dataBlock, blockLeafs * LeafSize, data, 1, (data.Length - 1)); tg.Initialize(); result[leafIndex] = tg.ComputeHash(data); data = new byte[LeafSize + 1]; data[0] = LeafHash; } } return(result); } }
void ProcessLeafs(object threadId) { using (LowPriority ? ThreadUtility.EnterBackgroundProcessingMode() : null) using (var threadFilePtr = FileStreamFactory.CreateFileStream(_filename, FileMode.Open, FileAccess.Read, FileShare.Read, FileStreamBufferLength)) { var threadFileBlock = _fileParts[(int)threadId]; var tg = new T(); var data = new byte[LeafSize + 1]; threadFilePtr.Position = threadFileBlock.Start; var dataBlock = new byte[DataBlockSize]; while (threadFilePtr.Position < threadFileBlock.End) { var leafIndex = (int)(threadFilePtr.Position / 1024); var dataBlockSize = (int)Math.Min(threadFileBlock.End - threadFilePtr.Position, DataBlockSize); threadFilePtr.Read(dataBlock, 0, dataBlockSize); //read block Interlocked.Add(ref _processedBytes, dataBlockSize); var blockLeafs = dataBlockSize / 1024; int i; for (i = 0; i < blockLeafs; i++) { Buffer.BlockCopy(dataBlock, i * LeafSize, data, 1, LeafSize); tg.Initialize(); TTH[0][leafIndex++] = tg.ComputeHash(data); } if (i * LeafSize < dataBlockSize) { data = new byte[dataBlockSize - blockLeafs * LeafSize + 1]; data[0] = LeafHash; Buffer.BlockCopy(dataBlock, blockLeafs * LeafSize, data, 1, (data.Length - 1)); tg.Initialize(); TTH[0][leafIndex] = tg.ComputeHash(data); data = new byte[LeafSize + 1]; data[0] = LeafHash; } } } }
void CompressTree() { int level = 0; using (LowPriority ? ThreadUtility.EnterBackgroundProcessingMode() : null) { while (level + 1 < LevelCount) { int leafIndex = 0; var internalLeafCount = (_leafCount / 2) + (_leafCount % 2); TTH[level + 1] = new byte[internalLeafCount][]; if (!LowPriority && _leafCount > 128) { Parallel.For(0, _leafCount / 2, ind => ProcessInternalLeaf(level + 1, ind, TTH[level][ind * 2], TTH[level][ind * 2 + 1])); leafIndex = _leafCount / 2; } else { for (var i = 1; i < _leafCount; i += 2) { ProcessInternalLeaf(level + 1, leafIndex++, TTH[level][i - 1], TTH[level][i]); } } if (leafIndex < internalLeafCount) { TTH[level + 1][leafIndex] = TTH[level][_leafCount - 1]; } level++; _leafCount = internalLeafCount; } } }