Coverage Report

Created: 2025-11-03 07:12

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
1
#define H5T_REF_MEM_SIZE         (H5R_REF_BUF_SIZE)
38
1
#define H5T_REF_OBJ_MEM_SIZE     (H5R_OBJ_REF_BUF_SIZE)
39
1
#define H5T_REF_DSETREG_MEM_SIZE (H5R_DSET_REG_REF_BUF_SIZE)
40
41
0
#define H5T_REF_OBJ_DISK_SIZE(f)     (H5F_SIZEOF_ADDR(f))
42
0
#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
3
    do {                                                                                                     \
57
3
    } 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
3
{
161
3
    htri_t ret_value = false; /* Indicate success, but no location change */
162
163
3
    FUNC_ENTER_PACKAGE
164
3
    H5T_REF_LOG_DEBUG("loc=%d", (int)loc);
165
166
3
    assert(dt);
167
    /* f is NULL when loc == H5T_LOC_MEMORY */
168
3
    assert(loc >= H5T_LOC_BADLOC && loc < H5T_LOC_MAXLOC);
169
170
    /* Only change the location if it's different */
171
3
    if (loc == dt->shared->u.atomic.u.r.loc && file == dt->shared->u.atomic.u.r.file)
172
0
        HGOTO_DONE(false);
173
174
3
    switch (loc) {
175
3
        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
3
            dt->shared->u.atomic.u.r.loc = H5T_LOC_MEMORY;
182
183
            /* Release owned file */
184
3
            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
3
            dt->shared->u.atomic.u.r.file = file; /* file is NULL */
192
193
3
            if (dt->shared->u.atomic.u.r.opaque) {
194
                /* Size in memory, disk size is different */
195
1
                dt->shared->size          = H5T_REF_MEM_SIZE;
196
1
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
197
198
                /* Set up the function pointers to access the reference in memory */
199
1
                dt->shared->u.atomic.u.r.cls = &H5T_ref_mem_g;
200
1
            } /* end if */
201
2
            else if (dt->shared->u.atomic.u.r.rtype == H5R_OBJECT1) {
202
                /* Size in memory, disk size is different */
203
1
                dt->shared->size          = H5T_REF_OBJ_MEM_SIZE;
204
1
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
205
206
                /* Unused for now */
207
1
                dt->shared->u.atomic.u.r.cls = NULL;
208
1
            } /* end else-if */
209
1
            else if (dt->shared->u.atomic.u.r.rtype == H5R_DATASET_REGION1) {
210
                /* Size in memory, disk size is different */
211
1
                dt->shared->size          = H5T_REF_DSETREG_MEM_SIZE;
212
1
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
213
214
                /* Unused for now */
215
1
                dt->shared->u.atomic.u.r.cls = NULL;
216
1
            } /* end else-if */
217
0
            else
218
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "invalid location");
219
3
            break;
220
221
3
        case H5T_LOC_DISK: /* Disk based reference datatype */
222
0
            assert(file);
223
224
            /* Mark this type as being stored on disk */
225
0
            dt->shared->u.atomic.u.r.loc = H5T_LOC_DISK;
226
227
            /* Set file pointer (since this reference is on disk) */
228
0
            dt->shared->u.atomic.u.r.file = file;
229
230
            /* dt now owns a reference to file */
231
0
            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
0
            if (dt->shared->u.atomic.u.r.rtype == H5R_OBJECT1) {
235
0
                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
0
                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
0
                dt->shared->size          = H5T_REF_OBJ_DISK_SIZE(f);
257
0
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
258
259
                /* Set up the function pointers to access the reference in memory */
260
0
                dt->shared->u.atomic.u.r.cls = &H5T_ref_obj_disk_g;
261
0
            } /* end if */
262
0
            else if (dt->shared->u.atomic.u.r.rtype == H5R_DATASET_REGION1) {
263
0
                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
0
                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
0
                dt->shared->size          = H5T_REF_DSETREG_DISK_SIZE(f);
285
0
                dt->shared->u.atomic.prec = 8 * dt->shared->size;
286
287
                /* Set up the function pointers to access the reference in memory */
288
0
                dt->shared->u.atomic.u.r.cls = &H5T_ref_dsetreg_disk_g;
289
0
            } /* 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
0
            break;
323
324
0
        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
3
    } /* end switch */
342
343
    /* Indicate that the location changed */
344
3
    ret_value = true;
345
346
3
done:
347
3
    FUNC_LEAVE_NOAPI(ret_value)
348
3
} /* 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 *dst_ref = (H5R_ref_priv_t *)dst_buf;
647
0
    H5R_ref_priv_t  tmp_ref; /* Temporary reference to decode into */
