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