Coverage Report

Created: 2026-02-23 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Oshared.c
Line
Count
Source
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the LICENSE file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/*
14
 * Purpose: Functions that operate on a shared message.  The shared
15
 *    message doesn't ever actually appear in the object header as
16
 *    a normal message.  Instead, if a message is shared, the
17
 *    H5O_FLAG_SHARED bit is set and the message body is that
18
 *    defined here for H5O_SHARED.  The message ID is the ID of the
19
 *    pointed-to message and the pointed-to message is stored in
20
 *    the global heap.
21
 */
22
23
/****************/
24
/* Module Setup */
25
/****************/
26
27
#include "H5Omodule.h" /* This source code file is part of the H5O module */
28
29
/***********/
30
/* Headers */
31
/***********/
32
#include "H5private.h"   /* Generic Functions     */
33
#include "H5Eprivate.h"  /* Error handling        */
34
#include "H5Fprivate.h"  /* File access       */
35
#include "H5HFprivate.h" /* Fractal heap        */
36
#include "H5MMprivate.h" /* Memory management     */
37
#include "H5Opkg.h"      /* Object headers      */
38
#include "H5SMprivate.h" /* Shared object header messages        */
39
#include "H5WBprivate.h" /* Wrapped Buffers                      */
40
41
/****************/
42
/* Local Macros */
43
/****************/
44
45
/* First version, with full symbol table entry as link for object header sharing */
46
0
#define H5O_SHARED_VERSION_1 1
47
48
/* Older version, with just address of object as link for object header sharing */
49
0
#define H5O_SHARED_VERSION_2 2
50
51
/* Newest version, which recognizes messages that are stored in the SOHM heap */
52
0
#define H5O_SHARED_VERSION_3      3
53
0
#define H5O_SHARED_VERSION_LATEST H5O_SHARED_VERSION_3
54
55
/* Size of stack buffer for serialized messages */
56
#define H5O_MESG_BUF_SIZE 128
57
58
/******************/
59
/* Local Typedefs */
60
/******************/
61
62
/********************/
63
/* Local Prototypes */
64
/********************/
65
static void  *H5O__shared_read(H5F_t *f, H5O_t *open_oh, unsigned *ioflags, const H5O_shared_t *shared,
66
                               const H5O_msg_class_t *type);
67
static herr_t H5O__shared_link_adj(H5F_t *f, H5O_t *open_oh, const H5O_msg_class_t *type,
68
                                   H5O_shared_t *shared, int adjust);
69
70
/*********************/
71
/* Package Variables */
72
/*********************/
73
74
/*****************************/
75
/* Library Private Variables */
76
/*****************************/
77
78
/*******************/
79
/* Local Variables */
80
/*******************/
81
82
/*-------------------------------------------------------------------------
83
 * Function:    H5O__shared_read
84
 *
85
 * Purpose:     Reads a message referred to by a shared message.
86
 *
87
 * Return:      Success:    Ptr to message in native format. The message
88
 *                          should be freed by calling H5O_msg_reset().
89
 *
90
 *              Failure:    NULL
91
 *
92
 *-------------------------------------------------------------------------
93
 */
94
static void *
95
H5O__shared_read(H5F_t *f, H5O_t *open_oh, unsigned *ioflags, const H5O_shared_t *shared,
96
                 const H5O_msg_class_t *type)
97
0
{
98
0
    H5HF_t *fheap = NULL;
99
0
    H5WB_t *wb    = NULL;                /* Wrapped buffer for attribute data */
100
0
    uint8_t mesg_buf[H5O_MESG_BUF_SIZE]; /* Buffer for deserializing messages */
101
0
    void   *ret_value = NULL;            /* Return value */
102
103
0
    FUNC_ENTER_PACKAGE
104
105
    /* check args */
106
0
    assert(f);
107
0
    assert(shared);
108
0
    assert(type);
109
0
    assert(type->share_flags & H5O_SHARE_IS_SHARABLE);
110
111
    /* This message could have a heap ID (SOHM) or the address of an object
112
     * header on disk (named datatype)
113
     */
114
0
    assert(H5O_IS_STORED_SHARED(shared->type));
115
116
    /* Check for implicit shared object header message */
117
0
    if (shared->type == H5O_SHARE_TYPE_SOHM) {
118
0
        haddr_t  fheap_addr; /* Address of SOHM heap */
119
0
        uint8_t *mesg_ptr;   /* Pointer to raw message in heap */
120
0
        size_t   mesg_size;  /* Size of message */
121
122
        /* Retrieve the fractal heap address for shared messages */
123
0
        if (H5SM_get_fheap_addr(f, type->id, &fheap_addr) < 0)
124
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "can't get fheap address for shared messages");
125
126
        /* Open the fractal heap */
127
0
        if (NULL == (fheap = H5HF_open(f, fheap_addr)))
128
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open fractal heap");
129
130
        /* Get the size of the message in the heap */
131
0
        if (H5HF_get_obj_len(fheap, &(shared->u.heap_id), &mesg_size) < 0)
132
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "can't get message size from fractal heap.");
133
134
        /* Wrap the local buffer for serialized message */
