/// <summary> /// 处理写。 /// </summary> /// <param name="state">状态。</param> private void PerpetualWriterMethod(object state) { #if Zip_Trace TraceOutput(TraceBits.WriterThread, "_PerpetualWriterMethod START"); #endif try { do { // wait for the next session #if Zip_Trace TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.WaitOne(begin) PWM"); #endif _sessionReset.WaitOne(); #if Zip_Trace TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.WaitOne(done) PWM"); #endif if (_isDisposed) { break; } #if Zip_Trace TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.Reset() PWM"); #endif _sessionReset.Reset(); // repeatedly write buffers as they become ready WorkItem workitem = null; Py.Algorithm.Crc32 c = new Py.Algorithm.Crc32(); do { workitem = _pool[_nextToWrite % _pc]; lock (workitem) { #if Zip_Trace if (_noMoreInputForThisSegment) { TraceOutput(TraceBits.Write, "Write drain wi({0}) stat({1}) canuse({2}) cba({3})", workitem.Index, workitem.CurrentStatus, (workitem.CurrentStatus == WorkItem.Status.Compressed), workitem.CompressedBytesAvailable); } #endif do { if (workitem.CurrentStatus == WorkItem.Status.Compressed) { #if Zip_Trace TraceOutput(TraceBits.WriteBegin, "Write begin wi({0}) stat({1}) cba({2})", workitem.Index, workitem.CurrentStatus, workitem.CompressedBytesAvailable); #endif workitem.CurrentStatus = WorkItem.Status.Writing; _outStream.Write(workitem.Compressed, 0, workitem.CompressedBytesAvailable); c.Combine(workitem.Crc, workitem.InputBytesAvailable); _totalBytesProcessed += workitem.InputBytesAvailable; _nextToWrite++; workitem.InputBytesAvailable = 0; workitem.CurrentStatus = WorkItem.Status.Done; #if Zip_Trace TraceOutput(TraceBits.WriteDone, "Write done wi({0}) stat({1}) cba({2})", workitem.Index, workitem.CurrentStatus, workitem.CompressedBytesAvailable); #endif Monitor.Pulse(workitem); break; } else { int wcycles = 0; // I've locked a workitem I cannot use. // Therefore, wake someone else up, and then release the lock. while (workitem.CurrentStatus != WorkItem.Status.Compressed) { #if Zip_Trace TraceOutput(TraceBits.WriteWait, "Write waiting wi({0}) stat({1}) nw({2}) nf({3}) nomore({4})", workitem.Index, workitem.CurrentStatus, _nextToWrite, _nextToFill, _noMoreInputForThisSegment); #endif if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) { break; } wcycles++; // wake up someone else Monitor.Pulse(workitem); // release and wait Monitor.Wait(workitem); #if Zip_Trace if (workitem.CurrentStatus == WorkItem.Status.Compressed) { TraceOutput(TraceBits.WriteWait, "Write A-OK wi({0}) stat({1}) iba({2}) cba({3}) cyc({4})", workitem.Index, workitem.CurrentStatus, workitem.InputBytesAvailable, workitem.CompressedBytesAvailable, wcycles); } #endif } if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) { break; } } }while (true); } #if Zip_Trace if (_noMoreInputForThisSegment) { TraceOutput(TraceBits.Write, "Write nomore nw({0}) nf({1}) break({2})", _nextToWrite, _nextToFill, (_nextToWrite == _nextToFill)); } #endif if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) { break; } } while (true); // Finish: // After writing a series of buffers, closing each one with // Flush.Sync, we now write the final one as Flush.Finish, and // then stop. byte[] buffer = new byte[128]; ZlibCodec compressor = new ZlibCodec(); ZlibState rc = compressor.InitializeDeflate(_compressLevel, false); compressor.InputBuffer = null; compressor.NextIn = 0; compressor.AvailableBytesIn = 0; compressor.OutputBuffer = buffer; compressor.NextOut = 0; compressor.AvailableBytesOut = buffer.Length; rc = compressor.Deflate(FlushType.Finish); if (rc != ZlibState.StreamEnd && rc != ZlibState.Success) { throw new ZlibException("压缩错误: " + compressor.Message); } if (buffer.Length - compressor.AvailableBytesOut > 0) { #if Zip_Trace TraceOutput(TraceBits.WriteBegin, "Write begin flush bytes({0})", buffer.Length - compressor.AvailableBytesOut); #endif _outStream.Write(buffer, 0, buffer.Length - compressor.AvailableBytesOut); #if Zip_Trace TraceOutput(TraceBits.WriteBegin, "Write done flush"); #endif } compressor.EndDeflate(); _Crc32 = c.Crc32Result; // signal that writing is complete: #if Zip_Trace TraceOutput(TraceBits.Synch, "Synch _writingDone.Set() PWM"); #endif _writingDone.Set(); }while (true); } catch (System.Exception exc1) { lock (_eLock) { // expose the exception to the main thread if (_pendingException != null) { _pendingException = exc1; } } } #if Zip_Trace TraceOutput(TraceBits.WriterThread, "_PerpetualWriterMethod FINIS"); #endif }
/// <summary> /// 压缩一个内容。 /// </summary> /// <param name="wi">内容。</param> private void DeflateOne(Object wi) { WorkItem workitem = (WorkItem)wi; try { // compress one buffer int myItem = workitem.Index; lock (workitem) { if (workitem.CurrentStatus != WorkItem.Status.Filled) { throw new InvalidOperationException(); } Py.Algorithm.Crc32 crc = new Py.Algorithm.Crc32(); // use the workitem: // calc CRC on the buffer crc.SlurpBlock(workitem.Buffer, 0, workitem.InputBytesAvailable); #region 压缩 ZlibCodec compressor = workitem.Compressor; ZlibState rc; compressor.ResetDeflate(); compressor.NextIn = 0; compressor.AvailableBytesIn = workitem.InputBytesAvailable; // 第 1 步: 压缩缓存 compressor.NextOut = 0; compressor.AvailableBytesOut = workitem.Compressed.Length; do { compressor.Deflate(FlushType.None); } while (compressor.AvailableBytesIn > 0 || compressor.AvailableBytesOut == 0); // 第 2 步: 异步输出缓存 rc = compressor.Deflate(FlushType.Sync); workitem.CompressedBytesAvailable = (int)compressor.TotalBytesOut; #endregion // 更新状态 workitem.CurrentStatus = WorkItem.Status.Compressed; workitem.Crc = crc.Crc32Result; #if Zip_Trace TraceOutput(TraceBits.Compress, "Compress wi({0}) stat({1}) len({2})", workitem.Index, workitem.CurrentStatus, workitem.CompressedBytesAvailable ); #endif // release the item Monitor.Pulse(workitem); } } catch (System.Exception exc1) { lock (_eLock) { // expose the exception to the main thread if (_pendingException != null) { _pendingException = exc1; } } } }