Coverage Report

Created: 2026-10-10 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Tref.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
 * Module Info: This module contains the functionality for reference
15
 *      datatypes in the H5T interface.
16
 */
17
18
#include "H5Tmodule.h" /* This source code file is part of the H5T module */
19
#define H5F_FRIEND     /*suppress error about including H5Fpkg   */
20
#define H5R_FRIEND     /*suppress error about including H5Rpkg   */
21
22
#include "H5private.h"   /* Generic Functions                        */
23
#include "H5CXprivate.h" /* API Contexts                             */
24
#include "H5Eprivate.h"  /* Error handling                           */
25
#include "H5Iprivate.h"  /* IDs                                      */
26
#include "H5Fpkg.h"      /* File                                     */
27
#include "H5MMprivate.h" /* Memory management                        */
28
#include "H5Rpkg.h"      /* References                               */
29
#include "H5Tpkg.h"      /* Datatypes                                */
30
31
#include "H5VLnative_private.h" /* Native VOL connector                     */
32
33
/****************/
34
/* Local Macros */
35
/****************/
36
37
2
#define H5T_REF_MEM_SIZE         (H5R_REF_BUF_SIZE)
38
2
#define H5T_REF_OBJ_MEM_SIZE     (H5R_OBJ_REF_BUF_SIZE)
39
2
#define H5T_REF_DSETREG_MEM_SIZE (H5R_DSET_REG_REF_BUF_SIZE)
40
41
15
#define H5T_REF_OBJ_DISK_SIZE(f)     (H5F_SIZEOF_ADDR(f))
42
1
#define H5T_REF_DSETREG_DISK_SIZE(f) (H5HG_HEAP_ID_SIZE(f))
43
44
/* Debug */
45
// #define H5T_REF_DEBUG
46
#ifdef H5T_REF_DEBUG
47
#define H5T_REF_LOG_DEBUG(...)                                                                               \
48
    do {                                                                                                     \
49
        fprintf(stdout, " # %s(): ", __func__);                                                              \
50
        fprintf(stdout, __VA_ARGS__);                                                                        \
51
        fprintf(stdout, "\n");                                                                               \
52
        fflush(stdout);                                                                                      \
53
    } while (0)
54
#else
55
#define H5T_REF_LOG_DEBUG(...)                                                                               \
56
38
    do {                                                                                                     \
57
38
    } while (0)
58
#endif
59
60
/******************/
61
/* Local Typedefs */
62
/******************/
63
64
/* For region compatibility support */
65
struct H5Tref_dsetreg {
66
    H5O_token_t token; /* Object token */
67
    H5S_t      *space; /* Dataspace */
68
};
69
70
/********************/
71
/* Local Prototypes */
72
/********************/
73
74
static herr_t H5T__ref_mem_isnull(const H5VL_object_t *src_file, const void *src_buf, bool *isnull);
75
static herr_t H5T__ref_mem_setnull(H5VL_object_t *dst_file, void *dst_buf, void *bg_buf);
76
static size_t H5T__ref_mem_getsize(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
77
                                   H5VL_object_t *dst_file, bool *dst_copy);
78
static herr_t H5T__ref_mem_read(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
79
                                H5VL_object_t *dst_file, void *dst_buf, size_t dst_size);
80
static herr_t H5T__ref_mem_write(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
81
                                 H5R_type_t src_type, H5VL_object_t *dst_file, void *dst_buf, size_t dst_size,
82
                                 void *bg_buf);
83
84
static herr_t H5T__ref_disk_isnull(const H5VL_object_t *src_file, const void *src_buf, bool *isnull);
85
static herr_t H5T__ref_disk_setnull(H5VL_object_t *dst_file, void *dst_buf, void *bg_buf);
86
static size_t H5T__ref_disk_getsize(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
87
                                    H5VL_object_t *dst_file, bool *dst_copy);
88
static herr_t H5T__ref_disk_read(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
89
                                 H5VL_object_t *dst_file, void *dst_buf, size_t dst_size);
90
static herr_t H5T__ref_disk_write(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
91
                                  H5R_type_t src_type, H5VL_object_t *dst_file, void *dst_buf,
92
                                  size_t dst_size, void *bg_buf);
93
94
/* For compatibility */
95
static herr_t H5T__ref_obj_disk_isnull(const H5VL_object_t *src_file, const void *src_buf, bool *isnull);
96
static size_t H5T__ref_obj_disk_getsize(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
97
                                        H5VL_object_t *dst_file, bool *dst_copy);
98
static herr_t H5T__ref_obj_disk_read(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
99
                                     H5VL_object_t *dst_file, void *dst_buf, size_t dst_size);
100
101
static herr_t H5T__ref_dsetreg_disk_isnull(const H5VL_object_t *src_file, const void *src_buf, bool *isnull);
102
static size_t H5T__ref_dsetreg_disk_getsize(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
103
                                            H5VL_object_t *dst_file, bool *dst_copy);
104
static herr_t H5T__ref_dsetreg_disk_read(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
105
                                         H5VL_object_t *dst_file, void *dst_buf, size_t dst_size);
106
107
/*******************/
108
/* Local Variables */
109
/*******************/
110
111
/* Class for reference in memory */
112
static const H5T_ref_class_t H5T_ref_mem_g = {
113
    H5T__ref_mem_isnull,  /* 'isnull' */
114
    H5T__ref_mem_setnull, /* 'setnull' */
115
    H5T__ref_mem_getsize, /* 'getsize' */
116
    H5T__ref_mem_read,    /* 'read' */
117
    H5T__ref_mem_write    /* 'write' */
118
};
119
120
static const H5T_ref_class_t H5T_ref_disk_g = {
121
    H5T__ref_disk_isnull,  /* 'isnull' */
122
    H5T__ref_disk_setnull, /* 'setnull' */
123
    H5T__ref_disk_getsize, /* 'getsize' */
124
    H5T__ref_disk_read,    /* 'read' */
125
    H5T__ref_disk_write    /* 'write' */
126
};
127
128
static const H5T_ref_class_t H5T_ref_obj_disk_g = {
129
    H5T__ref_obj_disk_isnull,  /* 'isnull' */
130
    NULL,                      /* 'setnull' */
131
    H5T__ref_obj_disk_getsize, /* 'getsize' */
132
    H5T__ref_obj_disk_read,    /* 'read' */
133
    NULL                       /* 'write' */
134
};
135
136
static const H5T_ref_class_t H5T_ref_dsetreg_disk_g = {
137
    H5T__ref_dsetreg_disk_isnull,  /* 'isnull' */
138
    NULL,                          /* 'setnull' */
139
    H5T__ref_dsetreg_disk_getsize, /* 'getsize' */
140
    H5T__ref_dsetreg_disk_read,    /* 'read' */
141
    NULL                           /* 'write' */
142
};
143
144
/*-------------------------------------------------------------------------
145
 * Function: H5T__ref_set_loc
146
 *
147
 * Purpose: Sets the location of a reference datatype to be either on disk
148
 *          or in memory
149
 *
150
 * Return:
151
 *  One of two values on success:
152
 *      true - If the location of any reference types changed
153
 *      false - If the location of any reference types is the same
154
 *  Negative value is returned on failure
155
 *
156
 *-------------------------------------------------------------------------
157
 */
