Coverage Report

Created: 2026-06-08 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Dfarray.c
Line
Count
Source
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the LICENSE file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/*
14
 * Purpose:     Fixed array indexed (chunked) I/O functions.
15
 *              The chunk coordinate is mapped as an index into an array of
16
 *              disk addresses for the chunks.
17
 */
18
19
/****************/
20
/* Module Setup */
21
/****************/
22
23
#include "H5Dmodule.h" /* This source code file is part of the H5D module */
24
25
/***********/
26
/* Headers */
27
/***********/
28
#include "H5private.h"   /* Generic Functions            */
29
#include "H5Dpkg.h"      /* Datasets                     */
30
#include "H5Eprivate.h"  /* Error handling               */
31
#include "H5FAprivate.h" /* Fixed arrays                 */
32
#include "H5FLprivate.h" /* Free Lists                   */
33
#include "H5MFprivate.h" /* File space management        */
34
#include "H5VMprivate.h" /* Vector functions             */
35
36
/****************/
37
/* Local Macros */
38
/****************/
39
40
1
#define H5D_FARRAY_IDX_IS_OPEN(idx_info) (NULL != (idx_info)->layout->storage.u.chunk.u.btree2.bt2)
41
42
/* Value to fill unset array elements with */
43
0
#define H5D_FARRAY_FILL HADDR_UNDEF
44
#define H5D_FARRAY_FILT_FILL                                                                                 \
45
0
    {                                                                                                        \
46
0
        HADDR_UNDEF, 0, 0                                                                                    \
47
0
    }
48
49
/*
50
 * Macros to compute the size required for encoding the size of a chunk. For version 4, this is the minimum
51
 * number of bytes required to encode the size of an unfiltered chunk plus an extra byte, in case the filter
52
 * makes the chunk larger. For versions after 4, this is simply the size of lengths for the file. For
53
 * unfiltered chunks, this is 0.
54
 */
55
#define H5D_FARRAY_FILT_COMPUTE_CHUNK_SIZE_LEN(chunk_size_len, f, layout)                                    \
56
0
    do {                                                                                                     \
57
0
        if ((layout)->version > H5O_LAYOUT_VERSION_4)                                                        \
58
0
            (chunk_size_len) = H5F_SIZEOF_SIZE(f);                                                           \
59
0
        else {                                                                                               \
60
0
            (chunk_size_len) = 1 + ((H5VM_log2_gen((uint64_t)(layout)->u.chunk.size) + 8) / 8);              \
61
0
            if ((chunk_size_len) > 8)                                                                        \
62
0
                (chunk_size_len) = 8;                                                                        \
63
0
        }                                                                                                    \
64
0
    } while (0)
65
#define H5D_FARRAY_COMPUTE_CHUNK_SIZE_LEN(chunk_size_len, idx_info)                                          \
66
0
    do {                                                                                                     \
67
0
        if ((idx_info)->pline->nused > 0)                                                                    \
68
0
            H5D_FARRAY_FILT_COMPUTE_CHUNK_SIZE_LEN(chunk_size_len, (idx_info)->f, (idx_info)->layout);       \
69
0
        else                                                                                                 \
70
0
            (chunk_size_len) = 0;                                                                            \
71
0
    } while (0)
72
73
/******************/
74
/* Local Typedefs */
75
/******************/
76
77
/* Fixed array create/open user data */
78
typedef struct H5D_farray_ctx_ud_t {
79
    const H5F_t *f;              /* Pointer to file info */
80
    size_t       chunk_size_len; /* Size of chunk sizes in the file (bytes) */
81
} H5D_farray_ctx_ud_t;
82
83
/* Fixed array callback context */
84
typedef struct H5D_farray_ctx_t {
85
    size_t file_addr_len;  /* Size of addresses in the file (bytes) */
86
    size_t chunk_size_len; /* Size of chunk sizes in the file (bytes) */
87
} H5D_farray_ctx_t;
88
89
/* Fixed Array callback info for iteration over chunks */
90
typedef struct H5D_farray_it_ud_t {
91
    H5D_chunk_common_ud_t common;    /* Common info for Fixed Array user data (must be first) */
92
    H5D_chunk_rec_t       chunk_rec; /* Generic chunk record for callback */
93
    bool                  filtered;  /* Whether the chunks are filtered */
94
    H5D_chunk_cb_func_t   cb;        /* Chunk callback routine */
95
    void                 *udata;     /* User data for chunk callback routine */
96
} H5D_farray_it_ud_t;
97
98
/* Native fixed array element for chunks w/filters */
99
typedef struct H5D_farray_filt_elmt_t {
100
    haddr_t  addr;        /* Address of chunk */
101
    hsize_t  nbytes;      /* Size of chunk (in file) */
102
    uint32_t filter_mask; /* Excluded filters for chunk */
103
} H5D_farray_filt_elmt_t;
104
105
/********************/
106
/* Local Prototypes */
107
/********************/
108
109
/* Fixed Array iterator callbacks */
110
static int H5D__farray_idx_iterate_cb(hsize_t idx, const void *_elmt, void *_udata);
111
static int H5D__farray_idx_delete_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
112
113
/* Fixed array class callbacks for chunks w/o filters */
114
static void  *H5D__farray_crt_context(void *udata);
115
static herr_t H5D__farray_dst_context(void *ctx);
116
static herr_t H5D__farray_fill(void *nat_blk, size_t nelmts);
117
static herr_t H5D__farray_encode(void *raw, const void *elmt, size_t nelmts, void *ctx);
118
static herr_t H5D__farray_decode(const void *raw, void *elmt, size_t nelmts, void *ctx);
119
static herr_t H5D__farray_debug(FILE *stream, int indent, int fwidth, hsize_t idx, const void *elmt);
120
static void  *H5D__farray_crt_dbg_context(H5F_t *f, haddr_t obj_addr);
121
static herr_t H5D__farray_dst_dbg_context(void *dbg_ctx);
122
123
/* Fixed array class callbacks for chunks w/filters */
124
/* (some shared with callbacks for chunks w/o filters) */
125
static herr_t H5D__farray_filt_fill(void *nat_blk, size_t nelmts);
126
static herr_t H5D__farray_filt_encode(void *raw, const void *elmt, size_t nelmts, void *ctx);
127
static herr_t H5D__farray_filt_decode(const void *raw, void *elmt, size_t nelmts, void *ctx);
128
static herr_t H5D__farray_filt_debug(FILE *stream, int indent, int fwidth, hsize_t idx, const void *elmt);
129
static void  *H5D__farray_filt_crt_dbg_context(H5F_t *f, haddr_t obj_addr);
130
131
/* Chunked layout indexing callbacks */
132
static herr_t H5D__farray_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t *space,
133
                                   haddr_t dset_ohdr_addr);
134
static herr_t H5D__farray_idx_create(const H5D_chk_idx_info_t *idx_info);
135
static herr_t H5D__farray_idx_open(const H5D_chk_idx_info_t *idx_info);
136
static herr_t H5D__farray_idx_close(const H5D_chk_idx_info_t *idx_info);
137
static herr_t H5D__farray_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open);
138
static bool   H5D__farray_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
139
static herr_t H5D__farray_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
140
                                     const H5D_t *dset);
141
static herr_t H5D__farray_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata);
142
static herr_t H5D__farray_idx_load_metadata(const H5D_chk_idx_info_t *idx_info);
143
static int    H5D__farray_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb,
144
                                      void *chunk_udata);
145
static herr_t H5D__farray_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata);
146
static herr_t H5D__farray_idx_delete(const H5D_chk_idx_info_t *idx_info);
147
static herr_t H5D__farray_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src,
148
                                         const H5D_chk_idx_info_t *idx_info_dst);
149
static herr_t H5D__farray_idx_copy_shutdown(H5O_storage_chunk_t *storage_src,
150
                                            H5O_storage_chunk_t *storage_dst);
