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