Coverage Report

Created: 2024-06-18 06:29

/src/hdf5/src/H5HFhuge.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:   H5HFhuge.c
16
 *
17
 * Purpose:   Routines for "huge" objects in fractal heap
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5HFmodule.h" /* This source code file is part of the H5HF module */
27
28
/***********/
29
/* Headers */
30
/***********/
31
#include "H5private.h"   /* Generic Functions     */
32
#include "H5Eprivate.h"  /* Error handling        */
33
#include "H5HFpkg.h"     /* Fractal heaps     */
34
#include "H5MFprivate.h" /* File memory management    */
35
#include "H5MMprivate.h" /* Memory management     */
36
37
/****************/
38
/* Local Macros */
39
/****************/
40
41
/* v2 B-tree creation macros */
42
0
#define H5HF_HUGE_BT2_NODE_SIZE  512
43
0
#define H5HF_HUGE_BT2_SPLIT_PERC 100
44
0
#define H5HF_HUGE_BT2_MERGE_PERC 40
45
46
/******************/
47
/* Local Typedefs */
48
/******************/
49
50
/********************/
51
/* Package Typedefs */
52
/********************/
53
54
/********************/
55
/* Local Prototypes */
56
/********************/
57
58
/* Local v2 B-tree operations */
59
static herr_t H5HF__huge_bt2_create(H5HF_hdr_t *hdr);
60
61
/* Local 'huge' object support routines */
62
static hsize_t H5HF__huge_new_id(H5HF_hdr_t *hdr);
63
static herr_t  H5HF__huge_op_real(H5HF_hdr_t *hdr, const uint8_t *id, bool is_read, H5HF_operator_t op,
64
                                  void *op_data);
65
66
/*********************/
67
/* Package Variables */
68
/*********************/
69
70
/*****************************/
71
/* Library Private Variables */
72
/*****************************/
73
74
/*******************/
75
/* Local Variables */
76
/*******************/
77
78
/*-------------------------------------------------------------------------
79
 * Function:  H5HF__huge_bt2_create
80
 *
81
 * Purpose: Create the v2 B-tree for tracking the huge objects in the heap
82
 *
83
 * Return:  SUCCEED/FAIL
84
 *
85
 *-------------------------------------------------------------------------
86
 */
87
static herr_t
88
H5HF__huge_bt2_create(H5HF_hdr_t *hdr)
89
0
{
90
0
    H5B2_create_t bt2_cparam;          /* v2 B-tree creation parameters */
91
0
    herr_t        ret_value = SUCCEED; /* Return value */
92
93
0
    FUNC_ENTER_PACKAGE
94
95
    /*
96
     * Check arguments.
97
     */
98
0
    assert(hdr);
99
100
    /* Compute the size of 'raw' records on disk */
101
    /* (Note: the size for huge IDs could be set to 'huge_id_size', instead
102
     *  of 'sizeof_size', but that would make the v2 B-tree callback routines
103
     *  depend on the heap header, which makes the v2 B-tree flush routines
104
     *  difficult to write.  "Waste" an extra byte or for small heaps (where
105
     *  the 'huge_id_size' is < 'sizeof_size' in order to make this easier -QAK)
106
     */
107
0
    if (hdr->huge_ids_direct) {
108
0
        if (hdr->filter_len > 0) {
109
0
            bt2_cparam.rrec_size =
110
0
                (uint32_t)((unsigned)hdr->sizeof_addr     /* Address of object */
111
0
                           + (unsigned)hdr->sizeof_size   /* Length of object */
112
0
                           + (unsigned)4                  /* Filter mask for filtered object */
113
0
                           + (unsigned)hdr->sizeof_size); /* Size of de-filtered object in memory */
114
0
            bt2_cparam.cls = H5HF_HUGE_BT2_FILT_DIR;
115
0
        } /* end if */
116
0
        else {
117
0
            bt2_cparam.rrec_size = (uint32_t)((unsigned)hdr->sizeof_addr     /* Address of object */
118
0
                                              + (unsigned)hdr->sizeof_size); /* Length of object */
119
0
            bt2_cparam.cls       = H5HF_HUGE_BT2_DIR;
120
0
        } /* end else */
121
0
    }     /* end if */
122
0
    else {
123
0
        if (hdr->filter_len > 0) {
124
0
            bt2_cparam.rrec_size =
125
0
                (uint32_t)((unsigned)hdr->sizeof_addr     /* Address of filtered object */
126
0
                           + (unsigned)hdr->sizeof_size   /* Length of filtered object */
127
0
                           + (unsigned)4                  /* Filter mask for filtered object */
128
0
                           + (unsigned)hdr->sizeof_size   /* Size of de-filtered object in memory */
129
0
                           + (unsigned)hdr->sizeof_size); /* Unique ID for object */
130
0
            bt2_cparam.cls = H5HF_HUGE_BT2_FILT_INDIR;
131
0
        } /* end if */
132
0
        else {
133
0
            bt2_cparam.rrec_size = (uint32_t)((unsigned)hdr->sizeof_addr     /* Address of object */
134
0
                                              + (unsigned)hdr->sizeof_size   /* Length of object */
135
0
                                              + (unsigned)hdr->sizeof_size); /* Unique ID for object */
136
0
            bt2_cparam.cls       = H5HF_HUGE_BT2_INDIR;
137
0
        } /* end else */
138
0
    }     /* end else */
139
0
    bt2_cparam.node_size     = (size_t)H5HF_HUGE_BT2_NODE_SIZE;
140
0
    bt2_cparam.split_percent = H5HF_HUGE_BT2_SPLIT_PERC;
141
0
    bt2_cparam.merge_percent = H5HF_HUGE_BT2_MERGE_PERC;
142
143
    /* Create v2 B-tree for tracking 'huge' objects */
144
0
    if (NULL == (hdr->huge_bt2 = H5B2_create(hdr->f, &bt2_cparam, hdr->f)))
145
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL,
146
0
                    "can't create v2 B-tree for tracking 'huge' heap objects");