648
0
    herr_t          ret_value = SUCCEED;
649
650
0
    FUNC_ENTER_PACKAGE
651
0
    H5T_REF_LOG_DEBUG("");
652
653
    /* Sanity check */
654
0
    assert(src_buf);
655
0
    assert(src_size);
656
0
    assert(dst_buf);
657
0
    assert(dst_size == H5T_REF_MEM_SIZE);
658
0
    HDcompile_assert(sizeof(*dst_ref) == sizeof(tmp_ref));
659
660
    /* Memory-to-memory conversion to support vlen conversion */
661
0
    if (NULL == src_file) {
662
0
        H5MM_memcpy(dst_buf, src_buf, src_size);
663
0
        HGOTO_DONE(ret_value);
664
0
    }
665
666
#ifndef NDEBUG
667
    if ((src_type == H5R_OBJECT1) || (src_type == H5R_DATASET_REGION1)) {
668
        bool is_native = false; /* Whether the src file is using the native VOL connector */
669
670
        /* Check if using native VOL connector */
671
        if (H5VL_object_is_native(src_file, &is_native) < 0)
672
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't query if file uses native VOL connector");
673
674
        /* Must use native VOL connector for this operation */
675
        assert(is_native);
676
    }
677
#endif /* NDEBUG */
678
679
    /* Retrieve file from VOL object */
680
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
681
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
682
683
    /* Make sure reference buffer is correctly initialized */
684
0
    memset(&tmp_ref, 0, sizeof(tmp_ref));
685
686
0
    switch (src_type) {
687
0
        case H5R_OBJECT1: {
688
0
            size_t token_size = H5F_SIZEOF_ADDR(src_f);
689
690
0
            if (H5R__create_object((const H5O_token_t *)src_buf, token_size, &tmp_ref) < 0)
691
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create object reference");
692
0
        } break;
693
694
0
        case H5R_DATASET_REGION1: {
695
0
            const struct H5Tref_dsetreg *src_reg    = (const struct H5Tref_dsetreg *)src_buf;
696
0
            size_t                       token_size = H5F_SIZEOF_ADDR(src_f);
697
698
0
            if (H5R__create_region(&src_reg->token, token_size, src_reg->space, &tmp_ref) < 0)
699
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create region reference");
700
701
            /* create_region creates its internal copy of the space */
702
0
            if (H5S_close(src_reg->space) < 0)
703
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTFREE, FAIL, "Cannot close dataspace");
704
0
        } break;
705
706
0
        case H5R_DATASET_REGION2:
707
            /* Pass the correct encoding version for the selection depending on the
708
             * file libver bounds, this is later retrieved in H5S hyper decode */
709
0
            H5CX_set_libver_bounds(src_f);
710
            /* FALLTHROUGH */
711
0
            H5_ATTR_FALLTHROUGH
712
0
        case H5R_OBJECT2:
713
0
        case H5R_ATTR:
714
            /* Decode reference */
715
0
            if (H5R__decode((const unsigned char *)src_buf, &src_size, &tmp_ref) < 0)
716
0
                HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Cannot decode reference");
717
0
            break;
718
719
0
        case H5R_BADTYPE:
720
0
        case H5R_MAXTYPE:
721
0
        default:
722
0
            assert("unknown reference type" && 0);
723
0
            HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)");
724
0
    } /* end switch */
725
726
    /* If no filename set, this is not an external reference */
727
0
    if (NULL == H5R_REF_FILENAME(&tmp_ref)) {
728
        /* TODO temporary hack to retrieve file object */
729
0
        if ((file_id = H5F_get_file_id(src_file, H5I_FILE, false)) < 0)
730
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object");
731
732
        /* Attach loc ID to reference and hold reference to it, this is a
733
         * user exposed reference so set app_ref to true. */
734
0
        if (H5R__set_loc_id(&tmp_ref, file_id, true, true) < 0)
735
0
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "unable to attach location id to reference");
736
0
    } /* end if */