151
static herr_t H5D__farray_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *size);
152
static herr_t H5D__farray_idx_reset(H5O_storage_chunk_t *storage, bool reset_addr);
153
static herr_t H5D__farray_idx_dump(const H5O_storage_chunk_t *storage, FILE *stream);
154
static herr_t H5D__farray_idx_dest(const H5D_chk_idx_info_t *idx_info);
155
156
/* Generic fixed array routines */
157
static herr_t H5D__farray_idx_depend(const H5D_chk_idx_info_t *idx_info);
158
159
/*********************/
160
/* Package Variables */
161
/*********************/
162
163
/* Fixed array indexed chunk I/O ops */
164
const H5D_chunk_ops_t H5D_COPS_FARRAY[1] = {{
165
    true,                           /* Fixed array indices support SWMR access */
166
    H5D__farray_idx_init,           /* init */
167
    H5D__farray_idx_create,         /* create */
168
    H5D__farray_idx_open,           /* open */
169
    H5D__farray_idx_close,          /* close */
170
    H5D__farray_idx_is_open,        /* is_open */
171
    H5D__farray_idx_is_space_alloc, /* is_space_alloc */
172
    H5D__farray_idx_insert,         /* insert */
173
    H5D__farray_idx_get_addr,       /* get_addr */
174
    H5D__farray_idx_load_metadata,  /* load_metadata */
175
    NULL,                           /* resize */
176
    H5D__farray_idx_iterate,        /* iterate */
177
    H5D__farray_idx_remove,         /* remove */
178
    H5D__farray_idx_delete,         /* delete */
179
    H5D__farray_idx_copy_setup,     /* copy_setup */
180
    H5D__farray_idx_copy_shutdown,  /* copy_shutdown */
181
    H5D__farray_idx_size,           /* size */
182
    H5D__farray_idx_reset,          /* reset */
183
    H5D__farray_idx_dump,           /* dump */
184
    H5D__farray_idx_dest            /* destroy */
185
}};
186
187
/*****************************/
188
/* Library Private Variables */
189
/*****************************/
190
191
/*******************/
192
/* Local Variables */
193
/*******************/
194
195
/* Fixed array class callbacks for dataset chunks w/o filters */
196
const H5FA_class_t H5FA_CLS_CHUNK[1] = {{
197
    H5FA_CLS_CHUNK_ID,           /* Type of fixed array */
198
    "Chunk w/o filters",         /* Name of fixed array class */
199
    sizeof(haddr_t),             /* Size of native element */
200
    H5D__farray_crt_context,     /* Create context */
201
    H5D__farray_dst_context,     /* Destroy context */
202
    H5D__farray_fill,            /* Fill block of missing elements callback */
203
    H5D__farray_encode,          /* Element encoding callback */
204
    H5D__farray_decode,          /* Element decoding callback */
205
    H5D__farray_debug,           /* Element debugging callback */
206
    H5D__farray_crt_dbg_context, /* Create debugging context */
207
    H5D__farray_dst_dbg_context  /* Destroy debugging context */
208
}};
209
210
/* Fixed array class callbacks for dataset chunks w/filters */
211
const H5FA_class_t H5FA_CLS_FILT_CHUNK[1] = {{
212
    H5FA_CLS_FILT_CHUNK_ID,           /* Type of fixed array */
213
    "Chunk w/filters",                /* Name of fixed array class */
214
    sizeof(H5D_farray_filt_elmt_t),   /* Size of native element */
215
    H5D__farray_crt_context,          /* Create context */
216
    H5D__farray_dst_context,          /* Destroy context */
217
    H5D__farray_filt_fill,            /* Fill block of missing elements callback */
218
    H5D__farray_filt_encode,          /* Element encoding callback */
219
    H5D__farray_filt_decode,          /* Element decoding callback */
220
    H5D__farray_filt_debug,           /* Element debugging callback */
221
    H5D__farray_filt_crt_dbg_context, /* Create debugging context */
222
    H5D__farray_dst_dbg_context       /* Destroy debugging context */
223
}};
224
225
/* Declare a free list to manage the H5D_farray_ctx_t struct */
226
H5FL_DEFINE_STATIC(H5D_farray_ctx_t);
227
228
/* Declare a free list to manage the H5D_farray_ctx_ud_t struct */
229
H5FL_DEFINE_STATIC(H5D_farray_ctx_ud_t);
230
231
/*-------------------------------------------------------------------------
232
 * Function:    H5D__farray_crt_context
233
 *
234
 * Purpose:     Create context for callbacks
235
 *
236
 * Return:      Success:    non-NULL
237
 *              Failure:    NULL
238
 *
239
 *-------------------------------------------------------------------------
240
 */
241
static void *
242
H5D__farray_crt_context(void *_udata)
243
0
{
244
0
    H5D_farray_ctx_t    *ctx;                                       /* Fixed array callback context */
245
0
    H5D_farray_ctx_ud_t *udata     = (H5D_farray_ctx_ud_t *)_udata; /* User data for fixed array context */
246
0
    void                *ret_value = NULL;                          /* Return value */
247
248
0
    FUNC_ENTER_PACKAGE
249
250
    /* Sanity checks */
251
0
    assert(udata);
252
0
    assert(udata->f);
253
254
    /* Allocate new context structure */
255
0
    if (NULL == (ctx = H5FL_MALLOC(H5D_farray_ctx_t)))
256
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate fixed array client callback context");
257
258
    /* Initialize the context */
259
0
    ctx->file_addr_len  = H5F_SIZEOF_ADDR(udata->f);
260
0
    ctx->chunk_size_len = udata->chunk_size_len;
261
262
    /* Set return value */
263
0
    ret_value = ctx;
264
265
0
done:
266
0
    FUNC_LEAVE_NOAPI(ret_value)
267
0
} /* end H5D__farray_crt_context() */
268
269
/*-------------------------------------------------------------------------
270
 * Function:    H5D__farray_dst_context
271
 *
272
 * Purpose:     Destroy context for callbacks
273
 *
274
 * Return:      Success:    non-NULL
275
 *              Failure:    NULL
276
 *
277
 *-------------------------------------------------------------------------
278
 */
279
static herr_t
280
H5D__farray_dst_context(void *_ctx)
281
0
{
282
0
    H5D_farray_ctx_t *ctx = (H5D_farray_ctx_t *)_ctx; /* Fixed array callback context */
283
284
0
    FUNC_ENTER_PACKAGE_NOERR
285
286
    /* Sanity checks */
287
0
    assert(ctx);
288
289
    /* Release context structure */
290
0
    ctx = H5FL_FREE(H5D_farray_ctx_t, ctx);
291
292
0
    FUNC_LEAVE_NOAPI(SUCCEED)
293
0
} /* end H5D__farray_dst_context() */
294
295
/*-------------------------------------------------------------------------
296
 * Function:    H5D__farray_fill
297
 *
298
 * Purpose:     Fill "missing elements" in block of elements
299
 *
300
 * Return:      Success:    non-negative
301
 *              Failure:    negative
302
 *
303
 *-------------------------------------------------------------------------
304
 */
305
static herr_t
306
H5D__farray_fill(void *nat_blk, size_t nelmts)
307
0
{
308
0
    haddr_t fill_val = H5D_FARRAY_FILL; /* Value to fill elements with */
309
310
0
    FUNC_ENTER_PACKAGE_NOERR
311
312
    /* Sanity checks */
313
0
    assert(nat_blk);
314
0
    assert(nelmts);
315
316
0
    H5VM_array_fill(nat_blk, &fill_val, H5FA_CLS_CHUNK->nat_elmt_size, nelmts);
317
318
0
    FUNC_LEAVE_NOAPI(SUCCEED)
319
0
} /* end H5D__farray_fill() */
320
321
/*-------------------------------------------------------------------------
322
 * Function:    H5D__farray_encode
323
 *
324
 * Purpose:     Encode an element from "native" to "raw" form
325
 *
326
 * Return:      Success:    non-negative
327
 *              Failure:    negative
328
 *
329
 *-------------------------------------------------------------------------
330
 */
331
static herr_t
332
H5D__farray_encode(void *raw, const void *_elmt, size_t nelmts, void *_ctx)
333
0
{
334
0
    H5D_farray_ctx_t *ctx  = (H5D_farray_ctx_t *)_ctx; /* Fixed array callback context */
335
0
    const haddr_t    *elmt = (const haddr_t *)_elmt;   /* Convenience pointer to native elements */
336
337
0
    FUNC_ENTER_PACKAGE_NOERR
338
339
    /* Sanity checks */
340
0
    assert(raw);
341
0
    assert(elmt);
342
0
    assert(nelmts);
343
0
    assert(ctx);
344
345
    /* Encode native elements into raw elements */
346
0
    while (nelmts) {
347
        /* Encode element */
348
        /* (advances 'raw' pointer) */
349
0
        H5F_addr_encode_len(ctx->file_addr_len, (uint8_t **)&raw, *elmt);
350
351
        /* Advance native element pointer */
352
0
        elmt++;
353
354
        /* Decrement # of elements to encode */
355
0
        nelmts--;
356
0
    } /* end while */
357
358
0
    FUNC_LEAVE_NOAPI(SUCCEED)
359
0
} /* end H5D__farray_encode() */
360
361
/*-------------------------------------------------------------------------
362
 * Function:    H5D__farray_decode
363
 *
364
 * Purpose:     Decode an element from "raw" to "native" form
365
 *
366
 * Return:      Success:    non-negative
367
 *              Failure:    negative
368
 *
369
 *-------------------------------------------------------------------------
370
 */
371
static herr_t
372
H5D__farray_decode(const void *_raw, void *_elmt, size_t nelmts, void *_ctx)
373
0
{
374
0
    H5D_farray_ctx_t *ctx  = (H5D_farray_ctx_t *)_ctx; /* Fixed array callback context */
375
0
    haddr_t          *elmt = (haddr_t *)_elmt;         /* Convenience pointer to native elements */
376
0
    const uint8_t    *raw  = (const uint8_t *)_raw;    /* Convenience pointer to raw elements */
377
378
0
    FUNC_ENTER_PACKAGE_NOERR
379
380
    /* Sanity checks */
381
0
    assert(raw);
382
0
    assert(elmt);
383
0
    assert(nelmts);
384
385
    /* Decode raw elements into native elements */
386
0
    while (nelmts) {
387
        /* Decode element */
388
        /* (advances 'raw' pointer) */
389
0
        H5F_addr_decode_len(ctx->file_addr_len, &raw, elmt);
390
391
        /* Advance native element pointer */
392
0
        elmt++;
393
394
        /* Decrement # of elements to decode */
395
0
        nelmts--;
396
0
    } /* end while */
397
398
0
    FUNC_LEAVE_NOAPI(SUCCEED)
399
0
} /* end H5D__farray_decode() */
400
401
/*-------------------------------------------------------------------------
402
 * Function:    H5D__farray_debug
403
 *
404
 * Purpose:     Display an element for debugging
405
 *
406
 * Return:      Success:    non-negative
407
 *              Failure:    negative
408
 *
409
 *-------------------------------------------------------------------------
410
 */
