[libvirt] [PATCH libvirt-glib 0/5] Updates to streams APIs

This patch series expands the streams APIs to allow practical use of non-blocking bi-directional streams. It also formally documents the required coding style conventions for libvirt-glib before we get too much more code that is out of the ordinary.

From: "Daniel P. Berrange" <berrange@redhat.com> * HACKING: Add notes on coding style conventions --- HACKING | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 220 insertions(+), 1 deletions(-) diff --git a/HACKING b/HACKING index fe52c17..ea419e5 100644 --- a/HACKING +++ b/HACKING @@ -6,4 +6,223 @@ having to run make install, there are two environment variables that need to be set: export GI_TYPELIB_PATH=`pwd`/libvirt-glib:`pwd`/libvirt-gconfig:`pwd`/libvirt-gobject - export LD_LIBRARY_PATH=`pwd`/libvirt-glib/.libs:`pwd`/libvirt-gconfig/.libs:`pwd`/libvirt-gobject/.libs \ No newline at end of file + export LD_LIBRARY_PATH=`pwd`/libvirt-glib/.libs:`pwd`/libvirt-gconfig/.libs:`pwd`/libvirt-gobject/.libs + + +Coding style rules + + - Opening & closing braces for functions should be at start of line + + int foo(int bar) + { + ... + } + + Not + + int foo(int bar) { + ... + } + + + + - Opening brace for if/while/for loops should be at the end of line + + if (foo) { + bar; + wizz; + } + + Not + + if (foo) + { + bar; + wizz; + } + + Rationale: putting every if/while/for opening brace on a new line + expands function length too much + + + + - If a brace needs to be used for one clause in an if/else statement, + it should be used for both clauses, even if the other clauses are + only single statements. eg + + if (foo) { + bar; + wizz; + } else { + eek; + } + + Not + + if (foo) { + bar; + wizz; + } else + eek; + + + + - Function parameter attribute annotations should follow the parameter + name, eg + + int foo(int bar G_GNUC_UNUSED) + { + } + + Not + + int foo(G_GNUC_UNUSED int bar) + { + } + + Rationale: Adding / removing G_GNUC_UNUSED should not cause the + rest of the line to move around since that obscures diffs. + + + + - There should be no space between function names & open brackets eg + + int foo(int bar) + { + } + + Not + + int foo (int bar) + { + } + + + + - To keep lines under 80 characters (where practical), multiple parameters + should be on new lines. Do not attempt to line up parameters vertically + eg + + int foo(int bar, + unsigned long wizz) + { + } + + Not + + int foo(int bar, unsigned long wizz) + { + } + + Not + + int foo(int bar, + unsigned long wizz) + { + } + + Rationale: attempting vertical alignment causes bigger diffs when + modifying code if type names change causing whitespace re-alignment. + + + + - Function declarations in headers should not attempt to line up parameters + vertically + + eg + + int foo(int bar) + unsigned long eek(sometype wizz) + + Not + + + int foo(int bar) + unsigned long eek(sometype wizz) + + Rationale: when making changes to headers, existing vertical alignment + is often invalidated, requiring reindentation. This causes bigger + diffs which obscures code review. + + Exception: the 6 common decls for defining a new GObject + + #define GVIR_TYPE_INPUT_STREAM (_gvir_input_stream_get_type ()) + #define GVIR_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GVIR_TYPE_INPUT_STREAM, GVirInputStream)) + #define GVIR_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) + #define GVIR_IS_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), GVIR_TYPE_INPUT_STREAM)) + #define GVIR_IS_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GVIR_TYPE_INPUT_STREAM)) + #define GVIR_INPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) + + Rationale: These decls never change once added so vertical + alignment of these 6 lines only, will not cause diff whitespace + problems later. + + + - Usage of goto should follow one of the following patterns, and + label naming conventions. In particular any exit path jumps should + obay the 'cleanup' vs 'error' label naming + + * Interrupted system calls: + + retry: + err = func() + if (err < 0 && errno == EINTR) + goto retry; + + Alternate label name: retry_func: + + + * Shared cleanup paths: + + int foo(int bar) + { + int ret = -1; + + + if (something goes wrong) + goto cleanup; + + ret = 0; + cleanup: + ...shared cleanup code... + return ret; + } + + + * Separate error exit paths: + + int foo(int bar) + { + if (something goes wrong) + goto error; + + return 0; + + error: + ...error cleanup code... + return -1; + } + + + * Separate and shared error exit paths: + + int foo(int bar) + { + int ret = -1; + + if (something very bad goes wrong) + goto error; + + if (something goes wrong) + goto cleanup; + + ret = 0; + cleanup: + ...shared cleanup code... + return 0; + + error: + ...error cleanup code... + return -1; + } + -- 1.7.6.4

On Mon, Nov 28, 2011 at 01:13:44PM +0000, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
* HACKING: Add notes on coding style conventions --- HACKING | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 220 insertions(+), 1 deletions(-)
diff --git a/HACKING b/HACKING index fe52c17..ea419e5 100644 --- a/HACKING +++ b/HACKING @@ -6,4 +6,223 @@ having to run make install, there are two environment variables that need to be set:
export GI_TYPELIB_PATH=`pwd`/libvirt-glib:`pwd`/libvirt-gconfig:`pwd`/libvirt-gobject - export LD_LIBRARY_PATH=`pwd`/libvirt-glib/.libs:`pwd`/libvirt-gconfig/.libs:`pwd`/libvirt-gobject/.libs \ No newline at end of file + export LD_LIBRARY_PATH=`pwd`/libvirt-glib/.libs:`pwd`/libvirt-gconfig/.libs:`pwd`/libvirt-gobject/.libs + + +Coding style rules + + - Opening & closing braces for functions should be at start of line + + int foo(int bar) + { + ... + } + + Not + + int foo(int bar) { + ... + } + + + + - Opening brace for if/while/for loops should be at the end of line + + if (foo) { + bar; + wizz; + } + + Not + + if (foo) + { + bar; + wizz; + } + + Rationale: putting every if/while/for opening brace on a new line + expands function length too much + + + + - If a brace needs to be used for one clause in an if/else statement, + it should be used for both clauses, even if the other clauses are + only single statements. eg + + if (foo) { + bar; + wizz; + } else { + eek; + } + + Not + + if (foo) { + bar; + wizz; + } else + eek; + + + + - Function parameter attribute annotations should follow the parameter + name, eg + + int foo(int bar G_GNUC_UNUSED) + { + } + + Not + + int foo(G_GNUC_UNUSED int bar) + { + } + + Rationale: Adding / removing G_GNUC_UNUSED should not cause the + rest of the line to move around since that obscures diffs. + + + + - There should be no space between function names & open brackets eg + + int foo(int bar) + { + } + + Not + + int foo (int bar) + { + } + + + + - To keep lines under 80 characters (where practical), multiple parameters + should be on new lines. Do not attempt to line up parameters vertically + eg + + int foo(int bar, + unsigned long wizz) + { + } + + Not + + int foo(int bar, unsigned long wizz) + { + } + + Not + + int foo(int bar, + unsigned long wizz) + { + } + + Rationale: attempting vertical alignment causes bigger diffs when + modifying code if type names change causing whitespace re-alignment. + + + + - Function declarations in headers should not attempt to line up parameters + vertically + + eg + + int foo(int bar) + unsigned long eek(sometype wizz) + + Not + + + int foo(int bar) + unsigned long eek(sometype wizz) + + Rationale: when making changes to headers, existing vertical alignment + is often invalidated, requiring reindentation. This causes bigger + diffs which obscures code review. + + Exception: the 6 common decls for defining a new GObject + + #define GVIR_TYPE_INPUT_STREAM (_gvir_input_stream_get_type ()) + #define GVIR_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GVIR_TYPE_INPUT_STREAM, GVirInputStream)) + #define GVIR_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) + #define GVIR_IS_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), GVIR_TYPE_INPUT_STREAM)) + #define GVIR_IS_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GVIR_TYPE_INPUT_STREAM)) + #define GVIR_INPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) + + Rationale: These decls never change once added so vertical + alignment of these 6 lines only, will not cause diff whitespace + problems later. + + + - Usage of goto should follow one of the following patterns, and + label naming conventions. In particular any exit path jumps should + obay the 'cleanup' vs 'error' label naming + + * Interrupted system calls: + + retry: + err = func() + if (err < 0 && errno == EINTR) + goto retry; + + Alternate label name: retry_func: + + + * Shared cleanup paths: + + int foo(int bar) + { + int ret = -1; + + + if (something goes wrong) + goto cleanup; + + ret = 0; + cleanup: + ...shared cleanup code... + return ret; + } + + + * Separate error exit paths: + + int foo(int bar) + { + if (something goes wrong) + goto error; + + return 0; + + error: + ...error cleanup code... + return -1; + } + + + * Separate and shared error exit paths: + + int foo(int bar) + { + int ret = -1; + + if (something very bad goes wrong) + goto error; + + if (something goes wrong) + goto cleanup; + + ret = 0; + cleanup: + ...shared cleanup code... + return 0; + + error: + ...error cleanup code... + return -1; + } +
For what it's worth this adds a blank line to the end of the file. Christophe