147
148
    /* Retrieve the v2 B-tree's address in the file */
149
0
    if (H5B2_get_addr(hdr->huge_bt2, &hdr->huge_bt2_addr) < 0)
150
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL,
151
0
                    "can't get v2 B-tree address for tracking 'huge' heap objects");
152
153
0
done:
154
0
    FUNC_LEAVE_NOAPI(ret_value)
155
0
} /* end H5HF__huge_bt2_create() */
156
157
/*-------------------------------------------------------------------------
158
 * Function:  H5HF__huge_init
159
 *
160
 * Purpose: Initialize information for tracking 'huge' objects
161
 *
162
 * Return:  SUCCEED/FAIL
163
 *
164
 *-------------------------------------------------------------------------
165
 */
166
herr_t
167
H5HF__huge_init(H5HF_hdr_t *hdr)
168
0
{
169
0
    FUNC_ENTER_PACKAGE_NOERR
170
171
    /*
172
     * Check arguments.
173
     */
174
0
    assert(hdr);
175
176
    /* Compute information about 'huge' objects for the heap */
177
178
    /* Check if we can completely hold the 'huge' object's offset & length in
179
     *  the file in the heap ID (which will speed up accessing it) and we don't
180
     *  have any I/O pipeline filters.
181
     */
182
0
    if (hdr->filter_len > 0) {
183
0
        if ((hdr->id_len - 1) >= (unsigned)(hdr->sizeof_addr + hdr->sizeof_size + 4 + hdr->sizeof_size)) {
184
            /* Indicate that v2 B-tree doesn't have to be used to locate object */
185
0
            hdr->huge_ids_direct = true;
186
187
            /* Set the size of 'huge' object IDs */
188
0
            hdr->huge_id_size = (uint8_t)(hdr->sizeof_addr + hdr->sizeof_size + hdr->sizeof_size);
189
0
        } /* end if */
190
0
        else
191
            /* Indicate that v2 B-tree must be used to access object */
192
0
            hdr->huge_ids_direct = false;
193
0
    } /* end if */
194
0
    else {
195
0
        if ((hdr->sizeof_addr + hdr->sizeof_size) <= (hdr->id_len - 1)) {
196
            /* Indicate that v2 B-tree doesn't have to be used to locate object */
197
0
            hdr->huge_ids_direct = true;
198
199
            /* Set the size of 'huge' object IDs */
200
0
            hdr->huge_id_size = (uint8_t)(hdr->sizeof_addr + hdr->sizeof_size);
201
0
        } /* end if */
202
0
        else
203
            /* Indicate that v2 B-tree must be used to locate object */
204
0
            hdr->huge_ids_direct = false;
205
0
    } /* end else */
206
0
    if (!hdr->huge_ids_direct) {
207
        /* Set the size and maximum value of 'huge' object ID */
208
0
        if ((hdr->id_len - 1) < sizeof(hsize_t)) {
209
0
            hdr->huge_id_size = (uint8_t)(hdr->id_len - 1);
210
0
            hdr->huge_max_id  = ((hsize_t)1 << (hdr->huge_id_size * 8)) - 1;
211
0
        } /*end if */
212
0
        else {
213
0
            hdr->huge_id_size = sizeof(hsize_t);
214
0
            hdr->huge_max_id  = HSIZET_MAX;
215
0
        } /* end else */
216
0
    }     /* end if */
217
0
    hdr->huge_bt2 = NULL;
218
219
0
    FUNC_LEAVE_NOAPI(SUCCEED)
220
0
} /* end H5HF__huge_init() */
221
222
/*-------------------------------------------------------------------------
223
 * Function:  H5HF__huge_new_id
224
 *
225
 * Purpose: Determine a new ID for an indirectly accessed 'huge' object
226
 *              (either filtered or not)
227
 *
228
 * Return:  SUCCEED/FAIL
229
 *
230
 *-------------------------------------------------------------------------
231
 */
232
static hsize_t
233
H5HF__huge_new_id(H5HF_hdr_t *hdr)
234
0
{
235
0
    hsize_t new_id;        /* New object's ID */
236
0
    hsize_t ret_value = 0; /* Return value */
237
238
0
    FUNC_ENTER_PACKAGE
239
240
    /*
241
     * Check arguments.
242
     */
243
0
    assert(hdr);
244
245
    /* Check for wrapping around 'huge' object ID space */
246
0
    if (hdr->huge_ids_wrapped)
247
        /* Fail for now - eventually should iterate through v2 B-tree, looking for available ID */
248
0
        HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, 0, "wrapping 'huge' object IDs not supported yet");
249
0
    else {
250
        /* Get new 'huge' object ID to use for object */
251
        /* (avoids using ID 0) */
252
0
        new_id = ++hdr->huge_next_id;
253
254
        /* Check for wrapping 'huge' object IDs around */
255
0
        if (hdr->huge_next_id == hdr->huge_max_id)
256
0
            hdr->huge_ids_wrapped = true;
257
0
    } /* end else */
258
259
    /* Set return value */
260
0
    ret_value = new_id;
261
262
0
done:
263
0
    FUNC_LEAVE_NOAPI(ret_value)
264
0
} /* end H5HF__huge_new_id() */
265
266
/*-------------------------------------------------------------------------
267
 * Function:  H5HF__huge_insert
268
 *
269
 * Purpose: Insert a 'huge' object into the file and track it
270
 *
271
 * Return:  SUCCEED/FAIL
272
 *
273
 *-------------------------------------------------------------------------
274
 */
