mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-21 12:05:17 +00:00
client rpc: Separate call creation from running IO loop
This makes it possible to create and queue new calls while we are running IO loop. (cherry picked from commit c57103e567b0fa09f2995cdd5a25015c48f7e017)
This commit is contained in:
parent
e48596773f
commit
400a5a9290
@ -1630,6 +1630,60 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static virNetClientCallPtr
|
||||||
|
virNetClientCallNew(virNetMessagePtr msg,
|
||||||
|
bool expectReply,
|
||||||
|
bool nonBlock)
|
||||||
|
{
|
||||||
|
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"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expectReply && nonBlock) {
|
||||||
|
virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Attempt to send a non-blocking message with"
|
||||||
|
" a synchronous reply"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_ALLOC(call) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virCondInit(&call->cond) < 0) {
|
||||||
|
virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("cannot initialize condition variable"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg->donefds = 0;
|
||||||
|
if (msg->bufferLength)
|
||||||
|
call->mode = VIR_NET_CLIENT_MODE_WAIT_TX;
|
||||||
|
else
|
||||||
|
call->mode = VIR_NET_CLIENT_MODE_WAIT_RX;
|
||||||
|
call->msg = msg;
|
||||||
|
call->expectReply = expectReply;
|
||||||
|
call->nonBlock = nonBlock;
|
||||||
|
|
||||||
|
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
|
* 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.
|
* for nonBlock==true), 0 if the call was completed and -1 on error.
|
||||||
@ -1648,47 +1702,18 @@ static int virNetClientSendInternal(virNetClientPtr client,
|
|||||||
msg->header.prog, msg->header.vers, msg->header.proc,
|
msg->header.prog, msg->header.vers, msg->header.proc,
|
||||||
msg->header.type, msg->header.status, msg->header.serial);
|
msg->header.type, msg->header.status, msg->header.serial);
|
||||||
|
|
||||||
if (expectReply &&
|
if (!client->sock || client->wantClose) {
|
||||||
(msg->bufferLength != 0) &&
|
|
||||||
(msg->header.status == VIR_NET_CONTINUE)) {
|
|
||||||
virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("Attempt to send an asynchronous message with a synchronous reply"));
|
_("client socket is closed"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expectReply && nonBlock) {
|
if (!(call = virNetClientCallNew(msg, expectReply, nonBlock))) {
|
||||||
virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
||||||
_("Attempt to send a non-blocking message with a synchronous reply"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_ALLOC(call) < 0) {
|
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!client->sock || client->wantClose) {
|
|
||||||
virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
||||||
_("client socket is closed"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virCondInit(&call->cond) < 0) {
|
|
||||||
virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
||||||
_("cannot initialize condition variable"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg->donefds = 0;
|
|
||||||
if (msg->bufferLength)
|
|
||||||
call->mode = VIR_NET_CLIENT_MODE_WAIT_TX;
|
|
||||||
else
|
|
||||||
call->mode = VIR_NET_CLIENT_MODE_WAIT_RX;
|
|
||||||
call->msg = msg;
|
|
||||||
call->expectReply = expectReply;
|
|
||||||
call->nonBlock = nonBlock;
|
|
||||||
call->haveThread = true;
|
call->haveThread = true;
|
||||||
|
|
||||||
ret = virNetClientIO(client, call);
|
ret = virNetClientIO(client, call);
|
||||||
|
|
||||||
/* If queued, the call will be finished and freed later by another thread;
|
/* If queued, the call will be finished and freed later by another thread;
|
||||||
@ -1697,8 +1722,6 @@ static int virNetClientSendInternal(virNetClientPtr client,
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ignore_value(virCondDestroy(&call->cond));
|
ignore_value(virCondDestroy(&call->cond));
|
||||||
|
|
||||||
cleanup:
|
|
||||||
VIR_FREE(call);
|
VIR_FREE(call);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user