135
0
        if (NULL == (wb = H5WB_wrap(mesg_buf, sizeof(mesg_buf))))
136
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't wrap buffer");
137
138
        /* Get a pointer to a buffer that's large enough for message */
139
0
        if (NULL == (mesg_ptr = (uint8_t *)H5WB_actual(wb, mesg_size)))
140
0
            HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't get actual buffer");
141
142
        /* Retrieve the message from the heap */
143
0
        if (H5HF_read(fheap, &(shared->u.heap_id), mesg_ptr) < 0)
144
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "can't read message from fractal heap.");
145
146
        /* Decode the message */
147
0
        if (NULL == (ret_value = (type->decode)(f, open_oh, 0, ioflags, mesg_size, mesg_ptr)))
148
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode shared message.");
149
0
    } /* end if */
150
0
    else {
151
0
        H5O_loc_t oloc; /* Location for object header where message is stored */
152
153
0
        assert(shared->type == H5O_SHARE_TYPE_COMMITTED);
154
155
        /* Build the object location for the shared message's object header */
156
0
        oloc.file         = f;
157
0
        oloc.addr         = shared->u.loc.oh_addr;
158
0
        oloc.holding_file = false;
159
160
0
        if (open_oh && oloc.addr == H5O_OH_GET_ADDR(open_oh)) {
161
            /* The shared message is in the already opened object header.  This
162
             * is possible, for example, if an attribute's datatype is shared in
163
             * the same object header the attribute is in.  Read the message
164
             * directly. */
165
0
            if (NULL == (ret_value = H5O_msg_read_oh(f, open_oh, type->id, NULL)))
166
0
                HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read message");
167
0
        }
168
0
        else
169
            /* The shared message is in another object header */
170
0
            if (NULL == (ret_value = H5O_msg_read(&oloc, type->id, NULL)))
171
0
                HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read message");
172
0
    } /* end else */
173
174
    /* Mark the message as shared */
175
0
    if (H5O_msg_set_share(type->id, shared, ret_value) < 0)
176
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information");
177
178
0
done:
179
    /* Release resources */
180
0
    if (fheap && H5HF_close(fheap) < 0)
181
0
        HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "can't close fractal heap");
182
0
    if (wb && H5WB_unwrap(wb) < 0)
183
0
        HDONE_ERROR(H5E_OHDR, H5E_CLOSEERROR, NULL, "can't close wrapped buffer");
184
185
0
    FUNC_LEAVE_NOAPI(ret_value)
186
0
} /* end H5O__shared_read() */
187
188
/*-------------------------------------------------------------------------
189
 * Function:    H5O__shared_link_adj
190
 *
191
 * Purpose:     Changes the link count for the object referenced by a shared
192
 *              message.
193
 *
194
 *              This function changes the object header link count and is
195
 *              only relevant for committed messages.  Messages shared in
196
 *              the heap are re-shared each time they're written, so their
197
 *              reference count is stored in the file-wide shared message
198
 *              index and is changed in a different place in the code.
199
 *
200
 * Return:      SUCCEED/FAIL
201
 *
202
 *-------------------------------------------------------------------------
203
 */
