On Mon, Jun 30, 2014 at 07:50:14PM +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 | 83 ++++++++++++++++++++++++++++++++ > libvirt-gobject/libvirt-gobject-domain.h | 37 ++++++++++++++ > libvirt-gobject/libvirt-gobject.sym | 2 + > 3 files changed, 122 insertions(+) > > diff --git a/libvirt-gobject/libvirt-gobject-domain.c b/libvirt-gobject/libvirt-gobject-domain.c > index c6e30e5..180a206 100644 > --- a/libvirt-gobject/libvirt-gobject-domain.c > +++ b/libvirt-gobject/libvirt-gobject-domain.c > @@ -38,6 +38,8 @@ struct _GVirDomainPrivate > { > virDomainPtr handle; > gchar uuid[VIR_UUID_STRING_BUFLEN]; > + GHashTable *snapshots; > + GMutex *lock; > }; > > G_DEFINE_TYPE(GVirDomain, gvir_domain, G_TYPE_OBJECT); > @@ -121,6 +123,11 @@ static void gvir_domain_finalize(GObject *object) > > g_debug("Finalize GVirDomain=%p", domain); > > + if (priv->snapshots) { > + g_hash_table_unref(priv->snapshots); > + } > + g_mutex_free(priv->lock); > + > virDomainFree(priv->handle); > > G_OBJECT_CLASS(gvir_domain_parent_class)->finalize(object); > @@ -237,6 +244,7 @@ static void gvir_domain_init(GVirDomain *domain) > g_debug("Init GVirDomain=%p", domain); > > domain->priv = GVIR_DOMAIN_GET_PRIVATE(domain); > + domain->priv->lock = g_mutex_new(); > } > > typedef struct virDomain GVirDomainHandle; > @@ -1514,3 +1522,78 @@ 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 > + * @cancellable: (allow-none)(transfer-none): cancellation object > + * @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, > + GCancellable *cancellable, > + GError **error) > +{ > + GVirDomainPrivate *priv; > + virDomainSnapshotPtr *snapshots = NULL; > + GVirDomainSnapshot *snap; > + GHashTable *snap_table; > + int n_snaps = 0; > + int i; > + gboolean ret = TRUE; > + > + g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE); > + g_return_val_if_fail((error == NULL) || (*error == NULL), FALSE); > + > + priv = dom->priv; > + > + snap_table = g_hash_table_new_full(g_str_hash, > + g_str_equal, > + NULL, > + g_object_unref); > + > + > + n_snaps = virDomainListAllSnapshots(priv->handle, &snapshots, list_flags); > + > + if (g_cancellable_set_error_if_cancelled(cancellable, error)) { > + ret = FALSE; > + goto cleanup; > + } > + > + if (n_snaps < 0) { > + gvir_set_error(error, GVIR_DOMAIN_ERROR, 0, > + "Unable to fetch snapshots of %s", > + gvir_domain_get_name(dom)); > + ret = FALSE; > + goto cleanup; > + } > + > + for (i = 0; i < n_snaps; i ++) { > + if (g_cancellable_set_error_if_cancelled(cancellable, error)) { > + ret = FALSE; > + goto cleanup; > + } > + snap = GVIR_DOMAIN_SNAPSHOT(g_object_new(GVIR_TYPE_DOMAIN_SNAPSHOT, > + "handle", snapshots[i], > + NULL)); > + g_hash_table_insert(snap_table, > + (gpointer)gvir_domain_snapshot_get_name(snap), > + snap); > + } > + > + > + g_mutex_lock(priv->lock); > + if (priv->snapshots != NULL) > + g_hash_table_unref(priv->snapshots); > + priv->snapshots = snap_table; > + g_mutex_unlock(priv->lock); > + > +cleanup: This is leaking 'snap_table' in error cases. You can have a if (snap_table != NULL) { g_hash_table_unref (snap_table); } here, and set snap_table to NULL right before the cleanup: label. > + free(snapshots); > + return ret; > +} > diff --git a/libvirt-gobject/libvirt-gobject-domain.h b/libvirt-gobject/libvirt-gobject-domain.h > index 38d3458..8c1a8e5 100644 > --- a/libvirt-gobject/libvirt-gobject-domain.h > +++ b/libvirt-gobject/libvirt-gobject-domain.h > @@ -183,6 +183,39 @@ typedef enum { > GVIR_DOMAIN_REBOOT_GUEST_AGENT = VIR_DOMAIN_REBOOT_GUEST_AGENT, > } GVirDomainRebootFlags; > > +/** > + * GVirDomainSnapshotListFlags: > + * @GVIR_DOMAIN_SNAPSHOT_LIST_ALL: List all snapshots > + * @GVIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS: List all descendants, not just > + * children, when listing a snapshot. > + * For historical reasons, groups do not use contiguous bits. > + * @GVIR_DOMAIN_SNAPSHOT_LIST_ROOTS: Filter by snapshots with no parents, when listing a domain > + * @GVIR_DOMAIN_SNAPSHOT_LIST_METADATA: Filter by snapshots which have metadata > + * @GVIR_DOMAIN_SNAPSHOT_LIST_LEAVES: Filter by snapshots with no children > + * @GVIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES: Filter by snapshots that have children > + * @GVIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA: Filter by snapshots with no metadata > + * @GVIR_DOMAIN_SNAPSHOT_LIST_INACTIVE: Filter by snapshots taken while guest was shut off > + * @GVIR_DOMAIN_SNAPSHOT_LIST_ACTIVE: Filter by snapshots taken while guest was active, and with memory state > + * @GVIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY: Filter by snapshots taken while guest was active, but without memory state > + * @GVIR_DOMAIN_SNAPSHOT_LIST_INTERNAL: Filter by snapshots stored internal to disk images > + * @GVIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL: Filter by snapshots that use files external to disk images > + */ > +typedef enum { > + GVIR_DOMAIN_SNAPSHOT_LIST_ALL = 0, > + GVIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS = VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS, > + GVIR_DOMAIN_SNAPSHOT_LIST_ROOTS = VIR_DOMAIN_SNAPSHOT_LIST_ROOTS, > + GVIR_DOMAIN_SNAPSHOT_LIST_METADATA = VIR_DOMAIN_SNAPSHOT_LIST_METADATA, > + GVIR_DOMAIN_SNAPSHOT_LIST_LEAVES = VIR_DOMAIN_SNAPSHOT_LIST_LEAVES, > + GVIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES = VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, > + GVIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA = VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, > + GVIR_DOMAIN_SNAPSHOT_LIST_INACTIVE = VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE, > + GVIR_DOMAIN_SNAPSHOT_LIST_ACTIVE = VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, > + GVIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY = VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY, > + GVIR_DOMAIN_SNAPSHOT_LIST_INTERNAL = VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL, > + GVIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL = VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL > +} GVirDomainSnapshotListFlags; > + > + > typedef struct _GVirDomainInfo GVirDomainInfo; > struct _GVirDomainInfo > { > @@ -330,6 +363,10 @@ gvir_domain_create_snapshot(GVirDomain *dom, > guint flags, > GError **err); > > +gboolean gvir_domain_fetch_snapshots(GVirDomain *dom, > + guint list_flags, > + GCancellable *cancellable, > + GError **error); > G_END_DECLS > > #endif /* __LIBVIRT_GOBJECT_DOMAIN_H__ */ > diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym > index b781cc6..781310f 100644 > --- a/libvirt-gobject/libvirt-gobject.sym > +++ b/libvirt-gobject/libvirt-gobject.sym > @@ -236,7 +236,9 @@ LIBVIRT_GOBJECT_0.1.5 { > > LIBVIRT_GOBJECT_0.1.9 { > global: > + gvir_domain_fetch_snapshots; > gvir_domain_snapshot_delete; > + gvir_domain_snapshot_list_flags_get_type; > } LIBVIRT_GOBJECT_0.1.5; > > # .... define new API here using predicted next version number .... > -- > 2.0.1 > > -- > libvir-list mailing list > libvir-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list
Attachment:
pgpzE6v3P2AhA.pgp
Description: PGP signature
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list