737
738
    /* Set output info */
739
0
    H5MM_memcpy(dst_ref, &tmp_ref, sizeof(tmp_ref));
740
741
0
done:
742
0
    if ((file_id != H5I_INVALID_HID) && (H5I_dec_ref(file_id) < 0))
743
0
        HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "unable to decrement refcount on location id");
744
0
    FUNC_LEAVE_NOAPI(ret_value)
745
0
} /* end H5T__ref_mem_write() */
746
747
/*-------------------------------------------------------------------------
748
 * Function:    H5T__ref_disk_isnull
749
 *
750
 * Purpose: Check if it's a NULL / uninitialized reference.
751
 *
752
 * Return:  Non-negative on success/Negative on failure
753
 *
754
 *-------------------------------------------------------------------------
755
 */
756
/*
757
 * It is the correct thing to do to have the reference buffer
758
 * be const-qualified here, but the VOL "blob specific" routine
759
 * needs a non-const pointer since an operation might modify
760
 * the "blob". Disable this warning here (at least temporarily)
761
 * for this reason.
762
 */
763
H5_WARN_CAST_AWAY_CONST_OFF
764
static herr_t
765
H5T__ref_disk_isnull(const H5VL_object_t *src_file, const void *src_buf, bool *isnull)
766
0
{
767
0
    const uint8_t *p = (const uint8_t *)src_buf;
768
0
    H5R_type_t     ref_type;
769
0
    herr_t         ret_value = SUCCEED;
770
771
0
    FUNC_ENTER_PACKAGE
772
0
    H5T_REF_LOG_DEBUG("");
773
774
    /* Check parameters */
775
0
    assert(src_file);
776
0
    assert(src_buf);
777
0
    assert(isnull);
778
779
    /* Try to check encoded reference type */
780
0
    ref_type = (H5R_type_t)*p++;
781
0
    if (ref_type) {
782
        /* This is a valid reference */
783
0
        *isnull = false;
784
0
    }
785
0
    else {
786
0
        H5VL_blob_specific_args_t vol_cb_args; /* Arguments to VOL callback */
787
788
        /* Skip the size / header */
789
0
        p = (const uint8_t *)src_buf + H5R_ENCODE_HEADER_SIZE + sizeof(uint32_t);
790
791
        /* Set up VOL callback arguments */
792
0
        vol_cb_args.op_type             = H5VL_BLOB_ISNULL;
793
0
        vol_cb_args.args.is_null.isnull = isnull;
794
795
        /* Check if blob ID is "nil" */
796
0
        if (H5VL_blob_specific(src_file, (void *)p, &vol_cb_args) < 0)
797
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to check if a blob ID is 'nil'");
798
0
    }
799
800
0
done:
801
0
    FUNC_LEAVE_NOAPI(ret_value)
802
0
} /* end H5T__ref_disk_isnull() */
803
H5_WARN_CAST_AWAY_CONST_ON
804
805
/*-------------------------------------------------------------------------
806
 * Function:    H5T__ref_disk_setnull
807
 *
808
 * Purpose: Set a reference as NULL / uninitialized.
809
 *
810
 * Return:  Non-negative on success/Negative on failure
811
 *
812
 *-------------------------------------------------------------------------
813
 */
