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