Ready
for receive? Receive is much more complicated than send. Similar to Send, Read
happens mostly within Connection. As an overview, Connection spread the work
for receive to TransportReceiveActor and ChannelReceiveActor.
TransportReceiveActor
deals with the data from transport, demultiplex it, and send to
ChannelReceiveActor.
ChannelReceiveActor
response to Channel ReadRequest by providing data provided by
TransportReceiveActor, after copying back to Channel, ChannelReceiveActor will
response to TransportReceiveActor the data is consumed. This is to free buffer
to allow space for further receives.
Here
is a more detailed view:
TransportReceiveActor
maintains a buffer – this buffer is used to store data from TCP transport.
Before this buffer is full, TransportReceiveActor keep requesting transport for
data. This buffer also serve the purpose of choking the sender. Because of we
are at low capacity to process the data, the buffer will remain not empty and
receive will not proceed, effectively stopping sender because its TCP sliding
window is used up.
After
data arrives in the buffer, TransportReceiveActor decodes them. Decoding is a
simple state machine – read the channel, read the size, read size bytes, and
repeats. However, since data is not available, the state machine must stop when
there is no data, and the state is saved until the next packet arrives. Here
the unread count is increased by the total size of the payload.
The
decoded payloads are then sent to ChannelReceiveActor, one complication arise
here if the ChannelReceiveActor is not there yet. This is a new channel! There
must be someone else trying to accept the Channel, the payload will be enqueued
in pending accept list. If there are any pending accept request, the accept
request is satisfied. Beyond that, the data will be sent to the
ChannelReceiveActor.
After
ChannelReceiveActor received the data, it enqueues it into a queue. The queue
is then checked to see if there are any pending read request, and if there is
one, try to fill the buffer and return. After filling the buffer, the used
count is send back to TransportReceiveActor to reduce the unused count. Once
the unused count goes back to 0, transport receive can start again.
No comments :
Post a Comment