814
static herr_t
815
H5T__ref_disk_setnull(H5VL_object_t *dst_file, void *dst_buf, void *bg_buf)
816
0
{
817
0
    H5VL_blob_specific_args_t vol_cb_args; /* Arguments to VOL callback */
818
0
    uint8_t                  *q         = (uint8_t *)dst_buf;
819
0
    uint8_t                  *p_bg      = (uint8_t *)bg_buf;
820
0
    herr_t                    ret_value = SUCCEED;
821
822
0
    FUNC_ENTER_PACKAGE
823
0
    H5T_REF_LOG_DEBUG("");
824
825
0
    assert(dst_file);
826
0
    assert(dst_buf);
827
828
    /* TODO Should get rid of bg stuff */
829
0
    if (p_bg) {
830
        /* Skip the size / header */
831
0
        p_bg += (sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE);
832
833
        /* Set up VOL callback arguments */
834
0
        vol_cb_args.op_type = H5VL_BLOB_DELETE;
835
836
        /* Remove blob for old data */
837
0
        if (H5VL_blob_specific(dst_file, (void *)p_bg, &vol_cb_args) < 0)
838
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to delete blob");
839
0
    } /* end if */
840
841
    /* Copy header manually so that it does not get encoded into the blob */
842
0
    memset(q, 0, H5R_ENCODE_HEADER_SIZE);
843
0
    q += H5R_ENCODE_HEADER_SIZE;
844
845
    /* Set the size */
846
0
    UINT32ENCODE(q, 0);
847
848
    /* Set up VOL callback arguments */
849
0
    vol_cb_args.op_type = H5VL_BLOB_SETNULL;
850
851
    /* Set blob ID to "nil" */
852
0
    if (H5VL_blob_specific(dst_file, q, &vol_cb_args) < 0)
853
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to set a blob ID to 'nil'");
854
855
0
done:
856
0
    FUNC_LEAVE_NOAPI(ret_value)
857
0
} /* end H5T__ref_disk_setnull() */
858
859
/*-------------------------------------------------------------------------
860
 * Function:  H5T__ref_disk_getsize
861
 *
862
 * Purpose: Retrieves the length of a disk based reference.
863
 *
864
 * Return:  Non-negative value (cannot fail)
865
 *
866
 *-------------------------------------------------------------------------
867
 */
868
static size_t
869
H5T__ref_disk_getsize(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf, size_t src_size,
870
                      H5VL_object_t H5_ATTR_UNUSED *dst_file, bool *dst_copy)
871
0
{
872
0
    const uint8_t *p = (const uint8_t *)src_buf;
873
0
    unsigned       flags;
874
0
    H5R_type_t     ref_type;
875
0
    size_t         ret_value = 0;
876
877
0
    FUNC_ENTER_PACKAGE
878
0
    H5T_REF_LOG_DEBUG("");
879
880
0
    assert(src_buf);
881
882
    /* Set reference type */
883
0
    ref_type = (H5R_type_t)*p++;
884
0
    if (ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE)
885
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid reference type");
886
887
    /* Set flags */
888
0
    flags = (unsigned)*p++;
889
890
0
    if (!(flags & H5R_IS_EXTERNAL) && (ref_type == H5R_OBJECT2)) {
891
        /* Can do a direct copy and skip blob decoding */
892
0
        *dst_copy = true;
893
894
0
        ret_value = src_size;
895
0
    } /* end if */
896
0
    else {
897
        /* Retrieve encoded data size */
898
0
        UINT32DECODE(p, ret_value);
899
900
        /* Add size of the header */
901
0
        ret_value += H5R_ENCODE_HEADER_SIZE;
902
0
    } /* end else */
903
904
0
done:
905
0
    FUNC_LEAVE_NOAPI(ret_value)
906
0
} /* end H5T__ref_disk_getsize() */
907
908
/*-------------------------------------------------------------------------
909
 * Function:  H5T__ref_disk_read
910
 *
911
 * Purpose: Reads the disk based reference into a buffer
912
 *
913
 * Return:  Non-negative on success/Negative on failure
914
 *
915
 *-------------------------------------------------------------------------
916
 */
917
static herr_t
918
H5T__ref_disk_read(H5VL_object_t *src_file, const void *src_buf, size_t H5_ATTR_NDEBUG_UNUSED src_size,
919
                   H5VL_object_t H5_ATTR_UNUSED *dst_file, void *dst_buf, size_t dst_size)
