public IAsyncResult BeginComputeHash(Stream s, AsyncCallback callback, object state) { var h = SHA1.Create(); var buffer = new byte[4 * 1024 * 1024]; var result = new GenericAsyncResult <byte[]>(callback, state, synchCompletion: false); AsyncCallback cb = null; cb = ar => { Console.Write('.'); try { var readBytes = s.EndRead(ar); if (readBytes != 0) { h.TransformBlock(buffer, 0, readBytes, buffer, 0); s.BeginRead(buffer, 0, buffer.Length, cb, null); } else { h.TransformFinalBlock(buffer, 0, 0); result.OnComplete(h.Hash, null); h.Dispose(); } } catch (Exception e) { result.OnComplete(null, e); h.Dispose(); return; } }; s.BeginRead(buffer, 0, buffer.Length, cb, null); return(result); }
/// <summary> /// Handles UNREGISTER messages. /// </summary> private static void ProcessUnregisterMessage(string unregister, byte [] buffer, Stream input, Stream output, Logger log, GenericAsyncResult <object> ar) { // Read message payload, terminated by an empty line. // Each payload line has the following format // <filename>:<ipAddress>:<portNumber> log.LogMessage(string.Format("::: UNREGISTER START IN THREAD {0}", Thread.CurrentThread.ManagedThreadId)); foreach (String line in unregister.Split('\n')) { string [] triple = line.Split(':'); if (triple.Length != 3) { log.LogMessage("Handler - Invalid UNREGISTER message:" + line); ar.OnComplete(null, null); return; } IPAddress ipAddress = IPAddress.Parse(triple [1]); ushort port; if (!ushort.TryParse(triple [2], out port)) { log.LogMessage("Handler - Invalid UNREGISTER message:" + line); ar.OnComplete(null, null); return; } Store.Instance.Unregister(triple [0], new IPEndPoint(ipAddress, port)); } ar.OnComplete(null, null); log.LogMessage(string.Format("::: UNREGISTER END IN THREAD {0}", Thread.CurrentThread.ManagedThreadId)); }
// begin take activating a timeout public IAsyncResult BeginTake(int timeout, CancellationToken ctk, AsyncCallback ucb, object ustate) { GenericAsyncResult <T> gar = new GenericAsyncResult <T>(ucb, ustate, false); filledSlots.BeginWaitEx(timeout, ctk, (ar) => { try { if (!filledSlots.EndWaitEx(ar)) { // complete request due to timeout gar.OnComplete(null, null); return; } // complete request with success T item; lock (room) { item = room[takeIdx++ % queueSize]; } freeSlots.Release(); gar.OnComplete(item, null); } catch (Exception ex) { gar.OnComplete(null, ex); } }, null); return(gar); }
//--- // asynchronous APM interface //--- // begin put activating a timeout public IAsyncResult BeginPut(T item, int timeout, CancellationToken ctk, AsyncCallback ucb, object ustate) { GenericAsyncResult <bool> gar = new GenericAsyncResult <bool>(ucb, ustate, false); freeSlots.BeginWaitEx(timeout, ctk, (ar) => { try { if (!freeSlots.EndWaitEx(ar)) { // complete put request with timeout gar.OnComplete(false, null); return; } // wait succeeded lock (room) { room[putIdx++ % queueSize] = item; } filledSlots.Release(); // complete put request with success gar.OnComplete(true, null); } catch (Exception ex) { // complete put request with exception gar.OnComplete(false, ex); } }, null); return(gar); }
// // File copy using APM asynchronous read and synchronous write operations. // public static IAsyncResult BeginCopyAsync(Stream src, Stream dst, AsyncCallback cb, object state) { GenericAsyncResult <long> gar = new GenericAsyncResult <long>(cb, state, false); byte[] rdBuffer = new byte[BUFFER_SIZE], wrBuffer = new byte[BUFFER_SIZE]; long fileSize = 0; AsyncCallback onReadCompleted = null; onReadCompleted = delegate(IAsyncResult ar) { int bytesRead = 0; try { bytesRead = src.EndRead(ar); } catch (IOException ioex) { src.Close(); gar.OnComplete(0, ioex); return; } if (bytesRead > 0) { // // Switch the buffers. // // The lock ensures that we can't process the completion of the // new read (writing the underlying buffer buffer) before write // the current read buffer. // byte[] tmp = rdBuffer; rdBuffer = wrBuffer; wrBuffer = tmp; lock (dst) { src.BeginRead(rdBuffer, 0, rdBuffer.Length, onReadCompleted, null); dst.Write(wrBuffer, 0, bytesRead); fileSize += bytesRead; } } else { // // We reach the EOF of the source stream. // We must ensure that the write of the last block is done, // before close the destination stream and complete the // underlying task. // src.Close(); lock (dst) { gar.OnComplete(fileSize, null); } dst.Close(); return; } }; // // Start the copy process starting the first asynchronous read. // src.BeginRead(rdBuffer, 0, rdBuffer.Length, onReadCompleted, null); return(gar); }
/// <summary> /// Handles LIST_FILES messages. /// </summary> private static void ProcessListFilesMessage(string commandBuffer, byte [] buffer, Stream input, Stream output, Logger log, GenericAsyncResult <object> ar) { // Request message does not have a payload. // Read end message mark (empty line) log.LogMessage(string.Format("::: LIST_FILES START IN THREAD {0}", Thread.CurrentThread.ManagedThreadId)); string [] trackedFiles = Store.Instance.GetTrackedFiles(); List <String> values = new List <string>(trackedFiles); string aggregatedValues = ""; if (trackedFiles.Length > 0) { aggregatedValues = values.Aggregate((a, b) => a + "\n" + b); } aggregatedValues += EMPTY_LINE; byte [] message = System.Text.Encoding.ASCII.GetBytes(aggregatedValues); // Send response message. // The message is composed of multiple lines and is terminated by an empty one. // Each line contains a name of a tracked file. output.BeginWrite(message, 0, message.Length, (res) => { output.EndWrite(res); // End response and flush it. output.Flush(); ar.OnComplete(null, null); log.LogMessage(string.Format("::: LIST_FILES END IN THREAD {0}", Thread.CurrentThread.ManagedThreadId)); }, null); }
private static void ProcessRun(String commandBuffer, byte [] buffer, Stream input, Stream output, Logger log, GenericAsyncResult <Object> asyncResult) { int commandDataLength = commandBuffer.IndexOf(EMPTY_LINE); int commandHeaderLength; String message = commandBuffer.Substring(0, commandDataLength); commandHeaderLength = message.IndexOf('\n'); if (commandHeaderLength < 0) { commandHeaderLength = message.Length; } string command = message.Substring(0, commandHeaderLength).Trim(); message = message.Substring(commandHeaderLength).TrimStart(); commandBuffer = commandBuffer.Substring(commandDataLength + EMPTY_LINE.Length); log.LogMessage("Handler - " + command); if (!MESSAGE_HANDLERS.ContainsKey(command)) { log.LogMessage("Handler - Unknown message type. Servicing ending."); asyncResult.OnComplete(null, null); return; } MESSAGE_HANDLERS [command](message, buffer, input, output, log, asyncResult); }
private static AsyncCallback GenerateBeginReadCallback(String commandBuffer, byte [] buffer, Stream input, Stream output, Logger log, GenericAsyncResult <Object> asyncResult, string key, int count) { return((result) => { try { int bytesRead = input.EndRead(result); if (result.CompletedSynchronously) { count++; } else { count = 0; } commandBuffer += System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead); if (commandBuffer.Contains(EMPTY_LINE)) { MESSAGE_HANDLERS [key](commandBuffer, buffer, input, output, log, asyncResult); } else if (count < RECURSION_LIMIT) { input.BeginRead(buffer, 0, buffer.Length, GenerateBeginReadCallback(commandBuffer, buffer, input, output, log, asyncResult, key, count), null); } } catch (IOException e) { asyncResult.OnComplete(null, e); log.LogMessage(String.Format("Handler - Connection closed by client {0}", e)); } }); }
/// <summary> /// Handles LIST_LOCATIONS messages. /// </summary> private static void ProcessListLocationsMessage(string line, byte [] buffer, Stream input, Stream output, Logger log, GenericAsyncResult <object> ar) { log.LogMessage(string.Format("::: LIST_LOCATIONS START IN THREAD {0}", Thread.CurrentThread.ManagedThreadId)); IPEndPoint [] fileLocations = Store.Instance.GetFileLocations(line); List <IPEndPoint> values = new List <IPEndPoint>(fileLocations); string aggregatedValues = ""; if (fileLocations.Length > 0) { aggregatedValues = values.Select((endpoint) => string.Format("{0}:{1}\n", endpoint.Address, endpoint.Port)) .Aggregate((a, b) => a + b); } aggregatedValues += EMPTY_LINE; byte [] message = System.Text.Encoding.ASCII.GetBytes(aggregatedValues); // Send response message. // The message is composed of multiple lines and is terminated by an empty one. // Each line has the following format // <ipAddress>:<portNumber> output.BeginWrite(message, 0, message.Length, (res) => { output.EndWrite(res); // End response and flush it. output.Flush(); ar.OnComplete(null, null); log.LogMessage(string.Format("::: LIST_LOCATIONS END IN THREAD {0}", Thread.CurrentThread.ManagedThreadId)); }, null); }
// // Returns a completed instance of GenericAsyncResult<R> with the specified result. // public static IAsyncResult FromResult(AsyncCallback ucallback, object ustate, R result, Exception error, bool synchCompletion) { GenericAsyncResult <R> gar = new GenericAsyncResult <R>(ucallback, ustate, synchCompletion); gar.OnComplete(result, error); return(gar); }
// // File copy using APM performs asynchronous reads and asynchronous write operations. // public static IAsyncResult BeginCopyAsync2(Stream src, Stream dst, AsyncCallback cb, object state) { GenericAsyncResult <long> gar = new GenericAsyncResult <long>(cb, state, false); long fileSize = 0; int pendingWrites = 1; // Account for the last read that reads 0 bytes. AsyncCallback onReadCompleted = null, onWriteCompleted = null; onReadCompleted = delegate(IAsyncResult ar) { int bytesRead = 0; try { bytesRead = src.EndRead(ar); } catch (IOException ioex) { src.Close(); gar.OnComplete(0, ioex); return; } byte[] readBuf = (byte[])ar.AsyncState; if (bytesRead > 0) { // // Start an asynchronous write, and then the next asynchronous read. // lock (dst) { pendingWrites++; dst.BeginWrite(readBuf, 0, bytesRead, onWriteCompleted, bytesRead); } // // Allocate a new buffer and start a new asynchronous read. // byte[] nextBuf = new byte[BUFFER_SIZE]; src.BeginRead(nextBuf, 0, nextBuf.Length, onReadCompleted, nextBuf); } else { // End of source file. src.Close(); lock (dst) { if (--pendingWrites == 0) { // // Last read is a zero-length read no writes are in progress. // The copy is completed. // dst.Close(); gar.OnComplete(fileSize, null); } } } }; onWriteCompleted = delegate(IAsyncResult ar) { try { dst.EndWrite(ar); } catch (IOException ioex) { dst.Close(); gar.OnComplete(0, ioex); return; } lock (dst) { fileSize += (int)ar.AsyncState; if (--pendingWrites == 0) { dst.Close(); gar.OnComplete(fileSize, null); } } }; byte[] firstBuf = new byte[BUFFER_SIZE]; src.BeginRead(firstBuf, 0, firstBuf.Length, onReadCompleted, firstBuf); return(gar); }