411
static herr_t
412
H5D__farray_debug(FILE *stream, int indent, int fwidth, hsize_t idx, const void *elmt)
413
0
{
414
0
    char temp_str[128]; /* Temporary string, for formatting */
415
416
0
    FUNC_ENTER_PACKAGE_NOERR
417
418
    /* Sanity checks */
419
0
    assert(stream);
420
0
    assert(elmt);
421
422
    /* Print element */
423
0
    snprintf(temp_str, sizeof(temp_str), "Element #%" PRIuHSIZE ":", idx);
424
0
    fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, temp_str, *(const haddr_t *)elmt);
425
426
0
    FUNC_LEAVE_NOAPI(SUCCEED)
427
0
} /* end H5D__farray_debug() */
428
429
/*-------------------------------------------------------------------------
430
 * Function:    H5D__farray_crt_dbg_context
431
 *
432
 * Purpose:     Create context for debugging callback
433
 *              (get the layout message in the specified object header)
434
 *
435
 * Return:      Success:    non-NULL
436
 *              Failure:    NULL
437
 *
438
 *-------------------------------------------------------------------------
439
 */
440
static void *
441
H5D__farray_crt_dbg_context(H5F_t *f, haddr_t H5_ATTR_UNUSED obj_addr)
442
0
{
443
0
    H5D_farray_ctx_ud_t *dbg_ctx   = NULL; /* Context for fixed array callback */
444
0
    void                *ret_value = NULL; /* Return value */
445
446
0
    FUNC_ENTER_PACKAGE
447
448
    /* Sanity checks */
449
0
    assert(f);
450
0
    assert(H5_addr_defined(obj_addr));
451
452
    /* Allocate context for debugging callback */
453
0
    if (NULL == (dbg_ctx = H5FL_MALLOC(H5D_farray_ctx_ud_t)))
454
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate fixed array client callback context");
455
456
    /* Create user data */
457
0
    dbg_ctx->f              = f;
458
0
    dbg_ctx->chunk_size_len = 0;
459
460
    /* Set return value */
461
0
    ret_value = dbg_ctx;
462
463
0
done:
464
    /* Cleanup on error */
465
0
    if (ret_value == NULL)
466
        /* Release context structure */
467
0
        if (dbg_ctx)
468
0
            dbg_ctx = H5FL_FREE(H5D_farray_ctx_ud_t, dbg_ctx);
469
470
0
    FUNC_LEAVE_NOAPI(ret_value)
471
0
} /* end H5D__farray_crt_dbg_context() */
472
473
/*-------------------------------------------------------------------------
474
 * Function:    H5D__farray_dst_dbg_context
475
 *
476
 * Purpose:     Destroy context for debugging callback
477
 *              (free the layout message from the specified object header)
478
 *
479
 * Return:      Success:    non-negative
480
 *              Failure:    negative
481
 *
482
 *-------------------------------------------------------------------------
483
 */
484
static herr_t
485
H5D__farray_dst_dbg_context(void *_dbg_ctx)
486
0
{
487
0
    H5D_farray_ctx_ud_t *dbg_ctx = (H5D_farray_ctx_ud_t *)_dbg_ctx; /* Context for fixed array callback */
488
489
0
    FUNC_ENTER_PACKAGE_NOERR
490
491
    /* Sanity checks */
492
0
    assert(dbg_ctx);
493
494
    /* Release context structure */
495
0
    dbg_ctx = H5FL_FREE(H5D_farray_ctx_ud_t, dbg_ctx);
496
497
0
    FUNC_LEAVE_NOAPI(SUCCEED)
498
0
} /* end H5D__farray_dst_dbg_context() */
499
500
/*-------------------------------------------------------------------------
501
 * Function:    H5D__farray_filt_fill
502
 *
503
 * Purpose:     Fill "missing elements" in block of elements
504
 *
505
 * Return:      Success:    non-negative
506
 *              Failure:    negative
507
 *
508
 *-------------------------------------------------------------------------
509
 */
510
static herr_t
511
H5D__farray_filt_fill(void *nat_blk, size_t nelmts)
512
0
{
513
0
    H5D_farray_filt_elmt_t fill_val = H5D_FARRAY_FILT_FILL; /* Value to fill elements with */
514
515
0
    FUNC_ENTER_PACKAGE_NOERR
516
517
    /* Sanity checks */
518
0
    assert(nat_blk);
519
0
    assert(nelmts);
520
0
    assert(sizeof(fill_val) == H5FA_CLS_FILT_CHUNK->nat_elmt_size);
521
522
0
    H5VM_array_fill(nat_blk, &fill_val, H5FA_CLS_FILT_CHUNK->nat_elmt_size, nelmts);
523
524
0
    FUNC_LEAVE_NOAPI(SUCCEED)
525
0
} /* end H5D__farray_filt_fill() */
526
527
/*-------------------------------------------------------------------------
528
 * Function:    H5D__farray_filt_encode
529
 *
530
 * Purpose:     Encode an element from "native" to "raw" form
531
 *
532
 * Return:      Success:    non-negative
533
 *              Failure:    negative
534
 *
535
 *-------------------------------------------------------------------------
536
 */
537
static herr_t
538
H5D__farray_filt_encode(void *_raw, const void *_elmt, size_t nelmts, void *_ctx)
539
0
{
540
0
    H5D_farray_ctx_t             *ctx = (H5D_farray_ctx_t *)_ctx; /* Fixed array callback context */
541
0
    uint8_t                      *raw = (uint8_t *)_raw;          /* Convenience pointer to raw elements */
542
0
    const H5D_farray_filt_elmt_t *elmt =
543
0
        (const H5D_farray_filt_elmt_t *)_elmt; /* Convenience pointer to native elements */
544
545
0
    FUNC_ENTER_PACKAGE_NOERR
546
547
    /* Sanity checks */
548
0
    assert(raw);
549
0
    assert(elmt);
550
0
    assert(nelmts);
551
0
    assert(ctx);
552
553
    /* Encode native elements into raw elements */
554
0
    while (nelmts) {
555
        /* Encode element */
556
        /* (advances 'raw' pointer) */
557
0
        H5F_addr_encode_len(ctx->file_addr_len, &raw, elmt->addr);
558
0
        UINT64ENCODE_VAR(raw, elmt->nbytes, ctx->chunk_size_len);
559
0
        UINT32ENCODE(raw, elmt->filter_mask);
560
561
        /* Advance native element pointer */
562
0
        elmt++;
563
564
        /* Decrement # of elements to encode */
565
0
        nelmts--;
566
0
    } /* end while */
567
568
0
    FUNC_LEAVE_NOAPI(SUCCEED)
569
0
} /* end H5D__farray_filt_encode() */
570
571
/*-------------------------------------------------------------------------
572
 * Function:    H5D__farray_filt_decode
573
 *
574
 * Purpose:     Decode an element from "raw" to "native" form
575
 *
576
 * Return:      Success:    non-negative
577
 *              Failure:    negative
578
 *
579
 *-------------------------------------------------------------------------
580
 */
581
static herr_t
582
H5D__farray_filt_decode(const void *_raw, void *_elmt, size_t nelmts, void *_ctx)
583
0
{
584
0
    H5D_farray_ctx_t       *ctx = (H5D_farray_ctx_t *)_ctx; /* Fixed array callback context */
585
0
    H5D_farray_filt_elmt_t *elmt =
586
0
        (H5D_farray_filt_elmt_t *)_elmt;        /* Convenience pointer to native elements */
587
0
    const uint8_t *raw = (const uint8_t *)_raw; /* Convenience pointer to raw elements */
588
589
0
    FUNC_ENTER_PACKAGE_NOERR
590
591
    /* Sanity checks */
592
0
    assert(raw);
593
0
    assert(elmt);
594
0
    assert(nelmts);
595
596
    /* Decode raw elements into native elements */
597
0
    while (nelmts) {
598
        /* Decode element */
599
        /* (advances 'raw' pointer) */
600
0
        H5F_addr_decode_len(ctx->file_addr_len, &raw, &elmt->addr);
601
0
        UINT64DECODE_VAR(raw, elmt->nbytes, ctx->chunk_size_len);
602
0
        UINT32DECODE(raw, elmt->filter_mask);
603
604
        /* Advance native element pointer */
605
0
        elmt++;
606
607
        /* Decrement # of elements to decode */
608
0
        nelmts--;
609
0
    } /* end while */
610
611
0
    FUNC_LEAVE_NOAPI(SUCCEED)
612
0
} /* end H5D__farray_filt_decode() */
613
614
/*-------------------------------------------------------------------------
615
 * Function:    H5D__farray_filt_debug
616
 *
617
 * Purpose:     Display an element for debugging
618
 *
619
 * Return:      Success:    non-negative
620
 *              Failure:    negative
621
 *
622
 *-------------------------------------------------------------------------
623
 */
624
static herr_t
625
H5D__farray_filt_debug(FILE *stream, int indent, int fwidth, hsize_t idx, const void *_elmt)
626
0
{
627
0
    const H5D_farray_filt_elmt_t *elmt =
628
0
        (const H5D_farray_filt_elmt_t *)_elmt; /* Convenience pointer to native elements */
629
0
    char temp_str[128];                        /* Temporary string, for formatting */
630
631
0
    FUNC_ENTER_PACKAGE_NOERR
632
633
    /* Sanity checks */
634
0
    assert(stream);
635
0
    assert(elmt);
636
637
    /* Print element */
638
0
    snprintf(temp_str, sizeof(temp_str), "Element #%" PRIuHSIZE ":", idx);
639
0
    fprintf(stream, "%*s%-*s {%" PRIuHADDR ", %" PRIuHSIZE ", %0x}\n", indent, "", fwidth, temp_str,
640
0
            elmt->addr, elmt->nbytes, elmt->filter_mask);
641
642
0
    FUNC_LEAVE_NOAPI(SUCCEED)
643
0
} /* end H5D__farray_filt_debug() */
644
645
/*-------------------------------------------------------------------------
646
 * Function:    H5D__farray_filt_crt_dbg_context
647
 *
648
 * Purpose:     Create context for debugging callback
649
 *              (get the layout message in the specified object header)
650
 *
651
 * Return:      Success:    non-NULL
652
 *              Failure:    NULL
653
 *
654
 *-------------------------------------------------------------------------
655
 */