920
0
{
921
0
    const uint8_t *p         = (const uint8_t *)src_buf;
922
0
    uint8_t       *q         = (uint8_t *)dst_buf;
923
0
    size_t         blob_size = dst_size;
924
0
    herr_t         ret_value = SUCCEED;
925
926
0
    FUNC_ENTER_PACKAGE
927
0
    H5T_REF_LOG_DEBUG("");
928
929
0
    assert(src_file);
930
0
    assert(src_buf);
931
0
    assert(dst_buf);
932
0
    assert(dst_size);
933
934
    /* Copy header manually */
935
0
    H5MM_memcpy(q, p, H5R_ENCODE_HEADER_SIZE);
936
0
    p += H5R_ENCODE_HEADER_SIZE;
937
0
    q += H5R_ENCODE_HEADER_SIZE;
938
0
    blob_size -= H5R_ENCODE_HEADER_SIZE;
939
940
    /* Skip the size */
941
0
    p += sizeof(uint32_t);
942
0
    assert(src_size > (H5R_ENCODE_HEADER_SIZE + sizeof(uint32_t)));
943
944
    /* Retrieve blob */
945
0
    if (H5VL_blob_get(src_file, p, q, blob_size, NULL) < 0)
946
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get blob");
947
948
0
done:
949
0
    FUNC_LEAVE_NOAPI(ret_value)
950
0
} /* end H5T__ref_disk_read() */
951
952
/*-------------------------------------------------------------------------
953
 * Function:  H5T__ref_disk_write
954
 *
955
 * Purpose: Writes the disk based reference from a buffer
956
 *
957
 * Return:  Non-negative on success/Negative on failure
958
 *
959
 *-------------------------------------------------------------------------
960
 */
961
static herr_t
962
H5T__ref_disk_write(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf, size_t src_size,
963
                    H5R_type_t H5_ATTR_UNUSED src_type, H5VL_object_t *dst_file, void *dst_buf,
964
                    size_t H5_ATTR_NDEBUG_UNUSED dst_size, void *bg_buf)
965
0
{
966
0
    const uint8_t *p         = (const uint8_t *)src_buf;
967
0
    uint8_t       *q         = (uint8_t *)dst_buf;
968
0
    uint8_t       *p_bg      = (uint8_t *)bg_buf;
969
0
    herr_t         ret_value = SUCCEED;
970
971
0
    FUNC_ENTER_PACKAGE
972
0
    H5T_REF_LOG_DEBUG("");
973
974
0
    assert(src_buf);
975
0
    assert(src_size);
976
0
    assert(dst_file);
977
0
    assert(dst_buf);
978
979
    /* TODO Should get rid of bg stuff */
980
0
    if (p_bg) {
981
0
        H5VL_blob_specific_args_t vol_cb_args; /* Arguments to VOL callback */
982
983
        /* Skip the size / header */
984
0
        p_bg += (sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE);
985
986
#ifndef NDEBUG
987
        size_t p_buf_size_left = dst_size;
988
        assert(p_buf_size_left > (sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE));
989
#endif
990
991
        /* Set up VOL callback arguments */
992
0
        vol_cb_args.op_type = H5VL_BLOB_DELETE;
993
994
        /* Remove blob for old data */
995
0
        if (H5VL_blob_specific(dst_file, (void *)p_bg, &vol_cb_args) < 0)
996
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to delete blob");
997
0
    } /* end if */
998
999
    /* Copy header manually so that it does not get encoded into the blob */
1000
0
    H5MM_memcpy(q, p, H5R_ENCODE_HEADER_SIZE);
1001
0
    p += H5R_ENCODE_HEADER_SIZE;
1002
0
    q += H5R_ENCODE_HEADER_SIZE;
1003
0
    src_size -= H5R_ENCODE_HEADER_SIZE;
1004
1005
#ifndef NDEBUG
1006
    {
1007
        size_t buf_size_left = dst_size - sizeof(uint32_t);
1008
        assert(buf_size_left > sizeof(uint32_t));
1009
    }
1010
#endif
1011
1012
    /* Set the size */
1013
0
    UINT32ENCODE(q, src_size);
1014
1015
    /* Store blob */
1016
0
    if (H5VL_blob_put(dst_file, p, src_size, q, NULL) < 0)
1017
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to put blob");
1018
1019
0
done:
1020
0
    FUNC_LEAVE_NOAPI(ret_value)
1021
0
} /* end H5T__ref_disk_write() */
1022
1023
/*-------------------------------------------------------------------------
1024
 * Function:    H5T__ref_obj_disk_isnull
1025
 *
1026
 * Purpose: Check if it's a NULL / uninitialized reference.
1027
 *
1028
 * Return:  Non-negative on success/Negative on failure
1029
 *
1030
 *-------------------------------------------------------------------------
1031
 */
