/// <summary> /// </summary> /// <param name="Algo"></param> public byte[] ComputeLargeStreamHash(Stream Stream, RateTracker Tracker, ChecksumProgressEventHandler Callback) { // Buffer size optimized for reading massive files. byte[] buffer = MemoryPool.AllocBuffer(BufferSize); int bytesRead; do { bytesRead = Stream.Read(buffer, 0, BufferSize); if (bytesRead > 0) { HashCore(buffer, 0, bytesRead); if (Callback != null) { Callback?.Invoke(bytesRead); } if (Tracker != null) { Tracker.Out(bytesRead); } } } while (bytesRead > 0); HashValue = HashFinal(); byte[] Tmp = (byte[])HashValue.Clone(); Initialize(); MemoryPool.ReleaseBuffer(buffer); return(Tmp); }
/// <summary> /// </summary> /// <param name="Stm"></param> /// <param name="Work"></param> /// <param name="Offset"></param> /// <param name="Size"></param> private void ReadWithOffset(ActiveStream Stm, Task Work, int Offset) { lock (Stm) { try { Stm.Stream.Seek(Work.Offset + Offset, SeekOrigin.Begin); Stm.Stream.BeginRead( Work.Data, (int)Work.DataOffset + Offset, (int)Work.Size - Offset, Result => { try { int BytesRead = Stm.Stream.EndRead(Result); if (BytesRead == 0) { Logger.Log(LogLevel.Error, LogCategory.IO, "Failed to read file {0} at offset {1} size {2}. Encountered end of file.", Stm.Path, Work.Offset + Offset, Work.Size - Offset); Work.Callback?.Invoke(false); } else { GlobalBandwidthStats.Out(BytesRead); if (BytesRead < Work.Size) { ReadWithOffset(Stm, Work, Offset + BytesRead); return; } ulong ElapsedTime = TimeUtils.Ticks - Work.QueueTime; OutLatency.Add(ElapsedTime); Work.Callback?.Invoke(true); } } catch (Exception Ex) { Logger.Log(LogLevel.Error, LogCategory.IO, "Failed to read file {0} with error: {1}", Stm.Path, Ex.Message); Work.Callback?.Invoke(false); } finally { Interlocked.Add(ref GlobalQueuedOut, -Work.Size); Interlocked.Decrement(ref Stm.ActiveOperations); WakeThread(); } }, null ); } catch (Exception Ex) { Logger.Log(LogLevel.Error, LogCategory.IO, "Failed to read to file {0} with error: {1}", Stm.Path, Ex.Message); Work.Callback?.Invoke(false); Interlocked.Add(ref GlobalQueuedOut, -Work.Size); Interlocked.Decrement(ref Stm.ActiveOperations); WakeThread(); } } }