204
static herr_t
205
H5O__shared_link_adj(H5F_t *f, H5O_t *open_oh, const H5O_msg_class_t *type, H5O_shared_t *shared, int adjust)
206
0
{
207
0
    herr_t ret_value = SUCCEED; /* Return value */
208
209
0
    FUNC_ENTER_PACKAGE
210
211
    /* check args */
212
0
    assert(f);
213
0
    assert(shared);
214
215
    /* Check for type of shared message */
216
0
    if (shared->type == H5O_SHARE_TYPE_COMMITTED) {
217
0
        H5O_loc_t oloc; /* Location for object header where message is stored */
218
219
        /*
220
         * The shared message is stored in some object header.
221
         * The other object header must be in the same file as the
222
         * new object header. Adjust the reference count on that
223
         * object header.
224
         */
225
        /* Unfortunately, it is possible for the shared->file pointer to become
226
         * invalid if the oh is kept in cache (which is contained in
227
         * shared->file->shared while shared->file is closed.  Just ignore
228
         * shared->file until the "top-level" file pointer is removed at some
229
         * point in the future.  -NAF */
230
        /* This is related to Jira issue #7638 and should be uncommented after
231
         * the library has been refactored to shift to using shared file
232
         * pointers for file operations, instead of using top file pointers.
233
         * -QAK */
234
        /*if(shared->file->shared != f->shared)
235
            HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "interfile hard links are not allowed")*/
236
237
        /* Build the object location for the shared message's object header */
238
0
        oloc.file         = f;
239
0
        oloc.addr         = shared->u.loc.oh_addr;
240
0
        oloc.holding_file = false;
241
242
0
        if (open_oh && oloc.addr == H5O_OH_GET_ADDR(open_oh)) {
243
            /* The shared message is in the already opened object header.  This
244
             * is possible, for example, if an attribute's datatype is shared in
245
             * the same object header the attribute is in.  Adjust the link
246
             * count directly. */
247
0
            bool deleted = false; /* This is used only to satisfy H5O__link_oh */
248
249
0
            if (H5O__link_oh(f, adjust, open_oh, &deleted) < 0)
250
0
                HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count");
251
252
0
            assert(!deleted);
253
0
        }
254
0
        else
255
            /* The shared message is in another object header */
256
0
            if (H5O_link(&oloc, adjust) < 0)
257
0
                HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count");
258
0
    } /* end if */
259
0
    else {
260
0
        assert(shared->type == H5O_SHARE_TYPE_SOHM || shared->type == H5O_SHARE_TYPE_HERE);
261
262
        /* Check for decrementing reference count on shared message */
263
0
        if (adjust < 0) {
264
0
            if (H5SM_delete(f, open_oh, shared) < 0)
265
0
                HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to delete message from SOHM table");
266
0
        } /* end if */
267
        /* Check for incrementing reference count on message */
268
0
        else if (adjust > 0) {
269
0
            if (H5SM_try_share(f, open_oh, 0, type->id, shared, NULL) < 0)
270
0
                HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "error trying to share message");
271
0
        } /* end if */
272
0
    }     /* end else */
273
274
0
done:
275
0
    FUNC_LEAVE_NOAPI(ret_value)
276
0
} /* end H5O__shared_link_adj() */
277
278
/*-------------------------------------------------------------------------
279
 * Function:    H5O__shared_decode
280
 *
281
 * Purpose:     Decodes a shared object message
282
 *
283
 * Return:      Success:    A buffer containing the decoded shared object
284
 *              Failure:    NULL
285
 *
286
 *-------------------------------------------------------------------------
287
 */
288
void *
289
H5O__shared_decode(H5F_t *f, H5O_t *open_oh, unsigned *ioflags, size_t buf_size, const uint8_t *buf,
290
                   const H5O_msg_class_t *type)
