public void ProcessReceivedBuffer(int bytes) { offset += bytes; if (offset < CurrentLength) { return; // Nothing to do except start the next receive } #if TRACK_DETAILED_STATS ThreadTrackingStatistic tracker = null; if (StatisticsCollector.CollectThreadTimeTrackingStats) { int id = System.Threading.Thread.CurrentThread.ManagedThreadId; if (!trackers.TryGetValue(id, out tracker)) { tracker = new ThreadTrackingStatistic("ThreadPoolThread." + System.Threading.Thread.CurrentThread.ManagedThreadId); bool added = trackers.TryAdd(id, tracker); if (added) { tracker.OnStartExecution(); } } tracker.OnStartProcessing(); } #endif try { if (batchingMode) { switch (phase) { case ReceivePhase.MetaHeader: numberOfMessages = BitConverter.ToInt32(metaHeaderBuffer, 0); lengthBuffer = new byte[numberOfMessages * Message.LENGTH_HEADER_SIZE]; lengths = new List <ArraySegment <byte> >() { new ArraySegment <byte>(lengthBuffer) }; phase = ReceivePhase.Lengths; offset = 0; break; case ReceivePhase.Lengths: headerBodies = new List <ArraySegment <byte> >(); headerLengths = new int[numberOfMessages]; bodyLengths = new int[numberOfMessages]; for (int i = 0; i < numberOfMessages; i++) { headerLengths[i] = BitConverter.ToInt32(lengthBuffer, i * 8); bodyLengths[i] = BitConverter.ToInt32(lengthBuffer, i * 8 + 4); headerBodiesLength += (headerLengths[i] + bodyLengths[i]); // We need to set the boundary of ArraySegment<byte>s to the same as the header/body boundary headerBodies.AddRange(BufferPool.GlobalPool.GetMultiBuffer(headerLengths[i])); headerBodies.AddRange(BufferPool.GlobalPool.GetMultiBuffer(bodyLengths[i])); } phase = ReceivePhase.HeaderBodies; offset = 0; break; case ReceivePhase.HeaderBodies: int lengtshSoFar = 0; for (int i = 0; i < numberOfMessages; i++) { header = ByteArrayBuilder.BuildSegmentListWithLengthLimit(headerBodies, lengtshSoFar, headerLengths[i]); body = ByteArrayBuilder.BuildSegmentListWithLengthLimit(headerBodies, lengtshSoFar + headerLengths[i], bodyLengths[i]); lengtshSoFar += (headerLengths[i] + bodyLengths[i]); var msg = new Message(header, body); MessagingStatisticsGroup.OnMessageReceive(msg, headerLengths[i], bodyLengths[i]); if (IMA.Log.IsVerbose3) { IMA.Log.Verbose3("Received a complete message of {0} bytes from {1}", headerLengths[i] + bodyLengths[i], msg.SendingAddress); } if (headerLengths[i] + bodyLengths[i] > Message.LargeMessageSizeThreshold) { IMA.Log.Info(ErrorCode.Messaging_LargeMsg_Incoming, "Receiving large message Size={0} HeaderLength={1} BodyLength={2}. Msg={3}", headerLengths[i] + bodyLengths[i], headerLengths[i], bodyLengths[i], msg.ToString()); if (IMA.Log.IsVerbose3) { IMA.Log.Verbose3("Received large message {0}", msg.ToLongString()); } } IMA.HandleMessage(msg, Sock); } MessagingStatisticsGroup.OnMessageBatchReceive(IMA.SocketDirection, numberOfMessages, lengtshSoFar); Reset(); break; } } else { // We've completed a buffer. What we do depends on which phase we were in switch (phase) { case ReceivePhase.Lengths: // Pull out the header and body lengths headerLength = BitConverter.ToInt32(lengthBuffer, 0); bodyLength = BitConverter.ToInt32(lengthBuffer, 4); header = BufferPool.GlobalPool.GetMultiBuffer(headerLength); body = BufferPool.GlobalPool.GetMultiBuffer(bodyLength); phase = ReceivePhase.Header; offset = 0; break; case ReceivePhase.Header: phase = ReceivePhase.Body; offset = 0; break; case ReceivePhase.Body: var msg = new Message(header, body); MessagingStatisticsGroup.OnMessageReceive(msg, headerLength, bodyLength); if (IMA.Log.IsVerbose3) { IMA.Log.Verbose3("Received a complete message of {0} bytes from {1}", headerLength + bodyLength, msg.SendingAddress); } if (headerLength + bodyLength > Message.LargeMessageSizeThreshold) { IMA.Log.Info(ErrorCode.Messaging_LargeMsg_Incoming, "Receiving large message Size={0} HeaderLength={1} BodyLength={2}. Msg={3}", headerLength + bodyLength, headerLength, bodyLength, msg.ToString()); if (IMA.Log.IsVerbose3) { IMA.Log.Verbose3("Received large message {0}", msg.ToLongString()); } } IMA.HandleMessage(msg, Sock); Reset(); break; } } } catch (Exception exc) { try { // Log details of receive state machine IMA.Log.Error(ErrorCode.MessagingProcessReceiveBufferException, string.Format( "Exception trying to process {0} bytes from endpoint {1} at offset {2} in phase {3}" + " CurrentLength={4} HeaderLength={5} BodyLength={6}", bytes, RemoteEndPoint, offset, phase, CurrentLength, headerLength, bodyLength ), exc); } catch (Exception) { } Reset(); // Reset back to a hopefully good base state throw; } finally { #if TRACK_DETAILED_STATS if (StatisticsCollector.CollectThreadTimeTrackingStats) { tracker.IncrementNumberOfProcessed(); tracker.OnStopProcessing(); } #endif } }
private void RunBatch() { try { var metaHeader = new byte[Message.LENGTH_META_HEADER]; var metaHeaderSegments = new List <ArraySegment <byte> > { new ArraySegment <byte>(metaHeader) }; while (!Cts.IsCancellationRequested) { if (!FillBuffer(metaHeaderSegments, Message.LENGTH_META_HEADER)) { continue; } var numberOfMessages = BitConverter.ToInt32(metaHeader, 0); var lengths = new byte[Message.LENGTH_HEADER_SIZE * numberOfMessages]; var lengthSegments = new List <ArraySegment <byte> > { new ArraySegment <byte>(lengths) }; if (!FillBuffer(lengthSegments, Message.LENGTH_HEADER_SIZE * numberOfMessages)) { continue; } var headerLengths = new int[numberOfMessages]; var bodyLengths = new int[numberOfMessages]; var headerbodiesLength = 0; var headerbodies = new List <ArraySegment <byte> >(); for (int i = 0; i < numberOfMessages; i++) { headerLengths[i] = BitConverter.ToInt32(lengths, i * 8); bodyLengths[i] = BitConverter.ToInt32(lengths, i * 8 + 4); headerbodiesLength += (headerLengths[i] + bodyLengths[i]); // We need to set the boundary of ArraySegment<byte>s to the same as the header/body boundary headerbodies.AddRange(BufferPool.GlobalPool.GetMultiBuffer(headerLengths[i])); headerbodies.AddRange(BufferPool.GlobalPool.GetMultiBuffer(bodyLengths[i])); } if (!FillBuffer(headerbodies, headerbodiesLength)) { continue; } var lengthSoFar = 0; for (int i = 0; i < numberOfMessages; i++) { var header = ByteArrayBuilder.BuildSegmentListWithLengthLimit(headerbodies, lengthSoFar, headerLengths[i]); var body = ByteArrayBuilder.BuildSegmentListWithLengthLimit(headerbodies, lengthSoFar + headerLengths[i], bodyLengths[i]); lengthSoFar += (headerLengths[i] + bodyLengths[i]); var msg = new Message(header, body); MessagingStatisticsGroup.OnMessageReceive(msg, headerLengths[i], bodyLengths[i]); if (Log.IsVerbose3) { Log.Verbose3("Received a message from gateway {0}: {1}", gatewayConnection.Address, msg); } gatewayConnection.MsgCenter.QueueIncomingMessage(msg); } MessagingStatisticsGroup.OnMessageBatchReceive(SocketDirection.ClientToGateway, numberOfMessages, lengthSoFar); } } catch (Exception ex) { Log.Warn(ErrorCode.ProxyClientUnhandledExceptionWhileReceiving, String.Format("Unexpected/unhandled exception while receiving: {0}. Restarting gateway receiver for {1}.", ex, gatewayConnection.Address), ex); throw; } }