Coverage Report

Created: 2025-11-09 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5FO.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
 * Open object info algorithms.
15
 *
16
 * These are used to track the objects currently open in a file, for various
17
 * internal mechanisms which need to be aware of such things.
18
 *
19
 */
20
21
#define H5F_FRIEND /*suppress error about including H5Fpkg    */
22
23
#include "H5private.h"   /* Generic Functions                     */
24
#include "H5Eprivate.h"  /* Error handling          */
25
#include "H5Fpkg.h"      /* File access                           */
26
#include "H5FLprivate.h" /* Free lists                            */
27
#include "H5FOprivate.h" /* File objects                          */
28
#include "H5Oprivate.h"  /* Object headers          */
29
#include "H5SLprivate.h" /* Skip Lists                            */
30
31
/* Private typedefs */
32
33
/* Information about open objects in a file */
34
typedef struct H5FO_open_obj_t {
35
    haddr_t addr;    /* Address of object header for object */
36
    void   *obj;     /* Pointer to the object            */
37
    bool    deleted; /* Flag to indicate that the object was deleted from the file */
38
} H5FO_open_obj_t;
39
40
/* Information about counted objects in a file */
41
typedef struct H5FO_obj_count_t {
42
    haddr_t addr;  /* Address of object header for object */
43
    hsize_t count; /* Number of times object is opened */
44
} H5FO_obj_count_t;
45
46
/* Declare a free list to manage the H5FO_open_obj_t struct */
47
H5FL_DEFINE_STATIC(H5FO_open_obj_t);
48
49
/* Declare a free list to manage the H5FO_obj_count_t struct */
50
H5FL_DEFINE_STATIC(H5FO_obj_count_t);
51
52
/*--------------------------------------------------------------------------
53
 NAME
54
    H5FO_create
55
 PURPOSE
56
    Create an open object info set
57
 USAGE
58
    herr_t H5FO_create(f)
59
        H5F_t *f;       IN/OUT: File to create opened object info set for
60
61
 RETURNS
62
    Returns non-negative on success, negative on failure
63
 DESCRIPTION
64
    Create a new open object info set.
65
 GLOBAL VARIABLES
66
 COMMENTS, BUGS, ASSUMPTIONS
67
 EXAMPLES
68
 REVISION LOG
69
--------------------------------------------------------------------------*/
70
herr_t
71
H5FO_create(const H5F_t *f)
72
10
{
73
10
    herr_t ret_value = SUCCEED; /* Return value */
74
75
10
    FUNC_ENTER_NOAPI(FAIL)
76
77
    /* Sanity check */
78
10
    assert(f);
79
10
    assert(f->shared);
80
81
    /* Create container used to store open object info */
82
10
    if ((f->shared->open_objs = H5SL_create(H5SL_TYPE_HADDR, NULL)) == NULL)
83
0
        HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create open object container");
84
85
10
done:
86
10
    FUNC_LEAVE_NOAPI(ret_value)
87
10
} /* end H5FO_create() */
88
89
/*--------------------------------------------------------------------------
90
 NAME
91
    H5FO_opened
92
 PURPOSE
93
    Checks if an object at an address is already open in the file.
94
 USAGE
95
    void * H5FO_opened(f,addr)
96
        const H5F_t *f;         IN: File to check opened object info set
97
        haddr_t addr;           IN: Address of object to check
98
99
 RETURNS
100
    Returns a pointer to the object on success, NULL on failure
101
 DESCRIPTION
102
    Check is an object at an address (the address of the object's object header)
103
    is already open in the file and return the ID for that object if it is open.
104
 GLOBAL VARIABLES
105
 COMMENTS, BUGS, ASSUMPTIONS
106
 EXAMPLES
107
 REVISION LOG
108
--------------------------------------------------------------------------*/
109
void *
110
H5FO_opened(const H5F_t *f, haddr_t addr)
111
0
{
112
0
    H5FO_open_obj_t *open_obj;  /* Information about open object */
113
0
    void            *ret_value; /* Return value */
114
115
0
    FUNC_ENTER_NOAPI_NOERR
116
117
    /* Sanity check */
118
0
    assert(f);
119
0
    assert(f->shared);
120
0
    assert(f->shared->open_objs);
121
0
    assert(H5_addr_defined(addr));
122
123
    /* Get the object node from the container */
124
0
    if (NULL != (open_obj = (H5FO_open_obj_t *)H5SL_search(f->shared->open_objs, &addr))) {
125
0
        ret_value = open_obj->obj;
126
0
        assert(ret_value != NULL);
127
0
    } /* end if */
128
0
    else
129
0
        ret_value = NULL;
130
131
0
    FUNC_LEAVE_NOAPI(ret_value)
132
0
} /* end H5FO_opened() */
133
134
/*--------------------------------------------------------------------------
135
 NAME
136
    H5FO_insert
137
 PURPOSE
138
    Insert a newly opened object/pointer pair into the opened object info set
139
 USAGE
140
    herr_t H5FO_insert(f,addr,obj,delete_flag)
141
        H5F_t *f;               IN/OUT: File's opened object info set
142
        haddr_t addr;           IN: Address of object to insert
143
        void *obj;              IN: Pointer to object to insert
144
        bool delete_flag;    IN: Whether to 'mark' this object for deletion
145
146
 RETURNS
147
    Returns a non-negative on success, negative on failure
148
 DESCRIPTION
149
    Insert an object/ID pair into the opened object info set.
150
 GLOBAL VARIABLES
151
 COMMENTS, BUGS, ASSUMPTIONS
152
 EXAMPLES
153
 REVISION LOG
154
--------------------------------------------------------------------------*/
155
herr_t
156
H5FO_insert(const H5F_t *f, haddr_t addr, void *obj, bool delete_flag)
157
0
{
158
0
    H5FO_open_obj_t *open_obj;            /* Information about open object */
159
0
    herr_t           ret_value = SUCCEED; /* Return value */
160
161
0
    FUNC_ENTER_NOAPI(FAIL)
162
163
    /* Sanity check */
164
0
    assert(f);
165
0
    assert(f->shared);
166
0
    assert(f->shared->open_objs);
167
0
    assert(H5_addr_defined(addr));
168
0
    assert(obj);
169
170
    /* Allocate new opened object information structure */
171
0
    if ((open_obj = H5FL_MALLOC(H5FO_open_obj_t)) == NULL)
172
0
        HGOTO_ERROR(H5E_CACHE, H5E_NOSPACE, FAIL, "memory allocation failed");
173
174
    /* Assign information */
175
0
    open_obj->addr    = addr;
176
0
    open_obj->obj     = obj;
177
0
    open_obj->deleted = delete_flag;
178
179
    /* Insert into container */
180
0
    if (H5SL_insert(f->shared->open_objs, &open_obj->addr, open_obj) < 0)
181
0
        HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, "can't insert object into container");