656
static void *
657
H5D__farray_filt_crt_dbg_context(H5F_t *f, haddr_t obj_addr)
658
0
{
659
0
    H5D_farray_ctx_ud_t *dbg_ctx = NULL;     /* Context for fixed array callback */
660
0
    H5O_loc_t            obj_loc;            /* Pointer to an object's location */
661
0
    bool                 obj_opened = false; /* Flag to indicate that the object header was opened */
662
0
    H5O_layout_t         layout;             /* Layout message */
663
0
    void                *ret_value = NULL;   /* Return value */
664
665
0
    FUNC_ENTER_PACKAGE
666
667
    /* Sanity checks */
668
0
    assert(f);
669
0
    assert(H5_addr_defined(obj_addr));
670
671
    /* Allocate context for debugging callback */
672
0
    if (NULL == (dbg_ctx = H5FL_MALLOC(H5D_farray_ctx_ud_t)))
673
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate fixed array client callback context");
674
675
    /* Set up the object header location info */
676
0
    H5O_loc_reset(&obj_loc);
677
0
    obj_loc.file = f;
678
0
    obj_loc.addr = obj_addr;
679
680
    /* Open the object header where the layout message resides */
681
0
    if (H5O_open(&obj_loc) < 0)
682
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "can't open object header");
683
0
    obj_opened = true;
684
685
    /* Read the layout message */
686
0
    if (NULL == H5O_msg_read(&obj_loc, H5O_LAYOUT_ID, &layout))
687
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't get layout info");
688
689
    /* close the object header */
690
0
    if (H5O_close(&obj_loc, NULL) < 0)
691
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, NULL, "can't close object header");
692
0
    obj_opened = false;
693
694
    /* Create user data */
695
0
    dbg_ctx->f = f;
696
697
    /* Calculate length of chunk size field */
698
0
    H5D_FARRAY_FILT_COMPUTE_CHUNK_SIZE_LEN(dbg_ctx->chunk_size_len, f, &layout);
699
700
    /* Set return value */
701
0
    ret_value = dbg_ctx;
702
703
0
done:
704
    /* Cleanup on error */
705
0
    if (ret_value == NULL) {
706
        /* Release context structure */
707
0
        if (dbg_ctx)
708
0
            dbg_ctx = H5FL_FREE(H5D_farray_ctx_ud_t, dbg_ctx);
709
710
        /* Close object header */
711
0
        if (obj_opened)
712
0
            if (H5O_close(&obj_loc, NULL) < 0)
713
0
                HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, NULL, "can't close object header");
714
0
    }
715
0
    else
716
0
        assert(!obj_opened);
717
718
0
    FUNC_LEAVE_NOAPI(ret_value)
719
0
} /* end H5D__farray_filt_crt_dbg_context() */
720
721
/*-------------------------------------------------------------------------
722
 * Function:    H5D__farray_idx_depend
723
 *
724
 * Purpose:     Create flush dependency between fixed array and dataset's
725
 *              object header.
726
 *
727
 * Return:      Success:    non-negative
728
 *              Failure:    negative
729
 *
730
 *-------------------------------------------------------------------------
731
 */
732
static herr_t
733
H5D__farray_idx_depend(const H5D_chk_idx_info_t *idx_info)
734
0
{
735
0
    H5O_t              *oh = NULL;           /* Object header */
736
0
    H5O_loc_t           oloc;                /* Temporary object header location for dataset */
737
0
    H5AC_proxy_entry_t *oh_proxy;            /* Dataset's object header proxy */
738
0
    herr_t              ret_value = SUCCEED; /* Return value */
739
740
0
    FUNC_ENTER_PACKAGE
741
742
    /* Check args */
743
0
    assert(idx_info);
744
0
    assert(idx_info->f);
745
0
    assert(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE);
746
0
    assert(idx_info->pline);
747
0
    assert(idx_info->layout);
748
0
    assert(H5D_CHUNK_IDX_FARRAY == idx_info->layout->u.chunk.idx_type);
749
0
    assert(H5D_CHUNK_IDX_FARRAY == idx_info->layout->storage.u.chunk.idx_type);
750
0
    assert(H5_addr_defined(idx_info->layout->storage.u.chunk.idx_addr));
751
0
    assert(idx_info->layout->storage.u.chunk.u.farray.fa);
752
753
    /* Set up object header location for dataset */
754
0
    H5O_loc_reset(&oloc);
755
0
    oloc.file = idx_info->f;
756
0
    oloc.addr = idx_info->layout->storage.u.chunk.u.farray.dset_ohdr_addr;
757
758
    /* Get header */
759
0
    if (NULL == (oh = H5O_protect(&oloc, H5AC__READ_ONLY_FLAG, true)))
760
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTPROTECT, FAIL, "unable to protect object header");
761
762
    /* Retrieve the dataset's object header proxy */
763
0
    if (NULL == (oh_proxy = H5O_get_proxy(oh)))
764
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get dataset object header proxy");
765
766
    /* Make the fixed array a child flush dependency of the dataset's object header proxy */
767
0
    if (H5FA_depend(idx_info->layout->storage.u.chunk.u.farray.fa, oh_proxy) < 0)
768
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL,
769
0
                    "unable to create flush dependency on object header proxy");
770
771
0
done:
772
    /* Release the object header from the cache */
773
0
    if (oh && H5O_unprotect(&oloc, oh, H5AC__NO_FLAGS_SET) < 0)
774
0
        HDONE_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to release object header");
775
776
0
    FUNC_LEAVE_NOAPI(ret_value)
777
0
} /* end H5D__farray_idx_depend() */
778
779
/*-------------------------------------------------------------------------
780
 * Function:    H5D__farray_idx_init
781
 *
782
 * Purpose:     Initialize the indexing information for a dataset.
783
 *
784
 * Return:      Non-negative on success/Negative on failure
785
 *
786
 *-------------------------------------------------------------------------
787
 */
788
static herr_t
789
H5D__farray_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t H5_ATTR_UNUSED *space,
790
                     haddr_t dset_ohdr_addr)
791
1
{
792
1
    FUNC_ENTER_PACKAGE_NOERR
793
794
    /* Check args */
795
1
    assert(idx_info);
796
1
    assert(idx_info->layout);
797
1
    assert(H5_addr_defined(dset_ohdr_addr));
798
799
1
    idx_info->layout->storage.u.chunk.u.farray.dset_ohdr_addr = dset_ohdr_addr;
800
801
1
    FUNC_LEAVE_NOAPI(SUCCEED)
802
1
} /* end H5D__farray_idx_init() */
803
804
/*-------------------------------------------------------------------------
805
 * Function:    H5D__farray_idx_create
806
 *
807
 * Purpose:     Creates a new indexed-storage fixed array and initializes
808
 *              the layout struct with information about the storage.  The
809
 *              struct should be immediately written to the object header.
810
 *
811
 *              This function must be called before passing LAYOUT to any of
812
 *              the other indexed storage functions!
813
 *
814
 * Return:      Non-negative on success (with the LAYOUT argument initialized
815
 *              and ready to write to an object header). Negative on failure.
816
 *
817
 *-------------------------------------------------------------------------
818
 */
819
static herr_t
820
H5D__farray_idx_create(const H5D_chk_idx_info_t *idx_info)
821
0
{
822
0
    H5FA_create_t       cparam;                   /* Fixed array creation parameters */
823
0
    H5D_farray_ctx_ud_t udata;                    /* User data for fixed array create call */
824
0
    unsigned            chunk_size_len = 0;       /* Size of encoded chunk size */
825
0
    herr_t              ret_value      = SUCCEED; /* Return value */
826
827
0
    FUNC_ENTER_PACKAGE
828
829
    /* Check args */
830
0
    assert(idx_info);
831
0
    assert(idx_info->f);
832
0
    assert(idx_info->pline);
833
0
    assert(idx_info->layout);
834
0
    assert(!H5_addr_defined(idx_info->layout->storage.u.chunk.idx_addr));
835
0
    assert(NULL == idx_info->layout->storage.u.chunk.u.farray.fa);
836
0
    assert(idx_info->layout->u.chunk.nchunks);
837
838
    /* General parameters */
839
0
    H5D_FARRAY_COMPUTE_CHUNK_SIZE_LEN(chunk_size_len, idx_info);
840
0
    if (idx_info->pline->nused > 0) {
841
0
        cparam.cls           = H5FA_CLS_FILT_CHUNK;
842
0
        cparam.raw_elmt_size = (uint8_t)(H5F_SIZEOF_ADDR(idx_info->f) + chunk_size_len + 4);
843
0
    } /* end if */
844
0
    else {
845
0
        cparam.cls           = H5FA_CLS_CHUNK;
846
0
        cparam.raw_elmt_size = (uint8_t)H5F_SIZEOF_ADDR(idx_info->f);
847
0
    } /* end else */
848
0
    cparam.max_dblk_page_nelmts_bits = idx_info->layout->u.chunk.u.farray.cparam.max_dblk_page_nelmts_bits;
849
0
    assert(cparam.max_dblk_page_nelmts_bits > 0);
850
0
    cparam.nelmts = idx_info->layout->u.chunk.max_nchunks;
851
852
    /* Set up the user data */
853
0
    udata.f              = idx_info->f;
854
0
    udata.chunk_size_len = (size_t)chunk_size_len;
855
856
    /* Create the fixed array for the chunk index */
857
0
    if (NULL == (idx_info->layout->storage.u.chunk.u.farray.fa = H5FA_create(idx_info->f, &cparam, &udata)))
858
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create fixed array");
859
860
    /* Get the address of the fixed array in file */
861
0
    if (H5FA_get_addr(idx_info->layout->storage.u.chunk.u.farray.fa,
862
0
                      &(idx_info->layout->storage.u.chunk.idx_addr)) < 0)
863
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query fixed array address");
864
865
    /* Check for SWMR writes to the file */
866
0
    if (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
867
0
        if (H5D__farray_idx_depend(idx_info) < 0)
868
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL,
869
0
                        "unable to create flush dependency on object header");
870
871
0
done:
872
0
    FUNC_LEAVE_NOAPI(ret_value)
873
0
} /* end H5D__farray_idx_create() */
874
875
/*-------------------------------------------------------------------------
876
 * Function:    H5D__farray_idx_open
877
 *
878
 * Purpose:     Opens an existing fixed array and initializes
879
 *              the layout struct with information about the storage.
880
 *
881
 * Return:      Success:    non-negative
882
 *              Failure:    negative
883
 *
884
 *-------------------------------------------------------------------------
885
 */