158
htri_t
159
H5T__ref_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc)
160
38
{
161
38
    htri_t ret_value = false; /* Indicate success, but no location change */
162
163
38
    FUNC_ENTER_PACKAGE
164
38
    H5T_REF_LOG_DEBUG("loc=%d", (int)loc);
165
166
38
    assert(dt);
167
    /* f is NULL when loc == H5T_LOC_MEMORY */
168
38
    assert(loc >= H5T_LOC_BADLOC && loc < H5T_LOC_MAXLOC);
169
170
    /* Only change the location if it's different */
171
38
    if (loc == dt->shared->u.atomic.u.r.loc && file == dt->shared->u.atomic.u.r.file)
172
16
        HGOTO_DONE(false);
173
174
22
    switch (loc) {
175
6
        case H5T_LOC_MEMORY: /* Memory based reference datatype */
176
177
            /* NB. We allow for the file to be non-NULL when doing
178
             * memory-to-memory conversion */
179
180
            /* Mark this type as being stored in memory */
181
6
            dt->shared->u.atomic.u.r.loc = H5T_LOC_MEMORY;
182
183
            /* Release owned file */
184
6
            if (dt->shared->owned_vol_obj) {
185
0
                if (H5VL_free_object(dt->shared->owned_vol_obj) < 0)
186
0
                    HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCLOSEOBJ, FAIL, "unable to close owned VOL object");
187
0
                dt->shared->owned_vol_obj = NULL;
188
0
            } /* end if */
189
190
            /* Reset file ID (since this reference is in memory) */
191
6
            dt->shared->u.atomic.u.r.file = file; /* file is NULL */
192
193
6
            if (dt->shared->u.atomic.u.r.opaque) {
194
                /* Size in memory, disk size is different */
195
2
                dt->shared->size          = H5T_REF_MEM_SIZE;
196
2
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
197
198
                /* Set up the function pointers to access the reference in memory */
199
2
                dt->shared->u.atomic.u.r.cls = &H5T_ref_mem_g;
200
2
            } /* end if */
201
4
            else if (dt->shared->u.atomic.u.r.rtype == H5R_OBJECT1) {
202
                /* Size in memory, disk size is different */
203
2
                dt->shared->size          = H5T_REF_OBJ_MEM_SIZE;
204
2
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
205
206
                /* Unused for now */
207
2
                dt->shared->u.atomic.u.r.cls = NULL;
208
2
            } /* end else-if */
209
2
            else if (dt->shared->u.atomic.u.r.rtype == H5R_DATASET_REGION1) {
210
                /* Size in memory, disk size is different */
211
2
                dt->shared->size          = H5T_REF_DSETREG_MEM_SIZE;
212
2
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
213
214
                /* Unused for now */
215
2
                dt->shared->u.atomic.u.r.cls = NULL;
216
2
            } /* end else-if */
217
0
            else
218
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "invalid location");
219
6
            break;
220
221
16
        case H5T_LOC_DISK: /* Disk based reference datatype */
222
16
            assert(file);
223
224
            /* Mark this type as being stored on disk */
225
16
            dt->shared->u.atomic.u.r.loc = H5T_LOC_DISK;
226
227
            /* Set file pointer (since this reference is on disk) */
228
16
            dt->shared->u.atomic.u.r.file = file;
229
230
            /* dt now owns a reference to file */
231
16
            if (H5T_own_vol_obj(dt, file) < 0)
232
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "can't give ownership of VOL object");
233
234
16
            if (dt->shared->u.atomic.u.r.rtype == H5R_OBJECT1) {
235
15
                H5F_t *f;
236
237
#ifndef NDEBUG
238
                {
239
                    bool is_native = false; /* Whether the file is using the native VOL connector */
240
241
                    /* Check if using native VOL connector */
242
                    if (H5VL_object_is_native(file, &is_native) < 0)
243
                        HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL,
244
                                    "can't query if file uses native VOL connector");
245
246
                    /* Must use native VOL connector for this operation */
247
                    assert(is_native);
248
                }
249
#endif /* NDEBUG */
250
251
                /* Retrieve file from VOL object */
252
15
                if (NULL == (f = (H5F_t *)H5VL_object_data(file)))
253
0
                    HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
254
255
                /* Size on disk, memory size is different */
256
15
                dt->shared->size          = H5T_REF_OBJ_DISK_SIZE(f);
257
15
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
258
259
                /* Set up the function pointers to access the reference in memory */
260
15
                dt->shared->u.atomic.u.r.cls = &H5T_ref_obj_disk_g;
261
15
            } /* end if */
262
1
            else if (dt->shared->u.atomic.u.r.rtype == H5R_DATASET_REGION1) {
263
1
                H5F_t *f;
264
265
#ifndef NDEBUG
266
                {
267
                    bool is_native = false; /* Whether the file is using the native VOL connector */
268
269
                    /* Check if using native VOL connector */
270
                    if (H5VL_object_is_native(file, &is_native) < 0)
271
                        HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL,
272
                                    "can't query if file uses native VOL connector");
273
274
                    /* Must use native VOL connector for this operation */
275
                    assert(is_native);
276
                }
277
#endif /* NDEBUG */
278
279
                /* Retrieve file from VOL object */
280
1
                if (NULL == (f = (H5F_t *)H5VL_object_data(file)))
281
0
                    HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
282
283
                /* Size on disk, memory size is different */
284
1
                dt->shared->size          = H5T_REF_DSETREG_DISK_SIZE(f);
285
1
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
286
287
                /* Set up the function pointers to access the reference in memory */
288
1
                dt->shared->u.atomic.u.r.cls = &H5T_ref_dsetreg_disk_g;
289
1
            } /* end else-if */
290
0
            else {
291
0
                H5VL_file_cont_info_t cont_info = {H5VL_CONTAINER_INFO_VERSION, 0, 0, 0};
292
0
                H5VL_file_get_args_t  vol_cb_args; /* Arguments to VOL callback */
293
0
                size_t                ref_encode_size;
294
0
                H5R_ref_priv_t        fixed_ref;
295
296
                /* Set up VOL callback arguments */
297
0
                vol_cb_args.op_type                 = H5VL_FILE_GET_CONT_INFO;
298
0
                vol_cb_args.args.get_cont_info.info = &cont_info;
299
300
                /* Get container info */
301
0
                if (H5VL_file_get(file, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
302
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get container info");
303
304
                /* Retrieve min encode size (when references have no vlen part) */
305
0
                memset(&fixed_ref, 0, sizeof(fixed_ref));
306
0
                fixed_ref.type       = (int8_t)H5R_OBJECT2;
307
0
                fixed_ref.token_size = (uint8_t)cont_info.token_size;
308
0
                if (H5R__encode(NULL, &fixed_ref, NULL, &ref_encode_size, 0) < 0)
309
0
                    HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't get encode size");
310
311
                /* Size on disk, memory size is different */
312
0
                dt->shared->size =
313
0
                    MAX(sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE + cont_info.blob_id_size, ref_encode_size);
314
0
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
315
316
                /* Set up the function pointers to access the information on
317
                 * disk. Region and attribute references are stored identically
318
                 * on disk, so use the same functions.
319
                 */
320
0
                dt->shared->u.atomic.u.r.cls = &H5T_ref_disk_g;
321
0
            }
322
16
            break;
323
324
16
        case H5T_LOC_BADLOC:
325
            /* Allow undefined location. In H5Odtype.c, H5O_dtype_decode sets undefined
326
             * location for reference type and leaves it for the caller to decide.
327
             */
328
0
            dt->shared->u.atomic.u.r.loc = H5T_LOC_BADLOC;
329
330
            /* Reset file pointer */
331
0
            dt->shared->u.atomic.u.r.file = NULL;
332
333
            /* Reset the function pointers */
334
0
            dt->shared->u.atomic.u.r.cls = NULL;
335
336
0
            break;
337
338
0
        case H5T_LOC_MAXLOC: /* MAXLOC is invalid */
339
0
        default:
340
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "invalid reference datatype location");
341
22
    } /* end switch */