182
183
0
done:
184
0
    FUNC_LEAVE_NOAPI(ret_value)
185
0
} /* end H5FO_insert() */
186
187
/*--------------------------------------------------------------------------
188
 NAME
189
    H5FO_delete
190
 PURPOSE
191
    Remove an opened object/ID pair from the opened object info set
192
 USAGE
193
    herr_t H5FO_delete(f,addr)
194
        H5F_t *f;               IN/OUT: File's opened object info set
195
        haddr_t addr;           IN: Address of object to remove
196
197
 RETURNS
198
    Returns a non-negative on success, negative on failure
199
 DESCRIPTION
200
    Remove an object/ID pair from the opened object info.
201
 GLOBAL VARIABLES
202
 COMMENTS, BUGS, ASSUMPTIONS
203
 EXAMPLES
204
 REVISION LOG
205
--------------------------------------------------------------------------*/
206
herr_t
207
H5FO_delete(H5F_t *f, haddr_t addr)
208
0
{
209
0
    H5FO_open_obj_t *open_obj;            /* Information about open object */
210
0
    herr_t           ret_value = SUCCEED; /* Return value */
211
212
0
    FUNC_ENTER_NOAPI(FAIL)
213
214
    /* Sanity check */
215
0
    assert(f);
216
0
    assert(f->shared);
217
0
    assert(f->shared->open_objs);
218
0
    assert(H5_addr_defined(addr));
219
220
    /* Remove from container */
221
0
    if (NULL == (open_obj = (H5FO_open_obj_t *)H5SL_remove(f->shared->open_objs, &addr)))
222
0
        HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "can't remove object from container");
223
224
    /* Check if the object was deleted from the file */
225
0
    if (open_obj->deleted) {
226
0
        if (H5O_delete(f, addr) < 0)
227
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file");
228
0
    } /* end if */
229
230
    /* Release the object information */
231
0
    open_obj = H5FL_FREE(H5FO_open_obj_t, open_obj);
232
233
0
done:
234
0
    FUNC_LEAVE_NOAPI(ret_value)
