The former is a public API and registers a callback that
will be called whenever the other side of a stream calls
virStreamSkip. The latter is a wrapper that actually calls
the callback. It is not made public as it is intended to be
used purely internally.

Signed-off-by: Michal Privoznik <mpriv...@redhat.com>
---
 include/libvirt/libvirt-stream.h | 21 ++++++++++++
 src/datatypes.h                  |  6 ++++
 src/libvirt-stream.c             | 70 ++++++++++++++++++++++++++++++++++++++++
 src/libvirt_internal.h           |  4 +++
 src/libvirt_private.syms         |  1 +
 src/libvirt_public.syms          |  1 +
 6 files changed, 103 insertions(+)

diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h
index f12d695..1a5286a 100644
--- a/include/libvirt/libvirt-stream.h
+++ b/include/libvirt/libvirt-stream.h
@@ -45,6 +45,27 @@ int virStreamRecv(virStreamPtr st,
                   char *data,
                   size_t nbytes);
 
+/**
+ * virStreamSkipFunc:
+ * @stream: stream
+ * @offset: size of hole in bytes
+ * @opaque: optional application provided data
+ *
+ * This callback is called whenever the other side of @stream is
+ * willing to skip a hole in the stream. The @offset argument
+ * then contains the size of hole in bytes.
+ *
+ * Returns 0 on success,
+ *        -1 otherwise.
+ */
+typedef int (*virStreamSkipFunc)(virStreamPtr stream,
+                                 unsigned long long offset,
+                                 void *opaque);
+
+int virStreamRegisterSkip(virStreamPtr stream,
+                          virStreamSkipFunc skipCb,
+                          void *opaque);
+
 int virStreamSkip(virStreamPtr st,
                   unsigned long long offset);
 
diff --git a/src/datatypes.h b/src/datatypes.h
index 92e6863..169fc46 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -568,6 +568,12 @@ struct _virStream {
 
     virStreamDriverPtr driver;
     void *privateData;
+
+    /* Unfortunately, this can't go into virStreamDriver because
+     * when register function for skipCb is called, @driver
+     * is not populated yet. */
+    virStreamSkipFunc skipCb;
+    void *skipCbOpaque;
 };
 
 /**
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index 1c9a12b..58665f1 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -286,6 +286,76 @@ virStreamRecv(virStreamPtr stream,
 
 
 /**
+ * virStreamRegisterSkip:
+ * @stream: stream
+ * @skipCb: callback function
+ * @opaque: optional application provided data
+ *
+ * This function registers callback that will be called whenever
+ * the other side of the @stream is willing to skip a hole in the
+ * stream.
+ *
+ * Returns 0 on success,
+ *        -1 otherwise.
+ */
+int
+virStreamRegisterSkip(virStreamPtr stream,
+                      virStreamSkipFunc skipCb,
+                      void *opaque)
+{
+    VIR_DEBUG("stream=%p, skipCb=%p opaque=%p", stream, skipCb, opaque);
+
+    virResetLastError();
+
+    virCheckStreamReturn(stream, -1);
+    virCheckNonNullArgReturn(skipCb, -1);
+
+    if (stream->skipCb) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("A skip callback is already registered"));
+        return -1;
+    }
+
+    stream->skipCb = skipCb;
+    stream->skipCbOpaque = opaque;
+    return 0;
+}
+
+
+/**
+ * virStreamSkipCallback:
+ * @stream: stream
+ * @offset: stream offset
+ *
+ * Call previously registered skip callback.
+ *
+ * Returns 0 on success,
+ *        -1 otherwise.
+ */
+int
+virStreamSkipCallback(virStreamPtr stream,
+                      unsigned long long offset)
+{
+    VIR_DEBUG("stream=%p, offset=%llu", stream, offset);
+
+    virCheckStreamReturn(stream, -1);
+
+    if (stream->skipCb) {
+        int ret;
+        ret = (stream->skipCb)(stream, offset, stream->skipCbOpaque);
+        if (ret < 0)
+            goto error;
+        return 0;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(stream->conn);
+    return -1;
+}
+
+
+/**
  * virStreamSkip:
  * @stream: pointer to the stream object
  * @offset: number of bytes to skip
diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h
index 96439d8..7a75491 100644
--- a/src/libvirt_internal.h
+++ b/src/libvirt_internal.h
@@ -294,4 +294,8 @@ virTypedParameterValidateSet(virConnectPtr conn,
                              virTypedParameterPtr params,
                              int nparams);
 
+int
+virStreamSkipCallback(virStreamPtr stream,
+                      unsigned long long offset);
+
 #endif
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5030ec3..e83d5d6 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1015,6 +1015,7 @@ virStateCleanup;
 virStateInitialize;
 virStateReload;
 virStateStop;
+virStreamSkipCallback;
 
 
 # locking/domain_lock.h
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index b4c693a..0b80d27 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -735,6 +735,7 @@ LIBVIRT_1.3.3 {
 LIBVIRT_1.3.5 {
     global:
         virStreamSkip;
+        virStreamRegisterSkip;
 } LIBVIRT_1.3.3;
 
 # .... define new API here using predicted next version number ....
-- 
2.8.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to