275
herr_t
276
H5HF__huge_insert(H5HF_hdr_t *hdr, size_t obj_size, void *obj, void *_id)
277
0
{
278
0
    uint8_t *id = (uint8_t *)_id;   /* Pointer to ID buffer */
279
0
    haddr_t  obj_addr;              /* Address of object in the file */
280
0
    void    *write_buf;             /* Pointer to buffer to write */
281
0
    size_t   write_size;            /* Size of [possibly filtered] object written to file */
282
0
    unsigned filter_mask = 0;       /* Filter mask for object (only used for filtered objects) */
283
0
    herr_t   ret_value   = SUCCEED; /* Return value */
284
285
0
    FUNC_ENTER_PACKAGE
286
287
    /*
288
     * Check arguments.
289
     */
290
0
    assert(hdr);
291
0
    assert(obj_size > hdr->max_man_size);
292
0
    assert(obj);
293
0
    assert(id);
294
295
    /* Check if the v2 B-tree for tracking 'huge' heap objects has been created yet */
296
0
    if (!H5_addr_defined(hdr->huge_bt2_addr)) {
297
        /* Go create (& open) v2 B-tree */
298
0
        if (H5HF__huge_bt2_create(hdr) < 0)
299
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL,
300
0
                        "can't create v2 B-tree for tracking 'huge' heap objects");
301
0
    } /* end if */
302
0
    else {
303
        /* Check if v2 B-tree is open yet */
304
0
        if (NULL == hdr->huge_bt2) {
305
            /* Open existing v2 B-tree */
306
0
            if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f)))
307
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL,
308
0
                            "unable to open v2 B-tree for tracking 'huge' heap objects");
309
0
        } /* end if */
310
0
    }     /* end else */
311
0
    assert(hdr->huge_bt2);
312
313
    /* Check for I/O pipeline filter on heap */
314
0
    if (hdr->filter_len > 0) {
315
0
        H5Z_cb_t filter_cb; /* Filter callback structure */
316
0
        size_t   nbytes;    /* Number of bytes used */
317
318
        /* Initialize the filter callback struct */
319
0
        filter_cb.op_data = NULL;
320
0
        filter_cb.func    = NULL; /* no callback function when failed */
321
322
        /* Allocate buffer to perform I/O filtering on */
323
0
        write_size = obj_size;
324
0
        if (NULL == (write_buf = H5MM_malloc(write_size)))
325
0
            HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer");
326
0
        H5MM_memcpy(write_buf, obj, write_size);
327
328
        /* Push direct block data through I/O filter pipeline */
329
0
        nbytes = write_size;
330
0
        if (H5Z_pipeline(&(hdr->pline), 0, &filter_mask, H5Z_NO_EDC, filter_cb, &nbytes, &write_size,
331
0
                         &write_buf) < 0)
332
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, FAIL, "output pipeline failed");
333
334
        /* Update size of object on disk */
335
0
        write_size = nbytes;
336
0
    } /* end if */
337
0
    else {
338
0
        write_buf  = obj;
339
0
        write_size = obj_size;
340
0
    } /* end else */
341
342
    /* Allocate space in the file for storing the 'huge' object */
343
0
    if (HADDR_UNDEF == (obj_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, (hsize_t)write_size)))
344
0
        HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap huge object");
345
346
    /* Write the object's data to disk */
347
0
    if (H5F_block_write(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, write_size, write_buf) < 0)
348
0
        HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "writing 'huge' object to file failed");
349
350
    /* Release buffer for writing, if we had one */
351
0
    if (write_buf != obj) {
352
0
        assert(hdr->filter_len > 0);
353
0
        H5MM_xfree(write_buf);
354
0
    } /* end if */
355
356
    /* Perform different actions for directly & indirectly accessed 'huge' objects */
357
0
    if (hdr->huge_ids_direct) {
358
0
        if (hdr->filter_len > 0) {
359
0
            H5HF_huge_bt2_filt_dir_rec_t obj_rec; /* Record for tracking object */
360
361
            /* Initialize record for tracking object in v2 B-tree */
362
0
            obj_rec.addr        = obj_addr;
363
0
            obj_rec.len         = write_size;
364
0
            obj_rec.filter_mask = filter_mask;
365
0
            obj_rec.obj_size    = obj_size;
366
367
            /* Insert record for object in v2 B-tree */
368
0
            if (H5B2_insert(hdr->huge_bt2, &obj_rec) < 0)
369
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL,
370
0
                            "couldn't insert object tracking record in v2 B-tree");
371
372
            /* Encode ID for user */
373
0
            *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE;
374
0
            H5F_addr_encode(hdr->f, &id, obj_addr);
375
0
            H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)write_size);
376
0
            UINT32ENCODE(id, filter_mask);
377
0
            H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)obj_size);
378
0
        } /* end if */
379
0
        else {
380
0
            H5HF_huge_bt2_dir_rec_t obj_rec; /* Record for tracking object */
381
382
            /* Initialize record for tracking object in v2 B-tree */
383
0
            obj_rec.addr = obj_addr;
384
0
            obj_rec.len  = write_size;
385
386
            /* Insert record for object in v2 B-tree */
387
0
            if (H5B2_insert(hdr->huge_bt2, &obj_rec) < 0)
388
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL,
389
0
                            "couldn't insert object tracking record in v2 B-tree");
390
391
            /* Encode ID for user */
392
0
            *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE;
393
0
            H5F_addr_encode(hdr->f, &id, obj_addr);
394
0
            H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)write_size);
395
0
        } /* end if */
396
0
    }     /* end if */
