提交 89a0e69c 编写于 作者: M Michal Privoznik

daemonStreamHandleRead: Wire up seekable stream

Whenever client is able to receive some data from stream
daemonStreamHandleRead is called. But now the behaviour of this
function needs to be changed a bit. Previously it just read data
from underlying file (of chardev or whatever) and sent those
through the stream to client. This model will not work any longer
because it does not differentiate whether underlying file is in
data or hole section. Therefore, at the beginning of this
function add code that checks this situation and acts
accordingly.
So after the this, when wanting to send some data we always check
whether we are not in a hole and if so, skip it an inform client
about its size.
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
上级 31024b3d
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "virlog.h" #include "virlog.h"
#include "virnetserverclient.h" #include "virnetserverclient.h"
#include "virerror.h" #include "virerror.h"
#include "libvirt_internal.h"
#define VIR_FROM_THIS VIR_FROM_STREAMS #define VIR_FROM_THIS VIR_FROM_STREAMS
...@@ -53,6 +54,7 @@ struct daemonClientStream { ...@@ -53,6 +54,7 @@ struct daemonClientStream {
bool tx; bool tx;
bool allowSkip; bool allowSkip;
size_t dataLen; /* How much data is there remaining until we see a hole */
daemonClientStreamPtr next; daemonClientStreamPtr next;
}; };
...@@ -796,6 +798,8 @@ daemonStreamHandleRead(virNetServerClientPtr client, ...@@ -796,6 +798,8 @@ daemonStreamHandleRead(virNetServerClientPtr client,
size_t bufferLen = VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX; size_t bufferLen = VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX;
int ret = -1; int ret = -1;
int rv; int rv;
int inData = 0;
long long length = 0;
VIR_DEBUG("client=%p, stream=%p tx=%d closed=%d", VIR_DEBUG("client=%p, stream=%p tx=%d closed=%d",
client, stream, stream->tx, stream->closed); client, stream, stream->tx, stream->closed);
...@@ -820,6 +824,58 @@ daemonStreamHandleRead(virNetServerClientPtr client, ...@@ -820,6 +824,58 @@ daemonStreamHandleRead(virNetServerClientPtr client,
if (!(msg = virNetMessageNew(false))) if (!(msg = virNetMessageNew(false)))
goto cleanup; goto cleanup;
if (stream->allowSkip && stream->dataLen == 0) {
/* Handle skip. We want to send some data to the client. But we might
* be in a hole. Seek to next data. But if we are in data already, just
* carry on. */
rv = virStreamInData(stream->st, &inData, &length);
VIR_DEBUG("rv=%d inData=%d length=%lld", rv, inData, length);
if (rv < 0) {
if (virNetServerProgramSendStreamError(remoteProgram,
client,
msg,
&rerr,
stream->procedure,
stream->serial) < 0)
goto cleanup;
msg = NULL;
/* We're done with this call */
goto done;
} else {
if (!inData && length) {
stream->tx = false;
msg->cb = daemonStreamMessageFinished;
msg->opaque = stream;
stream->refs++;
if (virNetServerProgramSendStreamHole(remoteProgram,
client,
msg,
stream->procedure,
stream->serial,
length,
0) < 0)
goto cleanup;
msg = NULL;
/* We have successfully sent stream skip to the other side.
* To keep streams in sync seek locally too. */
virStreamSendHole(stream->st, length, 0);
/* We're done with this call */
goto done;
}
}
stream->dataLen = length;
}
if (stream->allowSkip &&
bufferLen > stream->dataLen)
bufferLen = stream->dataLen;
rv = virStreamRecv(stream->st, buffer, bufferLen); rv = virStreamRecv(stream->st, buffer, bufferLen);
if (rv == -2) { if (rv == -2) {
/* Should never get this, since we're only called when we know /* Should never get this, since we're only called when we know
...@@ -834,6 +890,9 @@ daemonStreamHandleRead(virNetServerClientPtr client, ...@@ -834,6 +890,9 @@ daemonStreamHandleRead(virNetServerClientPtr client,
goto cleanup; goto cleanup;
msg = NULL; msg = NULL;
} else { } else {
if (stream->allowSkip)
stream->dataLen -= rv;
stream->tx = false; stream->tx = false;
if (rv == 0) if (rv == 0)
stream->recvEOF = true; stream->recvEOF = true;
...@@ -851,6 +910,7 @@ daemonStreamHandleRead(virNetServerClientPtr client, ...@@ -851,6 +910,7 @@ daemonStreamHandleRead(virNetServerClientPtr client,
msg = NULL; msg = NULL;
} }
done:
ret = 0; ret = 0;
cleanup: cleanup:
VIR_FREE(buffer); VIR_FREE(buffer);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册