Coverage Report

Created: 2024-06-18 06:29

/src/hdf5/src/H5Ochunk.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
 *
15
 * Created:   H5Ochunk.c
16
 *
17
 * Purpose:   Object header chunk routines.
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5Omodule.h" /* This source code file is part of the H5O module */
27
28
/***********/
29
/* Headers */
30
/***********/
31
#include "H5private.h"   /* Generic Functions     */
32
#include "H5Eprivate.h"  /* Error handling        */
33
#include "H5FLprivate.h" /* Free Lists                               */
34
#include "H5Opkg.h"      /* Object headers      */
35
36
/****************/
37
/* Local Macros */
38
/****************/
39
40
/******************/
41
/* Local Typedefs */
42
/******************/
43
44
/********************/
45
/* Package Typedefs */
46
/********************/
47
48
/********************/
49
/* Local Prototypes */
50
/********************/
51
52
/*********************/
53
/* Package Variables */
54
/*********************/
55
56
/* Declare the free list for H5O_chunk_proxy_t's */
57
H5FL_DEFINE(H5O_chunk_proxy_t);
58
59
/*****************************/
60
/* Library Private Variables */
61
/*****************************/
62
63
/*******************/
64
/* Local Variables */
65
/*******************/
66
67
/*-------------------------------------------------------------------------
68
 * Function:    H5O__chunk_add
69
 *
70
 * Purpose:     Add new chunk for object header to metadata cache
71
 *
72
 * Return:      SUCCEED/FAIL
73
 *
74
 *-------------------------------------------------------------------------
75
 */
76
herr_t
77
H5O__chunk_add(H5F_t *f, H5O_t *oh, unsigned idx, unsigned cont_chunkno)
78
0
{
79
0
    H5O_chunk_proxy_t *chk_proxy = NULL; /* Proxy for chunk, to mark it dirty in the cache */
80
0
    H5O_chunk_proxy_t *cont_chk_proxy =
81
0
        NULL; /* Proxy for chunk containing continuation message that points to this chunk, if not chunk 0 */
82
0
    herr_t ret_value = SUCCEED; /* Return value */
83
84
0
    FUNC_ENTER_PACKAGE_TAG(oh->cache_info.addr)
85
86
    /* check args */
87
0
    assert(f);
88
0
    assert(oh);
89
0
    assert(idx < oh->nchunks);
90
0
    assert(idx > 0);
91
92
    /* Allocate space for the object header data structure */
93
0
    if (NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
94
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
95
96
    /* Increment reference count on object header */
97
0
    if (H5O__inc_rc(oh) < 0)
98
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "can't increment reference count on object header");
99
100
    /* Set the values in the chunk proxy */
101
0
    chk_proxy->f       = f;
102
0
    chk_proxy->oh      = oh;
103
0
    chk_proxy->chunkno = idx;
104
105
    /* Determine the parent of the chunk */
106
0
    if (cont_chunkno != 0) {
107
0
        if (NULL == (cont_chk_proxy = H5O__chunk_protect(f, oh, cont_chunkno)))
108
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk");
109
0
        chk_proxy->fd_parent = cont_chk_proxy;
110
0
    } /* end else */
111
112
    /* Insert the chunk proxy into the cache */
113
0
    if (H5AC_insert_entry(f, H5AC_OHDR_CHK, oh->chunk[idx].addr, chk_proxy, H5AC__NO_FLAGS_SET) < 0)
114
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header chunk");
115
116
0
    chk_proxy = NULL;
117
118
0
done:
119
    /* Cleanup on failure */
120
0
    if (ret_value < 0)
121
0
        if (chk_proxy && H5O__chunk_dest(chk_proxy) < 0)
122
0
            HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk");
123
124
    /* Release resources */
125
0
    if (cont_chk_proxy)
126
0
        if (H5O__chunk_unprotect(f, cont_chk_proxy, false) < 0)
127
0
            HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk");
128
129
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
130
0
} /* end H5O__chunk_add() */
131
132
/*-------------------------------------------------------------------------
133
 * Function:    H5O__chunk_protect
134
 *
135
 * Purpose:     Protect an object header chunk for modifications
136
 *
137
 * Return:      SUCCEED/FAIL
138
 *
139
 *-------------------------------------------------------------------------
140
 */
