Coverage Report

Created: 2026-06-09 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5VL.c
Line
Count
Source
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 LICENSE 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:     The Virtual Object Layer as described in documentation.
15
 *              The purpose is to provide an abstraction on how to access the
16
 *              underlying HDF5 container, whether in a local file with
17
 *              a specific file format, or remotely on other machines, etc...
18
 */
19
20
/****************/
21
/* Module Setup */
22
/****************/
23
24
#include "H5VLmodule.h" /* This source code file is part of the H5VL module */
25
26
/***********/
27
/* Headers */
28
/***********/
29
30
#include "H5private.h"  /* Generic Functions                    */
31
#include "H5Eprivate.h" /* Error handling                       */
32
#include "H5Iprivate.h" /* IDs                                  */
33
#include "H5Pprivate.h" /* Property lists                       */
34
#include "H5Tprivate.h" /* Datatypes                            */
35
#include "H5VLpkg.h"    /* Virtual Object Layer                 */
36
37
/* VOL connectors */
38
#include "H5VLnative_private.h" /* Native VOL connector                 */
39
40
/****************/
41
/* Local Macros */
42
/****************/
43
44
/******************/
45
/* Local Typedefs */
46
/******************/
47
48
/********************/
49
/* Local Prototypes */
50
/********************/
51
52
/*********************/
53
/* Package Variables */
54
/*********************/
55
56
/*****************************/
57
/* Library Private Variables */
58
/*****************************/
59
60
/*******************/
61
/* Local Variables */
62
/*******************/
63
64
/*-------------------------------------------------------------------------
65
 * Function:    H5VLregister_connector
66
 *
67
 * Purpose:     Registers a new VOL connector as a member of the virtual object
68
 *              layer class.
69
 *
70
 *              VIPL_ID is a VOL initialization property list which must be
71
 *              created with H5Pcreate(H5P_VOL_INITIALIZE) (or H5P_DEFAULT).
72
 *
73
 * Return:      Success:    A VOL connector ID which is good until the
74
 *                          library is closed or the connector is
75
 *                          unregistered.
76
 *
77
 *              Failure:    H5I_INVALID_HID
78
 *
79
 *-------------------------------------------------------------------------
80
 */
81
hid_t
82
H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id)
83
0
{
84
0
    H5VL_connector_t *connector = NULL;
85
0
    hid_t             ret_value = H5I_INVALID_HID; /* Return value */
86
87
0
    FUNC_ENTER_API(H5I_INVALID_HID)
88
89
    /* Check VOL initialization property list */
90
0
    if (H5P_DEFAULT == vipl_id)
91
0
        vipl_id = H5P_VOL_INITIALIZE_DEFAULT;
92
0
    else if (true != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE))
93
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list");
94
95
    /* Register connector */
96
0
    if (NULL == (connector = H5VL__register_connector_by_class(cls, vipl_id)))
97
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL class");
98
99
    /* Get ID for connector */
100
0
    if ((ret_value = H5I_register(H5I_VOL, connector, true)) < 0)
101
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector");
102
103
0
done:
104
0
    if (ret_value < 0)
105
        /* Decrement refcount on connector */
106
0
        if (connector && H5VL_conn_dec_rc(connector) < 0)
107
0
            HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID,
108
0
                        "unable to decrement ref count on VOL connector");
109
110
0
    FUNC_LEAVE_API(ret_value)
111
0
} /* end H5VLregister_connector() */
112
113
/*-------------------------------------------------------------------------
114
 * Function:    H5VLregister_connector_by_name
115
 *
116
 * Purpose:     Registers a new VOL connector as a member of the virtual object
117
 *              layer class.
118
 *
119
 *              VIPL_ID is a VOL initialization property list which must be
120
 *              created with H5Pcreate(H5P_VOL_INITIALIZE) (or H5P_DEFAULT).
121
 *
122
 * Return:      Success:    A VOL connector ID which is good until the
123
 *                          library is closed or the connector is
124
 *                          unregistered.
125
 *
126
 *              Failure:    H5I_INVALID_HID
127
 *
128
 *-------------------------------------------------------------------------
129
 */
130
hid_t
131
H5VLregister_connector_by_name(const char *name, hid_t vipl_id)
132
0
{
133
0
    H5VL_connector_t *connector = NULL;
134
0
    hid_t             ret_value = H5I_INVALID_HID; /* Return value */
135
136
0
    FUNC_ENTER_API(H5I_INVALID_HID)
137
138
    /* Check arguments */
139
0
    if (!name)
140
0
        HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "null VOL connector name is disallowed");
141
0
    if (0 == strlen(name))
142
0
        HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID,
143
0
                    "zero-length VOL connector name is disallowed");
144
145
    /* Check VOL initialization property list */
146
0
    if (H5P_DEFAULT == vipl_id)
147
0
        vipl_id = H5P_VOL_INITIALIZE_DEFAULT;
148
0
    else if (true != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE))
149
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list");
150
151
    /* Register connector */
152
0
    if (NULL == (connector = H5VL__register_connector_by_name(name, vipl_id)))
153
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector");
154
155
    /* Get ID for connector */
156
0
    if ((ret_value = H5I_register(H5I_VOL, connector, true)) < 0)