342
343
    /* Indicate that the location changed */
344
22
    ret_value = true;
345
346
38
done:
347
38
    FUNC_LEAVE_NOAPI(ret_value)
348
38
} /* end H5T__ref_set_loc() */
349
350
/*-------------------------------------------------------------------------
351
 * Function:    H5T__ref_mem_isnull
352
 *
353
 * Purpose: Check if it's a NULL / uninitialized reference.
354
 *
355
 * Return:  Non-negative on success/Negative on failure
356
 *
357
 *-------------------------------------------------------------------------
358
 */
359
static herr_t
360
H5T__ref_mem_isnull(const H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf, bool *isnull)
361
0
{
362
0
    const unsigned char zeros[H5T_REF_MEM_SIZE] = {0};
363
0
    herr_t              ret_value               = SUCCEED;
364
365
0
    FUNC_ENTER_PACKAGE_NOERR
366
0
    H5T_REF_LOG_DEBUG("");
367
368
    /* Check parameters */
369
0
    assert(src_buf);
370
0
    assert(isnull);
371
372
0
    *isnull = (0 == memcmp(src_buf, zeros, H5T_REF_MEM_SIZE)) ? true : false;
373
374
0
    FUNC_LEAVE_NOAPI(ret_value)
375
0
} /* end H5T__ref_mem_isnull() */
376
377
/*-------------------------------------------------------------------------
378
 * Function:    H5T__ref_mem_setnull
379
 *
380
 * Purpose: Set a reference as NULL / uninitialized.
381
 *
382
 * Return:  Non-negative on success/Negative on failure
383
 *
384
 *-------------------------------------------------------------------------
385
 */
386
static herr_t
387
H5T__ref_mem_setnull(H5VL_object_t H5_ATTR_UNUSED *dst_file, void *dst_buf, H5_ATTR_UNUSED void *bg_buf)
388
0
{
389
0
    herr_t ret_value = SUCCEED;
390
391
0
    FUNC_ENTER_PACKAGE_NOERR
392
0
    H5T_REF_LOG_DEBUG("");
393
394
0
    memset(dst_buf, 0, H5T_REF_MEM_SIZE);
395
396
0
    FUNC_LEAVE_NOAPI(ret_value)
397
0
} /* end H5T__ref_mem_setnull() */
398
399
/*-------------------------------------------------------------------------
400
 * Function:  H5T__ref_mem_getsize
401
 *
402
 * Purpose: Retrieves the size of a memory based reference.
403
 *
404
 * Return:  Non-negative on success/zero on failure
405
 *
406
 *-------------------------------------------------------------------------
407
 */
408
static size_t
409
H5T__ref_mem_getsize(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf,
410
                     size_t H5_ATTR_UNUSED src_size, H5VL_object_t *dst_file, bool *dst_copy)
411
0
{
412
0
    H5VL_object_t        *vol_obj = NULL; /* VOL object for src ref's location */
413
0
    const H5R_ref_priv_t *src_ref = (const H5R_ref_priv_t *)src_buf;
414
0
    char                 *file_name_buf_dyn =
415
0
        NULL; /* Pointer to dynamically allocated buffer for file name, if static buffer is too small */
416
0
    unsigned flags     = 0; /* References flags */
417
0
    size_t   ret_value = 0; /* Return value */
418
419
0
    FUNC_ENTER_PACKAGE
420
0
    H5T_REF_LOG_DEBUG("");
421
422
    /* Sanity check */
423
0
    assert(src_buf);
424
0
    assert(src_size == H5T_REF_MEM_SIZE);
425
426
0
    if (NULL != dst_file) {
427
0
        bool files_equal = true; /* Whether src & dst references are in same file */
428
429
        /* Retrieve VOL object */
430
0
        if (NULL == (vol_obj = H5VL_vol_object(src_ref->loc_id)))
431
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid location identifier");
432
433
        /* Set external flag if referenced file is not destination file */
434
0
        if (H5VL_file_is_same(vol_obj, dst_file, &files_equal) < 0)
435
0
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOMPARE, 0, "can't check if files are equal");
436
0
        flags |= !files_equal ? H5R_IS_EXTERNAL : 0;
437
0
    }
438
439
    /* Force re-calculating encoding size if any flags are set */
440
0
    if (flags || !src_ref->encode_size) {
441
0
        H5VL_file_get_args_t vol_cb_args;               /* Arguments to VOL callback */
442
0
        char                *file_name = NULL;          /* Actual file name */
443
0
        char                 file_name_buf_static[256]; /* File name */
444
0
        size_t               file_name_len = 0;         /* Length of file name */
445
446
        /* Pass the correct encoding version for the selection depending on the
447
         * file libver bounds, this is later retrieved in H5S hyper encode */
448
0
        if (src_ref->type == (int8_t)H5R_DATASET_REGION2) {
449
0
            bool is_native = false; /* Whether the dest. file is using the native VOL connector */
450
451
            /* Check if using native VOL connector */
452
0
            if (H5VL_object_is_native(dst_file, &is_native) < 0)
453
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't query if file uses native VOL connector");
454
455
            /* Set the file's libver bounds if using the native VOL connector */
456
0
            if (is_native) {
457
0
                H5F_t *dst_f; /* Native file struct */
458
459
0
                if (NULL == (dst_f = (H5F_t *)H5VL_object_data(dst_file)))
460
0
                    HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object");
461
0
                H5CX_set_libver_bounds(dst_f);
462
0
            } /* end if */
463
0
            else
464
0
                H5CX_set_libver_bounds(NULL);
465
0
        } /* end if */
466
467
        /* Set up VOL callback arguments */
468
0
        vol_cb_args.op_type                     = H5VL_FILE_GET_NAME;
469
0
        vol_cb_args.args.get_name.type          = H5I_FILE;
470
0
        vol_cb_args.args.get_name.buf_size      = sizeof(file_name_buf_static);
471
0
        vol_cb_args.args.get_name.buf           = file_name_buf_static;
472
0
        vol_cb_args.args.get_name.file_name_len = &file_name_len;
473
474
        /* Get file name */
475
0
        if (H5VL_file_get(vol_obj, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, NULL) < 0)
476
0
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't get file name");
477
478
        /* Check if we need to allocate a buffer for the file name */
479
0
        if (file_name_len >= sizeof(file_name_buf_static)) {
480
            /* Allocate file name buffer */
481
0
            if (NULL == (file_name_buf_dyn = H5MM_malloc(file_name_len + 1)))
482
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTALLOC, 0, "can't allocate space for file name");
483
484
            /* Update VOL callback arguments */
485
0
            vol_cb_args.args.get_name.buf_size = file_name_len + 1;
486
0
            vol_cb_args.args.get_name.buf      = file_name_buf_dyn;
487
488
            /* Get file name again */
489
0
            if (H5VL_file_get(vol_obj, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, NULL) < 0)
490
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't get file name");
491
492
0
            file_name = file_name_buf_dyn;
493
0
        } /* end if */