291
0
{
292
0
    const uint8_t *buf_end = buf + buf_size - 1; /* End of the buffer */
293
0
    H5O_shared_t   sh_mesg;                      /* Shared message info */
294
0
    unsigned       version;                      /* Shared message version */
295
0
    void          *ret_value = NULL;             /* Return value */
296
297
0
    FUNC_ENTER_PACKAGE
298
299
    /* Check args */
300
0
    assert(f);
301
0
    assert(buf);
302
0
    assert(type);
303
304
    /* Version */
305
0
    if (H5_IS_BUFFER_OVERFLOW(buf, 1, buf_end))
306
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
307
0
    version = *buf++;
308
0
    if (version < H5O_SHARED_VERSION_1 || version > H5O_SHARED_VERSION_LATEST)
309
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message");
310
311
    /* Get the shared information type
312
     * Flags are unused before version 3.
313
     */
314
0
    if (H5_IS_BUFFER_OVERFLOW(buf, 1, buf_end))
315
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
316
0
    if (version >= H5O_SHARED_VERSION_2)
317
0
        sh_mesg.type = *buf++;
318
0
    else {
319
0
        sh_mesg.type = H5O_SHARE_TYPE_COMMITTED;
320
0
        buf++;
321
0
    } /* end else */
322
323
    /* Skip reserved bytes (for version 1) */
324
0
    if (version == H5O_SHARED_VERSION_1) {
325
0
        if (H5_IS_BUFFER_OVERFLOW(buf, 6, buf_end))
326
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
327
0
        buf += 6;
328
0
    }
329
330
    /* Body */
331
0
    if (version == H5O_SHARED_VERSION_1) {
332
        /* Initialize other location fields */
333
0
        sh_mesg.u.loc.index = 0;
334
335
        /* Decode stored "symbol table entry" into message location */
336
0
        if (H5_IS_BUFFER_OVERFLOW(buf, H5F_SIZEOF_SIZE(f), buf_end))
337
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
338
0
        buf += H5F_SIZEOF_SIZE(f); /* Skip over local heap address */
339
0
        if (H5_IS_BUFFER_OVERFLOW(buf, H5F_sizeof_addr(f), buf_end))
340
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
341
0
        H5F_addr_decode(f, &buf, &(sh_mesg.u.loc.oh_addr));
342
0
    } /* end if */
343
0
    else if (version >= H5O_SHARED_VERSION_2) {
344
        /* If this message is in the heap, copy a heap ID.
345
         * Otherwise, it is a named datatype, so copy an H5O_loc_t.
346
         */
347
0
        if (sh_mesg.type == H5O_SHARE_TYPE_SOHM) {
348
0
            assert(version >= H5O_SHARED_VERSION_3);
349
0
            if (H5_IS_BUFFER_OVERFLOW(buf, sizeof(sh_mesg.u.heap_id), buf_end))
350
0
                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
351
0
            H5MM_memcpy(&sh_mesg.u.heap_id, buf, sizeof(sh_mesg.u.heap_id));
352
0
        } /* end if */
353
0
        else {
354
            /* The H5O_COMMITTED_FLAG should be set if this message
355
             * is from an older version before the flag existed.
356
             */
357
0
            if (version < H5O_SHARED_VERSION_3)
358
0
                sh_mesg.type = H5O_SHARE_TYPE_COMMITTED;
359
360
0
            sh_mesg.u.loc.index = 0;
361
0
            if (H5_IS_BUFFER_OVERFLOW(buf, H5F_sizeof_addr(f), buf_end))
362
0
                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
363
0
            H5F_addr_decode(f, &buf, &sh_mesg.u.loc.oh_addr);
364
0
        } /* end else */
365
0
    }     /* end else if */
366
367
    /* Set file pointer & message type for all types of shared messages */
368
0
    sh_mesg.file        = f;
369
0
    sh_mesg.msg_type_id = type->id;
370
371
    /* Retrieve actual message, through decoded shared message info */
372
0
    if (NULL == (ret_value = H5O__shared_read(f, open_oh, ioflags, &sh_mesg, type)))
373
0
        HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to retrieve native message");
374
375
0
done:
376
0
    FUNC_LEAVE_NOAPI(ret_value)
377
0
} /* end H5O__shared_decode() */
378
379
/*-------------------------------------------------------------------------
380
 * Function:    H5O__shared_encode
381
 *
382
 * Purpose:     Encodes message _MESG into buffer BUF.
383
 *
384
 * Return:      SUCCEED/FAIL
385
 *
386
 *-------------------------------------------------------------------------
387
 */