157
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID");
158
159
0
done:
160
0
    if (ret_value < 0)
161
        /* Decrement refcount on connector */
162
0
        if (connector && H5VL_conn_dec_rc(connector) < 0)
163
0
            HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID,
164
0
                        "unable to decrement ref count on VOL connector");
165
166
0
    FUNC_LEAVE_API(ret_value)
167
0
} /* end H5VLregister_connector_by_name() */
168
169
/*-------------------------------------------------------------------------
170
 * Function:    H5VLregister_connector_by_value
171
 *
172
 * Purpose:     Registers a new VOL connector as a member of the virtual object
173
 *              layer class.
174
 *
175
 *              VIPL_ID is a VOL initialization property list which must be
176
 *              created with H5Pcreate(H5P_VOL_INITIALIZE) (or H5P_DEFAULT).
177
 *
178
 * Return:      Success:    A VOL connector ID which is good until the
179
 *                          library is closed or the connector is
180
 *                          unregistered.
181
 *
182
 *              Failure:    H5I_INVALID_HID
183
 *
184
 *-------------------------------------------------------------------------
185
 */
186
hid_t
187
H5VLregister_connector_by_value(H5VL_class_value_t value, hid_t vipl_id)
188
0
{
189
0
    H5VL_connector_t *connector = NULL;
190
0
    hid_t             ret_value = H5I_INVALID_HID; /* Return value */
191
192
0
    FUNC_ENTER_API(H5I_INVALID_HID)
193
194
    /* Check arguments */
195
0
    if (value < 0)
196
0
        HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID,
197
0
                    "negative VOL connector value is disallowed");
198
199
    /* Check VOL initialization property list */
200
0
    if (H5P_DEFAULT == vipl_id)
201
0
        vipl_id = H5P_VOL_INITIALIZE_DEFAULT;
202
0
    else if (true != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE))
203
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list");
204
205
    /* Register connector */
206
0
    if (NULL == (connector = H5VL__register_connector_by_value(value, vipl_id)))
207
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector");
208
209
    /* Get ID for connector */
210
0
    if ((ret_value = H5I_register(H5I_VOL, connector, true)) < 0)
211
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID");
212
213
0
done:
214
0
    if (ret_value < 0)
215
        /* Decrement refcount on connector */
216
0
        if (connector && H5VL_conn_dec_rc(connector) < 0)
217
0
            HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID,
218
0
                        "unable to decrement ref count on VOL connector");
219
220
0
    FUNC_LEAVE_API(ret_value)
221
0
} /* end H5VLregister_connector_by_value() */
222
223
/*-------------------------------------------------------------------------
224
 * Function:    H5VLis_connector_registered_by_name
225
 *
226
 * Purpose:     Tests whether a VOL class has been registered or not
227
 *              according to a supplied connector name.
228
 *
229
 * Return:      >0 if a VOL connector with that name has been registered
230
 *              0 if a VOL connector with that name has NOT been registered
231
 *              <0 on errors
232
 *
233
 *-------------------------------------------------------------------------
234
 */
235
htri_t
236
H5VLis_connector_registered_by_name(const char *name)
237
0
{
238
0
    htri_t ret_value = false; /* Return value */
239
240
0
    FUNC_ENTER_API(FAIL)
241
242
    /* Check if connector with this name is registered */
243
0
    if ((ret_value = H5VL__is_connector_registered_by_name(name)) < 0)
244
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't check for VOL");
245
246
0
done:
247
0
    FUNC_LEAVE_API(ret_value)
248
0
} /* end H5VLis_connector_registered_by_name() */
249
250
/*-------------------------------------------------------------------------
251
 * Function:    H5VLis_connector_registered_by_value
252
 *
253
 * Purpose:     Tests whether a VOL class has been registered or not
254
 *              according to a supplied connector value (ID).
255
 *
256
 * Return:      >0 if a VOL connector with that value has been registered
257
 *              0 if a VOL connector with that value hasn't been registered
258
 *              <0 on errors
259
 *
260
 *-------------------------------------------------------------------------
261
 */
262
htri_t
263
H5VLis_connector_registered_by_value(H5VL_class_value_t connector_value)
264
0
{
265
0
    htri_t ret_value = false;
266
267
0
    FUNC_ENTER_API(FAIL)
268
269
    /* Check if connector with this value is registered */
270
0
    if ((ret_value = H5VL__is_connector_registered_by_value(connector_value)) < 0)
271
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't check for VOL");
272
273
0
done:
274
0
    FUNC_LEAVE_API(ret_value)
275
0
} /* end H5VLis_connector_registered_by_value() */
276
277
/*-------------------------------------------------------------------------
278
 * Function:    H5VLget_connector_id
279
 *
280
 * Purpose:     Retrieves the VOL connector ID for a given object ID.
281
 *
282
 * Return:      A valid VOL connector ID. This ID will need to be closed
283
 *              using H5VLclose().
284
 *
285
 *              H5I_INVALID_HID on error.
286
 *
287
 *-------------------------------------------------------------------------
288
 */