494
0
        else
495
0
            file_name = file_name_buf_static;
496
497
        /* Determine encoding size */
498
0
        if (H5R__encode(file_name, src_ref, NULL, &ret_value, flags) < 0)
499
0
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, 0, "unable to determine encoding size");
500
0
    } /* end if */
501
0
    else {
502
        /* Can do a direct copy and skip blob decoding */
503
0
        if (src_ref->type == (int8_t)H5R_OBJECT2)
504
0
            *dst_copy = true;
505
506
        /* Get cached encoding size */
507
0
        ret_value = src_ref->encode_size;
508
0
    } /* end else */
509
510
0
done:
511
0
    H5MM_xfree(file_name_buf_dyn);
512
513
0
    FUNC_LEAVE_NOAPI(ret_value)
514
0
} /* end H5T__ref_mem_getsize() */
515
516
/*-------------------------------------------------------------------------
517
 * Function:  H5T__ref_mem_read
518
 *
519
 * Purpose: "Reads" the memory based reference into a buffer
520
 *
521
 * Return:  Non-negative on success/Negative on failure
522
 *
523
 *-------------------------------------------------------------------------
524
 */
525
static herr_t
526
H5T__ref_mem_read(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf, size_t H5_ATTR_UNUSED src_size,
527
                  H5VL_object_t *dst_file, void *dst_buf, size_t dst_size)
528
0
{
529
0
    H5VL_object_t        *vol_obj; /* VOL object for src ref's location */
530
0
    const H5R_ref_priv_t *src_ref     = (const H5R_ref_priv_t *)src_buf;
531
0
    bool                  files_equal = true; /* Whether src & dst references are in same file */
532
0
    char                 *file_name   = NULL; /* Actual file name */
533
0
    char                  file_name_buf_static[256] = {'\0'}; /* File name */
534
0
    char                 *file_name_buf_dyn =
535
0
        NULL; /* Pointer to dynamically allocated buffer for file name, if static buffer is too small */
536
0
    unsigned flags     = 0;       /* References flags */
537
0
    herr_t   ret_value = SUCCEED; /* Return value */
538
539
0
    FUNC_ENTER_PACKAGE
540
0
    H5T_REF_LOG_DEBUG("");
541
542
    /* Sanity check */
543
0
    assert(src_buf);
544
0
    assert(src_size == H5T_REF_MEM_SIZE);
545
0
    assert(dst_buf);
546
0
    assert(dst_size);
547
548
    /* Memory-to-memory conversion to support vlen conversion */
549
0
    if (NULL == dst_file) {
550
0
        H5MM_memcpy(dst_buf, src_buf, dst_size);
551
0
        HGOTO_DONE(ret_value);
552
0
    }
553
554
    /* Retrieve VOL object */
555
0
    if (NULL == (vol_obj = H5VL_vol_object(src_ref->loc_id)))
556
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid location identifier");
557
558
    /* Set external flag if referenced file is not destination file */
559
0
    if (H5VL_file_is_same(vol_obj, dst_file, &files_equal) < 0)
560
0
        HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOMPARE, FAIL, "can't check if files are equal");
561
0
    flags |= !files_equal ? H5R_IS_EXTERNAL : 0;
562
563
    /* Pass the correct encoding version for the selection depending on the
564
     * file libver bounds, this is later retrieved in H5S hyper encode */
565
0
    if (src_ref->type == (int8_t)H5R_DATASET_REGION2) {
566
0
        bool is_native = false; /* Whether the dest. file is using the native VOL connector */
567
568
        /* Check if using native VOL connector */
569
0
        if (H5VL_object_is_native(dst_file, &is_native) < 0)
570
0
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't query if file uses native VOL connector");
571
572
        /* Set the file's libver bounds if using the native VOL connector */
573
0
        if (is_native) {
574
0
            H5F_t *dst_f;
575
576
0
            if (NULL == (dst_f = (H5F_t *)H5VL_object_data(dst_file)))
577
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object");
578
0
            H5CX_set_libver_bounds(dst_f);
579
0
        } /* end if */
580
0
        else
581
0
            H5CX_set_libver_bounds(NULL);
582
0
    } /* end if */
583
584
    /* Get file name (if external reference) */
585
0
    if (flags) {
586
0
        H5VL_file_get_args_t vol_cb_args;       /* Arguments to VOL callback */
587
0
        size_t               file_name_len = 0; /* Length of file name */
588
589
        /* Set up VOL callback arguments */
590
0
        vol_cb_args.op_type                     = H5VL_FILE_GET_NAME;
591
0
        vol_cb_args.args.get_name.type          = H5I_FILE;
592
0
        vol_cb_args.args.get_name.buf_size      = sizeof(file_name_buf_static);
593
0
        vol_cb_args.args.get_name.buf           = file_name_buf_static;
594
0
        vol_cb_args.args.get_name.file_name_len = &file_name_len;
595
596
        /* Get file name */
597
0
        if (H5VL_file_get(vol_obj, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, NULL) < 0)
598
0
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't get file name");
599
600
        /* Check if we need to allocate a buffer for the file name */
601
0
        if (file_name_len >= sizeof(file_name_buf_static)) {
602
            /* Allocate file name buffer */
603
0
            if (NULL == (file_name_buf_dyn = H5MM_malloc(file_name_len + 1)))
604
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTALLOC, 0, "can't allocate space for file name");
605
606
            /* Update VOL callback arguments */
607
0
            vol_cb_args.args.get_name.buf_size = file_name_len + 1;
608
0
            vol_cb_args.args.get_name.buf      = file_name_buf_dyn;
609
610
            /* Get file name again */
611
0
            if (H5VL_file_get(vol_obj, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, NULL) < 0)
612
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't get file name");
613
614
0
            file_name = file_name_buf_dyn;
615
0
        } /* end if */
616
0
        else
617
0
            file_name = file_name_buf_static;
618
0
    } /* end if */
619
620
    /* Encode reference */
621
0
    if (H5R__encode(file_name, src_ref, (unsigned char *)dst_buf, &dst_size, flags) < 0)
622
0
        HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "Cannot encode reference");
623
624
0
done:
625
0
    H5MM_xfree(file_name_buf_dyn);
626
627
0
    FUNC_LEAVE_NOAPI(ret_value)
628
0
} /* end H5T__ref_mem_read() */
629
630
/*-------------------------------------------------------------------------
631
 * Function:  H5T__ref_mem_write
632
 *
633
 * Purpose: "Writes" the memory reference from a buffer
634
 *
635
 * Return:  Non-negative on success/Negative on failure
636
 *
637
 *-------------------------------------------------------------------------
638
 */
639
static herr_t
640
H5T__ref_mem_write(H5VL_object_t *src_file, const void *src_buf, size_t src_size, H5R_type_t src_type,
641
                   H5VL_object_t H5_ATTR_UNUSED *dst_file, void *dst_buf,
642
                   size_t H5_ATTR_NDEBUG_UNUSED dst_size, void H5_ATTR_UNUSED *bg_buf)