1032
static herr_t
1033
H5T__ref_obj_disk_isnull(const H5VL_object_t *src_file, const void *src_buf, bool *isnull)
1034
0
{
1035
0
    H5F_t         *src_f;
1036
0
    const uint8_t *p = (const uint8_t *)src_buf;
1037
0
    haddr_t        addr;
1038
0
    herr_t         ret_value = SUCCEED;
1039
1040
0
    FUNC_ENTER_PACKAGE
1041
0
    H5T_REF_LOG_DEBUG("");
1042
1043
    /* Check parameters */
1044
0
    assert(src_file);
1045
0
    assert(src_buf);
1046
0
    assert(isnull);
1047
1048
#ifndef NDEBUG
1049
    {
1050
        bool is_native = false; /* Whether the src file is using the native VOL connector */
1051
1052
        /* Check if using native VOL connector */
1053
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1054
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't query if file uses native VOL connector");
1055
1056
        /* Must use native VOL connector for this operation */
1057
        assert(is_native);
1058
    }
1059
#endif /* NDEBUG */
1060
1061
    /* Retrieve file from VOL object */
1062
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1063
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
1064
1065
    /* Get the object address */
1066
0
    H5F_addr_decode(src_f, &p, &addr);
1067
1068
    /* Check if heap address is 'nil' */
1069
0
    *isnull = (addr == 0) ? true : false;
1070
1071
0
done:
1072
0
    FUNC_LEAVE_NOAPI(ret_value)
1073
0
} /* end H5T__ref_obj_disk_isnull() */
1074
1075
/*-------------------------------------------------------------------------
1076
 * Function:    H5T__ref_obj_disk_getsize
1077
 *
1078
 * Purpose: Retrieves the length of a disk based reference.
1079
 *
1080
 * Return:  Non-negative value (cannot fail)
1081
 *
1082
 *-------------------------------------------------------------------------
1083
 */
1084
static size_t
1085
H5T__ref_obj_disk_getsize(H5VL_object_t *src_file, const void H5_ATTR_UNUSED *src_buf,
1086
                          size_t H5_ATTR_UNUSED src_size, H5VL_object_t H5_ATTR_UNUSED *dst_file,
1087
                          bool H5_ATTR_UNUSED *dst_copy)
1088
0
{
1089
0
    H5F_t *src_f;
1090
0
    size_t ret_value = 0;
1091
1092
0
    FUNC_ENTER_PACKAGE
1093
0
    H5T_REF_LOG_DEBUG("");
1094
1095
0
    assert(src_file);
1096
0
    assert(src_buf);
1097
1098
#ifndef NDEBUG
1099
    {
1100
        bool is_native = false; /* Whether the src file is using the native VOL connector */
1101
1102
        /* Check if using native VOL connector */
1103
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1104
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't query if file uses native VOL connector");
1105
1106
        /* Must use native VOL connector for this operation */
1107
        assert(is_native);
1108
    }
1109
#endif /* NDEBUG */
1110
1111
    /* Retrieve file from VOL object */
1112
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1113
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object");
1114
1115
0
    assert(src_size == H5T_REF_OBJ_DISK_SIZE(src_f));
1116
1117
0
    ret_value = H5T_REF_OBJ_DISK_SIZE(src_f);
1118
1119
0
done:
1120
0
    FUNC_LEAVE_NOAPI(ret_value)
1121
0
} /* end H5T__ref_obj_disk_getsize() */
1122
1123
/*-------------------------------------------------------------------------
1124
 * Function:    H5T__ref_obj_disk_read
1125
 *
1126
 * Purpose: Reads the disk based reference into a buffer
1127
 *
1128
 * Return:  Non-negative on success/Negative on failure
1129
 *
1130
 *-------------------------------------------------------------------------
1131
 */
1132
static herr_t
1133
H5T__ref_obj_disk_read(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
1134
                       H5VL_object_t H5_ATTR_UNUSED *dst_file, void *dst_buf, size_t H5_ATTR_UNUSED dst_size)