289
hid_t
290
H5VLget_connector_id(hid_t obj_id)
291
0
{
292
0
    H5VL_object_t *vol_obj   = NULL;
293
0
    hid_t          ret_value = H5I_INVALID_HID; /* Return value */
294
295
0
    FUNC_ENTER_API(H5I_INVALID_HID)
296
297
    /* Get the underlying VOL object for the object ID */
298
0
    if (NULL == (vol_obj = H5VL_vol_object(obj_id)))
299
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier");
300
301
    /* Register an ID for the connector */
302
0
    if ((ret_value = H5VL_conn_register(vol_obj->connector)) < 0)
303
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "can't get VOL ID");
304
305
0
done:
306
0
    FUNC_LEAVE_API(ret_value)
307
0
} /* end H5VLget_connector_id() */
308
309
/*-------------------------------------------------------------------------
310
 * Function:    H5VLget_connector_id_by_name
311
 *
312
 * Purpose:     Retrieves the ID for a registered VOL connector.
313
 *
314
 * Return:      A valid VOL connector ID if a connector by that name has
315
 *              been registered. This ID will need to be closed using
316
 *              H5VLclose().
317
 *
318
 *              H5I_INVALID_HID on error or if a VOL connector of that
319
 *              name has not been registered.
320
 *
321
 *-------------------------------------------------------------------------
322
 */
323
hid_t
324
H5VLget_connector_id_by_name(const char *name)
325
0
{
326
0
    H5VL_connector_t *connector = NULL;
327
0
    hid_t             ret_value = H5I_INVALID_HID; /* Return value */
328
329
0
    FUNC_ENTER_API(H5I_INVALID_HID)
330
331
    /* Get connector ID with this name */
332
0
    if (NULL == (connector = H5VL__get_connector_by_name(name)))
333
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL connector");
334
335
    /* Get ID for connector */
336
0
    if ((ret_value = H5I_register(H5I_VOL, connector, true)) < 0)
337
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID");
338
339
0
done:
340
0
    if (ret_value < 0)
341
        /* Decrement refcount on connector */
342
0
        if (connector && H5VL_conn_dec_rc(connector) < 0)
343
0
            HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID,
344
0
                        "unable to decrement ref count on VOL connector");
345
346
0
    FUNC_LEAVE_API(ret_value)
347
0
} /* end H5VLget_connector_id_by_name() */
348
349
/*-------------------------------------------------------------------------
350
 * Function:    H5VLget_connector_id_by_value
351
 *
352
 * Purpose:     Retrieves the ID for a registered VOL connector.
353
 *
354
 * Return:      A valid VOL connector ID if a connector with that value has
355
 *              been registered. This ID will need to be closed using
356
 *              H5VLclose().
357
 *
358
 *              H5I_INVALID_HID on error or if a VOL connector with that
359
 *              value has not been registered.
360
 *
361
 *-------------------------------------------------------------------------
362
 */
363
hid_t
364
H5VLget_connector_id_by_value(H5VL_class_value_t connector_value)
365
0
{
366
0
    H5VL_connector_t *connector = NULL;
367
0
    hid_t             ret_value = H5I_INVALID_HID; /* Return value */
368
369
0
    FUNC_ENTER_API(H5I_INVALID_HID)
370
371
    /* Get connector ID with this value */
372
0
    if (NULL == (connector = H5VL__get_connector_by_value(connector_value)))
373
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL connector");
374
375
    /* Get ID for connector */
376
0
    if ((ret_value = H5I_register(H5I_VOL, connector, true)) < 0)
377
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID");
378
379
0
done:
380
0
    if (ret_value < 0)
381
        /* Decrement refcount on connector */
382
0
        if (connector && H5VL_conn_dec_rc(connector) < 0)
383
0
            HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID,
384
0
                        "unable to decrement ref count on VOL connector");
385
386
0
    FUNC_LEAVE_API(ret_value)
387
0
} /* end H5VLget_connector_id_by_value() */
388
389
/*-------------------------------------------------------------------------
390
 * Function:    H5VLget_connector_name
391
 *
392
 * Purpose:     Returns the connector name for the VOL associated with the
393
 *              object or file ID.
394
 *
395
 *              This works like other calls where the caller must provide a
396
 *              buffer of the appropriate size for the library to fill in.
397
 *              i.e., passing in a NULL pointer for NAME will return the
398
 *              required size of the buffer.
399
 *
400
 * Return:      Success:        The length of the connector name
401
 *
402
 *              Failure:        Negative
403
 *
404
 *-------------------------------------------------------------------------
405
 */
406
ssize_t
407
H5VLget_connector_name(hid_t obj_id, char *name /*out*/, size_t size)
408
0
{
409
0
    H5VL_object_t *vol_obj;
410
0
    ssize_t        ret_value = -1;
411
412
0
    FUNC_ENTER_API(FAIL)
413
414
    /* Get the object pointer */
415
0
    if (NULL == (vol_obj = H5VL_vol_object(obj_id)))
416
0
        HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "invalid VOL identifier");
417
418
    /* Call internal routine */
419
0
    ret_value = (ssize_t)H5VL__get_connector_name(vol_obj->connector, name, size);
420
421
0
done:
422
0
    FUNC_LEAVE_API(ret_value)