235
0
} /* end H5FO_delete() */
236
237
/*--------------------------------------------------------------------------
238
 NAME
239
    H5FO_mark
240
 PURPOSE
241
    Mark an object to be deleted when it is closed
242
 USAGE
243
    herr_t H5FO_mark(f,addr,deleted)
244
        const H5F_t *f;         IN: File opened object is in
245
        haddr_t addr;           IN: Address of object to delete
246
        bool deleted;           IN: true for to be deleted
247
248
 RETURNS
249
    Returns a non-negative ID for the object on success, negative on failure
250
 DESCRIPTION
251
    Mark an opened object for deletion from the file when it is closed.
252
 GLOBAL VARIABLES
253
 COMMENTS, BUGS, ASSUMPTIONS
254
 EXAMPLES
255
 REVISION LOG
256
--------------------------------------------------------------------------*/
257
herr_t
258
H5FO_mark(const H5F_t *f, haddr_t addr, bool deleted)
259
0
{
260
0
    H5FO_open_obj_t *open_obj;            /* Information about open object */
261
0
    herr_t           ret_value = SUCCEED; /* Return value */
262
263
0
    FUNC_ENTER_NOAPI_NOERR
264
265
    /* Sanity check */
266
0
    assert(f);
267
0
    assert(f->shared);
268
0
    assert(f->shared->open_objs);
269
0
    assert(H5_addr_defined(addr));
270
271
    /* Get the object node from the container */
272
0
    if (NULL != (open_obj = (H5FO_open_obj_t *)H5SL_search(f->shared->open_objs, &addr)))
273
0
        open_obj->deleted = deleted;
274
0
    else
275
0
        ret_value = FAIL;
276
277
0
    FUNC_LEAVE_NOAPI(ret_value)
278
0
} /* end H5FO_mark() */
279
280
/*--------------------------------------------------------------------------
281
 NAME
282
    H5FO_marked
283
 PURPOSE
284
    Check if an object is marked to be deleted when it is closed
285
 USAGE
286
    bool H5FO_marked(f,addr)
287
        const H5F_t *f;         IN: File opened object is in
288
        haddr_t addr;           IN: Address of object to delete
289
290
 RETURNS
291
    Returns a true/false on success
292
 DESCRIPTION
293
    Checks if the object is currently in the "opened objects" tree and
294
    whether its marks for deletion from the file when it is closed.
295
 GLOBAL VARIABLES
296
 COMMENTS, BUGS, ASSUMPTIONS
297
 EXAMPLES
298
 REVISION LOG
299
--------------------------------------------------------------------------*/
300
bool
301
H5FO_marked(const H5F_t *f, haddr_t addr)
302
0
{
303
0
    H5FO_open_obj_t *open_obj;          /* Information about open object */
304
0
    bool             ret_value = false; /* Return value */
305
306
0
    FUNC_ENTER_NOAPI_NOERR
307
308
    /* Sanity check */
309
0
    assert(f);
310
0
    assert(f->shared);
311
0
    assert(f->shared->open_objs);
312
0
    assert(H5_addr_defined(addr));
313
314
    /* Get the object node from the container */
315
0
    if (NULL != (open_obj = (H5FO_open_obj_t *)H5SL_search(f->shared->open_objs, &addr)))
316
0
        ret_value = open_obj->deleted;
317
318
0
    FUNC_LEAVE_NOAPI(ret_value)
319
0
} /* end H5FO_marked() */
320
321
/*--------------------------------------------------------------------------
322
 NAME
323
    H5FO_dest
324
 PURPOSE
325
    Destroy an open object info set
326
 USAGE
327
    herr_t H5FO_dest(f)
328
        H5F_t *f;               IN/OUT: File's opened object info set
329
330
 RETURNS
331
    Returns a non-negative on success, negative on failure
332
 DESCRIPTION
333
    Destroy an existing open object info set.
334
 GLOBAL VARIABLES
335
 COMMENTS, BUGS, ASSUMPTIONS
336
 EXAMPLES
337
 REVISION LOG
338
--------------------------------------------------------------------------*/
339
herr_t
340
H5FO_dest(const H5F_t *f)
341
10
{
342
10
    herr_t ret_value = SUCCEED; /* Return value */
343
344
10
    FUNC_ENTER_NOAPI(FAIL)
345
346
    /* Sanity check */
347
10
    assert(f);
348
10
    assert(f->shared);
349
10
    assert(f->shared->open_objs);
350
351
    /* Check if the object info set is empty */
352
10
    if (H5SL_count(f->shared->open_objs) != 0)
353
0
        HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "objects still in open object info set");
354
355
    /* Release the open object info set container */
356
10
    if (H5SL_close(f->shared->open_objs) < 0)
357
0
        HGOTO_ERROR(H5E_CACHE, H5E_CANTCLOSEOBJ, FAIL, "can't close open object info set");