643
0
{
644
0
    H5F_t         *src_f   = NULL;
645
0
    hid_t          file_id = H5I_INVALID_HID;
646
0
    H5R_ref_priv_t tmp_ref; /* Temporary reference to decode into */
647
0
    herr_t         ret_value = SUCCEED;
648
649
0
    FUNC_ENTER_PACKAGE
650
0
    H5T_REF_LOG_DEBUG("");
651
652
    /* Sanity check */
653
0
    assert(src_buf);
654
0
    assert(src_size);
655
0
    assert(dst_buf);
656
0
    assert(dst_size == H5T_REF_MEM_SIZE);
657
658
    /* Memory-to-memory conversion to support vlen conversion */
659
0
    if (NULL == src_file) {
660
0
        H5MM_memcpy(dst_buf, src_buf, src_size);
661
0
        HGOTO_DONE(ret_value);
662
0
    }
663
664
#ifndef NDEBUG
665
    if ((src_type == H5R_OBJECT1) || (src_type == H5R_DATASET_REGION1)) {
666
        bool is_native = false; /* Whether the src file is using the native VOL connector */
667
668
        /* Check if using native VOL connector */
669
        if (H5VL_object_is_native(src_file, &is_native) < 0)
670
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't query if file uses native VOL connector");
671
672
        /* Must use native VOL connector for this operation */
673
        assert(is_native);
674
    }
675
#endif /* NDEBUG */
676
677
    /* Retrieve file from VOL object */
678
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
679
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
680
681
    /* Make sure reference buffer is correctly initialized */
682
0
    memset(&tmp_ref, 0, sizeof(tmp_ref));
683
684
0
    switch (src_type) {
685
0
        case H5R_OBJECT1: {
686
0
            size_t token_size = H5F_SIZEOF_ADDR(src_f);
687
688
0
            if (H5R__create_object((const H5O_token_t *)src_buf, token_size, &tmp_ref) < 0)
689
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create object reference");
690
0
        } break;
691
692
0
        case H5R_DATASET_REGION1: {
693
0
            const struct H5Tref_dsetreg *src_reg    = (const struct H5Tref_dsetreg *)src_buf;
694
0
            size_t                       token_size = H5F_SIZEOF_ADDR(src_f);
695
696
0
            if (H5R__create_region(&src_reg->token, token_size, src_reg->space, &tmp_ref) < 0)
697
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create region reference");
698
699
            /* create_region creates its internal copy of the space */
700
0
            if (H5S_close(src_reg->space) < 0)
701
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTFREE, FAIL, "Cannot close dataspace");
702
0
        } break;
703
704
0
        case H5R_DATASET_REGION2:
705
            /* Pass the correct encoding version for the selection depending on the
706
             * file libver bounds, this is later retrieved in H5S hyper decode */
707
0
            H5CX_set_libver_bounds(src_f);
708
            /* FALLTHROUGH */
709
0
            H5_ATTR_FALLTHROUGH
710
0
        case H5R_OBJECT2:
711
0
        case H5R_ATTR:
712
            /* Decode reference */
713
0
            if (H5R__decode((const unsigned char *)src_buf, &src_size, &tmp_ref) < 0)
714
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Cannot decode reference");
715
0
            break;
716
717
0
        case H5R_BADTYPE:
718
0
        case H5R_MAXTYPE:
719
0
        default:
720
0
            assert("unknown reference type" && 0);
721
0
            HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)");
722
0
    } /* end switch */
723
724
    /* If no filename set, this is not an external reference */
725
0
    if (NULL == H5R_REF_FILENAME(&tmp_ref)) {
726
        /* TODO temporary hack to retrieve file object */
727
0
        if ((file_id = H5F_get_file_id(src_file, H5I_FILE, false)) < 0)
728
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object");
729
730
        /* Attach loc ID to reference and hold reference to it, this is a
731
         * user exposed reference so set app_ref to true. */
732
0
        if (H5R__set_loc_id(&tmp_ref, file_id, true, true) < 0)
733
0
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "unable to attach location id to reference");
734
0
    } /* end if */
735
736
    /* Set output info */
737
0
    H5MM_memcpy(dst_buf, &tmp_ref, sizeof(tmp_ref));
738
739
0
done:
740
0
    if ((file_id != H5I_INVALID_HID) && (H5I_dec_ref(file_id) < 0))
741
0
        HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "unable to decrement refcount on location id");
742
0
    FUNC_LEAVE_NOAPI(ret_value)
743
0
} /* end H5T__ref_mem_write() */
744
745
/*-------------------------------------------------------------------------
746
 * Function:    H5T__ref_disk_isnull
747
 *
748
 * Purpose: Check if it's a NULL / uninitialized reference.
749
 *
750
 * Return:  Non-negative on success/Negative on failure
751
 *
752
 *-------------------------------------------------------------------------
753
 */
754
/*
755
 * It is the correct thing to do to have the reference buffer
756
 * be const-qualified here, but the VOL "blob specific" routine
757
 * needs a non-const pointer since an operation might modify
758
 * the "blob". Disable this warning here (at least temporarily)
759
 * for this reason.
760
 */
761
H5_WARN_CAST_AWAY_CONST_OFF
762
static herr_t
763
H5T__ref_disk_isnull(const H5VL_object_t *src_file, const void *src_buf, bool *isnull)
764
0
{
765
0
    const uint8_t *p = (const uint8_t *)src_buf;
766
0
    H5R_type_t     ref_type;
767
0
    herr_t         ret_value = SUCCEED;
768
769
0
    FUNC_ENTER_PACKAGE
770
0
    H5T_REF_LOG_DEBUG("");
771
772
    /* Check parameters */
773
0
    assert(src_file);
774
0
    assert(src_buf);
775
0
    assert(isnull);
776
777
    /* Try to check encoded reference type */
778
0
    ref_type = (H5R_type_t)*p++;
779
0
    if (ref_type) {
780
        /* This is a valid reference */
781
0
        *isnull = false;
782
0
    }
783
0
    else {
784
0
        H5VL_blob_specific_args_t vol_cb_args; /* Arguments to VOL callback */
785
786
        /* Skip the size / header */
787
0
        p = (const uint8_t *)src_buf + H5R_ENCODE_HEADER_SIZE + sizeof(uint32_t);
788
789
        /* Set up VOL callback arguments */
790
0
        vol_cb_args.op_type             = H5VL_BLOB_ISNULL;
791
0
        vol_cb_args.args.is_null.isnull = isnull;
792
793
        /* Check if blob ID is "nil" */
794
0
        if (H5VL_blob_specific(src_file, (void *)p, &vol_cb_args) < 0)
795
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to check if a blob ID is 'nil'");
796
0
    }
797
798
0
done:
799
0
    FUNC_LEAVE_NOAPI(ret_value)
800
0
} /* end H5T__ref_disk_isnull() */
801
H5_WARN_CAST_AWAY_CONST_ON
802
803
/*-------------------------------------------------------------------------
804
 * Function:    H5T__ref_disk_setnull
805
 *
806
 * Purpose: Set a reference as NULL / uninitialized.
807
 *
808
 * Return:  Non-negative on success/Negative on failure
809
 *
810
 *-------------------------------------------------------------------------
811
 */
