diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am
index f656725e3a..5035b9b524 100644
--- a/src/conf/Makefile.inc.am
+++ b/src/conf/Makefile.inc.am
@@ -36,6 +36,8 @@ DOMAIN_CONF_SOURCES = \
conf/numa_conf.c \
conf/numa_conf.h \
conf/virconftypes.h \
+ conf/virdomaincheckpointobjlist.c \
+ conf/virdomaincheckpointobjlist.h \
conf/virdomainobjlist.c \
conf/virdomainobjlist.h \
conf/virdomainmomentobjlist.c \
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
index fe3f0af14f..e8e9b6c314 100644
--- a/src/conf/virconftypes.h
+++ b/src/conf/virconftypes.h
@@ -105,6 +105,12 @@ typedef virDomainBlockIoTuneInfo *virDomainBlockIoTuneInfoPtr;
typedef struct _virDomainCheckpointDef virDomainCheckpointDef;
typedef virDomainCheckpointDef *virDomainCheckpointDefPtr;
+typedef struct _virDomainCheckpointObj virDomainCheckpointObj;
+typedef virDomainCheckpointObj *virDomainCheckpointObjPtr;
+
+typedef struct _virDomainCheckpointObjList virDomainCheckpointObjList;
+typedef virDomainCheckpointObjList *virDomainCheckpointObjListPtr;
+
typedef struct _virDomainChrDef virDomainChrDef;
typedef virDomainChrDef *virDomainChrDefPtr;
diff --git a/src/conf/virdomaincheckpointobjlist.c b/src/conf/virdomaincheckpointobjlist.c
new file mode 100644
index 0000000000..03aad9f5ef
--- /dev/null
+++ b/src/conf/virdomaincheckpointobjlist.c
@@ -0,0 +1,243 @@
+/*
+ * virdomaincheckpointobjlist.c: handle a tree of checkpoint objects
+ * (derived from virdomainsnapshotobjlist.c)
+ *
+ * Copyright (C) 2006-2019 Red Hat, Inc.
+ * Copyright (C) 2006-2008 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * .
+ */
+
+#include
+
+#include "internal.h"
+#include "virdomaincheckpointobjlist.h"
+#include "checkpoint_conf.h"
+#include "virlog.h"
+#include "virerror.h"
+#include "datatypes.h"
+#include "virstring.h"
+#include "viralloc.h"
+
+#define VIR_FROM_THIS VIR_FROM_DOMAIN_CHECKPOINT
+
+VIR_LOG_INIT("conf.virdomaincheckpointobjlist");
+
+struct _virDomainCheckpointObjList {
+ virDomainMomentObjListPtr base;
+};
+
+virDomainMomentObjPtr
+virDomainCheckpointAssignDef(virDomainCheckpointObjListPtr checkpoints,
+ virDomainCheckpointDefPtr def)
+{
+ return virDomainMomentAssignDef(checkpoints->base, &def->parent);
+}
+
+
+static bool
+virDomainCheckpointFilter(virDomainMomentObjPtr obj ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ /* For now, we have no further filters than what the common code handles. */
+ virCheckFlags(0, false);
+ return true;
+}
+
+
+virDomainCheckpointObjListPtr
+virDomainCheckpointObjListNew(void)
+{
+ virDomainCheckpointObjListPtr checkpoints;
+
+ if (VIR_ALLOC(checkpoints) < 0)
+ return NULL;
+ checkpoints->base = virDomainMomentObjListNew();
+ if (!checkpoints->base) {
+ VIR_FREE(checkpoints);
+ return NULL;
+ }
+ return checkpoints;
+}
+
+
+void
+virDomainCheckpointObjListFree(virDomainCheckpointObjListPtr checkpoints)
+{
+ if (!checkpoints)
+ return;
+ virDomainMomentObjListFree(checkpoints->base);
+ VIR_FREE(checkpoints);
+}
+
+
+static int
+virDomainCheckpointObjListGetNames(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr from,
+ char **const names,
+ int maxnames,
+ unsigned int flags)
+{
+ /* We intentionally chose our public flags to match the common flags */
+ verify(VIR_DOMAIN_CHECKPOINT_LIST_ROOTS ==
+ (int) VIR_DOMAIN_MOMENT_LIST_ROOTS);
+ verify(VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL ==
+ (int) VIR_DOMAIN_MOMENT_LIST_TOPOLOGICAL);
+ verify(VIR_DOMAIN_CHECKPOINT_LIST_LEAVES ==
+ (int) VIR_DOMAIN_MOMENT_LIST_LEAVES);
+ verify(VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES ==
+ (int) VIR_DOMAIN_MOMENT_LIST_NO_LEAVES);
+
+ return virDomainMomentObjListGetNames(checkpoints->base, from, names,
+ maxnames, flags,
+ virDomainCheckpointFilter, 0);
+}
+
+
+virDomainMomentObjPtr
+virDomainCheckpointFindByName(virDomainCheckpointObjListPtr checkpoints,
+ const char *name)
+{
+ return virDomainMomentFindByName(checkpoints->base, name);
+}
+
+
+/* Return the current checkpoint, or NULL */
+virDomainMomentObjPtr
+virDomainCheckpointGetCurrent(virDomainCheckpointObjListPtr checkpoints)
+{
+ return virDomainMomentGetCurrent(checkpoints->base);
+}
+
+
+/* Return the current checkpoint's name, or NULL */
+const char *
+virDomainCheckpointGetCurrentName(virDomainCheckpointObjListPtr checkpoints)
+{
+ return virDomainMomentGetCurrentName(checkpoints->base);
+}
+
+
+/* Update the current checkpoint, using NULL if no current remains */
+void
+virDomainCheckpointSetCurrent(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr checkpoint)
+{
+ virDomainMomentSetCurrent(checkpoints->base, checkpoint);
+}
+
+
+/* Remove checkpoint from the list; return true if it was current */
+bool
+virDomainCheckpointObjListRemove(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr checkpoint)
+{
+ return virDomainMomentObjListRemove(checkpoints->base, checkpoint);
+}
+
+
+/* Remove all checkpoints tracked in the list */
+void
+virDomainCheckpointObjListRemoveAll(virDomainCheckpointObjListPtr checkpoints)
+{
+ return virDomainMomentObjListRemoveAll(checkpoints->base);
+}
+
+
+int
+virDomainCheckpointForEach(virDomainCheckpointObjListPtr checkpoints,
+ virHashIterator iter,
+ void *data)
+{
+ return virDomainMomentForEach(checkpoints->base, iter, data);
+}
+
+
+/* Populate parent link of a given checkpoint. */
+void
+virDomainCheckpointLinkParent(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr chk)
+{
+ return virDomainMomentLinkParent(checkpoints->base, chk);
+}
+
+
+/* Populate parent link and child count of all checkpoints, 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. Set leaf to the end of the chain, if there is
+ * exactly one such leaf. */
+int
+virDomainCheckpointUpdateRelations(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr *leaf)
+{
+ int ret = virDomainMomentUpdateRelations(checkpoints->base);
+
+ if (ret == 0)
+ *leaf = virDomainMomentFindLeaf(checkpoints->base);
+ return ret;
+}
+
+
+int
+virDomainCheckpointCheckCycles(virDomainCheckpointObjListPtr checkpoints,
+ virDomainCheckpointDefPtr def,
+ const char *domname)
+{
+ return virDomainMomentCheckCycles(checkpoints->base, &def->parent, domname);
+}
+
+
+int
+virDomainListCheckpoints(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr from,
+ virDomainPtr dom,
+ virDomainCheckpointPtr **chks,
+ unsigned int flags)
+{
+ int count = virDomainCheckpointObjListGetNames(checkpoints, from, NULL,
+ 0, flags);
+ virDomainCheckpointPtr *list = NULL;
+ char **names;
+ int ret = -1;
+ size_t i;
+
+ if (!chks || count < 0)
+ return count;
+ if (VIR_ALLOC_N(names, count) < 0 ||
+ VIR_ALLOC_N(list, count + 1) < 0)
+ goto cleanup;
+
+ if (virDomainCheckpointObjListGetNames(checkpoints, from, names, count,
+ flags) < 0)
+ goto cleanup;
+ for (i = 0; i < count; i++)
+ if ((list[i] = virGetDomainCheckpoint(dom, names[i])) == NULL)
+ goto cleanup;
+
+ ret = count;
+ *chks = list;
+
+ cleanup:
+ for (i = 0; i < count; i++)
+ VIR_FREE(names[i]);
+ VIR_FREE(names);
+ if (ret < 0 && list) {
+ for (i = 0; i < count; i++)
+ virObjectUnref(list[i]);
+ VIR_FREE(list);
+ }
+ return ret;
+}
diff --git a/src/conf/virdomaincheckpointobjlist.h b/src/conf/virdomaincheckpointobjlist.h
new file mode 100644
index 0000000000..2005177434
--- /dev/null
+++ b/src/conf/virdomaincheckpointobjlist.h
@@ -0,0 +1,96 @@
+/*
+ * virdomaincheckpointobjlist.h: handle a tree of checkpoint objects
+ * (derived from virdomainsnapshotobjlist.h)
+ *
+ * Copyright (C) 2006-2019 Red Hat, Inc.
+ * Copyright (C) 2006-2008 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * .
+ */
+
+#pragma once
+
+#include "internal.h"
+#include "virdomainmomentobjlist.h"
+#include "virbuffer.h"
+
+virDomainCheckpointObjListPtr
+virDomainCheckpointObjListNew(void);
+
+void
+virDomainCheckpointObjListFree(virDomainCheckpointObjListPtr checkpoints);
+
+virDomainMomentObjPtr
+virDomainCheckpointAssignDef(virDomainCheckpointObjListPtr checkpoints,
+ virDomainCheckpointDefPtr def);
+
+virDomainMomentObjPtr
+virDomainCheckpointFindByName(virDomainCheckpointObjListPtr checkpoints,
+ const char *name);
+
+virDomainMomentObjPtr
+virDomainCheckpointGetCurrent(virDomainCheckpointObjListPtr checkpoints);
+
+const char *
+virDomainCheckpointGetCurrentName(virDomainCheckpointObjListPtr checkpoints);
+
+void
+virDomainCheckpointSetCurrent(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr checkpoint);
+
+bool
+virDomainCheckpointObjListRemove(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr checkpoint);
+
+void
+virDomainCheckpointObjListRemoveAll(virDomainCheckpointObjListPtr checkpoints);
+
+int
+virDomainCheckpointForEach(virDomainCheckpointObjListPtr checkpoints,
+ virHashIterator iter,
+ void *data);
+
+void
+virDomainCheckpointLinkParent(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr chk);
+
+int
+virDomainCheckpointUpdateRelations(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr *leaf);
+
+int
+virDomainCheckpointCheckCycles(virDomainCheckpointObjListPtr checkpoints,
+ virDomainCheckpointDefPtr def,
+ const char *domname);
+
+#define VIR_DOMAIN_CHECKPOINT_FILTERS_LEAVES \
+ (VIR_DOMAIN_CHECKPOINT_LIST_LEAVES | \
+ VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES)
+
+#define VIR_DOMAIN_CHECKPOINT_FILTERS_ALL \
+ (VIR_DOMAIN_CHECKPOINT_FILTERS_LEAVES)
+
+int
+virDomainListCheckpoints(virDomainCheckpointObjListPtr checkpoints,
+ virDomainMomentObjPtr from,
+ virDomainPtr dom,
+ virDomainCheckpointPtr **objs,
+ unsigned int flags);
+
+static inline virDomainCheckpointDefPtr
+virDomainCheckpointObjGetDef(virDomainMomentObjPtr obj)
+{
+ return (virDomainCheckpointDefPtr) obj->def;
+}
diff --git a/src/conf/virdomainmomentobjlist.c b/src/conf/virdomainmomentobjlist.c
index c8dd8f8e01..d02efb420a 100644
--- a/src/conf/virdomainmomentobjlist.c
+++ b/src/conf/virdomainmomentobjlist.c
@@ -31,8 +31,8 @@
#include "viralloc.h"
/* FIXME: using virObject would allow us to not need this */
-#include "snapshot_conf.h"
#include "virdomainsnapshotobjlist.h"
+#include "virdomaincheckpointobjlist.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN
@@ -589,3 +589,18 @@ virDomainMomentCheckCycles(virDomainMomentObjListPtr list,
}
return 0;
}
+
+/* If there is exactly one leaf node, return that node. */
+virDomainMomentObjPtr
+virDomainMomentFindLeaf(virDomainMomentObjListPtr list)
+{
+ virDomainMomentObjPtr moment = &list->metaroot;
+
+ if (moment->nchildren != 1)
+ return NULL;
+ while (moment->nchildren == 1)
+ moment = moment->first_child;
+ if (moment->nchildren == 0)
+ return moment;
+ return NULL;
+}
diff --git a/src/conf/virdomainmomentobjlist.h b/src/conf/virdomainmomentobjlist.h
index 5b73175e8d..75198909ba 100644
--- a/src/conf/virdomainmomentobjlist.h
+++ b/src/conf/virdomainmomentobjlist.h
@@ -121,3 +121,4 @@ int virDomainMomentUpdateRelations(virDomainMomentObjListPtr moments);
int virDomainMomentCheckCycles(virDomainMomentObjListPtr list,
virDomainMomentDefPtr def,
const char *domname);
+virDomainMomentObjPtr virDomainMomentFindLeaf(virDomainMomentObjListPtr list);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 36eb20f64f..aec174d874 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -983,6 +983,22 @@ virChrdevFree;
virChrdevOpen;
+# conf/virdomaincheckpointobjlist.h
+virDomainCheckpointAssignDef;
+virDomainCheckpointFindByName;
+virDomainCheckpointForEach;
+virDomainCheckpointGetCurrent;
+virDomainCheckpointGetCurrentName;
+virDomainCheckpointLinkParent;
+virDomainCheckpointObjListFree;
+virDomainCheckpointObjListNew;
+virDomainCheckpointObjListRemove;
+virDomainCheckpointObjListRemoveAll;
+virDomainCheckpointSetCurrent;
+virDomainCheckpointUpdateRelations;
+virDomainListCheckpoints;
+
+
# conf/virdomainmomentobjlist.h
virDomainMomentDropChildren;
virDomainMomentDropParent;