1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * All rights reserved.                                                      *
4  *                                                                           *
5  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6  * terms governing use, modification, and redistribution, is contained in    *
7  * the COPYING file, which can be found at the root of the source code       *
8  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9  * If you do not have access to either file, you may request a copy from     *
10  * help@hdfgroup.org.                                                        *
11  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12 
13 /*
14  * Purpose:     This is a "pass through" VOL connector, which forwards each
15  *              VOL callback to an underlying connector.
16  *
17  *              It is designed as an example VOL connector for developers to
18  *              use when creating new connectors, especially connectors that
19  *              are outside of the HDF5 library.  As such, it should _NOT_
20  *              include _any_ private HDF5 header files.  This connector should
21  *              therefore only make public HDF5 API calls and use standard C /
22  *              POSIX calls.
23  *
24  *              Note that the HDF5 error stack must be preserved on code paths
25  *              that could be invoked when the underlying VOL connector's
26  *              callback can fail.
27  *
28  */
29 
30 /* Header files needed */
31 /* Do NOT include private HDF5 files here! */
32 #include <assert.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 /* Public HDF5 file */
39 #include "hdf5.h"
40 
41 /* This connector's header */
42 #include "H5VLpassthru.h"
43 
44 /**********/
45 /* Macros */
46 /**********/
47 
48 /* Whether to display log messge when callback is invoked */
49 /* (Uncomment to enable) */
50 /* #define ENABLE_PASSTHRU_LOGGING */
51 
52 /* Hack for missing va_copy() in old Visual Studio editions
53  * (from H5win2_defs.h - used on VS2012 and earlier)
54  */
55 #if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1800)
56 #define va_copy(D, S) ((D) = (S))
57 #endif
58 
59 /************/
60 /* Typedefs */
61 /************/
62 
63 /* The pass through VOL info object */
64 typedef struct H5VL_pass_through_t {
65     hid_t under_vol_id; /* ID for underlying VOL connector */
66     void *under_object; /* Info object for underlying VOL connector */
67 } H5VL_pass_through_t;
68 
69 /* The pass through VOL wrapper context */
70 typedef struct H5VL_pass_through_wrap_ctx_t {
71     hid_t under_vol_id;   /* VOL ID for under VOL */
72     void *under_wrap_ctx; /* Object wrapping context for under VOL */
73 } H5VL_pass_through_wrap_ctx_t;
74 
75 /********************* */
76 /* Function prototypes */
77 /********************* */
78 
79 /* Helper routines */
80 static herr_t H5VL_pass_through_file_specific_reissue(void *obj, hid_t connector_id,
81                                                       H5VL_file_specific_t specific_type, hid_t dxpl_id,
82                                                       void **req, ...);
83 static herr_t H5VL_pass_through_request_specific_reissue(void *obj, hid_t connector_id,
84                                                          H5VL_request_specific_t specific_type, ...);
85 static herr_t H5VL_pass_through_link_create_reissue(H5VL_link_create_type_t create_type, void *obj,
86                                                     const H5VL_loc_params_t *loc_params, hid_t connector_id,
87                                                     hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req,
88                                                     ...);
89 static H5VL_pass_through_t *H5VL_pass_through_new_obj(void *under_obj, hid_t under_vol_id);
90 static herr_t               H5VL_pass_through_free_obj(H5VL_pass_through_t *obj);
91 
92 /* "Management" callbacks */
93 static herr_t H5VL_pass_through_init(hid_t vipl_id);
94 static herr_t H5VL_pass_through_term(void);
95 
96 /* VOL info callbacks */
97 static void * H5VL_pass_through_info_copy(const void *info);
98 static herr_t H5VL_pass_through_info_cmp(int *cmp_value, const void *info1, const void *info2);
99 static herr_t H5VL_pass_through_info_free(void *info);
100 static herr_t H5VL_pass_through_info_to_str(const void *info, char **str);
101 static herr_t H5VL_pass_through_str_to_info(const char *str, void **info);
102 
103 /* VOL object wrap / retrieval callbacks */
104 static void * H5VL_pass_through_get_object(const void *obj);
105 static herr_t H5VL_pass_through_get_wrap_ctx(const void *obj, void **wrap_ctx);
106 static void * H5VL_pass_through_wrap_object(void *obj, H5I_type_t obj_type, void *wrap_ctx);
107 static void * H5VL_pass_through_unwrap_object(void *obj);
108 static herr_t H5VL_pass_through_free_wrap_ctx(void *obj);
109 
110 /* Attribute callbacks */
111 static void * H5VL_pass_through_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
112                                             hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id,
113                                             hid_t dxpl_id, void **req);
114 static void * H5VL_pass_through_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
115                                           hid_t aapl_id, hid_t dxpl_id, void **req);
116 static herr_t H5VL_pass_through_attr_read(void *attr, hid_t mem_type_id, void *buf, hid_t dxpl_id,
117                                           void **req);
118 static herr_t H5VL_pass_through_attr_write(void *attr, hid_t mem_type_id, const void *buf, hid_t dxpl_id,
119                                            void **req);
120 static herr_t H5VL_pass_through_attr_get(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req,
121                                          va_list arguments);
122 static herr_t H5VL_pass_through_attr_specific(void *obj, const H5VL_loc_params_t *loc_params,
123                                               H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req,
124                                               va_list arguments);
125 static herr_t H5VL_pass_through_attr_optional(void *obj, H5VL_attr_optional_t opt_type, hid_t dxpl_id,
126                                               void **req, va_list arguments);
127 static herr_t H5VL_pass_through_attr_close(void *attr, hid_t dxpl_id, void **req);
128 
129 /* Dataset callbacks */
130 static void * H5VL_pass_through_dataset_create(void *obj, const H5VL_loc_params_t *loc_params,
131                                                const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id,
132                                                hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req);
133 static void * H5VL_pass_through_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
134                                              hid_t dapl_id, hid_t dxpl_id, void **req);
135 static herr_t H5VL_pass_through_dataset_read(void *dset, hid_t mem_type_id, hid_t mem_space_id,
136                                              hid_t file_space_id, hid_t plist_id, void *buf, void **req);
137 static herr_t H5VL_pass_through_dataset_write(void *dset, hid_t mem_type_id, hid_t mem_space_id,
138                                               hid_t file_space_id, hid_t plist_id, const void *buf,
139                                               void **req);
140 static herr_t H5VL_pass_through_dataset_get(void *dset, H5VL_dataset_get_t get_type, hid_t dxpl_id,
141                                             void **req, va_list arguments);
142 static herr_t H5VL_pass_through_dataset_specific(void *obj, H5VL_dataset_specific_t specific_type,
143                                                  hid_t dxpl_id, void **req, va_list arguments);
144 static herr_t H5VL_pass_through_dataset_optional(void *obj, H5VL_dataset_optional_t opt_type, hid_t dxpl_id,
145                                                  void **req, va_list arguments);
146 static herr_t H5VL_pass_through_dataset_close(void *dset, hid_t dxpl_id, void **req);
147 
148 /* Datatype callbacks */
149 static void *H5VL_pass_through_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params,
150                                                const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id,
151                                                hid_t tapl_id, hid_t dxpl_id, void **req);
152 static void *H5VL_pass_through_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
153                                              hid_t tapl_id, hid_t dxpl_id, void **req);
154 static herr_t H5VL_pass_through_datatype_get(void *dt, H5VL_datatype_get_t get_type, hid_t dxpl_id,
155                                              void **req, va_list arguments);
156 static herr_t H5VL_pass_through_datatype_specific(void *obj, H5VL_datatype_specific_t specific_type,
157                                                   hid_t dxpl_id, void **req, va_list arguments);
158 static herr_t H5VL_pass_through_datatype_optional(void *obj, H5VL_datatype_optional_t opt_type, hid_t dxpl_id,
159                                                   void **req, va_list arguments);
160 static herr_t H5VL_pass_through_datatype_close(void *dt, hid_t dxpl_id, void **req);
161 
162 /* File callbacks */
163 static void * H5VL_pass_through_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
164                                             hid_t dxpl_id, void **req);
165 static void * H5VL_pass_through_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id,
166                                           void **req);
167 static herr_t H5VL_pass_through_file_get(void *file, H5VL_file_get_t get_type, hid_t dxpl_id, void **req,
168                                          va_list arguments);
169 static herr_t H5VL_pass_through_file_specific(void *file, H5VL_file_specific_t specific_type, hid_t dxpl_id,
170                                               void **req, va_list arguments);
171 static herr_t H5VL_pass_through_file_optional(void *file, H5VL_file_optional_t opt_type, hid_t dxpl_id,
172                                               void **req, va_list arguments);
173 static herr_t H5VL_pass_through_file_close(void *file, hid_t dxpl_id, void **req);
174 
175 /* Group callbacks */
176 static void * H5VL_pass_through_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
177                                              hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id,
178                                              void **req);
179 static void * H5VL_pass_through_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
180                                            hid_t gapl_id, hid_t dxpl_id, void **req);
181 static herr_t H5VL_pass_through_group_get(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id, void **req,
182                                           va_list arguments);
183 static herr_t H5VL_pass_through_group_specific(void *obj, H5VL_group_specific_t specific_type, hid_t dxpl_id,
184                                                void **req, va_list arguments);
185 static herr_t H5VL_pass_through_group_optional(void *obj, H5VL_group_optional_t opt_type, hid_t dxpl_id,
186                                                void **req, va_list arguments);
187 static herr_t H5VL_pass_through_group_close(void *grp, hid_t dxpl_id, void **req);
188 
189 /* Link callbacks */
190 static herr_t H5VL_pass_through_link_create(H5VL_link_create_type_t create_type, void *obj,
191                                             const H5VL_loc_params_t *loc_params, hid_t lcpl_id, hid_t lapl_id,
192                                             hid_t dxpl_id, void **req, va_list arguments);
193 static herr_t H5VL_pass_through_link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj,
194                                           const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id,
195                                           hid_t dxpl_id, void **req);
196 static herr_t H5VL_pass_through_link_move(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj,
197                                           const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id,
198                                           hid_t dxpl_id, void **req);
199 static herr_t H5VL_pass_through_link_get(void *obj, const H5VL_loc_params_t *loc_params,
200                                          H5VL_link_get_t get_type, hid_t dxpl_id, void **req,
201                                          va_list arguments);
202 static herr_t H5VL_pass_through_link_specific(void *obj, const H5VL_loc_params_t *loc_params,
203                                               H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req,
204                                               va_list arguments);
205 static herr_t H5VL_pass_through_link_optional(void *obj, H5VL_link_optional_t opt_type, hid_t dxpl_id,
206                                               void **req, va_list arguments);
207 
208 /* Object callbacks */
209 static void * H5VL_pass_through_object_open(void *obj, const H5VL_loc_params_t *loc_params,
210                                             H5I_type_t *opened_type, hid_t dxpl_id, void **req);
211 static herr_t H5VL_pass_through_object_copy(void *src_obj, const H5VL_loc_params_t *src_loc_params,
212                                             const char *src_name, void *dst_obj,
213                                             const H5VL_loc_params_t *dst_loc_params, const char *dst_name,
214                                             hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req);
215 static herr_t H5VL_pass_through_object_get(void *obj, const H5VL_loc_params_t *loc_params,
216                                            H5VL_object_get_t get_type, hid_t dxpl_id, void **req,
217                                            va_list arguments);
218 static herr_t H5VL_pass_through_object_specific(void *obj, const H5VL_loc_params_t *loc_params,
219                                                 H5VL_object_specific_t specific_type, hid_t dxpl_id,
220                                                 void **req, va_list arguments);
221 static herr_t H5VL_pass_through_object_optional(void *obj, H5VL_object_optional_t opt_type, hid_t dxpl_id,
222                                                 void **req, va_list arguments);
223 
224 /* Container/connector introspection callbacks */
225 static herr_t H5VL_pass_through_introspect_get_conn_cls(void *obj, H5VL_get_conn_lvl_t lvl,
226                                                         const H5VL_class_t **conn_cls);
227 static herr_t H5VL_pass_through_introspect_opt_query(void *obj, H5VL_subclass_t cls, int opt_type,
228                                                      hbool_t *supported);
229 
230 /* Async request callbacks */
231 static herr_t H5VL_pass_through_request_wait(void *req, uint64_t timeout, H5ES_status_t *status);
232 static herr_t H5VL_pass_through_request_notify(void *obj, H5VL_request_notify_t cb, void *ctx);
233 static herr_t H5VL_pass_through_request_cancel(void *req);
234 static herr_t H5VL_pass_through_request_specific(void *req, H5VL_request_specific_t specific_type,
235                                                  va_list arguments);
236 static herr_t H5VL_pass_through_request_optional(void *req, H5VL_request_optional_t opt_type,
237                                                  va_list arguments);
238 static herr_t H5VL_pass_through_request_free(void *req);
239 
240 /* Blob callbacks */
241 static herr_t H5VL_pass_through_blob_put(void *obj, const void *buf, size_t size, void *blob_id, void *ctx);
242 static herr_t H5VL_pass_through_blob_get(void *obj, const void *blob_id, void *buf, size_t size, void *ctx);
243 static herr_t H5VL_pass_through_blob_specific(void *obj, void *blob_id, H5VL_blob_specific_t specific_type,
244                                               va_list arguments);
245 static herr_t H5VL_pass_through_blob_optional(void *obj, void *blob_id, H5VL_blob_optional_t opt_type,
246                                               va_list arguments);
247 
248 /* Token callbacks */
249 static herr_t H5VL_pass_through_token_cmp(void *obj, const H5O_token_t *token1, const H5O_token_t *token2,
250                                           int *cmp_value);
251 static herr_t H5VL_pass_through_token_to_str(void *obj, H5I_type_t obj_type, const H5O_token_t *token,
252                                              char **token_str);
253 static herr_t H5VL_pass_through_token_from_str(void *obj, H5I_type_t obj_type, const char *token_str,
254                                                H5O_token_t *token);
255 
256 /* Generic optional callback */
257 static herr_t H5VL_pass_through_optional(void *obj, int op_type, hid_t dxpl_id, void **req,
258                                          va_list arguments);
259 
260 /*******************/
261 /* Local variables */
262 /*******************/
263 
264 /* Pass through VOL connector class struct */
265 static const H5VL_class_t H5VL_pass_through_g = {
266     H5VL_VERSION,                            /* VOL class struct version */
267     (H5VL_class_value_t)H5VL_PASSTHRU_VALUE, /* value        */
268     H5VL_PASSTHRU_NAME,                      /* name         */
269     0,                                       /* capability flags */
270     H5VL_pass_through_init,                  /* initialize   */
271     H5VL_pass_through_term,                  /* terminate    */
272     {
273         /* info_cls */
274         sizeof(H5VL_pass_through_info_t), /* size    */
275         H5VL_pass_through_info_copy,      /* copy    */
276         H5VL_pass_through_info_cmp,       /* compare */
277         H5VL_pass_through_info_free,      /* free    */
278         H5VL_pass_through_info_to_str,    /* to_str  */
279         H5VL_pass_through_str_to_info     /* from_str */
280     },
281     {
282         /* wrap_cls */
283         H5VL_pass_through_get_object,    /* get_object   */
284         H5VL_pass_through_get_wrap_ctx,  /* get_wrap_ctx */
285         H5VL_pass_through_wrap_object,   /* wrap_object  */
286         H5VL_pass_through_unwrap_object, /* unwrap_object */
287         H5VL_pass_through_free_wrap_ctx  /* free_wrap_ctx */
288     },
289     {
290         /* attribute_cls */
291         H5VL_pass_through_attr_create,   /* create */
292         H5VL_pass_through_attr_open,     /* open */
293         H5VL_pass_through_attr_read,     /* read */
294         H5VL_pass_through_attr_write,    /* write */
295         H5VL_pass_through_attr_get,      /* get */
296         H5VL_pass_through_attr_specific, /* specific */
297         H5VL_pass_through_attr_optional, /* optional */
298         H5VL_pass_through_attr_close     /* close */
299     },
300     {
301         /* dataset_cls */
302         H5VL_pass_through_dataset_create,   /* create */
303         H5VL_pass_through_dataset_open,     /* open */
304         H5VL_pass_through_dataset_read,     /* read */
305         H5VL_pass_through_dataset_write,    /* write */
306         H5VL_pass_through_dataset_get,      /* get */
307         H5VL_pass_through_dataset_specific, /* specific */
308         H5VL_pass_through_dataset_optional, /* optional */
309         H5VL_pass_through_dataset_close     /* close */
310     },
311     {
312         /* datatype_cls */
313         H5VL_pass_through_datatype_commit,   /* commit */
314         H5VL_pass_through_datatype_open,     /* open */
315         H5VL_pass_through_datatype_get,      /* get_size */
316         H5VL_pass_through_datatype_specific, /* specific */
317         H5VL_pass_through_datatype_optional, /* optional */
318         H5VL_pass_through_datatype_close     /* close */
319     },
320     {
321         /* file_cls */
322         H5VL_pass_through_file_create,   /* create */
323         H5VL_pass_through_file_open,     /* open */
324         H5VL_pass_through_file_get,      /* get */
325         H5VL_pass_through_file_specific, /* specific */
326         H5VL_pass_through_file_optional, /* optional */
327         H5VL_pass_through_file_close     /* close */
328     },
329     {
330         /* group_cls */
331         H5VL_pass_through_group_create,   /* create */
332         H5VL_pass_through_group_open,     /* open */
333         H5VL_pass_through_group_get,      /* get */
334         H5VL_pass_through_group_specific, /* specific */
335         H5VL_pass_through_group_optional, /* optional */
336         H5VL_pass_through_group_close     /* close */
337     },
338     {
339         /* link_cls */
340         H5VL_pass_through_link_create,   /* create */
341         H5VL_pass_through_link_copy,     /* copy */
342         H5VL_pass_through_link_move,     /* move */
343         H5VL_pass_through_link_get,      /* get */
344         H5VL_pass_through_link_specific, /* specific */
345         H5VL_pass_through_link_optional  /* optional */
346     },
347     {
348         /* object_cls */
349         H5VL_pass_through_object_open,     /* open */
350         H5VL_pass_through_object_copy,     /* copy */
351         H5VL_pass_through_object_get,      /* get */
352         H5VL_pass_through_object_specific, /* specific */
353         H5VL_pass_through_object_optional  /* optional */
354     },
355     {
356         /* introspect_cls */
357         H5VL_pass_through_introspect_get_conn_cls, /* get_conn_cls */
358         H5VL_pass_through_introspect_opt_query,    /* opt_query */
359     },
360     {
361         /* request_cls */
362         H5VL_pass_through_request_wait,     /* wait */
363         H5VL_pass_through_request_notify,   /* notify */
364         H5VL_pass_through_request_cancel,   /* cancel */
365         H5VL_pass_through_request_specific, /* specific */
366         H5VL_pass_through_request_optional, /* optional */
367         H5VL_pass_through_request_free      /* free */
368     },
369     {
370         /* blob_cls */
371         H5VL_pass_through_blob_put,      /* put */
372         H5VL_pass_through_blob_get,      /* get */
373         H5VL_pass_through_blob_specific, /* specific */
374         H5VL_pass_through_blob_optional  /* optional */
375     },
376     {
377         /* token_cls */
378         H5VL_pass_through_token_cmp,     /* cmp */
379         H5VL_pass_through_token_to_str,  /* to_str */
380         H5VL_pass_through_token_from_str /* from_str */
381     },
382     H5VL_pass_through_optional /* optional */
383 };
384 
385 /* The connector identification number, initialized at runtime */
386 static hid_t H5VL_PASSTHRU_g = H5I_INVALID_HID;
387 
388 /*-------------------------------------------------------------------------
389  * Function:    H5VL__pass_through_new_obj
390  *
391  * Purpose:     Create a new pass through object for an underlying object
392  *
393  * Return:      Success:    Pointer to the new pass through object
394  *              Failure:    NULL
395  *
396  * Programmer:  Quincey Koziol
397  *              Monday, December 3, 2018
398  *
399  *-------------------------------------------------------------------------
400  */
401 static H5VL_pass_through_t *
H5VL_pass_through_new_obj(void * under_obj,hid_t under_vol_id)402 H5VL_pass_through_new_obj(void *under_obj, hid_t under_vol_id)
403 {
404     H5VL_pass_through_t *new_obj;
405 
406     new_obj               = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t));
407     new_obj->under_object = under_obj;
408     new_obj->under_vol_id = under_vol_id;
409     H5Iinc_ref(new_obj->under_vol_id);
410 
411     return new_obj;
412 } /* end H5VL__pass_through_new_obj() */
413 
414 /*-------------------------------------------------------------------------
415  * Function:    H5VL__pass_through_free_obj
416  *
417  * Purpose:     Release a pass through object
418  *
419  * Note:	Take care to preserve the current HDF5 error stack
420  *		when calling HDF5 API calls.
421  *
422  * Return:      Success:    0
423  *              Failure:    -1
424  *
425  * Programmer:  Quincey Koziol
426  *              Monday, December 3, 2018
427  *
428  *-------------------------------------------------------------------------
429  */
430 static herr_t
H5VL_pass_through_free_obj(H5VL_pass_through_t * obj)431 H5VL_pass_through_free_obj(H5VL_pass_through_t *obj)
432 {
433     hid_t err_id;
434 
435     err_id = H5Eget_current_stack();
436 
437     H5Idec_ref(obj->under_vol_id);
438 
439     H5Eset_current_stack(err_id);
440 
441     free(obj);
442 
443     return 0;
444 } /* end H5VL__pass_through_free_obj() */
445 
446 /*-------------------------------------------------------------------------
447  * Function:    H5VL_pass_through_register
448  *
449  * Purpose:     Register the pass-through VOL connector and retrieve an ID
450  *              for it.
451  *
452  * Return:      Success:    The ID for the pass-through VOL connector
453  *              Failure:    -1
454  *
455  * Programmer:  Quincey Koziol
456  *              Wednesday, November 28, 2018
457  *
458  *-------------------------------------------------------------------------
459  */
460 hid_t
H5VL_pass_through_register(void)461 H5VL_pass_through_register(void)
462 {
463     /* Singleton register the pass-through VOL connector ID */
464     if (H5VL_PASSTHRU_g < 0)
465         H5VL_PASSTHRU_g = H5VLregister_connector(&H5VL_pass_through_g, H5P_DEFAULT);
466 
467     return H5VL_PASSTHRU_g;
468 } /* end H5VL_pass_through_register() */
469 
470 /*-------------------------------------------------------------------------
471  * Function:    H5VL_pass_through_init
472  *
473  * Purpose:     Initialize this VOL connector, performing any necessary
474  *              operations for the connector that will apply to all containers
475  *              accessed with the connector.
476  *
477  * Return:      Success:    0
478  *              Failure:    -1
479  *
480  *-------------------------------------------------------------------------
481  */
482 static herr_t
H5VL_pass_through_init(hid_t vipl_id)483 H5VL_pass_through_init(hid_t vipl_id)
484 {
485 #ifdef ENABLE_PASSTHRU_LOGGING
486     printf("------- PASS THROUGH VOL INIT\n");
487 #endif
488 
489     /* Shut compiler up about unused parameter */
490     (void)vipl_id;
491 
492     return 0;
493 } /* end H5VL_pass_through_init() */
494 
495 /*---------------------------------------------------------------------------
496  * Function:    H5VL_pass_through_term
497  *
498  * Purpose:     Terminate this VOL connector, performing any necessary
499  *              operations for the connector that release connector-wide
500  *              resources (usually created / initialized with the 'init'
501  *              callback).
502  *
503  * Return:      Success:    0
504  *              Failure:    (Can't fail)
505  *
506  *---------------------------------------------------------------------------
507  */
508 static herr_t
H5VL_pass_through_term(void)509 H5VL_pass_through_term(void)
510 {
511 #ifdef ENABLE_PASSTHRU_LOGGING
512     printf("------- PASS THROUGH VOL TERM\n");
513 #endif
514 
515     /* Reset VOL ID */
516     H5VL_PASSTHRU_g = H5I_INVALID_HID;
517 
518     return 0;
519 } /* end H5VL_pass_through_term() */
520 
521 /*---------------------------------------------------------------------------
522  * Function:    H5VL_pass_through_info_copy
523  *
524  * Purpose:     Duplicate the connector's info object.
525  *
526  * Returns:     Success:    New connector info object
527  *              Failure:    NULL
528  *
529  *---------------------------------------------------------------------------
530  */
531 static void *
H5VL_pass_through_info_copy(const void * _info)532 H5VL_pass_through_info_copy(const void *_info)
533 {
534     const H5VL_pass_through_info_t *info = (const H5VL_pass_through_info_t *)_info;
535     H5VL_pass_through_info_t *      new_info;
536 
537 #ifdef ENABLE_PASSTHRU_LOGGING
538     printf("------- PASS THROUGH VOL INFO Copy\n");
539 #endif
540 
541     /* Allocate new VOL info struct for the pass through connector */
542     new_info = (H5VL_pass_through_info_t *)calloc(1, sizeof(H5VL_pass_through_info_t));
543 
544     /* Increment reference count on underlying VOL ID, and copy the VOL info */
545     new_info->under_vol_id = info->under_vol_id;
546     H5Iinc_ref(new_info->under_vol_id);
547     if (info->under_vol_info)
548         H5VLcopy_connector_info(new_info->under_vol_id, &(new_info->under_vol_info), info->under_vol_info);
549 
550     return new_info;
551 } /* end H5VL_pass_through_info_copy() */
552 
553 /*---------------------------------------------------------------------------
554  * Function:    H5VL_pass_through_info_cmp
555  *
556  * Purpose:     Compare two of the connector's info objects, setting *cmp_value,
557  *              following the same rules as strcmp().
558  *
559  * Return:      Success:    0
560  *              Failure:    -1
561  *
562  *---------------------------------------------------------------------------
563  */
564 static herr_t
H5VL_pass_through_info_cmp(int * cmp_value,const void * _info1,const void * _info2)565 H5VL_pass_through_info_cmp(int *cmp_value, const void *_info1, const void *_info2)
566 {
567     const H5VL_pass_through_info_t *info1 = (const H5VL_pass_through_info_t *)_info1;
568     const H5VL_pass_through_info_t *info2 = (const H5VL_pass_through_info_t *)_info2;
569 
570 #ifdef ENABLE_PASSTHRU_LOGGING
571     printf("------- PASS THROUGH VOL INFO Compare\n");
572 #endif
573 
574     /* Sanity checks */
575     assert(info1);
576     assert(info2);
577 
578     /* Initialize comparison value */
579     *cmp_value = 0;
580 
581     /* Compare under VOL connector classes */
582     H5VLcmp_connector_cls(cmp_value, info1->under_vol_id, info2->under_vol_id);
583     if (*cmp_value != 0)
584         return 0;
585 
586     /* Compare under VOL connector info objects */
587     H5VLcmp_connector_info(cmp_value, info1->under_vol_id, info1->under_vol_info, info2->under_vol_info);
588     if (*cmp_value != 0)
589         return 0;
590 
591     return 0;
592 } /* end H5VL_pass_through_info_cmp() */
593 
594 /*---------------------------------------------------------------------------
595  * Function:    H5VL_pass_through_info_free
596  *
597  * Purpose:     Release an info object for the connector.
598  *
599  * Note:	Take care to preserve the current HDF5 error stack
600  *		when calling HDF5 API calls.
601  *
602  * Return:      Success:    0
603  *              Failure:    -1
604  *
605  *---------------------------------------------------------------------------
606  */
607 static herr_t
H5VL_pass_through_info_free(void * _info)608 H5VL_pass_through_info_free(void *_info)
609 {
610     H5VL_pass_through_info_t *info = (H5VL_pass_through_info_t *)_info;
611     hid_t                     err_id;
612 
613 #ifdef ENABLE_PASSTHRU_LOGGING
614     printf("------- PASS THROUGH VOL INFO Free\n");
615 #endif
616 
617     err_id = H5Eget_current_stack();
618 
619     /* Release underlying VOL ID and info */
620     if (info->under_vol_info)
621         H5VLfree_connector_info(info->under_vol_id, info->under_vol_info);
622     H5Idec_ref(info->under_vol_id);
623 
624     H5Eset_current_stack(err_id);
625 
626     /* Free pass through info object itself */
627     free(info);
628 
629     return 0;
630 } /* end H5VL_pass_through_info_free() */
631 
632 /*---------------------------------------------------------------------------
633  * Function:    H5VL_pass_through_info_to_str
634  *
635  * Purpose:     Serialize an info object for this connector into a string
636  *
637  * Return:      Success:    0
638  *              Failure:    -1
639  *
640  *---------------------------------------------------------------------------
641  */
642 static herr_t
H5VL_pass_through_info_to_str(const void * _info,char ** str)643 H5VL_pass_through_info_to_str(const void *_info, char **str)
644 {
645     const H5VL_pass_through_info_t *info              = (const H5VL_pass_through_info_t *)_info;
646     H5VL_class_value_t              under_value       = (H5VL_class_value_t)-1;
647     char *                          under_vol_string  = NULL;
648     size_t                          under_vol_str_len = 0;
649 
650 #ifdef ENABLE_PASSTHRU_LOGGING
651     printf("------- PASS THROUGH VOL INFO To String\n");
652 #endif
653 
654     /* Get value and string for underlying VOL connector */
655     H5VLget_value(info->under_vol_id, &under_value);
656     H5VLconnector_info_to_str(info->under_vol_info, info->under_vol_id, &under_vol_string);
657 
658     /* Determine length of underlying VOL info string */
659     if (under_vol_string)
660         under_vol_str_len = strlen(under_vol_string);
661 
662     /* Allocate space for our info */
663     *str = (char *)H5allocate_memory(32 + under_vol_str_len, (hbool_t)0);
664     assert(*str);
665 
666     /* Encode our info
667      * Normally we'd use snprintf() here for a little extra safety, but that
668      * call had problems on Windows until recently. So, to be as platform-independent
669      * as we can, we're using sprintf() instead.
670      */
671     sprintf(*str, "under_vol=%u;under_info={%s}", (unsigned)under_value,
672             (under_vol_string ? under_vol_string : ""));
673 
674     return 0;
675 } /* end H5VL_pass_through_info_to_str() */
676 
677 /*---------------------------------------------------------------------------
678  * Function:    H5VL_pass_through_str_to_info
679  *
680  * Purpose:     Deserialize a string into an info object for this connector.
681  *
682  * Return:      Success:    0
683  *              Failure:    -1
684  *
685  *---------------------------------------------------------------------------
686  */
687 static herr_t
H5VL_pass_through_str_to_info(const char * str,void ** _info)688 H5VL_pass_through_str_to_info(const char *str, void **_info)
689 {
690     H5VL_pass_through_info_t *info;
691     unsigned                  under_vol_value;
692     const char *              under_vol_info_start, *under_vol_info_end;
693     hid_t                     under_vol_id;
694     void *                    under_vol_info = NULL;
695 
696 #ifdef ENABLE_PASSTHRU_LOGGING
697     printf("------- PASS THROUGH VOL INFO String To Info\n");
698 #endif
699 
700     /* Retrieve the underlying VOL connector value and info */
701     sscanf(str, "under_vol=%u;", &under_vol_value);
702     under_vol_id         = H5VLregister_connector_by_value((H5VL_class_value_t)under_vol_value, H5P_DEFAULT);
703     under_vol_info_start = strchr(str, '{');
704     under_vol_info_end   = strrchr(str, '}');
705     assert(under_vol_info_end > under_vol_info_start);
706     if (under_vol_info_end != (under_vol_info_start + 1)) {
707         char *under_vol_info_str;
708 
709         under_vol_info_str = (char *)malloc((size_t)(under_vol_info_end - under_vol_info_start));
710         memcpy(under_vol_info_str, under_vol_info_start + 1,
711                (size_t)((under_vol_info_end - under_vol_info_start) - 1));
712         *(under_vol_info_str + (under_vol_info_end - under_vol_info_start)) = '\0';
713 
714         H5VLconnector_str_to_info(under_vol_info_str, under_vol_id, &under_vol_info);
715 
716         free(under_vol_info_str);
717     } /* end else */
718 
719     /* Allocate new pass-through VOL connector info and set its fields */
720     info                 = (H5VL_pass_through_info_t *)calloc(1, sizeof(H5VL_pass_through_info_t));
721     info->under_vol_id   = under_vol_id;
722     info->under_vol_info = under_vol_info;
723 
724     /* Set return value */
725     *_info = info;
726 
727     return 0;
728 } /* end H5VL_pass_through_str_to_info() */
729 
730 /*---------------------------------------------------------------------------
731  * Function:    H5VL_pass_through_get_object
732  *
733  * Purpose:     Retrieve the 'data' for a VOL object.
734  *
735  * Return:      Success:    0
736  *              Failure:    -1
737  *
738  *---------------------------------------------------------------------------
739  */
740 static void *
H5VL_pass_through_get_object(const void * obj)741 H5VL_pass_through_get_object(const void *obj)
742 {
743     const H5VL_pass_through_t *o = (const H5VL_pass_through_t *)obj;
744 
745 #ifdef ENABLE_PASSTHRU_LOGGING
746     printf("------- PASS THROUGH VOL Get object\n");
747 #endif
748 
749     return H5VLget_object(o->under_object, o->under_vol_id);
750 } /* end H5VL_pass_through_get_object() */
751 
752 /*---------------------------------------------------------------------------
753  * Function:    H5VL_pass_through_get_wrap_ctx
754  *
755  * Purpose:     Retrieve a "wrapper context" for an object
756  *
757  * Return:      Success:    0
758  *              Failure:    -1
759  *
760  *---------------------------------------------------------------------------
761  */
762 static herr_t
H5VL_pass_through_get_wrap_ctx(const void * obj,void ** wrap_ctx)763 H5VL_pass_through_get_wrap_ctx(const void *obj, void **wrap_ctx)
764 {
765     const H5VL_pass_through_t *   o = (const H5VL_pass_through_t *)obj;
766     H5VL_pass_through_wrap_ctx_t *new_wrap_ctx;
767 
768 #ifdef ENABLE_PASSTHRU_LOGGING
769     printf("------- PASS THROUGH VOL WRAP CTX Get\n");
770 #endif
771 
772     /* Allocate new VOL object wrapping context for the pass through connector */
773     new_wrap_ctx = (H5VL_pass_through_wrap_ctx_t *)calloc(1, sizeof(H5VL_pass_through_wrap_ctx_t));
774 
775     /* Increment reference count on underlying VOL ID, and copy the VOL info */
776     new_wrap_ctx->under_vol_id = o->under_vol_id;
777     H5Iinc_ref(new_wrap_ctx->under_vol_id);
778     H5VLget_wrap_ctx(o->under_object, o->under_vol_id, &new_wrap_ctx->under_wrap_ctx);
779 
780     /* Set wrap context to return */
781     *wrap_ctx = new_wrap_ctx;
782 
783     return 0;
784 } /* end H5VL_pass_through_get_wrap_ctx() */
785 
786 /*---------------------------------------------------------------------------
787  * Function:    H5VL_pass_through_wrap_object
788  *
789  * Purpose:     Use a "wrapper context" to wrap a data object
790  *
791  * Return:      Success:    Pointer to wrapped object
792  *              Failure:    NULL
793  *
794  *---------------------------------------------------------------------------
795  */
796 static void *
H5VL_pass_through_wrap_object(void * obj,H5I_type_t obj_type,void * _wrap_ctx)797 H5VL_pass_through_wrap_object(void *obj, H5I_type_t obj_type, void *_wrap_ctx)
798 {
799     H5VL_pass_through_wrap_ctx_t *wrap_ctx = (H5VL_pass_through_wrap_ctx_t *)_wrap_ctx;
800     H5VL_pass_through_t *         new_obj;
801     void *                        under;
802 
803 #ifdef ENABLE_PASSTHRU_LOGGING
804     printf("------- PASS THROUGH VOL WRAP Object\n");
805 #endif
806 
807     /* Wrap the object with the underlying VOL */
808     under = H5VLwrap_object(obj, obj_type, wrap_ctx->under_vol_id, wrap_ctx->under_wrap_ctx);
809     if (under)
810         new_obj = H5VL_pass_through_new_obj(under, wrap_ctx->under_vol_id);
811     else
812         new_obj = NULL;
813 
814     return new_obj;
815 } /* end H5VL_pass_through_wrap_object() */
816 
817 /*---------------------------------------------------------------------------
818  * Function:    H5VL_pass_through_unwrap_object
819  *
820  * Purpose:     Unwrap a wrapped object, discarding the wrapper, but returning
821  *		underlying object.
822  *
823  * Return:      Success:    Pointer to unwrapped object
824  *              Failure:    NULL
825  *
826  *---------------------------------------------------------------------------
827  */
828 static void *
H5VL_pass_through_unwrap_object(void * obj)829 H5VL_pass_through_unwrap_object(void *obj)
830 {
831     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
832     void *               under;
833 
834 #ifdef ENABLE_PASSTHRU_LOGGING
835     printf("------- PASS THROUGH VOL UNWRAP Object\n");
836 #endif
837 
838     /* Unrap the object with the underlying VOL */
839     under = H5VLunwrap_object(o->under_object, o->under_vol_id);
840 
841     if (under)
842         H5VL_pass_through_free_obj(o);
843 
844     return under;
845 } /* end H5VL_pass_through_unwrap_object() */
846 
847 /*---------------------------------------------------------------------------
848  * Function:    H5VL_pass_through_free_wrap_ctx
849  *
850  * Purpose:     Release a "wrapper context" for an object
851  *
852  * Note:	Take care to preserve the current HDF5 error stack
853  *		when calling HDF5 API calls.
854  *
855  * Return:      Success:    0
856  *              Failure:    -1
857  *
858  *---------------------------------------------------------------------------
859  */
860 static herr_t
H5VL_pass_through_free_wrap_ctx(void * _wrap_ctx)861 H5VL_pass_through_free_wrap_ctx(void *_wrap_ctx)
862 {
863     H5VL_pass_through_wrap_ctx_t *wrap_ctx = (H5VL_pass_through_wrap_ctx_t *)_wrap_ctx;
864     hid_t                         err_id;
865 
866 #ifdef ENABLE_PASSTHRU_LOGGING
867     printf("------- PASS THROUGH VOL WRAP CTX Free\n");
868 #endif
869 
870     err_id = H5Eget_current_stack();
871 
872     /* Release underlying VOL ID and wrap context */
873     if (wrap_ctx->under_wrap_ctx)
874         H5VLfree_wrap_ctx(wrap_ctx->under_wrap_ctx, wrap_ctx->under_vol_id);
875     H5Idec_ref(wrap_ctx->under_vol_id);
876 
877     H5Eset_current_stack(err_id);
878 
879     /* Free pass through wrap context object itself */
880     free(wrap_ctx);
881 
882     return 0;
883 } /* end H5VL_pass_through_free_wrap_ctx() */
884 
885 /*-------------------------------------------------------------------------
886  * Function:    H5VL_pass_through_attr_create
887  *
888  * Purpose:     Creates an attribute on an object.
889  *
890  * Return:      Success:    Pointer to attribute object
891  *              Failure:    NULL
892  *
893  *-------------------------------------------------------------------------
894  */
895 static void *
H5VL_pass_through_attr_create(void * obj,const H5VL_loc_params_t * loc_params,const char * name,hid_t type_id,hid_t space_id,hid_t acpl_id,hid_t aapl_id,hid_t dxpl_id,void ** req)896 H5VL_pass_through_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t type_id,
897                               hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req)
898 {
899     H5VL_pass_through_t *attr;
900     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
901     void *               under;
902 
903 #ifdef ENABLE_PASSTHRU_LOGGING
904     printf("------- PASS THROUGH VOL ATTRIBUTE Create\n");
905 #endif
906 
907     under = H5VLattr_create(o->under_object, loc_params, o->under_vol_id, name, type_id, space_id, acpl_id,
908                             aapl_id, dxpl_id, req);
909     if (under) {
910         attr = H5VL_pass_through_new_obj(under, o->under_vol_id);
911 
912         /* Check for async request */
913         if (req && *req)
914             *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
915     } /* end if */
916     else
917         attr = NULL;
918 
919     return (void *)attr;
920 } /* end H5VL_pass_through_attr_create() */
921 
922 /*-------------------------------------------------------------------------
923  * Function:    H5VL_pass_through_attr_open
924  *
925  * Purpose:     Opens an attribute on an object.
926  *
927  * Return:      Success:    Pointer to attribute object
928  *              Failure:    NULL
929  *
930  *-------------------------------------------------------------------------
931  */
932 static void *
H5VL_pass_through_attr_open(void * obj,const H5VL_loc_params_t * loc_params,const char * name,hid_t aapl_id,hid_t dxpl_id,void ** req)933 H5VL_pass_through_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t aapl_id,
934                             hid_t dxpl_id, void **req)
935 {
936     H5VL_pass_through_t *attr;
937     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
938     void *               under;
939 
940 #ifdef ENABLE_PASSTHRU_LOGGING
941     printf("------- PASS THROUGH VOL ATTRIBUTE Open\n");
942 #endif
943 
944     under = H5VLattr_open(o->under_object, loc_params, o->under_vol_id, name, aapl_id, dxpl_id, req);
945     if (under) {
946         attr = H5VL_pass_through_new_obj(under, o->under_vol_id);
947 
948         /* Check for async request */
949         if (req && *req)
950             *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
951     } /* end if */
952     else
953         attr = NULL;
954 
955     return (void *)attr;
956 } /* end H5VL_pass_through_attr_open() */
957 
958 /*-------------------------------------------------------------------------
959  * Function:    H5VL_pass_through_attr_read
960  *
961  * Purpose:     Reads data from attribute.
962  *
963  * Return:      Success:    0
964  *              Failure:    -1
965  *
966  *-------------------------------------------------------------------------
967  */
968 static herr_t
H5VL_pass_through_attr_read(void * attr,hid_t mem_type_id,void * buf,hid_t dxpl_id,void ** req)969 H5VL_pass_through_attr_read(void *attr, hid_t mem_type_id, void *buf, hid_t dxpl_id, void **req)
970 {
971     H5VL_pass_through_t *o = (H5VL_pass_through_t *)attr;
972     herr_t               ret_value;
973 
974 #ifdef ENABLE_PASSTHRU_LOGGING
975     printf("------- PASS THROUGH VOL ATTRIBUTE Read\n");
976 #endif
977 
978     ret_value = H5VLattr_read(o->under_object, o->under_vol_id, mem_type_id, buf, dxpl_id, req);
979 
980     /* Check for async request */
981     if (req && *req)
982         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
983 
984     return ret_value;
985 } /* end H5VL_pass_through_attr_read() */
986 
987 /*-------------------------------------------------------------------------
988  * Function:    H5VL_pass_through_attr_write
989  *
990  * Purpose:     Writes data to attribute.
991  *
992  * Return:      Success:    0
993  *              Failure:    -1
994  *
995  *-------------------------------------------------------------------------
996  */
997 static herr_t
H5VL_pass_through_attr_write(void * attr,hid_t mem_type_id,const void * buf,hid_t dxpl_id,void ** req)998 H5VL_pass_through_attr_write(void *attr, hid_t mem_type_id, const void *buf, hid_t dxpl_id, void **req)
999 {
1000     H5VL_pass_through_t *o = (H5VL_pass_through_t *)attr;
1001     herr_t               ret_value;
1002 
1003 #ifdef ENABLE_PASSTHRU_LOGGING
1004     printf("------- PASS THROUGH VOL ATTRIBUTE Write\n");
1005 #endif
1006 
1007     ret_value = H5VLattr_write(o->under_object, o->under_vol_id, mem_type_id, buf, dxpl_id, req);
1008 
1009     /* Check for async request */
1010     if (req && *req)
1011         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1012 
1013     return ret_value;
1014 } /* end H5VL_pass_through_attr_write() */
1015 
1016 /*-------------------------------------------------------------------------
1017  * Function:    H5VL_pass_through_attr_get
1018  *
1019  * Purpose:     Gets information about an attribute
1020  *
1021  * Return:      Success:    0
1022  *              Failure:    -1
1023  *
1024  *-------------------------------------------------------------------------
1025  */
1026 static herr_t
H5VL_pass_through_attr_get(void * obj,H5VL_attr_get_t get_type,hid_t dxpl_id,void ** req,va_list arguments)1027 H5VL_pass_through_attr_get(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments)
1028 {
1029     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1030     herr_t               ret_value;
1031 
1032 #ifdef ENABLE_PASSTHRU_LOGGING
1033     printf("------- PASS THROUGH VOL ATTRIBUTE Get\n");
1034 #endif
1035 
1036     ret_value = H5VLattr_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments);
1037 
1038     /* Check for async request */
1039     if (req && *req)
1040         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1041 
1042     return ret_value;
1043 } /* end H5VL_pass_through_attr_get() */
1044 
1045 /*-------------------------------------------------------------------------
1046  * Function:    H5VL_pass_through_attr_specific
1047  *
1048  * Purpose:     Specific operation on attribute
1049  *
1050  * Return:      Success:    0
1051  *              Failure:    -1
1052  *
1053  *-------------------------------------------------------------------------
1054  */
1055 static herr_t
H5VL_pass_through_attr_specific(void * obj,const H5VL_loc_params_t * loc_params,H5VL_attr_specific_t specific_type,hid_t dxpl_id,void ** req,va_list arguments)1056 H5VL_pass_through_attr_specific(void *obj, const H5VL_loc_params_t *loc_params,
1057                                 H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req,
1058                                 va_list arguments)
1059 {
1060     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1061     herr_t               ret_value;
1062 
1063 #ifdef ENABLE_PASSTHRU_LOGGING
1064     printf("------- PASS THROUGH VOL ATTRIBUTE Specific\n");
1065 #endif
1066 
1067     ret_value = H5VLattr_specific(o->under_object, loc_params, o->under_vol_id, specific_type, dxpl_id, req,
1068                                   arguments);
1069 
1070     /* Check for async request */
1071     if (req && *req)
1072         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1073 
1074     return ret_value;
1075 } /* end H5VL_pass_through_attr_specific() */
1076 
1077 /*-------------------------------------------------------------------------
1078  * Function:    H5VL_pass_through_attr_optional
1079  *
1080  * Purpose:     Perform a connector-specific operation on an attribute
1081  *
1082  * Return:      Success:    0
1083  *              Failure:    -1
1084  *
1085  *-------------------------------------------------------------------------
1086  */
1087 static herr_t
H5VL_pass_through_attr_optional(void * obj,H5VL_attr_optional_t opt_type,hid_t dxpl_id,void ** req,va_list arguments)1088 H5VL_pass_through_attr_optional(void *obj, H5VL_attr_optional_t opt_type, hid_t dxpl_id, void **req,
1089                                 va_list arguments)
1090 {
1091     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1092     herr_t               ret_value;
1093 
1094 #ifdef ENABLE_PASSTHRU_LOGGING
1095     printf("------- PASS THROUGH VOL ATTRIBUTE Optional\n");
1096 #endif
1097 
1098     ret_value = H5VLattr_optional(o->under_object, o->under_vol_id, opt_type, dxpl_id, req, arguments);
1099 
1100     /* Check for async request */
1101     if (req && *req)
1102         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1103 
1104     return ret_value;
1105 } /* end H5VL_pass_through_attr_optional() */
1106 
1107 /*-------------------------------------------------------------------------
1108  * Function:    H5VL_pass_through_attr_close
1109  *
1110  * Purpose:     Closes an attribute.
1111  *
1112  * Return:      Success:    0
1113  *              Failure:    -1, attr not closed.
1114  *
1115  *-------------------------------------------------------------------------
1116  */
1117 static herr_t
H5VL_pass_through_attr_close(void * attr,hid_t dxpl_id,void ** req)1118 H5VL_pass_through_attr_close(void *attr, hid_t dxpl_id, void **req)
1119 {
1120     H5VL_pass_through_t *o = (H5VL_pass_through_t *)attr;
1121     herr_t               ret_value;
1122 
1123 #ifdef ENABLE_PASSTHRU_LOGGING
1124     printf("------- PASS THROUGH VOL ATTRIBUTE Close\n");
1125 #endif
1126 
1127     ret_value = H5VLattr_close(o->under_object, o->under_vol_id, dxpl_id, req);
1128 
1129     /* Check for async request */
1130     if (req && *req)
1131         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1132 
1133     /* Release our wrapper, if underlying attribute was closed */
1134     if (ret_value >= 0)
1135         H5VL_pass_through_free_obj(o);
1136 
1137     return ret_value;
1138 } /* end H5VL_pass_through_attr_close() */
1139 
1140 /*-------------------------------------------------------------------------
1141  * Function:    H5VL_pass_through_dataset_create
1142  *
1143  * Purpose:     Creates a dataset in a container
1144  *
1145  * Return:      Success:    Pointer to a dataset object
1146  *              Failure:    NULL
1147  *
1148  *-------------------------------------------------------------------------
1149  */
1150 static void *
H5VL_pass_through_dataset_create(void * obj,const H5VL_loc_params_t * loc_params,const char * name,hid_t lcpl_id,hid_t type_id,hid_t space_id,hid_t dcpl_id,hid_t dapl_id,hid_t dxpl_id,void ** req)1151 H5VL_pass_through_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
1152                                  hid_t lcpl_id, hid_t type_id, hid_t space_id, hid_t dcpl_id, hid_t dapl_id,
1153                                  hid_t dxpl_id, void **req)
1154 {
1155     H5VL_pass_through_t *dset;
1156     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1157     void *               under;
1158 
1159 #ifdef ENABLE_PASSTHRU_LOGGING
1160     printf("------- PASS THROUGH VOL DATASET Create\n");
1161 #endif
1162 
1163     under = H5VLdataset_create(o->under_object, loc_params, o->under_vol_id, name, lcpl_id, type_id, space_id,
1164                                dcpl_id, dapl_id, dxpl_id, req);
1165     if (under) {
1166         dset = H5VL_pass_through_new_obj(under, o->under_vol_id);
1167 
1168         /* Check for async request */
1169         if (req && *req)
1170             *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1171     } /* end if */
1172     else
1173         dset = NULL;
1174 
1175     return (void *)dset;
1176 } /* end H5VL_pass_through_dataset_create() */
1177 
1178 /*-------------------------------------------------------------------------
1179  * Function:    H5VL_pass_through_dataset_open
1180  *
1181  * Purpose:     Opens a dataset in a container
1182  *
1183  * Return:      Success:    Pointer to a dataset object
1184  *              Failure:    NULL
1185  *
1186  *-------------------------------------------------------------------------
1187  */
1188 static void *
H5VL_pass_through_dataset_open(void * obj,const H5VL_loc_params_t * loc_params,const char * name,hid_t dapl_id,hid_t dxpl_id,void ** req)1189 H5VL_pass_through_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
1190                                hid_t dapl_id, hid_t dxpl_id, void **req)
1191 {
1192     H5VL_pass_through_t *dset;
1193     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1194     void *               under;
1195 
1196 #ifdef ENABLE_PASSTHRU_LOGGING
1197     printf("------- PASS THROUGH VOL DATASET Open\n");
1198 #endif
1199 
1200     under = H5VLdataset_open(o->under_object, loc_params, o->under_vol_id, name, dapl_id, dxpl_id, req);
1201     if (under) {
1202         dset = H5VL_pass_through_new_obj(under, o->under_vol_id);
1203 
1204         /* Check for async request */
1205         if (req && *req)
1206             *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1207     } /* end if */
1208     else
1209         dset = NULL;
1210 
1211     return (void *)dset;
1212 } /* end H5VL_pass_through_dataset_open() */
1213 
1214 /*-------------------------------------------------------------------------
1215  * Function:    H5VL_pass_through_dataset_read
1216  *
1217  * Purpose:     Reads data elements from a dataset into a buffer.
1218  *
1219  * Return:      Success:    0
1220  *              Failure:    -1
1221  *
1222  *-------------------------------------------------------------------------
1223  */
1224 static herr_t
H5VL_pass_through_dataset_read(void * dset,hid_t mem_type_id,hid_t mem_space_id,hid_t file_space_id,hid_t plist_id,void * buf,void ** req)1225 H5VL_pass_through_dataset_read(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
1226                                hid_t plist_id, void *buf, void **req)
1227 {
1228     H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset;
1229     herr_t               ret_value;
1230 
1231 #ifdef ENABLE_PASSTHRU_LOGGING
1232     printf("------- PASS THROUGH VOL DATASET Read\n");
1233 #endif
1234 
1235     ret_value = H5VLdataset_read(o->under_object, o->under_vol_id, mem_type_id, mem_space_id, file_space_id,
1236                                  plist_id, buf, req);
1237 
1238     /* Check for async request */
1239     if (req && *req)
1240         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1241 
1242     return ret_value;
1243 } /* end H5VL_pass_through_dataset_read() */
1244 
1245 /*-------------------------------------------------------------------------
1246  * Function:    H5VL_pass_through_dataset_write
1247  *
1248  * Purpose:     Writes data elements from a buffer into a dataset.
1249  *
1250  * Return:      Success:    0
1251  *              Failure:    -1
1252  *
1253  *-------------------------------------------------------------------------
1254  */
1255 static herr_t
H5VL_pass_through_dataset_write(void * dset,hid_t mem_type_id,hid_t mem_space_id,hid_t file_space_id,hid_t plist_id,const void * buf,void ** req)1256 H5VL_pass_through_dataset_write(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
1257                                 hid_t plist_id, const void *buf, void **req)
1258 {
1259     H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset;
1260     herr_t               ret_value;
1261 
1262 #ifdef ENABLE_PASSTHRU_LOGGING
1263     printf("------- PASS THROUGH VOL DATASET Write\n");
1264 #endif
1265 
1266     ret_value = H5VLdataset_write(o->under_object, o->under_vol_id, mem_type_id, mem_space_id, file_space_id,
1267                                   plist_id, buf, req);
1268 
1269     /* Check for async request */
1270     if (req && *req)
1271         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1272 
1273     return ret_value;
1274 } /* end H5VL_pass_through_dataset_write() */
1275 
1276 /*-------------------------------------------------------------------------
1277  * Function:    H5VL_pass_through_dataset_get
1278  *
1279  * Purpose:     Gets information about a dataset
1280  *
1281  * Return:      Success:    0
1282  *              Failure:    -1
1283  *
1284  *-------------------------------------------------------------------------
1285  */
1286 static herr_t
H5VL_pass_through_dataset_get(void * dset,H5VL_dataset_get_t get_type,hid_t dxpl_id,void ** req,va_list arguments)1287 H5VL_pass_through_dataset_get(void *dset, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req,
1288                               va_list arguments)
1289 {
1290     H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset;
1291     herr_t               ret_value;
1292 
1293 #ifdef ENABLE_PASSTHRU_LOGGING
1294     printf("------- PASS THROUGH VOL DATASET Get\n");
1295 #endif
1296 
1297     ret_value = H5VLdataset_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments);
1298 
1299     /* Check for async request */
1300     if (req && *req)
1301         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1302 
1303     return ret_value;
1304 } /* end H5VL_pass_through_dataset_get() */
1305 
1306 /*-------------------------------------------------------------------------
1307  * Function:    H5VL_pass_through_dataset_specific
1308  *
1309  * Purpose:     Specific operation on a dataset
1310  *
1311  * Return:      Success:    0
1312  *              Failure:    -1
1313  *
1314  *-------------------------------------------------------------------------
1315  */
1316 static herr_t
H5VL_pass_through_dataset_specific(void * obj,H5VL_dataset_specific_t specific_type,hid_t dxpl_id,void ** req,va_list arguments)1317 H5VL_pass_through_dataset_specific(void *obj, H5VL_dataset_specific_t specific_type, hid_t dxpl_id,
1318                                    void **req, va_list arguments)
1319 {
1320     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1321     hid_t                under_vol_id;
1322     herr_t               ret_value;
1323 
1324 #ifdef ENABLE_PASSTHRU_LOGGING
1325     printf("------- PASS THROUGH VOL H5Dspecific\n");
1326 #endif
1327 
1328     // Save copy of underlying VOL connector ID and prov helper, in case of
1329     // refresh destroying the current object
1330     under_vol_id = o->under_vol_id;
1331 
1332     ret_value =
1333         H5VLdataset_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments);
1334 
1335     /* Check for async request */
1336     if (req && *req)
1337         *req = H5VL_pass_through_new_obj(*req, under_vol_id);
1338 
1339     return ret_value;
1340 } /* end H5VL_pass_through_dataset_specific() */
1341 
1342 /*-------------------------------------------------------------------------
1343  * Function:    H5VL_pass_through_dataset_optional
1344  *
1345  * Purpose:     Perform a connector-specific operation on a dataset
1346  *
1347  * Return:      Success:    0
1348  *              Failure:    -1
1349  *
1350  *-------------------------------------------------------------------------
1351  */
1352 static herr_t
H5VL_pass_through_dataset_optional(void * obj,H5VL_dataset_optional_t opt_type,hid_t dxpl_id,void ** req,va_list arguments)1353 H5VL_pass_through_dataset_optional(void *obj, H5VL_dataset_optional_t opt_type, hid_t dxpl_id, void **req,
1354                                    va_list arguments)
1355 {
1356     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1357     herr_t               ret_value;
1358 
1359 #ifdef ENABLE_PASSTHRU_LOGGING
1360     printf("------- PASS THROUGH VOL DATASET Optional\n");
1361 #endif
1362 
1363     ret_value = H5VLdataset_optional(o->under_object, o->under_vol_id, opt_type, dxpl_id, req, arguments);
1364 
1365     /* Check for async request */
1366     if (req && *req)
1367         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1368 
1369     return ret_value;
1370 } /* end H5VL_pass_through_dataset_optional() */
1371 
1372 /*-------------------------------------------------------------------------
1373  * Function:    H5VL_pass_through_dataset_close
1374  *
1375  * Purpose:     Closes a dataset.
1376  *
1377  * Return:      Success:    0
1378  *              Failure:    -1, dataset not closed.
1379  *
1380  *-------------------------------------------------------------------------
1381  */
1382 static herr_t
H5VL_pass_through_dataset_close(void * dset,hid_t dxpl_id,void ** req)1383 H5VL_pass_through_dataset_close(void *dset, hid_t dxpl_id, void **req)
1384 {
1385     H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset;
1386     herr_t               ret_value;
1387 
1388 #ifdef ENABLE_PASSTHRU_LOGGING
1389     printf("------- PASS THROUGH VOL DATASET Close\n");
1390 #endif
1391 
1392     ret_value = H5VLdataset_close(o->under_object, o->under_vol_id, dxpl_id, req);
1393 
1394     /* Check for async request */
1395     if (req && *req)
1396         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1397 
1398     /* Release our wrapper, if underlying dataset was closed */
1399     if (ret_value >= 0)
1400         H5VL_pass_through_free_obj(o);
1401 
1402     return ret_value;
1403 } /* end H5VL_pass_through_dataset_close() */
1404 
1405 /*-------------------------------------------------------------------------
1406  * Function:    H5VL_pass_through_datatype_commit
1407  *
1408  * Purpose:     Commits a datatype inside a container.
1409  *
1410  * Return:      Success:    Pointer to datatype object
1411  *              Failure:    NULL
1412  *
1413  *-------------------------------------------------------------------------
1414  */
1415 static void *
H5VL_pass_through_datatype_commit(void * obj,const H5VL_loc_params_t * loc_params,const char * name,hid_t type_id,hid_t lcpl_id,hid_t tcpl_id,hid_t tapl_id,hid_t dxpl_id,void ** req)1416 H5VL_pass_through_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
1417                                   hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id,
1418                                   void **req)
1419 {
1420     H5VL_pass_through_t *dt;
1421     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1422     void *               under;
1423 
1424 #ifdef ENABLE_PASSTHRU_LOGGING
1425     printf("------- PASS THROUGH VOL DATATYPE Commit\n");
1426 #endif
1427 
1428     under = H5VLdatatype_commit(o->under_object, loc_params, o->under_vol_id, name, type_id, lcpl_id, tcpl_id,
1429                                 tapl_id, dxpl_id, req);
1430     if (under) {
1431         dt = H5VL_pass_through_new_obj(under, o->under_vol_id);
1432 
1433         /* Check for async request */
1434         if (req && *req)
1435             *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1436     } /* end if */
1437     else
1438         dt = NULL;
1439 
1440     return (void *)dt;
1441 } /* end H5VL_pass_through_datatype_commit() */
1442 
1443 /*-------------------------------------------------------------------------
1444  * Function:    H5VL_pass_through_datatype_open
1445  *
1446  * Purpose:     Opens a named datatype inside a container.
1447  *
1448  * Return:      Success:    Pointer to datatype object
1449  *              Failure:    NULL
1450  *
1451  *-------------------------------------------------------------------------
1452  */
1453 static void *
H5VL_pass_through_datatype_open(void * obj,const H5VL_loc_params_t * loc_params,const char * name,hid_t tapl_id,hid_t dxpl_id,void ** req)1454 H5VL_pass_through_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
1455                                 hid_t tapl_id, hid_t dxpl_id, void **req)
1456 {
1457     H5VL_pass_through_t *dt;
1458     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1459     void *               under;
1460 
1461 #ifdef ENABLE_PASSTHRU_LOGGING
1462     printf("------- PASS THROUGH VOL DATATYPE Open\n");
1463 #endif
1464 
1465     under = H5VLdatatype_open(o->under_object, loc_params, o->under_vol_id, name, tapl_id, dxpl_id, req);
1466     if (under) {
1467         dt = H5VL_pass_through_new_obj(under, o->under_vol_id);
1468 
1469         /* Check for async request */
1470         if (req && *req)
1471             *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1472     } /* end if */
1473     else
1474         dt = NULL;
1475 
1476     return (void *)dt;
1477 } /* end H5VL_pass_through_datatype_open() */
1478 
1479 /*-------------------------------------------------------------------------
1480  * Function:    H5VL_pass_through_datatype_get
1481  *
1482  * Purpose:     Get information about a datatype
1483  *
1484  * Return:      Success:    0
1485  *              Failure:    -1
1486  *
1487  *-------------------------------------------------------------------------
1488  */
1489 static herr_t
H5VL_pass_through_datatype_get(void * dt,H5VL_datatype_get_t get_type,hid_t dxpl_id,void ** req,va_list arguments)1490 H5VL_pass_through_datatype_get(void *dt, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req,
1491                                va_list arguments)
1492 {
1493     H5VL_pass_through_t *o = (H5VL_pass_through_t *)dt;
1494     herr_t               ret_value;
1495 
1496 #ifdef ENABLE_PASSTHRU_LOGGING
1497     printf("------- PASS THROUGH VOL DATATYPE Get\n");
1498 #endif
1499 
1500     ret_value = H5VLdatatype_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments);
1501 
1502     /* Check for async request */
1503     if (req && *req)
1504         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1505 
1506     return ret_value;
1507 } /* end H5VL_pass_through_datatype_get() */
1508 
1509 /*-------------------------------------------------------------------------
1510  * Function:    H5VL_pass_through_datatype_specific
1511  *
1512  * Purpose:     Specific operations for datatypes
1513  *
1514  * Return:      Success:    0
1515  *              Failure:    -1
1516  *
1517  *-------------------------------------------------------------------------
1518  */
1519 static herr_t
H5VL_pass_through_datatype_specific(void * obj,H5VL_datatype_specific_t specific_type,hid_t dxpl_id,void ** req,va_list arguments)1520 H5VL_pass_through_datatype_specific(void *obj, H5VL_datatype_specific_t specific_type, hid_t dxpl_id,
1521                                     void **req, va_list arguments)
1522 {
1523     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1524     hid_t                under_vol_id;
1525     herr_t               ret_value;
1526 
1527 #ifdef ENABLE_PASSTHRU_LOGGING
1528     printf("------- PASS THROUGH VOL DATATYPE Specific\n");
1529 #endif
1530 
1531     // Save copy of underlying VOL connector ID and prov helper, in case of
1532     // refresh destroying the current object
1533     under_vol_id = o->under_vol_id;
1534 
1535     ret_value =
1536         H5VLdatatype_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments);
1537 
1538     /* Check for async request */
1539     if (req && *req)
1540         *req = H5VL_pass_through_new_obj(*req, under_vol_id);
1541 
1542     return ret_value;
1543 } /* end H5VL_pass_through_datatype_specific() */
1544 
1545 /*-------------------------------------------------------------------------
1546  * Function:    H5VL_pass_through_datatype_optional
1547  *
1548  * Purpose:     Perform a connector-specific operation on a datatype
1549  *
1550  * Return:      Success:    0
1551  *              Failure:    -1
1552  *
1553  *-------------------------------------------------------------------------
1554  */
1555 static herr_t
H5VL_pass_through_datatype_optional(void * obj,H5VL_datatype_optional_t opt_type,hid_t dxpl_id,void ** req,va_list arguments)1556 H5VL_pass_through_datatype_optional(void *obj, H5VL_datatype_optional_t opt_type, hid_t dxpl_id, void **req,
1557                                     va_list arguments)
1558 {
1559     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1560     herr_t               ret_value;
1561 
1562 #ifdef ENABLE_PASSTHRU_LOGGING
1563     printf("------- PASS THROUGH VOL DATATYPE Optional\n");
1564 #endif
1565 
1566     ret_value = H5VLdatatype_optional(o->under_object, o->under_vol_id, opt_type, dxpl_id, req, arguments);
1567 
1568     /* Check for async request */
1569     if (req && *req)
1570         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1571 
1572     return ret_value;
1573 } /* end H5VL_pass_through_datatype_optional() */
1574 
1575 /*-------------------------------------------------------------------------
1576  * Function:    H5VL_pass_through_datatype_close
1577  *
1578  * Purpose:     Closes a datatype.
1579  *
1580  * Return:      Success:    0
1581  *              Failure:    -1, datatype not closed.
1582  *
1583  *-------------------------------------------------------------------------
1584  */
1585 static herr_t
H5VL_pass_through_datatype_close(void * dt,hid_t dxpl_id,void ** req)1586 H5VL_pass_through_datatype_close(void *dt, hid_t dxpl_id, void **req)
1587 {
1588     H5VL_pass_through_t *o = (H5VL_pass_through_t *)dt;
1589     herr_t               ret_value;
1590 
1591 #ifdef ENABLE_PASSTHRU_LOGGING
1592     printf("------- PASS THROUGH VOL DATATYPE Close\n");
1593 #endif
1594 
1595     assert(o->under_object);
1596 
1597     ret_value = H5VLdatatype_close(o->under_object, o->under_vol_id, dxpl_id, req);
1598 
1599     /* Check for async request */
1600     if (req && *req)
1601         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1602 
1603     /* Release our wrapper, if underlying datatype was closed */
1604     if (ret_value >= 0)
1605         H5VL_pass_through_free_obj(o);
1606 
1607     return ret_value;
1608 } /* end H5VL_pass_through_datatype_close() */
1609 
1610 /*-------------------------------------------------------------------------
1611  * Function:    H5VL_pass_through_file_create
1612  *
1613  * Purpose:     Creates a container using this connector
1614  *
1615  * Return:      Success:    Pointer to a file object
1616  *              Failure:    NULL
1617  *
1618  *-------------------------------------------------------------------------
1619  */
1620 static void *
H5VL_pass_through_file_create(const char * name,unsigned flags,hid_t fcpl_id,hid_t fapl_id,hid_t dxpl_id,void ** req)1621 H5VL_pass_through_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id,
1622                               void **req)
1623 {
1624     H5VL_pass_through_info_t *info;
1625     H5VL_pass_through_t *     file;
1626     hid_t                     under_fapl_id;
1627     void *                    under;
1628 
1629 #ifdef ENABLE_PASSTHRU_LOGGING
1630     printf("------- PASS THROUGH VOL FILE Create\n");
1631 #endif
1632 
1633     /* Get copy of our VOL info from FAPL */
1634     H5Pget_vol_info(fapl_id, (void **)&info);
1635 
1636     /* Make sure we have info about the underlying VOL to be used */
1637     if (!info)
1638         return NULL;
1639 
1640     /* Copy the FAPL */
1641     under_fapl_id = H5Pcopy(fapl_id);
1642 
1643     /* Set the VOL ID and info for the underlying FAPL */
1644     H5Pset_vol(under_fapl_id, info->under_vol_id, info->under_vol_info);
1645 
1646     /* Open the file with the underlying VOL connector */
1647     under = H5VLfile_create(name, flags, fcpl_id, under_fapl_id, dxpl_id, req);
1648     if (under) {
1649         file = H5VL_pass_through_new_obj(under, info->under_vol_id);
1650 
1651         /* Check for async request */
1652         if (req && *req)
1653             *req = H5VL_pass_through_new_obj(*req, info->under_vol_id);
1654     } /* end if */
1655     else
1656         file = NULL;
1657 
1658     /* Close underlying FAPL */
1659     H5Pclose(under_fapl_id);
1660 
1661     /* Release copy of our VOL info */
1662     H5VL_pass_through_info_free(info);
1663 
1664     return (void *)file;
1665 } /* end H5VL_pass_through_file_create() */
1666 
1667 /*-------------------------------------------------------------------------
1668  * Function:    H5VL_pass_through_file_open
1669  *
1670  * Purpose:     Opens a container created with this connector
1671  *
1672  * Return:      Success:    Pointer to a file object
1673  *              Failure:    NULL
1674  *
1675  *-------------------------------------------------------------------------
1676  */
1677 static void *
H5VL_pass_through_file_open(const char * name,unsigned flags,hid_t fapl_id,hid_t dxpl_id,void ** req)1678 H5VL_pass_through_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req)
1679 {
1680     H5VL_pass_through_info_t *info;
1681     H5VL_pass_through_t *     file;
1682     hid_t                     under_fapl_id;
1683     void *                    under;
1684 
1685 #ifdef ENABLE_PASSTHRU_LOGGING
1686     printf("------- PASS THROUGH VOL FILE Open\n");
1687 #endif
1688 
1689     /* Get copy of our VOL info from FAPL */
1690     H5Pget_vol_info(fapl_id, (void **)&info);
1691 
1692     /* Make sure we have info about the underlying VOL to be used */
1693     if (!info)
1694         return NULL;
1695 
1696     /* Copy the FAPL */
1697     under_fapl_id = H5Pcopy(fapl_id);
1698 
1699     /* Set the VOL ID and info for the underlying FAPL */
1700     H5Pset_vol(under_fapl_id, info->under_vol_id, info->under_vol_info);
1701 
1702     /* Open the file with the underlying VOL connector */
1703     under = H5VLfile_open(name, flags, under_fapl_id, dxpl_id, req);
1704     if (under) {
1705         file = H5VL_pass_through_new_obj(under, info->under_vol_id);
1706 
1707         /* Check for async request */
1708         if (req && *req)
1709             *req = H5VL_pass_through_new_obj(*req, info->under_vol_id);
1710     } /* end if */
1711     else
1712         file = NULL;
1713 
1714     /* Close underlying FAPL */
1715     H5Pclose(under_fapl_id);
1716 
1717     /* Release copy of our VOL info */
1718     H5VL_pass_through_info_free(info);
1719 
1720     return (void *)file;
1721 } /* end H5VL_pass_through_file_open() */
1722 
1723 /*-------------------------------------------------------------------------
1724  * Function:    H5VL_pass_through_file_get
1725  *
1726  * Purpose:     Get info about a file
1727  *
1728  * Return:      Success:    0
1729  *              Failure:    -1
1730  *
1731  *-------------------------------------------------------------------------
1732  */
1733 static herr_t
H5VL_pass_through_file_get(void * file,H5VL_file_get_t get_type,hid_t dxpl_id,void ** req,va_list arguments)1734 H5VL_pass_through_file_get(void *file, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments)
1735 {
1736     H5VL_pass_through_t *o = (H5VL_pass_through_t *)file;
1737     herr_t               ret_value;
1738 
1739 #ifdef ENABLE_PASSTHRU_LOGGING
1740     printf("------- PASS THROUGH VOL FILE Get\n");
1741 #endif
1742 
1743     ret_value = H5VLfile_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments);
1744 
1745     /* Check for async request */
1746     if (req && *req)
1747         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1748 
1749     return ret_value;
1750 } /* end H5VL_pass_through_file_get() */
1751 
1752 /*-------------------------------------------------------------------------
1753  * Function:    H5VL_pass_through_file_specific_reissue
1754  *
1755  * Purpose:     Re-wrap vararg arguments into a va_list and reissue the
1756  *              file specific callback to the underlying VOL connector.
1757  *
1758  * Return:      Success:    0
1759  *              Failure:    -1
1760  *
1761  *-------------------------------------------------------------------------
1762  */
1763 static herr_t
H5VL_pass_through_file_specific_reissue(void * obj,hid_t connector_id,H5VL_file_specific_t specific_type,hid_t dxpl_id,void ** req,...)1764 H5VL_pass_through_file_specific_reissue(void *obj, hid_t connector_id, H5VL_file_specific_t specific_type,
1765                                         hid_t dxpl_id, void **req, ...)
1766 {
1767     va_list arguments;
1768     herr_t  ret_value;
1769 
1770     va_start(arguments, req);
1771     ret_value = H5VLfile_specific(obj, connector_id, specific_type, dxpl_id, req, arguments);
1772     va_end(arguments);
1773 
1774     return ret_value;
1775 } /* end H5VL_pass_through_file_specific_reissue() */
1776 
1777 /*-------------------------------------------------------------------------
1778  * Function:    H5VL_pass_through_file_specific
1779  *
1780  * Purpose:     Specific operation on file
1781  *
1782  * Return:      Success:    0
1783  *              Failure:    -1
1784  *
1785  *-------------------------------------------------------------------------
1786  */
1787 static herr_t
H5VL_pass_through_file_specific(void * file,H5VL_file_specific_t specific_type,hid_t dxpl_id,void ** req,va_list arguments)1788 H5VL_pass_through_file_specific(void *file, H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req,
1789                                 va_list arguments)
1790 {
1791     H5VL_pass_through_t *o            = (H5VL_pass_through_t *)file;
1792     hid_t                under_vol_id = -1;
1793     herr_t               ret_value;
1794 
1795 #ifdef ENABLE_PASSTHRU_LOGGING
1796     printf("------- PASS THROUGH VOL FILE Specific\n");
1797 #endif
1798 
1799     /* Unpack arguments to get at the child file pointer when mounting a file */
1800     if (specific_type == H5VL_FILE_MOUNT) {
1801         H5I_type_t           loc_type;
1802         const char *         name;
1803         H5VL_pass_through_t *child_file;
1804         hid_t                plist_id;
1805 
1806         /* Retrieve parameters for 'mount' operation, so we can unwrap the child file */
1807         loc_type   = (H5I_type_t)va_arg(arguments, int); /* enum work-around */
1808         name       = va_arg(arguments, const char *);
1809         child_file = (H5VL_pass_through_t *)va_arg(arguments, void *);
1810         plist_id   = va_arg(arguments, hid_t);
1811 
1812         /* Keep the correct underlying VOL ID for possible async request token */
1813         under_vol_id = o->under_vol_id;
1814 
1815         /* Re-issue 'file specific' call, using the unwrapped pieces */
1816         ret_value = H5VL_pass_through_file_specific_reissue(o->under_object, o->under_vol_id, specific_type,
1817                                                             dxpl_id, req, (int)loc_type, name,
1818                                                             child_file->under_object, plist_id);
1819     } /* end if */
1820     else if (specific_type == H5VL_FILE_IS_ACCESSIBLE || specific_type == H5VL_FILE_DELETE) {
1821         H5VL_pass_through_info_t *info;
1822         hid_t                     fapl_id, under_fapl_id;
1823         const char *              name;
1824         htri_t *                  ret;
1825 
1826         /* Get the arguments for the 'is accessible' check */
1827         fapl_id = va_arg(arguments, hid_t);
1828         name    = va_arg(arguments, const char *);
1829         ret     = va_arg(arguments, htri_t *);
1830 
1831         /* Get copy of our VOL info from FAPL */
1832         H5Pget_vol_info(fapl_id, (void **)&info);
1833 
1834         /* Make sure we have info about the underlying VOL to be used */
1835         if (!info)
1836             return (-1);
1837 
1838         /* Copy the FAPL */
1839         under_fapl_id = H5Pcopy(fapl_id);
1840 
1841         /* Set the VOL ID and info for the underlying FAPL */
1842         H5Pset_vol(under_fapl_id, info->under_vol_id, info->under_vol_info);
1843 
1844         /* Keep the correct underlying VOL ID for possible async request token */
1845         under_vol_id = info->under_vol_id;
1846 
1847         /* Re-issue 'file specific' call */
1848         ret_value = H5VL_pass_through_file_specific_reissue(NULL, info->under_vol_id, specific_type, dxpl_id,
1849                                                             req, under_fapl_id, name, ret);
1850 
1851         /* Close underlying FAPL */
1852         H5Pclose(under_fapl_id);
1853 
1854         /* Release copy of our VOL info */
1855         H5VL_pass_through_info_free(info);
1856     } /* end else-if */
1857     else {
1858         va_list my_arguments;
1859 
1860         /* Make a copy of the argument list for later, if reopening */
1861         if (specific_type == H5VL_FILE_REOPEN)
1862             va_copy(my_arguments, arguments);
1863 
1864         /* Keep the correct underlying VOL ID for possible async request token */
1865         under_vol_id = o->under_vol_id;
1866 
1867         ret_value =
1868             H5VLfile_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments);
1869 
1870         /* Wrap file struct pointer, if we reopened one */
1871         if (specific_type == H5VL_FILE_REOPEN) {
1872             if (ret_value >= 0) {
1873                 void **ret = va_arg(my_arguments, void **);
1874 
1875                 if (ret && *ret)
1876                     *ret = H5VL_pass_through_new_obj(*ret, o->under_vol_id);
1877             } /* end if */
1878 
1879             /* Finish use of copied vararg list */
1880             va_end(my_arguments);
1881         } /* end if */
1882     }     /* end else */
1883 
1884     /* Check for async request */
1885     if (req && *req)
1886         *req = H5VL_pass_through_new_obj(*req, under_vol_id);
1887 
1888     return ret_value;
1889 } /* end H5VL_pass_through_file_specific() */
1890 
1891 /*-------------------------------------------------------------------------
1892  * Function:    H5VL_pass_through_file_optional
1893  *
1894  * Purpose:     Perform a connector-specific operation on a file
1895  *
1896  * Return:      Success:    0
1897  *              Failure:    -1
1898  *
1899  *-------------------------------------------------------------------------
1900  */
1901 static herr_t
H5VL_pass_through_file_optional(void * file,H5VL_file_optional_t opt_type,hid_t dxpl_id,void ** req,va_list arguments)1902 H5VL_pass_through_file_optional(void *file, H5VL_file_optional_t opt_type, hid_t dxpl_id, void **req,
1903                                 va_list arguments)
1904 {
1905     H5VL_pass_through_t *o = (H5VL_pass_through_t *)file;
1906     herr_t               ret_value;
1907 
1908 #ifdef ENABLE_PASSTHRU_LOGGING
1909     printf("------- PASS THROUGH VOL File Optional\n");
1910 #endif
1911 
1912     ret_value = H5VLfile_optional(o->under_object, o->under_vol_id, opt_type, dxpl_id, req, arguments);
1913 
1914     /* Check for async request */
1915     if (req && *req)
1916         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1917 
1918     return ret_value;
1919 } /* end H5VL_pass_through_file_optional() */
1920 
1921 /*-------------------------------------------------------------------------
1922  * Function:    H5VL_pass_through_file_close
1923  *
1924  * Purpose:     Closes a file.
1925  *
1926  * Return:      Success:    0
1927  *              Failure:    -1, file not closed.
1928  *
1929  *-------------------------------------------------------------------------
1930  */
1931 static herr_t
H5VL_pass_through_file_close(void * file,hid_t dxpl_id,void ** req)1932 H5VL_pass_through_file_close(void *file, hid_t dxpl_id, void **req)
1933 {
1934     H5VL_pass_through_t *o = (H5VL_pass_through_t *)file;
1935     herr_t               ret_value;
1936 
1937 #ifdef ENABLE_PASSTHRU_LOGGING
1938     printf("------- PASS THROUGH VOL FILE Close\n");
1939 #endif
1940 
1941     ret_value = H5VLfile_close(o->under_object, o->under_vol_id, dxpl_id, req);
1942 
1943     /* Check for async request */
1944     if (req && *req)
1945         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1946 
1947     /* Release our wrapper, if underlying file was closed */
1948     if (ret_value >= 0)
1949         H5VL_pass_through_free_obj(o);
1950 
1951     return ret_value;
1952 } /* end H5VL_pass_through_file_close() */
1953 
1954 /*-------------------------------------------------------------------------
1955  * Function:    H5VL_pass_through_group_create
1956  *
1957  * Purpose:     Creates a group inside a container
1958  *
1959  * Return:      Success:    Pointer to a group object
1960  *              Failure:    NULL
1961  *
1962  *-------------------------------------------------------------------------
1963  */
1964 static void *
H5VL_pass_through_group_create(void * obj,const H5VL_loc_params_t * loc_params,const char * name,hid_t lcpl_id,hid_t gcpl_id,hid_t gapl_id,hid_t dxpl_id,void ** req)1965 H5VL_pass_through_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
1966                                hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req)
1967 {
1968     H5VL_pass_through_t *group;
1969     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
1970     void *               under;
1971 
1972 #ifdef ENABLE_PASSTHRU_LOGGING
1973     printf("------- PASS THROUGH VOL GROUP Create\n");
1974 #endif
1975 
1976     under = H5VLgroup_create(o->under_object, loc_params, o->under_vol_id, name, lcpl_id, gcpl_id, gapl_id,
1977                              dxpl_id, req);
1978     if (under) {
1979         group = H5VL_pass_through_new_obj(under, o->under_vol_id);
1980 
1981         /* Check for async request */
1982         if (req && *req)
1983             *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
1984     } /* end if */
1985     else
1986         group = NULL;
1987 
1988     return (void *)group;
1989 } /* end H5VL_pass_through_group_create() */
1990 
1991 /*-------------------------------------------------------------------------
1992  * Function:    H5VL_pass_through_group_open
1993  *
1994  * Purpose:     Opens a group inside a container
1995  *
1996  * Return:      Success:    Pointer to a group object
1997  *              Failure:    NULL
1998  *
1999  *-------------------------------------------------------------------------
2000  */
2001 static void *
H5VL_pass_through_group_open(void * obj,const H5VL_loc_params_t * loc_params,const char * name,hid_t gapl_id,hid_t dxpl_id,void ** req)2002 H5VL_pass_through_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t gapl_id,
2003                              hid_t dxpl_id, void **req)
2004 {
2005     H5VL_pass_through_t *group;
2006     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2007     void *               under;
2008 
2009 #ifdef ENABLE_PASSTHRU_LOGGING
2010     printf("------- PASS THROUGH VOL GROUP Open\n");
2011 #endif
2012 
2013     under = H5VLgroup_open(o->under_object, loc_params, o->under_vol_id, name, gapl_id, dxpl_id, req);
2014     if (under) {
2015         group = H5VL_pass_through_new_obj(under, o->under_vol_id);
2016 
2017         /* Check for async request */
2018         if (req && *req)
2019             *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
2020     } /* end if */
2021     else
2022         group = NULL;
2023 
2024     return (void *)group;
2025 } /* end H5VL_pass_through_group_open() */
2026 
2027 /*-------------------------------------------------------------------------
2028  * Function:    H5VL_pass_through_group_get
2029  *
2030  * Purpose:     Get info about a group
2031  *
2032  * Return:      Success:    0
2033  *              Failure:    -1
2034  *
2035  *-------------------------------------------------------------------------
2036  */
2037 static herr_t
H5VL_pass_through_group_get(void * obj,H5VL_group_get_t get_type,hid_t dxpl_id,void ** req,va_list arguments)2038 H5VL_pass_through_group_get(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id, void **req,
2039                             va_list arguments)
2040 {
2041     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2042     herr_t               ret_value;
2043 
2044 #ifdef ENABLE_PASSTHRU_LOGGING
2045     printf("------- PASS THROUGH VOL GROUP Get\n");
2046 #endif
2047 
2048     ret_value = H5VLgroup_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments);
2049 
2050     /* Check for async request */
2051     if (req && *req)
2052         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
2053 
2054     return ret_value;
2055 } /* end H5VL_pass_through_group_get() */
2056 
2057 /*-------------------------------------------------------------------------
2058  * Function:    H5VL_pass_through_group_specific
2059  *
2060  * Purpose:     Specific operation on a group
2061  *
2062  * Return:      Success:    0
2063  *              Failure:    -1
2064  *
2065  *-------------------------------------------------------------------------
2066  */
2067 static herr_t
H5VL_pass_through_group_specific(void * obj,H5VL_group_specific_t specific_type,hid_t dxpl_id,void ** req,va_list arguments)2068 H5VL_pass_through_group_specific(void *obj, H5VL_group_specific_t specific_type, hid_t dxpl_id, void **req,
2069                                  va_list arguments)
2070 {
2071     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2072     hid_t                under_vol_id;
2073     herr_t               ret_value;
2074 
2075 #ifdef ENABLE_PASSTHRU_LOGGING
2076     printf("------- PASS THROUGH VOL GROUP Specific\n");
2077 #endif
2078 
2079     // Save copy of underlying VOL connector ID and prov helper, in case of
2080     // refresh destroying the current object
2081     under_vol_id = o->under_vol_id;
2082 
2083     ret_value = H5VLgroup_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments);
2084 
2085     /* Check for async request */
2086     if (req && *req)
2087         *req = H5VL_pass_through_new_obj(*req, under_vol_id);
2088 
2089     return ret_value;
2090 } /* end H5VL_pass_through_group_specific() */
2091 
2092 /*-------------------------------------------------------------------------
2093  * Function:    H5VL_pass_through_group_optional
2094  *
2095  * Purpose:     Perform a connector-specific operation on a group
2096  *
2097  * Return:      Success:    0
2098  *              Failure:    -1
2099  *
2100  *-------------------------------------------------------------------------
2101  */
2102 static herr_t
H5VL_pass_through_group_optional(void * obj,H5VL_group_optional_t opt_type,hid_t dxpl_id,void ** req,va_list arguments)2103 H5VL_pass_through_group_optional(void *obj, H5VL_group_optional_t opt_type, hid_t dxpl_id, void **req,
2104                                  va_list arguments)
2105 {
2106     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2107     herr_t               ret_value;
2108 
2109 #ifdef ENABLE_PASSTHRU_LOGGING
2110     printf("------- PASS THROUGH VOL GROUP Optional\n");
2111 #endif
2112 
2113     ret_value = H5VLgroup_optional(o->under_object, o->under_vol_id, opt_type, dxpl_id, req, arguments);
2114 
2115     /* Check for async request */
2116     if (req && *req)
2117         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
2118 
2119     return ret_value;
2120 } /* end H5VL_pass_through_group_optional() */
2121 
2122 /*-------------------------------------------------------------------------
2123  * Function:    H5VL_pass_through_group_close
2124  *
2125  * Purpose:     Closes a group.
2126  *
2127  * Return:      Success:    0
2128  *              Failure:    -1, group not closed.
2129  *
2130  *-------------------------------------------------------------------------
2131  */
2132 static herr_t
H5VL_pass_through_group_close(void * grp,hid_t dxpl_id,void ** req)2133 H5VL_pass_through_group_close(void *grp, hid_t dxpl_id, void **req)
2134 {
2135     H5VL_pass_through_t *o = (H5VL_pass_through_t *)grp;
2136     herr_t               ret_value;
2137 
2138 #ifdef ENABLE_PASSTHRU_LOGGING
2139     printf("------- PASS THROUGH VOL H5Gclose\n");
2140 #endif
2141 
2142     ret_value = H5VLgroup_close(o->under_object, o->under_vol_id, dxpl_id, req);
2143 
2144     /* Check for async request */
2145     if (req && *req)
2146         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
2147 
2148     /* Release our wrapper, if underlying file was closed */
2149     if (ret_value >= 0)
2150         H5VL_pass_through_free_obj(o);
2151 
2152     return ret_value;
2153 } /* end H5VL_pass_through_group_close() */
2154 
2155 /*-------------------------------------------------------------------------
2156  * Function:    H5VL_pass_through_link_create_reissue
2157  *
2158  * Purpose:     Re-wrap vararg arguments into a va_list and reissue the
2159  *              link create callback to the underlying VOL connector.
2160  *
2161  * Return:      Success:    0
2162  *              Failure:    -1
2163  *
2164  *-------------------------------------------------------------------------
2165  */
2166 static herr_t
H5VL_pass_through_link_create_reissue(H5VL_link_create_type_t create_type,void * obj,const H5VL_loc_params_t * loc_params,hid_t connector_id,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id,void ** req,...)2167 H5VL_pass_through_link_create_reissue(H5VL_link_create_type_t create_type, void *obj,
2168                                       const H5VL_loc_params_t *loc_params, hid_t connector_id, hid_t lcpl_id,
2169                                       hid_t lapl_id, hid_t dxpl_id, void **req, ...)
2170 {
2171     va_list arguments;
2172     herr_t  ret_value;
2173 
2174     va_start(arguments, req);
2175     ret_value = H5VLlink_create(create_type, obj, loc_params, connector_id, lcpl_id, lapl_id, dxpl_id, req,
2176                                 arguments);
2177     va_end(arguments);
2178 
2179     return ret_value;
2180 } /* end H5VL_pass_through_link_create_reissue() */
2181 
2182 /*-------------------------------------------------------------------------
2183  * Function:    H5VL_pass_through_link_create
2184  *
2185  * Purpose:     Creates a hard / soft / UD / external link.
2186  *
2187  * Return:      Success:    0
2188  *              Failure:    -1
2189  *
2190  *-------------------------------------------------------------------------
2191  */
2192 static herr_t
H5VL_pass_through_link_create(H5VL_link_create_type_t create_type,void * obj,const H5VL_loc_params_t * loc_params,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id,void ** req,va_list arguments)2193 H5VL_pass_through_link_create(H5VL_link_create_type_t create_type, void *obj,
2194                               const H5VL_loc_params_t *loc_params, hid_t lcpl_id, hid_t lapl_id,
2195                               hid_t dxpl_id, void **req, va_list arguments)
2196 {
2197     H5VL_pass_through_t *o            = (H5VL_pass_through_t *)obj;
2198     hid_t                under_vol_id = -1;
2199     herr_t               ret_value;
2200 
2201 #ifdef ENABLE_PASSTHRU_LOGGING
2202     printf("------- PASS THROUGH VOL LINK Create\n");
2203 #endif
2204 
2205     /* Try to retrieve the "under" VOL id */
2206     if (o)
2207         under_vol_id = o->under_vol_id;
2208 
2209     /* Fix up the link target object for hard link creation */
2210     if (H5VL_LINK_CREATE_HARD == create_type) {
2211         void *             cur_obj;
2212         H5VL_loc_params_t *cur_params;
2213 
2214         /* Retrieve the object & loc params for the link target */
2215         cur_obj    = va_arg(arguments, void *);
2216         cur_params = va_arg(arguments, H5VL_loc_params_t *);
2217 
2218         /* If it's a non-NULL pointer, find the 'under object' and re-set the property */
2219         if (cur_obj) {
2220             /* Check if we still need the "under" VOL ID */
2221             if (under_vol_id < 0)
2222                 under_vol_id = ((H5VL_pass_through_t *)cur_obj)->under_vol_id;
2223 
2224             /* Set the object for the link target */
2225             cur_obj = ((H5VL_pass_through_t *)cur_obj)->under_object;
2226         } /* end if */
2227 
2228         /* Re-issue 'link create' call, using the unwrapped pieces */
2229         ret_value = H5VL_pass_through_link_create_reissue(create_type, (o ? o->under_object : NULL),
2230                                                           loc_params, under_vol_id, lcpl_id, lapl_id, dxpl_id,
2231                                                           req, cur_obj, cur_params);
2232     } /* end if */
2233     else
2234         ret_value = H5VLlink_create(create_type, (o ? o->under_object : NULL), loc_params, under_vol_id,
2235                                     lcpl_id, lapl_id, dxpl_id, req, arguments);
2236 
2237     /* Check for async request */
2238     if (req && *req)
2239         *req = H5VL_pass_through_new_obj(*req, under_vol_id);
2240 
2241     return ret_value;
2242 } /* end H5VL_pass_through_link_create() */
2243 
2244 /*-------------------------------------------------------------------------
2245  * Function:    H5VL_pass_through_link_copy
2246  *
2247  * Purpose:     Renames an object within an HDF5 container and copies it to a new
2248  *              group.  The original name SRC is unlinked from the group graph
2249  *              and then inserted with the new name DST (which can specify a
2250  *              new path for the object) as an atomic operation. The names
2251  *              are interpreted relative to SRC_LOC_ID and
2252  *              DST_LOC_ID, which are either file IDs or group ID.
2253  *
2254  * Return:      Success:    0
2255  *              Failure:    -1
2256  *
2257  *-------------------------------------------------------------------------
2258  */
2259 static herr_t
H5VL_pass_through_link_copy(void * src_obj,const H5VL_loc_params_t * loc_params1,void * dst_obj,const H5VL_loc_params_t * loc_params2,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id,void ** req)2260 H5VL_pass_through_link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj,
2261                             const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id,
2262                             void **req)
2263 {
2264     H5VL_pass_through_t *o_src        = (H5VL_pass_through_t *)src_obj;
2265     H5VL_pass_through_t *o_dst        = (H5VL_pass_through_t *)dst_obj;
2266     hid_t                under_vol_id = -1;
2267     herr_t               ret_value;
2268 
2269 #ifdef ENABLE_PASSTHRU_LOGGING
2270     printf("------- PASS THROUGH VOL LINK Copy\n");
2271 #endif
2272 
2273     /* Retrieve the "under" VOL id */
2274     if (o_src)
2275         under_vol_id = o_src->under_vol_id;
2276     else if (o_dst)
2277         under_vol_id = o_dst->under_vol_id;
2278     assert(under_vol_id > 0);
2279 
2280     ret_value =
2281         H5VLlink_copy((o_src ? o_src->under_object : NULL), loc_params1, (o_dst ? o_dst->under_object : NULL),
2282                       loc_params2, under_vol_id, lcpl_id, lapl_id, dxpl_id, req);
2283 
2284     /* Check for async request */
2285     if (req && *req)
2286         *req = H5VL_pass_through_new_obj(*req, under_vol_id);
2287 
2288     return ret_value;
2289 } /* end H5VL_pass_through_link_copy() */
2290 
2291 /*-------------------------------------------------------------------------
2292  * Function:    H5VL_pass_through_link_move
2293  *
2294  * Purpose:     Moves a link within an HDF5 file to a new group.  The original
2295  *              name SRC is unlinked from the group graph
2296  *              and then inserted with the new name DST (which can specify a
2297  *              new path for the object) as an atomic operation. The names
2298  *              are interpreted relative to SRC_LOC_ID and
2299  *              DST_LOC_ID, which are either file IDs or group ID.
2300  *
2301  * Return:      Success:    0
2302  *              Failure:    -1
2303  *
2304  *-------------------------------------------------------------------------
2305  */
2306 static herr_t
H5VL_pass_through_link_move(void * src_obj,const H5VL_loc_params_t * loc_params1,void * dst_obj,const H5VL_loc_params_t * loc_params2,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id,void ** req)2307 H5VL_pass_through_link_move(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj,
2308                             const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id,
2309                             void **req)
2310 {
2311     H5VL_pass_through_t *o_src        = (H5VL_pass_through_t *)src_obj;
2312     H5VL_pass_through_t *o_dst        = (H5VL_pass_through_t *)dst_obj;
2313     hid_t                under_vol_id = -1;
2314     herr_t               ret_value;
2315 
2316 #ifdef ENABLE_PASSTHRU_LOGGING
2317     printf("------- PASS THROUGH VOL LINK Move\n");
2318 #endif
2319 
2320     /* Retrieve the "under" VOL id */
2321     if (o_src)
2322         under_vol_id = o_src->under_vol_id;
2323     else if (o_dst)
2324         under_vol_id = o_dst->under_vol_id;
2325     assert(under_vol_id > 0);
2326 
2327     ret_value =
2328         H5VLlink_move((o_src ? o_src->under_object : NULL), loc_params1, (o_dst ? o_dst->under_object : NULL),
2329                       loc_params2, under_vol_id, lcpl_id, lapl_id, dxpl_id, req);
2330 
2331     /* Check for async request */
2332     if (req && *req)
2333         *req = H5VL_pass_through_new_obj(*req, under_vol_id);
2334 
2335     return ret_value;
2336 } /* end H5VL_pass_through_link_move() */
2337 
2338 /*-------------------------------------------------------------------------
2339  * Function:    H5VL_pass_through_link_get
2340  *
2341  * Purpose:     Get info about a link
2342  *
2343  * Return:      Success:    0
2344  *              Failure:    -1
2345  *
2346  *-------------------------------------------------------------------------
2347  */
2348 static herr_t
H5VL_pass_through_link_get(void * obj,const H5VL_loc_params_t * loc_params,H5VL_link_get_t get_type,hid_t dxpl_id,void ** req,va_list arguments)2349 H5VL_pass_through_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_t get_type,
2350                            hid_t dxpl_id, void **req, va_list arguments)
2351 {
2352     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2353     herr_t               ret_value;
2354 
2355 #ifdef ENABLE_PASSTHRU_LOGGING
2356     printf("------- PASS THROUGH VOL LINK Get\n");
2357 #endif
2358 
2359     ret_value = H5VLlink_get(o->under_object, loc_params, o->under_vol_id, get_type, dxpl_id, req, arguments);
2360 
2361     /* Check for async request */
2362     if (req && *req)
2363         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
2364 
2365     return ret_value;
2366 } /* end H5VL_pass_through_link_get() */
2367 
2368 /*-------------------------------------------------------------------------
2369  * Function:    H5VL_pass_through_link_specific
2370  *
2371  * Purpose:     Specific operation on a link
2372  *
2373  * Return:      Success:    0
2374  *              Failure:    -1
2375  *
2376  *-------------------------------------------------------------------------
2377  */
2378 static herr_t
H5VL_pass_through_link_specific(void * obj,const H5VL_loc_params_t * loc_params,H5VL_link_specific_t specific_type,hid_t dxpl_id,void ** req,va_list arguments)2379 H5VL_pass_through_link_specific(void *obj, const H5VL_loc_params_t *loc_params,
2380                                 H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req,
2381                                 va_list arguments)
2382 {
2383     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2384     herr_t               ret_value;
2385 
2386 #ifdef ENABLE_PASSTHRU_LOGGING
2387     printf("------- PASS THROUGH VOL LINK Specific\n");
2388 #endif
2389 
2390     ret_value = H5VLlink_specific(o->under_object, loc_params, o->under_vol_id, specific_type, dxpl_id, req,
2391                                   arguments);
2392 
2393     /* Check for async request */
2394     if (req && *req)
2395         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
2396 
2397     return ret_value;
2398 } /* end H5VL_pass_through_link_specific() */
2399 
2400 /*-------------------------------------------------------------------------
2401  * Function:    H5VL_pass_through_link_optional
2402  *
2403  * Purpose:     Perform a connector-specific operation on a link
2404  *
2405  * Return:      Success:    0
2406  *              Failure:    -1
2407  *
2408  *-------------------------------------------------------------------------
2409  */
2410 static herr_t
H5VL_pass_through_link_optional(void * obj,H5VL_link_optional_t opt_type,hid_t dxpl_id,void ** req,va_list arguments)2411 H5VL_pass_through_link_optional(void *obj, H5VL_link_optional_t opt_type, hid_t dxpl_id, void **req,
2412                                 va_list arguments)
2413 {
2414     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2415     herr_t               ret_value;
2416 
2417 #ifdef ENABLE_PASSTHRU_LOGGING
2418     printf("------- PASS THROUGH VOL LINK Optional\n");
2419 #endif
2420 
2421     ret_value = H5VLlink_optional(o->under_object, o->under_vol_id, opt_type, dxpl_id, req, arguments);
2422 
2423     /* Check for async request */
2424     if (req && *req)
2425         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
2426 
2427     return ret_value;
2428 } /* end H5VL_pass_through_link_optional() */
2429 
2430 /*-------------------------------------------------------------------------
2431  * Function:    H5VL_pass_through_object_open
2432  *
2433  * Purpose:     Opens an object inside a container.
2434  *
2435  * Return:      Success:    Pointer to object
2436  *              Failure:    NULL
2437  *
2438  *-------------------------------------------------------------------------
2439  */
2440 static void *
H5VL_pass_through_object_open(void * obj,const H5VL_loc_params_t * loc_params,H5I_type_t * opened_type,hid_t dxpl_id,void ** req)2441 H5VL_pass_through_object_open(void *obj, const H5VL_loc_params_t *loc_params, H5I_type_t *opened_type,
2442                               hid_t dxpl_id, void **req)
2443 {
2444     H5VL_pass_through_t *new_obj;
2445     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2446     void *               under;
2447 
2448 #ifdef ENABLE_PASSTHRU_LOGGING
2449     printf("------- PASS THROUGH VOL OBJECT Open\n");
2450 #endif
2451 
2452     under = H5VLobject_open(o->under_object, loc_params, o->under_vol_id, opened_type, dxpl_id, req);
2453     if (under) {
2454         new_obj = H5VL_pass_through_new_obj(under, o->under_vol_id);
2455 
2456         /* Check for async request */
2457         if (req && *req)
2458             *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
2459     } /* end if */
2460     else
2461         new_obj = NULL;
2462 
2463     return (void *)new_obj;
2464 } /* end H5VL_pass_through_object_open() */
2465 
2466 /*-------------------------------------------------------------------------
2467  * Function:    H5VL_pass_through_object_copy
2468  *
2469  * Purpose:     Copies an object inside a container.
2470  *
2471  * Return:      Success:    0
2472  *              Failure:    -1
2473  *
2474  *-------------------------------------------------------------------------
2475  */
2476 static herr_t
H5VL_pass_through_object_copy(void * src_obj,const H5VL_loc_params_t * src_loc_params,const char * src_name,void * dst_obj,const H5VL_loc_params_t * dst_loc_params,const char * dst_name,hid_t ocpypl_id,hid_t lcpl_id,hid_t dxpl_id,void ** req)2477 H5VL_pass_through_object_copy(void *src_obj, const H5VL_loc_params_t *src_loc_params, const char *src_name,
2478                               void *dst_obj, const H5VL_loc_params_t *dst_loc_params, const char *dst_name,
2479                               hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req)
2480 {
2481     H5VL_pass_through_t *o_src = (H5VL_pass_through_t *)src_obj;
2482     H5VL_pass_through_t *o_dst = (H5VL_pass_through_t *)dst_obj;
2483     herr_t               ret_value;
2484 
2485 #ifdef ENABLE_PASSTHRU_LOGGING
2486     printf("------- PASS THROUGH VOL OBJECT Copy\n");
2487 #endif
2488 
2489     ret_value =
2490         H5VLobject_copy(o_src->under_object, src_loc_params, src_name, o_dst->under_object, dst_loc_params,
2491                         dst_name, o_src->under_vol_id, ocpypl_id, lcpl_id, dxpl_id, req);
2492 
2493     /* Check for async request */
2494     if (req && *req)
2495         *req = H5VL_pass_through_new_obj(*req, o_src->under_vol_id);
2496 
2497     return ret_value;
2498 } /* end H5VL_pass_through_object_copy() */
2499 
2500 /*-------------------------------------------------------------------------
2501  * Function:    H5VL_pass_through_object_get
2502  *
2503  * Purpose:     Get info about an object
2504  *
2505  * Return:      Success:    0
2506  *              Failure:    -1
2507  *
2508  *-------------------------------------------------------------------------
2509  */
2510 static herr_t
H5VL_pass_through_object_get(void * obj,const H5VL_loc_params_t * loc_params,H5VL_object_get_t get_type,hid_t dxpl_id,void ** req,va_list arguments)2511 H5VL_pass_through_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type,
2512                              hid_t dxpl_id, void **req, va_list arguments)
2513 {
2514     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2515     herr_t               ret_value;
2516 
2517 #ifdef ENABLE_PASSTHRU_LOGGING
2518     printf("------- PASS THROUGH VOL OBJECT Get\n");
2519 #endif
2520 
2521     ret_value =
2522         H5VLobject_get(o->under_object, loc_params, o->under_vol_id, get_type, dxpl_id, req, arguments);
2523 
2524     /* Check for async request */
2525     if (req && *req)
2526         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
2527 
2528     return ret_value;
2529 } /* end H5VL_pass_through_object_get() */
2530 
2531 /*-------------------------------------------------------------------------
2532  * Function:    H5VL_pass_through_object_specific
2533  *
2534  * Purpose:     Specific operation on an object
2535  *
2536  * Return:      Success:    0
2537  *              Failure:    -1
2538  *
2539  *-------------------------------------------------------------------------
2540  */
2541 static herr_t
H5VL_pass_through_object_specific(void * obj,const H5VL_loc_params_t * loc_params,H5VL_object_specific_t specific_type,hid_t dxpl_id,void ** req,va_list arguments)2542 H5VL_pass_through_object_specific(void *obj, const H5VL_loc_params_t *loc_params,
2543                                   H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req,
2544                                   va_list arguments)
2545 {
2546     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2547     hid_t                under_vol_id;
2548     herr_t               ret_value;
2549 
2550 #ifdef ENABLE_PASSTHRU_LOGGING
2551     printf("------- PASS THROUGH VOL OBJECT Specific\n");
2552 #endif
2553 
2554     // Save copy of underlying VOL connector ID and prov helper, in case of
2555     // refresh destroying the current object
2556     under_vol_id = o->under_vol_id;
2557 
2558     ret_value = H5VLobject_specific(o->under_object, loc_params, o->under_vol_id, specific_type, dxpl_id, req,
2559                                     arguments);
2560 
2561     /* Check for async request */
2562     if (req && *req)
2563         *req = H5VL_pass_through_new_obj(*req, under_vol_id);
2564 
2565     return ret_value;
2566 } /* end H5VL_pass_through_object_specific() */
2567 
2568 /*-------------------------------------------------------------------------
2569  * Function:    H5VL_pass_through_object_optional
2570  *
2571  * Purpose:     Perform a connector-specific operation for an object
2572  *
2573  * Return:      Success:    0
2574  *              Failure:    -1
2575  *
2576  *-------------------------------------------------------------------------
2577  */
2578 static herr_t
H5VL_pass_through_object_optional(void * obj,H5VL_object_optional_t opt_type,hid_t dxpl_id,void ** req,va_list arguments)2579 H5VL_pass_through_object_optional(void *obj, H5VL_object_optional_t opt_type, hid_t dxpl_id, void **req,
2580                                   va_list arguments)
2581 {
2582     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2583     herr_t               ret_value;
2584 
2585 #ifdef ENABLE_PASSTHRU_LOGGING
2586     printf("------- PASS THROUGH VOL OBJECT Optional\n");
2587 #endif
2588 
2589     ret_value = H5VLobject_optional(o->under_object, o->under_vol_id, opt_type, dxpl_id, req, arguments);
2590 
2591     /* Check for async request */
2592     if (req && *req)
2593         *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
2594 
2595     return ret_value;
2596 } /* end H5VL_pass_through_object_optional() */
2597 
2598 /*-------------------------------------------------------------------------
2599  * Function:    H5VL_pass_through_introspect_get_conn_clss
2600  *
2601  * Purpose:     Query the connector class.
2602  *
2603  * Return:      SUCCEED / FAIL
2604  *
2605  *-------------------------------------------------------------------------
2606  */
2607 herr_t
H5VL_pass_through_introspect_get_conn_cls(void * obj,H5VL_get_conn_lvl_t lvl,const H5VL_class_t ** conn_cls)2608 H5VL_pass_through_introspect_get_conn_cls(void *obj, H5VL_get_conn_lvl_t lvl, const H5VL_class_t **conn_cls)
2609 {
2610     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2611     herr_t               ret_value;
2612 
2613 #ifdef ENABLE_PASSTHRU_LOGGING
2614     printf("------- PASS THROUGH VOL INTROSPECT GetConnCls\n");
2615 #endif
2616 
2617     /* Check for querying this connector's class */
2618     if (H5VL_GET_CONN_LVL_CURR == lvl) {
2619         *conn_cls = &H5VL_pass_through_g;
2620         ret_value = 0;
2621     } /* end if */
2622     else
2623         ret_value = H5VLintrospect_get_conn_cls(o->under_object, o->under_vol_id, lvl, conn_cls);
2624 
2625     return ret_value;
2626 } /* end H5VL_pass_through_introspect_get_conn_cls() */
2627 
2628 /*-------------------------------------------------------------------------
2629  * Function:    H5VL_pass_through_introspect_opt_query
2630  *
2631  * Purpose:     Query if an optional operation is supported by this connector
2632  *
2633  * Return:      SUCCEED / FAIL
2634  *
2635  *-------------------------------------------------------------------------
2636  */
2637 herr_t
H5VL_pass_through_introspect_opt_query(void * obj,H5VL_subclass_t cls,int opt_type,hbool_t * supported)2638 H5VL_pass_through_introspect_opt_query(void *obj, H5VL_subclass_t cls, int opt_type, hbool_t *supported)
2639 {
2640     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2641     herr_t               ret_value;
2642 
2643 #ifdef ENABLE_PASSTHRU_LOGGING
2644     printf("------- PASS THROUGH VOL INTROSPECT OptQuery\n");
2645 #endif
2646 
2647     ret_value = H5VLintrospect_opt_query(o->under_object, o->under_vol_id, cls, opt_type, supported);
2648 
2649     return ret_value;
2650 } /* end H5VL_pass_through_introspect_opt_query() */
2651 
2652 /*-------------------------------------------------------------------------
2653  * Function:    H5VL_pass_through_request_wait
2654  *
2655  * Purpose:     Wait (with a timeout) for an async operation to complete
2656  *
2657  * Note:        Releases the request if the operation has completed and the
2658  *              connector callback succeeds
2659  *
2660  * Return:      Success:    0
2661  *              Failure:    -1
2662  *
2663  *-------------------------------------------------------------------------
2664  */
2665 static herr_t
H5VL_pass_through_request_wait(void * obj,uint64_t timeout,H5ES_status_t * status)2666 H5VL_pass_through_request_wait(void *obj, uint64_t timeout, H5ES_status_t *status)
2667 {
2668     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2669     herr_t               ret_value;
2670 
2671 #ifdef ENABLE_PASSTHRU_LOGGING
2672     printf("------- PASS THROUGH VOL REQUEST Wait\n");
2673 #endif
2674 
2675     ret_value = H5VLrequest_wait(o->under_object, o->under_vol_id, timeout, status);
2676 
2677     if (ret_value >= 0 && *status != H5ES_STATUS_IN_PROGRESS)
2678         H5VL_pass_through_free_obj(o);
2679 
2680     return ret_value;
2681 } /* end H5VL_pass_through_request_wait() */
2682 
2683 /*-------------------------------------------------------------------------
2684  * Function:    H5VL_pass_through_request_notify
2685  *
2686  * Purpose:     Registers a user callback to be invoked when an asynchronous
2687  *              operation completes
2688  *
2689  * Note:        Releases the request, if connector callback succeeds
2690  *
2691  * Return:      Success:    0
2692  *              Failure:    -1
2693  *
2694  *-------------------------------------------------------------------------
2695  */
2696 static herr_t
H5VL_pass_through_request_notify(void * obj,H5VL_request_notify_t cb,void * ctx)2697 H5VL_pass_through_request_notify(void *obj, H5VL_request_notify_t cb, void *ctx)
2698 {
2699     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2700     herr_t               ret_value;
2701 
2702 #ifdef ENABLE_PASSTHRU_LOGGING
2703     printf("------- PASS THROUGH VOL REQUEST Notify\n");
2704 #endif
2705 
2706     ret_value = H5VLrequest_notify(o->under_object, o->under_vol_id, cb, ctx);
2707 
2708     if (ret_value >= 0)
2709         H5VL_pass_through_free_obj(o);
2710 
2711     return ret_value;
2712 } /* end H5VL_pass_through_request_notify() */
2713 
2714 /*-------------------------------------------------------------------------
2715  * Function:    H5VL_pass_through_request_cancel
2716  *
2717  * Purpose:     Cancels an asynchronous operation
2718  *
2719  * Note:        Releases the request, if connector callback succeeds
2720  *
2721  * Return:      Success:    0
2722  *              Failure:    -1
2723  *
2724  *-------------------------------------------------------------------------
2725  */
2726 static herr_t
H5VL_pass_through_request_cancel(void * obj)2727 H5VL_pass_through_request_cancel(void *obj)
2728 {
2729     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2730     herr_t               ret_value;
2731 
2732 #ifdef ENABLE_PASSTHRU_LOGGING
2733     printf("------- PASS THROUGH VOL REQUEST Cancel\n");
2734 #endif
2735 
2736     ret_value = H5VLrequest_cancel(o->under_object, o->under_vol_id);
2737 
2738     if (ret_value >= 0)
2739         H5VL_pass_through_free_obj(o);
2740 
2741     return ret_value;
2742 } /* end H5VL_pass_through_request_cancel() */
2743 
2744 /*-------------------------------------------------------------------------
2745  * Function:    H5VL_pass_through_request_specific_reissue
2746  *
2747  * Purpose:     Re-wrap vararg arguments into a va_list and reissue the
2748  *              request specific callback to the underlying VOL connector.
2749  *
2750  * Return:      Success:    0
2751  *              Failure:    -1
2752  *
2753  *-------------------------------------------------------------------------
2754  */
2755 static herr_t
H5VL_pass_through_request_specific_reissue(void * obj,hid_t connector_id,H5VL_request_specific_t specific_type,...)2756 H5VL_pass_through_request_specific_reissue(void *obj, hid_t connector_id,
2757                                            H5VL_request_specific_t specific_type, ...)
2758 {
2759     va_list arguments;
2760     herr_t  ret_value;
2761 
2762     va_start(arguments, specific_type);
2763     ret_value = H5VLrequest_specific(obj, connector_id, specific_type, arguments);
2764     va_end(arguments);
2765 
2766     return ret_value;
2767 } /* end H5VL_pass_through_request_specific_reissue() */
2768 
2769 /*-------------------------------------------------------------------------
2770  * Function:    H5VL_pass_through_request_specific
2771  *
2772  * Purpose:     Specific operation on a request
2773  *
2774  * Return:      Success:    0
2775  *              Failure:    -1
2776  *
2777  *-------------------------------------------------------------------------
2778  */
2779 static herr_t
H5VL_pass_through_request_specific(void * obj,H5VL_request_specific_t specific_type,va_list arguments)2780 H5VL_pass_through_request_specific(void *obj, H5VL_request_specific_t specific_type, va_list arguments)
2781 {
2782     herr_t ret_value = -1;
2783 
2784 #ifdef ENABLE_PASSTHRU_LOGGING
2785     printf("------- PASS THROUGH VOL REQUEST Specific\n");
2786 #endif
2787 
2788     if (H5VL_REQUEST_WAITANY == specific_type || H5VL_REQUEST_WAITSOME == specific_type ||
2789         H5VL_REQUEST_WAITALL == specific_type) {
2790         va_list tmp_arguments;
2791         size_t  req_count;
2792 
2793         /* Sanity check */
2794         assert(obj == NULL);
2795 
2796         /* Get enough info to call the underlying connector */
2797         va_copy(tmp_arguments, arguments);
2798         req_count = va_arg(tmp_arguments, size_t);
2799 
2800         /* Can only use a request to invoke the underlying VOL connector when there's >0 requests */
2801         if (req_count > 0) {
2802             void **              req_array;
2803             void **              under_req_array;
2804             uint64_t             timeout;
2805             H5VL_pass_through_t *o;
2806             size_t               u; /* Local index variable */
2807 
2808             /* Get the request array */
2809             req_array = va_arg(tmp_arguments, void **);
2810 
2811             /* Get a request to use for determining the underlying VOL connector */
2812             o = (H5VL_pass_through_t *)req_array[0];
2813 
2814             /* Create array of underlying VOL requests */
2815             under_req_array = (void **)malloc(req_count * sizeof(void **));
2816             for (u = 0; u < req_count; u++)
2817                 under_req_array[u] = ((H5VL_pass_through_t *)req_array[u])->under_object;
2818 
2819             /* Remove the timeout value from the vararg list (it's used in all the calls below) */
2820             timeout = va_arg(tmp_arguments, uint64_t);
2821 
2822             /* Release requests that have completed */
2823             if (H5VL_REQUEST_WAITANY == specific_type) {
2824                 size_t *       idx;    /* Pointer to the index of completed request */
2825                 H5ES_status_t *status; /* Pointer to the request's status */
2826 
2827                 /* Retrieve the remaining arguments */
2828                 idx = va_arg(tmp_arguments, size_t *);
2829                 assert(*idx <= req_count);
2830                 status = va_arg(tmp_arguments, H5ES_status_t *);
2831 
2832                 /* Reissue the WAITANY 'request specific' call */
2833                 ret_value = H5VL_pass_through_request_specific_reissue(o->under_object, o->under_vol_id,
2834                                                                        specific_type, req_count,
2835                                                                        under_req_array, timeout, idx, status);
2836 
2837                 /* Release the completed request, if it completed */
2838                 if (ret_value >= 0 && *status != H5ES_STATUS_IN_PROGRESS) {
2839                     H5VL_pass_through_t *tmp_o;
2840 
2841                     tmp_o = (H5VL_pass_through_t *)req_array[*idx];
2842                     H5VL_pass_through_free_obj(tmp_o);
2843                 } /* end if */
2844             }     /* end if */
2845             else if (H5VL_REQUEST_WAITSOME == specific_type) {
2846                 size_t *       outcount;          /* # of completed requests */
2847                 unsigned *     array_of_indices;  /* Array of indices for completed requests */
2848                 H5ES_status_t *array_of_statuses; /* Array of statuses for completed requests */
2849 
2850                 /* Retrieve the remaining arguments */
2851                 outcount = va_arg(tmp_arguments, size_t *);
2852                 assert(*outcount <= req_count);
2853                 array_of_indices  = va_arg(tmp_arguments, unsigned *);
2854                 array_of_statuses = va_arg(tmp_arguments, H5ES_status_t *);
2855 
2856                 /* Reissue the WAITSOME 'request specific' call */
2857                 ret_value = H5VL_pass_through_request_specific_reissue(
2858                     o->under_object, o->under_vol_id, specific_type, req_count, under_req_array, timeout,
2859                     outcount, array_of_indices, array_of_statuses);
2860 
2861                 /* If any requests completed, release them */
2862                 if (ret_value >= 0 && *outcount > 0) {
2863                     unsigned *idx_array; /* Array of indices of completed requests */
2864 
2865                     /* Retrieve the array of completed request indices */
2866                     idx_array = va_arg(tmp_arguments, unsigned *);
2867 
2868                     /* Release the completed requests */
2869                     for (u = 0; u < *outcount; u++) {
2870                         H5VL_pass_through_t *tmp_o;
2871 
2872                         tmp_o = (H5VL_pass_through_t *)req_array[idx_array[u]];
2873                         H5VL_pass_through_free_obj(tmp_o);
2874                     }                             /* end for */
2875                 }                                 /* end if */
2876             }                                     /* end else-if */
2877             else {                                /* H5VL_REQUEST_WAITALL == specific_type */
2878                 H5ES_status_t *array_of_statuses; /* Array of statuses for completed requests */
2879 
2880                 /* Retrieve the remaining arguments */
2881                 array_of_statuses = va_arg(tmp_arguments, H5ES_status_t *);
2882 
2883                 /* Reissue the WAITALL 'request specific' call */
2884                 ret_value = H5VL_pass_through_request_specific_reissue(
2885                     o->under_object, o->under_vol_id, specific_type, req_count, under_req_array, timeout,
2886                     array_of_statuses);
2887 
2888                 /* Release the completed requests */
2889                 if (ret_value >= 0) {
2890                     for (u = 0; u < req_count; u++) {
2891                         if (array_of_statuses[u] != H5ES_STATUS_IN_PROGRESS) {
2892                             H5VL_pass_through_t *tmp_o;
2893 
2894                             tmp_o = (H5VL_pass_through_t *)req_array[u];
2895                             H5VL_pass_through_free_obj(tmp_o);
2896                         } /* end if */
2897                     }     /* end for */
2898                 }         /* end if */
2899             }             /* end else */
2900 
2901             /* Release array of requests for underlying connector */
2902             free(under_req_array);
2903         } /* end if */
2904 
2905         /* Finish use of copied vararg list */
2906         va_end(tmp_arguments);
2907     } /* end if */
2908     else {
2909         H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2910 
2911         ret_value = H5VLrequest_specific(o->under_object, o->under_vol_id, specific_type, arguments);
2912     } /* end else */
2913 
2914     return ret_value;
2915 } /* end H5VL_pass_through_request_specific() */
2916 
2917 /*-------------------------------------------------------------------------
2918  * Function:    H5VL_pass_through_request_optional
2919  *
2920  * Purpose:     Perform a connector-specific operation for a request
2921  *
2922  * Return:      Success:    0
2923  *              Failure:    -1
2924  *
2925  *-------------------------------------------------------------------------
2926  */
2927 static herr_t
H5VL_pass_through_request_optional(void * obj,H5VL_request_optional_t opt_type,va_list arguments)2928 H5VL_pass_through_request_optional(void *obj, H5VL_request_optional_t opt_type, va_list arguments)
2929 {
2930     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2931     herr_t               ret_value;
2932 
2933 #ifdef ENABLE_PASSTHRU_LOGGING
2934     printf("------- PASS THROUGH VOL REQUEST Optional\n");
2935 #endif
2936 
2937     ret_value = H5VLrequest_optional(o->under_object, o->under_vol_id, opt_type, arguments);
2938 
2939     return ret_value;
2940 } /* end H5VL_pass_through_request_optional() */
2941 
2942 /*-------------------------------------------------------------------------
2943  * Function:    H5VL_pass_through_request_free
2944  *
2945  * Purpose:     Releases a request, allowing the operation to complete without
2946  *              application tracking
2947  *
2948  * Return:      Success:    0
2949  *              Failure:    -1
2950  *
2951  *-------------------------------------------------------------------------
2952  */
2953 static herr_t
H5VL_pass_through_request_free(void * obj)2954 H5VL_pass_through_request_free(void *obj)
2955 {
2956     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2957     herr_t               ret_value;
2958 
2959 #ifdef ENABLE_PASSTHRU_LOGGING
2960     printf("------- PASS THROUGH VOL REQUEST Free\n");
2961 #endif
2962 
2963     ret_value = H5VLrequest_free(o->under_object, o->under_vol_id);
2964 
2965     if (ret_value >= 0)
2966         H5VL_pass_through_free_obj(o);
2967 
2968     return ret_value;
2969 } /* end H5VL_pass_through_request_free() */
2970 
2971 /*-------------------------------------------------------------------------
2972  * Function:    H5VL_pass_through_blob_put
2973  *
2974  * Purpose:     Handles the blob 'put' callback
2975  *
2976  * Return:      SUCCEED / FAIL
2977  *
2978  *-------------------------------------------------------------------------
2979  */
2980 herr_t
H5VL_pass_through_blob_put(void * obj,const void * buf,size_t size,void * blob_id,void * ctx)2981 H5VL_pass_through_blob_put(void *obj, const void *buf, size_t size, void *blob_id, void *ctx)
2982 {
2983     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
2984     herr_t               ret_value;
2985 
2986 #ifdef ENABLE_PASSTHRU_LOGGING
2987     printf("------- PASS THROUGH VOL BLOB Put\n");
2988 #endif
2989 
2990     ret_value = H5VLblob_put(o->under_object, o->under_vol_id, buf, size, blob_id, ctx);
2991 
2992     return ret_value;
2993 } /* end H5VL_pass_through_blob_put() */
2994 
2995 /*-------------------------------------------------------------------------
2996  * Function:    H5VL_pass_through_blob_get
2997  *
2998  * Purpose:     Handles the blob 'get' callback
2999  *
3000  * Return:      SUCCEED / FAIL
3001  *
3002  *-------------------------------------------------------------------------
3003  */
3004 herr_t
H5VL_pass_through_blob_get(void * obj,const void * blob_id,void * buf,size_t size,void * ctx)3005 H5VL_pass_through_blob_get(void *obj, const void *blob_id, void *buf, size_t size, void *ctx)
3006 {
3007     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
3008     herr_t               ret_value;
3009 
3010 #ifdef ENABLE_PASSTHRU_LOGGING
3011     printf("------- PASS THROUGH VOL BLOB Get\n");
3012 #endif
3013 
3014     ret_value = H5VLblob_get(o->under_object, o->under_vol_id, blob_id, buf, size, ctx);
3015 
3016     return ret_value;
3017 } /* end H5VL_pass_through_blob_get() */
3018 
3019 /*-------------------------------------------------------------------------
3020  * Function:    H5VL_pass_through_blob_specific
3021  *
3022  * Purpose:     Handles the blob 'specific' callback
3023  *
3024  * Return:      SUCCEED / FAIL
3025  *
3026  *-------------------------------------------------------------------------
3027  */
3028 herr_t
H5VL_pass_through_blob_specific(void * obj,void * blob_id,H5VL_blob_specific_t specific_type,va_list arguments)3029 H5VL_pass_through_blob_specific(void *obj, void *blob_id, H5VL_blob_specific_t specific_type,
3030                                 va_list arguments)
3031 {
3032     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
3033     herr_t               ret_value;
3034 
3035 #ifdef ENABLE_PASSTHRU_LOGGING
3036     printf("------- PASS THROUGH VOL BLOB Specific\n");
3037 #endif
3038 
3039     ret_value = H5VLblob_specific(o->under_object, o->under_vol_id, blob_id, specific_type, arguments);
3040 
3041     return ret_value;
3042 } /* end H5VL_pass_through_blob_specific() */
3043 
3044 /*-------------------------------------------------------------------------
3045  * Function:    H5VL_pass_through_blob_optional
3046  *
3047  * Purpose:     Handles the blob 'optional' callback
3048  *
3049  * Return:      SUCCEED / FAIL
3050  *
3051  *-------------------------------------------------------------------------
3052  */
3053 herr_t
H5VL_pass_through_blob_optional(void * obj,void * blob_id,H5VL_blob_optional_t opt_type,va_list arguments)3054 H5VL_pass_through_blob_optional(void *obj, void *blob_id, H5VL_blob_optional_t opt_type, va_list arguments)
3055 {
3056     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
3057     herr_t               ret_value;
3058 
3059 #ifdef ENABLE_PASSTHRU_LOGGING
3060     printf("------- PASS THROUGH VOL BLOB Optional\n");
3061 #endif
3062 
3063     ret_value = H5VLblob_optional(o->under_object, o->under_vol_id, blob_id, opt_type, arguments);
3064 
3065     return ret_value;
3066 } /* end H5VL_pass_through_blob_optional() */
3067 
3068 /*---------------------------------------------------------------------------
3069  * Function:    H5VL_pass_through_token_cmp
3070  *
3071  * Purpose:     Compare two of the connector's object tokens, setting
3072  *              *cmp_value, following the same rules as strcmp().
3073  *
3074  * Return:      Success:    0
3075  *              Failure:    -1
3076  *
3077  *---------------------------------------------------------------------------
3078  */
3079 static herr_t
H5VL_pass_through_token_cmp(void * obj,const H5O_token_t * token1,const H5O_token_t * token2,int * cmp_value)3080 H5VL_pass_through_token_cmp(void *obj, const H5O_token_t *token1, const H5O_token_t *token2, int *cmp_value)
3081 {
3082     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
3083     herr_t               ret_value;
3084 
3085 #ifdef ENABLE_PASSTHRU_LOGGING
3086     printf("------- PASS THROUGH VOL TOKEN Compare\n");
3087 #endif
3088 
3089     /* Sanity checks */
3090     assert(obj);
3091     assert(token1);
3092     assert(token2);
3093     assert(cmp_value);
3094 
3095     ret_value = H5VLtoken_cmp(o->under_object, o->under_vol_id, token1, token2, cmp_value);
3096 
3097     return ret_value;
3098 } /* end H5VL_pass_through_token_cmp() */
3099 
3100 /*---------------------------------------------------------------------------
3101  * Function:    H5VL_pass_through_token_to_str
3102  *
3103  * Purpose:     Serialize the connector's object token into a string.
3104  *
3105  * Return:      Success:    0
3106  *              Failure:    -1
3107  *
3108  *---------------------------------------------------------------------------
3109  */
3110 static herr_t
H5VL_pass_through_token_to_str(void * obj,H5I_type_t obj_type,const H5O_token_t * token,char ** token_str)3111 H5VL_pass_through_token_to_str(void *obj, H5I_type_t obj_type, const H5O_token_t *token, char **token_str)
3112 {
3113     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
3114     herr_t               ret_value;
3115 
3116 #ifdef ENABLE_PASSTHRU_LOGGING
3117     printf("------- PASS THROUGH VOL TOKEN To string\n");
3118 #endif
3119 
3120     /* Sanity checks */
3121     assert(obj);
3122     assert(token);
3123     assert(token_str);
3124 
3125     ret_value = H5VLtoken_to_str(o->under_object, obj_type, o->under_vol_id, token, token_str);
3126 
3127     return ret_value;
3128 } /* end H5VL_pass_through_token_to_str() */
3129 
3130 /*---------------------------------------------------------------------------
3131  * Function:    H5VL_pass_through_token_from_str
3132  *
3133  * Purpose:     Deserialize the connector's object token from a string.
3134  *
3135  * Return:      Success:    0
3136  *              Failure:    -1
3137  *
3138  *---------------------------------------------------------------------------
3139  */
3140 static herr_t
H5VL_pass_through_token_from_str(void * obj,H5I_type_t obj_type,const char * token_str,H5O_token_t * token)3141 H5VL_pass_through_token_from_str(void *obj, H5I_type_t obj_type, const char *token_str, H5O_token_t *token)
3142 {
3143     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
3144     herr_t               ret_value;
3145 
3146 #ifdef ENABLE_PASSTHRU_LOGGING
3147     printf("------- PASS THROUGH VOL TOKEN From string\n");
3148 #endif
3149 
3150     /* Sanity checks */
3151     assert(obj);
3152     assert(token);
3153     assert(token_str);
3154 
3155     ret_value = H5VLtoken_from_str(o->under_object, obj_type, o->under_vol_id, token_str, token);
3156 
3157     return ret_value;
3158 } /* end H5VL_pass_through_token_from_str() */
3159 
3160 /*-------------------------------------------------------------------------
3161  * Function:    H5VL_pass_through_optional
3162  *
3163  * Purpose:     Handles the generic 'optional' callback
3164  *
3165  * Return:      SUCCEED / FAIL
3166  *
3167  *-------------------------------------------------------------------------
3168  */
3169 herr_t
H5VL_pass_through_optional(void * obj,int op_type,hid_t dxpl_id,void ** req,va_list arguments)3170 H5VL_pass_through_optional(void *obj, int op_type, hid_t dxpl_id, void **req, va_list arguments)
3171 {
3172     H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
3173     herr_t               ret_value;
3174 
3175 #ifdef ENABLE_PASSTHRU_LOGGING
3176     printf("------- PASS THROUGH VOL generic Optional\n");
3177 #endif
3178 
3179     ret_value = H5VLoptional(o->under_object, o->under_vol_id, op_type, dxpl_id, req, arguments);
3180 
3181     return ret_value;
3182 } /* end H5VL_pass_through_optional() */
3183