886
static herr_t
887
H5D__farray_idx_open(const H5D_chk_idx_info_t *idx_info)
888
0
{
889
0
    H5D_farray_ctx_ud_t udata;               /* User data for fixed array open call */
890
0
    herr_t              ret_value = SUCCEED; /* Return value */
891
892
0
    FUNC_ENTER_PACKAGE
893
894
    /* Check args */
895
0
    assert(idx_info);
896
0
    assert(idx_info->f);
897
0
    assert(idx_info->pline);
898
0
    assert(idx_info->layout);
899
0
    assert(H5D_CHUNK_IDX_FARRAY == idx_info->layout->u.chunk.idx_type);
900
0
    assert(H5D_CHUNK_IDX_FARRAY == idx_info->layout->storage.u.chunk.idx_type);
901
0
    assert(H5_addr_defined(idx_info->layout->storage.u.chunk.idx_addr));
902
0
    assert(NULL == idx_info->layout->storage.u.chunk.u.farray.fa);
903
904
    /* Set up the user data */
905
0
    udata.f = idx_info->f;
906
907
    /* Compute number of bytes used to encode the chunk size */
908
0
    H5D_FARRAY_COMPUTE_CHUNK_SIZE_LEN(udata.chunk_size_len, idx_info);
909
910
    /* Open the fixed array for the chunk index */
911
0
    if (NULL == (idx_info->layout->storage.u.chunk.u.farray.fa =
912
0
                     H5FA_open(idx_info->f, idx_info->layout->storage.u.chunk.idx_addr, &udata)))
913
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open fixed array");
914
915
    /* Check for SWMR writes to the file */
916
0
    if (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
917
0
        if (H5D__farray_idx_depend(idx_info) < 0)
918
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL,
919
0
                        "unable to create flush dependency on object header");
920
921
0
done:
922
0
    FUNC_LEAVE_NOAPI(ret_value)
923
0
} /* end H5D__farray_idx_open() */
924
925
/*-------------------------------------------------------------------------
926
 * Function:    H5D__farray_idx_close
927
 *
928
 * Purpose:     Closes an existing fixed array.
929
 *
930
 * Return:      Success:    non-negative
931
 *              Failure:    negative
932
 *
933
 *-------------------------------------------------------------------------
934
 */
935
static herr_t
936
H5D__farray_idx_close(const H5D_chk_idx_info_t *idx_info)
937
0
{
938
0
    herr_t ret_value = SUCCEED; /* Return value */
939
940
0
    FUNC_ENTER_PACKAGE
941
942
0
    assert(idx_info);
943
0
    assert(idx_info->layout);
944
0
    assert(H5D_CHUNK_IDX_FARRAY == idx_info->layout->storage.u.chunk.idx_type);
945
0
    assert(idx_info->layout->storage.u.chunk.u.farray.fa);
946
947
0
    if (H5FA_close(idx_info->layout->storage.u.chunk.u.farray.fa) < 0)
948
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
949
0
    idx_info->layout->storage.u.chunk.u.farray.fa = NULL;
950
951
0
done:
952
0
    FUNC_LEAVE_NOAPI(ret_value)
953
0
} /* end H5D__farray_idx_close() */
954
955
/*-------------------------------------------------------------------------
956
 * Function:    H5D__farray_idx_is_open
957
 *
958
 * Purpose:     Query if the index is opened or not
959
 *
960
 * Return:      SUCCEED (can't fail)
961
 *
962
 *-------------------------------------------------------------------------
963
 */
964
static herr_t
965
H5D__farray_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open)
966
0
{
967
0
    FUNC_ENTER_PACKAGE_NOERR
968
969
0
    assert(idx_info);
970
0
    assert(idx_info->layout);
971
0
    assert(H5D_CHUNK_IDX_FARRAY == idx_info->layout->storage.u.chunk.idx_type);
972
0
    assert(is_open);
973
974
0
    *is_open = H5D_FARRAY_IDX_IS_OPEN(idx_info);
975
976
0
    FUNC_LEAVE_NOAPI(SUCCEED)
977
0
} /* end H5D__farray_idx_is_open() */
978
979
/*-------------------------------------------------------------------------
980
 * Function:    H5D__farray_idx_is_space_alloc
981
 *
982
 * Purpose:     Query if space is allocated for index method
983
 *
984
 * Return:      true/false
985
 *
986
 *-------------------------------------------------------------------------
987
 */
988
static bool
989
H5D__farray_idx_is_space_alloc(const H5O_storage_chunk_t *storage)
990
0
{
991
0
    FUNC_ENTER_PACKAGE_NOERR
992
993
    /* Check args */
994
0
    assert(storage);
995
996
0
    FUNC_LEAVE_NOAPI((bool)H5_addr_defined(storage->idx_addr))
997
0
} /* end H5D__farray_idx_is_space_alloc() */
998
999
/*-------------------------------------------------------------------------
1000
 * Function:    H5D__farray_idx_insert
1001
 *
1002
 * Purpose:     Insert chunk address into the indexing structure.
1003
 *
1004
 * Return:      Non-negative on success/Negative on failure
1005
 *
1006
 *-------------------------------------------------------------------------
1007
 */
1008
static herr_t
1009
H5D__farray_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
1010
                       const H5D_t H5_ATTR_UNUSED *dset)
1011
0
{
1012
0
    H5FA_t *fa;                  /* Pointer to fixed array structure */
1013
0
    herr_t  ret_value = SUCCEED; /* Return value */
1014
1015
0
    FUNC_ENTER_PACKAGE
1016
1017
    /* Sanity checks */
1018
0
    assert(idx_info);
1019
0
    assert(idx_info->f);
1020
0
    assert(idx_info->pline);
1021
0
    assert(idx_info->layout);
1022
0
    assert(H5_addr_defined(idx_info->layout->storage.u.chunk.idx_addr));
1023
0
    assert(udata);
1024
1025
    /* Check if the fixed array is open yet */
1026
0
    if (!H5D_FARRAY_IDX_IS_OPEN(idx_info)) {
1027
        /* Open the fixed array in file */
1028
0
        if (H5D__farray_idx_open(idx_info) < 0)
1029
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
1030
0
    }
1031
0
    else /* Patch the top level file pointer contained in fa if needed */
1032
0
        H5FA_patch_file(idx_info->layout->storage.u.chunk.u.farray.fa, idx_info->f);
1033
1034
    /* Set convenience pointer to fixed array structure */
1035
0
    fa = idx_info->layout->storage.u.chunk.u.farray.fa;
1036
1037
0
    if (!H5_addr_defined(udata->chunk_block.offset))
1038
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "The chunk should have allocated already");
1039
0
    if (udata->chunk_idx != (udata->chunk_idx & 0xffffffff)) /* negative value */
1040
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "chunk index must be less than 2^32");
1041
1042
    /* Check for filters on chunks */
1043
0
    if (idx_info->pline->nused > 0) {
1044
0
        H5D_farray_filt_elmt_t elmt; /* Fixed array element */
1045
1046
0
        elmt.addr        = udata->chunk_block.offset;
1047
0
        elmt.nbytes      = udata->chunk_block.length;
1048
0
        elmt.filter_mask = udata->filter_mask;
1049
1050
        /* Set the info for the chunk */
1051
0
        if (H5FA_set(fa, udata->chunk_idx, &elmt) < 0)
1052
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set chunk info");
1053
0
    } /* end if */
1054
0
    else {
1055
        /* Set the address for the chunk */
1056
0
        if (H5FA_set(fa, udata->chunk_idx, &udata->chunk_block.offset) < 0)
1057
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set chunk address");
1058
0
    } /* end else */
1059
1060
0
done:
1061
0
    FUNC_LEAVE_NOAPI(ret_value)
