<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Wed, Jun 13, 2018 at 7:42 PM Eric Blake <<a href="mailto:eblake@redhat.com">eblake@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Prepare for introducing a bunch of new public APIs related to<br>
backup checkpoints by first introducing a new internal type<br>
and errors associated with that type.  Checkpoints are modeled<br>
heavily after virDomainSnapshotPtr (both represent a point in<br>
time of the guest), although a snapshot exists with the intent<br>
of rolling back to that state, while a checkpoint exists to<br>
make it possible to create an incremental backup at a later<br>
time.<br>
<br>
Signed-off-by: Eric Blake <<a href="mailto:eblake@redhat.com" target="_blank">eblake@redhat.com</a>><br>
---<br>
 include/libvirt/libvirt-domain-snapshot.h |  8 ++--<br>
 include/libvirt/libvirt.h                 |  2 +<br>
 include/libvirt/virterror.h               |  5 ++-<br>
 src/datatypes.c                           | 62 ++++++++++++++++++++++++++++++-<br>
 src/datatypes.h                           | 31 +++++++++++++++-<br>
 src/libvirt_private.syms                  |  2 +<br>
 src/util/virerror.c                       | 15 +++++++-<br>
 7 files changed, 118 insertions(+), 7 deletions(-)<br>
<br>
diff --git a/include/libvirt/libvirt-domain-snapshot.h b/include/libvirt/libvirt-domain-snapshot.h<br>
index e5a893a767..ff1e890cfc 100644<br>
--- a/include/libvirt/libvirt-domain-snapshot.h<br>
+++ b/include/libvirt/libvirt-domain-snapshot.h<br>
@@ -31,15 +31,17 @@<br>
 /**<br>
  * virDomainSnapshot:<br>
  *<br>
- * a virDomainSnapshot is a private structure representing a snapshot of<br>
- * a domain.<br>
+ * A virDomainSnapshot is a private structure representing a snapshot of<br>
+ * a domain.  A snapshot captures the state of the domain at a point in<br>
+ * time, with the intent that the guest can be reverted back to that<br>
+ * state at a later time.<br></blockquote><div><br></div><div>The extra context is very nice...</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  */<br>
 typedef struct _virDomainSnapshot virDomainSnapshot;<br>