388
herr_t
389
H5O__shared_encode(const H5F_t *f, uint8_t *buf /*out*/, const H5O_shared_t *sh_mesg)
390
0
{
391
0
    unsigned version;
392
393
0
    FUNC_ENTER_PACKAGE_NOERR
394
395
    /* Check args */
396
0
    assert(f);
397
0
    assert(buf);
398
0
    assert(sh_mesg);
399
400
    /* If this message is shared in the heap, we need to use version 3 of the
401
     * encoding and encode the SHARED_IN_HEAP flag.
402
     */
403
0
    if (sh_mesg->type == H5O_SHARE_TYPE_SOHM)
404
0
        version = H5O_SHARED_VERSION_LATEST;
405
0
    else {
406
0
        assert(sh_mesg->type == H5O_SHARE_TYPE_COMMITTED);
407
0
        version = H5O_SHARED_VERSION_2; /* version 1 is no longer used */
408
0
    }                                   /* end else */
409
410
0
    *buf++ = (uint8_t)version;
411
0
    *buf++ = (uint8_t)sh_mesg->type;
412
413
    /* Encode either the heap ID of the message or the address of the
414
     * object header that holds it.
415
     */
416
0
    if (sh_mesg->type == H5O_SHARE_TYPE_SOHM)
417
0
        H5MM_memcpy(buf, &(sh_mesg->u.heap_id), sizeof(sh_mesg->u.heap_id));
418
0
    else
419
0
        H5F_addr_encode(f, &buf, sh_mesg->u.loc.oh_addr);
420
421
0
    FUNC_LEAVE_NOAPI(SUCCEED)
422
0
} /* end H5O__shared_encode() */
423
424
/*-------------------------------------------------------------------------
425
 * Function:    H5O_set_shared
426
 *
427
 * Purpose:     Sets the shared component for a message.
428
 *
429
 * Return:      SUCCEED/FAIL
430
 *
431
 *-------------------------------------------------------------------------
432
 */
433
herr_t
434
H5O_set_shared(H5O_shared_t *dst, const H5O_shared_t *src)
435
0
{
436
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
437
438
    /* check args */
439
0
    assert(dst);
440
0
    assert(src);
441
442
    /* copy */
443
0
    *dst = *src;
444
445
0
    FUNC_LEAVE_NOAPI(SUCCEED)
446
0
} /* end H5O_set_shared() */
447
448
/*-------------------------------------------------------------------------
449
 * Function:    H5O__shared_size
450
 *
451
 * Purpose:     Returns the length of a shared object message.
452
 *
453
 * Return:      Success:    Length
454
 *              Failure:    0
455
 *
456
 *-------------------------------------------------------------------------
457
 */
458
size_t
459
H5O__shared_size(const H5F_t *f, const H5O_shared_t *sh_mesg)
460
0
{
461
0
    size_t ret_value = 0; /* Return value */
462
463
0
    FUNC_ENTER_PACKAGE_NOERR
464
465
0
    if (sh_mesg->type == H5O_SHARE_TYPE_COMMITTED) {
466
0
        ret_value = (size_t)1 +                 /* Version                      */
467
0
                    (size_t)1 +                 /* Type field                   */
468
0
                    (size_t)H5F_SIZEOF_ADDR(f); /* Sharing by another obj hdr   */
469
0
    }                                           /* end if */
470
0
    else {
471
0
        assert(sh_mesg->type == H5O_SHARE_TYPE_SOHM);
472
0
        ret_value = 1 +               /* Version              */
473
0
                    1 +               /* Type field           */
474
0
                    H5O_FHEAP_ID_LEN; /* Shared in the heap   */
475
0
    }                                 /* end else */
476
477
0
    FUNC_LEAVE_NOAPI(ret_value)
478
0
} /* end H5O__shared_size() */
479
480
/*-------------------------------------------------------------------------
481
 * Function:    H5O__shared_delete
482
 *
483
 * Purpose:     Free file space referenced by message
484
 *
485
 * Return:      SUCCEED/FAIL
486
 *
487
 *-------------------------------------------------------------------------
488
 */
489
herr_t
490
H5O__shared_delete(H5F_t *f, H5O_t *open_oh, const H5O_msg_class_t *type, H5O_shared_t *sh_mesg)
491
0
{
492
0
    herr_t ret_value = SUCCEED; /* Return value */
493
494
0
    FUNC_ENTER_PACKAGE
495
496
    /* check args */
497
0
    assert(f);
498
0
    assert(sh_mesg);
499
500
    /*
501
     * Committed datatypes increment the OH of the original message when they
502
     * are written (in H5O_shared_link) and decrement it here.
503
     * SOHMs in the heap behave differently; their refcount is incremented
504
     * during H5SM_share when they are going to be written (in H5O_msg_append
505
     * or H5O_msg_write). Their refcount in the SOHM indexes still needs to
506
     * be decremented when they're deleted (in H5O__shared_link_adj).
507
     */
508
509
    /* Decrement the reference count on the shared object */
510
0
    if (H5O__shared_link_adj(f, open_oh, type, sh_mesg, -1) < 0)
511
0
        HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count");
512
513
0
done:
514
0
    FUNC_LEAVE_NOAPI(ret_value)
515
0
} /* end H5O__shared_delete() */
516
517
/*-------------------------------------------------------------------------
518
 * Function:    H5O__shared_link
519
 *
520
 * Purpose:     Increment reference count on any objects referenced by
521
 *              message
522
 *
523
 * Return:      SUCCEED/FAIL
524
 *
525
 *-------------------------------------------------------------------------
526
 */