1135
0
{
1136
0
    H5F_t *src_f;
1137
0
    herr_t ret_value = SUCCEED;
1138
1139
0
    FUNC_ENTER_PACKAGE
1140
0
    H5T_REF_LOG_DEBUG("");
1141
1142
0
    assert(src_file);
1143
0
    assert(src_buf);
1144
0
    assert(dst_buf);
1145
1146
#ifndef NDEBUG
1147
    {
1148
        bool is_native = false; /* Whether the src file is using the native VOL connector */
1149
1150
        /* Check if using native VOL connector */
1151
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1152
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't query if file uses native VOL connector");
1153
1154
        /* Must use native VOL connector for this operation */
1155
        assert(is_native);
1156
    }
1157
#endif /* NDEBUG */
1158
1159
    /* Retrieve file from VOL object */
1160
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1161
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
1162
1163
0
    assert(src_size == H5T_REF_OBJ_DISK_SIZE(src_f));
1164
0
    assert(dst_size == H5F_SIZEOF_ADDR(src_f));
1165
1166
    /* Get object address */
1167
0
    if (H5R__decode_token_obj_compat((const unsigned char *)src_buf, &src_size, (H5O_token_t *)dst_buf,
1168
0
                                     H5F_SIZEOF_ADDR(src_f)) < 0)
1169
0
        HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object address");
1170
1171
0
done:
1172
0
    FUNC_LEAVE_NOAPI(ret_value)
1173
0
} /* end H5T__ref_obj_disk_read() */
1174
1175
/*-------------------------------------------------------------------------
1176
 * Function:    H5T__ref_dsetreg_disk_isnull
1177
 *
1178
 * Purpose: Check if it's a NULL / uninitialized reference.
1179
 *
1180
 * Return:  Non-negative on success/Negative on failure
1181
 *
1182
 *-------------------------------------------------------------------------
1183
 */
1184
static herr_t
1185
H5T__ref_dsetreg_disk_isnull(const H5VL_object_t *src_file, const void *src_buf, bool *isnull)
1186
0
{
1187
0
    H5F_t         *src_f;
1188
0
    const uint8_t *p = (const uint8_t *)src_buf;
1189
0
    haddr_t        addr;
1190
0
    herr_t         ret_value = SUCCEED;
1191
1192
0
    FUNC_ENTER_PACKAGE
1193
0
    H5T_REF_LOG_DEBUG("");
1194
1195
    /* Check parameters */
1196
0
    assert(src_file);
1197
0
    assert(src_buf);
1198
0
    assert(isnull);
1199
1200
#ifndef NDEBUG
1201
    {
1202
        bool is_native = false; /* Whether the src file is using the native VOL connector */
1203
1204
        /* Check if using native VOL connector */
1205
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1206
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't query if file uses native VOL connector");
1207
1208
        /* Must use native VOL connector for this operation */
1209
        assert(is_native);
1210
    }
1211
#endif /* NDEBUG */
1212
1213
    /* Retrieve file from VOL object */
1214
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1215
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
1216
1217
    /* Get the heap address */
1218
0
    H5F_addr_decode(src_f, &p, &addr);
1219
1220
    /* Check if heap address is 'nil' */
1221
0
    *isnull = (addr == 0) ? true : false;
1222
1223
0
done:
1224
0
    FUNC_LEAVE_NOAPI(ret_value)
1225
0
} /* end H5T__ref_dsetreg_disk_isnull() */
1226
1227
/*-------------------------------------------------------------------------
1228
 * Function:    H5T__ref_dsetreg_disk_getsize
1229
 *
1230
 * Purpose: Retrieves the length of a disk based reference.
1231
 *
1232
 * Return:  Non-negative value (cannot fail)
1233
 *
1234
 *-------------------------------------------------------------------------
1235
 */
1236
static size_t
1237
H5T__ref_dsetreg_disk_getsize(H5VL_object_t H5_ATTR_UNUSED *src_file, const void H5_ATTR_UNUSED *src_buf,
1238
                              size_t H5_ATTR_UNUSED src_size, H5VL_object_t H5_ATTR_UNUSED *dst_file,
1239
                              bool H5_ATTR_UNUSED *dst_copy)
