Subject: Re: readv() questions
From: [email-masked]
To: [email-masked]
Cc: [email-masked]
Date: Tue, 9 May 2006 22:11:35 -0700

On Tue, May 09, 2006 at 03:54:16PM +0100, Dave Korn wrote:
> > You cannot
> > even use the idiom of "well let me just get the rest of this here and I'll
> > make a request for the dropped data after."
> 
>   Yes you absolutely can.  Who said you can't?  You're just not trying.  It
> works fine.

Well 85% of it was honestly whining in retrospect.

> > If that's the cake to eat,
> > then I'll just rewrite my readv wrapper to deal with it I guess. Not like
> > that is trivial if data is disrupted mid-vector. :-|
> 
>   Yes, it so is trivial.  It's barely the tiniest bit more complex than
> dealing with restarting a call to read().
> 
>     cheers,
>       DaveK

Thanks for taking the time to go through the original mail Dave - I
appreciate it.

After refactoring (just kidding, I don't really subscrib to that word)^H^H
modifying my original n_recv_iov() code to deal with the edge-of-MSS
and other partial readv() occurences I'm not having a problem anymore -
unsurprisingly.

I actually just call my n_recv() (standard non-blocking linear read)
to read remaining bytes of a partially filled vector because I'd rather not
muck with the contents of the original iovec passed in. I just pass it to
n_iov_offset() with the bytes read as a value-result argument which returns
number of iovecs filled + offset within a partially filled iovec in the v-r
arg.

So far so good, but if anyone sees anything glaring might as well point it
out - although this is not really CW related at this point.

-cl

New stuff:

    400 size_t n_iov_offset(const struct iovec *v, const size_t c, size_t *os)
    401 {
    402         size_t          l, cv;
    403
    404         for (cv = 0; cv < c; cv++) {
    405                 if ((l = v[cv].iov_len) > *os) break;
    406                 *os -= l;
    407         }
    408
    409         return cv;
    410 }
    411
    412 size_t n_iov_total(const struct iovec *v, const size_t c)
    413 {
    414         size_t          cv, bt;
    415
    416         for (cv = bt = 0; cv < c; cv++)
    417                 bt += v[cv].iov_len;
    418
    419         return bt;
    420 }
    421
    422 size_t n_recv_iov(const int s, const struct iovec *v, size_t c, int tout)
    423 {
    424         size_t          cv, br, bre, brt = 0;
    425         int             res;
    426         struct timeval  to;
    427         fd_set          fds, fds_m;
    428
    429         FD_ZERO(&fds_m);
    430         FD_SET(s, &fds_m);
    431
    432         bre = n_iov_total(v, c);
    433
    434         while (brt < bre) {
    435                 fds = fds_m;
    436                 to.tv_sec = tout;
    437                 to.tv_usec = 0;
    438
    439                 if ((br = readv(s, v, c)) == (size_t)-1) {
    440                         switch (errno) {
    441                         case EWOULDBLOCK:
    442                         case EINTR:
    443                                 break;
    444                         default:
    445                                 perror("readv");
    446                                 return -1;
    447                         }
    448                 } else if (br) {
    449                         if ((brt += br) < bre) {
    450                                 /* short read, mid-vector offset returned in br */
    451                                 cv = n_iov_offset(v, c, &br);
    452                                 v += cv;
    453                                 c -= cv;
    454
    455                                 if (br == 0)
    456                                         continue;
    457
    458                                 /* call read if we're short mid-vector */
    459                                 br = n_recv(s, (char *)v->iov_base + br,
    460                                         v->iov_len - br, tout);
    461                                 if (br == (size_t)-1)
    462                                         return -1;
    463
    464                                 /* done with mid-vector fill, proceed with rest */
    465                                 brt += br;
    466                                 v++;
    467                                 c--;
    468                         }
    469                 } else {
    470                         break;
    471                 }
    472
    473                 if ((res = select(s + 1, &fds, NULL, NULL, &to)) == 0)
    474                         return -1;              /* timeout */
    475                 else if (res == -1) {
    476                         perror("select");       /* never happen */
    477                         return -1;
    478                 }
    479         }
    480
    481         return brt;
    482 }

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/