397
0
    else {
398
0
        H5HF_huge_bt2_filt_indir_rec_t filt_indir_rec; /* Record for tracking filtered object */
399
0
        H5HF_huge_bt2_indir_rec_t      indir_rec;      /* Record for tracking non-filtered object */
400
0
        void                          *ins_rec;        /* Pointer to record to insert */
401
0
        hsize_t                        new_id;         /* New ID for object */
402
403
        /* Get new ID for object */
404
0
        if (0 == (new_id = H5HF__huge_new_id(hdr)))
405
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't generate new ID for object");
406
407
0
        if (hdr->filter_len > 0) {
408
            /* Initialize record for object in v2 B-tree */
409
0
            filt_indir_rec.addr        = obj_addr;
410
0
            filt_indir_rec.len         = write_size;
411
0
            filt_indir_rec.filter_mask = filter_mask;
412
0
            filt_indir_rec.obj_size    = obj_size;
413
0
            filt_indir_rec.id          = new_id;
414
415
            /* Set pointer to record to insert */
416
0
            ins_rec = &filt_indir_rec;
417
0
        } /* end if */
418
0
        else {
419
            /* Initialize record for object in v2 B-tree */
420
0
            indir_rec.addr = obj_addr;
421
0
            indir_rec.len  = write_size;
422
0
            indir_rec.id   = new_id;
423
424
            /* Set pointer to record to insert */
425
0
            ins_rec = &indir_rec;
426
0
        } /* end else */
427
428
        /* Insert record for tracking object in v2 B-tree */
429
0
        if (H5B2_insert(hdr->huge_bt2, ins_rec) < 0)
430
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL,
431
0
                        "couldn't insert object tracking record in v2 B-tree");
432
433
        /* Encode ID for user */
434
0
        *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE;
435
0
        UINT64ENCODE_VAR(id, new_id, hdr->huge_id_size);
436
0
    } /* end else */
437
438
    /* Update statistics about heap */
439
0
    hdr->huge_size += obj_size;
440
0
    hdr->huge_nobjs++;
441
442
    /* Mark heap header as modified */
443
0
    if (H5HF__hdr_dirty(hdr) < 0)
444
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty");
445
446
0
done:
447
0
    FUNC_LEAVE_NOAPI(ret_value)
448
0
} /* end H5HF__huge_insert() */
449
450
/*-------------------------------------------------------------------------
451
 * Function:  H5HF__huge_get_obj_len
452
 *
453
 * Purpose: Get the size of a 'huge' object in a fractal heap
454
 *
455
 * Return:  SUCCEED/FAIL
456
 *
457
 *-------------------------------------------------------------------------
458
 */
459
herr_t
460
H5HF__huge_get_obj_len(H5HF_hdr_t *hdr, const uint8_t *id, size_t *obj_len_p)
461
0
{
462
0
    herr_t ret_value = SUCCEED; /* Return value */
463
464
0
    FUNC_ENTER_PACKAGE
465
466
    /*
467
     * Check arguments.
468
     */
469
0
    assert(hdr);
470
0
    assert(H5_addr_defined(hdr->huge_bt2_addr));
471
0
    assert(id);
472
0
    assert(obj_len_p);
473
474
    /* Skip over the flag byte */
475
0
    id++;
476
477
    /* Check if 'huge' object ID encodes address & length directly */
478
0
    if (hdr->huge_ids_direct) {
479
0
        if (hdr->filter_len > 0) {
480
            /* Skip over filtered object info */
481
0
            id += hdr->sizeof_addr + hdr->sizeof_size + 4;
482
483
            /* Retrieve the object's length */
484
0
            H5F_DECODE_LENGTH(hdr->f, id, *obj_len_p);
485
0
        } /* end if */
486
0
        else {
487
            /* Skip over object offset in file */
488
0
            id += hdr->sizeof_addr;
489
490
            /* Retrieve the object's length */
491
0
            H5F_DECODE_LENGTH(hdr->f, id, *obj_len_p);
492
0
        } /* end else */
493
0
    }     /* end if */
494
0
    else {
495
0
        bool found = false; /* Whether entry was found */
496
497
        /* Check if v2 B-tree is open yet */
498
0
        if (NULL == hdr->huge_bt2) {
499
            /* Open existing v2 B-tree */
500
0
            if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f)))
501
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL,
502
0
                            "unable to open v2 B-tree for tracking 'huge' heap objects");
503
0
        } /* end if */
504
505
0
        if (hdr->filter_len > 0) {
506
0
            H5HF_huge_bt2_filt_indir_rec_t found_rec;  /* Record found from tracking object */
507
0
            H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */
508
509
            /* Get ID for looking up 'huge' object in v2 B-tree */
510
0
            UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size);
511
512
            /* Look up object in v2 B-tree */
513
0
            if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_filt_indir_found, &found_rec) <
514
0
                0)
515
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree");
516
0
            if (!found)
517
0
                HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree");
518
519
            /* Retrieve the object's length */
520
0
            *obj_len_p = (size_t)found_rec.obj_size;
521
0
        } /* end if */
522
0
        else {
523
0
            H5HF_huge_bt2_indir_rec_t found_rec;  /* Record found from tracking object */
524
0
            H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
525
526
            /* Get ID for looking up 'huge' object in v2 B-tree */
527
0
            UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size);
528
529
            /* Look up object in v2 B-tree */
530
0
            if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0)
531
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree");
532
0
            if (!found)
533
0
                HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree");
534
535
            /* Retrieve the object's length */
536
0
            *obj_len_p = (size_t)found_rec.len;
537
0
        } /* end else */
538
0
    }     /* end else */
539
540
0
done:
541
0
    FUNC_LEAVE_NOAPI(ret_value)
542
0
} /* end H5HF__huge_get_obj_len() */
543
544
/*-------------------------------------------------------------------------
545
 * Function:  H5HF__huge_get_obj_off
546
 *
547
 * Purpose: Get the offset of a 'huge' object in a fractal heap
548
 *
549
 * Return:  SUCCEED/FAIL
550
 *
551
 *-------------------------------------------------------------------------
552
 */