141
H5O_chunk_proxy_t *
142
H5O__chunk_protect(H5F_t *f, H5O_t *oh, unsigned idx)
143
0
{
144
0
    H5O_chunk_proxy_t *chk_proxy = NULL; /* Proxy for protected chunk */
145
0
    H5O_chunk_proxy_t *ret_value = NULL; /* Return value */
146
147
0
    FUNC_ENTER_PACKAGE_TAG(oh->cache_info.addr)
148
149
    /* check args */
150
0
    assert(f);
151
0
    assert(oh);
152
0
    assert(idx < oh->nchunks);
153
154
    /* Check for protecting first chunk */
155
0
    if (0 == idx) {
156
        /* Create new "fake" chunk proxy for first chunk */
157
        /* (since the first chunk is already handled by the H5O_t object) */
158
0
        if (NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
159
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed");
160
161
        /* Increment reference count on object header */
162
0
        if (H5O__inc_rc(oh) < 0)
163
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "can't increment reference count on object header");
164
165
        /* Set chunk proxy fields */
166
0
        chk_proxy->f       = f;
167
0
        chk_proxy->oh      = oh;
168
0
        chk_proxy->chunkno = idx;
169
0
    } /* end if */
170
0
    else {
171
0
        H5O_chk_cache_ud_t chk_udata; /* User data for loading chunk */
172
173
        /* Construct the user data for protecting chunk proxy */
174
        /* (and _not_ decoding it) */
175
0
        memset(&chk_udata, 0, sizeof(chk_udata));
176
0
        chk_udata.oh      = oh;
177
0
        chk_udata.chunkno = idx;
178
0
        chk_udata.size    = oh->chunk[idx].size;
179
180
        /* Get the chunk proxy */
181
0
        if (NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, H5AC_OHDR_CHK, oh->chunk[idx].addr,
182
0
                                                                   &chk_udata, H5AC__NO_FLAGS_SET)))
183
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk");
184
185
        /* Sanity check */
186
0
        assert(chk_proxy->oh == oh);
187
0
        assert(chk_proxy->chunkno == idx);
188
0
    } /* end else */
189
190
    /* Set return value */
191
0
    ret_value = chk_proxy;
192
193
0
done:
194
    /* Cleanup on error */
195
0
    if (!ret_value)
196
0
        if (0 == idx && chk_proxy && H5O__chunk_dest(chk_proxy) < 0)
197
0
            HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header chunk");
198
199
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
200
0
} /* end H5O__chunk_protect() */
201
202
/*-------------------------------------------------------------------------
203
 * Function:    H5O__chunk_unprotect
204
 *
205
 * Purpose:     Unprotect an object header chunk after modifications
206
 *
207
 * Return:      SUCCEED/FAIL
208
 *
209
 *-------------------------------------------------------------------------
210
 */
211
herr_t
212
H5O__chunk_unprotect(H5F_t *f, H5O_chunk_proxy_t *chk_proxy, bool dirtied)
213
0
{
214
0
    herr_t ret_value = SUCCEED; /* Return value */
215
216
0
    FUNC_ENTER_PACKAGE
217
218
    /* check args */
219
0
    assert(f);
220
0
    assert(chk_proxy);
221
222
    /* Check for releasing first chunk */
223
0
    if (0 == chk_proxy->chunkno) {
224
        /* Check for dirtying the first chunk */
225
0
        if (dirtied) {
226
            /* Mark object header as dirty in cache */
227
0
            if (H5AC_mark_entry_dirty(chk_proxy->oh) < 0)
228
0
                HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty");
229
0
        } /* end else/if */
230
231
        /* Decrement reference count of object header */
232
0
        if (H5O__dec_rc(chk_proxy->oh) < 0)
233
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "can't decrement reference count on object header");
234
235
        /* Free fake chunk proxy */
236
0
        chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
237
0
    } /* end if */
238
0
    else {
239
        /* Release the chunk proxy from the cache, possibly marking it dirty */
240
0
        if (H5AC_unprotect(f, H5AC_OHDR_CHK, chk_proxy->oh->chunk[chk_proxy->chunkno].addr, chk_proxy,
241
0
                           (dirtied ? H5AC__DIRTIED_FLAG : H5AC__NO_FLAGS_SET)) < 0)
242
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk");
243
0
    } /* end else */
244
245
0
done:
246
0
    FUNC_LEAVE_NOAPI(ret_value)
247
0
} /* end H5O__chunk_unprotect() */
248
249
/*-------------------------------------------------------------------------
250
 * Function:    H5O__chunk_resize
251
 *
252
 * Purpose:     Resize an object header chunk
253
 *
254
 * Return:      SUCCEED/FAIL
255
 *
256
 *-------------------------------------------------------------------------
257
 */
258
herr_t
259
H5O__chunk_resize(H5O_t *oh, H5O_chunk_proxy_t *chk_proxy)
260
0
{
261
0
    herr_t ret_value = SUCCEED; /* Return value */
262
263
0
    FUNC_ENTER_PACKAGE
264
265
    /* check args */
266
0
    assert(oh);
267
0
    assert(chk_proxy);
268
269
    /* Check for resizing first chunk */
270
0
    if (0 == chk_proxy->chunkno) {
271
        /* Resize object header in cache */
272
0
        if (H5AC_resize_entry(oh, oh->chunk[0].size) < 0)
273
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTRESIZE, FAIL, "unable to resize chunk in cache");
274
0
    } /* end if */
275
0
    else {
276
        /* Resize chunk in cache */
277
0
        if (H5AC_resize_entry(chk_proxy, oh->chunk[chk_proxy->chunkno].size) < 0)
278
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTRESIZE, FAIL, "unable to resize chunk in cache");
279
0
    } /* end else */
