protected override async Task Start() { while (true) { Sum += await m_channel.ReadAsync(); } }
/// <summary> /// The method that implements this process /// </summary> protected override async Task Start() { try { while (true) { // Grab the next request var req = await m_requests.ReadAsync(); LOG.DebugFormat("Found request with ID: {0}, channel: {3}, type: {1}, dtype: {2}", req.RequestID, req.RequestType, req.ChannelDataType, req.ChannelID); var nwc = await LocateChannelHandler(req.ChannelID); lock (m_lock) { LOG.DebugFormat("Registered pending request with ID: {0}, channel: {3}, type: {1}, dtype: {2}", req.RequestID, req.RequestType, req.ChannelDataType, req.ChannelID); m_pendingRequests[req.ChannelID].Add(req.RequestID, req); } try { await nwc.WriteAsync(req); LOG.DebugFormat("Passed req {0}, channel: {3}, with type {1}, dtype: {2}", req.RequestID, req.RequestType, req.ChannelDataType, req.ChannelID); } catch (Exception ex) { LOG.Error("Failed to send request", ex); // If the connection closed in some way // restart the connection and try again // otherwise: TrySetException(req.Task, ex); } } } catch (Exception ex) { try { Requests.Dispose(); } catch { } if (ex.IsRetiredException()) { if (m_pendingRequests.Values.Any(x => x.Count > 0)) { LOG.Fatal("Network client is retired, but there were pending messages in queue"); throw; } } else { LOG.Fatal("Crashed network client", ex); throw; } } }
/// <summary> /// Registers a desire to read from the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a /// negative span to wait forever.</param> /// <returns>The async.</returns> public Task <T> ReadAsync(TimeSpan timeout, ITwoPhaseOffer offer = null) { if (offer != null) { throw new InvalidOperationException("LatencyHidingReader does not support offers"); } while (m_readQueue.Count < m_buffersize) { m_readQueue.Enqueue(m_parent.ReadAsync(timeout, offer)); } return(m_readQueue.Dequeue()); }
/// <summary> /// The process that serializes data from a <see cref="CoCoL.Network.PendingNetworkRequest" /> and sends it into the channel. /// </summary> /// <returns>The awaitable task.</returns> /// <param name="client">The <see cref="System.Net.Sockets.TcpClient"/> to read data from.</param> /// <param name="stream">The stream to write data to.</param> /// <param name="channel">The channel to read requests from.</param> /// <param name="selfid">A string used to identify this process in logs</param> private static async Task WriterProcess(TcpClient client, Stream stream, IReadChannelEnd <PendingNetworkRequest> channel, string selfid) { try { var headbuffer = new byte[SMALL_MESSAGE_SIZE]; var json = new Newtonsoft.Json.JsonSerializer(); using (client) using (stream) using (channel) { while (true) { var prnq = await channel.ReadAsync(); var header = new RequestHeader() { ChannelID = prnq.ChannelID, ChannelDataType = prnq.ChannelDataType.AssemblyQualifiedName, RequestID = prnq.RequestID, SourceID = prnq.SourceID, RequestType = prnq.RequestType, Timeout = prnq.Timeout, PayloadClassName = prnq.Value == null ? null : prnq.Value.GetType().AssemblyQualifiedName, NoOffer = prnq.Offer == null }; ushort headlen; using (var ms = new MemoryStream(headbuffer, true)) { // Make space for the size fields ms.Write(headbuffer, 0, 8 + 2); using (var tw = new StreamWriter(ms)) using (var jw = new Newtonsoft.Json.JsonTextWriter(tw)) { json.Serialize(jw, header); jw.Flush(); await tw.FlushAsync(); headlen = (ushort)(ms.Position - 8 - 2); } } // We write it all into the array before writing to the stream if (headlen > SMALL_MESSAGE_SIZE - 8 - 2 - 8) { throw new Exception("Too larger header"); } // Make a memory stream for the payload using (var ms = new MemoryStream()) using (var tw = new StreamWriter(ms)) using (var jw = new Newtonsoft.Json.JsonTextWriter(tw)) { ulong payloadlen = 0; if (prnq.Value != null) { json.Serialize(jw, prnq.Value); jw.Flush(); await tw.FlushAsync(); payloadlen = (ulong)ms.Length; ms.Position = 0; } if (payloadlen > MAX_MESSAGE_SIZE) { throw new Exception("Too large message payload"); } ulong packlen = 8uL + 2uL + headlen + 8uL + payloadlen; Array.Copy(BitConverter.GetBytes(packlen), headbuffer, 8); Array.Copy(BitConverter.GetBytes(headlen), 0, headbuffer, 8, 2); Array.Copy(BitConverter.GetBytes(payloadlen), 0, headbuffer, 8 + 2 + headlen, 8); LOG.DebugFormat("{2}: Sending {0} - {1} request", prnq.RequestID, prnq.RequestType, selfid); await stream.WriteAsync(headbuffer, 0, headlen + 8 + 2 + 8); if (payloadlen != 0) { await ms.CopyToAsync(stream); } LOG.DebugFormat("{4}: Sent {0} - {1} request with {2} bytes to {3}", prnq.RequestID, prnq.RequestType, packlen, client.Client.RemoteEndPoint, selfid); await stream.FlushAsync(); } } } } catch (Exception ex) { if (!ex.IsRetiredException()) { LOG.Error("Crashed network client writer side", ex); throw; } else { LOG.Info("Stopped network client writer"); } } }