non-blocking rpc receive
we already drop the lock between sending and receiving the rpc packets. now making it so that receive doesn't block for too long (ie 100ms) before unlocking the socket. this is needed for the callback. original rpc is sent and it triggers a callback from the server. we fork another thread to handle it, ie it needs to send a deleg_return rpc. if original rpc gets control and blocks on trying to receive its reply, it'll timeout and original rpc will return an error. instead we need to not block for long and allow the deleg_return to go thru so that the server can reply successfully to the original rpc.
This commit is contained in:
parent
d7e438be5e
commit
741e8bf0bf
5 changed files with 77 additions and 62 deletions
|
|
@ -480,11 +480,10 @@ xdrrec_skiprecord(xdrs)
|
|||
enum xprt_stat xstat;
|
||||
|
||||
if (rstrm->nonblock) {
|
||||
if (__xdrrec_getrec(xdrs, &xstat, FALSE)) {
|
||||
rstrm->fbtbc = 0;
|
||||
if (__xdrrec_getrec(xdrs, &xstat, FALSE))
|
||||
return TRUE;
|
||||
}
|
||||
if (rstrm->in_finger == rstrm->in_boundry &&
|
||||
|
||||
if (rstrm->in_finger == rstrm->in_boundry &&
|
||||
xstat == XPRT_MOREREQS) {
|
||||
rstrm->fbtbc = 0;
|
||||
return TRUE;
|
||||
|
|
@ -592,6 +591,7 @@ __xdrrec_getrec(xdrs, statp, expectdata)
|
|||
*statp = XPRT_DIED;
|
||||
return FALSE;
|
||||
}
|
||||
rstrm->fbtbc = rstrm->in_header & (~LAST_FRAG);
|
||||
rstrm->in_reclen += fraglen;
|
||||
if (rstrm->in_reclen > rstrm->recvsize)
|
||||
realloc_stream(rstrm, rstrm->in_reclen);
|
||||
|
|
@ -601,35 +601,39 @@ __xdrrec_getrec(xdrs, statp, expectdata)
|
|||
}
|
||||
}
|
||||
|
||||
n = rstrm->readit(rstrm->tcp_handle,
|
||||
rstrm->in_base + rstrm->in_received,
|
||||
(rstrm->in_reclen - rstrm->in_received));
|
||||
do {
|
||||
n = rstrm->readit(rstrm->tcp_handle,
|
||||
rstrm->in_base + rstrm->in_received,
|
||||
(rstrm->in_reclen - rstrm->in_received));
|
||||
|
||||
if (n < 0) {
|
||||
*statp = XPRT_DIED;
|
||||
return FALSE;
|
||||
}
|
||||
/* this case is needed for non-block as socket returns TIMEDOUT and -1
|
||||
* -2 is an error case and covered by the next if() statement */
|
||||
if (n == -1) continue;
|
||||
|
||||
if (n == 0) {
|
||||
*statp = expectdata ? XPRT_DIED : XPRT_IDLE;
|
||||
return FALSE;
|
||||
}
|
||||
if (n < 0) {
|
||||
*statp = XPRT_DIED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rstrm->in_received += n;
|
||||
if (n == 0) {
|
||||
*statp = expectdata ? XPRT_DIED : XPRT_IDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (rstrm->in_received == rstrm->in_reclen) {
|
||||
rstrm->in_haveheader = FALSE;
|
||||
rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
|
||||
rstrm->in_hdrlen = 0;
|
||||
if (rstrm->last_frag) {
|
||||
rstrm->fbtbc = rstrm->in_reclen;
|
||||
rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen;
|
||||
rstrm->in_finger = rstrm->in_base;
|
||||
rstrm->in_reclen = rstrm->in_received = 0;
|
||||
*statp = XPRT_MOREREQS;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
rstrm->in_received += n;
|
||||
if (rstrm->in_received == rstrm->in_reclen) {
|
||||
rstrm->in_haveheader = FALSE;
|
||||
rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
|
||||
rstrm->in_hdrlen = 0;
|
||||
if (rstrm->last_frag) {
|
||||
rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen;
|
||||
rstrm->in_finger = rstrm->in_base;
|
||||
rstrm->in_reclen = rstrm->in_received = 0;
|
||||
*statp = XPRT_MOREREQS;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
|
||||
*statp = XPRT_MOREREQS;
|
||||
return FALSE;
|
||||
|
|
@ -649,6 +653,15 @@ __xdrrec_setnonblock(xdrs, maxrec)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t
|
||||
__xdrrec_setblock(xdrs)
|
||||
XDR *xdrs;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
|
||||
|
||||
rstrm->nonblock = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
/*
|
||||
* Internal useful routines
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue