This makes it possible to create and queue new calls while we are running IO loop. --- src/rpc/virnetclient.c | 85 ++++++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 31 deletions(-) diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index e9898be..b956f6e 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -1642,53 +1642,38 @@ done: } -/* - * Returns 1 if the call was queued and will be completed later (only - * for nonBlock==true), 0 if the call was completed and -1 on error. - */ -static int virNetClientSendInternal(virNetClientPtr client, - virNetMessagePtr msg, - bool expectReply, - bool nonBlock) +static virNetClientCallPtr +virNetClientCallNew(virNetMessagePtr msg, + bool expectReply, + bool nonBlock) { - virNetClientCallPtr call; - int ret = -1; - - PROBE(RPC_CLIENT_MSG_TX_QUEUE, - "client=%p len=%zu prog=%u vers=%u proc=%u type=%u status=%u serial=%u", - client, msg->bufferLength, - msg->header.prog, msg->header.vers, msg->header.proc, - msg->header.type, msg->header.status, msg->header.serial); + virNetClientCallPtr call = NULL; if (expectReply && (msg->bufferLength != 0) && (msg->header.status == VIR_NET_CONTINUE)) { virNetError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Attempt to send an asynchronous message with a synchronous reply")); - return -1; + _("Attempt to send an asynchronous message with" + " a synchronous reply")); + goto error; } if (expectReply && nonBlock) { virNetError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Attempt to send a non-blocking message with a synchronous reply")); - return -1; + _("Attempt to send a non-blocking message with" + " a synchronous reply")); + goto error; } if (VIR_ALLOC(call) < 0) { virReportOOMError(); - return -1; - } - - if (!client->sock || client->wantClose) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", - _("client socket is closed")); - goto cleanup; + goto error; } if (virCondInit(&call->cond) < 0) { virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize condition variable")); - goto cleanup; + goto error; } msg->donefds = 0; @@ -1699,8 +1684,48 @@ static int virNetClientSendInternal(virNetClientPtr client, call->msg = msg; call->expectReply = expectReply; call->nonBlock = nonBlock; - call->haveThread = true; + VIR_DEBUG("New call %p: msg=%p, expectReply=%d, nonBlock=%d", + call, msg, expectReply, nonBlock); + + return call; + +error: + VIR_FREE(call); + return NULL; +} + + +/* + * Returns 1 if the call was queued and will be completed later (only + * for nonBlock==true), 0 if the call was completed and -1 on error. + */ +static int virNetClientSendInternal(virNetClientPtr client, + virNetMessagePtr msg, + bool expectReply, + bool nonBlock) +{ + virNetClientCallPtr call; + int ret = -1; + + PROBE(RPC_CLIENT_MSG_TX_QUEUE, + "client=%p len=%zu prog=%u vers=%u proc=%u type=%u status=%u serial=%u", + client, msg->bufferLength, + msg->header.prog, msg->header.vers, msg->header.proc, + msg->header.type, msg->header.status, msg->header.serial); + + if (!client->sock || client->wantClose) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", + _("client socket is closed")); + return -1; + } + + if (!(call = virNetClientCallNew(msg, expectReply, nonBlock))) { + virReportOOMError(); + return -1; + } + + call->haveThread = true; ret = virNetClientIO(client, call); /* If queued, the call will be finished and freed later by another thread; @@ -1709,8 +1734,6 @@ static int virNetClientSendInternal(virNetClientPtr client, return 1; ignore_value(virCondDestroy(&call->cond)); - -cleanup: VIR_FREE(call); return ret; } -- 1.7.10.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list