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