812
static herr_t
813
H5T__ref_disk_setnull(H5VL_object_t *dst_file, void *dst_buf, void *bg_buf)
814
0
{
815
0
    H5VL_blob_specific_args_t vol_cb_args; /* Arguments to VOL callback */
816
0
    uint8_t                  *q         = (uint8_t *)dst_buf;
817
0
    uint8_t                  *p_bg      = (uint8_t *)bg_buf;
818
0
    herr_t                    ret_value = SUCCEED;
819
820
0
    FUNC_ENTER_PACKAGE
821
0
    H5T_REF_LOG_DEBUG("");
822
823
0
    assert(dst_file);
824
0
    assert(dst_buf);
825
826
    /* TODO Should get rid of bg stuff */
827
0
    if (p_bg) {
828
        /* Skip the size / header */
829
0
        p_bg += (sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE);
830
831
        /* Set up VOL callback arguments */
832
0
        vol_cb_args.op_type = H5VL_BLOB_DELETE;
833
834
        /* Remove blob for old data */
835
0
        if (H5VL_blob_specific(dst_file, (void *)p_bg, &vol_cb_args) < 0)
836
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to delete blob");
837
0
    } /* end if */
838
839
    /* Copy header manually so that it does not get encoded into the blob */
840
0
    memset(q, 0, H5R_ENCODE_HEADER_SIZE);
841
0
    q += H5R_ENCODE_HEADER_SIZE;
842
843
    /* Set the size */
844
0
    UINT32ENCODE(q, 0);
845
846
    /* Set up VOL callback arguments */
847
0
    vol_cb_args.op_type = H5VL_BLOB_SETNULL;
848
849
    /* Set blob ID to "nil" */
850
0
    if (H5VL_blob_specific(dst_file, q, &vol_cb_args) < 0)
851
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to set a blob ID to 'nil'");
852
853
0
done:
854
0
    FUNC_LEAVE_NOAPI(ret_value)
855
0
} /* end H5T__ref_disk_setnull() */
856
857
/*-------------------------------------------------------------------------
858
 * Function:  H5T__ref_disk_getsize
859
 *
860
 * Purpose: Retrieves the length of a disk based reference.
861
 *
862
 * Return:  Non-negative value (cannot fail)
863
 *
864
 *-------------------------------------------------------------------------
865
 */
866
static size_t
867
H5T__ref_disk_getsize(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf, size_t src_size,
868
                      H5VL_object_t H5_ATTR_UNUSED *dst_file, bool *dst_copy)
869
0
{
870
0
    const uint8_t *p = (const uint8_t *)src_buf;
871
0
    unsigned       flags;
872
0
    H5R_type_t     ref_type;
873
0
    size_t         ret_value = 0;
874
875
0
    FUNC_ENTER_PACKAGE
876
0
    H5T_REF_LOG_DEBUG("");
877
878
0
    assert(src_buf);
879
880
    /* Set reference type */
881
0
    ref_type = (H5R_type_t)*p++;
882
0
    if (ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE)
883
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid reference type");
884
885
    /* Set flags */
886
0
    flags = (unsigned)*p++;
887
888
0
    if (!(flags & H5R_IS_EXTERNAL) && (ref_type == H5R_OBJECT2)) {
889
        /* Can do a direct copy and skip blob decoding */
890
0
        *dst_copy = true;
891
892
0
        ret_value = src_size;
893
0
    } /* end if */
894
0
    else {
895
        /* Retrieve encoded data size */
896
0
        UINT32DECODE(p, ret_value);
897
898
        /* Add size of the header */
899
0
        ret_value += H5R_ENCODE_HEADER_SIZE;
900
0
    } /* end else */
901
902
0
done:
903
0
    FUNC_LEAVE_NOAPI(ret_value)
904
0
} /* end H5T__ref_disk_getsize() */
905
906
/*-------------------------------------------------------------------------
907
 * Function:  H5T__ref_disk_read
908
 *
909
 * Purpose: Reads the disk based reference into a buffer
910
 *
911
 * Return:  Non-negative on success/Negative on failure
912
 *
913
 *-------------------------------------------------------------------------
914
 */
915
static herr_t
916
H5T__ref_disk_read(H5VL_object_t *src_file, const void *src_buf, size_t H5_ATTR_NDEBUG_UNUSED src_size,
917
                   H5VL_object_t H5_ATTR_UNUSED *dst_file, void *dst_buf, size_t dst_size)
918
0
{
919
0
    const uint8_t *p         = (const uint8_t *)src_buf;
920
0
    uint8_t       *q         = (uint8_t *)dst_buf;
921
0
    size_t         blob_size = dst_size;
922
0
    herr_t         ret_value = SUCCEED;
923
924
0
    FUNC_ENTER_PACKAGE
925
0
    H5T_REF_LOG_DEBUG("");
926
927
0
    assert(src_file);
928
0
    assert(src_buf);
929
0
    assert(dst_buf);
930
0
    assert(dst_size);
931
932
    /* Copy header manually */
933
0
    H5MM_memcpy(q, p, H5R_ENCODE_HEADER_SIZE);
934
0
    p += H5R_ENCODE_HEADER_SIZE;
935
0
    q += H5R_ENCODE_HEADER_SIZE;
936
0
    blob_size -= H5R_ENCODE_HEADER_SIZE;
937
938
    /* Skip the size */
939
0
    p += sizeof(uint32_t);
940
0
    assert(src_size > (H5R_ENCODE_HEADER_SIZE + sizeof(uint32_t)));
941
942
    /* Retrieve blob */
943
0
    if (H5VL_blob_get(src_file, p, q, blob_size, NULL) < 0)
944
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get blob");
945
946
0
done:
947
0
    FUNC_LEAVE_NOAPI(ret_value)
948
0
} /* end H5T__ref_disk_read() */
949
950
/*-------------------------------------------------------------------------
951
 * Function:  H5T__ref_disk_write
952
 *
953
 * Purpose: Writes the disk based reference from a buffer
954
 *
955
 * Return:  Non-negative on success/Negative on failure
956
 *
957
 *-------------------------------------------------------------------------
958
 */
959
static herr_t
960
H5T__ref_disk_write(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf, size_t src_size,
961
                    H5R_type_t H5_ATTR_UNUSED src_type, H5VL_object_t *dst_file, void *dst_buf,
962
                    size_t H5_ATTR_NDEBUG_UNUSED dst_size, void *bg_buf)
