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(a)redhat.com>
---
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