527
herr_t
528
H5O__shared_link(H5F_t *f, H5O_t *open_oh, const H5O_msg_class_t *type, H5O_shared_t *sh_mesg)
529
0
{
530
0
    herr_t ret_value = SUCCEED; /* Return value */
531
532
0
    FUNC_ENTER_PACKAGE
533
534
    /* Check args */
535
0
    assert(f);
536
0
    assert(sh_mesg);
537
538
    /* Increment the reference count on the shared object */
539
0
    if (H5O__shared_link_adj(f, open_oh, type, sh_mesg, 1) < 0)
540
0
        HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count");
541
542
0
done:
543
0
    FUNC_LEAVE_NOAPI(ret_value)
544
0
} /* end H5O__shared_link() */
545
546
/*-------------------------------------------------------------------------
547
 * Function:    H5O__shared_copy_file
548
 *
549
 * Purpose:     Copies a message from _MESG to _DEST in file
550
 *
551
 * Return:      SUCCEED/FAIL
552
 *
553
 *-------------------------------------------------------------------------
554
 */
555
herr_t
556
H5O__shared_copy_file(H5F_t H5_ATTR_NDEBUG_UNUSED *file_src, H5F_t *file_dst,
557
                      const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst,
558
                      bool H5_ATTR_UNUSED *recompute_size, unsigned *mesg_flags,
559
                      H5O_copy_t H5_ATTR_NDEBUG_UNUSED *cpy_info, void H5_ATTR_UNUSED *udata)
560
0
{
561
0
    const H5O_shared_t *shared_src =
562
0
        (const H5O_shared_t *)_native_src; /* Alias to shared info in native source */
563
0
    H5O_shared_t *shared_dst =
564
0
        (H5O_shared_t *)_native_dst; /* Alias to shared info in native destination message */
565
0
    herr_t ret_value = SUCCEED;      /* Return value */
566
567
0
    FUNC_ENTER_PACKAGE
568
569
    /* check args */
570
0
    assert(file_src);
571
0
    assert(file_dst);
572
0
    assert(mesg_type);
573
0
    assert(shared_src);
574
0
    assert(shared_dst);
575
0
    assert(recompute_size);
576
0
    assert(cpy_info);
577
578
    /* Committed shared messages create a shared message at the destination
579
     * and also copy the committed object that they point to.
580
     *
581
     * Other messages simulate sharing the destination message to determine how
582
     * it will eventually be shared (if at all), but do not actually share the
583
     * message until "post copy".  The "H5O_shared_t" part of the message will
584
     * be updated (to allow calculation of the final size) but the message is
585
     * not actually shared.
586
     */
587
0
    if (shared_src->type != H5O_SHARE_TYPE_COMMITTED) {
588
        /* Simulate trying to share new message in the destination file. */
589
        /* Set copied metadata tag */
590
0
        H5_BEGIN_TAG(H5AC__COPIED_TAG)
591
592
0
        if (H5SM_try_share(file_dst, NULL, H5SM_DEFER, mesg_type->id, _native_dst, mesg_flags) < 0)
593
0
            HGOTO_ERROR_TAG(H5E_OHDR, H5E_WRITEERROR, FAIL,
594
0
                            "unable to determine if message should be shared");
595
596
        /* Reset metadata tag */
597
0
        H5_END_TAG
598
0
    } /* end if */
599
0
    else {
600
        /* Mark the message as committed - as it will be committed in post copy
601
         */
602
0
        H5O_UPDATE_SHARED(shared_dst, H5O_SHARE_TYPE_COMMITTED, file_dst, mesg_type->id, 0, HADDR_UNDEF)
603
0
        *mesg_flags |= H5O_MSG_FLAG_SHARED;
604
0
    } /* end else */
605
606
0
done:
607
0
    FUNC_LEAVE_NOAPI(ret_value)
608
0
} /* H5O__shared_copy_file() */
609
610
/*-------------------------------------------------------------------------
611
 * Function:    H5O__shared_post_copy_file
612
 *
613
 * Purpose:     Delete a shared message and replace with a new one.
614
 *              The function is needed at cases such as copying a shared reg_ref attribute.
615
 *              When a shared reg_ref attribute is copied from one file to
616
 *              another, the values in file need to be replaced. The only way
617
 *              to complish that is to delete the old message and write the
618
 *              new message with the correct values.
619
 *
620
 * Return:      SUCCEED/FAIL
621
 *
622
 *-------------------------------------------------------------------------
623
 */