963
0
{
964
0
    const uint8_t *p         = (const uint8_t *)src_buf;
965
0
    uint8_t       *q         = (uint8_t *)dst_buf;
966
0
    uint8_t       *p_bg      = (uint8_t *)bg_buf;
967
0
    herr_t         ret_value = SUCCEED;
968
969
0
    FUNC_ENTER_PACKAGE
970
0
    H5T_REF_LOG_DEBUG("");
971
972
0
    assert(src_buf);
973
0
    assert(src_size);
974
0
    assert(dst_file);
975
0
    assert(dst_buf);
976
977
    /* TODO Should get rid of bg stuff */
978
0
    if (p_bg) {
979
0
        H5VL_blob_specific_args_t vol_cb_args; /* Arguments to VOL callback */
980
981
        /* Skip the size / header */
982
0
        p_bg += (sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE);
983
984
#ifndef NDEBUG
985
        size_t p_buf_size_left = dst_size;
986
        assert(p_buf_size_left > (sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE));
987
#endif
988
989
        /* Set up VOL callback arguments */
990
0
        vol_cb_args.op_type = H5VL_BLOB_DELETE;
991
992
        /* Remove blob for old data */
993
0
        if (H5VL_blob_specific(dst_file, (void *)p_bg, &vol_cb_args) < 0)
994
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to delete blob");
995
0
    } /* end if */
996
997
    /* Copy header manually so that it does not get encoded into the blob */
998
0
    H5MM_memcpy(q, p, H5R_ENCODE_HEADER_SIZE);
999
0
    p += H5R_ENCODE_HEADER_SIZE;
1000
0
    q += H5R_ENCODE_HEADER_SIZE;
1001
0
    src_size -= H5R_ENCODE_HEADER_SIZE;
1002
1003
#ifndef NDEBUG
1004
    {
1005
        size_t buf_size_left = dst_size - sizeof(uint32_t);
1006
        assert(buf_size_left > sizeof(uint32_t));
1007
    }
1008
#endif
1009
1010
    /* Set the size */
1011
0
    UINT32ENCODE(q, src_size);
1012
1013
    /* Store blob */
1014
0
    if (H5VL_blob_put(dst_file, p, src_size, q, NULL) < 0)
1015
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to put blob");
1016
1017
0
done:
1018
0
    FUNC_LEAVE_NOAPI(ret_value)
1019
0
} /* end H5T__ref_disk_write() */
1020
1021
/*-------------------------------------------------------------------------
1022
 * Function:    H5T__ref_obj_disk_isnull
1023
 *
1024
 * Purpose: Check if it's a NULL / uninitialized reference.
1025
 *
1026
 * Return:  Non-negative on success/Negative on failure
1027
 *
1028
 *-------------------------------------------------------------------------
1029
 */
1030
static herr_t
1031
H5T__ref_obj_disk_isnull(const H5VL_object_t *src_file, const void *src_buf, bool *isnull)
1032
0
{
1033
0
    H5F_t         *src_f;
1034
0
    const uint8_t *p = (const uint8_t *)src_buf;
1035
0
    haddr_t        addr;
1036
0
    herr_t         ret_value = SUCCEED;
1037
1038
0
    FUNC_ENTER_PACKAGE
1039
0
    H5T_REF_LOG_DEBUG("");
1040
1041
    /* Check parameters */
1042
0
    assert(src_file);
1043
0
    assert(src_buf);
1044
0
    assert(isnull);
1045
1046
#ifndef NDEBUG
1047
    {
1048
        bool is_native = false; /* Whether the src file is using the native VOL connector */
1049
1050
        /* Check if using native VOL connector */
1051
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1052
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't query if file uses native VOL connector");
1053
1054
        /* Must use native VOL connector for this operation */
1055
        assert(is_native);
1056
    }
1057
#endif /* NDEBUG */
1058
1059
    /* Retrieve file from VOL object */
1060
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1061
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
1062
1063
    /* Get the object address */
1064
0
    H5F_addr_decode(src_f, &p, &addr);
1065
1066
    /* Check if heap address is 'nil' */
1067
0
    *isnull = (addr == 0) ? true : false;
1068
1069
0
done:
1070
0
    FUNC_LEAVE_NOAPI(ret_value)
1071
0
} /* end H5T__ref_obj_disk_isnull() */
1072
1073
/*-------------------------------------------------------------------------
1074
 * Function:    H5T__ref_obj_disk_getsize
1075
 *
1076
 * Purpose: Retrieves the length of a disk based reference.
1077
 *
1078
 * Return:  Non-negative value (cannot fail)
1079
 *
1080
 *-------------------------------------------------------------------------
1081
 */
1082
static size_t
1083
H5T__ref_obj_disk_getsize(H5VL_object_t *src_file, const void H5_ATTR_UNUSED *src_buf,
1084
                          size_t H5_ATTR_UNUSED src_size, H5VL_object_t H5_ATTR_UNUSED *dst_file,
1085
                          bool H5_ATTR_UNUSED *dst_copy)
1086
0
{
1087
0
    H5F_t *src_f;
1088
0
    size_t ret_value = 0;
1089
1090
0
    FUNC_ENTER_PACKAGE
1091
0
    H5T_REF_LOG_DEBUG("");
1092
1093
0
    assert(src_file);
1094
0
    assert(src_buf);
1095
1096
#ifndef NDEBUG
1097
    {
1098
        bool is_native = false; /* Whether the src file is using the native VOL connector */
1099
1100
        /* Check if using native VOL connector */
1101
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1102
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't query if file uses native VOL connector");
1103
1104
        /* Must use native VOL connector for this operation */
1105
        assert(is_native);
1106
    }
1107
#endif /* NDEBUG */
1108
1109
    /* Retrieve file from VOL object */
1110
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1111
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object");
1112
1113
0
    assert(src_size == H5T_REF_OBJ_DISK_SIZE(src_f));
1114
1115
0
    ret_value = H5T_REF_OBJ_DISK_SIZE(src_f);
1116
1117
0
done:
1118
0
    FUNC_LEAVE_NOAPI(ret_value)
1119
0
} /* end H5T__ref_obj_disk_getsize() */
1120
1121
/*-------------------------------------------------------------------------
1122
 * Function:    H5T__ref_obj_disk_read
1123
 *
1124
 * Purpose: Reads the disk based reference into a buffer
1125
 *
1126
 * Return:  Non-negative on success/Negative on failure
1127
 *
1128
 *-------------------------------------------------------------------------
1129
 */
1130
static herr_t
1131
H5T__ref_obj_disk_read(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
1132
                       H5VL_object_t H5_ATTR_UNUSED *dst_file, void *dst_buf, size_t H5_ATTR_UNUSED dst_size)
1133
0
{
1134
0
    H5F_t *src_f;
1135
0
    herr_t ret_value = SUCCEED;
1136
1137
0
    FUNC_ENTER_PACKAGE
1138
0
    H5T_REF_LOG_DEBUG("");
1139
1140
0
    assert(src_file);
1141
0
    assert(src_buf);
1142
0
    assert(dst_buf);
1143
1144
#ifndef NDEBUG
1145
    {
1146
        bool is_native = false; /* Whether the src file is using the native VOL connector */
1147
1148
        /* Check if using native VOL connector */
1149
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1150
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't query if file uses native VOL connector");
1151
1152
        /* Must use native VOL connector for this operation */
1153
        assert(is_native);
1154
    }
1155
#endif /* NDEBUG */
1156
1157
    /* Retrieve file from VOL object */
1158
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1159
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
1160
1161
0
    assert(src_size == H5T_REF_OBJ_DISK_SIZE(src_f));
1162
0
    assert(dst_size == H5F_SIZEOF_ADDR(src_f));
1163
1164
    /* Get object address */
1165
0
    if (H5R__decode_token_obj_compat((const unsigned char *)src_buf, &src_size, (H5O_token_t *)dst_buf,
1166
0
                                     H5F_SIZEOF_ADDR(src_f)) < 0)
1167
0
        HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object address");
1168
1169
0
done:
1170
0
    FUNC_LEAVE_NOAPI(ret_value)
1171
0
} /* end H5T__ref_obj_disk_read() */
1172
1173
/*-------------------------------------------------------------------------
1174
 * Function:    H5T__ref_dsetreg_disk_isnull
1175
 *
1176
 * Purpose: Check if it's a NULL / uninitialized reference.
1177
 *
1178
 * Return:  Non-negative on success/Negative on failure
1179
 *
1180
 *-------------------------------------------------------------------------
1181
 */