1062
0
} /* H5D__farray_idx_insert() */
1063
1064
/*-------------------------------------------------------------------------
1065
 * Function:    H5D__farray_idx_get_addr
1066
 *
1067
 * Purpose:     Get the file address of a chunk if file space has been
1068
 *              assigned.  Save the retrieved information in the udata
1069
 *              supplied.
1070
 *
1071
 * Return:      Non-negative on success/Negative on failure
1072
 *
1073
 *-------------------------------------------------------------------------
1074
 */
1075
static herr_t
1076
H5D__farray_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
1077
0
{
1078
0
    H5FA_t *fa;                  /* Pointer to fixed array structure */
1079
0
    hsize_t idx;                 /* Array index of chunk */
1080
0
    herr_t  ret_value = SUCCEED; /* Return value */
1081
1082
0
    FUNC_ENTER_PACKAGE
1083
1084
    /* Sanity checks */
1085
0
    assert(idx_info);
1086
0
    assert(idx_info->f);
1087
0
    assert(idx_info->pline);
1088
0
    assert(idx_info->layout);
1089
0
    assert(H5_addr_defined(idx_info->layout->storage.u.chunk.idx_addr));
1090
0
    assert(udata);
1091
1092
    /* Check if the fixed array is open yet */
1093
0
    if (!H5D_FARRAY_IDX_IS_OPEN(idx_info)) {
1094
        /* Open the fixed array in file */
1095
0
        if (H5D__farray_idx_open(idx_info) < 0)
1096
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
1097
0
    }
1098
0
    else /* Patch the top level file pointer contained in fa if needed */
1099
0
        H5FA_patch_file(idx_info->layout->storage.u.chunk.u.farray.fa, idx_info->f);
1100
1101
    /* Set convenience pointer to fixed array structure */
1102
0
    fa = idx_info->layout->storage.u.chunk.u.farray.fa;
1103
1104
    /* Calculate the index of this chunk */
1105
0
    idx = H5VM_array_offset_pre((idx_info->layout->u.chunk.ndims - 1),
1106
0
                                idx_info->layout->u.chunk.max_down_chunks, udata->common.scaled);
1107
1108
0
    udata->chunk_idx = idx;
1109
1110
    /* Check for filters on chunks */
1111
0
    if (idx_info->pline->nused > 0) {
1112
0
        H5D_farray_filt_elmt_t elmt; /* Fixed array element */
1113
1114
        /* Get the information for the chunk */
1115
0
        if (H5FA_get(fa, idx, &elmt) < 0)
1116
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info");
1117
1118
        /* Set the info for the chunk */
1119
0
        udata->chunk_block.offset = elmt.addr;
1120
0
        udata->chunk_block.length = elmt.nbytes;
1121
0
        udata->filter_mask        = elmt.filter_mask;
1122
0
    } /* end if */
1123
0
    else {
1124
        /* Get the address for the chunk */
1125
0
        if (H5FA_get(fa, idx, &udata->chunk_block.offset) < 0)
1126
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
1127
1128
        /* Update the other (constant) information for the chunk */
1129
0
        udata->chunk_block.length = idx_info->layout->u.chunk.size;
1130
0
        udata->filter_mask        = 0;
1131
0
    } /* end else */
1132
1133
0
    if (!H5_addr_defined(udata->chunk_block.offset))
1134
0
        udata->chunk_block.length = 0;
1135
1136
0
done:
1137
0
    FUNC_LEAVE_NOAPI(ret_value)
1138
0
} /* H5D__farray_idx_get_addr() */
1139
1140
/*-------------------------------------------------------------------------
1141
 * Function:    H5D__farray_idx_load_metadata
1142
 *
1143
 * Purpose:     Load additional chunk index metadata beyond the chunk index
1144
 *              itself.
1145
 *
1146
 * Return:      Non-negative on success/Negative on failure
1147
 *
1148
 *-------------------------------------------------------------------------
1149
 */
1150
static herr_t
1151
H5D__farray_idx_load_metadata(const H5D_chk_idx_info_t *idx_info)
1152
0
{
1153
0
    H5D_chunk_ud_t chunk_ud;
1154
0
    hsize_t        scaled[H5O_LAYOUT_NDIMS] = {0};
1155
0
    herr_t         ret_value                = SUCCEED;
1156
1157
0
    FUNC_ENTER_PACKAGE
1158
1159
    /*
1160
     * After opening a dataset that uses a fixed array, the
1161
     * fixed array data block will generally not be read in
1162
     * until an element is looked up for the first time. Since
1163
     * there isn't currently a good way of controlling that
1164
     * explicitly, perform a fake lookup of a chunk to cause
1165
     * it to be read in.
1166
     */
1167
0
    chunk_ud.common.layout  = &idx_info->layout->u.chunk;
1168
0
    chunk_ud.common.storage = &idx_info->layout->storage.u.chunk;
1169
0
    chunk_ud.common.scaled  = scaled;
1170
1171
0
    chunk_ud.chunk_block.offset = HADDR_UNDEF;
1172
0
    chunk_ud.chunk_block.length = 0;
1173
0
    chunk_ud.filter_mask        = 0;
1174
0
    chunk_ud.new_unfilt_chunk   = false;
1175
0
    chunk_ud.idx_hint           = UINT_MAX;
1176
1177
0
    if (H5D__farray_idx_get_addr(idx_info, &chunk_ud) < 0)
1178
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't load fixed array data block");
1179
1180
0
done:
1181
0
    FUNC_LEAVE_NOAPI(ret_value)
1182
0
} /* H5D__farray_idx_load_metadata() */
1183
1184
/*-------------------------------------------------------------------------
1185
 * Function:    H5D__farray_idx_iterate_cb
1186
 *
1187
 * Purpose:     Callback routine for fixed array element iteration.
1188
 *
1189
 * Return:      Non-negative on success/Negative on failure
1190
 *
1191
 *-------------------------------------------------------------------------
1192
 */
1193
static int
1194
H5D__farray_idx_iterate_cb(hsize_t H5_ATTR_UNUSED idx, const void *_elmt, void *_udata)
1195
0
{
1196
0
    H5D_farray_it_ud_t *udata = (H5D_farray_it_ud_t *)_udata; /* User data */
1197
0
    unsigned            ndims;                                /* Rank of chunk */
1198
0
    int                 curr_dim;                             /* Current dimension */
1199
0
    int                 ret_value = H5_ITER_CONT;             /* Return value */
1200
1201
0
    FUNC_ENTER_PACKAGE_NOERR
1202
1203
    /* Compose generic chunk record for callback */
1204
0
    if (udata->filtered) {
1205
0
        const H5D_farray_filt_elmt_t *filt_elmt = (const H5D_farray_filt_elmt_t *)_elmt;
1206
1207
0
        udata->chunk_rec.chunk_addr  = filt_elmt->addr;
1208
0
        udata->chunk_rec.nbytes      = filt_elmt->nbytes;
1209
0
        udata->chunk_rec.filter_mask = filt_elmt->filter_mask;
1210
0
    } /* end if */
1211
0
    else
1212
0
        udata->chunk_rec.chunk_addr = *(const haddr_t *)_elmt;
1213
1214
    /* Make "generic chunk" callback */
1215
0
    if (H5_addr_defined(udata->chunk_rec.chunk_addr))
1216
0
        if ((ret_value = (udata->cb)(&udata->chunk_rec, udata->udata)) < 0)
1217
0
            HERROR(H5E_DATASET, H5E_CALLBACK, "failure in generic chunk iterator callback");
1218
1219
    /* Update coordinates of chunk in dataset */
1220
0
    ndims = udata->common.layout->ndims - 1;
1221
0
    assert(ndims > 0);
1222
0
    curr_dim = (int)(ndims - 1);
1223
0
    while (curr_dim >= 0) {
1224
        /* Increment coordinate in current dimension */
1225
0
        udata->chunk_rec.scaled[curr_dim]++;
1226
1227
        /* Check if we went off the end of the current dimension */
1228
0
        if (udata->chunk_rec.scaled[curr_dim] >= udata->common.layout->max_chunks[curr_dim]) {
1229
            /* Reset coordinate & move to next faster dimension */
1230
0
            udata->chunk_rec.scaled[curr_dim] = 0;
1231
0
            curr_dim--;
1232
0
        } /* end if */
1233
0
        else
1234
0
            break;
1235
0
    } /* end while */
1236
1237
0
    FUNC_LEAVE_NOAPI(ret_value)
1238
0
} /* H5D__farray_idx_iterate_cb() */
1239
1240
/*-------------------------------------------------------------------------
1241
 * Function:    H5D__farray_idx_iterate
1242
 *
1243
 * Purpose:     Iterate over the chunks in an index, making a callback
1244
 *              for each one.
1245
 *
1246
 * Return:      Non-negative on success/Negative on failure
1247
 *
1248
 *-------------------------------------------------------------------------
1249
 */