423
0
} /* end H5VLget_connector_name() */
424
425
/*-------------------------------------------------------------------------
426
 * Function:    H5VLclose
427
 *
428
 * Purpose:     Closes a VOL connector ID.  This in no way affects
429
 *              file access property lists which have been defined to use
430
 *              this VOL connector or files which are already opened under with
431
 *              this connector.
432
 *
433
 * Return:      Success:    Non-negative
434
 *              Failure:    Negative
435
 *
436
 *-------------------------------------------------------------------------
437
 */
438
herr_t
439
H5VLclose(hid_t vol_id)
440
0
{
441
0
    herr_t ret_value = SUCCEED; /* Return value */
442
443
0
    FUNC_ENTER_API(FAIL)
444
445
    /* Check args */
446
0
    if (NULL == H5I_object_verify(vol_id, H5I_VOL))
447
0
        HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector");
448
449
    /* Decrement the ref count on the ID, possibly releasing the VOL connector */
450
0
    if (H5I_dec_app_ref(vol_id) < 0)
451
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to close VOL connector ID");
452
453
0
done:
454
0
    FUNC_LEAVE_API(ret_value)
455
0
} /* end H5VLclose() */
456
457
/*-------------------------------------------------------------------------
458
 * Function:    H5VLunregister_connector
459
 *
460
 * Purpose:     Removes a VOL connector ID from the library. This in no way affects
461
 *              file access property lists which have been defined to use
462
 *              this VOL connector or files which are already opened under with
463
 *              this connector.
464
 *
465
 *              The native VOL connector cannot be unregistered and attempts
466
 *              to do so are considered an error.
467
 *
468
 * Return:      Success:    Non-negative
469
 *              Failure:    Negative
470
 *
471
 *-------------------------------------------------------------------------
472
 */
473
herr_t
474
H5VLunregister_connector(hid_t vol_id)
475
0
{
476
0
    H5VL_connector_t *native, *connector;
477
0
    int               cmp_value;           /* Comparison result */
478
0
    herr_t            ret_value = SUCCEED; /* Return value */
479
480
0
    FUNC_ENTER_API(FAIL)
481
482
    /* Check arguments */
483
0
    if (NULL == (connector = H5I_object_verify(vol_id, H5I_VOL)))
484
0
        HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector ID");
485
486
    /* For the time being, we disallow unregistering the native VOL connector */
487
0
    native = H5VL_NATIVE_conn_g;
488
0
    if (H5VL_cmp_connector_cls(&cmp_value, connector->cls, native->cls) < 0)
489
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTCOMPARE, FAIL, "can't compare connector classes");
490
0
    if (0 == cmp_value)
491
0
        HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "unregistering the native VOL connector is not allowed");
492
493
    /* The H5VL_connector_t struct will be freed by this function */
494
0
    if (H5I_dec_app_ref(vol_id) < 0)
495
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to unregister VOL connector");
496
497
0
done:
498
0
    FUNC_LEAVE_API(ret_value)
499
0
} /* end H5VLunregister_connector() */
500
501
/*---------------------------------------------------------------------------
502
 * Function:    H5VLcmp_connector_cls
503
 *
504
 * Purpose:     Compares two connector classes (based on their value field)
505
 *
506
 * Note:        This routine is _only_ for HDF5 VOL connector authors!  It is
507
 *              _not_ part of the public API for HDF5 application developers.
508
 *
509
 * Return:      Success:    Non-negative, *cmp set to a value like strcmp
510
 *
511
 *              Failure:    Negative, *cmp unset
512
 *
513
 *---------------------------------------------------------------------------
514
 */
515
herr_t
516
H5VLcmp_connector_cls(int *cmp, hid_t connector_id1, hid_t connector_id2)
517
0
{
518
0
    H5VL_connector_t *conn1, *conn2;       /* Connectors for IDs */
519
0
    herr_t            ret_value = SUCCEED; /* Return value */
520
521
0
    FUNC_ENTER_API(FAIL)
522
523
    /* Check args and get class pointers */
524
0
    if (NULL == (conn1 = H5I_object_verify(connector_id1, H5I_VOL)))
525
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID");
526
0
    if (NULL == (conn2 = H5I_object_verify(connector_id2, H5I_VOL)))
527
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID");
528
529
    /* Compare the two VOL connector classes */
530
0
    if (H5VL_cmp_connector_cls(cmp, conn1->cls, conn2->cls) < 0)
531
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTCOMPARE, FAIL, "can't compare connector classes");
532
533
0
done:
534
0
    FUNC_LEAVE_API(ret_value)
535
0
} /* H5VLcmp_connector_cls() */
536
537
/*---------------------------------------------------------------------------
538
 * Function:    H5VLwrap_register
539
 *
540
 * Purpose:     Wrap an internal object with a "wrap context" and register an
541
 *              hid_t for the resulting object.
542
 *
543
 * Note:        This routine is mainly targeted toward wrapping objects for
544
 *              iteration routine callbacks (i.e. the callbacks from H5Aiterate*,
545
 *              H5Literate* / H5Lvisit*, and H5Ovisit* ).
546
 *
547
 *              type must be a VOL-managed object class (H5I_FILE,
548
 *              H5I_GROUP, H5I_DATATYPE, H5I_DATASET, H5I_MAP, or H5I_ATTR).
549
 *
550
 * Return:      Success:    Non-negative hid_t for the object.
551
 *              Failure:    Negative (H5I_INVALID_HID)
552
 *
553
 *---------------------------------------------------------------------------
554
 */