1182
static herr_t
1183
H5T__ref_dsetreg_disk_isnull(const H5VL_object_t *src_file, const void *src_buf, bool *isnull)
1184
0
{
1185
0
    H5F_t         *src_f;
1186
0
    const uint8_t *p = (const uint8_t *)src_buf;
1187
0
    haddr_t        addr;
1188
0
    herr_t         ret_value = SUCCEED;
1189
1190
0
    FUNC_ENTER_PACKAGE
1191
0
    H5T_REF_LOG_DEBUG("");
1192
1193
    /* Check parameters */
1194
0
    assert(src_file);
1195
0
    assert(src_buf);
1196
0
    assert(isnull);
1197
1198
#ifndef NDEBUG
1199
    {
1200
        bool is_native = false; /* Whether the src file is using the native VOL connector */
1201
1202
        /* Check if using native VOL connector */
1203
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1204
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't query if file uses native VOL connector");
1205
1206
        /* Must use native VOL connector for this operation */
1207
        assert(is_native);
1208
    }
1209
#endif /* NDEBUG */
1210
1211
    /* Retrieve file from VOL object */
1212
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1213
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
1214
1215
    /* Get the heap address */
1216
0
    H5F_addr_decode(src_f, &p, &addr);
1217
1218
    /* Check if heap address is 'nil' */
1219
0
    *isnull = (addr == 0) ? true : false;
1220
1221
0
done:
1222
0
    FUNC_LEAVE_NOAPI(ret_value)
1223
0
} /* end H5T__ref_dsetreg_disk_isnull() */
1224
1225
/*-------------------------------------------------------------------------
1226
 * Function:    H5T__ref_dsetreg_disk_getsize
1227
 *
1228
 * Purpose: Retrieves the length of a disk based reference.
1229
 *
1230
 * Return:  Non-negative value (cannot fail)
1231
 *
1232
 *-------------------------------------------------------------------------
1233
 */
1234
static size_t
1235
H5T__ref_dsetreg_disk_getsize(H5VL_object_t H5_ATTR_UNUSED *src_file, const void H5_ATTR_UNUSED *src_buf,
1236
                              size_t H5_ATTR_UNUSED src_size, H5VL_object_t H5_ATTR_UNUSED *dst_file,
1237
                              bool H5_ATTR_UNUSED *dst_copy)
1238
0
{
1239
0
    size_t ret_value = sizeof(struct H5Tref_dsetreg);
1240
1241
#ifndef NDEBUG
1242
    FUNC_ENTER_PACKAGE
1243
#else
1244
0
    FUNC_ENTER_PACKAGE_NOERR
1245
0
#endif
1246
0
    H5T_REF_LOG_DEBUG("");
1247
1248
0
    assert(src_buf);
1249
1250
#ifndef NDEBUG
1251
    {
1252
        H5F_t *src_f;
1253
        bool   is_native = false; /* Whether the src file is using the native VOL connector */
1254
1255
        /* Check if using native VOL connector */
1256
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1257
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't query if file uses native VOL connector");
1258
1259
        /* Must use native VOL connector for this operation */
1260
        assert(is_native);
1261
1262
        /* Retrieve file from VOL object */
1263
        if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1264
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object");
1265
1266
        assert(src_size == H5T_REF_DSETREG_DISK_SIZE(src_f));
1267
    }
1268
#endif /* NDEBUG */
1269
1270
#ifndef NDEBUG
1271
done:
1272
#endif
1273
0
    FUNC_LEAVE_NOAPI(ret_value)
1274
0
} /* end H5T__ref_dsetreg_disk_getsize() */
1275
1276
/*-------------------------------------------------------------------------
1277
 * Function:    H5T__ref_dsetreg_disk_read
1278
 *
1279
 * Purpose: Reads the disk based reference into a buffer
1280
 *
1281
 * Return:  Non-negative on success/Negative on failure
1282
 *
1283
 *-------------------------------------------------------------------------
1284
 */
1285
static herr_t
1286
H5T__ref_dsetreg_disk_read(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
1287
                           H5VL_object_t H5_ATTR_UNUSED *dst_file, void *dst_buf,
1288
                           size_t H5_ATTR_UNUSED dst_size)
1289
0
{
1290
0
    H5F_t                 *src_f;
1291
0
    struct H5Tref_dsetreg *dst_reg   = (struct H5Tref_dsetreg *)dst_buf;
1292
0
    herr_t                 ret_value = SUCCEED;
1293
1294
0
    FUNC_ENTER_PACKAGE
1295
0
    H5T_REF_LOG_DEBUG("");
1296
1297
0
    assert(src_file);
1298
0
    assert(src_buf);
1299
0
    assert(dst_buf);
1300
0
    assert(dst_size == sizeof(struct H5Tref_dsetreg));
1301
1302
#ifndef NDEBUG
1303
    {
1304
        bool is_native = false; /* Whether the src file is using the native VOL connector */
1305
1306
        /* Check if using native VOL connector */
1307
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1308
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't query if file uses native VOL connector");
1309
1310
        /* Must use native VOL connector for this operation */
1311
        assert(is_native);
1312
    }
1313
#endif /* NDEBUG */
1314
1315
    /* Retrieve file from VOL object */
1316
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1317
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
1318
1319
0
    assert(src_size == H5T_REF_DSETREG_DISK_SIZE(src_f));
1320
1321
    /* Retrieve object address and space */
1322
0
    if (H5R__decode_token_region_compat(src_f, (const unsigned char *)src_buf, &src_size, &dst_reg->token,
1323
0
                                        H5F_SIZEOF_ADDR(src_f), &dst_reg->space) < 0)
1324
0
        HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object address");
1325
1326
0
done:
1327
0
    FUNC_LEAVE_NOAPI(ret_value)
1328
0
} /* end H5T__ref_dsetreg_disk_read() */
1329
1330
/*-------------------------------------------------------------------------
1331
 * Function:    H5T__ref_reclaim
1332
 *
1333
 * Purpose: Internal routine to free reference datatypes
1334
 *
1335
 * Return:  Non-negative on success / Negative on failure
1336
 *
1337
 *-------------------------------------------------------------------------
1338
 */
1339
herr_t
1340
H5T__ref_reclaim(void *elem, const H5T_t *dt)
1341
0
{
1342
0
    herr_t ret_value = SUCCEED; /* Return value */
1343
1344
0
    FUNC_ENTER_PACKAGE
1345
0
    H5T_REF_LOG_DEBUG("");
1346
1347
    /* Sanity checks */
1348
0
    assert(elem);
1349
0
    assert(dt && (dt->shared->type == H5T_REFERENCE));
1350
1351
0
    if (dt->shared->u.atomic.u.r.opaque && H5R__destroy((H5R_ref_priv_t *)elem) < 0)
1352
0
        HGOTO_ERROR(H5E_REFERENCE, H5E_CANTFREE, FAIL, "cannot free reference");
1353
1354
0
done:
1355
0
    FUNC_LEAVE_NOAPI(ret_value)
1356
0
} /* end H5T__ref_reclaim() */