Helper functions for processing data streams in libvirtd

Defines the extensions to the remote protocol for generic
data streams. Adds a bunch of helper code to the libvirtd
daemon for working with data streams.

* daemon/Makefile.am: Add stream.c/stream.h to build
* daemon/stream.c, qemud/stream.h: Generic helper functions for
  creating new streams, associating streams with clients, finding
  existing streams for a client and removing/deleting streams.
* src/remote/remote_protocol.x: Add a new 'REMOTE_STREAM' constant
  for the 'enum remote_message_type' for encoding stream data
  in wire messages. Add a new 'REMOTE_CONTINUE' constant to
  'enum remote_message_status' to indicate further data stream
  messsages are expected to follow.  Document how the
  remote_message_header is used to encode data streams
* src/remote/remote_protocol.h: Regenerate
* daemon/dispatch.c: Remove assumption that a error message
  sent to client is always type=REMOTE_REPLY. It may now
  also be type=REMOTE_STREAM. Add convenient method for
  sending outgoing stream data packets. Log and ignore
  non-filtered incoming stream packets. Add a method for
  serializing a stream error message
* daemon/dispatch.h:  Add API for serializing stream errors
  and sending stream data packets
* daemon/qemud.h: Add struct qemud_client_stream for tracking
  active data streams for clients. Tweak filter function
  operation so that it accepts a client object too.
* daemon/qemud.c: Refactor code for free'ing message objects
  which have been fully transmitted into separate method.
  Release all active streams when client shuts down. Change
  filter function to be responsible for queueing the message
This commit is contained in:
Daniel P. Berrange
2009-07-10 13:06:36 +01:00
parent 182eba1bc6
commit 11573f3ec1
9 changed files with 509 additions and 29 deletions

View File

@@ -61,6 +61,7 @@
#include "conf.h"
#include "event.h"
#include "memory.h"
#include "stream.h"
#ifdef HAVE_AVAHI
#include "mdns.h"
#endif
@@ -1723,10 +1724,15 @@ readmore:
/* Check if any filters match this message */
filter = client->filters;
while (filter) {
if ((filter->query)(msg, filter->opaque)) {
qemudClientMessageQueuePush(&filter->dx, msg);
int ret;
ret = (filter->query)(client, msg, filter->opaque);
if (ret == 1) {
msg = NULL;
break;
} else if (ret == -1) {
VIR_FREE(msg);
qemudDispatchClientFailure(client);
return;
}
filter = filter->next;
}
@@ -1888,6 +1894,29 @@ static ssize_t qemudClientWrite(struct qemud_client *client) {
}
void
qemudClientMessageRelease(struct qemud_client *client,
struct qemud_client_message *msg)
{
if (!msg->async)
client->nrequests--;
/* See if the recv queue is currently throttled */
if (!client->rx &&
client->nrequests < max_client_requests) {
/* Reset message record for next RX attempt */
memset(msg, 0, sizeof(*msg));
client->rx = msg;
/* Get ready to receive next message */
client->rx->bufferLength = REMOTE_MESSAGE_HEADER_XDR_LEN;
} else {
VIR_FREE(msg);
}
qemudUpdateClientEvent(client);
}
/*
* Process all queued client->tx messages until
* we would block on I/O
@@ -1911,26 +1940,10 @@ qemudDispatchClientWrite(struct qemud_client *client) {
/* Get finished reply from head of tx queue */
reply = qemudClientMessageQueueServe(&client->tx);
/* If its not an async message, then we have
* just completed an RPC request */
if (!reply->async)
client->nrequests--;
/* Move record to end of 'rx' ist */
if (!client->rx &&
client->nrequests < max_client_requests) {
/* Reset message record for next RX attempt */
client->rx = reply;
client->rx->bufferOffset = 0;
client->rx->bufferLength = REMOTE_MESSAGE_HEADER_XDR_LEN;
} else {
VIR_FREE(reply);
}
qemudClientMessageRelease(client, reply);
if (client->closing)
qemudDispatchClientFailure(client);
else
qemudUpdateClientEvent(client);
}
}
}
@@ -2142,6 +2155,9 @@ static void qemudFreeClient(struct qemud_client *client) {
VIR_FREE(msg);
}
while (client->streams)
remoteRemoveClientStream(client, client->streams);
if (client->conn)
virConnectClose(client->conn);
virMutexDestroy(&client->lock);