555
hid_t
556
H5VLwrap_register(void *obj, H5I_type_t type)
557
0
{
558
0
    hid_t ret_value; /* Return value */
559
560
    /* Use FUNC_ENTER_API_NOINIT here, so the API context doesn't get reset */
561
0
    FUNC_ENTER_API_NOINIT
562
563
    /* Check args */
564
    /* Use a switch here for (hopefully) better performance than a series of
565
     * equality checks.  We could also group these types together in H5I_type_t,
566
     * make some assertions here to guarantee that, then just check the range.
567
     */
568
0
    switch (type) {
569
0
        case H5I_FILE:
570
0
        case H5I_GROUP:
571
0
        case H5I_DATATYPE:
572
0
        case H5I_DATASET:
573
0
        case H5I_MAP:
574
0
        case H5I_ATTR:
575
            /* VOL-managed objects, call is valid */
576
0
            break;
577
0
        case H5I_UNINIT:
578
0
        case H5I_BADID:
579
0
        case H5I_DATASPACE:
580
0
        case H5I_VFL:
581
0
        case H5I_VOL:
582
0
        case H5I_GENPROP_CLS:
583
0
        case H5I_GENPROP_LST:
584
0
        case H5I_ERROR_CLASS:
585
0
        case H5I_ERROR_MSG:
586
0
        case H5I_ERROR_STACK:
587
0
        case H5I_SPACE_SEL_ITER:
588
0
        case H5I_EVENTSET:
589
0
        case H5I_NTYPES:
590
0
        default:
591
0
            HGOTO_ERROR(H5E_VOL, H5E_BADRANGE, H5I_INVALID_HID, "invalid type number");
592
0
    } /* end switch */
593
0
    if (NULL == obj)
594
0
        HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, H5I_INVALID_HID, "obj is NULL");
595
596
    /* Wrap the object and register an ID for it */
597
0
    if ((ret_value = H5VL_wrap_register(type, obj, true)) < 0)
598
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to wrap object");
599
600
0
done:
601
0
    FUNC_LEAVE_API_NOINIT(ret_value)
602
0
} /* H5VLwrap_register() */
603
604
/*---------------------------------------------------------------------------
605
 * Function:    H5VLobject
606
 *
607
 * Purpose:     Retrieve the object pointer associated with an hid_t for a
608
 *              VOL object.
609
 *
610
 * Note:        This routine is mainly targeted toward unwrapping objects for
611
 *              testing.
612
 *
613
 * Return:      Success:    Object pointer
614
 *              Failure:    NULL
615
 *
616
 *---------------------------------------------------------------------------
617
 */
618
void *
619
H5VLobject(hid_t id)
620
0
{
621
0
    void *ret_value; /* Return value */
622
623
0
    FUNC_ENTER_API(NULL)
624
625
    /* Retrieve the object pointer for the ID */
626
0
    if (NULL == (ret_value = H5VL_object(id)))
627
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "unable to retrieve object");
628
629
0
done:
630
0
    FUNC_LEAVE_API(ret_value)
631
0
} /* H5VLobject() */
632
633
/*---------------------------------------------------------------------------
634
 * Function:    H5VLobject_is_native
635
 *
636
 * Purpose:     Determines whether an object ID represents a native VOL
637
 *              connector object.
638
 *
639
 * Return:      Non-negative on success/Negative on failure
640
 *
641
 *---------------------------------------------------------------------------
642
 */
643
herr_t
644
H5VLobject_is_native(hid_t obj_id, bool *is_native)
645
0
{
646
0
    H5VL_object_t *vol_obj   = NULL;
647
0
    herr_t         ret_value = SUCCEED;
648
649
0
    FUNC_ENTER_API(FAIL)
650
651
0
    if (!is_native)
652
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "`is_native` argument is NULL");
653
654
    /* Get the location object for the ID */
655
0
    if (NULL == (vol_obj = H5VL_vol_object(obj_id)))
656
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier");
657
658
0
    if (H5VL_object_is_native(vol_obj, is_native) < 0)
659
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't determine if object is a native connector object");
660
661
0
done:
662
0
    FUNC_LEAVE_API(ret_value)
663
0
} /* H5VLobject_is_native() */
664
665
/*-------------------------------------------------------------------------
666
 * Function:    H5VLget_file_type
667
 *
668
 * Purpose:     Returns a copy of dtype_id with its location set to be in
669
 *              the file, with updated size, etc.
670
 *
671
 * Return:      Non-negative on success/Negative on failure
672
 *
673
 *-------------------------------------------------------------------------
674
 */
675
hid_t
676
H5VLget_file_type(void *file_obj, hid_t connector_id, hid_t dtype_id)
677
0
{
678
0
    H5T_t            *dtype;               /* unregistered type       */
679
0
    H5T_t            *file_type    = NULL; /* copied file type        */
680
0
    hid_t             file_type_id = -1;   /* copied file type id     */
681
0
    H5VL_connector_t *connector;           /* VOL connector */
682
0
    H5VL_object_t    *file_vol_obj = NULL; /* VOL object for file     */
683
0
    hid_t             ret_value    = -1;   /* Return value            */
684
685
0
    FUNC_ENTER_API(H5I_INVALID_HID)
686
687
    /* Check args */
688
0
    if (!file_obj)
689
0
        HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "no file object supplied");