624
herr_t
625
H5O__shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type, const H5O_shared_t *shared_src,
626
                           H5O_shared_t *shared_dst, unsigned *mesg_flags, H5O_copy_t *cpy_info)
627
0
{
628
0
    herr_t ret_value = SUCCEED; /* Return value */
629
630
0
    FUNC_ENTER_PACKAGE
631
632
    /* check args */
633
0
    assert(f);
634
0
    assert(shared_src);
635
0
    assert(shared_dst);
636
637
    /* Copy the target of committed messages, try to share others */
638
0
    if (shared_src->type == H5O_SHARE_TYPE_COMMITTED) {
639
0
        H5O_loc_t dst_oloc;
640
0
        H5O_loc_t src_oloc;
641
642
        /* Copy the shared object from source to destination */
643
0
        H5O_loc_reset(&dst_oloc);
644
0
        dst_oloc.file = f;
645
0
        src_oloc.file = shared_src->file;
646
0
        src_oloc.addr = shared_src->u.loc.oh_addr;
647
0
        if (H5O_copy_header_map(&src_oloc, &dst_oloc, cpy_info, false, NULL, NULL) < 0)
648
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object");
649
650
        /* Set up destination message's shared info */
651
0
        H5O_UPDATE_SHARED(shared_dst, H5O_SHARE_TYPE_COMMITTED, f, mesg_type->id, 0, dst_oloc.addr)
652
0
    } /* end if */
653
0
    else
654
        /* Share the message */
655
0
        if (H5SM_try_share(f, NULL, H5SM_WAS_DEFERRED, mesg_type->id, shared_dst, mesg_flags) < 0)
656
0
            HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't share message");
657
658
0
done:
659
0
    FUNC_LEAVE_NOAPI(ret_value)
660
0
} /* end H5O__shared_post_copy_file() */
661
662
/*-------------------------------------------------------------------------
663
 * Function:  H5O__shared_debug
664
 *
665
 * Purpose: Prints debugging info for the message
666
 *
667
 * Return:  Non-negative on success/Negative on failure
668
 *
669
 *-------------------------------------------------------------------------
670
 */
671
herr_t
672
H5O__shared_debug(const H5O_shared_t *mesg, FILE *stream, int indent, int fwidth)
673
0
{
674
0
    FUNC_ENTER_PACKAGE_NOERR
675
676
    /* Check args */
677
0
    assert(mesg);
678
0
    assert(stream);
679
0
    assert(indent >= 0);
680
0
    assert(fwidth >= 0);
681
682
0
    switch (mesg->type) {
683
0
        case H5O_SHARE_TYPE_UNSHARED:
684
0
            fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Shared Message type:", "Unshared");
685
0
            break;
686
687
0
        case H5O_SHARE_TYPE_COMMITTED:
688
0
            fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Shared Message type:", "Obj Hdr");
689
0
            fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth,
690
0
                    "Object address:", mesg->u.loc.oh_addr);
691
0
            break;
692
693
0
        case H5O_SHARE_TYPE_SOHM:
694
0
            fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Shared Message type:", "SOHM");
695
0
            fprintf(stream, "%*s%-*s %016llx\n", indent, "", fwidth,
696
0
                    "Heap ID:", (unsigned long long)mesg->u.heap_id.val);
697
0
            break;
698
699
0
        case H5O_SHARE_TYPE_HERE:
700
0
            fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Shared Message type:", "Here");
701
0
            break;
702
703
0
        default:
704
0
            fprintf(stream, "%*s%-*s %s (%u)\n", indent, "", fwidth, "Shared Message type:", "Unknown",
705
0
                    (unsigned)mesg->type);
706
0
    } /* end switch */
707
708
0
    FUNC_LEAVE_NOAPI(SUCCEED)
709
0
} /* end H5O__shared_debug() */