1250
static int
1251
H5D__farray_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb, void *chunk_udata)
1252
0
{
1253
0
    H5FA_t     *fa;               /* Pointer to fixed array structure */
1254
0
    H5FA_stat_t fa_stat;          /* Fixed array statistics */
1255
0
    int         ret_value = FAIL; /* Return value */
1256
1257
0
    FUNC_ENTER_PACKAGE
1258
1259
    /* Sanity checks */
1260
0
    assert(idx_info);
1261
0
    assert(idx_info->f);
1262
0
    assert(idx_info->pline);
1263
0
    assert(idx_info->layout);
1264
0
    assert(H5_addr_defined(idx_info->layout->storage.u.chunk.idx_addr));
1265
0
    assert(chunk_cb);
1266
0
    assert(chunk_udata);
1267
1268
    /* Check if the fixed array is open yet */
1269
0
    if (!H5D_FARRAY_IDX_IS_OPEN(idx_info)) {
1270
        /* Open the fixed array in file */
1271
0
        if (H5D__farray_idx_open(idx_info) < 0)
1272
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
1273
0
    }
1274
0
    else /* Patch the top level file pointer contained in fa if needed */
1275
0
        H5FA_patch_file(idx_info->layout->storage.u.chunk.u.farray.fa, idx_info->f);
1276
1277
    /* Set convenience pointer to fixed array structure */
1278
0
    fa = idx_info->layout->storage.u.chunk.u.farray.fa;
1279
1280
    /* Get the fixed array statistics */
1281
0
    if (H5FA_get_stats(fa, &fa_stat) < 0)
1282
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query fixed array statistics");
1283
1284
    /* Check if there are any array elements */
1285
0
    if (fa_stat.nelmts > 0) {
1286
0
        H5D_farray_it_ud_t udata; /* User data for iteration callback */
1287
1288
        /* Initialize userdata */
1289
0
        memset(&udata, 0, sizeof udata);
1290
0
        udata.common.layout  = &idx_info->layout->u.chunk;
1291
0
        udata.common.storage = &idx_info->layout->storage.u.chunk;
1292
0
        memset(&udata.chunk_rec, 0, sizeof(udata.chunk_rec));
1293
0
        udata.filtered = (idx_info->pline->nused > 0);
1294
0
        if (!udata.filtered) {
1295
0
            udata.chunk_rec.nbytes      = idx_info->layout->u.chunk.size;
1296
0
            udata.chunk_rec.filter_mask = 0;
1297
0
        } /* end if */
1298
0
        udata.cb    = chunk_cb;
1299
0
        udata.udata = chunk_udata;
1300
1301
        /* Iterate over the fixed array elements */
1302
0
        if ((ret_value = H5FA_iterate(fa, H5D__farray_idx_iterate_cb, &udata)) < 0)
1303
0
            HERROR(H5E_DATASET, H5E_BADITER, "unable to iterate over fixed array chunk index");
1304
0
    } /* end if */
1305
1306
0
done:
1307
0
    FUNC_LEAVE_NOAPI(ret_value)
1308
0
} /* end H5D__farray_idx_iterate() */
1309
1310
/*-------------------------------------------------------------------------
1311
 * Function:    H5D__farray_idx_remove
1312
 *
1313
 * Purpose:     Remove chunk from index.
1314
 *
1315
 * Return:      Non-negative on success/Negative on failure
1316
 *
1317
 *-------------------------------------------------------------------------
1318
 */
1319
static herr_t
1320
H5D__farray_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata)
1321
0
{
1322
0
    H5FA_t *fa;                  /* Pointer to fixed array structure */
1323
0
    hsize_t idx;                 /* Array index of chunk */
1324
0
    herr_t  ret_value = SUCCEED; /* Return value */
1325
1326
0
    FUNC_ENTER_PACKAGE
1327
1328
    /* Sanity checks */
1329
0
    assert(idx_info);
1330
0
    assert(idx_info->f);
1331
0
    assert(idx_info->pline);
1332
0
    assert(idx_info->layout);
1333
0
    assert(H5_addr_defined(idx_info->layout->storage.u.chunk.idx_addr));
1334
0
    assert(udata);
1335
1336
    /* Check if the fixed array is open yet */
1337
0
    if (!H5D_FARRAY_IDX_IS_OPEN(idx_info)) {
1338
        /* Open the fixed array in file */
1339
0
        if (H5D__farray_idx_open(idx_info) < 0)
1340
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
1341
0
    }
1342
0
    else /* Patch the top level file pointer contained in fa if needed */
1343
0
        if (H5FA_patch_file(idx_info->layout->storage.u.chunk.u.farray.fa, idx_info->f) < 0)
1344
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch fixed array file pointer");
1345
1346
    /* Set convenience pointer to fixed array structure */
1347
0
    fa = idx_info->layout->storage.u.chunk.u.farray.fa;
1348
1349
    /* Calculate the index of this chunk */
1350
0
    idx = H5VM_array_offset_pre((idx_info->layout->u.chunk.ndims - 1),
1351
0
                                idx_info->layout->u.chunk.max_down_chunks, udata->scaled);
1352
1353
    /* Check for filters on chunks */
1354
0
    if (idx_info->pline->nused > 0) {
1355
0
        H5D_farray_filt_elmt_t elmt; /* Fixed array element */
1356
1357
        /* Get the info about the chunk for the index */
1358
0
        if (H5FA_get(fa, idx, &elmt) < 0)
1359
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info");
1360
1361
        /* Remove raw data chunk from file if not doing SWMR writes */
1362
0
        assert(H5_addr_defined(elmt.addr));
1363
0
        if (!(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE))
1364
0
            if (H5MF_xfree(idx_info->f, H5FD_MEM_DRAW, elmt.addr, elmt.nbytes) < 0)
1365
0
                HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to free chunk");
1366
1367
        /* Reset the info about the chunk for the index */
1368
0
        elmt.addr        = HADDR_UNDEF;
1369
0
        elmt.nbytes      = 0;
1370
0
        elmt.filter_mask = 0;
1371
0
        if (H5FA_set(fa, idx, &elmt) < 0)
1372
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to reset chunk info");
1373
0
    } /* end if */
1374
0
    else {
1375
0
        haddr_t addr = HADDR_UNDEF; /* Chunk address */
1376
1377
        /* Get the address of the chunk for the index */
1378
0
        if (H5FA_get(fa, idx, &addr) < 0)
1379
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
1380
1381
        /* Remove raw data chunk from file if not doing SWMR writes */
1382
0
        assert(H5_addr_defined(addr));
1383
0
        if (!(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE))
1384
0
            if (H5MF_xfree(idx_info->f, H5FD_MEM_DRAW, addr, idx_info->layout->u.chunk.size) < 0)
1385
0
                HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to free chunk");
1386
1387
        /* Reset the address of the chunk for the index */
1388
0
        addr = HADDR_UNDEF;
1389
0
        if (H5FA_set(fa, idx, &addr) < 0)
1390
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to reset chunk address");
1391
0
    } /* end else */
1392
1393
0
done:
1394
0
    FUNC_LEAVE_NOAPI(ret_value)
1395
0
} /* H5D__farray_idx_remove() */
1396
1397
/*-------------------------------------------------------------------------
1398
 * Function:    H5D__farray_idx_delete_cb
1399
 *
1400
 * Purpose:     Delete space for chunk in file
1401
 *
1402
 * Return:      Success:    Non-negative
1403
 *              Failure:    negative
1404
 *
1405
 *-------------------------------------------------------------------------
1406
 */
1407
static int
1408
H5D__farray_idx_delete_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
1409
0
{
1410
0
    H5F_t *f         = (H5F_t *)_udata; /* User data for callback */
1411
0
    int    ret_value = H5_ITER_CONT;    /* Return value */
1412
1413
0
    FUNC_ENTER_PACKAGE
1414
1415
    /* Sanity checks */
1416
0
    assert(chunk_rec);
1417
0
    assert(H5_addr_defined(chunk_rec->chunk_addr));
1418
0
    assert(chunk_rec->nbytes > 0);
1419
0
    assert(f);
1420
1421
    /* Remove raw data chunk from file */
1422
0
    if (H5MF_xfree(f, H5FD_MEM_DRAW, chunk_rec->chunk_addr, chunk_rec->nbytes) < 0)
1423
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, H5_ITER_ERROR, "unable to free chunk");
1424
1425
0
done:
1426
0
    FUNC_LEAVE_NOAPI(ret_value)
1427
0
} /* end H5D__farray_idx_delete_cb() */
1428
1429
/*-------------------------------------------------------------------------
1430
 * Function:    H5D__farray_idx_delete
1431
 *
1432
 * Purpose:     Delete index and raw data storage for entire dataset
1433
 *              (i.e. all chunks)
1434
 *
1435
 * Return:      Success:    Non-negative
1436
 *              Failure:    negative
1437
 *
1438
 *-------------------------------------------------------------------------
1439
 */
1440
static herr_t
1441
H5D__farray_idx_delete(const H5D_chk_idx_info_t *idx_info)
1442
0
{
1443
0
    herr_t ret_value = SUCCEED; /* Return value */
1444
1445
0
    FUNC_ENTER_PACKAGE
1446
1447
    /* Sanity checks */
1448
0
    assert(idx_info);
1449
0
    assert(idx_info->f);
1450
0
    assert(idx_info->pline);
1451
0
    assert(idx_info->layout);
1452
1453
    /* Check if the index data structure has been allocated */
1454
0
    if (H5_addr_defined(idx_info->layout->storage.u.chunk.idx_addr)) {
1455
0
        H5D_farray_ctx_ud_t ctx_udata; /* User data for fixed array open call */
1456
1457
        /* Iterate over the chunk addresses in the fixed array, deleting each chunk */
1458
0
        if (H5D__farray_idx_iterate(idx_info, H5D__farray_idx_delete_cb, idx_info->f) < 0)
1459
0
            HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk addresses");
1460
1461
        /* Close fixed array */
1462
0
        if (H5D__farray_idx_close(idx_info) < 0)
1463
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
1464
1465
        /* Set up the user data */
1466
0
        ctx_udata.f = idx_info->f;
1467
1468
        /* Compute number of bytes used to encode the chunk size */
1469
0
        H5D_FARRAY_COMPUTE_CHUNK_SIZE_LEN(ctx_udata.chunk_size_len, idx_info);
1470
1471
        /* Delete fixed array */
1472
0
        if (H5FA_delete(idx_info->f, idx_info->layout->storage.u.chunk.idx_addr, &ctx_udata) < 0)
1473
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to delete chunk fixed array");
1474
0
        idx_info->layout->storage.u.chunk.idx_addr = HADDR_UNDEF;
1475
0
    } /* end if */
1476
0
    else
1477
0
        assert(NULL == idx_info->layout->storage.u.chunk.u.farray.fa);
1478
1479
0
done:
1480
0
    FUNC_LEAVE_NOAPI(ret_value)
1481
0
} /* end H5D__farray_idx_delete() */
1482
1483
/*-------------------------------------------------------------------------
1484
 * Function:    H5D__farray_idx_copy_setup
1485
 *
1486
 * Purpose:     Set up any necessary information for copying chunks
1487
 *
1488
 * Return:      Non-negative on success/Negative on failure
1489
 *
1490
 *-------------------------------------------------------------------------
1491
 */