690
0
    if (NULL == (dtype = H5I_object_verify(dtype_id, H5I_DATATYPE)))
691
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
692
0
    if (NULL == (connector = H5I_object_verify(connector_id, H5I_VOL)))
693
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file VOL ID");
694
695
    /* Create VOL object for file if necessary (force_conv will be true if and
696
     * only if file needs to be passed to H5T_set_loc) */
697
0
    if (H5T_GET_FORCE_CONV(dtype))
698
0
        if (NULL == (file_vol_obj = H5VL_new_vol_obj(H5I_FILE, file_obj, connector, true)))
699
0
            HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, FAIL, "can't create VOL object");
700
701
    /* Copy the datatype */
702
0
    if (NULL == (file_type = H5T_copy(dtype, H5T_COPY_TRANSIENT)))
703
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTCOPY, H5I_INVALID_HID, "unable to copy datatype");
704
705
    /* Register file type id */
706
0
    if ((file_type_id = H5I_register(H5I_DATATYPE, file_type, false)) < 0) {
707
0
        (void)H5T_close_real(file_type);
708
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register file datatype");
709
0
    } /* end if */
710
711
    /* Set the location of the datatype to be in the file */
712
0
    if (H5T_set_loc(file_type, file_vol_obj, H5T_LOC_DISK) < 0)
713
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, H5I_INVALID_HID, "can't set datatype location");
714
715
    /* Release our reference to file_type */
716
0
    if (file_vol_obj) {
717
0
        if (H5VL_free_object(file_vol_obj) < 0)
718
0
            HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID, "unable to free VOL object");
719
0
        file_vol_obj = NULL;
720
0
    } /* end if */
721
722
    /* Set return value */
723
0
    ret_value = file_type_id;
724
725
0
done:
726
    /* Cleanup on error */
727
0
    if (ret_value < 0) {
728
0
        if (file_vol_obj && H5VL_free_object(file_vol_obj) < 0)
729
0
            HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID, "unable to free VOL object");
730
0
        if (file_type_id >= 0 && H5I_dec_ref(file_type_id) < 0)
731
0
            HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID, "unable to close file datatype");
732
0
    } /* end if */
733
734
0
    FUNC_LEAVE_API(ret_value)
735
0
} /* end H5VLget_file_type() */
736
737
/*---------------------------------------------------------------------------
738
 * Function:    H5VLretrieve_lib_state
739
 *
740
 * Purpose:     Retrieves a copy of the internal state of the HDF5 library,
741
 *              so that it can be restored later.
742
 *
743
 * Note:        This routine is _only_ for HDF5 VOL connector authors!  It is
744
 *              _not_ part of the public API for HDF5 application developers.
745
 *
746
 * Return:      Success:    Non-negative, *state set
747
 *              Failure:    Negative, *state unset
748
 *
749
 *---------------------------------------------------------------------------
750
 */
751
herr_t
752
H5VLretrieve_lib_state(void **state /*out*/)
753
0
{
754
0
    herr_t ret_value = SUCCEED; /* Return value */
755
756
    /* Must use this, to avoid modifying the API context stack in FUNC_ENTER */
757
0
    FUNC_ENTER_API_NOINIT
758
759
    /* Check args */
760
0
    if (NULL == state)
761
0
        HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "invalid state pointer");
762
763
    /* Retrieve the library state */
764
0
    if (H5VL_retrieve_lib_state(state) < 0)
765
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't retrieve library state");
766
767
0
done:
768
0
    FUNC_LEAVE_API_NOINIT(ret_value)
769
0
} /* H5VLretrieve_lib_state() */
770
771
herr_t
772
H5VLopen_lib_context(void **context)
773
0
{
774
0
    herr_t ret_value = SUCCEED; /* Return value */
775
776
    /* Must use this, to avoid modifying the API context stack in FUNC_ENTER */
777
0
    FUNC_ENTER_API_NOINIT
778
779
    /* Check args */
780
0
    if (NULL == context)
781
0
        HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "invalid context pointer");
782
783
    /* Start a new library state */
784
0
    if (H5VL_start_lib_state(context) < 0)
785
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't start new library state");
786
787
0
done:
788
0
    FUNC_LEAVE_API_NOINIT(ret_value)
789
0
} /* H5VLopen_lib_context() */
790
791
/*---------------------------------------------------------------------------
792
 * Function:    H5VLrestore_lib_state
793
 *
794
 * Purpose:     Restores the internal state of the HDF5 library.
795
 *
796
 * Note:        This routine is _only_ for HDF5 VOL connector authors!  It is
797
 *              _not_ part of the public API for HDF5 application developers.
798
 *
799
 * Return:      Success:    Non-negative
800
 *              Failure:    Negative
801
 *
802
 *---------------------------------------------------------------------------
803
 */
