Finish the code motion of generic moment list handling. Well, mostly - we need to convert to using virObject to get polymorphic cleanup functions (so for now there are still a few lingering ties specific to snapshots). In this case, I kept virDomainSnapshotObjList as a wrapper type around the new generic virDomainMomentObjList; the bulk of the algorithms move, but the old functions remain and forward to the generic helpers. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- src/conf/virconftypes.h | 3 + src/conf/virdomainmomentobjlist.h | 32 +++ src/conf/virdomainsnapshotobjlist.h | 6 - src/conf/virdomainmomentobjlist.c | 356 ++++++++++++++++++++++++++++ src/conf/virdomainsnapshotobjlist.c | 266 +++------------------ 5 files changed, 422 insertions(+), 241 deletions(-) diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index 574815cf04..6a8267c422 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -223,6 +223,9 @@ typedef virDomainMomentDef *virDomainMomentDefPtr; typedef struct _virDomainMomentObj virDomainMomentObj; typedef virDomainMomentObj *virDomainMomentObjPtr; +typedef struct _virDomainMomentObjList virDomainMomentObjList; +typedef virDomainMomentObjList *virDomainMomentObjListPtr; + typedef struct _virDomainNVRAMDef virDomainNVRAMDef; typedef virDomainNVRAMDef *virDomainNVRAMDefPtr; diff --git a/src/conf/virdomainmomentobjlist.h b/src/conf/virdomainmomentobjlist.h index dceb55fca2..4d765c552f 100644 --- a/src/conf/virdomainmomentobjlist.h +++ b/src/conf/virdomainmomentobjlist.h @@ -27,6 +27,10 @@ # include "virconftypes.h" # include "virhash.h" +/* Filter that returns true if a given moment matches the filter flags */ +typedef bool (*virDomainMomentObjListFilter)(virDomainMomentObjPtr obj, + unsigned int flags); + /* Struct that allows tracing hierarchical relationships between * multiple virDomainMoment objects. The opaque type * virDomainMomentObjList then maintains both a hash of these structs @@ -60,4 +64,32 @@ void virDomainMomentMoveChildren(virDomainMomentObjPtr from, void virDomainMomentSetParent(virDomainMomentObjPtr moment, virDomainMomentObjPtr parent); +virDomainMomentObjListPtr virDomainMomentObjListNew(virDomainMomentObjListFilter filter); +void virDomainMomentObjListFree(virDomainMomentObjListPtr moments); + +virDomainMomentObjPtr virDomainMomentAssignDef(virDomainMomentObjListPtr moments, + virDomainMomentDefPtr def); + +int virDomainMomentObjListGetNames(virDomainMomentObjListPtr moments, + virDomainMomentObjPtr from, + char **const names, + int maxnames, + unsigned int flags); +virDomainMomentObjPtr virDomainMomentFindByName(virDomainMomentObjListPtr moments, + const char *name); +int virDomainMomentObjListSize(virDomainMomentObjListPtr moments); +virDomainMomentObjPtr virDomainMomentGetCurrent(virDomainMomentObjListPtr moments); +const char *virDomainMomentGetCurrentName(virDomainMomentObjListPtr moments); +bool virDomainMomentIsCurrentName(virDomainMomentObjListPtr moments, + const char *name); +void virDomainMomentSetCurrent(virDomainMomentObjListPtr moments, + virDomainMomentObjPtr moment); +bool virDomainMomentObjListRemove(virDomainMomentObjListPtr moments, + virDomainMomentObjPtr moment); +void virDomainMomentObjListRemoveAll(virDomainMomentObjListPtr moments); +int virDomainMomentForEach(virDomainMomentObjListPtr moments, + virHashIterator iter, + void *data); +int virDomainMomentUpdateRelations(virDomainMomentObjListPtr moments); + #endif /* LIBVIRT_VIRDOMAINMOMENTOBJLIST_H */ diff --git a/src/conf/virdomainsnapshotobjlist.h b/src/conf/virdomainsnapshotobjlist.h index c36b498751..9daecacfdc 100644 --- a/src/conf/virdomainsnapshotobjlist.h +++ b/src/conf/virdomainsnapshotobjlist.h @@ -27,10 +27,6 @@ # include "virdomainmomentobjlist.h" # include "virbuffer.h" -/* Filter that returns true if a given moment matches the filter flags */ -typedef bool (*virDomainMomentObjListFilter)(virDomainMomentObjPtr obj, - unsigned int flags); - virDomainSnapshotObjListPtr virDomainSnapshotObjListNew(void); void virDomainSnapshotObjListFree(virDomainSnapshotObjListPtr snapshots); @@ -59,7 +55,6 @@ int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots, unsigned int flags); virDomainMomentObjPtr virDomainSnapshotFindByName(virDomainSnapshotObjListPtr snapshots, const char *name); -int virDomainSnapshotObjListSize(virDomainSnapshotObjListPtr snapshots); virDomainMomentObjPtr virDomainSnapshotGetCurrent(virDomainSnapshotObjListPtr snapshots); const char *virDomainSnapshotGetCurrentName(virDomainSnapshotObjListPtr snapshots); bool virDomainSnapshotIsCurrentName(virDomainSnapshotObjListPtr snapshots, @@ -68,7 +63,6 @@ void virDomainSnapshotSetCurrent(virDomainSnapshotObjListPtr snapshots, virDomainMomentObjPtr snapshot); bool virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots, virDomainMomentObjPtr snapshot); -void virDomainSnapshotObjListRemoveAll(virDomainSnapshotObjListPtr snapshots); int virDomainSnapshotForEach(virDomainSnapshotObjListPtr snapshots, virHashIterator iter, void *data); diff --git a/src/conf/virdomainmomentobjlist.c b/src/conf/virdomainmomentobjlist.c index 766d7fe2e4..f987329a6b 100644 --- a/src/conf/virdomainmomentobjlist.c +++ b/src/conf/virdomainmomentobjlist.c @@ -29,10 +29,27 @@ #include "virstring.h" #include "moment_conf.h" +/* FIXME: using virObject would allow us to not need this */ +#include "snapshot_conf.h" +#include "virdomainsnapshotobjlist.h" + #define VIR_FROM_THIS VIR_FROM_DOMAIN VIR_LOG_INIT("conf.virdomainmomentobjlist"); +/* Opaque struct */ +struct _virDomainMomentObjList { + /* name string -> virDomainMomentObj mapping + * for O(1), lockless lookup-by-name */ + virHashTable *objs; + + virDomainMomentObj metaroot; /* Special parent of all root snapshots */ + virDomainMomentObjPtr current; /* The current snapshot, if any */ + + virDomainMomentObjListFilter filter; +}; + + /* Run iter(data) on all direct children of moment, while ignoring all * other entries in moments. Return the number of children * visited. No particular ordering is guaranteed. */ @@ -163,3 +180,342 @@ virDomainMomentMoveChildren(virDomainMomentObjPtr from, from->nchildren = 0; from->first_child = NULL; } + + +static virDomainMomentObjPtr +virDomainMomentObjNew(void) +{ + virDomainMomentObjPtr snapshot; + + if (VIR_ALLOC(snapshot) < 0) + return NULL; + + VIR_DEBUG("obj=%p", snapshot); + + return snapshot; +} + +static void +virDomainMomentObjFree(virDomainMomentObjPtr snapshot) +{ + if (!snapshot) + return; + + VIR_DEBUG("obj=%p", snapshot); + + /* FIXME: Make this polymorphic by inheriting from virObject */ + virDomainSnapshotDefFree(virDomainSnapshotObjGetDef(snapshot)); + VIR_FREE(snapshot); +} + + +/* Add def to the list and return a matching object, or NULL on error */ +virDomainMomentObjPtr +virDomainMomentAssignDef(virDomainMomentObjListPtr moments, + virDomainMomentDefPtr def) +{ + virDomainMomentObjPtr moment; + + if (virHashLookup(moments->objs, def->name) != NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected domain moment %s already exists"), + def->name); + return NULL; + } + + if (!(moment = virDomainMomentObjNew())) + return NULL; + moment->def = def; + + if (virHashAddEntry(moments->objs, moment->def->name, moment) < 0) { + VIR_FREE(moment); + return NULL; + } + + return moment; +} + + +static void +virDomainMomentObjListDataFree(void *payload, + const void *name ATTRIBUTE_UNUSED) +{ + virDomainMomentObjPtr obj = payload; + + virDomainMomentObjFree(obj); +} + + +virDomainMomentObjListPtr +virDomainMomentObjListNew(virDomainMomentObjListFilter filter) +{ + virDomainMomentObjListPtr moments; + + if (VIR_ALLOC(moments) < 0) + return NULL; + moments->objs = virHashCreate(50, virDomainMomentObjListDataFree); + if (!moments->objs) { + VIR_FREE(moments); + return NULL; + } + moments->filter = filter; + return moments; +} + +void +virDomainMomentObjListFree(virDomainMomentObjListPtr moments) +{ + if (!moments) + return; + virHashFree(moments->objs); + VIR_FREE(moments); +} + + +/* Struct and callback for collecting a list of names of moments that + * meet a particular filter. */ +struct virDomainMomentNameData { + char **const names; + int maxnames; + unsigned int flags; + int count; + bool error; + virDomainMomentObjListFilter filter; +}; + +static int virDomainMomentObjListCopyNames(void *payload, + const void *name ATTRIBUTE_UNUSED, + void *opaque) +{ + virDomainMomentObjPtr obj = payload; + struct virDomainMomentNameData *data = opaque; + + if (data->error) + return 0; + /* Caller already sanitized flags. Filtering on DESCENDANTS was + * done by choice of iteration in the caller. */ + if ((data->flags & VIR_DOMAIN_SNAPSHOT_LIST_LEAVES) && obj->nchildren) + return 0; + if ((data->flags & VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES) && !obj->nchildren) + return 0; + + if (!data->filter(obj, data->flags)) + return 0; + + if (data->names && data->count < data->maxnames && + VIR_STRDUP(data->names[data->count], obj->def->name) < 0) { + data->error = true; + return 0; + } + data->count++; + return 0; +} + + +int +virDomainMomentObjListGetNames(virDomainMomentObjListPtr moments, + virDomainMomentObjPtr from, + char **const names, + int maxnames, + unsigned int flags) +{ + struct virDomainMomentNameData data = { names, maxnames, flags, 0, + false, moments->filter }; + size_t i; + + if (!from) { + /* LIST_ROOTS and LIST_DESCENDANTS have the same bit value, + * but opposite semantics. Toggle here to get the correct + * traversal on the metaroot. */ + flags ^= VIR_DOMAIN_SNAPSHOT_LIST_ROOTS; + from = &moments->metaroot; + } + + /* We handle LIST_ROOT/LIST_DESCENDANTS and LIST_TOPOLOGICAL directly, + * mask those bits out to determine when we must use the filter callback. */ + data.flags &= ~(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS | + VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL); + + /* If this common code is being used, we assume that all snapshots + * have metadata, and thus can handle METADATA up front as an + * all-or-none filter. XXX This might not always be true, if we + * add the ability to track qcow2 internal snapshots without the + * use of metadata. */ + if ((data.flags & VIR_DOMAIN_SNAPSHOT_FILTERS_METADATA) == + VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA) + return 0; + data.flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_METADATA; + + if (flags & VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS) { + /* We could just always do a topological visit; but it is + * possible to optimize for less stack usage and time when a + * simpler full hashtable visit or counter will do. */ + if (from->def || (names && + (flags & VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL))) + virDomainMomentForEachDescendant(from, + virDomainMomentObjListCopyNames, + &data); + else if (names || data.flags) + virHashForEach(moments->objs, virDomainMomentObjListCopyNames, + &data); + else + data.count = virHashSize(moments->objs); + } else if (names || data.flags) { + virDomainMomentForEachChild(from, + virDomainMomentObjListCopyNames, &data); + } else { + data.count = from->nchildren; + } + + if (data.error) { + for (i = 0; i < data.count; i++) + VIR_FREE(names[i]); + return -1; + } + + return data.count; +} + + +virDomainMomentObjPtr +virDomainMomentFindByName(virDomainMomentObjListPtr moments, + const char *name) +{ + return name ? virHashLookup(moments->objs, name) : &moments->metaroot; +} + + +/* Return the current moment, or NULL */ +virDomainMomentObjPtr +virDomainMomentGetCurrent(virDomainMomentObjListPtr moments) +{ + return moments->current; +} + + +/* Return the current moment's name, or NULL */ +const char * +virDomainMomentGetCurrentName(virDomainMomentObjListPtr moments) +{ + if (moments->current) + return moments->current->def->name; + return NULL; +} + + +/* Return true if name matches the current moment */ +bool +virDomainMomentIsCurrentName(virDomainMomentObjListPtr moments, + const char *name) +{ + return moments->current && STREQ(moments->current->def->name, name); +} + + +/* Update the current moment, using NULL if no current remains */ +void +virDomainMomentSetCurrent(virDomainMomentObjListPtr moments, + virDomainMomentObjPtr moment) +{ + moments->current = moment; +} + + +/* Return the number of moments in the list */ +int +virDomainMomentObjListSize(virDomainMomentObjListPtr moments) +{ + return virHashSize(moments->objs); +} + + +/* Remove moment from the list; return true if it was current */ +bool +virDomainMomentObjListRemove(virDomainMomentObjListPtr moments, + virDomainMomentObjPtr moment) +{ + bool ret = moments->current == moment; + + virHashRemoveEntry(moments->objs, moment->def->name); + if (ret) + moments->current = NULL; + return ret; +} + + +/* Remove all moments tracked in the list */ +void +virDomainMomentObjListRemoveAll(virDomainMomentObjListPtr moments) +{ + virHashRemoveAll(moments->objs); + virDomainMomentDropChildren(&moments->metaroot); +} + + +/* Call iter on each member of the list, in unspecified order */ +int +virDomainMomentForEach(virDomainMomentObjListPtr moments, + virHashIterator iter, + void *data) +{ + return virHashForEach(moments->objs, iter, data); +} + + +/* Struct and callback function used as a hash table callback; each call + * inspects the pre-existing moment->def->parent field, and adjusts + * the moment->parent field as well as the parent's child fields to + * wire up the hierarchical relations for the given snapshot. The error + * indicator gets set if a parent is missing or a requested parent would + * cause a circular parent chain. */ +struct moment_set_relation { + virDomainMomentObjListPtr moments; + int err; +}; +static int +virDomainMomentSetRelations(void *payload, + const void *name ATTRIBUTE_UNUSED, + void *data) +{ + virDomainMomentObjPtr obj = payload; + struct moment_set_relation *curr = data; + virDomainMomentObjPtr tmp; + virDomainMomentObjPtr parent; + + parent = virDomainMomentFindByName(curr->moments, obj->def->parent); + if (!parent) { + curr->err = -1; + parent = &curr->moments->metaroot; + VIR_WARN("snapshot %s lacks parent", obj->def->name); + } else { + tmp = parent; + while (tmp && tmp->def) { + if (tmp == obj) { + curr->err = -1; + parent = &curr->moments->metaroot; + VIR_WARN("snapshot %s in circular chain", obj->def->name); + break; + } + tmp = tmp->parent; + } + } + virDomainMomentSetParent(obj, parent); + return 0; +} + + +/* Populate parent link and child count of all snapshots, with all + * assigned defs having relations starting as 0/NULL. Return 0 on + * success, -1 if a parent is missing or if a circular relationship + * was requested. */ +int +virDomainMomentUpdateRelations(virDomainMomentObjListPtr moments) +{ + struct moment_set_relation act = { moments, 0 }; + + virDomainMomentDropChildren(&moments->metaroot); + virHashForEach(moments->objs, virDomainMomentSetRelations, &act); + if (act.err) + moments->current = NULL; + return act.err; +} diff --git a/src/conf/virdomainsnapshotobjlist.c b/src/conf/virdomainsnapshotobjlist.c index 8ecb131176..31ed1c672d 100644 --- a/src/conf/virdomainsnapshotobjlist.c +++ b/src/conf/virdomainsnapshotobjlist.c @@ -35,12 +35,7 @@ VIR_LOG_INIT("conf.virdomainsnapshotobjlist"); struct _virDomainSnapshotObjList { - /* name string -> virDomainMomentObj mapping - * for O(1), lockless lookup-by-name */ - virHashTable *objs; - - virDomainMomentObj metaroot; /* Special parent of all root snapshots */ - virDomainMomentObjPtr current; /* The current snapshot, if any */ + virDomainMomentObjListPtr base; }; @@ -72,7 +67,7 @@ virDomainSnapshotObjListParse(const char *xmlStr, _("incorrect flags for bulk parse")); return -1; } - if (virDomainSnapshotObjListSize(snapshots)) { + if (virDomainMomentObjListSize(snapshots->base)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("bulk define of snapshots only possible with " "no existing snapshot")); @@ -143,7 +138,7 @@ virDomainSnapshotObjListParse(const char *xmlStr, if (ret < 0) { /* There were no snapshots before this call; so on error, just * blindly delete anything created before the failure. */ - virDomainSnapshotObjListRemoveAll(snapshots); + virDomainMomentObjListRemoveAll(snapshots->base); } xmlXPathFreeContext(ctxt); xmlFreeDoc(xml); @@ -211,55 +206,14 @@ virDomainSnapshotObjListFormat(virBufferPtr buf, } -/* Snapshot Obj functions */ -static virDomainMomentObjPtr virDomainMomentObjNew(void) +virDomainMomentObjPtr +virDomainSnapshotAssignDef(virDomainSnapshotObjListPtr snapshots, + virDomainSnapshotDefPtr def) { - virDomainMomentObjPtr snapshot; - - if (VIR_ALLOC(snapshot) < 0) - return NULL; - - VIR_DEBUG("obj=%p", snapshot); - - return snapshot; -} - -static void virDomainMomentObjFree(virDomainMomentObjPtr snapshot) -{ - if (!snapshot) - return; - - VIR_DEBUG("obj=%p", snapshot); - - virDomainSnapshotDefFree(virDomainSnapshotObjGetDef(snapshot)); - VIR_FREE(snapshot); + return virDomainMomentAssignDef(snapshots->base, &def->common); } -virDomainMomentObjPtr virDomainSnapshotAssignDef(virDomainSnapshotObjListPtr snapshots, - virDomainSnapshotDefPtr def) -{ - virDomainMomentObjPtr snap; - - if (virHashLookup(snapshots->objs, def->common.name) != NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected domain snapshot %s already exists"), - def->common.name); - return NULL; - } - - if (!(snap = virDomainMomentObjNew())) - return NULL; - snap->def = &def->common; - - if (virHashAddEntry(snapshots->objs, snap->def->name, snap) < 0) { - VIR_FREE(snap); - return NULL; - } - - return snap; -} -/* Snapshot Obj List functions */ static bool virDomainSnapshotFilter(virDomainMomentObjPtr obj, unsigned int flags) @@ -292,76 +246,30 @@ virDomainSnapshotFilter(virDomainMomentObjPtr obj, } -static void -virDomainSnapshotObjListDataFree(void *payload, - const void *name ATTRIBUTE_UNUSED) -{ - virDomainMomentObjPtr obj = payload; - - virDomainMomentObjFree(obj); -} - virDomainSnapshotObjListPtr virDomainSnapshotObjListNew(void) { virDomainSnapshotObjListPtr snapshots; + if (VIR_ALLOC(snapshots) < 0) return NULL; - snapshots->objs = virHashCreate(50, virDomainSnapshotObjListDataFree); - if (!snapshots->objs) { + snapshots->base = virDomainMomentObjListNew(virDomainSnapshotFilter); + if (!snapshots->base) { VIR_FREE(snapshots); return NULL; } return snapshots; } + void virDomainSnapshotObjListFree(virDomainSnapshotObjListPtr snapshots) { - if (!snapshots) - return; - virHashFree(snapshots->objs); + virDomainMomentObjListFree(snapshots->base); VIR_FREE(snapshots); } -struct virDomainMomentNameData { - char **const names; - int maxnames; - unsigned int flags; - int count; - bool error; - virDomainMomentObjListFilter filter; -}; - -static int virDomainMomentObjListCopyNames(void *payload, - const void *name ATTRIBUTE_UNUSED, - void *opaque) -{ - virDomainMomentObjPtr obj = payload; - struct virDomainMomentNameData *data = opaque; - - if (data->error) - return 0; - /* Caller already sanitized flags. Filtering on DESCENDANTS was - * done by choice of iteration in the caller. */ - if ((data->flags & VIR_DOMAIN_SNAPSHOT_LIST_LEAVES) && obj->nchildren) - return 0; - if ((data->flags & VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES) && !obj->nchildren) - return 0; - - if (data->filter(obj, data->flags)) - return 0; - - if (data->names && data->count < data->maxnames && - VIR_STRDUP(data->names[data->count], obj->def->name) < 0) { - data->error = true; - return 0; - } - data->count++; - return 0; -} - int virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots, virDomainMomentObjPtr from, @@ -369,73 +277,29 @@ virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots, int maxnames, unsigned int flags) { - struct virDomainMomentNameData data = { names, maxnames, flags, 0, - false, virDomainSnapshotFilter }; - size_t i; - - if (!from) { - /* LIST_ROOTS and LIST_DESCENDANTS have the same bit value, - * but opposite semantics. Toggle here to get the correct - * traversal on the metaroot. */ - flags ^= VIR_DOMAIN_SNAPSHOT_LIST_ROOTS; - from = &snapshots->metaroot; - } - - /* We handle LIST_ROOT/LIST_DESCENDANTS and LIST_TOPOLOGICAL directly, - * mask those bits out to determine when we must use the filter callback. */ - data.flags &= ~(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS | - VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL); - /* If this common code is being used, we assume that all snapshots * have metadata, and thus can handle METADATA up front as an * all-or-none filter. XXX This might not always be true, if we * add the ability to track qcow2 internal snapshots without the * use of metadata. */ - if ((data.flags & VIR_DOMAIN_SNAPSHOT_FILTERS_METADATA) == + if ((flags & VIR_DOMAIN_SNAPSHOT_FILTERS_METADATA) == VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA) return 0; - data.flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_METADATA; + flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_METADATA; /* For ease of coding the visitor, it is easier to zero each group * where all of the bits are set. */ - if ((data.flags & VIR_DOMAIN_SNAPSHOT_FILTERS_LEAVES) == + if ((flags & VIR_DOMAIN_SNAPSHOT_FILTERS_LEAVES) == VIR_DOMAIN_SNAPSHOT_FILTERS_LEAVES) - data.flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_LEAVES; - if ((data.flags & VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS) == + flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_LEAVES; + if ((flags & VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS) == VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS) - data.flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS; - if ((data.flags & VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION) == + flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS; + if ((flags & VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION) == VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION) - data.flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION; - - if (flags & VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS) { - /* We could just always do a topological visit; but it is - * possible to optimize for less stack usage and time when a - * simpler full hashtable visit or counter will do. */ - if (from->def || (names && - (flags & VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL))) - virDomainMomentForEachDescendant(from, - virDomainMomentObjListCopyNames, - &data); - else if (names || data.flags) - virHashForEach(snapshots->objs, virDomainMomentObjListCopyNames, - &data); - else - data.count = virHashSize(snapshots->objs); - } else if (names || data.flags) { - virDomainMomentForEachChild(from, - virDomainMomentObjListCopyNames, &data); - } else { - data.count = from->nchildren; - } - - if (data.error) { - for (i = 0; i < data.count; i++) - VIR_FREE(names[i]); - return -1; - } - - return data.count; + flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION; + return virDomainMomentObjListGetNames(snapshots->base, from, names, + maxnames, flags); } int @@ -446,19 +310,12 @@ virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots, return virDomainSnapshotObjListGetNames(snapshots, from, NULL, 0, flags); } + virDomainMomentObjPtr virDomainSnapshotFindByName(virDomainSnapshotObjListPtr snapshots, const char *name) { - return name ? virHashLookup(snapshots->objs, name) : &snapshots->metaroot; -} - - -/* Return the number of objects currently in the list */ -int -virDomainSnapshotObjListSize(virDomainSnapshotObjListPtr snapshots) -{ - return virHashSize(snapshots->objs); + return virDomainMomentFindByName(snapshots->base, name); } @@ -466,7 +323,7 @@ virDomainSnapshotObjListSize(virDomainSnapshotObjListPtr snapshots) virDomainMomentObjPtr virDomainSnapshotGetCurrent(virDomainSnapshotObjListPtr snapshots) { - return snapshots->current; + return virDomainMomentGetCurrent(snapshots->base); } @@ -474,9 +331,7 @@ virDomainSnapshotGetCurrent(virDomainSnapshotObjListPtr snapshots) const char * virDomainSnapshotGetCurrentName(virDomainSnapshotObjListPtr snapshots) { - if (snapshots->current) - return snapshots->current->def->name; - return NULL; + return virDomainMomentGetCurrentName(snapshots->base); } @@ -485,7 +340,7 @@ bool virDomainSnapshotIsCurrentName(virDomainSnapshotObjListPtr snapshots, const char *name) { - return snapshots->current && STREQ(snapshots->current->def->name, name); + return virDomainMomentIsCurrentName(snapshots->base, name); } @@ -494,7 +349,7 @@ void virDomainSnapshotSetCurrent(virDomainSnapshotObjListPtr snapshots, virDomainMomentObjPtr snapshot) { - snapshots->current = snapshot; + virDomainMomentSetCurrent(snapshots->base, snapshot); } @@ -502,19 +357,7 @@ virDomainSnapshotSetCurrent(virDomainSnapshotObjListPtr snapshots, bool virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots, virDomainMomentObjPtr snapshot) { - bool ret = snapshots->current == snapshot; - virHashRemoveEntry(snapshots->objs, snapshot->def->name); - if (ret) - snapshots->current = NULL; - return ret; -} - -/* Remove all snapshots tracked in the list */ -void -virDomainSnapshotObjListRemoveAll(virDomainSnapshotObjListPtr snapshots) -{ - virHashRemoveAll(snapshots->objs); - virDomainMomentDropChildren(&snapshots->metaroot); + return virDomainMomentObjListRemove(snapshots->base, snapshot); } @@ -523,51 +366,10 @@ virDomainSnapshotForEach(virDomainSnapshotObjListPtr snapshots, virHashIterator iter, void *data) { - return virHashForEach(snapshots->objs, iter, data); + return virDomainMomentForEach(snapshots->base, iter, data); } -/* Struct and callback function used as a hash table callback; each call - * inspects the pre-existing snapshot->def->parent field, and adjusts - * the snapshot->parent field as well as the parent's child fields to - * wire up the hierarchical relations for the given snapshot. The error - * indicator gets set if a parent is missing or a requested parent would - * cause a circular parent chain. */ -struct moment_set_relation { - virDomainSnapshotObjListPtr snapshots; - int err; -}; -static int -virDomainMomentSetRelations(void *payload, - const void *name ATTRIBUTE_UNUSED, - void *data) -{ - virDomainMomentObjPtr obj = payload; - struct moment_set_relation *curr = data; - virDomainMomentObjPtr tmp; - virDomainMomentObjPtr parent; - - parent = virDomainSnapshotFindByName(curr->snapshots, obj->def->parent); - if (!parent) { - curr->err = -1; - parent = &curr->snapshots->metaroot; - VIR_WARN("snapshot %s lacks parent", obj->def->name); - } else { - tmp = parent; - while (tmp && tmp->def) { - if (tmp == obj) { - curr->err = -1; - parent = &curr->snapshots->metaroot; - VIR_WARN("snapshot %s in circular chain", obj->def->name); - break; - } - tmp = tmp->parent; - } - } - virDomainMomentSetParent(obj, parent); - return 0; -} - /* Populate parent link and child count of all snapshots, with all * assigned defs having relations starting as 0/NULL. Return 0 on * success, -1 if a parent is missing or if a circular relationship @@ -575,13 +377,7 @@ virDomainMomentSetRelations(void *payload, int virDomainSnapshotUpdateRelations(virDomainSnapshotObjListPtr snapshots) { - struct moment_set_relation act = { snapshots, 0 }; - - virDomainMomentDropChildren(&snapshots->metaroot); - virHashForEach(snapshots->objs, virDomainMomentSetRelations, &act); - if (act.err) - snapshots->current = NULL; - return act.err; + return virDomainMomentUpdateRelations(snapshots->base); } -- 2.20.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list