553
herr_t
554
H5HF__huge_get_obj_off(H5HF_hdr_t *hdr, const uint8_t *id, hsize_t *obj_off_p)
555
0
{
556
0
    haddr_t obj_addr;            /* Object's address in the file */
557
0
    herr_t  ret_value = SUCCEED; /* Return value */
558
559
0
    FUNC_ENTER_PACKAGE
560
561
    /*
562
     * Check arguments.
563
     */
564
0
    assert(hdr);
565
0
    assert(H5_addr_defined(hdr->huge_bt2_addr));
566
0
    assert(id);
567
0
    assert(obj_off_p);
568
569
    /* Skip over the flag byte */
570
0
    id++;
571
572
    /* Check if 'huge' object ID encodes address & length directly */
573
0
    if (hdr->huge_ids_direct) {
574
        /* Retrieve the object's address (common) */
575
0
        H5F_addr_decode(hdr->f, &id, &obj_addr);
576
0
    } /* end if */
577
0
    else {
578
0
        bool found = false; /* Whether entry was found */
579
580
        /* Sanity check */
581
0
        assert(H5_addr_defined(hdr->huge_bt2_addr));
582
583
        /* Check if v2 B-tree is open yet */
584
0
        if (NULL == hdr->huge_bt2) {
585
            /* Open existing v2 B-tree */
586
0
            if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f)))
587
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL,
588
0
                            "unable to open v2 B-tree for tracking 'huge' heap objects");
589
0
        } /* end if */
590
591
0
        if (hdr->filter_len > 0) {
592
0
            H5HF_huge_bt2_filt_indir_rec_t found_rec;  /* Record found from tracking object */
593
0
            H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */
594
595
            /* Get ID for looking up 'huge' object in v2 B-tree */
596
0
            UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size);
597
598
            /* Look up object in v2 B-tree */
599
0
            if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_filt_indir_found, &found_rec) <
600
0
                0)
601
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree");
602
0
            if (!found)
603
0
                HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree");
604
605
            /* Retrieve the object's address & length */
606
0
            obj_addr = found_rec.addr;
607
0
        } /* end if */
608
0
        else {
609
0
            H5HF_huge_bt2_indir_rec_t found_rec;  /* Record found from tracking object */
610
0
            H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
611
612
            /* Get ID for looking up 'huge' object in v2 B-tree */
613
0
            UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size);
614
615
            /* Look up object in v2 B-tree */
616
0
            if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0)
617
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree");
618
0
            if (!found)
619
0
                HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree");
620
621
            /* Retrieve the object's address & length */
622
0
            obj_addr = found_rec.addr;
623
0
        } /* end else */
624
0
    }     /* end else */
625
626
    /* Set the value to return */
627
0
    *obj_off_p = (hsize_t)obj_addr;
628
629
0
done:
630
0
    FUNC_LEAVE_NOAPI(ret_value)
631
0
} /* end H5HF__huge_get_obj_off() */
632
633
/*-------------------------------------------------------------------------
634
 * Function:  H5HF__huge_op_real
635
 *
636
 * Purpose: Internal routine to perform an operation on a 'huge' object
637
 *
638
 * Return:  SUCCEED/FAIL
639
 *
640
 *-------------------------------------------------------------------------
641
 */
642
static herr_t
643
H5HF__huge_op_real(H5HF_hdr_t *hdr, const uint8_t *id, bool is_read, H5HF_operator_t op, void *op_data)
644
0
{
645
0
    void    *read_buf = NULL;       /* Pointer to buffer for reading */
646
0
    haddr_t  obj_addr;              /* Object's address in the file */
647
0
    size_t   obj_size    = 0;       /* Object's size in the file */
648
0
    unsigned filter_mask = 0;       /* Filter mask for object (only used for filtered objects) */
649
0
    herr_t   ret_value   = SUCCEED; /* Return value */
650
651
0
    FUNC_ENTER_PACKAGE
652
653
    /*
654
     * Check arguments.
655
     */
656
0
    assert(hdr);
657
0
    assert(id);
658
0
    assert(is_read || op);
659
660
    /* Skip over the flag byte */
661
0
    id++;
662
663
    /* Check for 'huge' object ID that encodes address & length directly */
664
0
    if (hdr->huge_ids_direct) {
665
        /* Retrieve the object's address and length (common) */
666
0
        H5F_addr_decode(hdr->f, &id, &obj_addr);
667
0
        H5F_DECODE_LENGTH(hdr->f, id, obj_size);
668
669
        /* Retrieve extra information needed for filtered objects */
670
0
        if (hdr->filter_len > 0)
671
0
            UINT32DECODE(id, filter_mask);
672
0
    } /* end if */
673
0
    else {
674
0
        bool found = false; /* Whether entry was found */
675
676
        /* Sanity check */
677
0
        assert(H5_addr_defined(hdr->huge_bt2_addr));
678
679
        /* Check if v2 B-tree is open yet */
680
0
        if (NULL == hdr->huge_bt2) {
681
            /* Open existing v2 B-tree */
682
0
            if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f)))
683
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL,
684
0
                            "unable to open v2 B-tree for tracking 'huge' heap objects");
685
0
        } /* end if */
686
687
0
        if (hdr->filter_len > 0) {
688
0
            H5HF_huge_bt2_filt_indir_rec_t found_rec;  /* Record found from tracking object */
689
0
            H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */
690
691
            /* Get ID for looking up 'huge' object in v2 B-tree */
692
0
            UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size);
693
694
            /* Look up object in v2 B-tree */
695
0
            if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_filt_indir_found, &found_rec) <
696
0
                0)
697
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree");
698
0
            if (!found)
699
0
                HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree");
700
701
            /* Retrieve the object's address & length */
702
0
            obj_addr = found_rec.addr;
703
0
            H5_CHECKED_ASSIGN(obj_size, size_t, found_rec.len, hsize_t);
704
0
            filter_mask = found_rec.filter_mask;
705
0
        } /* end if */