358
359
10
    f->shared->open_objs = NULL;
360
361
10
done:
362
10
    FUNC_LEAVE_NOAPI(ret_value)
363
10
} /* end H5FO_dest() */
364
365
/*--------------------------------------------------------------------------
366
 NAME
367
    H5FO_top_create
368
 PURPOSE
369
    Create the "top" open object count set
370
 USAGE
371
    herr_t H5FO_top_create(f)
372
        H5F_t *f;       IN/OUT: File to create opened object count set for
373
374
 RETURNS
375
    Returns non-negative on success, negative on failure
376
 DESCRIPTION
377
    Create a new open object count set.
378
 GLOBAL VARIABLES
379
 COMMENTS, BUGS, ASSUMPTIONS
380
 EXAMPLES
381
 REVISION LOG
382
--------------------------------------------------------------------------*/
383
herr_t
384
H5FO_top_create(H5F_t *f)
385
10
{
386
10
    herr_t ret_value = SUCCEED; /* Return value */
387
388
10
    FUNC_ENTER_NOAPI(FAIL)
389
390
    /* Sanity check */
391
10
    assert(f);
392
393
    /* Create container used to store open object info */
394
10
    if ((f->obj_count = H5SL_create(H5SL_TYPE_HADDR, NULL)) == NULL)
395
0
        HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create open object container");
396
397
10
done:
398
10
    FUNC_LEAVE_NOAPI(ret_value)
399
10
} /* end H5FO_top_create() */
400
401
/*--------------------------------------------------------------------------
402
 NAME
403
    H5FO_top_incr
404
 PURPOSE
405
    Increment the "top" reference count for an object in a file
406
 USAGE
407
    herr_t H5FO_top_incr(f, addr)
408
        H5F_t *f;               IN/OUT: File's opened object info set
409
        haddr_t addr;           IN: Address of object to increment
410
411
 RETURNS
412
    Returns a non-negative on success, negative on failure
413
 DESCRIPTION
414
    Increment the reference count for an object in the opened object count set.
415
 GLOBAL VARIABLES
416
 COMMENTS, BUGS, ASSUMPTIONS
417
 EXAMPLES
418
 REVISION LOG
419
--------------------------------------------------------------------------*/
420
herr_t
421
H5FO_top_incr(const H5F_t *f, haddr_t addr)
422
0
{
423
0
    H5FO_obj_count_t *obj_count;           /* Ref. count for object */
424
0
    herr_t            ret_value = SUCCEED; /* Return value */
425
426
0
    FUNC_ENTER_NOAPI(FAIL)
427
428
    /* Sanity check */
429
0
    assert(f);
430
0
    assert(f->obj_count);
431
0
    assert(H5_addr_defined(addr));
432
433
    /* Get the object node from the container */
434
0
    if (NULL != (obj_count = (H5FO_obj_count_t *)H5SL_search(f->obj_count, &addr))) {
435
0
        (obj_count->count)++;
436
0
    } /* end if */
437
0
    else {
438
        /* Allocate new opened object information structure */
439
0
        if (NULL == (obj_count = H5FL_MALLOC(H5FO_obj_count_t)))
440
0
            HGOTO_ERROR(H5E_CACHE, H5E_NOSPACE, FAIL, "memory allocation failed");
441
442
        /* Assign information */
443
0
        obj_count->addr  = addr;
444
0
        obj_count->count = 1;
445
446
        /* Insert into container */
447
0
        if (H5SL_insert(f->obj_count, &obj_count->addr, obj_count) < 0)
448
0
            HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, "can't insert object into container");
449
0
    } /* end if */
450
451
0
done:
452
0
    FUNC_LEAVE_NOAPI(ret_value)