804
herr_t
805
H5VLrestore_lib_state(const void *state)
806
0
{
807
0
    herr_t ret_value = SUCCEED; /* Return value */
808
809
    /* Must use this, to avoid modifying the API context stack in FUNC_ENTER */
810
0
    FUNC_ENTER_API_NOINIT
811
812
    /* Check args */
813
0
    if (NULL == state)
814
0
        HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "invalid state pointer");
815
816
    /* Restore the library state */
817
0
    if (H5VL_restore_lib_state(state) < 0)
818
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't restore library state");
819
820
0
done:
821
0
    FUNC_LEAVE_API_NOINIT(ret_value)
822
0
} /* H5VLrestore_lib_state() */
823
824
herr_t
825
H5VLclose_lib_context(void *context)
826
0
{
827
0
    herr_t ret_value = SUCCEED; /* Return value */
828
829
    /* Must use this, to avoid modifying the API context stack in FUNC_ENTER */
830
0
    FUNC_ENTER_API_NOINIT
831
832
    /* Check args */
833
0
    if (NULL == context)
834
0
        HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "invalid context pointer");
835
836
    /* Reset the library state */
837
0
    if (H5VL_finish_lib_state(context) < 0)
838
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset library state");
839
840
0
done:
841
0
    FUNC_LEAVE_API_NOINIT(ret_value)
842
0
} /* H5VLclose_lib_context() */
843
844
/*---------------------------------------------------------------------------
845
 * Function:    H5VLfree_lib_state
846
 *
847
 * Purpose:     Free a retrieved library state.
848
 *
849
 * Note:        This routine is _only_ for HDF5 VOL connector authors!  It is
850
 *              _not_ part of the public API for HDF5 application developers.
851
 *
852
 * Note:        This routine must be called as a "pair" with
853
 *              H5VLretrieve_lib_state.
854
 *
855
 * Return:      Success:    Non-negative
856
 *              Failure:    Negative
857
 *
858
 *---------------------------------------------------------------------------
859
 */
860
herr_t
861
H5VLfree_lib_state(void *state)
862
0
{
863
0
    herr_t ret_value = SUCCEED; /* Return value */
864
865
0
    FUNC_ENTER_API(FAIL)
866
867
    /* Check args */
868
0
    if (NULL == state)
869
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid state pointer");
870
871
    /* Free the library state */
872
0
    if (H5VL_free_lib_state(state) < 0)
873
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "can't free library state");
874
875
0
done:
876
0
    FUNC_LEAVE_API(ret_value)
877
0
} /* H5VLfree_lib_state() */
878
879
/*---------------------------------------------------------------------------
880
 * Function:    H5VLquery_optional
881
 *
882
 * Purpose:     Determine if a VOL connector supports a particular optional
883
 *              callback operation, and a general sense of the operation's
884
 *              behavior.
885
 *
886
 * Return:      Success:    Non-negative
887
 *              Failure:    Negative
888
 *
889
 *---------------------------------------------------------------------------
890
 */
891
herr_t
892
H5VLquery_optional(hid_t obj_id, H5VL_subclass_t subcls, int opt_type, uint64_t *flags /*out*/)
893
0
{
894
0
    H5VL_object_t *vol_obj   = NULL;
895
0
    herr_t         ret_value = SUCCEED; /* Return value */
896
897
0
    FUNC_ENTER_API(FAIL)
898
899
    /* Check args */
900
0
    if (NULL == flags)
901
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid 'flags' pointer");
902
0
    if (NULL == (vol_obj = H5VL_vol_object(obj_id)))
903
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier");
904
905
    /* Query the connector */
906
0
    if (H5VL_introspect_opt_query(vol_obj, subcls, opt_type, flags) < 0)
907
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to query VOL connector operation");
908
909
0
done:
910
0
    FUNC_LEAVE_API(ret_value)
911
0
} /* H5VLquery_optional() */
912
913
/*---------------------------------------------------------------------------
914
 * Function:    H5VLregister_opt_operation
915
 *
916
 * Purpose:     Allow a VOL connector to register a new optional operation
917
 *              for a VOL object subclass.   The operation name must be runtime
918
 *              unique for each operation, preferably avoiding naming clashes
919
 *              by using a Uniform Type Identifier (UTI,
920
 *https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/understanding_utis/understand_utis_conc/understand_utis_conc.html)
921
 *              for each operation name.  The value returned in the 'op_val'
922
 *              pointer will be unique for that VOL connector to use for its
923
 *              operation on that subclass.
924
 *
925
 *              For example, registering a 'prefetch' operation for the
926
 *              caching VOL connector written at the ALCF at Argonne National
927
 *              Laboratory could have a UTI of: "gov.anl.alcf.cache.prefetch",
928
 *              and the "evict" operation for the same connector could have a
929
 *              UTI of: "gov.anl.alcf.cache.evict".   Registering a "suspend
930
 *              background threads" operation for the asynchronous VOL connector
931
 *              written at NERSC at Lawrence Berkeley National Laboratory could
932
 *              have a UTI of: "gov.lbnl.nersc.async.suspend_bkg_threads".
933
 *
934
 * Note:        The first 1024 values of each subclass's optional operations
935
 *              are reserved for the native VOL connector's use.
936
 *
937
 * Return:      Success:    Non-negative
938
 *              Failure:    Negative
939
 *
940
 *---------------------------------------------------------------------------
941
 */