1240
0
{
1241
0
    size_t ret_value = sizeof(struct H5Tref_dsetreg);
1242
1243
#ifndef NDEBUG
1244
    FUNC_ENTER_PACKAGE
1245
#else
1246
0
    FUNC_ENTER_PACKAGE_NOERR
1247
0
#endif
1248
0
    H5T_REF_LOG_DEBUG("");
1249
1250
0
    assert(src_buf);
1251
1252
#ifndef NDEBUG
1253
    {
1254
        H5F_t *src_f;
1255
        bool   is_native = false; /* Whether the src file is using the native VOL connector */
1256
1257
        /* Check if using native VOL connector */
1258
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1259
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't query if file uses native VOL connector");
1260
1261
        /* Must use native VOL connector for this operation */
1262
        assert(is_native);
1263
1264
        /* Retrieve file from VOL object */
1265
        if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1266
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object");
1267
1268
        assert(src_size == H5T_REF_DSETREG_DISK_SIZE(src_f));
1269
    }
1270
#endif /* NDEBUG */
1271
1272
#ifndef NDEBUG
1273
done:
1274
#endif
1275
0
    FUNC_LEAVE_NOAPI(ret_value)
1276
0
} /* end H5T__ref_dsetreg_disk_getsize() */
1277
1278
/*-------------------------------------------------------------------------
1279
 * Function:    H5T__ref_dsetreg_disk_read
1280
 *
1281
 * Purpose: Reads the disk based reference into a buffer
1282
 *
1283
 * Return:  Non-negative on success/Negative on failure
1284
 *
1285
 *-------------------------------------------------------------------------
1286
 */
1287
static herr_t
1288
H5T__ref_dsetreg_disk_read(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
1289
                           H5VL_object_t H5_ATTR_UNUSED *dst_file, void *dst_buf,
1290
                           size_t H5_ATTR_UNUSED dst_size)
1291
0
{
1292
0
    H5F_t                 *src_f;
1293
0
    struct H5Tref_dsetreg *dst_reg   = (struct H5Tref_dsetreg *)dst_buf;
1294
0
    herr_t                 ret_value = SUCCEED;
1295
1296
0
    FUNC_ENTER_PACKAGE
1297
0
    H5T_REF_LOG_DEBUG("");
1298
1299
0
    assert(src_file);
1300
0
    assert(src_buf);
1301
0
    assert(dst_buf);
1302
0
    assert(dst_size == sizeof(struct H5Tref_dsetreg));
1303
1304
#ifndef NDEBUG
1305
    {
1306
        bool is_native = false; /* Whether the src file is using the native VOL connector */
1307
1308
        /* Check if using native VOL connector */
1309
        if (H5VL_object_is_native(src_file, &is_native) < 0)
1310
            HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't query if file uses native VOL connector");
1311
1312
        /* Must use native VOL connector for this operation */
1313
        assert(is_native);
1314
    }
1315
#endif /* NDEBUG */
1316
1317
    /* Retrieve file from VOL object */
1318
0
    if (NULL == (src_f = (H5F_t *)H5VL_object_data(src_file)))
1319
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object");
1320
1321
0
    assert(src_size == H5T_REF_DSETREG_DISK_SIZE(src_f));
1322
1323
    /* Retrieve object address and space */
1324
0
    if (H5R__decode_token_region_compat(src_f, (const unsigned char *)src_buf, &src_size, &dst_reg->token,
1325
0
                                        H5F_SIZEOF_ADDR(src_f), &dst_reg->space) < 0)
1326
0
        HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object address");
1327
1328
0
done:
1329
0
    FUNC_LEAVE_NOAPI(ret_value)
1330
0
} /* end H5T__ref_dsetreg_disk_read() */
1331
1332
/*-------------------------------------------------------------------------
1333
 * Function:    H5T__ref_reclaim
1334
 *
1335
 * Purpose: Internal routine to free reference datatypes
1336
 *
1337
 * Return:  Non-negative on success / Negative on failure
1338
 *
1339
 *-------------------------------------------------------------------------
1340
 */
1341
herr_t
1342
H5T__ref_reclaim(void *elem, const H5T_t *dt)
1343
0
{
1344
0
    herr_t ret_value = SUCCEED; /* Return value */
1345
1346
0
    FUNC_ENTER_PACKAGE
1347
0
    H5T_REF_LOG_DEBUG("");
1348
1349
    /* Sanity checks */
1350
0
    assert(elem);
1351
0
    assert(dt && (dt->shared->type == H5T_REFERENCE));
1352
1353
0
    if (dt->shared->u.atomic.u.r.opaque && H5R__destroy((H5R_ref_priv_t *)elem) < 0)
1354
0
        HGOTO_ERROR(H5E_REFERENCE, H5E_CANTFREE, FAIL, "cannot free reference");
1355
1356
0
done:
1357
0
    FUNC_LEAVE_NOAPI(ret_value)
1358
0
} /* end H5T__ref_reclaim() */