280
281
0
done:
282
0
    FUNC_LEAVE_NOAPI(ret_value)
283
0
} /* end H5O__chunk_resize() */
284
285
/*-------------------------------------------------------------------------
286
 * Function:    H5O__chunk_update_idx
287
 *
288
 * Purpose:     Update the chunk index for a chunk proxy
289
 *
290
 * Return:      SUCCEED/FAIL
291
 *
292
 *-------------------------------------------------------------------------
293
 */
294
herr_t
295
H5O__chunk_update_idx(H5F_t *f, H5O_t *oh, unsigned idx)
296
0
{
297
0
    H5O_chunk_proxy_t *chk_proxy = NULL;    /* Proxy for chunk, to mark it dirty in the cache */
298
0
    H5O_chk_cache_ud_t chk_udata;           /* User data for loading chunk */
299
0
    herr_t             ret_value = SUCCEED; /* Return value */
300
301
0
    FUNC_ENTER_PACKAGE_TAG(oh->cache_info.addr)
302
303
    /* check args */
304
0
    assert(f);
305
0
    assert(oh);
306
0
    assert(idx < oh->nchunks);
307
0
    assert(idx > 0);
308
309
    /* Construct the user data for protecting chunk proxy */
310
    /* (and _not_ decoding it) */
311
0
    memset(&chk_udata, 0, sizeof(chk_udata));
312
0
    chk_udata.oh      = oh;
313
0
    chk_udata.chunkno = idx;
314
0
    chk_udata.size    = oh->chunk[idx].size;
315
316
    /* Get the chunk proxy */
317
0
    if (NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, H5AC_OHDR_CHK, oh->chunk[idx].addr,
318
0
                                                               &chk_udata, H5AC__NO_FLAGS_SET)))
319
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk");
320
321
    /* Update index for chunk proxy in cache */
322
0
    chk_proxy->chunkno = idx;
323
324
    /* Release the chunk proxy from the cache, marking it deleted */
325
0
    if (H5AC_unprotect(f, H5AC_OHDR_CHK, oh->chunk[idx].addr, chk_proxy, H5AC__DIRTIED_FLAG) < 0)
326
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk");
327
328
0
done:
329
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
330
0
} /* end H5O__chunk_update_idx() */
331
332
/*-------------------------------------------------------------------------
333
 * Function:    H5O__chunk_delete
334
 *
335
 * Purpose:     Notify metadata cache that a chunk has been deleted
336
 *
337
 * Return:      SUCCEED/FAIL
338
 *
339
 *-------------------------------------------------------------------------
340
 */
341
herr_t
342
H5O__chunk_delete(H5F_t *f, H5O_t *oh, unsigned idx)
343
0
{
344
0
    H5O_chunk_proxy_t *chk_proxy   = NULL;               /* Proxy for chunk, to mark it dirty in the cache */
345
0
    unsigned           cache_flags = H5AC__DELETED_FLAG; /* Flags for unprotecting proxy */
346
0
    herr_t             ret_value   = SUCCEED;            /* Return value */
347
348
0
    FUNC_ENTER_PACKAGE_TAG(oh->cache_info.addr)
349
350
    /* check args */
351
0
    assert(f);
352
0
    assert(oh);
353
0
    assert(idx < oh->nchunks);
354
0
    assert(idx > 0);
355
356
    /* Get the chunk proxy */
357
0
    if (NULL == (chk_proxy = H5O__chunk_protect(f, oh, idx)))
358
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk");
359
360
    /* Only free file space if not doing SWMR writes */
361
0
    if (!oh->swmr_write)
362
0
        cache_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
363
364
0
done:
365
    /* Release the chunk proxy from the cache, marking it deleted */
366
0
    if (chk_proxy && H5AC_unprotect(f, H5AC_OHDR_CHK, oh->chunk[idx].addr, chk_proxy, cache_flags) < 0)
367
0
        HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk");
368
369
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
370
0
} /* end H5O__chunk_delete() */
371
372
/*-------------------------------------------------------------------------
373
 * Function:    H5O__chunk_dest
374
 *
375
 * Purpose:     Destroy a chunk proxy object
376
 *
377
 * Return:      SUCCEED/FAIL
378
 *
379
 *-------------------------------------------------------------------------
380
 */
381
herr_t
382
H5O__chunk_dest(H5O_chunk_proxy_t *chk_proxy)
383
10
{
384
10
    herr_t ret_value = SUCCEED; /* Return value */
385
386
10
    FUNC_ENTER_PACKAGE
387
388
    /* Check arguments */
389
10
    assert(chk_proxy);
390
391
    /* Decrement reference count of object header */
392
10
    if (H5O__dec_rc(chk_proxy->oh) < 0)
393
3
        HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "can't decrement reference count on object header");
394
395
10
done:
396
    /* Release the chunk proxy object */
397
10
    chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
398
399
10
    FUNC_LEAVE_NOAPI(ret_value)
400
10
} /* H5O__chunk_dest() */