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