[sorry, this probably breaks threading as I mistakenly deleted the original email] On Mon, Jun 23, 2014 at 05:29:10PM +0200, Timm Bäder wrote: > This function can be used to fetch the snapshots of a domain (according > to the given GVirDomainSnapshotListFlags) and save them in a > domain-internal GHashTable. A function to access them from outside will > be added in a later patch. > --- > libvirt-gobject/libvirt-gobject-domain.c | 59 ++++++++++++++++++++++++++++++++ > libvirt-gobject/libvirt-gobject-domain.h | 36 +++++++++++++++++++ > libvirt-gobject/libvirt-gobject.sym | 2 ++ > 3 files changed, 97 insertions(+) > > diff --git a/libvirt-gobject/libvirt-gobject-domain.c b/libvirt-gobject/libvirt-gobject-domain.c > index c6e30e5..f6b5837 100644 > --- a/libvirt-gobject/libvirt-gobject-domain.c > +++ b/libvirt-gobject/libvirt-gobject-domain.c > @@ -38,6 +38,7 @@ struct _GVirDomainPrivate > { > virDomainPtr handle; > gchar uuid[VIR_UUID_STRING_BUFLEN]; > + GHashTable *snapshots; > }; > > G_DEFINE_TYPE(GVirDomain, gvir_domain, G_TYPE_OBJECT); > @@ -121,6 +122,8 @@ static void gvir_domain_finalize(GObject *object) > > g_debug("Finalize GVirDomain=%p", domain); > > + g_hash_table_unref (priv->snapshots); > + You need to check if it's NULL before trying to unref it. > virDomainFree(priv->handle); > > G_OBJECT_CLASS(gvir_domain_parent_class)->finalize(object); > @@ -1514,3 +1517,59 @@ gvir_domain_create_snapshot(GVirDomain *dom, > g_free(custom_xml); > return dom_snapshot; > } > + > + > + > +/** > + * gvir_domain_fetch_snapshots: > + * @dom: The domain > + * @list_flags: bitwise-OR of #GVirDomainSnapshotListFlags > + * @error: (allow-none): Place-holder for error or NULL > + * > + * Returns: TRUE on success, FALSE otherwise. > + */ > +gboolean gvir_domain_fetch_snapshots(GVirDomain *dom, > + guint list_flags, > + GError **error) > +{ > + GVirDomainPrivate *priv; > + virDomainSnapshotPtr *snapshots = NULL; > + GVirDomainSnapshot *snap; > + int n_snaps = 0; > + int i; > + > + g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE); > + g_return_val_if_fail((error == NULL) || (*error == NULL), FALSE); > + > + priv = dom->priv; > + > + if (priv->snapshots != NULL) { > + g_hash_table_destroy (priv->snapshots); g_hash_table_unref() would be more consistent with what is done in _finalize. > + } > + > + priv->snapshots = g_hash_table_new_full(g_str_hash, > + g_str_equal, > + g_free, The g_free() here seems wrong (more details below) > + g_object_unref); > + > + > + n_snaps = virDomainListAllSnapshots(priv->handle, &snapshots, list_flags); > + > + if (n_snaps < 0) { > + gvir_set_error(error, GVIR_DOMAIN_ERROR, 0, > + "Unable to fetch snapshots of %s", > + gvir_domain_get_name (dom)); > + return FALSE; > + } > + > + for (i = 0; i < n_snaps; i ++) { > + snap = GVIR_DOMAIN_SNAPSHOT(g_object_new(GVIR_TYPE_DOMAIN_SNAPSHOT, > + "handle", snapshots[i], > + NULL)); > + g_hash_table_insert(priv->snapshots, > + (gpointer)gvir_domain_snapshot_get_name(snap), > + snap); gvir_domain_snapshot_get_name() does not return a copy of the string, but just a const char * you do not own, so the g_free you passed to g_hash_table_new_full to destroy the key is not correct. > + } > + g_free(snapshots); snapshots was allocated by libvirt, so it should be freed using free(), not g_free(). Most of the time, g_free() ends up calling free(), but this can be changed (by the library user) with g_mem_set_vtable(). Patch looks good otherwise. As calling into libvirt can be costly (we could be talking to a remote libvirt), do you have plans to implement an async() variant of this as well? Christophe
Attachment:
pgpcutdBTQzZQ.pgp
Description: PGP signature
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list