Coverage Report

Created: 2024-06-18 06:29

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