private void SendPageContents(MessageHeader hdr, BufferSegment segment) { if (segment.Length > 0) { if (debug) { Console.Error.WriteLine(" Sending page len {0}", segment.Length); } segment.Copy(); // Increment refcount for the destination process. this.bytesSent += segment.Length; this.messagesSent += 1; this.sender.Vertex.scheduler.statistics[(int)RuntimeStatistic.TxProgressMessages] += 1; this.sender.Vertex.scheduler.statistics[(int)RuntimeStatistic.TxProgressBytes] += segment.Length; this.networkChannel.SendBufferSegment(hdr, this.receiverProcessId, segment, true); } // Decrement refcount for the initial call to Consume(). segment.Dispose(); }
private void ReadCallback(UvStream stream, int receivedBytes, Exception error, object stateObject) { try { if (error != null) { throw error; } var state = (ReceiveState)stateObject; state.ReceivedBytes += receivedBytes; int remainingBytes; int nextPacketOffset = 0; do { remainingBytes = this.Protocol.TryRead( state.Buffer.Buffer, state.Buffer.Offset + nextPacketOffset, state.ReceivedBytes - nextPacketOffset, out var packet); if (packet != null) { // Synchronously handle packet before reading the next packet this.HandlePacket(packet); } if (remainingBytes == 0) { // Packet has been received completely, no other data currently available state.ReceivedBytes = 0; // Return to a buffer of recommended size if (state.Buffer.Length > this.Protocol.RecommendedBufferSize) { BufferSegment bufferToReturn = null; try { var oldBuffer = state.Buffer; state.Buffer = this.BufferPool.Acquire(this.Protocol.RecommendedBufferSize); bufferToReturn = oldBuffer; } finally { bufferToReturn?.Dispose(); } } } else if (remainingBytes < 0) { // There is complete another packet in our buffer, calculate it's offset nextPacketOffset = state.ReceivedBytes + remainingBytes; } else if (state.ReceivedBytes + remainingBytes > state.Buffer.Length) { // There's next packet's incomplete body left and it does not fit into the rest of the buffer. // We need to move it at the beginning of the buffer. var nextPacketSize = state.ReceivedBytes - nextPacketOffset + remainingBytes; var sourceBuffer = state.Buffer; BufferSegment bufferToReturn = null; try { if (nextPacketSize > state.Buffer.Length) { // The packet is bigger than our current buffer. We should try to acquire a bigger one from the buffer pool. state.Buffer = this.BufferPool.Acquire(nextPacketSize); bufferToReturn = sourceBuffer; } // Basically cutting the used part of received butes and storing the rest into the state's buffer state.ReceivedBytes -= nextPacketOffset; Buffer.BlockCopy( sourceBuffer.Buffer, sourceBuffer.Offset + nextPacketOffset, state.Buffer.Buffer, state.Buffer.Offset, state.ReceivedBytes); } finally { bufferToReturn?.Dispose(); } } }while (remainingBytes < 0); // Wait for another read callback } catch (UvErrorException exception) { if (exception.ErrorCode == UvErrorCode.EOF || exception.ErrorCode == UvErrorCode.ECONNRESET) { this.Close(); } else { this.Close(exception); } } catch (Exception exception) { this.Close(exception); } }