Matthew Booth
2012-Apr-26 10:44 UTC
[Libguestfs] [PATCH 1/3] gobject: NFC generated code formatting fix
--- generator/generator_gobject.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/generator_gobject.ml b/generator/generator_gobject.ml index e4c175b..48ddbf0 100644 --- a/generator/generator_gobject.ml +++ b/generator/generator_gobject.ml @@ -391,7 +391,7 @@ let generate_gobject_optargs_source name optargs flags () pr "G_DEFINE_TYPE(%s, guestfs_%s, G_TYPE_OBJECT);\n\n" camel_name name; pr "enum {\n"; - pr "PROP_GUESTFS_%s_PROP0" uc_name; + pr " PROP_GUESTFS_%s_PROP0" uc_name; List.iter ( fun optargt -> let uc_optname = String.uppercase (name_of_optargt optargt) in -- 1.7.10
Matthew Booth
2012-Apr-26 10:44 UTC
[Libguestfs] [PATCH 2/3] gobject: Wrap literal sections in POD in CDATA sections
--- generator/generator_gobject.ml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/generator/generator_gobject.ml b/generator/generator_gobject.ml index 48ddbf0..479e34d 100644 --- a/generator/generator_gobject.ml +++ b/generator/generator_gobject.ml @@ -765,6 +765,7 @@ guestfs_session_close(GuestfsSession *session, GError **err) let api_crossref = Str.regexp "C<guestfs_\\([-_0-9a-zA-Z]+\\)>" in let nonapi_crossref = Str.regexp "C<\\([-_0-9a-zA-Z]+\\)>" in let escaped = Str.regexp "E<\\([0-9a-zA-Z]+\\)>" in + let literal = Str.regexp "\\(^\\|\n\\)[ \t]+\\([^\n]*\\)\\(\n\\|$\\)" in List.iter ( fun (name, (ret, args, optargs as style), _, flags, _, shortdesc, longdesc) -> @@ -807,6 +808,10 @@ guestfs_session_close(GuestfsSession *session, GError **err) fun s -> "&" ^ Str.matched_group 1 s ^ ";" ) longdesc in + let longdesc = Str.global_substitute literal ( + fun s -> + "\n <![CDATA[" ^ Str.matched_group 2 s ^ "]]>\n" + ) longdesc in let doc = pod2text ~width:76 name longdesc in let doc = String.concat "\n * " doc in let camel_name = camel_of_name flags name in -- 1.7.10
Matthew Booth
2012-Apr-26 10:44 UTC
[Libguestfs] [PATCH 3/3] gobject: Implement libguestfs events as signals
Implement libguestfs events as GObject signals. Callback arguments are passed in a boxed object. Note that this patch fixes the length of the uint64_t array in the callback arguments at 16, whereas it is actually arbitrary length. This is to make it introspectable. There is currently no way to pass an arbitrary length array to a callback, and have its type introspected. --- generator/generator_gobject.ml | 188 +++++++++++++++++++++++++++++++++++++++- gobject/tests-misc.js | 33 +++++++ 2 files changed, 220 insertions(+), 1 deletion(-) diff --git a/generator/generator_gobject.ml b/generator/generator_gobject.ml index 479e34d..312ecb4 100644 --- a/generator/generator_gobject.ml +++ b/generator/generator_gobject.ml @@ -23,6 +23,7 @@ open Printf open Generator_actions open Generator_docstrings +open Generator_events open Generator_pr open Generator_structs open Generator_types @@ -597,6 +598,60 @@ guestfs_tristate_get_type(void) let generate_gobject_session_header () pr " +/* GuestfsSessionEvent */ + +/** + * GuestfsSessionEvent: +"; + + List.iter ( + fun (name, _) -> + pr " * @GUESTFS_SESSION_EVENT_%s: The %s event\n" + (String.uppercase name) name; + ) events; + + pr " * + * For more detail on libguestfs events, see \"SETTING CALLBACKS TO HANDLE + * EVENTS\" in guestfs(3). + */ +typedef enum {"; + + List.iter ( + fun (name, _) -> + pr "\n GUESTFS_SESSION_EVENT_%s," (String.uppercase name); + ) events; + + pr " +} GuestfsSessionEvent; +GType guestfs_session_event_get_type(void); +#define GUESTFS_TYPE_SESSION_EVENT (guestfs_session_event_get_type()) + +/* GuestfsSessionEventParams */ + +/** + * GuestfsSessionEventParams: + * @event: The event + * @flags: Unused + * @buf: A message buffer. This buffer can contain arbitrary 8 bit data, + * including NUL bytes + * @array: An array of 64-bit unsigned integers + * @array_len: The length of @array + */ +typedef struct _GuestfsSessionEventParams GuestfsSessionEventParams; +struct _GuestfsSessionEventParams { + GuestfsSessionEvent event; + guint flags; + GByteArray *buf; + /* The libguestfs array has no fixed length, although it is currently only + * ever empty or length 4. We fix the length of the array here as there is + * currently no way for an arbitrary length array to be introspected in a + * boxed object. + */ + guint64 array[16]; + size_t array_len; +}; +GType guestfs_session_event_params_get_type(void); + /* GuestfsSession object definition */ #define GUESTFS_TYPE_SESSION (guestfs_session_get_type()) #define GUESTFS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ( \ @@ -661,6 +716,8 @@ let generate_gobject_session_source () #include <glib.h> #include <glib-object.h> #include <guestfs.h> + #include <stdint.h> + #include <stdio.h> #include <string.h> /* Error quark */ @@ -681,6 +738,104 @@ cancelled_handler(gpointer data) guestfs_user_cancel(g); } +/* GuestfsSessionEventParams */ +static GuestfsSessionEventParams * +guestfs_session_event_params_copy(GuestfsSessionEventParams *src) +{ + return g_slice_dup(GuestfsSessionEventParams, src); +} + +static void +guestfs_session_event_params_free(GuestfsSessionEventParams *src) +{ + g_slice_free(GuestfsSessionEventParams, src); +} + +G_DEFINE_BOXED_TYPE(GuestfsSessionEventParams, + guestfs_session_event_params, + guestfs_session_event_params_copy, + guestfs_session_event_params_free) + +/* Event callback */ +"; + + pr "static guint signals[%i] = { 0 };\n" (List.length events); + +pr " +static GuestfsSessionEvent +guestfs_session_event_from_guestfs_event(uint64_t event) +{ + switch(event) {"; + + List.iter ( + fun (name, _) -> + let enum_name = "GUESTFS_SESSION_EVENT_" ^ String.uppercase name in + let guestfs_name = "GUESTFS_EVENT_" ^ String.uppercase name in + pr "\n case %s: return %s;" guestfs_name enum_name; + ) events; + +pr " + } + + g_warning(\"guestfs_session_event_from_guestfs_event: invalid event %%lu\", + event); + return UINT32_MAX; +} + +static void +event_callback(guestfs_h *g, void *opaque, + uint64_t event, int event_handle, + int flags, + const char *buf, size_t buf_len, + const uint64_t *array, size_t array_len) +{ + GuestfsSessionEventParams *params = g_slice_new0(GuestfsSessionEventParams); + + params->event = guestfs_session_event_from_guestfs_event(event); + params->flags = flags; + + params->buf = g_byte_array_sized_new(buf_len); + g_byte_array_append(params->buf, buf, buf_len); + + for(size_t i = 0; i < array_len && i < 4; i++) { + if(array_len > 4) { + array_len = 4; + } + memcpy(params->array, array, sizeof(array[0]) * array_len); + } + params->array_len = array_len; + + GuestfsSession *session = (GuestfsSession *) opaque; + + g_signal_emit(session, signals[params->event], 0, params); + + guestfs_session_event_params_free(params); +} + +/* GuestfsSessionEvent */ + +GType +guestfs_session_event_get_type(void) +{ + static GType etype = 0; + if (etype == 0) { + static const GEnumValue values[] = {"; + + List.iter ( + fun (name, _) -> + let enum_name = "GUESTFS_SESSION_EVENT_" ^ String.uppercase name in + pr "\n { %s, \"%s\", \"%s\" }," enum_name enum_name name + ) events; + + pr " + }; + etype = g_enum_register_static(\"GuestfsSessionEvent\", values); + } + return etype; +} + +/* GuestfsSession */ + #define GUESTFS_SESSION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ( \ (obj), \ GUESTFS_TYPE_SESSION, \ @@ -689,6 +844,7 @@ cancelled_handler(gpointer data) struct _GuestfsSessionPrivate { guestfs_h *g; + int event_handle; }; G_DEFINE_TYPE(GuestfsSession, guestfs_session, G_TYPE_OBJECT); @@ -711,7 +867,31 @@ guestfs_session_class_init(GuestfsSessionClass *klass) object_class->finalize = guestfs_session_finalize; - g_type_class_add_private(klass, sizeof(GuestfsSessionPrivate)); + g_type_class_add_private(klass, sizeof(GuestfsSessionPrivate));"; + + List.iter ( + fun (name, _) -> + pr "\n\n"; + pr " /**\n"; + pr " * GuestfsSession::%s:\n" name; + pr " * @session: The session which emitted the signal\n"; + pr " * @params: An object containing event parameters\n"; + pr " *\n"; + pr " * See \"SETTING CALLBACKS TO HANDLE EVENTS\" in guestfs(3) for\n"; + pr " * more details about this event.\n"; + pr " */\n"; + pr " signals[GUESTFS_SESSION_EVENT_%s] =\n" (String.uppercase name); + pr " g_signal_new(g_intern_static_string(\"%s\"),\n" name; + pr " G_OBJECT_CLASS_TYPE(object_class),\n"; + pr " G_SIGNAL_RUN_LAST,\n"; + pr " 0,\n"; + pr " NULL, NULL,\n"; + pr " NULL,\n"; + pr " G_TYPE_NONE,\n"; + pr " 1, guestfs_session_event_params_get_type());"; + ) events; + + pr " } static void @@ -719,6 +899,12 @@ guestfs_session_init(GuestfsSession *session) { session->priv = GUESTFS_SESSION_GET_PRIVATE(session); session->priv->g = guestfs_create(); + + guestfs_h *g = session->priv->g; + + session->priv->event_handle + guestfs_set_event_callback(g, event_callback, GUESTFS_EVENT_ALL, + 0, session); } /** diff --git a/gobject/tests-misc.js b/gobject/tests-misc.js index aadc2f3..8faf8a8 100644 --- a/gobject/tests-misc.js +++ b/gobject/tests-misc.js @@ -21,6 +21,39 @@ var fail = false; var g = new Guestfs.Session(); +var progress_detected = false; +var trace_detected = false; + +// Test events +g.connect('progress', function(session, params) { + if (params.array_len == 4) { + // Look for the final progress notification where position = total + if (params.array[2] == params.array[3] && params.array[2] != 0) { + progress_detected = true; + } + } +}); +g.connect('trace', function(session, params) { + if (params.buf == 'launch') { + trace_detected = true; + } +}); + +g.add_drive('../tests/guests/fedora.img'); +g.set_trace(true); +g.launch(); +// Fake progress messages for a 5 second event. We do this as launch() will not +// generate any progress messages unless it takes at least 5 seconds. +g.debug('progress', ['5']); +if (!trace_detected) { + print("failed to detect trace message for launch"); + fail = true; +} +if (!progress_detected) { + print("failed to detect progress message for launch"); + fail = true; +} + // Test close() g.close(); var threw = false; -- 1.7.10
Richard W.M. Jones
2012-Apr-26 10:57 UTC
[Libguestfs] [PATCH 1/3] gobject: NFC generated code formatting fix
On Thu, Apr 26, 2012 at 11:44:50AM +0100, Matthew Booth wrote:> --- > generator/generator_gobject.ml | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/generator/generator_gobject.ml b/generator/generator_gobject.ml > index e4c175b..48ddbf0 100644 > --- a/generator/generator_gobject.ml > +++ b/generator/generator_gobject.ml > @@ -391,7 +391,7 @@ let generate_gobject_optargs_source name optargs flags () > pr "G_DEFINE_TYPE(%s, guestfs_%s, G_TYPE_OBJECT);\n\n" camel_name name; > > pr "enum {\n"; > - pr "PROP_GUESTFS_%s_PROP0" uc_name; > + pr " PROP_GUESTFS_%s_PROP0" uc_name; > List.iter ( > fun optargt -> > let uc_optname = String.uppercase (name_of_optargt optargt) in > -- > 1.7.10ACK. Fixes an obvious problem with formatting in the output: enum { PROP_GUESTFS_UMOUNT_LOCAL_PROP0, PROP_GUESTFS_UMOUNT_LOCAL_RETRY }; Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v