1492
static herr_t
1493
H5D__farray_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src, const H5D_chk_idx_info_t *idx_info_dst)
1494
0
{
1495
0
    herr_t ret_value = SUCCEED; /* Return value */
1496
1497
0
    FUNC_ENTER_PACKAGE
1498
1499
    /* Check args */
1500
0
    assert(idx_info_src);
1501
0
    assert(idx_info_src->f);
1502
0
    assert(idx_info_src->pline);
1503
0
    assert(idx_info_src->layout);
1504
0
    assert(idx_info_dst);
1505
0
    assert(idx_info_dst->f);
1506
0
    assert(idx_info_dst->pline);
1507
0
    assert(idx_info_dst->layout);
1508
0
    assert(!H5_addr_defined(idx_info_dst->layout->storage.u.chunk.idx_addr));
1509
1510
    /* Check if the source fixed array is open yet */
1511
0
    if (!H5D_FARRAY_IDX_IS_OPEN(idx_info_src)) {
1512
        /* Open the fixed array in file */
1513
0
        if (H5D__farray_idx_open(idx_info_src) < 0)
1514
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
1515
0
    }
1516
1517
    /* Set copied metadata tag */
1518
0
    H5_BEGIN_TAG(H5AC__COPIED_TAG)
1519
1520
    /* Create the fixed array that describes chunked storage in the dest. file */
1521
0
    if (H5D__farray_idx_create(idx_info_dst) < 0)
1522
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize chunked storage");
1523
0
    assert(H5_addr_defined(idx_info_dst->layout->storage.u.chunk.idx_addr));
1524
1525
    /* Reset metadata tag */
1526
0
    H5_END_TAG
1527
1528
0
done:
1529
0
    FUNC_LEAVE_NOAPI(ret_value)
1530
0
} /* end H5D__farray_idx_copy_setup() */
1531
1532
/*-------------------------------------------------------------------------
1533
 * Function:    H5D__farray_idx_copy_shutdown
1534
 *
1535
 * Purpose:     Shutdown any information from copying chunks
1536
 *
1537
 * Return:      Non-negative on success/Negative on failure
1538
 *
1539
 *-------------------------------------------------------------------------
1540
 */
1541
static herr_t
1542
H5D__farray_idx_copy_shutdown(H5O_storage_chunk_t *storage_src, H5O_storage_chunk_t *storage_dst)
1543
0
{
1544
0
    herr_t ret_value = SUCCEED; /* Return value */
1545
1546
0
    FUNC_ENTER_PACKAGE
1547
1548
    /* Check args */
1549
0
    assert(storage_src);
1550
0
    assert(storage_src->u.farray.fa);
1551
0
    assert(storage_dst);
1552
0
    assert(storage_dst->u.farray.fa);
1553
1554
    /* Close fixed arrays */
1555
0
    if (H5FA_close(storage_src->u.farray.fa) < 0)
1556
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
1557
0
    storage_src->u.farray.fa = NULL;
1558
0
    if (H5FA_close(storage_dst->u.farray.fa) < 0)
1559
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
1560
0
    storage_dst->u.farray.fa = NULL;
1561
1562
0
done:
1563
0
    FUNC_LEAVE_NOAPI(ret_value)
1564
0
} /* end H5D__farray_idx_copy_shutdown() */
1565
1566
/*-------------------------------------------------------------------------
1567
 * Function:    H5D__farray_idx_size
1568
 *
1569
 * Purpose:     Retrieve the amount of index storage for chunked dataset
1570
 *
1571
 * Return:      Success:        Non-negative
1572
 *              Failure:        negative
1573
 *
1574
 *-------------------------------------------------------------------------
1575
 */
1576
static herr_t
1577
H5D__farray_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size)
1578
0
{
1579
0
    H5FA_t     *fa;                  /* Pointer to fixed array structure */
1580
0
    H5FA_stat_t fa_stat;             /* Fixed array statistics */
1581
0
    herr_t      ret_value = SUCCEED; /* Return value */
1582
1583
0
    FUNC_ENTER_PACKAGE
1584
1585
    /* Check args */
1586
0
    assert(idx_info);
1587
0
    assert(idx_info->f);
1588
0
    assert(idx_info->pline);
1589
0
    assert(idx_info->layout);
1590
0
    assert(H5_addr_defined(idx_info->layout->storage.u.chunk.idx_addr));
1591
0
    assert(index_size);
1592
1593
    /* Open the fixed array in file */
1594
0
    if (H5D__farray_idx_open(idx_info) < 0)
1595
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
1596
1597
    /* Set convenience pointer to fixed array structure */
1598
0
    fa = idx_info->layout->storage.u.chunk.u.farray.fa;
1599
1600
    /* Get the fixed array statistics */
1601
0
    if (H5FA_get_stats(fa, &fa_stat) < 0)
1602
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query fixed array statistics");
1603
1604
0
    *index_size = fa_stat.hdr_size;
1605
0
    *index_size += fa_stat.dblk_size;
1606
1607
0
done:
1608
0
    if (idx_info->layout->storage.u.chunk.u.farray.fa) {
1609
0
        if (H5D__farray_idx_close(idx_info) < 0)
1610
0
            HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
1611
0
    } /* end if */
1612
1613
0
    FUNC_LEAVE_NOAPI(ret_value)
1614
0
} /* end H5D__farray_idx_size() */
1615
1616
/*-------------------------------------------------------------------------
1617
 * Function:    H5D__farray_idx_reset
1618
 *
1619
 * Purpose:     Reset indexing information.
1620
 *
1621
 * Return:      Non-negative on success/Negative on failure
1622
 *
1623
 *-------------------------------------------------------------------------
1624
 */
1625
static herr_t
1626
H5D__farray_idx_reset(H5O_storage_chunk_t *storage, bool reset_addr)
1627
1
{
1628
1
    FUNC_ENTER_PACKAGE_NOERR
1629
1630
    /* Check args */
1631
1
    assert(storage);
1632
1633
    /* Reset index info */
1634
1
    if (reset_addr)
1635
0
        storage->idx_addr = HADDR_UNDEF;
1636
1
    storage->u.farray.fa = NULL;
1637
1638
1
    FUNC_LEAVE_NOAPI(SUCCEED)
1639
1
} /* end H5D__farray_idx_reset() */
1640
1641
/*-------------------------------------------------------------------------
1642
 * Function:    H5D__farray_idx_dump
1643
 *
1644
 * Purpose:     Dump indexing information to a stream.
1645
 *
1646
 * Return:      Non-negative on success/Negative on failure
1647
 *
1648
 *-------------------------------------------------------------------------
1649
 */
1650
static herr_t
1651
H5D__farray_idx_dump(const H5O_storage_chunk_t *storage, FILE *stream)
1652
0
{
1653
0
    FUNC_ENTER_PACKAGE_NOERR
1654
1655
    /* Check args */
1656
0
    assert(storage);
1657
0
    assert(stream);
1658
1659
0
    fprintf(stream, "    Address: %" PRIuHADDR "\n", storage->idx_addr);
1660
1661
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1662
0
} /* end H5D__farray_idx_dump() */
1663
1664
/*-------------------------------------------------------------------------
1665
 * Function:    H5D__farray_idx_dest
1666
 *
1667
 * Purpose:     Release indexing information in memory.
1668
 *
1669
 * Return:      Non-negative on success/Negative on failure
1670
 *
1671
 *-------------------------------------------------------------------------
1672
 */
1673
static herr_t
1674
H5D__farray_idx_dest(const H5D_chk_idx_info_t *idx_info)
1675
1
{
1676
1
    herr_t ret_value = SUCCEED; /* Return value */
1677
1678
1
    FUNC_ENTER_PACKAGE
1679
1680
    /* Check args */
1681
1
    assert(idx_info);
1682
1
    assert(idx_info->f);
1683
1
    assert(idx_info->layout);
1684
1685
    /* Check if the fixed array is open */
1686
1
    if (H5D_FARRAY_IDX_IS_OPEN(idx_info)) {
1687
        /* Patch the top level file pointer contained in fa if needed */
1688
0
        if (H5FA_patch_file(idx_info->layout->storage.u.chunk.u.farray.fa, idx_info->f) < 0)
1689
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch fixed array file pointer");
1690
1691
        /* Close fixed array */
1692
0
        if (H5D__farray_idx_close(idx_info) < 0)
1693
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
1694
0
    } /* end if */
1695
1696
1
done:
1697
1
    FUNC_LEAVE_NOAPI(ret_value)
1698
1
} /* end H5D__farray_idx_dest() */