On 28 Feb 2001, Martin Pool <[EMAIL PROTECTED]> wrote:

> > What I don't see is how we could recode this to avoid the zero window
> > without losing a lot of the pipelining advantage we have now. Going to
> > a more traditional request/response model in rsync would certainly
> > make TCP like us but would incur a huge penalty in latency.
> > 
> > As we are currently working on the design of rsync 3.0 it would be
> > good to get suggestions now on brilliant ways of solving this
> > problem. (please don't suggest opening a second control socket!)

Here's my current idea: it may be naïve about the TCP bugs, but I hope
it will be more reliable and still keep both directions on the network
maximally full.

I don't think we really need multiplexed streams: all error messages
relate back to a particular operation which has failed, although at
the moment they're not construed that way in the code.

So, I'd like to change to a request-response protocol like POP3,
HTTP/1.1 or SMTP, where the client sends commands and gets response
codes which contain a status, possibly body data, and possibly an
error message.  Perhaps we can allow the body data to be sent in
several chunks so that responses that fail halfway through (e.g. file
truncated or IO error) can be truncated.   If there's an error on the
server, then it should result in an error response.  I'm imagining
a fairly concise encoding format, perhaps ASCII, with commands like

 * authentication conversations modelled on PAM

 * choose rsync module

 * mkdir

 * set permissions/acl

 * get rsync signature

 * apply patch

 * list directory

 * make link

 * turn on gzip

At first in rsync3, we can just do this in blocking mode, like most
HTTP or POP implementations where the client sends the command, then
does blocking reads to get the response.

I think we could then just have the client start pipelining requests,
by using select() on the socket and a work queue to keep track of
outstanding requests.  In some cases where there are dependencies
between requests, such as creating a directory and then the files
inside it, we'll have to compose the protocol so that all the requests
can issue before the first one completes.  Also, for example, we might
have to keep issuing requests for signatures until the first one
arrives back, and then start sending its delta.  The server of course
doesn't have to be nonblocking, but can just handle requests as they
arrive.

So, I think this will keep the send and receive sides full as much of
the time as possible, while still allowing TCP to keep the two sides
in loose synchronization.

To me, this seems like a fairly conservative use of sockets, and so I
hope it won't encounter more of these kinds of bugs.  Is it going to
be a problem (with or without SSH) to have e.g. the ->server side of
the socket full while the server is trying to write, or vice versa, if
the client doesn't fork?

-- 
Martin Pool, Human Resource
Linuxcare. Inc.   +61 2 6262 8990
[EMAIL PROTECTED], http://linuxcare.com.au/
Linuxcare.  Putting Open Source to work.

Reply via email to