[libvirt] [PATCH 06/27] Introduce virStreamInData and virStreamRegisterInData

Michal Privoznik mprivozn at redhat.com
Thu Apr 28 10:04:53 UTC 2016


These functions will be called to determine whether underlying
file that stream is transferring is currently in a data or hole.

While virStreamRegisterInData is exposed, virStreamInData does
not need to be made a public API as it will be called just
internally.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 include/libvirt/libvirt-stream.h | 23 +++++++++++
 src/datatypes.h                  |  8 ++--
 src/libvirt-stream.c             | 88 ++++++++++++++++++++++++++++++++++++++++
 src/libvirt_internal.h           |  3 ++
 src/libvirt_private.syms         |  1 +
 src/libvirt_public.syms          |  1 +
 6 files changed, 121 insertions(+), 3 deletions(-)

diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h
index 1a5286a..3a0c986 100644
--- a/include/libvirt/libvirt-stream.h
+++ b/include/libvirt/libvirt-stream.h
@@ -69,6 +69,29 @@ int virStreamRegisterSkip(virStreamPtr stream,
 int virStreamSkip(virStreamPtr st,
                   unsigned long long offset);
 
+/**
+ * virStreamInDataFunc:
+ * @stream: stream
+ * @data: are we in data or hole
+ * @offset: offset to next section
+ * @opaque: optional application provided data
+ *
+ * This callback is called whenever virStreamInData needs to
+ * check whether @stream is in data section or in hole. Check
+ * description for virStreamInData for more detailed description.
+ *
+ * Returns 0 on success (with @data and @offset updated)
+ *        -1 otherwise (with @data and @offset untouched)
+ */
+typedef int (*virStreamInDataFunc)(virStreamPtr stream,
+                                   int *data,
+                                   unsigned long long *offset,
+                                   void *opaque);
+
+int virStreamRegisterInData(virStreamPtr stream,
+                            virStreamInDataFunc inDataCb,
+                            void *opaque);
+
 
 /**
  * virStreamSourceFunc:
diff --git a/src/datatypes.h b/src/datatypes.h
index 169fc46..41f1536 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -569,11 +569,13 @@ 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. */
+    /* Unfortunately, these can't go into virStreamDriver because
+     * when register function for skipCb or inDataFunc is called,
+     * @driver is not populated yet. */
     virStreamSkipFunc skipCb;
     void *skipCbOpaque;
+    virStreamInDataFunc inDataCb;
+    void *inDataCbOpaque;
 };
 
 /**
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index 58665f1..371efed 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -396,6 +396,94 @@ virStreamSkip(virStreamPtr stream,
 
 
 /**
+ * virStreamRegisterInData:
+ * @stream: stream
+ * @inDataCb: callback function
+ * @opaque: optional application provided data
+ *
+ * This function registers callback that will be called whenever
+ * virStreamInData needs to check whether @stream is currently in
+ * data or in a hole. This is to be used purely with sparse
+ * streams.
+ *
+ * Returns 0 on success,
+ *        -1 otherwise.
+ */
+int
+virStreamRegisterInData(virStreamPtr stream,
+                        virStreamInDataFunc inDataCb,
+                        void *opaque)
+{
+    VIR_DEBUG("stream=%p, inDataCb=%p opaque=%p", stream, inDataCb, opaque);
+
+    virResetLastError();
+
+    virCheckStreamReturn(stream, -1);
+    virCheckNonNullArgReturn(inDataCb, -1);
+
+    if (stream->inDataCb) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("A inData callback is already registered"));
+        return -1;
+    }
+
+    stream->inDataCb = inDataCb;
+    stream->inDataCbOpaque = opaque;
+    return 0;
+}
+
+
+/**
+ * virStreamInData:
+ * @stream: stream
+ * @data: are we in data or hole
+ * @offset: offset to next section
+ *
+ * This function will check underlying stream (typically a file)
+ * whether the current position the stream is in lies in a data
+ * section or in a hole. Upon return @data is set to a nonzero
+ * value if former is the case, or to zero if @stream is in a
+ * hole. Moreover, @offset it updated to tell caller how much
+ * bytes can be read from @stream until current section changes
+ * (from data to a hole or vice versa).
+ *
+ * As a special case, there's an implicit hole at EOF. In this
+ * situation this function should set @data = false, @offset = 0
+ * and return 0.
+ *
+ * Returns 0 on success,
+ *        -1 otherwise
+ */
+int
+virStreamInData(virStreamPtr stream,
+                int *data,
+                unsigned long long *offset)
+{
+    VIR_DEBUG("stream=%p, data=%p, offset=%p", stream, data, offset);
+
+    virResetLastError();
+
+    virCheckStreamReturn(stream, -1);
+    virCheckNonNullArgReturn(data, -1);
+    virCheckNonNullArgReturn(offset, -1);
+
+    if (stream->inDataCb) {
+        int ret;
+        ret = (stream->inDataCb)(stream, data, offset, stream->inDataCbOpaque);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(stream->conn);
+    return -1;
+}
+
+
+/**
  * virStreamSendAll:
  * @stream: pointer to the stream object
  * @handler: source callback for reading data from application
diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h
index 7a75491..d20acbc 100644
--- a/src/libvirt_internal.h
+++ b/src/libvirt_internal.h
@@ -298,4 +298,7 @@ int
 virStreamSkipCallback(virStreamPtr stream,
                       unsigned long long offset);
 
+int virStreamInData(virStreamPtr stream,
+                    int *data,
+                    unsigned long long *offset);
 #endif
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e83d5d6..e506d1c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1015,6 +1015,7 @@ virStateCleanup;
 virStateInitialize;
 virStateReload;
 virStateStop;
+virStreamInData;
 virStreamSkipCallback;
 
 
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 0b80d27..396fea5 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -736,6 +736,7 @@ LIBVIRT_1.3.5 {
     global:
         virStreamSkip;
         virStreamRegisterSkip;
+        virStreamRegisterInData;
 } LIBVIRT_1.3.3;
 
 # .... define new API here using predicted next version number ....
-- 
2.8.1




More information about the libvir-list mailing list