706
0
        else {
707
0
            H5HF_huge_bt2_indir_rec_t found_rec;  /* Record found from tracking object */
708
0
            H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
709
710
            /* Get ID for looking up 'huge' object in v2 B-tree */
711
0
            UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size);
712
713
            /* Look up object in v2 B-tree */
714
0
            if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0)
715
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree");
716
0
            if (!found)
717
0
                HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree");
718
719
            /* Retrieve the object's address & length */
720
0
            obj_addr = found_rec.addr;
721
0
            H5_CHECKED_ASSIGN(obj_size, size_t, found_rec.len, hsize_t);
722
0
        } /* end else */
723
0
    }     /* end else */
724
725
    /* Set up buffer for reading */
726
0
    if (hdr->filter_len > 0 || !is_read) {
727
0
        if (NULL == (read_buf = H5MM_malloc((size_t)obj_size)))
728
0
            HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer");
729
0
    } /* end if */
730
0
    else
731
0
        read_buf = op_data;
732
733
    /* Read the object's (possibly filtered) data from the file */
734
    /* (reads directly into application's buffer if no filters are present) */
735
0
    if (H5F_block_read(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, (size_t)obj_size, read_buf) < 0)
736
0
        HGOTO_ERROR(H5E_HEAP, H5E_READERROR, FAIL, "can't read 'huge' object's data from the file");
737
738
    /* Check for I/O pipeline filter on heap */
739
0
    if (hdr->filter_len > 0) {
740
0
        H5Z_cb_t filter_cb; /* Filter callback structure */
741
0
        size_t   read_size; /* Object's size in the file */
742
0
        size_t   nbytes;    /* Number of bytes used */
743
744
        /* Initialize the filter callback struct */
745
0
        filter_cb.op_data = NULL;
746
0
        filter_cb.func    = NULL; /* no callback function when failed */
747
748
        /* De-filter the object */
749
0
        read_size = nbytes = obj_size;
750
0
        if (H5Z_pipeline(&(hdr->pline), H5Z_FLAG_REVERSE, &filter_mask, H5Z_NO_EDC, filter_cb, &nbytes,
751
0
                         &read_size, &read_buf) < 0)
752
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, FAIL, "input filter failed");
753
0
        obj_size = nbytes;
754
0
    } /* end if */
755
756
    /* Perform correct operation on buffer read in */
757
0
    if (is_read) {
758
        /* Copy object to user's buffer if there's filters on heap data */
759
        /* (if there's no filters, the object was read directly into the user's buffer) */
760
0
        if (hdr->filter_len > 0)
761
0
            H5MM_memcpy(op_data, read_buf, (size_t)obj_size);
762
0
    } /* end if */
763
0
    else {
764
        /* Call the user's 'op' callback */
765
0
        if (op(read_buf, (size_t)obj_size, op_data) < 0) {
766
            /* Release buffer */
767
0
            read_buf = H5MM_xfree(read_buf);
768
769
            /* Indicate error */
770
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "application's callback failed");
771
0
        } /* end if */
772
0
    }     /* end if */
773
774
0
done:
775
    /* Release the buffer for reading */
776
0
    if (read_buf && read_buf != op_data)
777
0
        read_buf = H5MM_xfree(read_buf);
778
779
0
    FUNC_LEAVE_NOAPI(ret_value)
780
0
} /* end H5HF__huge_op_real() */
781
782
/*-------------------------------------------------------------------------
783
 * Function:    H5HF__huge_write
784
 *
785
 * Purpose:     Write a 'huge' object to the heap
786
 *
787
 * Note:        This implementation somewhat limited: it doesn't handle
788
 *              heaps with filters, which would require re-compressing the
789
 *              huge object and probably changing the address of the object
790
 *              on disk (and possibly the heap ID for "direct" huge IDs).
791
 *
792
 * Return:      SUCCEED/FAIL
793
 *
794
 *-------------------------------------------------------------------------
795
 */
796
herr_t
797
H5HF__huge_write(H5HF_hdr_t *hdr, const uint8_t *id, const void *obj)
798
0
{
799
0
    haddr_t obj_addr  = HADDR_UNDEF; /* Object's address in the file */
800
0
    size_t  obj_size  = 0;           /* Object's size in the file */
801
0
    herr_t  ret_value = SUCCEED;
802
803
0
    FUNC_ENTER_PACKAGE
804
805
0
    assert(hdr);
806
0
    assert(id);
807
0
    assert(obj);
808
809
    /* Check for filters on the heap */
810
0
    if (hdr->filter_len > 0)
811
0
        HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL,
812
0
                    "modifying 'huge' object with filters not supported yet");
813
814
    /* Skip over the flag byte */
815
0
    id++;
816
817
    /* Check for 'huge' object ID that encodes address & length directly */
818
0
    if (hdr->huge_ids_direct) {
819
        /* Retrieve the object's address and length (common) */
820
0
        H5F_addr_decode(hdr->f, &id, &obj_addr);
821
0
        H5F_DECODE_LENGTH(hdr->f, id, obj_size);
822
0
    }
823
0
    else {
824
0
        H5HF_huge_bt2_indir_rec_t found_rec;     /* Record found from tracking object */
825
0
        H5HF_huge_bt2_indir_rec_t search_rec;    /* Record for searching for object */
826
0
        bool                      found = false; /* Whether entry was found */
827
828
        /* Sanity check */
829
0
        assert(H5_addr_defined(hdr->huge_bt2_addr));
830
831
        /* Check if v2 B-tree is open yet */
832
0
        if (NULL == hdr->huge_bt2) {
833
            /* Open existing v2 B-tree */
834
0
            if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f)))
835
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL,
836
0
                            "unable to open v2 B-tree for tracking 'huge' heap objects");
837
0
        }
838
839
        /* Get ID for looking up 'huge' object in v2 B-tree */
840
0
        UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size);
841
842
        /* Look up object in v2 B-tree */