On Mon, Nov 28, 2011 at 05:24:56PM +0100, Christophe Fergeau wrote:
On Mon, Nov 28, 2011 at 01:13:44PM +0000, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
* HACKING: Add notes on coding style conventions --- HACKING | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 220 insertions(+), 1 deletions(-)
diff --git a/HACKING b/HACKING index fe52c17..ea419e5 100644 --- a/HACKING +++ b/HACKING @@ -6,4 +6,223 @@ having to run make install, there are two environment variables that need to be set:
export GI_TYPELIB_PATH=`pwd`/libvirt-glib:`pwd`/libvirt-gconfig:`pwd`/libvirt-gobject - export LD_LIBRARY_PATH=`pwd`/libvirt-glib/.libs:`pwd`/libvirt-gconfig/.libs:`pwd`/libvirt-gobject/.libs \ No newline at end of file + export LD_LIBRARY_PATH=`pwd`/libvirt-glib/.libs:`pwd`/libvirt-gconfig/.libs:`pwd`/libvirt-gobject/.libs + + +Coding style rules + + - Opening & closing braces for functions should be at start of line + + int foo(int bar) + { + ... + } + + Not + + int foo(int bar) { + ... + } + + + + - Opening brace for if/while/for loops should be at the end of line + + if (foo) { + bar; + wizz; + } + + Not + + if (foo) + { + bar; + wizz; + } + + Rationale: putting every if/while/for opening brace on a new line + expands function length too much + + + + - If a brace needs to be used for one clause in an if/else statement, + it should be used for both clauses, even if the other clauses are + only single statements. eg + + if (foo) { + bar; + wizz; + } else { + eek; + } + + Not + + if (foo) { + bar; + wizz; + } else + eek; + + + + - Function parameter attribute annotations should follow the parameter + name, eg + + int foo(int bar G_GNUC_UNUSED) + { + } + + Not + + int foo(G_GNUC_UNUSED int bar) + { + } + + Rationale: Adding / removing G_GNUC_UNUSED should not cause the + rest of the line to move around since that obscures diffs. + + + + - There should be no space between function names & open brackets eg + + int foo(int bar) + { + } + + Not + + int foo (int bar) + { + } + + + + - To keep lines under 80 characters (where practical), multiple parameters + should be on new lines. Do not attempt to line up parameters vertically + eg + + int foo(int bar, + unsigned long wizz) + { + } + + Not + + int foo(int bar, unsigned long wizz) + { + } + + Not + + int foo(int bar, + unsigned long wizz) + { + } + + Rationale: attempting vertical alignment causes bigger diffs when + modifying code if type names change causing whitespace re-alignment. + + + + - Function declarations in headers should not attempt to line up parameters + vertically + + eg + + int foo(int bar) + unsigned long eek(sometype wizz) + + Not + + + int foo(int bar) + unsigned long eek(sometype wizz) + + Rationale: when making changes to headers, existing vertical alignment + is often invalidated, requiring reindentation. This causes bigger + diffs which obscures code review. + + Exception: the 6 common decls for defining a new GObject + + #define GVIR_TYPE_INPUT_STREAM (_gvir_input_stream_get_type ()) + #define GVIR_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GVIR_TYPE_INPUT_STREAM, GVirInputStream)) + #define GVIR_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) + #define GVIR_IS_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), GVIR_TYPE_INPUT_STREAM)) + #define GVIR_IS_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GVIR_TYPE_INPUT_STREAM)) + #define GVIR_INPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) + + Rationale: These decls never change once added so vertical + alignment of these 6 lines only, will not cause diff whitespace + problems later. + + + - Usage of goto should follow one of the following patterns, and + label naming conventions. In particular any exit path jumps should + obay the 'cleanup' vs 'error' label naming + + * Interrupted system calls: + + retry: + err = func() + if (err < 0 && errno == EINTR) + goto retry; + + Alternate label name: retry_func: + + + * Shared cleanup paths: + + int foo(int bar) + { + int ret = -1; + + + if (something goes wrong) + goto cleanup; + + ret = 0; + cleanup: + ...shared cleanup code... + return ret; + } + + + * Separate error exit paths: + + int foo(int bar) + { + if (something goes wrong) + goto error; + + return 0; + + error: + ...error cleanup code... + return -1; + } + + + * Separate and shared error exit paths: + + int foo(int bar) + { + int ret = -1; + + if (something very bad goes wrong) + goto error; + + if (something goes wrong) + goto cleanup; + + ret = 0; + cleanup: + ...shared cleanup code... + return 0; + + error: + ...error cleanup code... + return -1; + } +
For what it's worth this adds a blank line to the end of the file.
And ACK in any case Christophe

