The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting.Channels \ AsyncCopyStreamResult

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. //============================================================
  16. //
  17. // File: StreamHelper.cs
  18. //
  19. // Summary: Helper methods for streams.
  20. //
  21. //===========================================================
  22. using System;
  23. using System.IO;
  24. using System.Runtime.Remoting;
  25. using System.Threading;
  26. namespace System.Runtime.Remoting.Channels
  27. {
  28.    
  29.     static internal class StreamHelper
  30.     {
  31.         private static AsyncCallback _asyncCopyStreamReadCallback = new AsyncCallback(AsyncCopyStreamReadCallback);
  32.         private static AsyncCallback _asyncCopyStreamWriteCallback = new AsyncCallback(AsyncCopyStreamWriteCallback);
  33.        
  34.         static internal void CopyStream(Stream source, Stream target)
  35.         {
  36.             if (source == null)
  37.                 return;
  38.            
  39.             // see if this is a ChunkedMemoryStream (we can do a direct write)
  40.             ChunkedMemoryStream chunkedMemStream = source as ChunkedMemoryStream;
  41.             if (chunkedMemStream != null) {
  42.                 chunkedMemStream.WriteTo(target);
  43.             }
  44.             else {
  45.                 // see if this is a MemoryStream (we can do a direct write)
  46.                 MemoryStream memContentStream = source as MemoryStream;
  47.                 if (memContentStream != null) {
  48.                     memContentStream.WriteTo(target);
  49.                 }
  50.                 else {
  51.                     // otherwise, we need to copy the data through an intermediate buffer
  52.                    
  53.                     byte[] buffer = CoreChannel.BufferPool.GetBuffer();
  54.                     int bufferSize = buffer.Length;
  55.                     int readCount = source.Read(buffer, 0, bufferSize);
  56.                     while (readCount > 0) {
  57.                         target.Write(buffer, 0, readCount);
  58.                         readCount = source.Read(buffer, 0, bufferSize);
  59.                     }
  60.                     CoreChannel.BufferPool.ReturnBuffer(buffer);
  61.                 }
  62.             }
  63.            
  64.         }
  65.         // CopyStream
  66.        
  67.        
  68.         static internal void BufferCopy(byte[] source, int srcOffset, byte[] dest, int destOffset, int count)
  69.         {
  70.             if (count > 8) {
  71.                 Buffer.BlockCopy(source, srcOffset, dest, destOffset, count);
  72.             }
  73.             else {
  74.                 for (int co = 0; co < count; co++)
  75.                     dest[destOffset + co] = source[srcOffset + co];
  76.             }
  77.         }
  78.         // BufferCopy
  79.        
  80.        
  81.        
  82.         static internal IAsyncResult BeginAsyncCopyStream(Stream source, Stream target, bool asyncRead, bool asyncWrite, bool closeSource, bool closeTarget, AsyncCallback callback, object state)
  83.         {
  84.             AsyncCopyStreamResult streamState = new AsyncCopyStreamResult(callback, state);
  85.            
  86.             byte[] buffer = CoreChannel.BufferPool.GetBuffer();
  87.            
  88.             streamState.Source = source;
  89.             streamState.Target = target;
  90.             streamState.Buffer = buffer;
  91.             streamState.AsyncRead = asyncRead;
  92.             streamState.AsyncWrite = asyncWrite;
  93.             streamState.CloseSource = closeSource;
  94.             streamState.CloseTarget = closeTarget;
  95.            
  96.             try {
  97.                 AsyncCopyReadHelper(streamState);
  98.             }
  99.             catch (Exception e) {
  100.                 streamState.SetComplete(null, e);
  101.             }
  102.             catch {
  103.                 streamState.SetComplete(null, new Exception(CoreChannel.GetResourceString("Remoting_nonClsCompliantException")));
  104.             }
  105.            
  106.             return streamState;
  107.         }
  108.         // BeginAsyncCopyStream
  109.         static internal void EndAsyncCopyStream(IAsyncResult iar)
  110.         {
  111.             AsyncCopyStreamResult asyncResult = (AsyncCopyStreamResult)iar;
  112.            
  113.             if (!iar.IsCompleted) {
  114.                 iar.AsyncWaitHandle.WaitOne();
  115.             }
  116.            
  117.             if (asyncResult.Exception != null) {
  118.                 throw asyncResult.Exception;
  119.             }
  120.         }
  121.         // EndAsyncCopyStream
  122.        
  123.         private static void AsyncCopyReadHelper(AsyncCopyStreamResult streamState)
  124.         {
  125.             // There is no try-catch here because the calling method always has a try-catch.
  126.            
  127.             if (streamState.AsyncRead) {
  128.                 byte[] buffer = streamState.Buffer;
  129.                 streamState.Source.BeginRead(buffer, 0, buffer.Length, _asyncCopyStreamReadCallback, streamState);
  130.             }
  131.             else {
  132.                 byte[] buffer = streamState.Buffer;
  133.                 int bytesRead = streamState.Source.Read(buffer, 0, buffer.Length);
  134.                 if (bytesRead == 0) {
  135.                     streamState.SetComplete(null, null);
  136.                 }
  137.                 else if (bytesRead < 0) {
  138.                     throw new RemotingException(CoreChannel.GetResourceString("Remoting_Stream_UnknownReadError"));
  139.                 }
  140.                 else {
  141.                     AsyncCopyWriteHelper(streamState, bytesRead);
  142.                 }
  143.             }
  144.         }
  145.         // AsyncCopyReadHelper
  146.        
  147.         private static void AsyncCopyWriteHelper(AsyncCopyStreamResult streamState, int bytesRead)
  148.         {
  149.             // There is no try-catch here because the calling method always has a try-catch.
  150.            
  151.             if (streamState.AsyncWrite) {
  152.                 byte[] buffer = streamState.Buffer;
  153.                 streamState.Target.BeginWrite(buffer, 0, bytesRead, _asyncCopyStreamWriteCallback, streamState);
  154.             }
  155.             else {
  156.                 byte[] buffer = streamState.Buffer;
  157.                 streamState.Target.Write(buffer, 0, bytesRead);
  158.                
  159.                 AsyncCopyReadHelper(streamState);
  160.             }
  161.         }
  162.         // AsyncCopyWriteHelper
  163.        
  164.         private static void AsyncCopyStreamReadCallback(IAsyncResult iar)
  165.         {
  166.             AsyncCopyStreamResult state = (AsyncCopyStreamResult)iar.AsyncState;
  167.            
  168.             try {
  169.                 Stream source = state.Source;
  170.                
  171.                 int bytesRead = source.EndRead(iar);
  172.                 if (bytesRead == 0) {
  173.                     state.SetComplete(null, null);
  174.                 }
  175.                 else if (bytesRead < 0) {
  176.                     throw new RemotingException(CoreChannel.GetResourceString("Remoting_Stream_UnknownReadError"));
  177.                 }
  178.                 else {
  179.                     AsyncCopyWriteHelper(state, bytesRead);
  180.                 }
  181.             }
  182.             catch (Exception e) {
  183.                 state.SetComplete(null, e);
  184.             }
  185.             catch {
  186.                 state.SetComplete(null, new Exception(CoreChannel.GetResourceString("Remoting_nonClsCompliantException")));
  187.             }
  188.         }
  189.         // AsyncCopyStreamReadCallback
  190.        
  191.         private static void AsyncCopyStreamWriteCallback(IAsyncResult iar)
  192.         {
  193.             AsyncCopyStreamResult state = (AsyncCopyStreamResult)iar.AsyncState;
  194.            
  195.             try {
  196.                 state.Target.EndWrite(iar);
  197.                
  198.                 AsyncCopyReadHelper(state);
  199.             }
  200.             catch (Exception e) {
  201.                 state.SetComplete(null, e);
  202.             }
  203.             catch {
  204.                 state.SetComplete(null, new Exception(CoreChannel.GetResourceString("Remoting_nonClsCompliantException")));
  205.             }
  206.         }
  207.         // AsyncCopyStreamWriteCallback
  208.     }
  209.     // class StreamHelper
  210.    
  211.    
  212.     internal class AsyncCopyStreamResult : BasicAsyncResult
  213.     {
  214.         internal Stream Source;
  215.         internal Stream Target;
  216.         internal byte[] Buffer;
  217.         internal bool AsyncRead;
  218.         internal bool AsyncWrite;
  219.         internal bool CloseSource;
  220.         internal bool CloseTarget;
  221.        
  222.         internal AsyncCopyStreamResult(AsyncCallback callback, object state) : base(callback, state)
  223.         {
  224.         }
  225.        
  226.         internal override void CleanupOnComplete()
  227.         {
  228.             if (Buffer != null)
  229.                 CoreChannel.BufferPool.ReturnBuffer(Buffer);
  230.            
  231.             if (CloseSource)
  232.                 Source.Close();
  233.             if (CloseTarget)
  234.                 Target.Close();
  235.            
  236.         }
  237.         // CleanupOnComplete
  238.     }
  239.     // class AsyncCopyStreamResult
  240.    
  241. }
  242. // namespace System.Runtime.Remoting.Channels

Developer Fusion