843
0
        if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0)
844
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree");
845
0
        if (!found)
846
0
            HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree");
847
848
        /* Retrieve the object's address & length */
849
0
        obj_addr = found_rec.addr;
850
0
        H5_CHECKED_ASSIGN(obj_size, size_t, found_rec.len, hsize_t);
851
0
    }
852
853
    /* Write the object's data to the file */
854
    /* (writes directly from application's buffer) */
855
0
    if (H5F_block_write(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, obj_size, obj) < 0)
856
0
        HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "writing 'huge' object to file failed");
857
858
0
done:
859
0
    FUNC_LEAVE_NOAPI(ret_value)
860
0
} /* end H5HF__huge_write() */
861
862
/*-------------------------------------------------------------------------
863
 * Function:  H5HF__huge_read
864
 *
865
 * Purpose: Read a 'huge' object from the heap
866
 *
867
 * Return:  SUCCEED/FAIL
868
 *
869
 *-------------------------------------------------------------------------
870
 */
871
herr_t
872
H5HF__huge_read(H5HF_hdr_t *hdr, const uint8_t *id, void *obj)
873
0
{
874
0
    herr_t ret_value = SUCCEED; /* Return value */
875
876
0
    FUNC_ENTER_PACKAGE
877
878
    /*
879
     * Check arguments.
880
     */
881
0
    assert(hdr);
882
0
    assert(id);
883
0
    assert(obj);
884
885
    /* Call the internal 'op' routine */
886
0
    if (H5HF__huge_op_real(hdr, id, true, NULL, obj) < 0)
887
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object");
888
889
0
done:
890
0
    FUNC_LEAVE_NOAPI(ret_value)
891
0
} /* end H5HF__huge_read() */
892
893
/*-------------------------------------------------------------------------
894
 * Function:  H5HF__huge_op
895
 *
896
 * Purpose: Operate directly on a 'huge' object
897
 *
898
 * Return:  SUCCEED/FAIL
899
 *
900
 *-------------------------------------------------------------------------
901
 */
902
herr_t
903
H5HF__huge_op(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op, void *op_data)
904
0
{
905
0
    herr_t ret_value = SUCCEED; /* Return value */
906
907
0
    FUNC_ENTER_PACKAGE
908
909
    /*
910
     * Check arguments.
911
     */
912
0
    assert(hdr);
913
0
    assert(id);
914
0
    assert(op);
915
916
    /* Call the internal 'op' routine routine */
917
0
    if (H5HF__huge_op_real(hdr, id, false, op, op_data) < 0)
918
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object");
919
920
0
done:
921
0
    FUNC_LEAVE_NOAPI(ret_value)
922
0
} /* end H5HF__huge_op() */
923
924
/*-------------------------------------------------------------------------
925
 * Function:  H5HF__huge_remove
926
 *
927
 * Purpose: Remove a 'huge' object from the file and the v2 B-tree tracker
928
 *
929
 * Return:  SUCCEED/FAIL
930
 *
931
 *-------------------------------------------------------------------------
932
 */
933
herr_t
934
H5HF__huge_remove(H5HF_hdr_t *hdr, const uint8_t *id)
935
0
{
936
0
    H5HF_huge_remove_ud_t udata;               /* User callback data for v2 B-tree remove call */
937
0
    herr_t                ret_value = SUCCEED; /* Return value */
938
939
0
    FUNC_ENTER_PACKAGE
940
941
    /*
942
     * Check arguments.
943
     */
944
0
    assert(hdr);
945
0
    assert(H5_addr_defined(hdr->huge_bt2_addr));
946
0
    assert(id);
947
948
    /* Check if v2 B-tree is open yet */
949
0
    if (NULL == hdr->huge_bt2) {
950
        /* Open existing v2 B-tree */
951
0
        if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f)))
952
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL,
953
0
                        "unable to open v2 B-tree for tracking 'huge' heap objects");
954
0
    } /* end if */
955
956
    /* Skip over the flag byte */
957
0
    id++;
958
959
    /* Set up the common callback info */
960
0
    udata.hdr = hdr;
961
962
    /* Check for 'huge' object ID that encodes address & length directly */
963
0
    if (hdr->huge_ids_direct) {
964
0
        if (hdr->filter_len > 0) {
965
0
            H5HF_huge_bt2_filt_dir_rec_t search_rec; /* Record for searching for object */
966
967
            /* Retrieve the object's address and length */
968
            /* (used as key in v2 B-tree record) */
969
0
            H5F_addr_decode(hdr->f, &id, &search_rec.addr);
970
0
            H5F_DECODE_LENGTH(hdr->f, id, search_rec.len);
971
972
            /* Remove the record for tracking the 'huge' object from the v2 B-tree */
973
            /* (space in the file for the object is freed in the 'remove' callback) */
974
0
            if (H5B2_remove(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_filt_dir_remove, &udata) < 0)
975
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree");
976
0
        } /* end if */
977
0
        else {
978
0
            H5HF_huge_bt2_dir_rec_t search_rec; /* Record for searching for object */
979
980
            /* Retrieve the object's address and length */
981
            /* (used as key in v2 B-tree record) */
982
0
            H5F_addr_decode(hdr->f, &id, &search_rec.addr);
983
0
            H5F_DECODE_LENGTH(hdr->f, id, search_rec.len);
984
985
            /* Remove the record for tracking the 'huge' object from the v2 B-tree */
986
            /* (space in the file for the object is freed in the 'remove' callback) */
987
0
            if (H5B2_remove(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_dir_remove, &udata) < 0)
988
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree");
989
0
        } /* end else */
990
0
    }     /* end if */