From: "Daniel P. Berrange" <berrange@redhat.com> The GIO GInputStream/GOutputStream async model for I/O does not work for working with non-blocking bi-directional streams. To allow that to be done more effectively, add an API to allow main loop watches to be registered against streams. Since the libvirt level virStreamEventAddCallback API only allows a single callback to be registered to a stream at any time, the GVirStream object needs to be multiplexing of multiple watches into a single libvirt level callback. Watches can be removed in the normal way with g_source_remove * libvirt-gobject/libvirt-gobject-stream.c, libvirt-gobject/libvirt-gobject-stream.h, libvirt-gobject/libvirt-gobject.sym: Add gvir_stream_add_watch --- libvirt-gobject/libvirt-gobject-stream.c | 180 ++++++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-stream.h | 17 +++ libvirt-gobject/libvirt-gobject.sym | 1 + 3 files changed, 198 insertions(+), 0 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-stream.c b/libvirt-gobject/libvirt-gobject-stream.c index 0d1c2d1..03b2c84 100644 --- a/libvirt-gobject/libvirt-gobject-stream.c +++ b/libvirt-gobject/libvirt-gobject-stream.c @@ -46,8 +46,20 @@ struct _GVirStreamPrivate virStreamPtr handle; GInputStream *input_stream; GOutputStream *output_stream; + + gboolean eventRegistered; + int eventLast; + GList *sources; }; +typedef struct { + GSource source; + GVirStreamIOCondition cond; + GVirStreamIOCondition newCond; + GVirStream *stream; +} GVirStreamSource; + + G_DEFINE_TYPE(GVirStream, gvir_stream, G_TYPE_IO_STREAM); @@ -186,6 +198,7 @@ static void gvir_stream_finalize(GObject *object) { GVirStream *self = GVIR_STREAM(object); GVirStreamPrivate *priv = self->priv; + GList *tmp; DEBUG("Finalize GVirStream=%p", self); @@ -199,6 +212,14 @@ static void gvir_stream_finalize(GObject *object) virStreamFree(priv->handle); } + tmp = priv->sources; + while (tmp) { + GVirStreamSource *source = tmp->data; + g_source_remove(g_source_get_id((GSource*)source)); + tmp = tmp->next; + } + g_list_free(priv->sources); + G_OBJECT_CLASS(gvir_stream_parent_class)->finalize(object); } @@ -448,3 +469,162 @@ gvir_stream_send_all(GVirStream *self, GVirStreamSourceFunc func, gpointer user_ return r; } + + +static void gvir_stream_handle_events(virStreamPtr st G_GNUC_UNUSED, + int events, + void *opaque) +{ + GVirStream *stream = GVIR_STREAM(opaque); + GVirStreamPrivate *priv = stream->priv; + GList *tmp = priv->sources; + + while (tmp) { + GVirStreamSource *source = tmp->data; + source->newCond = 0; + if (source->cond & GVIR_STREAM_IO_CONDITION_READABLE) { + if (events & VIR_STREAM_EVENT_READABLE) + source->newCond |= GVIR_STREAM_IO_CONDITION_READABLE; + if (events & VIR_STREAM_EVENT_HANGUP) + source->newCond |= GVIR_STREAM_IO_CONDITION_HANGUP; + if (events & VIR_STREAM_EVENT_ERROR) + source->newCond |= GVIR_STREAM_IO_CONDITION_ERROR; + } + if (source->cond & GVIR_STREAM_IO_CONDITION_WRITABLE) { + if (events & VIR_STREAM_EVENT_WRITABLE) + source->newCond |= GVIR_STREAM_IO_CONDITION_WRITABLE; + if (events & VIR_STREAM_EVENT_HANGUP) + source->newCond |= GVIR_STREAM_IO_CONDITION_HANGUP; + if (events & VIR_STREAM_EVENT_ERROR) + source->newCond |= GVIR_STREAM_IO_CONDITION_ERROR; + } + tmp = tmp->next; + } + +} + + +static void gvir_stream_update_events(GVirStream *stream) +{ + GVirStreamPrivate *priv = stream->priv; + int mask = 0; + GList *tmp = priv->sources; + + while (tmp) { + GVirStreamSource *source = tmp->data; + if (source->cond & GVIR_STREAM_IO_CONDITION_READABLE) + mask |= VIR_STREAM_EVENT_READABLE; + if (source->cond & GVIR_STREAM_IO_CONDITION_WRITABLE) + mask |= VIR_STREAM_EVENT_WRITABLE; + tmp = tmp->next; + } + + if (mask) { + if (priv->eventRegistered) { + virStreamEventUpdateCallback(priv->handle, mask); + } else { + virStreamEventAddCallback(priv->handle, mask, + gvir_stream_handle_events, + g_object_ref(stream), + g_object_unref); + priv->eventRegistered = TRUE; + } + } else { + if (priv->eventRegistered) { + virStreamEventRemoveCallback(priv->handle); + priv->eventRegistered = FALSE; + } + } +} + +static gboolean gvir_stream_source_prepare(GSource *source, + gint *timeout) +{ + GVirStreamSource *gsource = (GVirStreamSource*)source; + if (gsource->newCond) { + *timeout = 0; + return TRUE; + } + *timeout = -1; + return FALSE; +} + +static gboolean gvir_stream_source_check(GSource *source) +{ + GVirStreamSource *gsource = (GVirStreamSource*)source; + if (gsource->newCond) + return TRUE; + return FALSE; +} + +static gboolean gvir_stream_source_dispatch(GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + GVirStreamSource *gsource = (GVirStreamSource*)source; + GVirStreamIOFunc func = (GVirStreamIOFunc)callback; + gboolean ret; + ret = func(gsource->stream, gsource->newCond, user_data); + gsource->newCond = 0; + return ret; +} + +static void gvir_stream_source_finalize(GSource *source) +{ + GVirStreamSource *gsource = (GVirStreamSource*)source; + GVirStreamPrivate *priv = gsource->stream->priv; + GList *tmp, *prev = NULL; + + tmp = priv->sources; + while (tmp) { + if (tmp->data == source) { + if (prev) { + prev->next = tmp->next; + } else { + priv->sources = tmp->next; + } + tmp->next = NULL; + g_list_free(tmp); + break; + } + + prev = tmp; + tmp = tmp->next; + } + + gvir_stream_update_events(gsource->stream); +} + +GSourceFuncs gvir_stream_source_funcs = { + .prepare = gvir_stream_source_prepare, + .check = gvir_stream_source_check, + .dispatch = gvir_stream_source_dispatch, + .finalize = gvir_stream_source_finalize, +}; + +gint gvir_stream_add_watch(GVirStream *stream, + GVirStreamIOCondition cond, + GVirStreamIOFunc func, + gpointer opaque, + GDestroyNotify notify) +{ + GVirStreamPrivate *priv = stream->priv; + gint id; + GVirStreamSource *source = (GVirStreamSource*)g_source_new(&gvir_stream_source_funcs, + sizeof(GVirStreamSource)); + + source->stream = stream; + source->cond = cond; + + priv->sources = g_list_append(priv->sources, source); + + gvir_stream_update_events(source->stream); + + g_source_set_callback((GSource*)source, (GSourceFunc)func, opaque, notify); + g_source_attach((GSource*)source, g_main_context_default()); + + id = g_source_get_id((GSource*)source); + g_source_unref((GSource*)source); + + return id; +} diff --git a/libvirt-gobject/libvirt-gobject-stream.h b/libvirt-gobject/libvirt-gobject-stream.h index 5a1ee68..e0004b2 100644 --- a/libvirt-gobject/libvirt-gobject-stream.h +++ b/libvirt-gobject/libvirt-gobject-stream.h @@ -93,6 +93,23 @@ typedef gint (* GVirStreamSourceFunc)(GVirStream *stream, GType gvir_stream_get_type(void); GType gvir_stream_handle_get_type(void); +typedef enum { + GVIR_STREAM_IO_CONDITION_READABLE = (1 << 0), + GVIR_STREAM_IO_CONDITION_WRITABLE = (1 << 1), + GVIR_STREAM_IO_CONDITION_HANGUP = (1 << 2), + GVIR_STREAM_IO_CONDITION_ERROR = (1 << 3), +} GVirStreamIOCondition; + +typedef gboolean (*GVirStreamIOFunc)(GVirStream *stream, + GVirStreamIOCondition cond, + gpointer opaque); + +gint gvir_stream_add_watch(GVirStream *stream, + GVirStreamIOCondition cond, + GVirStreamIOFunc func, + gpointer opaque, + GDestroyNotify notify); + gssize gvir_stream_receive_all(GVirStream *stream, GVirStreamSinkFunc func, gpointer user_data, GError **error); gssize gvir_stream_receive(GVirStream *stream, gchar *buffer, gsize size, GCancellable *cancellable, GError **error); diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym index 78b3935..6261865 100644 --- a/libvirt-gobject/libvirt-gobject.sym +++ b/libvirt-gobject/libvirt-gobject.sym @@ -126,6 +126,7 @@ LIBVIRT_GOBJECT_0.0.1 { gvir_stream_get_type; gvir_stream_receive_all; gvir_stream_handle_get_type; + gvir_stream_add_watch; local: *; -- 1.7.6.4

On Mon, Nov 28, 2011 at 01:13:45PM +0000, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
The GIO GInputStream/GOutputStream async model for I/O does not work for working with non-blocking bi-directional streams. To allow that to be done more effectively, add an API to allow main loop watches to be registered against streams.
Since the libvirt level virStreamEventAddCallback API only allows a single callback to be registered to a stream at any time, the GVirStream object needs to be multiplexing of multiple watches into a single libvirt level callback.
Watches can be removed in the normal way with g_source_remove
* libvirt-gobject/libvirt-gobject-stream.c, libvirt-gobject/libvirt-gobject-stream.h, libvirt-gobject/libvirt-gobject.sym: Add gvir_stream_add_watch --- libvirt-gobject/libvirt-gobject-stream.c | 180 ++++++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-stream.h | 17 +++ libvirt-gobject/libvirt-gobject.sym | 1 + 3 files changed, 198 insertions(+), 0 deletions(-)
diff --git a/libvirt-gobject/libvirt-gobject-stream.c b/libvirt-gobject/libvirt-gobject-stream.c index 0d1c2d1..03b2c84 100644 --- a/libvirt-gobject/libvirt-gobject-stream.c +++ b/libvirt-gobject/libvirt-gobject-stream.c @@ -46,8 +46,20 @@ struct _GVirStreamPrivate virStreamPtr handle; GInputStream *input_stream; GOutputStream *output_stream; + + gboolean eventRegistered; + int eventLast; + GList *sources; };
+typedef struct { + GSource source; + GVirStreamIOCondition cond; + GVirStreamIOCondition newCond; + GVirStream *stream; +} GVirStreamSource; + + G_DEFINE_TYPE(GVirStream, gvir_stream, G_TYPE_IO_STREAM);
@@ -186,6 +198,7 @@ static void gvir_stream_finalize(GObject *object) { GVirStream *self = GVIR_STREAM(object); GVirStreamPrivate *priv = self->priv; + GList *tmp;
DEBUG("Finalize GVirStream=%p", self);
@@ -199,6 +212,14 @@ static void gvir_stream_finalize(GObject *object) virStreamFree(priv->handle); }
+ tmp = priv->sources; + while (tmp) { + GVirStreamSource *source = tmp->data; + g_source_remove(g_source_get_id((GSource*)source));
I think g_source_destroy can be used here
+ tmp = tmp->next; + } + g_list_free(priv->sources); + G_OBJECT_CLASS(gvir_stream_parent_class)->finalize(object); }
@@ -448,3 +469,162 @@ gvir_stream_send_all(GVirStream *self, GVirStreamSourceFunc func, gpointer user_
return r; } + + +static void gvir_stream_handle_events(virStreamPtr st G_GNUC_UNUSED, + int events, + void *opaque) +{ + GVirStream *stream = GVIR_STREAM(opaque); + GVirStreamPrivate *priv = stream->priv; + GList *tmp = priv->sources; + + while (tmp) { + GVirStreamSource *source = tmp->data; + source->newCond = 0; + if (source->cond & GVIR_STREAM_IO_CONDITION_READABLE) { + if (events & VIR_STREAM_EVENT_READABLE) + source->newCond |= GVIR_STREAM_IO_CONDITION_READABLE; + if (events & VIR_STREAM_EVENT_HANGUP) + source->newCond |= GVIR_STREAM_IO_CONDITION_HANGUP; + if (events & VIR_STREAM_EVENT_ERROR) + source->newCond |= GVIR_STREAM_IO_CONDITION_ERROR; + } + if (source->cond & GVIR_STREAM_IO_CONDITION_WRITABLE) { + if (events & VIR_STREAM_EVENT_WRITABLE) + source->newCond |= GVIR_STREAM_IO_CONDITION_WRITABLE; + if (events & VIR_STREAM_EVENT_HANGUP) + source->newCond |= GVIR_STREAM_IO_CONDITION_HANGUP; + if (events & VIR_STREAM_EVENT_ERROR) + source->newCond |= GVIR_STREAM_IO_CONDITION_ERROR; + } + tmp = tmp->next; + } + +} + + +static void gvir_stream_update_events(GVirStream *stream) +{ + GVirStreamPrivate *priv = stream->priv; + int mask = 0; + GList *tmp = priv->sources; + + while (tmp) { + GVirStreamSource *source = tmp->data; + if (source->cond & GVIR_STREAM_IO_CONDITION_READABLE) + mask |= VIR_STREAM_EVENT_READABLE; + if (source->cond & GVIR_STREAM_IO_CONDITION_WRITABLE) + mask |= VIR_STREAM_EVENT_WRITABLE; + tmp = tmp->next; + } + + if (mask) { + if (priv->eventRegistered) { + virStreamEventUpdateCallback(priv->handle, mask); + } else { + virStreamEventAddCallback(priv->handle, mask, + gvir_stream_handle_events, + g_object_ref(stream), + g_object_unref); + priv->eventRegistered = TRUE; + } + } else { + if (priv->eventRegistered) { + virStreamEventRemoveCallback(priv->handle); + priv->eventRegistered = FALSE; + } + } +} + +static gboolean gvir_stream_source_prepare(GSource *source, + gint *timeout) +{ + GVirStreamSource *gsource = (GVirStreamSource*)source; + if (gsource->newCond) { + *timeout = 0; + return TRUE; + } + *timeout = -1; + return FALSE; +} + +static gboolean gvir_stream_source_check(GSource *source) +{ + GVirStreamSource *gsource = (GVirStreamSource*)source; + if (gsource->newCond) + return TRUE; + return FALSE; +} + +static gboolean gvir_stream_source_dispatch(GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + GVirStreamSource *gsource = (GVirStreamSource*)source; + GVirStreamIOFunc func = (GVirStreamIOFunc)callback; + gboolean ret; + ret = func(gsource->stream, gsource->newCond, user_data); + gsource->newCond = 0; + return ret; +} + +static void gvir_stream_source_finalize(GSource *source) +{ + GVirStreamSource *gsource = (GVirStreamSource*)source; + GVirStreamPrivate *priv = gsource->stream->priv; + GList *tmp, *prev = NULL; + + tmp = priv->sources; + while (tmp) { + if (tmp->data == source) { + if (prev) { + prev->next = tmp->next; + } else { + priv->sources = tmp->next; + } + tmp->next = NULL; + g_list_free(tmp); + break; + } + + prev = tmp; + tmp = tmp->next; + }
isn't it doing the same as g_list_remove?
+ + gvir_stream_update_events(gsource->stream); +} + +GSourceFuncs gvir_stream_source_funcs = { + .prepare = gvir_stream_source_prepare, + .check = gvir_stream_source_check, + .dispatch = gvir_stream_source_dispatch, + .finalize = gvir_stream_source_finalize, +}; + +gint gvir_stream_add_watch(GVirStream *stream, + GVirStreamIOCondition cond, + GVirStreamIOFunc func, + gpointer opaque, + GDestroyNotify notify)
Dunno if it's worth having both gvir_stream_add_watch and gvir_stream_add_watch_full to be consistent with most glib source functions (g_timeout_add, g_idle_add, g_io_add_watch, ...). The notify argument would only be in the _full variant.
+{ + GVirStreamPrivate *priv = stream->priv; + gint id; + GVirStreamSource *source = (GVirStreamSource*)g_source_new(&gvir_stream_source_funcs, + sizeof(GVirStreamSource)); + + source->stream = stream; + source->cond = cond; + + priv->sources = g_list_append(priv->sources, source); + + gvir_stream_update_events(source->stream); + + g_source_set_callback((GSource*)source, (GSourceFunc)func, opaque, notify); + g_source_attach((GSource*)source, g_main_context_default()); + + id = g_source_get_id((GSource*)source);
g_source_attach returns this id which is of type guint.
+ g_source_unref((GSource*)source); + + return id; +} diff --git a/libvirt-gobject/libvirt-gobject-stream.h b/libvirt-gobject/libvirt-gobject-stream.h index 5a1ee68..e0004b2 100644 --- a/libvirt-gobject/libvirt-gobject-stream.h +++ b/libvirt-gobject/libvirt-gobject-stream.h @@ -93,6 +93,23 @@ typedef gint (* GVirStreamSourceFunc)(GVirStream *stream, GType gvir_stream_get_type(void); GType gvir_stream_handle_get_type(void);
+typedef enum { + GVIR_STREAM_IO_CONDITION_READABLE = (1 << 0), + GVIR_STREAM_IO_CONDITION_WRITABLE = (1 << 1), + GVIR_STREAM_IO_CONDITION_HANGUP = (1 << 2), + GVIR_STREAM_IO_CONDITION_ERROR = (1 << 3), +} GVirStreamIOCondition; + +typedef gboolean (*GVirStreamIOFunc)(GVirStream *stream, + GVirStreamIOCondition cond, + gpointer opaque); + +gint gvir_stream_add_watch(GVirStream *stream, + GVirStreamIOCondition cond, + GVirStreamIOFunc func, + gpointer opaque, + GDestroyNotify notify); + gssize gvir_stream_receive_all(GVirStream *stream, GVirStreamSinkFunc func, gpointer user_data, GError **error); gssize gvir_stream_receive(GVirStream *stream, gchar *buffer, gsize size, GCancellable *cancellable, GError **error);
diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym index 78b3935..6261865 100644 --- a/libvirt-gobject/libvirt-gobject.sym +++ b/libvirt-gobject/libvirt-gobject.sym @@ -126,6 +126,7 @@ LIBVIRT_GOBJECT_0.0.1 { gvir_stream_get_type; gvir_stream_receive_all; gvir_stream_handle_get_type; + gvir_stream_add_watch;
local: *; -- 1.7.6.4
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On Mon, Nov 28, 2011 at 06:52:43PM +0100, Christophe Fergeau wrote:
On Mon, Nov 28, 2011 at 01:13:45PM +0000, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
The GIO GInputStream/GOutputStream async model for I/O does not work for working with non-blocking bi-directional streams. To allow that to be done more effectively, add an API to allow main loop watches to be registered against streams.
Since the libvirt level virStreamEventAddCallback API only allows a single callback to be registered to a stream at any time, the GVirStream object needs to be multiplexing of multiple watches into a single libvirt level callback.
Watches can be removed in the normal way with g_source_remove
* libvirt-gobject/libvirt-gobject-stream.c, libvirt-gobject/libvirt-gobject-stream.h, libvirt-gobject/libvirt-gobject.sym: Add gvir_stream_add_watch --- libvirt-gobject/libvirt-gobject-stream.c | 180 ++++++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-stream.h | 17 +++ libvirt-gobject/libvirt-gobject.sym | 1 + 3 files changed, 198 insertions(+), 0 deletions(-)
@@ -199,6 +212,14 @@ static void gvir_stream_finalize(GObject *object) virStreamFree(priv->handle); }
+ tmp = priv->sources; + while (tmp) { + GVirStreamSource *source = tmp->data; + g_source_remove(g_source_get_id((GSource*)source));
I think g_source_destroy can be used here
Yes, I believe so.
+static void gvir_stream_source_finalize(GSource *source) +{ + GVirStreamSource *gsource = (GVirStreamSource*)source; + GVirStreamPrivate *priv = gsource->stream->priv; + GList *tmp, *prev = NULL; + + tmp = priv->sources; + while (tmp) { + if (tmp->data == source) { + if (prev) { + prev->next = tmp->next; + } else { + priv->sources = tmp->next; + } + tmp->next = NULL; + g_list_free(tmp); + break; + } + + prev = tmp; + tmp = tmp->next; + }
isn't it doing the same as g_list_remove?
Yes, indeed it is. I will simplify that.
+ + gvir_stream_update_events(gsource->stream); +} + +GSourceFuncs gvir_stream_source_funcs = { + .prepare = gvir_stream_source_prepare, + .check = gvir_stream_source_check, + .dispatch = gvir_stream_source_dispatch, + .finalize = gvir_stream_source_finalize, +}; + +gint gvir_stream_add_watch(GVirStream *stream, + GVirStreamIOCondition cond, + GVirStreamIOFunc func, + gpointer opaque, + GDestroyNotify notify)
Dunno if it's worth having both gvir_stream_add_watch and gvir_stream_add_watch_full to be consistent with most glib source functions (g_timeout_add, g_idle_add, g_io_add_watch, ...). The notify argument would only be in the _full variant.
Consistency is always nice, so I'll add a _full variant.
+{ + GVirStreamPrivate *priv = stream->priv; + gint id; + GVirStreamSource *source = (GVirStreamSource*)g_source_new(&gvir_stream_source_funcs, + sizeof(GVirStreamSource)); + + source->stream = stream; + source->cond = cond; + + priv->sources = g_list_append(priv->sources, source); + + gvir_stream_update_events(source->stream); + + g_source_set_callback((GSource*)source, (GSourceFunc)func, opaque, notify); + g_source_attach((GSource*)source, g_main_context_default()); + + id = g_source_get_id((GSource*)source);
g_source_attach returns this id which is of type guint.
Ahh, didn't notice that. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

From: "Daniel P. Berrange" <berrange@redhat.com> * libvirt-gobject/libvirt-gobject.sym: Export gvir_stream_receive, gvir_stream_send, gvir_stream_send_all --- libvirt-gobject/libvirt-gobject.sym | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym index 6261865..936525e 100644 --- a/libvirt-gobject/libvirt-gobject.sym +++ b/libvirt-gobject/libvirt-gobject.sym @@ -124,7 +124,10 @@ LIBVIRT_GOBJECT_0.0.1 { gvir_manager_find_connection_by_uri; gvir_stream_get_type; + gvir_stream_receive; gvir_stream_receive_all; + gvir_stream_send; + gvir_stream_send_all; gvir_stream_handle_get_type; gvir_stream_add_watch; -- 1.7.6.4

ACK On Mon, Nov 28, 2011 at 01:13:46PM +0000, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
* libvirt-gobject/libvirt-gobject.sym: Export gvir_stream_receive, gvir_stream_send, gvir_stream_send_all --- libvirt-gobject/libvirt-gobject.sym | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym index 6261865..936525e 100644 --- a/libvirt-gobject/libvirt-gobject.sym +++ b/libvirt-gobject/libvirt-gobject.sym @@ -124,7 +124,10 @@ LIBVIRT_GOBJECT_0.0.1 { gvir_manager_find_connection_by_uri;
gvir_stream_get_type; + gvir_stream_receive; gvir_stream_receive_all; + gvir_stream_send; + gvir_stream_send_all; gvir_stream_handle_get_type; gvir_stream_add_watch;
-- 1.7.6.4
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

From: "Daniel P. Berrange" <berrange@redhat.com> --- libvirt-gobject/libvirt-gobject-input-stream.c | 39 ++++++++++--------- libvirt-gobject/libvirt-gobject-input-stream.h | 27 +++++-------- libvirt-gobject/libvirt-gobject-output-stream.c | 16 ++++---- libvirt-gobject/libvirt-gobject-output-stream.h | 27 +++++-------- libvirt-gobject/libvirt-gobject-stream.c | 47 ++++++++++++++++------- libvirt-gobject/libvirt-gobject-stream.h | 24 +++++++++-- 6 files changed, 102 insertions(+), 78 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-input-stream.c b/libvirt-gobject/libvirt-gobject-input-stream.c index 39459c4..06ea716 100644 --- a/libvirt-gobject/libvirt-gobject-input-stream.c +++ b/libvirt-gobject/libvirt-gobject-input-stream.c @@ -54,9 +54,9 @@ struct _GVirInputStreamPrivate gsize count; }; -static void gvir_input_stream_get_property(GObject *object, - guint prop_id, - GValue *value, +static void gvir_input_stream_get_property(GObject *object, + guint prop_id, + GValue *value, GParamSpec *pspec) { GVirInputStream *stream = GVIR_INPUT_STREAM(object); @@ -71,10 +71,10 @@ static void gvir_input_stream_get_property(GObject *object, } } -static void gvir_input_stream_set_property(GObject *object, - guint prop_id, +static void gvir_input_stream_set_property(GObject *object, + guint prop_id, const GValue *value, - GParamSpec *pspec) + GParamSpec *pspec) { GVirInputStream *stream = GVIR_INPUT_STREAM(object); @@ -100,8 +100,9 @@ static void gvir_input_stream_finalize(GObject *object) } static void -gvir_input_stream_read_ready (G_GNUC_UNUSED virStreamPtr st, - int events, void *opaque) +gvir_input_stream_read_ready(virStreamPtr st G_GNUC_UNUSED, + int events, + void *opaque) { GVirInputStream *stream = GVIR_INPUT_STREAM(opaque); GVirInputStreamPrivate *priv = stream->priv; @@ -139,13 +140,13 @@ gvir_input_stream_read_ready (G_GNUC_UNUSED virStreamPtr st, return; } -static void gvir_input_stream_read_async(GInputStream *stream, - void *buffer, - gsize count, - G_GNUC_UNUSED int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +static void gvir_input_stream_read_async(GInputStream *stream, + void *buffer, + gsize count, + int io_priority G_GNUC_UNUSED, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { GVirInputStream *input_stream = GVIR_INPUT_STREAM(stream); virStreamPtr handle; @@ -180,9 +181,9 @@ end: } -static gssize gvir_input_stream_read_finish(GInputStream *stream, - GAsyncResult *result, - G_GNUC_UNUSED GError **error) +static gssize gvir_input_stream_read_finish(GInputStream *stream, + GAsyncResult *result, + GError **error G_GNUC_UNUSED) { GVirInputStream *input_stream = GVIR_INPUT_STREAM(stream); GSimpleAsyncResult *simple; @@ -233,7 +234,7 @@ static void gvir_input_stream_init(GVirInputStream *stream) stream->priv = G_TYPE_INSTANCE_GET_PRIVATE(stream, GVIR_TYPE_INPUT_STREAM, GVirInputStreamPrivate); } -GVirInputStream* _gvir_input_stream_new(GVirStream *stream) +GVirInputStream *_gvir_input_stream_new(GVirStream *stream) { return GVIR_INPUT_STREAM(g_object_new(GVIR_TYPE_INPUT_STREAM, "stream", stream, NULL)); } diff --git a/libvirt-gobject/libvirt-gobject-input-stream.h b/libvirt-gobject/libvirt-gobject-input-stream.h index e8002b9..3c9b4b8 100644 --- a/libvirt-gobject/libvirt-gobject-input-stream.h +++ b/libvirt-gobject/libvirt-gobject-input-stream.h @@ -33,21 +33,16 @@ G_BEGIN_DECLS -#define GVIR_TYPE_INPUT_STREAM (_gvir_input_stream_get_type ()) -#define GVIR_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ - GVIR_TYPE_INPUT_STREAM, GVirInputStream)) -#define GVIR_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \ - GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) -#define GVIR_IS_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ - GVIR_TYPE_INPUT_STREAM)) -#define GVIR_IS_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \ - GVIR_TYPE_INPUT_STREAM)) -#define GVIR_INPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ - GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) +#define GVIR_TYPE_INPUT_STREAM (_gvir_input_stream_get_type ()) +#define GVIR_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GVIR_TYPE_INPUT_STREAM, GVirInputStream)) +#define GVIR_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) +#define GVIR_IS_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), GVIR_TYPE_INPUT_STREAM)) +#define GVIR_IS_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GVIR_TYPE_INPUT_STREAM)) +#define GVIR_INPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) -typedef struct _GVirInputStreamPrivate GVirInputStreamPrivate; -typedef struct _GVirInputStreamClass GVirInputStreamClass; -typedef struct _GVirInputStream GVirInputStream; +typedef struct _GVirInputStreamPrivate GVirInputStreamPrivate; +typedef struct _GVirInputStreamClass GVirInputStreamClass; +typedef struct _GVirInputStream GVirInputStream; struct _GVirInputStreamClass { @@ -60,8 +55,8 @@ struct _GVirInputStream GVirInputStreamPrivate *priv; }; -GType _gvir_input_stream_get_type (void) G_GNUC_CONST; -GVirInputStream * _gvir_input_stream_new (GVirStream *stream); +GType _gvir_input_stream_get_type(void) G_GNUC_CONST; +GVirInputStream *_gvir_input_stream_new(GVirStream *stream); G_END_DECLS diff --git a/libvirt-gobject/libvirt-gobject-output-stream.c b/libvirt-gobject/libvirt-gobject-output-stream.c index 30ee519..74eddc5 100644 --- a/libvirt-gobject/libvirt-gobject-output-stream.c +++ b/libvirt-gobject/libvirt-gobject-output-stream.c @@ -54,9 +54,9 @@ struct _GVirOutputStreamPrivate gsize count; }; -static void gvir_output_stream_get_property(GObject *object, - guint prop_id, - GValue *value, +static void gvir_output_stream_get_property(GObject *object, + guint prop_id, + GValue *value, GParamSpec *pspec) { GVirOutputStream *stream = GVIR_OUTPUT_STREAM(object); @@ -71,10 +71,10 @@ static void gvir_output_stream_get_property(GObject *object, } } -static void gvir_output_stream_set_property(GObject *object, - guint prop_id, +static void gvir_output_stream_set_property(GObject *object, + guint prop_id, const GValue *value, - GParamSpec *pspec) + GParamSpec *pspec) { GVirOutputStream *stream = GVIR_OUTPUT_STREAM(object); @@ -181,8 +181,8 @@ end: } -static gssize gvir_output_stream_write_finish(GOutputStream *stream, - GAsyncResult *result, +static gssize gvir_output_stream_write_finish(GOutputStream *stream, + GAsyncResult *result, GError **error G_GNUC_UNUSED) { GVirOutputStream *output_stream = GVIR_OUTPUT_STREAM(stream); diff --git a/libvirt-gobject/libvirt-gobject-output-stream.h b/libvirt-gobject/libvirt-gobject-output-stream.h index 0ca0053..dd1d651 100644 --- a/libvirt-gobject/libvirt-gobject-output-stream.h +++ b/libvirt-gobject/libvirt-gobject-output-stream.h @@ -33,21 +33,16 @@ G_BEGIN_DECLS -#define GVIR_TYPE_OUTPUT_STREAM (_gvir_output_stream_get_type ()) -#define GVIR_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ - GVIR_TYPE_OUTPUT_STREAM, GVirOutputStream)) -#define GVIR_OUTPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \ - GVIR_TYPE_OUTPUT_STREAM, GVirOutputStreamClass)) -#define GVIR_IS_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ - GVIR_TYPE_OUTPUT_STREAM)) -#define GVIR_IS_OUTPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \ - GVIR_TYPE_OUTPUT_STREAM)) -#define GVIR_OUTPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ - GVIR_TYPE_OUTPUT_STREAM, GVirOutputStreamClass)) +#define GVIR_TYPE_OUTPUT_STREAM (_gvir_output_stream_get_type ()) +#define GVIR_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GVIR_TYPE_OUTPUT_STREAM, GVirOutputStream)) +#define GVIR_OUTPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GVIR_TYPE_OUTPUT_STREAM, GVirOutputStreamClass)) +#define GVIR_IS_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), GVIR_TYPE_OUTPUT_STREAM)) +#define GVIR_IS_OUTPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GVIR_TYPE_OUTPUT_STREAM)) +#define GVIR_OUTPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GVIR_TYPE_OUTPUT_STREAM, GVirOutputStreamClass)) -typedef struct _GVirOutputStreamPrivate GVirOutputStreamPrivate; -typedef struct _GVirOutputStreamClass GVirOutputStreamClass; -typedef struct _GVirOutputStream GVirOutputStream; +typedef struct _GVirOutputStreamPrivate GVirOutputStreamPrivate; +typedef struct _GVirOutputStreamClass GVirOutputStreamClass; +typedef struct _GVirOutputStream GVirOutputStream; struct _GVirOutputStreamClass { @@ -60,8 +55,8 @@ struct _GVirOutputStream GVirOutputStreamPrivate *priv; }; -GType _gvir_output_stream_get_type (void) G_GNUC_CONST; -GVirOutputStream * _gvir_output_stream_new (GVirStream *stream); +GType _gvir_output_stream_get_type(void) G_GNUC_CONST; +GVirOutputStream *_gvir_output_stream_new(GVirStream *stream); G_END_DECLS diff --git a/libvirt-gobject/libvirt-gobject-stream.c b/libvirt-gobject/libvirt-gobject-stream.c index 03b2c84..8cd3cef 100644 --- a/libvirt-gobject/libvirt-gobject-stream.c +++ b/libvirt-gobject/libvirt-gobject-stream.c @@ -102,7 +102,8 @@ static GOutputStream* gvir_stream_get_output_stream(GIOStream *io_stream) static gboolean gvir_stream_close(GIOStream *io_stream, - GCancellable *cancellable, G_GNUC_UNUSED GError **error) + GCancellable *cancellable, + G_GNUC_UNUSED GError **error) { GVirStream *self = GVIR_STREAM(io_stream); @@ -116,8 +117,10 @@ static gboolean gvir_stream_close(GIOStream *io_stream, } -static void gvir_stream_close_async(GIOStream *stream, G_GNUC_UNUSED int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, +static void gvir_stream_close_async(GIOStream *stream, + int io_priority G_GNUC_UNUSED, + GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *res; @@ -146,9 +149,9 @@ static void gvir_stream_close_async(GIOStream *stream, G_GNUC_UNUSED int io_prio static gboolean -gvir_stream_close_finish(G_GNUC_UNUSED GIOStream *stream, - G_GNUC_UNUSED GAsyncResult *result, - G_GNUC_UNUSED GError **error) +gvir_stream_close_finish(GIOStream *stream G_GNUC_UNUSED, + GAsyncResult *result G_GNUC_UNUSED, + GError **error G_GNUC_UNUSED) { return TRUE; } @@ -301,8 +304,11 @@ G_DEFINE_BOXED_TYPE(GVirStreamHandle, gvir_stream_handle, * Returns: Number of bytes read, or 0 if the end of stream reached, * or -1 on error. */ -gssize gvir_stream_receive(GVirStream *self, gchar *buffer, gsize size, - GCancellable *cancellable, GError **error) +gssize gvir_stream_receive(GVirStream *self, + gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error) { int got; @@ -332,7 +338,9 @@ struct stream_sink_helper { static int stream_sink(virStreamPtr st G_GNUC_UNUSED, - const char *bytes, size_t nbytes, void *opaque) + const char *bytes, + size_t nbytes, + void *opaque) { struct stream_sink_helper *helper = opaque; @@ -351,7 +359,10 @@ stream_sink(virStreamPtr st G_GNUC_UNUSED, * to virStreamRecv, for apps that do blocking-I/o. */ gssize -gvir_stream_receive_all(GVirStream *self, GVirStreamSinkFunc func, gpointer user_data, GError **err) +gvir_stream_receive_all(GVirStream *self, + GVirStreamSinkFunc func, + gpointer user_data, + GError **err) { struct stream_sink_helper helper = { .self = self, @@ -397,8 +408,11 @@ gvir_stream_receive_all(GVirStream *self, GVirStreamSinkFunc func, gpointer user * Returns: Number of bytes read, or 0 if the end of stream reached, * or -1 on error. */ -gssize gvir_stream_send(GVirStream *self, const gchar *buffer, gsize size, - GCancellable *cancellable, GError **error) +gssize gvir_stream_send(GVirStream *self, + const gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error) { int got; @@ -428,7 +442,9 @@ struct stream_source_helper { static int stream_source(virStreamPtr st G_GNUC_UNUSED, - char *bytes, size_t nbytes, void *opaque) + char *bytes, + size_t nbytes, + void *opaque) { struct stream_source_helper *helper = opaque; @@ -447,7 +463,10 @@ stream_source(virStreamPtr st G_GNUC_UNUSED, * to virStreamRecv, for apps that do blocking-I/o. */ gssize -gvir_stream_send_all(GVirStream *self, GVirStreamSourceFunc func, gpointer user_data, GError **err) +gvir_stream_send_all(GVirStream *self, + GVirStreamSourceFunc func, + gpointer user_data, + GError **err) { struct stream_source_helper helper = { .self = self, diff --git a/libvirt-gobject/libvirt-gobject-stream.h b/libvirt-gobject/libvirt-gobject-stream.h index e0004b2..2719ff3 100644 --- a/libvirt-gobject/libvirt-gobject-stream.h +++ b/libvirt-gobject/libvirt-gobject-stream.h @@ -110,11 +110,25 @@ gint gvir_stream_add_watch(GVirStream *stream, gpointer opaque, GDestroyNotify notify); -gssize gvir_stream_receive_all(GVirStream *stream, GVirStreamSinkFunc func, gpointer user_data, GError **error); -gssize gvir_stream_receive(GVirStream *stream, gchar *buffer, gsize size, GCancellable *cancellable, GError **error); - -gssize gvir_stream_send_all(GVirStream *stream, GVirStreamSourceFunc func, gpointer user_data, GError **error); -gssize gvir_stream_send(GVirStream *stream, const gchar *buffer, gsize size, GCancellable *cancellable, GError **error); +gssize gvir_stream_receive_all(GVirStream *stream, + GVirStreamSinkFunc func, + gpointer user_data, + GError **error); +gssize gvir_stream_receive(GVirStream *stream, + gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error); + +gssize gvir_stream_send_all(GVirStream *stream, + GVirStreamSourceFunc func, + gpointer user_data, + GError **error); +gssize gvir_stream_send(GVirStream *stream, + const gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error); G_END_DECLS -- 1.7.6.4

ACK On Mon, Nov 28, 2011 at 01:13:47PM +0000, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
--- libvirt-gobject/libvirt-gobject-input-stream.c | 39 ++++++++++--------- libvirt-gobject/libvirt-gobject-input-stream.h | 27 +++++-------- libvirt-gobject/libvirt-gobject-output-stream.c | 16 ++++---- libvirt-gobject/libvirt-gobject-output-stream.h | 27 +++++-------- libvirt-gobject/libvirt-gobject-stream.c | 47 ++++++++++++++++------- libvirt-gobject/libvirt-gobject-stream.h | 24 +++++++++-- 6 files changed, 102 insertions(+), 78 deletions(-)
diff --git a/libvirt-gobject/libvirt-gobject-input-stream.c b/libvirt-gobject/libvirt-gobject-input-stream.c index 39459c4..06ea716 100644 --- a/libvirt-gobject/libvirt-gobject-input-stream.c +++ b/libvirt-gobject/libvirt-gobject-input-stream.c @@ -54,9 +54,9 @@ struct _GVirInputStreamPrivate gsize count; };
-static void gvir_input_stream_get_property(GObject *object, - guint prop_id, - GValue *value, +static void gvir_input_stream_get_property(GObject *object, + guint prop_id, + GValue *value, GParamSpec *pspec) { GVirInputStream *stream = GVIR_INPUT_STREAM(object); @@ -71,10 +71,10 @@ static void gvir_input_stream_get_property(GObject *object, } }
-static void gvir_input_stream_set_property(GObject *object, - guint prop_id, +static void gvir_input_stream_set_property(GObject *object, + guint prop_id, const GValue *value, - GParamSpec *pspec) + GParamSpec *pspec) { GVirInputStream *stream = GVIR_INPUT_STREAM(object);
@@ -100,8 +100,9 @@ static void gvir_input_stream_finalize(GObject *object) }
static void -gvir_input_stream_read_ready (G_GNUC_UNUSED virStreamPtr st, - int events, void *opaque) +gvir_input_stream_read_ready(virStreamPtr st G_GNUC_UNUSED, + int events, + void *opaque) { GVirInputStream *stream = GVIR_INPUT_STREAM(opaque); GVirInputStreamPrivate *priv = stream->priv; @@ -139,13 +140,13 @@ gvir_input_stream_read_ready (G_GNUC_UNUSED virStreamPtr st, return; }
-static void gvir_input_stream_read_async(GInputStream *stream, - void *buffer, - gsize count, - G_GNUC_UNUSED int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +static void gvir_input_stream_read_async(GInputStream *stream, + void *buffer, + gsize count, + int io_priority G_GNUC_UNUSED, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { GVirInputStream *input_stream = GVIR_INPUT_STREAM(stream); virStreamPtr handle; @@ -180,9 +181,9 @@ end: }
-static gssize gvir_input_stream_read_finish(GInputStream *stream, - GAsyncResult *result, - G_GNUC_UNUSED GError **error) +static gssize gvir_input_stream_read_finish(GInputStream *stream, + GAsyncResult *result, + GError **error G_GNUC_UNUSED) { GVirInputStream *input_stream = GVIR_INPUT_STREAM(stream); GSimpleAsyncResult *simple; @@ -233,7 +234,7 @@ static void gvir_input_stream_init(GVirInputStream *stream) stream->priv = G_TYPE_INSTANCE_GET_PRIVATE(stream, GVIR_TYPE_INPUT_STREAM, GVirInputStreamPrivate); }
-GVirInputStream* _gvir_input_stream_new(GVirStream *stream) +GVirInputStream *_gvir_input_stream_new(GVirStream *stream) { return GVIR_INPUT_STREAM(g_object_new(GVIR_TYPE_INPUT_STREAM, "stream", stream, NULL)); } diff --git a/libvirt-gobject/libvirt-gobject-input-stream.h b/libvirt-gobject/libvirt-gobject-input-stream.h index e8002b9..3c9b4b8 100644 --- a/libvirt-gobject/libvirt-gobject-input-stream.h +++ b/libvirt-gobject/libvirt-gobject-input-stream.h @@ -33,21 +33,16 @@
G_BEGIN_DECLS
-#define GVIR_TYPE_INPUT_STREAM (_gvir_input_stream_get_type ()) -#define GVIR_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ - GVIR_TYPE_INPUT_STREAM, GVirInputStream)) -#define GVIR_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \ - GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) -#define GVIR_IS_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ - GVIR_TYPE_INPUT_STREAM)) -#define GVIR_IS_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \ - GVIR_TYPE_INPUT_STREAM)) -#define GVIR_INPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ - GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) +#define GVIR_TYPE_INPUT_STREAM (_gvir_input_stream_get_type ()) +#define GVIR_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GVIR_TYPE_INPUT_STREAM, GVirInputStream)) +#define GVIR_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass)) +#define GVIR_IS_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), GVIR_TYPE_INPUT_STREAM)) +#define GVIR_IS_INPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GVIR_TYPE_INPUT_STREAM)) +#define GVIR_INPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GVIR_TYPE_INPUT_STREAM, GVirInputStreamClass))
-typedef struct _GVirInputStreamPrivate GVirInputStreamPrivate; -typedef struct _GVirInputStreamClass GVirInputStreamClass; -typedef struct _GVirInputStream GVirInputStream; +typedef struct _GVirInputStreamPrivate GVirInputStreamPrivate; +typedef struct _GVirInputStreamClass GVirInputStreamClass; +typedef struct _GVirInputStream GVirInputStream;
struct _GVirInputStreamClass { @@ -60,8 +55,8 @@ struct _GVirInputStream GVirInputStreamPrivate *priv; };
-GType _gvir_input_stream_get_type (void) G_GNUC_CONST; -GVirInputStream * _gvir_input_stream_new (GVirStream *stream); +GType _gvir_input_stream_get_type(void) G_GNUC_CONST; +GVirInputStream *_gvir_input_stream_new(GVirStream *stream);
G_END_DECLS
diff --git a/libvirt-gobject/libvirt-gobject-output-stream.c b/libvirt-gobject/libvirt-gobject-output-stream.c index 30ee519..74eddc5 100644 --- a/libvirt-gobject/libvirt-gobject-output-stream.c +++ b/libvirt-gobject/libvirt-gobject-output-stream.c @@ -54,9 +54,9 @@ struct _GVirOutputStreamPrivate gsize count; };
-static void gvir_output_stream_get_property(GObject *object, - guint prop_id, - GValue *value, +static void gvir_output_stream_get_property(GObject *object, + guint prop_id, + GValue *value, GParamSpec *pspec) { GVirOutputStream *stream = GVIR_OUTPUT_STREAM(object); @@ -71,10 +71,10 @@ static void gvir_output_stream_get_property(GObject *object, } }
-static void gvir_output_stream_set_property(GObject *object, - guint prop_id, +static void gvir_output_stream_set_property(GObject *object, + guint prop_id, const GValue *value, - GParamSpec *pspec) + GParamSpec *pspec) { GVirOutputStream *stream = GVIR_OUTPUT_STREAM(object);
@@ -181,8 +181,8 @@ end: }
-static gssize gvir_output_stream_write_finish(GOutputStream *stream, - GAsyncResult *result, +static gssize gvir_output_stream_write_finish(GOutputStream *stream, + GAsyncResult *result, GError **error G_GNUC_UNUSED) { GVirOutputStream *output_stream = GVIR_OUTPUT_STREAM(stream); diff --git a/libvirt-gobject/libvirt-gobject-output-stream.h b/libvirt-gobject/libvirt-gobject-output-stream.h index 0ca0053..dd1d651 100644 --- a/libvirt-gobject/libvirt-gobject-output-stream.h +++ b/libvirt-gobject/libvirt-gobject-output-stream.h @@ -33,21 +33,16 @@
G_BEGIN_DECLS
-#define GVIR_TYPE_OUTPUT_STREAM (_gvir_output_stream_get_type ()) -#define GVIR_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ - GVIR_TYPE_OUTPUT_STREAM, GVirOutputStream)) -#define GVIR_OUTPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \ - GVIR_TYPE_OUTPUT_STREAM, GVirOutputStreamClass)) -#define GVIR_IS_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ - GVIR_TYPE_OUTPUT_STREAM)) -#define GVIR_IS_OUTPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \ - GVIR_TYPE_OUTPUT_STREAM)) -#define GVIR_OUTPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ - GVIR_TYPE_OUTPUT_STREAM, GVirOutputStreamClass)) +#define GVIR_TYPE_OUTPUT_STREAM (_gvir_output_stream_get_type ()) +#define GVIR_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GVIR_TYPE_OUTPUT_STREAM, GVirOutputStream)) +#define GVIR_OUTPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GVIR_TYPE_OUTPUT_STREAM, GVirOutputStreamClass)) +#define GVIR_IS_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), GVIR_TYPE_OUTPUT_STREAM)) +#define GVIR_IS_OUTPUT_STREAM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GVIR_TYPE_OUTPUT_STREAM)) +#define GVIR_OUTPUT_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GVIR_TYPE_OUTPUT_STREAM, GVirOutputStreamClass))
-typedef struct _GVirOutputStreamPrivate GVirOutputStreamPrivate; -typedef struct _GVirOutputStreamClass GVirOutputStreamClass; -typedef struct _GVirOutputStream GVirOutputStream; +typedef struct _GVirOutputStreamPrivate GVirOutputStreamPrivate; +typedef struct _GVirOutputStreamClass GVirOutputStreamClass; +typedef struct _GVirOutputStream GVirOutputStream;
struct _GVirOutputStreamClass { @@ -60,8 +55,8 @@ struct _GVirOutputStream GVirOutputStreamPrivate *priv; };
-GType _gvir_output_stream_get_type (void) G_GNUC_CONST; -GVirOutputStream * _gvir_output_stream_new (GVirStream *stream); +GType _gvir_output_stream_get_type(void) G_GNUC_CONST; +GVirOutputStream *_gvir_output_stream_new(GVirStream *stream);
G_END_DECLS
diff --git a/libvirt-gobject/libvirt-gobject-stream.c b/libvirt-gobject/libvirt-gobject-stream.c index 03b2c84..8cd3cef 100644 --- a/libvirt-gobject/libvirt-gobject-stream.c +++ b/libvirt-gobject/libvirt-gobject-stream.c @@ -102,7 +102,8 @@ static GOutputStream* gvir_stream_get_output_stream(GIOStream *io_stream)
static gboolean gvir_stream_close(GIOStream *io_stream, - GCancellable *cancellable, G_GNUC_UNUSED GError **error) + GCancellable *cancellable, + G_GNUC_UNUSED GError **error) { GVirStream *self = GVIR_STREAM(io_stream);
@@ -116,8 +117,10 @@ static gboolean gvir_stream_close(GIOStream *io_stream, }
-static void gvir_stream_close_async(GIOStream *stream, G_GNUC_UNUSED int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, +static void gvir_stream_close_async(GIOStream *stream, + int io_priority G_GNUC_UNUSED, + GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *res; @@ -146,9 +149,9 @@ static void gvir_stream_close_async(GIOStream *stream, G_GNUC_UNUSED int io_prio
static gboolean -gvir_stream_close_finish(G_GNUC_UNUSED GIOStream *stream, - G_GNUC_UNUSED GAsyncResult *result, - G_GNUC_UNUSED GError **error) +gvir_stream_close_finish(GIOStream *stream G_GNUC_UNUSED, + GAsyncResult *result G_GNUC_UNUSED, + GError **error G_GNUC_UNUSED) { return TRUE; } @@ -301,8 +304,11 @@ G_DEFINE_BOXED_TYPE(GVirStreamHandle, gvir_stream_handle, * Returns: Number of bytes read, or 0 if the end of stream reached, * or -1 on error. */ -gssize gvir_stream_receive(GVirStream *self, gchar *buffer, gsize size, - GCancellable *cancellable, GError **error) +gssize gvir_stream_receive(GVirStream *self, + gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error) { int got;
@@ -332,7 +338,9 @@ struct stream_sink_helper {
static int stream_sink(virStreamPtr st G_GNUC_UNUSED, - const char *bytes, size_t nbytes, void *opaque) + const char *bytes, + size_t nbytes, + void *opaque) { struct stream_sink_helper *helper = opaque;
@@ -351,7 +359,10 @@ stream_sink(virStreamPtr st G_GNUC_UNUSED, * to virStreamRecv, for apps that do blocking-I/o. */ gssize -gvir_stream_receive_all(GVirStream *self, GVirStreamSinkFunc func, gpointer user_data, GError **err) +gvir_stream_receive_all(GVirStream *self, + GVirStreamSinkFunc func, + gpointer user_data, + GError **err) { struct stream_sink_helper helper = { .self = self, @@ -397,8 +408,11 @@ gvir_stream_receive_all(GVirStream *self, GVirStreamSinkFunc func, gpointer user * Returns: Number of bytes read, or 0 if the end of stream reached, * or -1 on error. */ -gssize gvir_stream_send(GVirStream *self, const gchar *buffer, gsize size, - GCancellable *cancellable, GError **error) +gssize gvir_stream_send(GVirStream *self, + const gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error) { int got;
@@ -428,7 +442,9 @@ struct stream_source_helper {
static int stream_source(virStreamPtr st G_GNUC_UNUSED, - char *bytes, size_t nbytes, void *opaque) + char *bytes, + size_t nbytes, + void *opaque) { struct stream_source_helper *helper = opaque;
@@ -447,7 +463,10 @@ stream_source(virStreamPtr st G_GNUC_UNUSED, * to virStreamRecv, for apps that do blocking-I/o. */ gssize -gvir_stream_send_all(GVirStream *self, GVirStreamSourceFunc func, gpointer user_data, GError **err) +gvir_stream_send_all(GVirStream *self, + GVirStreamSourceFunc func, + gpointer user_data, + GError **err) { struct stream_source_helper helper = { .self = self, diff --git a/libvirt-gobject/libvirt-gobject-stream.h b/libvirt-gobject/libvirt-gobject-stream.h index e0004b2..2719ff3 100644 --- a/libvirt-gobject/libvirt-gobject-stream.h +++ b/libvirt-gobject/libvirt-gobject-stream.h @@ -110,11 +110,25 @@ gint gvir_stream_add_watch(GVirStream *stream, gpointer opaque, GDestroyNotify notify);
-gssize gvir_stream_receive_all(GVirStream *stream, GVirStreamSinkFunc func, gpointer user_data, GError **error); -gssize gvir_stream_receive(GVirStream *stream, gchar *buffer, gsize size, GCancellable *cancellable, GError **error); - -gssize gvir_stream_send_all(GVirStream *stream, GVirStreamSourceFunc func, gpointer user_data, GError **error); -gssize gvir_stream_send(GVirStream *stream, const gchar *buffer, gsize size, GCancellable *cancellable, GError **error); +gssize gvir_stream_receive_all(GVirStream *stream, + GVirStreamSinkFunc func, + gpointer user_data, + GError **error); +gssize gvir_stream_receive(GVirStream *stream, + gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error); + +gssize gvir_stream_send_all(GVirStream *stream, + GVirStreamSourceFunc func, + gpointer user_data, + GError **error); +gssize gvir_stream_send(GVirStream *stream, + const gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error);
G_END_DECLS
-- 1.7.6.4
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

From: "Daniel P. Berrange" <berrange@redhat.com> Since virStreamEventAddCallback only allows a single callback to be registered, GVirInputStream/GVirOutputStream should not use that directly. Instead they should use the gvir_stream_add_watch function * libvirt-gobject/libvirt-gobject-input-stream.c, libvirt-gobject/libvirt-gobject-output-stream.c: Convert to use gvir_stream_add_watch --- libvirt-gobject/libvirt-gobject-input-stream.c | 62 +++++++++++----------- libvirt-gobject/libvirt-gobject-output-stream.c | 62 +++++++++++----------- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-input-stream.c b/libvirt-gobject/libvirt-gobject-input-stream.c index 06ea716..04ecb18 100644 --- a/libvirt-gobject/libvirt-gobject-input-stream.c +++ b/libvirt-gobject/libvirt-gobject-input-stream.c @@ -99,30 +99,40 @@ static void gvir_input_stream_finalize(GObject *object) (*G_OBJECT_CLASS(gvir_input_stream_parent_class)->finalize)(object); } -static void -gvir_input_stream_read_ready(virStreamPtr st G_GNUC_UNUSED, - int events, +static gboolean +gvir_input_stream_read_ready(GVirStream *stream G_GNUC_UNUSED, + GVirStreamIOCondition cond, void *opaque) { - GVirInputStream *stream = GVIR_INPUT_STREAM(opaque); - GVirInputStreamPrivate *priv = stream->priv; - GSimpleAsyncResult *simple; + GVirInputStream *input_stream = GVIR_INPUT_STREAM(opaque); + GVirInputStreamPrivate *priv = input_stream->priv; + GSimpleAsyncResult *simple = priv->result; GError *error = NULL; gssize result; - g_return_if_fail(events & VIR_STREAM_EVENT_READABLE); + if (!(cond & GVIR_STREAM_IO_CONDITION_READABLE)) { + g_warn_if_reached(); + g_simple_async_result_set_error(simple, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "%s", + "Expected stream to be readable"); + goto cleanup; + } - result = gvir_stream_receive(priv->stream, priv->buffer, priv->count, + result = gvir_stream_receive(stream, priv->buffer, priv->count, priv->cancellable, &error); if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_warn_if_reached(); - return; + g_simple_async_result_set_error(simple, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "%s", + "Expected stream to be readable"); + goto cleanup; } - simple = stream->priv->result; - stream->priv->result = NULL; - if (result >= 0) g_simple_async_result_set_op_res_gssize(simple, result); @@ -130,14 +140,15 @@ gvir_input_stream_read_ready(virStreamPtr st G_GNUC_UNUSED, g_simple_async_result_take_error(simple, error); if (priv->cancellable) { - g_object_unref(stream->priv->cancellable); + g_object_unref(priv->cancellable); priv->cancellable = NULL; } +cleanup: + priv->result = NULL; g_simple_async_result_complete(simple); g_object_unref(simple); - - return; + return FALSE; } static void gvir_input_stream_read_async(GInputStream *stream, @@ -149,23 +160,15 @@ static void gvir_input_stream_read_async(GInputStream *stream, gpointer user_data) { GVirInputStream *input_stream = GVIR_INPUT_STREAM(stream); - virStreamPtr handle; g_return_if_fail(GVIR_IS_INPUT_STREAM(stream)); g_return_if_fail(input_stream->priv->result == NULL); - g_object_get(input_stream->priv->stream, "handle", &handle, NULL); - - if (virStreamEventAddCallback(handle, VIR_STREAM_EVENT_READABLE, - gvir_input_stream_read_ready, stream, NULL) < 0) { - g_simple_async_report_error_in_idle(G_OBJECT(stream), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Couldn't add event callback %s", - G_STRFUNC); - goto end; - } + gvir_stream_add_watch(input_stream->priv->stream, + GVIR_STREAM_IO_CONDITION_READABLE, + gvir_input_stream_read_ready, + g_object_ref(stream), + (GDestroyNotify)g_object_unref); input_stream->priv->result = g_simple_async_result_new(G_OBJECT(stream), callback, user_data, @@ -175,9 +178,6 @@ static void gvir_input_stream_read_async(GInputStream *stream, input_stream->priv->cancellable = cancellable; input_stream->priv->buffer = buffer; input_stream->priv->count = count; - -end: - virStreamFree(handle); } diff --git a/libvirt-gobject/libvirt-gobject-output-stream.c b/libvirt-gobject/libvirt-gobject-output-stream.c index 74eddc5..39beb46 100644 --- a/libvirt-gobject/libvirt-gobject-output-stream.c +++ b/libvirt-gobject/libvirt-gobject-output-stream.c @@ -99,30 +99,40 @@ static void gvir_output_stream_finalize(GObject *object) (*G_OBJECT_CLASS(gvir_output_stream_parent_class)->finalize)(object); } -static void -gvir_output_stream_write_ready(virStreamPtr st G_GNUC_UNUSED, - int events, +static gboolean +gvir_output_stream_write_ready(GVirStream *stream, + GVirStreamIOCondition cond, void *opaque) { - GVirOutputStream *stream = GVIR_OUTPUT_STREAM(opaque); - GVirOutputStreamPrivate *priv = stream->priv; - GSimpleAsyncResult *simple; + GVirOutputStream *output_stream = GVIR_OUTPUT_STREAM(opaque); + GVirOutputStreamPrivate *priv = output_stream->priv; + GSimpleAsyncResult *simple = priv->result; GError *error = NULL; gssize result; - g_return_if_fail(events & VIR_STREAM_EVENT_WRITABLE); + if (!(cond & GVIR_STREAM_IO_CONDITION_WRITABLE)) { + g_warn_if_reached(); + g_simple_async_result_set_error(simple, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "%s", + "Expected stream to be writable"); + goto cleanup; + } - result = gvir_stream_send(priv->stream, priv->buffer, priv->count, + result = gvir_stream_send(stream, priv->buffer, priv->count, priv->cancellable, &error); if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_warn_if_reached(); - return; + g_simple_async_result_set_error(simple, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "%s", + "Expected stream to be writable"); + goto cleanup; } - simple = stream->priv->result; - stream->priv->result = NULL; - if (result >= 0) g_simple_async_result_set_op_res_gssize(simple, result); @@ -130,14 +140,15 @@ gvir_output_stream_write_ready(virStreamPtr st G_GNUC_UNUSED, g_simple_async_result_take_error(simple, error); if (priv->cancellable) { - g_object_unref(stream->priv->cancellable); + g_object_unref(priv->cancellable); priv->cancellable = NULL; } +cleanup: + priv->result = NULL; g_simple_async_result_complete(simple); g_object_unref(simple); - - return; + return FALSE; } static void gvir_output_stream_write_async(GOutputStream *stream, @@ -149,23 +160,15 @@ static void gvir_output_stream_write_async(GOutputStream *stream, gpointer user_data) { GVirOutputStream *output_stream = GVIR_OUTPUT_STREAM(stream); - virStreamPtr handle; g_return_if_fail(GVIR_IS_OUTPUT_STREAM(stream)); g_return_if_fail(output_stream->priv->result == NULL); - g_object_get(output_stream->priv->stream, "handle", &handle, NULL); - - if (virStreamEventAddCallback(handle, VIR_STREAM_EVENT_WRITABLE, - gvir_output_stream_write_ready, stream, NULL) < 0) { - g_simple_async_report_error_in_idle(G_OBJECT(stream), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Couldn't add event callback %s", - G_STRFUNC); - goto end; - } + gvir_stream_add_watch(output_stream->priv->stream, + GVIR_STREAM_IO_CONDITION_WRITABLE, + gvir_output_stream_write_ready, + g_object_ref(stream), + (GDestroyNotify)g_object_unref); output_stream->priv->result = g_simple_async_result_new(G_OBJECT(stream), callback, user_data, @@ -175,9 +178,6 @@ static void gvir_output_stream_write_async(GOutputStream *stream, output_stream->priv->cancellable = cancellable; output_stream->priv->buffer = buffer; output_stream->priv->count = count; - -end: - virStreamFree(handle); } -- 1.7.6.4

On Mon, Nov 28, 2011 at 01:13:48PM +0000, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Since virStreamEventAddCallback only allows a single callback to be registered, GVirInputStream/GVirOutputStream should not use that directly. Instead they should use the gvir_stream_add_watch function
* libvirt-gobject/libvirt-gobject-input-stream.c, libvirt-gobject/libvirt-gobject-output-stream.c: Convert to use gvir_stream_add_watch --- libvirt-gobject/libvirt-gobject-input-stream.c | 62 +++++++++++----------- libvirt-gobject/libvirt-gobject-output-stream.c | 62 +++++++++++----------- 2 files changed, 62 insertions(+), 62 deletions(-)
diff --git a/libvirt-gobject/libvirt-gobject-input-stream.c b/libvirt-gobject/libvirt-gobject-input-stream.c index 06ea716..04ecb18 100644 --- a/libvirt-gobject/libvirt-gobject-input-stream.c +++ b/libvirt-gobject/libvirt-gobject-input-stream.c @@ -99,30 +99,40 @@ static void gvir_input_stream_finalize(GObject *object) (*G_OBJECT_CLASS(gvir_input_stream_parent_class)->finalize)(object); }
-static void -gvir_input_stream_read_ready(virStreamPtr st G_GNUC_UNUSED, - int events, +static gboolean +gvir_input_stream_read_ready(GVirStream *stream G_GNUC_UNUSED,
G_GNUC_UNUSED can be dropped since stream is used in the call to gvir_stream_receive below. Christophe
+ GVirStreamIOCondition cond, void *opaque) { - GVirInputStream *stream = GVIR_INPUT_STREAM(opaque); - GVirInputStreamPrivate *priv = stream->priv; - GSimpleAsyncResult *simple; + GVirInputStream *input_stream = GVIR_INPUT_STREAM(opaque); + GVirInputStreamPrivate *priv = input_stream->priv; + GSimpleAsyncResult *simple = priv->result; GError *error = NULL; gssize result;
- g_return_if_fail(events & VIR_STREAM_EVENT_READABLE); + if (!(cond & GVIR_STREAM_IO_CONDITION_READABLE)) { + g_warn_if_reached(); + g_simple_async_result_set_error(simple, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "%s", + "Expected stream to be readable"); + goto cleanup; + }
- result = gvir_stream_receive(priv->stream, priv->buffer, priv->count, + result = gvir_stream_receive(stream, priv->buffer, priv->count, priv->cancellable, &error);
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_warn_if_reached(); - return; + g_simple_async_result_set_error(simple, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "%s", + "Expected stream to be readable"); + goto cleanup; }
- simple = stream->priv->result; - stream->priv->result = NULL; - if (result >= 0) g_simple_async_result_set_op_res_gssize(simple, result);
@@ -130,14 +140,15 @@ gvir_input_stream_read_ready(virStreamPtr st G_GNUC_UNUSED, g_simple_async_result_take_error(simple, error);
if (priv->cancellable) { - g_object_unref(stream->priv->cancellable); + g_object_unref(priv->cancellable); priv->cancellable = NULL; }
+cleanup: + priv->result = NULL; g_simple_async_result_complete(simple); g_object_unref(simple); - - return; + return FALSE; }
static void gvir_input_stream_read_async(GInputStream *stream, @@ -149,23 +160,15 @@ static void gvir_input_stream_read_async(GInputStream *stream, gpointer user_data) { GVirInputStream *input_stream = GVIR_INPUT_STREAM(stream); - virStreamPtr handle;
g_return_if_fail(GVIR_IS_INPUT_STREAM(stream)); g_return_if_fail(input_stream->priv->result == NULL);
- g_object_get(input_stream->priv->stream, "handle", &handle, NULL); - - if (virStreamEventAddCallback(handle, VIR_STREAM_EVENT_READABLE, - gvir_input_stream_read_ready, stream, NULL) < 0) { - g_simple_async_report_error_in_idle(G_OBJECT(stream), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Couldn't add event callback %s", - G_STRFUNC); - goto end; - } + gvir_stream_add_watch(input_stream->priv->stream, + GVIR_STREAM_IO_CONDITION_READABLE, + gvir_input_stream_read_ready, + g_object_ref(stream), + (GDestroyNotify)g_object_unref);
input_stream->priv->result = g_simple_async_result_new(G_OBJECT(stream), callback, user_data, @@ -175,9 +178,6 @@ static void gvir_input_stream_read_async(GInputStream *stream, input_stream->priv->cancellable = cancellable; input_stream->priv->buffer = buffer; input_stream->priv->count = count; - -end: - virStreamFree(handle); }
diff --git a/libvirt-gobject/libvirt-gobject-output-stream.c b/libvirt-gobject/libvirt-gobject-output-stream.c index 74eddc5..39beb46 100644 --- a/libvirt-gobject/libvirt-gobject-output-stream.c +++ b/libvirt-gobject/libvirt-gobject-output-stream.c @@ -99,30 +99,40 @@ static void gvir_output_stream_finalize(GObject *object) (*G_OBJECT_CLASS(gvir_output_stream_parent_class)->finalize)(object); }
-static void -gvir_output_stream_write_ready(virStreamPtr st G_GNUC_UNUSED, - int events, +static gboolean +gvir_output_stream_write_ready(GVirStream *stream, + GVirStreamIOCondition cond, void *opaque) { - GVirOutputStream *stream = GVIR_OUTPUT_STREAM(opaque); - GVirOutputStreamPrivate *priv = stream->priv; - GSimpleAsyncResult *simple; + GVirOutputStream *output_stream = GVIR_OUTPUT_STREAM(opaque); + GVirOutputStreamPrivate *priv = output_stream->priv; + GSimpleAsyncResult *simple = priv->result; GError *error = NULL; gssize result;
- g_return_if_fail(events & VIR_STREAM_EVENT_WRITABLE); + if (!(cond & GVIR_STREAM_IO_CONDITION_WRITABLE)) { + g_warn_if_reached(); + g_simple_async_result_set_error(simple, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "%s", + "Expected stream to be writable"); + goto cleanup; + }
- result = gvir_stream_send(priv->stream, priv->buffer, priv->count, + result = gvir_stream_send(stream, priv->buffer, priv->count, priv->cancellable, &error);
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_warn_if_reached(); - return; + g_simple_async_result_set_error(simple, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "%s", + "Expected stream to be writable"); + goto cleanup; }
- simple = stream->priv->result; - stream->priv->result = NULL; - if (result >= 0) g_simple_async_result_set_op_res_gssize(simple, result);
@@ -130,14 +140,15 @@ gvir_output_stream_write_ready(virStreamPtr st G_GNUC_UNUSED, g_simple_async_result_take_error(simple, error);
if (priv->cancellable) { - g_object_unref(stream->priv->cancellable); + g_object_unref(priv->cancellable); priv->cancellable = NULL; }
+cleanup: + priv->result = NULL; g_simple_async_result_complete(simple); g_object_unref(simple); - - return; + return FALSE; }
static void gvir_output_stream_write_async(GOutputStream *stream, @@ -149,23 +160,15 @@ static void gvir_output_stream_write_async(GOutputStream *stream, gpointer user_data) { GVirOutputStream *output_stream = GVIR_OUTPUT_STREAM(stream); - virStreamPtr handle;
g_return_if_fail(GVIR_IS_OUTPUT_STREAM(stream)); g_return_if_fail(output_stream->priv->result == NULL);
- g_object_get(output_stream->priv->stream, "handle", &handle, NULL); - - if (virStreamEventAddCallback(handle, VIR_STREAM_EVENT_WRITABLE, - gvir_output_stream_write_ready, stream, NULL) < 0) { - g_simple_async_report_error_in_idle(G_OBJECT(stream), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Couldn't add event callback %s", - G_STRFUNC); - goto end; - } + gvir_stream_add_watch(output_stream->priv->stream, + GVIR_STREAM_IO_CONDITION_WRITABLE, + gvir_output_stream_write_ready, + g_object_ref(stream), + (GDestroyNotify)g_object_unref);
output_stream->priv->result = g_simple_async_result_new(G_OBJECT(stream), callback, user_data, @@ -175,9 +178,6 @@ static void gvir_output_stream_write_async(GOutputStream *stream, output_stream->priv->cancellable = cancellable; output_stream->priv->buffer = buffer; output_stream->priv->count = count; - -end: - virStreamFree(handle); }
-- 1.7.6.4
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
participants (2)
-
Christophe Fergeau
-
Daniel P. Berrange