453
0
} /* end H5FO_top_incr() */
454
455
/*--------------------------------------------------------------------------
456
 NAME
457
    H5FO_top_decr
458
 PURPOSE
459
    Decrement the "top" reference count for an object in a file
460
 USAGE
461
    herr_t H5FO_top_decr(f, addr)
462
        H5F_t *f;               IN/OUT: File's opened object info set
463
        haddr_t addr;           IN: Address of object to decrement
464
465
 RETURNS
466
    Returns a non-negative on success, negative on failure
467
 DESCRIPTION
468
    Decrement the reference count for an object in the opened object count set.
469
 GLOBAL VARIABLES
470
 COMMENTS, BUGS, ASSUMPTIONS
471
 EXAMPLES
472
 REVISION LOG
473
--------------------------------------------------------------------------*/
474
herr_t
475
H5FO_top_decr(const H5F_t *f, haddr_t addr)
476
0
{
477
0
    H5FO_obj_count_t *obj_count;           /* Ref. count for object */
478
0
    herr_t            ret_value = SUCCEED; /* Return value */
479
480
0
    FUNC_ENTER_NOAPI(FAIL)
481
482
    /* Sanity check */
483
0
    assert(f);
484
0
    assert(f->obj_count);
485
0
    assert(H5_addr_defined(addr));
486
487
    /* Get the object node from the container */
488
0
    if (NULL != (obj_count = (H5FO_obj_count_t *)H5SL_search(f->obj_count, &addr))) {
489
        /* Decrement the reference count for the object */
490
0
        (obj_count->count)--;
491
492
0
        if (obj_count->count == 0) {
493
            /* Remove from container */
494
0
            if (NULL == (obj_count = (H5FO_obj_count_t *)H5SL_remove(f->obj_count, &addr)))
495
0
                HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "can't remove object from container");
496
497
            /* Release the object information */
498
0
            obj_count = H5FL_FREE(H5FO_obj_count_t, obj_count);
499
0
        } /* end if */
500
0
    }     /* end if */
501
0
    else
502
0
        HGOTO_ERROR(H5E_CACHE, H5E_NOTFOUND, FAIL, "can't decrement ref. count");
503
504
0
done:
505
0
    FUNC_LEAVE_NOAPI(ret_value)
506
0
} /* end H5FO_top_decr() */
507
508
/*--------------------------------------------------------------------------
509
 NAME
510
    H5FO_top_count
511
 PURPOSE
512
    Return the "top" reference count for an object in a file
513
 USAGE
514
    hsize_t H5FO_top_count(f, addr)
515
        H5F_t *f;               IN/OUT: File's opened object info set
516
        haddr_t addr;           IN: Address of object to increment
517
518
 RETURNS
519
    Returns a non-negative on success, negative on failure
520
 DESCRIPTION
521
    Retrieves the reference count for an object in the opened object count set.
522
 GLOBAL VARIABLES
523
 COMMENTS, BUGS, ASSUMPTIONS
524
 EXAMPLES
525
 REVISION LOG
526
--------------------------------------------------------------------------*/
527
hsize_t
528
H5FO_top_count(const H5F_t *f, haddr_t addr)
529
0
{
530
0
    H5FO_obj_count_t *obj_count; /* Ref. count for object */
531
0
    hsize_t           ret_value; /* Return value */
532
533
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
534
535
    /* Sanity check */
536
0
    assert(f);
537
0
    assert(f->obj_count);
538
0
    assert(H5_addr_defined(addr));
539
540
    /* Get the object node from the container */
541
0
    if (NULL != (obj_count = (H5FO_obj_count_t *)H5SL_search(f->obj_count, &addr)))
542
0
        ret_value = obj_count->count;
543
0
    else
544
0
        ret_value = 0;
545
546
0
    FUNC_LEAVE_NOAPI(ret_value)
547
0
} /* end H5FO_top_count() */
548
549
/*--------------------------------------------------------------------------
550
 NAME
551
    H5FO_top_dest
552
 PURPOSE
553
    Destroy an open object info set
554
 USAGE
555
    herr_t H5FO_top_dest(f)
556
        H5F_t *f;               IN/OUT: File's opened object info set
557
558
 RETURNS
559
    Returns a non-negative on success, negative on failure
560
 DESCRIPTION
561
    Destroy an existing open object info set.
562
 GLOBAL VARIABLES
563
 COMMENTS, BUGS, ASSUMPTIONS
564
 EXAMPLES
565
 REVISION LOG
566
--------------------------------------------------------------------------*/
567
herr_t
568
H5FO_top_dest(H5F_t *f)
569
10
{
570
10
    herr_t ret_value = SUCCEED; /* Return value */
571
572
10
    FUNC_ENTER_NOAPI(FAIL)
573
574
    /* Sanity check */
575
10
    assert(f);
576
10
    assert(f->obj_count);
577
578
    /* Check if the object count set is empty */
579
10
    if (H5SL_count(f->obj_count) != 0)
580
0
        HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "objects still in open object info set");
581
582
    /* Release the open object count set container */
583
10
    if (H5SL_close(f->obj_count) < 0)
584
0
        HGOTO_ERROR(H5E_CACHE, H5E_CANTCLOSEOBJ, FAIL, "can't close open object info set");
585
586
10
    f->obj_count = NULL;
587
588
10
done:
589
10
    FUNC_LEAVE_NOAPI(ret_value)
590
10
} /* end H5FO_top_dest() */