991
0
    else {
992
0
        if (hdr->filter_len > 0) {
993
0
            H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */
994
995
            /* Get ID for looking up 'huge' object in v2 B-tree */
996
0
            UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size);
997
998
            /* Remove the record for tracking the 'huge' object from the v2 B-tree */
999
            /* (space in the file for the object is freed in the 'remove' callback) */
1000
0
            if (H5B2_remove(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_filt_indir_remove, &udata) < 0)
1001
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree");
1002
0
        } /* end if */
1003
0
        else {
1004
0
            H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
1005
1006
            /* Get ID for looking up 'huge' object in v2 B-tree */
1007
0
            UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size);
1008
1009
            /* Remove the record for tracking the 'huge' object from the v2 B-tree */
1010
            /* (space in the file for the object is freed in the 'remove' callback) */
1011
0
            if (H5B2_remove(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_indir_remove, &udata) < 0)
1012
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree");
1013
0
        } /* end else */
1014
0
    }     /* end else */
1015
1016
    /* Update statistics about heap */
1017
0
    hdr->huge_size -= udata.obj_len;
1018
0
    hdr->huge_nobjs--;
1019
1020
    /* Mark heap header as modified */
1021
0
    if (H5HF__hdr_dirty(hdr) < 0)
1022
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty");
1023
1024
0
done:
1025
0
    FUNC_LEAVE_NOAPI(ret_value)
1026
0
} /* end H5HF__huge_remove() */
1027
1028
/*-------------------------------------------------------------------------
1029
 * Function:  H5HF__huge_term
1030
 *
1031
 * Purpose: Shut down the information for tracking 'huge' objects
1032
 *
1033
 * Return:  SUCCEED/FAIL
1034
 *
1035
 *-------------------------------------------------------------------------
1036
 */
1037
herr_t
1038
H5HF__huge_term(H5HF_hdr_t *hdr)
1039
0
{
1040
0
    herr_t ret_value = SUCCEED; /* Return value */
1041
1042
0
    FUNC_ENTER_PACKAGE
1043
1044
    /*
1045
     * Check arguments.
1046
     */
1047
0
    assert(hdr);
1048
1049
    /* Check if v2 B-tree index is open */
1050
0
    if (hdr->huge_bt2) {
1051
        /* Sanity check */
1052
0
        assert(H5_addr_defined(hdr->huge_bt2_addr));
1053
1054
        /* Close v2 B-tree index */
1055
0
        if (H5B2_close(hdr->huge_bt2) < 0)
1056
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree");
1057
0
        hdr->huge_bt2 = NULL;
1058
0
    } /* end if */
1059
1060
    /* Check if there are no more 'huge' objects in the heap and delete the
1061
     *  v2 B-tree that tracks them, if so
1062
     */
1063
0
    if (H5_addr_defined(hdr->huge_bt2_addr) && hdr->huge_nobjs == 0) {
1064
        /* Sanity check */
1065
0
        assert(hdr->huge_size == 0);
1066
1067
        /* Delete the v2 B-tree */
1068
        /* (any v2 B-tree class will work here) */
1069
0
        if (H5B2_delete(hdr->f, hdr->huge_bt2_addr, hdr->f, NULL, NULL) < 0)
1070
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree");
1071
1072
        /* Reset the information about 'huge' objects in the file */
1073
0
        hdr->huge_bt2_addr    = HADDR_UNDEF;
1074
0
        hdr->huge_next_id     = 0;
1075
0
        hdr->huge_ids_wrapped = false;
1076
1077
        /* Mark heap header as modified */
1078
0
        if (H5HF__hdr_dirty(hdr) < 0)
1079
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty");
1080
0
    } /* end if */
1081
1082
0
done:
1083
0
    FUNC_LEAVE_NOAPI(ret_value)
1084
0
} /* end H5HF__huge_term() */
1085
1086
/*-------------------------------------------------------------------------
1087
 * Function:  H5HF__huge_delete
1088
 *
1089
 * Purpose: Delete all the 'huge' objects in the heap, and the v2 B-tree
1090
 *              tracker for them
1091
 *
1092
 * Return:  SUCCEED/FAIL
1093
 *
1094
 *-------------------------------------------------------------------------
1095
 */
1096
herr_t
1097
H5HF__huge_delete(H5HF_hdr_t *hdr)
1098
0
{
1099
0
    H5HF_huge_remove_ud_t udata;               /* User callback data for v2 B-tree remove call */
1100
0
    H5B2_remove_t         op;                  /* Callback for v2 B-tree removal */
1101
0
    herr_t                ret_value = SUCCEED; /* Return value */
1102
1103
0
    FUNC_ENTER_PACKAGE
1104
1105
    /*
1106
     * Check arguments.
1107
     */
1108
0
    assert(hdr);
1109
0
    assert(H5_addr_defined(hdr->huge_bt2_addr));
1110
0
    assert(hdr->huge_nobjs);
1111
0
    assert(hdr->huge_size);
1112
1113
    /* Set up the callback info */
1114
0
    udata.hdr = hdr;
1115
1116
    /* Set the v2 B-tree callback operator */
1117
0
    if (hdr->huge_ids_direct) {
1118
0
        if (hdr->filter_len > 0)
1119
0
            op = H5HF__huge_bt2_filt_dir_remove;
1120
0
        else
1121
0
            op = H5HF__huge_bt2_dir_remove;
1122
0
    } /* end if */
1123
0
    else {
1124
0
        if (hdr->filter_len > 0)
1125
0
            op = H5HF__huge_bt2_filt_indir_remove;
1126
0
        else
1127
0
            op = H5HF__huge_bt2_indir_remove;
1128
0
    } /* end else */
1129
1130
    /* Delete the v2 B-tree */
1131
0
    if (H5B2_delete(hdr->f, hdr->huge_bt2_addr, hdr->f, op, &udata) < 0)
1132
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree");
1133
1134
0
done:
1135
0
    FUNC_LEAVE_NOAPI(ret_value)
1136
0
} /* end H5HF__huge_delete() */