942
herr_t
943
H5VLregister_opt_operation(H5VL_subclass_t subcls, const char *op_name, int *op_val /*out*/)
944
0
{
945
0
    herr_t ret_value = SUCCEED; /* Return value */
946
947
0
    FUNC_ENTER_API(FAIL)
948
949
    /* Check args */
950
0
    if (NULL == op_val)
951
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid op_val pointer");
952
0
    if (NULL == op_name)
953
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid op_name pointer");
954
0
    if ('\0' == *op_name)
955
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid op_name string");
956
0
    if (!((H5VL_SUBCLS_ATTR == subcls) || (H5VL_SUBCLS_DATASET == subcls) ||
957
0
          (H5VL_SUBCLS_DATATYPE == subcls) || (H5VL_SUBCLS_FILE == subcls) || (H5VL_SUBCLS_GROUP == subcls) ||
958
0
          (H5VL_SUBCLS_OBJECT == subcls) || (H5VL_SUBCLS_LINK == subcls) || (H5VL_SUBCLS_REQUEST == subcls)))
959
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid VOL subclass type");
960
961
    /* Register the operation */
962
0
    if (H5VL__register_opt_operation(subcls, op_name, op_val) < 0)
963
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, FAIL, "can't register dynamic optional operation: '%s'",
964
0
                    op_name);
965
966
0
done:
967
0
    FUNC_LEAVE_API(ret_value)
968
0
} /* H5VLregister_opt_operation() */
969
970
/*---------------------------------------------------------------------------
971
 * Function:    H5VLfind_opt_operation
972
 *
973
 * Purpose:     Look up a optional operation for a VOL object subclass, by name.
974
 *
975
 * Return:      Success:    Non-negative
976
 *              Failure:    Negative
977
 *
978
 *---------------------------------------------------------------------------
979
 */
980
herr_t
981
H5VLfind_opt_operation(H5VL_subclass_t subcls, const char *op_name, int *op_val /*out*/)
982
0
{
983
0
    herr_t ret_value = SUCCEED; /* Return value */
984
985
0
    FUNC_ENTER_API(FAIL)
986
987
    /* Check args */
988
0
    if (NULL == op_val)
989
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid op_val pointer");
990
0
    if (NULL == op_name)
991
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid op_name pointer");
992
0
    if ('\0' == *op_name)
993
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid op_name string");
994
0
    if (!((H5VL_SUBCLS_ATTR == subcls) || (H5VL_SUBCLS_DATASET == subcls) ||
995
0
          (H5VL_SUBCLS_DATATYPE == subcls) || (H5VL_SUBCLS_FILE == subcls) || (H5VL_SUBCLS_GROUP == subcls) ||
996
0
          (H5VL_SUBCLS_OBJECT == subcls) || (H5VL_SUBCLS_LINK == subcls) || (H5VL_SUBCLS_REQUEST == subcls)))
997
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid VOL subclass type");
998
999
    /* Find the operation */
1000
0
    if (H5VL__find_opt_operation(subcls, op_name, op_val) < 0)
1001
0
        HGOTO_ERROR(H5E_VOL, H5E_NOTFOUND, FAIL, "can't find dynamic optional operation: '%s'", op_name);
1002
1003
0
done:
1004
0
    FUNC_LEAVE_API(ret_value)
1005
0
} /* H5VLfind_opt_operation() */
1006
1007
/*---------------------------------------------------------------------------
1008
 * Function:    H5VLunregister_opt_operation
1009
 *
1010
 * Purpose:     Unregister a optional operation for a VOL object subclass, by name.
1011
 *
1012
 * Return:      Success:    Non-negative
1013
 *              Failure:    Negative
1014
 *
1015
 *---------------------------------------------------------------------------
1016
 */
1017
herr_t
1018
H5VLunregister_opt_operation(H5VL_subclass_t subcls, const char *op_name)
1019
0
{
1020
0
    herr_t ret_value = SUCCEED; /* Return value */
1021
1022
0
    FUNC_ENTER_API(FAIL)
1023
1024
    /* Check args */
1025
0
    if (NULL == op_name)
1026
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid op_name pointer");
1027
0
    if ('\0' == *op_name)
1028
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid op_name string");
1029
0
    if (!((H5VL_SUBCLS_ATTR == subcls) || (H5VL_SUBCLS_DATASET == subcls) ||
1030
0
          (H5VL_SUBCLS_DATATYPE == subcls) || (H5VL_SUBCLS_FILE == subcls) || (H5VL_SUBCLS_GROUP == subcls) ||
1031
0
          (H5VL_SUBCLS_OBJECT == subcls) || (H5VL_SUBCLS_LINK == subcls) || (H5VL_SUBCLS_REQUEST == subcls)))
1032
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid VOL subclass type");
1033
1034
    /* Unregister the operation */
1035
0
    if (H5VL__unregister_opt_operation(subcls, op_name) < 0)
1036
0
        HGOTO_ERROR(H5E_VOL, H5E_CANTREMOVE, FAIL, "can't unregister dynamic optional operation: '%s'",
1037
0
                    op_name);
1038
1039
0
done:
1040
    FUNC_LEAVE_API(ret_value)
1041
0
} /* H5VLunregister_opt_operation() */