From bf76baef3335460fac43a77a9b5ad84c9c99a19d Mon Sep 17 00:00:00 2001
From: mattjala <124107509+mattjala@users.noreply.github.com>
Date: Sat, 29 Jun 2024 15:22:35 -0500
Subject: [PATCH] Document VOL object wrapping context (#4611)
---
doxygen/dox/VOLConnGuide.dox | 39 +++++++++++++++++++++++++++---------
src/H5VLcallback.c | 5 ++++-
src/H5VLconnector.h | 3 ++-
src/H5VLint.c | 11 +++++++++-
4 files changed, 46 insertions(+), 12 deletions(-)
diff --git a/doxygen/dox/VOLConnGuide.dox b/doxygen/dox/VOLConnGuide.dox
index fb662a0ef5a..05219db442c 100644
--- a/doxygen/dox/VOLConnGuide.dox
+++ b/doxygen/dox/VOLConnGuide.dox
@@ -657,7 +657,11 @@ structure. It is the opposite of the to_str callback.
\subsection subsecVOLRefWrap Object Wrap Callbacks
The object wrap callbacks are used by passthrough connectors to wrap/unwrap objects and contexts when
-passing them up and down the VOL chain.
+passing them up and down the VOL chain. Each passthrough VOL must define an object wrapping structure and a wrap context.
+The object wrapping structure should contain the information necessary to recursively unwrap the object - at a minimum, this is the object provided from and the ID of the next connector in the stack.
+The wrap context should contain the information necessary to recursively wrap the object - at a minimum, this is the ID and the wrap context of the next VOL connector in the stack.
+
+Each callback should use H5VL<callback> to recursively invoke the same callback in all lower passthrough VOl connectors.
Wrap class for object wrapping routines, H5VLconnector.h
\code
@@ -671,7 +675,13 @@ typedef struct H5VL_wrap_class_t {
\endcode
\subsubsection subsubsecVOLRefWrapobj wrap: get_object
-Retrieves an underlying object.
+Retrieves the underlying object from a wrapped object. Should return a pointer to the underlying object belonging to the terminal VOL connector.
+
+This will generally be done by unwrapping this VOL's object wrapping structure, before recursively calling H5VLget_object to invoke the get_object
+callback for all lower VOL connectors which define it. H5VLget_object requires the object returned by the next VOL and the next VOL's ID. Both of
+these fields should be stored by the VOL somehow, generally on the wrapped object structure.
+
+This callback should not cleanup or modify the provided object wrapping structure.
Signature: |
@@ -689,7 +699,7 @@ Retrieves an underlying object.
\code
- obj (IN): Object being unwrapped.
+ obj (IN): The object to be unwrapped.
\endcode
|
@@ -697,6 +707,9 @@ Retrieves an underlying object.
\subsubsection subsubsecVOLRefWrapctx wrap: get_wrap_ctx
Get a VOL connector's object wrapping context.
+
+The context should be returned in dynamically allocated memory under *wrap_ctx.
+Any resources this callback allocates should be freed within free_wrap_ctx.
Signature: |
@@ -714,7 +727,7 @@ Get a VOL connector's object wrapping context.
\code
- obj (IN): Object for which we need a context.
+ obj (IN): Object wrapped by this VOL connector, for which we need a context.
wrap_ctx (OUT): Context.
\endcode
|
@@ -722,7 +735,11 @@ Get a VOL connector's object wrapping context.
\subsubsection subsubsecVOLRefWrapwrap wrap: wrap_object
-Asks a connector to wrap an underlying object.
+Asks a connector to wrap an underlying object. This callback should use H5VLwrap_object
+to recursively have the object wrapped by all lower VOL connectors before performing its own wrapping.
+
+The wrapped object should provide the information necessary for unwrap_object to recursively
+unwrap it - at a minimum, the object provided from and the ID of the next VOL connector.
Signature: |
@@ -740,7 +757,7 @@ Asks a connector to wrap an underlying object.
\code
- obj (IN): Object being wrapped.
+ obj (IN): The object to be wrapped.
obj_type (IN): Object type (see H5Ipublic.h).
wrap_ctx (IN): Context.
\endcode
@@ -749,7 +766,10 @@ Asks a connector to wrap an underlying object.
|
\subsubsection subsubsecVOLRefWrapunwrap wrap: unwrap_object
-Unwrap an object from connector.
+Unwrap an object from connector. Any resources allocated during wrap_object should be released and cleaned up here.
+
+This callback should clean up this VOL's object wrapping structure before recursively invoking H5VLunwrap_object.
+
Signature: |
@@ -767,14 +787,15 @@ Unwrap an object from connector.
\code
- obj (IN): Object being unwrapped.
+ obj (IN): Object to be unwrapped.
\endcode
|
\subsubsection subsubsecVOLRefWrapfree wrap: free_wrap_ctx
-Release a VOL connector's object wrapping context.
+Release a VOL connector's object wrapping context. This should free any resources allocated during get_wrap_ctx, and recursively invoke H5VLfree_wrap_ctx
+to execute the free callback for the lower VOL connectors in the stack.
Signature: |
diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c
index 83ff9e92402..0d6a2d22215 100644
--- a/src/H5VLcallback.c
+++ b/src/H5VLcallback.c
@@ -776,7 +776,10 @@ H5VL_get_wrap_ctx(const H5VL_class_t *connector, void *obj, void **wrap_ctx)
/*---------------------------------------------------------------------------
* Function: H5VLget_wrap_ctx
*
- * Purpose: Get a VOL connector's object wrapping context
+ * Purpose: Get a VOL connector's object wrapping context. The output
+ * wrap context is stored in memory allocated by the VOL callback
+ * under *wrap_ctx and must be freed by the caller through
+ * H5VLfree_wrap_ctx().
*
* Return: Success: Non-negative
* Failure: Negative
diff --git a/src/H5VLconnector.h b/src/H5VLconnector.h
index 02d22314ebc..83a5b087133 100644
--- a/src/H5VLconnector.h
+++ b/src/H5VLconnector.h
@@ -845,7 +845,8 @@ typedef struct H5VL_info_class_t {
} H5VL_info_class_t;
/* VOL object wrap / retrieval callbacks */
-/* (These only need to be implemented by "pass through" VOL connectors) */
+/* (These must be implemented by "pass through" VOL connectors, and should not be implemented by terminal VOL
+ * connectors) */
typedef struct H5VL_wrap_class_t {
void *(*get_object)(const void *obj); /* Callback to retrieve underlying object */
herr_t (*get_wrap_ctx)(
diff --git a/src/H5VLint.c b/src/H5VLint.c
index de52dfc4519..4337e48c91f 100644
--- a/src/H5VLint.c
+++ b/src/H5VLint.c
@@ -55,7 +55,16 @@
/* Local Typedefs */
/******************/
-/* Object wrapping context info */
+/* Object wrapping context info for passthrough VOL connectors.
+ * Passthrough VOL connectors must wrap objects returned from lower level(s) of the VOL connector stack
+ * so that they may be passed back up the stack to the library, and must unwrap objects
+ * passed down the stack before providing them to the next lower VOL connector.
+ * This is generally done individually within each VOL object callback. However, the library sometimes
+ * needs to wrap objects from places that don't pass through the VOL layer.
+ * In this case, the wrap callbacks defined in H5VL_wrap_class_t are used, and the VOL-defined wrap context
+ * (obj_wrap_ctx) provides necessary information - at a minimum, the object originally returned by the lower
+ * VOL connector, and the ID of the next VOL connector.
+ */
typedef struct H5VL_wrap_ctx_t {
H5_ATOMIC(unsigned) rc; /* Ref. count for the # of times the context was set / reset */
H5VL_t *connector; /* VOL connector for "outermost" class to start wrap */