<br>
 /**<br>
  * virDomainSnapshotPtr:<br>
  *<br>
- * a virDomainSnapshotPtr is pointer to a virDomainSnapshot private structure,<br>
+ * A virDomainSnapshotPtr is pointer to a virDomainSnapshot private structure,<br>
  * and is the type used to reference a domain snapshot in the API.<br>
  */<br></blockquote><div><br></div><div><div>But I think users of this API would like to find it here, explaining the public</div><div>type.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 typedef virDomainSnapshot *virDomainSnapshotPtr;<br>
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h<br>
index 36f6d60775..26887a40e7 100644<br>
--- a/include/libvirt/libvirt.h<br>
+++ b/include/libvirt/libvirt.h<br>
@@ -36,6 +36,8 @@ extern "C" {<br>
 # include <libvirt/libvirt-common.h><br>
 # include <libvirt/libvirt-host.h><br>
 # include <libvirt/libvirt-domain.h><br>
+typedef struct _virDomainCheckpoint virDomainCheckpoint;<br>
+typedef virDomainCheckpoint *virDomainCheckpointPtr;<br>
 # include <libvirt/libvirt-domain-snapshot.h><br>
 # include <libvirt/libvirt-event.h><br>
 # include <libvirt/libvirt-interface.h><br>
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h<br>
index 5e58b6a3f9..87ac16be0b 100644<br>
--- a/include/libvirt/virterror.h<br>
+++ b/include/libvirt/virterror.h<br>
@@ -4,7 +4,7 @@<br>
  * Description: Provides the interfaces of the libvirt library to handle<br>
  *              errors raised while using the library.<br>
  *<br>
- * Copyright (C) 2006-2016 Red Hat, Inc.<br>
+ * Copyright (C) 2006-2018 Red Hat, Inc.<br>
  *<br>
  * This library is free software; you can redistribute it and/or<br>
  * modify it under the terms of the GNU Lesser General Public<br>
@@ -133,6 +133,7 @@ typedef enum {<br>
     VIR_FROM_PERF = 65,         /* Error from perf */<br>
     VIR_FROM_LIBSSH = 66,       /* Error from libssh connection transport */<br>
     VIR_FROM_RESCTRL = 67,      /* Error from resource control */<br>
+    VIR_FROM_DOMAIN_CHECKPOINT = 68,/* Error from domain checkpoint */<br>
<br>
 # ifdef VIR_ENUM_SENTINELS<br>
     VIR_ERR_DOMAIN_LAST<br>
@@ -321,6 +322,8 @@ typedef enum {<br>
                                            to guest-sync command (DEPRECATED)*/<br>
     VIR_ERR_LIBSSH = 98,                /* error in libssh transport driver */<br>
     VIR_ERR_DEVICE_MISSING = 99,        /* fail to find the desired device */<br>
+    VIR_ERR_INVALID_DOMAIN_CHECKPOINT = 100,/* invalid domain checkpoint */<br></blockquote><div><br></div><div>What is invalid checkpoint? It would be nice if there would not be</div><div>such thing.</div><div><br></div><div>Also the comment does not add anything.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    VIR_ERR_NO_DOMAIN_CHECKPOINT = 101, /* domain checkpoint not found */ </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 } virErrorNumber;<br>
<br>
 /**<br>
diff --git a/src/datatypes.c b/src/datatypes.c<br>
index 09b8eea5a2..3c9069c938 100644<br>
--- a/src/datatypes.c<br>
+++ b/src/datatypes.c<br>
@@ -1,7 +1,7 @@<br>
 /*<br>
  * datatypes.c: management of structs for public data types<br>
  *<br>
- * Copyright (C) 2006-2015 Red Hat, Inc.<br>
+ * Copyright (C) 2006-2018 Red Hat, Inc.<br>
  *<br>
  * This library is free software; you can redistribute it and/or<br>
  * modify it under the terms of the GNU Lesser General Public<br>
@@ -36,6 +36,7 @@ VIR_LOG_INIT("datatypes");<br>
 virClassPtr virConnectClass;<br>
 virClassPtr virConnectCloseCallbackDataClass;<br>
 virClassPtr virDomainClass;<br>
+virClassPtr virDomainCheckpointClass;<br>
 virClassPtr virDomainSnapshotClass;<br>
 virClassPtr virInterfaceClass;<br>
 virClassPtr virNetworkClass;<br>
@@ -49,6 +50,7 @@ virClassPtr virStoragePoolClass;<br>
 static void virConnectDispose(void *obj);<br>
 static void virConnectCloseCallbackDataDispose(void *obj);<br>
 static void virDomainDispose(void *obj);<br>
+static void virDomainCheckpointDispose(void *obj);<br>
 static void virDomainSnapshotDispose(void *obj);<br>
 static void virInterfaceDispose(void *obj);<br>
 static void virNetworkDispose(void *obj);<br>
@@ -84,6 +86,7 @@ virDataTypesOnceInit(void)<br>
     DECLARE_CLASS_LOCKABLE(virConnect);<br>
     DECLARE_CLASS_LOCKABLE(virConnectCloseCallbackData);<br>
     DECLARE_CLASS(virDomain);<br>
+    DECLARE_CLASS(virDomainCheckpoint);<br>
     DECLARE_CLASS(virDomainSnapshot);<br>
     DECLARE_CLASS(virInterface);<br>
     DECLARE_CLASS(virNetwork);<br>
@@ -887,6 +890,63 @@ virDomainSnapshotDispose(void *obj)<br>
 }<br>
<br>
<br>
+/**<br>
+ * virGetDomainCheckpoint:<br>
+ * @domain: the domain to checkpoint<br>
+ * @name: pointer to the domain checkpoint name<br>
+ *<br>
+ * Allocates a new domain checkpoint object. When the object is no longer needed,<br>
+ * virObjectUnref() must be called in order to not leak data.<br>
+ *<br>
+ * Returns a pointer to the domain checkpoint object, or NULL on error.<br>
+ */<br>
+virDomainCheckpointPtr<br>
+virGetDomainCheckpoint(virDomainPtr domain, const char *name)<br>
+{<br>
+    virDomainCheckpointPtr ret = NULL;<br>
+<br>
+    if (virDataTypesInitialize() < 0)<br>
+        return NULL;<br>
+<br>
+    virCheckDomainGoto(domain, error);<br>
+    virCheckNonNullArgGoto(name, error);<br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">+<br>
+    if (!(ret = virObjectNew(virDomainCheckpointClass)))<br>
+        goto error;<br>
+    if (VIR_STRDUP(ret->name, name) < 0)<br>
+        goto error;<br>
+<br>
+    ret->domain = virObjectRef(domain);<br>
+<br>
+    return ret;<br>
+<br>
+ error:<br>
+    virObjectUnref(ret);<br>
+    return NULL;<br>
+}<br>
+<br>
+<br>
+/**<br>
+ * virDomainCheckpointDispose:<br>
+ * @obj: the domain checkpoint to release<br>
+ *<br>
+ * Unconditionally release all memory associated with a checkpoint.<br>
+ * The checkpoint object must not be used once this method returns.<br>
+ *<br>
+ * It will also unreference the associated connection object,<br>
+ * which may also be released if its ref count hits zero.<br>
+ */<br>
+static void<br>
+virDomainCheckpointDispose(void *obj)<br>
+{<br>
+    virDomainCheckpointPtr checkpoint = obj;<br>
+    VIR_DEBUG("release checkpoint %p %s", checkpoint, checkpoint->name);<br>
+<br>
+    VIR_FREE(checkpoint->name);<br>
+    virObjectUnref(checkpoint->domain);<br>
+}<br>
+<br>
+<br>
 virAdmConnectPtr<br>
 virAdmConnectNew(void)<br>
 {<br>
diff --git a/src/datatypes.h b/src/datatypes.h<br>
index 192c86be80..fbe842d105 100644<br>
--- a/src/datatypes.h<br>
+++ b/src/datatypes.h<br>
@@ -1,7 +1,7 @@<br>
 /*<br>
  * datatypes.h: management of structs for public data types<br>
  *<br>
- * Copyright (C) 2006-2015 Red Hat, Inc.<br>
+ * Copyright (C) 2006-2018 Red Hat, Inc.<br>
  *<br>
  * This library is free software; you can redistribute it and/or<br>
  * modify it under the terms of the GNU Lesser General Public<br>
@@ -31,6 +31,7 @@<br>
<br>
 extern virClassPtr virConnectClass;<br>
 extern virClassPtr virDomainClass;<br>
+extern virClassPtr virDomainCheckpointClass;<br>
 extern virClassPtr virDomainSnapshotClass;<br>
 extern virClassPtr virInterfaceClass;<br>
 extern virClassPtr virNetworkClass;<br>
@@ -292,6 +293,21 @@ extern virClassPtr virAdmClientClass;<br>
         } \<br>
     } while (0)<br>
<br>
+# define virCheckDomainCheckpointReturn(obj, retval) \<br>
+    do { \<br>
+        virDomainCheckpointPtr _check = (obj); \<br>
+        if (!virObjectIsClass(_check, virDomainCheckpointClass) || \<br>
+            !virObjectIsClass(_check->domain, virDomainClass) || \<br>
+            !virObjectIsClass(_check->domain->conn, virConnectClass)) { \<br>
+            virReportErrorHelper(VIR_FROM_DOMAIN_CHECKPOINT, \<br>
+                                 VIR_ERR_INVALID_DOMAIN_CHECKPOINT, \<br>
+                                 __FILE__, __FUNCTION__, __LINE__, \<br>
+                                 __FUNCTION__); \<br></blockquote><div><br></div><div>I guess that this is invalid domain checkpoint. Isn't this a generic </div><div>error, providing a pointer of the wrong type?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+            virDispatchError(NULL); \<br>
+            return retval; \<br>
+        } \<br>
+    } while (0)<br>
+<br>
<br>
 /* Helper macros to implement VIR_DOMAIN_DEBUG using just C99.  This<br>
  * assumes you pass fewer than 15 arguments to VIR_DOMAIN_DEBUG, but<br>
@@ -652,6 +668,17 @@ struct _virStream {<br>
     void *privateData;<br>
 };<br>
<br>
+/**<br>
+ * _virDomainCheckpoint<br>
+ *<br>
+ * Internal structure associated with a domain checkpoint<br>
+ */<br>
+struct _virDomainCheckpoint {<br>
+    virObject parent;<br>
+    char *name;<br>
+    virDomainPtr domain;<br>
+};<br>
+<br>
 /**<br>
  * _virDomainSnapshot<br>
  *<br>
@@ -712,6 +739,8 @@ virStreamPtr virGetStream(virConnectPtr conn);<br>
 virNWFilterPtr virGetNWFilter(virConnectPtr conn,<br>
                               const char *name,<br>
                               const unsigned char *uuid);<br>
+virDomainCheckpointPtr virGetDomainCheckpoint(virDomainPtr domain,<br>
+                                              const char *name);<br></blockquote><div><br></div><div>I guess this implemented and documented elsewhere.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 virDomainSnapshotPtr virGetDomainSnapshot(virDomainPtr domain,<br>
                                           const char *name);<br>
<br>
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms<br>
index ea24f2847c..4686c775a5 100644<br>
--- a/src/libvirt_private.syms<br>
+++ b/src/libvirt_private.syms<br>
@@ -1183,10 +1183,12 @@ virConnectCloseCallbackDataClass;<br>
 virConnectCloseCallbackDataGetCallback;<br>
 virConnectCloseCallbackDataRegister;<br>
 virConnectCloseCallbackDataUnregister;<br>
+virDomainCheckpointClass;<br>
 virDomainClass;<br>
 virDomainSnapshotClass;<br>
 virGetConnect;<br>
 virGetDomain;<br>
+virGetDomainCheckpoint;<br>
 virGetDomainSnapshot;<br>
 virGetInterface;<br>
 virGetNetwork;<br>
diff --git a/src/util/virerror.c b/src/util/virerror.c<br>
index 93632dbdf7..1e6fd77abf 100644<br>
--- a/src/util/virerror.c<br>
+++ b/src/util/virerror.c<br>
@@ -1,7 +1,7 @@<br>
 /*<br>
  * virerror.c: error handling and reporting code for libvirt<br>
  *<br>
- * Copyright (C) 2006, 2008-2016 Red Hat, Inc.<br>
+ * Copyright (C) 2006, 2008-2018 Red Hat, Inc.<br>
  *<br>
  * This library is free software; you can redistribute it and/or<br>
  * modify it under the terms of the GNU Lesser General Public<br>
@@ -140,6 +140,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,<br>
               "Perf", /* 65 */<br>
               "Libssh transport layer",<br>
               "Resource control",<br>
+              "Domain Checkpoint",<br>
     )<br>
<br>
<br>
@@ -1494,6 +1495,18 @@ virErrorMsg(virErrorNumber error, const char *info)<br>
             else<br>
                 errmsg = _("device not found: %s");<br>
             break;<br>
+        case VIR_ERR_INVALID_DOMAIN_CHECKPOINT:<br>
+            if (info == NULL)<br>
+                errmsg = _("Invalid checkpoint");<br>
+            else<br>
+                errmsg = _("Invalid checkpoint: %s");<br>
+            break;<br>
+        case VIR_ERR_NO_DOMAIN_CHECKPOINT:<br>
+            if (info == NULL)<br>
+                errmsg = _("Domain snapshot not found");<br>
+            else<br>
+                errmsg = _("Domain snapshot not found: %s");<br>
+            break;<br>
     }<br>
     return errmsg;<br>
 }<br>
-- <br>
2.14.4<br>
<br></blockquote><div><br></div><div>Nir </div></div></div>