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