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 /****************/
15 /* Module Setup */
16 /****************/
17 
18 #include "H5Dmodule.h"          /* This source code file is part of the H5D module */
19 
20 
21 /***********/
22 /* Headers */
23 /***********/
24 #include "H5private.h"        /* Generic Functions */
25 #include "H5Dpkg.h"           /* Datasets */
26 #include "H5CXprivate.h"      /* API Contexts */
27 #include "H5Eprivate.h"       /* Error handling */
28 #include "H5FLprivate.h"      /* Free Lists */
29 #include "H5FOprivate.h"      /* File objects */
30 #include "H5Iprivate.h"       /* IDs */
31 #include "H5Lprivate.h"       /* Links */
32 #include "H5MMprivate.h"      /* Memory management */
33 
34 
35 /****************/
36 /* Local Macros */
37 /****************/
38 
39 
40 /******************/
41 /* Local Typedefs */
42 /******************/
43 
44 
45 /********************/
46 /* Local Prototypes */
47 /********************/
48 
49 /* General stuff */
50 static H5D_shared_t *H5D__new(hid_t dcpl_id, hbool_t creating, hbool_t vl_type);
51 static herr_t H5D__init_type(H5F_t *file, const H5D_t *dset, hid_t type_id,
52     const H5T_t *type);
53 static herr_t H5D__cache_dataspace_info(const H5D_t *dset);
54 static herr_t H5D__init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space);
55 static herr_t H5D__update_oh_info(H5F_t *file, H5D_t *dset, hid_t dapl_id);
56 static herr_t H5D__build_file_prefix(const H5D_t *dset, hid_t dapl_id,
57     const char *prefix_type, char **file_prefix);
58 static herr_t H5D__open_oid(H5D_t *dataset, hid_t dapl_id);
59 static herr_t H5D__init_storage(const H5D_io_info_t *io_info, hbool_t full_overwrite,
60         hsize_t old_dim[]);
61 static herr_t H5D__get_storage_size_real(const H5D_t *dset, hsize_t *storage_size);
62 static herr_t H5D__append_flush_setup(H5D_t *dset, hid_t dapl_id);
63 static herr_t H5D__close_cb(H5D_t *dataset);
64 
65 /*********************/
66 /* Package Variables */
67 /*********************/
68 
69 /* Declare a free list to manage blocks of VL data */
70 H5FL_BLK_DEFINE(vlen_vl_buf);
71 
72 /* Declare a free list to manage other blocks of VL data */
73 H5FL_BLK_DEFINE(vlen_fl_buf);
74 
75 
76 /*****************************/
77 /* Library Private Variables */
78 /*****************************/
79 
80 
81 /*******************/
82 /* Local Variables */
83 /*******************/
84 
85 /* Declare a free list to manage the H5D_t and H5D_shared_t structs */
86 H5FL_DEFINE_STATIC(H5D_t);
87 H5FL_DEFINE_STATIC(H5D_shared_t);
88 
89 /* Declare the external PQ free list for the sieve buffer information */
90 H5FL_BLK_EXTERN(sieve_buf);
91 
92 /* Declare the external free list to manage the H5D_chunk_info_t struct */
93 H5FL_EXTERN(H5D_chunk_info_t);
94 
95 /* Declare extern the free list to manage blocks of type conversion data */
96 H5FL_BLK_EXTERN(type_conv);
97 
98 /* Define a static "default" dataset structure to use to initialize new datasets */
99 static H5D_shared_t H5D_def_dset;
100 
101 /* Dataset ID class */
102 static const H5I_class_t H5I_DATASET_CLS[1] = {{
103     H5I_DATASET,                /* ID class value */
104     0,                          /* Class flags */
105     0,                          /* # of reserved IDs for class */
106     (H5I_free_t)H5D__close_cb   /* Callback routine for closing objects of this class */
107 }};
108 
109 /* Flag indicating "top" of interface has been initialized */
110 static hbool_t H5D_top_package_initialize_s = FALSE;
111 
112 
113 
114 /*-------------------------------------------------------------------------
115  * Function: H5D_init
116  *
117  * Purpose:  Initialize the interface from some other layer.
118  *
119  * Return:   Success:    non-negative
120  *
121  *           Failure:    negative
122  *-------------------------------------------------------------------------
123  */
124 herr_t
H5D_init(void)125 H5D_init(void)
126 {
127     herr_t ret_value = SUCCEED;   /* Return value */
128 
129     FUNC_ENTER_NOAPI(FAIL)
130     /* FUNC_ENTER() does all the work */
131 
132 done:
133     FUNC_LEAVE_NOAPI(ret_value)
134 } /* end H5D_init() */
135 
136 
137 /*--------------------------------------------------------------------------
138 NAME
139     H5D__init_package -- Initialize interface-specific information
140 USAGE
141     herr_t H5D__init_package()
142 
143 RETURNS
144     Non-negative on success/Negative on failure
145 DESCRIPTION
146     Initializes any interface-specific data or routines.
147 NOTES
148     Care must be taken when using the H5P functions, since they can cause
149     a deadlock in the library when the library is attempting to terminate -QAK
150 
151 --------------------------------------------------------------------------*/
152 herr_t
H5D__init_package(void)153 H5D__init_package(void)
154 {
155     H5P_genplist_t *def_dcpl;           /* Default Dataset Creation Property list */
156     herr_t ret_value = SUCCEED;         /* Return value */
157 
158     FUNC_ENTER_PACKAGE
159 
160     /* Initialize the atom group for the dataset IDs */
161     if(H5I_register_type(H5I_DATASET_CLS) < 0)
162         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize interface")
163 
164     /* Reset the "default dataset" information */
165     HDmemset(&H5D_def_dset, 0, sizeof(H5D_shared_t));
166 
167     /* Get the default dataset creation property list values and initialize the
168      * default dataset with them.
169      */
170     if(NULL == (def_dcpl = (H5P_genplist_t *)H5I_object(H5P_LST_DATASET_CREATE_ID_g)))
171         HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "can't get default dataset creation property list")
172 
173     /* Get the default data storage layout */
174     if(H5P_get(def_dcpl, H5D_CRT_LAYOUT_NAME, &H5D_def_dset.layout) < 0)
175          HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve layout")
176 
177     /* Get the default dataset creation properties */
178     if(H5P_get(def_dcpl, H5D_CRT_EXT_FILE_LIST_NAME, &H5D_def_dset.dcpl_cache.efl) < 0)
179         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve external file list")
180     if(H5P_get(def_dcpl, H5D_CRT_FILL_VALUE_NAME, &H5D_def_dset.dcpl_cache.fill) < 0)
181         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve fill value")
182     if(H5P_get(def_dcpl, H5O_CRT_PIPELINE_NAME, &H5D_def_dset.dcpl_cache.pline) < 0)
183         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve pipeline filter")
184 
185     /* Mark "top" of interface as initialized, too */
186     H5D_top_package_initialize_s = TRUE;
187 
188 done:
189     FUNC_LEAVE_NOAPI(ret_value)
190 } /* end H5D__init_package() */
191 
192 
193 /*-------------------------------------------------------------------------
194  * Function: H5D_top_term_package
195  *
196  * Purpose:  Close the "top" of the interface, releasing IDs, etc.
197  *
198  * Return:   Success:    Positive if anything was done that might
199  *                affect other interfaces; zero otherwise.
200  *           Failure:    Negative.
201  *-------------------------------------------------------------------------
202  */
203 int
H5D_top_term_package(void)204 H5D_top_term_package(void)
205 {
206     int    n = 0;
207 
208     FUNC_ENTER_NOAPI_NOINIT_NOERR
209 
210     if(H5D_top_package_initialize_s) {
211         if(H5I_nmembers(H5I_DATASET) > 0) {
212             /* The dataset API uses the "force" flag set to true because it
213              * is using the "file objects" (H5FO) API functions to track open
214              * objects in the file.  Using the H5FO code means that dataset
215              * IDs can have reference counts >1, when an existing dataset is
216              * opened more than once.  However, the H5I code does not attempt
217              * to close objects with reference counts>1 unless the "force" flag
218              * is set to true.
219              *
220              * At some point (probably after the group and datatypes use the
221              * the H5FO code), the H5FO code might need to be switched around
222              * to storing pointers to the objects being tracked (H5D_t, H5G_t,
223              * etc) and reference count those itself instead of relying on the
224              * reference counting in the H5I layer.  Then, the "force" flag can
225              * be put back to false.
226              *
227              * Setting the "force" flag to true for all the interfaces won't
228              * work because the "file driver" (H5FD) APIs use the H5I reference
229              * counting to avoid closing a file driver out from underneath an
230              * open file...
231              *
232              * QAK - 5/13/03
233              */
234             (void)H5I_clear_type(H5I_DATASET, TRUE, FALSE);
235             n++; /*H5I*/
236         } /* end if */
237 
238         /* Mark closed */
239         if(0 == n)
240             H5D_top_package_initialize_s = FALSE;
241     } /* end if */
242 
243     FUNC_LEAVE_NOAPI(n)
244 } /* end H5D_top_term_package() */
245 
246 
247 /*-------------------------------------------------------------------------
248  * Function: H5D_term_package
249  *
250  * Purpose:  Terminate this interface.
251  *
252  * Note:     Finishes shutting down the interface, after
253  *           H5D_top_term_package() is called
254  *
255  * Return:   Success:    Positive if anything was done that might
256  *                affect other interfaces; zero otherwise.
257  *            Failure:    Negative.
258  *-------------------------------------------------------------------------
259  */
260 int
H5D_term_package(void)261 H5D_term_package(void)
262 {
263     int    n = 0;
264 
265     FUNC_ENTER_NOAPI_NOINIT_NOERR
266 
267     if(H5_PKG_INIT_VAR) {
268         /* Sanity checks */
269         HDassert(0 == H5I_nmembers(H5I_DATASET));
270         HDassert(FALSE == H5D_top_package_initialize_s);
271 
272         /* Destroy the dataset object id group */
273         n += (H5I_dec_type_ref(H5I_DATASET) > 0);
274 
275         /* Mark closed */
276         if(0 == n)
277             H5_PKG_INIT_VAR = FALSE;
278     } /* end if */
279 
280     FUNC_LEAVE_NOAPI(n)
281 } /* end H5D_term_package() */
282 
283 
284 /*-------------------------------------------------------------------------
285  * Function: H5D__create_named
286  *
287  * Purpose:  Internal routine to create a new dataset.
288  *
289  * Return:   Success:    Non-NULL, pointer to new dataset object.
290  *
291  *           Failure:    NULL
292  *-------------------------------------------------------------------------
293  */
294 H5D_t *
H5D__create_named(const H5G_loc_t * loc,const char * name,hid_t type_id,const H5S_t * space,hid_t lcpl_id,hid_t dcpl_id,hid_t dapl_id)295 H5D__create_named(const H5G_loc_t *loc, const char *name, hid_t type_id,
296     const H5S_t *space, hid_t lcpl_id, hid_t dcpl_id, hid_t dapl_id)
297 {
298     H5O_obj_create_t ocrt_info;         /* Information for object creation */
299     H5D_obj_create_t dcrt_info;         /* Information for dataset creation */
300     H5D_t       *ret_value = NULL;      /* Return value */
301 
302     FUNC_ENTER_PACKAGE_VOL
303 
304     /* Check arguments */
305     HDassert(loc);
306     HDassert(name && *name);
307     HDassert(type_id != H5P_DEFAULT);
308     HDassert(space);
309     HDassert(lcpl_id != H5P_DEFAULT);
310     HDassert(dcpl_id != H5P_DEFAULT);
311     HDassert(dapl_id != H5P_DEFAULT);
312 
313     /* Set up dataset creation info */
314     dcrt_info.type_id = type_id;
315     dcrt_info.space = space;
316     dcrt_info.dcpl_id = dcpl_id;
317     dcrt_info.dapl_id = dapl_id;
318 
319     /* Set up object creation information */
320     ocrt_info.obj_type = H5O_TYPE_DATASET;
321     ocrt_info.crt_info = &dcrt_info;
322     ocrt_info.new_obj = NULL;
323 
324     /* Create the new dataset and link it to its parent group */
325     if(H5L_link_object(loc, name, &ocrt_info, lcpl_id) < 0)
326         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to create and link to dataset")
327     HDassert(ocrt_info.new_obj);
328 
329     /* Set the return value */
330     ret_value = (H5D_t *)ocrt_info.new_obj;
331 
332 done:
333     FUNC_LEAVE_NOAPI_VOL(ret_value)
334 } /* end H5D__create_named() */
335 
336 
337 /*-------------------------------------------------------------------------
338  * Function:    H5D__create_anon
339  *
340  * Purpose:     Internal routine to create a new anonymous dataset.
341  *
342  * Note:        This routine is needed so that there's a non-API routine for
343  *              creating datasets that can set up VOL / SWMR info
344  *              (which need a DXPL).
345  *
346  * Return:      Success:    Non-NULL, pointer to new dataset object.
347  *              Failure:    NULL
348  *
349  * Programmer:	Quincey Koziol
350  *		December 9, 2017
351  *
352  *-------------------------------------------------------------------------
353  */
354 H5D_t *
H5D__create_anon(H5F_t * file,hid_t type_id,const H5S_t * space,hid_t dcpl_id,hid_t dapl_id)355 H5D__create_anon(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
356     hid_t dapl_id)
357 {
358     H5D_t       *ret_value = NULL;      /* Return value */
359 
360     FUNC_ENTER_PACKAGE_VOL
361 
362     /* Check arguments */
363     HDassert(file);
364     HDassert(type_id != H5P_DEFAULT);
365     HDassert(space);
366     HDassert(dcpl_id != H5P_DEFAULT);
367     HDassert(dapl_id != H5P_DEFAULT);
368 
369     /* Build and open the dataset */
370     if(NULL == (ret_value = H5D__create(file, type_id, space, dcpl_id, dapl_id)))
371 	HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to create dataset")
372 
373 done:
374     FUNC_LEAVE_NOAPI_VOL(ret_value)
375 } /* end H5D__create_anon() */
376 
377 
378 /*-------------------------------------------------------------------------
379  * Function:    H5D__get_space_status
380  *
381  * Purpose:     Returns the status of dataspace allocation.
382  *
383  * Return:
384  *              Success:        Non-negative
385  *              Failture:       Negative
386  *-------------------------------------------------------------------------
387  */
388 herr_t
H5D__get_space_status(const H5D_t * dset,H5D_space_status_t * allocation)389 H5D__get_space_status(const H5D_t *dset, H5D_space_status_t *allocation)
390 {
391     herr_t      ret_value = SUCCEED;
392 
393     FUNC_ENTER_PACKAGE_VOL
394 
395     HDassert(dset);
396 
397     /* Check for chunked layout */
398     if(dset->shared->layout.type == H5D_CHUNKED) {
399         hsize_t     space_allocated;    /* The number of bytes allocated for chunks */
400         hssize_t    snelmts;            /* Temporary holder for number of elements in dataspace */
401         hsize_t     nelmts;             /* Number of elements in dataspace */
402         size_t      dt_size;            /* Size of datatype */
403         hsize_t     full_size;          /* The number of bytes in the dataset when fully populated */
404 
405         /* For chunked layout set the space status by the storage size */
406         /* Get the dataset's dataspace */
407         HDassert(dset->shared->space);
408 
409         /* Get the total number of elements in dataset's dataspace */
410         if((snelmts = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0)
411             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve number of elements in dataspace")
412         nelmts = (hsize_t)snelmts;
413 
414         /* Get the size of the dataset's datatype */
415         if(0 == (dt_size = H5T_GET_SIZE(dset->shared->type)))
416             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve size of datatype")
417 
418         /* Compute the maximum size of the dataset in bytes */
419         full_size = nelmts * dt_size;
420 
421         /* Check for overflow during multiplication */
422         if(nelmts != (full_size / dt_size))
423             HGOTO_ERROR(H5E_DATASET, H5E_OVERFLOW, FAIL, "size of dataset's storage overflowed")
424 
425         /* Difficult to error check, since the error value is 0 and 0 is a valid value... :-/ */
426         if(H5D__get_storage_size_real(dset, &space_allocated) < 0)
427             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get size of dataset's storage")
428 
429         /* Decide on how much of the space is allocated */
430         if(space_allocated == 0)
431             *allocation = H5D_SPACE_STATUS_NOT_ALLOCATED;
432         else if(space_allocated == full_size)
433             *allocation = H5D_SPACE_STATUS_ALLOCATED;
434         else
435             *allocation = H5D_SPACE_STATUS_PART_ALLOCATED;
436     } /* end if */
437     else {
438         /* For non-chunked layouts set space status by result of is_space_alloc
439          * function */
440         if(dset->shared->layout.ops->is_space_alloc(&dset->shared->layout.storage))
441             *allocation = H5D_SPACE_STATUS_ALLOCATED;
442         else
443             *allocation = H5D_SPACE_STATUS_NOT_ALLOCATED;
444     } /* end else */
445 
446 done:
447     FUNC_LEAVE_NOAPI_VOL(ret_value)
448 } /* end H5D__get_space_status() */
449 
450 
451 /*-------------------------------------------------------------------------
452  * Function: H5D__new
453  *
454  * Purpose:  Creates a new, empty dataset structure
455  *
456  * Return:   Success:    Pointer to a new dataset descriptor.
457  *           Failure:    NULL
458  *-------------------------------------------------------------------------
459  */
460 static H5D_shared_t *
H5D__new(hid_t dcpl_id,hbool_t creating,hbool_t vl_type)461 H5D__new(hid_t dcpl_id, hbool_t creating, hbool_t vl_type)
462 {
463     H5D_shared_t    *new_dset = NULL;   /* New dataset object */
464     H5P_genplist_t  *plist;             /* Property list created */
465     H5D_shared_t    *ret_value = NULL;  /* Return value */
466 
467     FUNC_ENTER_STATIC
468 
469     /* Allocate new shared dataset structure */
470     if(NULL == (new_dset = H5FL_MALLOC(H5D_shared_t)))
471         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
472 
473     /* Copy the default dataset information */
474     HDmemcpy(new_dset, &H5D_def_dset, sizeof(H5D_shared_t));
475 
476     /* If we are using the default dataset creation property list, during creation
477      * don't bother to copy it, just increment the reference count
478      */
479     if(!vl_type && creating && dcpl_id == H5P_DATASET_CREATE_DEFAULT) {
480         if(H5I_inc_ref(dcpl_id, FALSE) < 0)
481             HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't increment default DCPL ID")
482         new_dset->dcpl_id = dcpl_id;
483     } /* end if */
484     else {
485         /* Get the property list */
486         if(NULL == (plist = (H5P_genplist_t *)H5I_object(dcpl_id)))
487             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list")
488 
489         new_dset->dcpl_id = H5P_copy_plist(plist, FALSE);
490     } /* end else */
491 
492     /* Set return value */
493     ret_value = new_dset;
494 
495 done:
496     if(ret_value == NULL)
497         if(new_dset != NULL) {
498             if(new_dset->dcpl_id != 0 && H5I_dec_ref(new_dset->dcpl_id) < 0)
499                 HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, NULL, "can't decrement temporary datatype ID")
500             new_dset = H5FL_FREE(H5D_shared_t, new_dset);
501         } /* end if */
502 
503     FUNC_LEAVE_NOAPI(ret_value)
504 } /* end H5D__new() */
505 
506 
507 /*-------------------------------------------------------------------------
508  * Function: H5D__init_type
509  *
510  * Purpose:  Copy a datatype for a dataset's use, performing all the
511  *              necessary adjustments, etc.
512  *
513  * Return:   Success:    SUCCEED
514  *           Failure:    FAIL
515  *-------------------------------------------------------------------------
516  */
517 static herr_t
H5D__init_type(H5F_t * file,const H5D_t * dset,hid_t type_id,const H5T_t * type)518 H5D__init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, const H5T_t *type)
519 {
520     htri_t relocatable;            /* Flag whether the type is relocatable */
521     htri_t immutable;              /* Flag whether the type is immutable */
522     hbool_t use_at_least_v18;      /* Flag indicating to use at least v18 format versions */
523     herr_t ret_value = SUCCEED;    /* Return value */
524 
525     FUNC_ENTER_STATIC
526 
527     /* Sanity checking */
528     HDassert(file);
529     HDassert(dset);
530     HDassert(type);
531 
532     /* Check whether the datatype is relocatable */
533     if((relocatable = H5T_is_relocatable(type)) < 0)
534         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't check datatype?")
535 
536     /* Check whether the datatype is immutable */
537     if((immutable = H5T_is_immutable(type)) < 0)
538         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't check datatype?")
539 
540     /* To use at least v18 format versions or not */
541     use_at_least_v18 = (H5F_LOW_BOUND(file) >= H5F_LIBVER_V18);
542 
543     /* Copy the datatype if it's a custom datatype or if it'll change when it's location is changed */
544     if(!immutable || relocatable || use_at_least_v18) {
545         /* Copy datatype for dataset */
546         if((dset->shared->type = H5T_copy(type, H5T_COPY_ALL)) == NULL)
547             HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy datatype")
548 
549         /* Convert a datatype (if committed) to a transient type if the committed datatype's file
550            location is different from the file location where the dataset will be created */
551         if(H5T_convert_committed_datatype(dset->shared->type, file) < 0)
552             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't get shared datatype info")
553 
554         /* Mark any datatypes as being on disk now */
555         if(H5T_set_loc(dset->shared->type, file, H5T_LOC_DISK) < 0)
556             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't set datatype location")
557 
558         /* Set the version for datatype */
559        if(H5T_set_version(file, dset->shared->type) < 0)
560             HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set version of datatype")
561 
562         /* Get a datatype ID for the dataset's datatype */
563         if((dset->shared->type_id = H5I_register(H5I_DATATYPE, dset->shared->type, FALSE)) < 0)
564             HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register type")
565     } /* end if */
566     /* Not a custom datatype, just use it directly */
567     else {
568         if(H5I_inc_ref(type_id, FALSE) < 0)
569             HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, FAIL, "Can't increment datatype ID")
570 
571         /* Use existing datatype */
572         dset->shared->type_id = type_id;
573         dset->shared->type = (H5T_t *)type; /* (Cast away const OK - QAK) */
574     } /* end else */
575 
576 done:
577     FUNC_LEAVE_NOAPI(ret_value)
578 } /* end H5D__init_type() */
579 
580 
581 /*-------------------------------------------------------------------------
582  * Function: H5D__cache_dataspace_info
583  *
584  * Purpose:  Cache dataspace info for a dataset
585  *
586  * Return:   Success:    SUCCEED
587  *           Failure:    FAIL
588  *-------------------------------------------------------------------------
589  */
590 static herr_t
H5D__cache_dataspace_info(const H5D_t * dset)591 H5D__cache_dataspace_info(const H5D_t *dset)
592 {
593     int sndims;                         /* Signed number of dimensions of dataspace rank */
594     unsigned u;                         /* Local index value */
595     herr_t ret_value = SUCCEED;         /* Return value */
596 
597     FUNC_ENTER_STATIC
598 
599     /* Sanity checking */
600     HDassert(dset);
601 
602     /* Cache info for dataset's dataspace */
603     if((sndims = H5S_get_simple_extent_dims(dset->shared->space, dset->shared->curr_dims, dset->shared->max_dims)) < 0)
604         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't cache dataspace dimensions")
605     dset->shared->ndims = (unsigned)sndims;
606 
607     /* Compute the initial 'power2up' values */
608     for(u = 0; u < dset->shared->ndims; u++) {
609         hsize_t scaled_power2up;    /* Scaled value, rounded to next power of 2 */
610 
611         if( !(scaled_power2up = H5VM_power2up(dset->shared->curr_dims[u])) )
612             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get the next power of 2")
613         dset->shared->curr_power2up[u] = scaled_power2up;
614     } /* end for */
615 
616 done:
617     FUNC_LEAVE_NOAPI(ret_value)
618 } /* end H5D__cache_dataspace_info() */
619 
620 
621 /*-------------------------------------------------------------------------
622  * Function: H5D__init_space
623  *
624  * Purpose:  Copy a dataspace for a dataset's use, performing all the
625  *              necessary adjustments, etc.
626  *
627  * Return:   Success:    SUCCEED
628  *           Failure:    FAIL
629  *-------------------------------------------------------------------------
630  */
631 static herr_t
H5D__init_space(H5F_t * file,const H5D_t * dset,const H5S_t * space)632 H5D__init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space)
633 {
634     herr_t ret_value = SUCCEED;         /* Return value */
635 
636     FUNC_ENTER_STATIC
637 
638     /* Sanity checking */
639     HDassert(file);
640     HDassert(dset);
641     HDassert(space);
642 
643     /* Copy dataspace for dataset */
644     if(NULL == (dset->shared->space = H5S_copy(space, FALSE, TRUE)))
645         HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy dataspace")
646 
647     /* Cache the dataset's dataspace info */
648     if(H5D__cache_dataspace_info(dset) < 0)
649         HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't cache dataspace info")
650 
651     /* Set the version for dataspace */
652     if(H5S_set_version(file, dset->shared->space) < 0)
653         HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of datatype")
654 
655     /* Set the dataset's dataspace to 'all' selection */
656     if(H5S_select_all(dset->shared->space, TRUE) < 0)
657         HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set all selection")
658 
659 done:
660     FUNC_LEAVE_NOAPI(ret_value)
661 } /* end H5D__init_space() */
662 
663 
664 /*-------------------------------------------------------------------------
665  * Function: H5D__update_oh_info
666  *
667  * Purpose:  Create and fill object header for dataset
668  *
669  * Return:   Success:    SUCCEED
670  *           Failure:    FAIL
671  *-------------------------------------------------------------------------
672  */
673 static herr_t
H5D__update_oh_info(H5F_t * file,H5D_t * dset,hid_t dapl_id)674 H5D__update_oh_info(H5F_t *file, H5D_t *dset, hid_t dapl_id)
675 {
676     H5O_t              *oh = NULL;      /* Pointer to dataset's object header */
677     size_t              ohdr_size = H5D_MINHDR_SIZE;    /* Size of dataset's object header */
678     H5O_loc_t          *oloc = NULL;    /* Dataset's object location */
679     H5O_layout_t       *layout;         /* Dataset's layout information */
680     H5T_t              *type;           /* Dataset's datatype */
681     H5O_fill_t         *fill_prop;      /* Pointer to dataset's fill value information */
682     H5D_fill_value_t    fill_status;    /* Fill value status */
683     hbool_t             fill_changed = FALSE;   /* Flag indicating the fill value was changed */
684     hbool_t             layout_init = FALSE;    /* Flag to indicate that chunk information was initialized */
685     hbool_t             use_at_least_v18;       /* Flag indicating to use at least v18 format versions */
686     herr_t ret_value = SUCCEED;         /* Return value */
687 
688     FUNC_ENTER_STATIC
689 
690     /* Sanity checking */
691     HDassert(file);
692     HDassert(dset);
693 
694     /* Set some local variables, for convenience */
695     oloc = &dset->oloc;
696     layout = &dset->shared->layout;
697     type = dset->shared->type;
698     fill_prop = &dset->shared->dcpl_cache.fill;
699 
700     /* To use at least v18 format versions or not */
701     use_at_least_v18 = (H5F_LOW_BOUND(file) >= H5F_LIBVER_V18);
702 
703     /* Retrieve "defined" status of fill value */
704     if(H5P_is_fill_value_defined(fill_prop, &fill_status) < 0)
705         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
706 
707     /* Special case handling for variable-length types */
708     if(H5T_detect_class(type, H5T_VLEN, FALSE)) {
709         /* If the default fill value is chosen for variable-length types, always write it */
710         if(fill_prop->fill_time == H5D_FILL_TIME_IFSET && fill_status == H5D_FILL_VALUE_DEFAULT) {
711             /* Update dataset creation property */
712             fill_prop->fill_time = H5D_FILL_TIME_ALLOC;
713 
714             /* Note that the fill value changed */
715             fill_changed = TRUE;
716         } /* end if */
717 
718         /* Don't allow never writing fill values with variable-length types */
719         if(fill_prop->fill_time == H5D_FILL_TIME_NEVER)
720             HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Dataset doesn't support VL datatype when fill value is not defined")
721     } /* end if */
722 
723     /* Determine whether fill value is defined or not */
724     if(fill_status == H5D_FILL_VALUE_DEFAULT || fill_status == H5D_FILL_VALUE_USER_DEFINED) {
725         /* Convert fill value buffer to dataset's datatype */
726         if(fill_prop->buf && fill_prop->size > 0 && H5O_fill_convert(fill_prop, type, &fill_changed) < 0)
727             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert fill value to dataset type")
728 
729         fill_prop->fill_defined = TRUE;
730     } /* end if */
731     else if(fill_status == H5D_FILL_VALUE_UNDEFINED)
732         fill_prop->fill_defined = FALSE;
733     else
734         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine if fill value is defined")
735 
736     /* Check for invalid fill & allocation time setting */
737     if(fill_prop->fill_defined == FALSE && fill_prop->fill_time == H5D_FILL_TIME_ALLOC)
738         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "fill value writing on allocation set, but no fill value defined")
739 
740     /* Check if the fill value info changed */
741     if(fill_changed) {
742         H5P_genplist_t     *dc_plist;               /* Dataset's creation property list */
743 
744         /* Get dataset's property list object */
745         HDassert(dset->shared->dcpl_id != H5P_DATASET_CREATE_DEFAULT);
746         if(NULL == (dc_plist = (H5P_genplist_t *)H5I_object(dset->shared->dcpl_id)))
747             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get dataset creation property list")
748 
749         /* Update dataset creation property */
750         if(H5P_set(dc_plist, H5D_CRT_FILL_VALUE_NAME, fill_prop) < 0)
751             HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set fill value info")
752     } /* end if */
753 
754     /* Add the dataset's raw data size to the size of the header, if the raw data will be stored as compact */
755     if(layout->type == H5D_COMPACT)
756         ohdr_size += layout->storage.u.compact.size;
757 
758     /* Create an object header for the dataset */
759     if(H5O_create(file, ohdr_size, (size_t)1, dset->shared->dcpl_id, oloc/*out*/) < 0)
760         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset object header")
761     HDassert(file == dset->oloc.file);
762 
763     /* Pin the object header */
764     if(NULL == (oh = H5O_pin(oloc)))
765         HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header")
766 
767     /* Write the dataspace header message */
768     if(H5S_append(file, oh, dset->shared->space) < 0)
769         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update dataspace header message")
770 
771     /* Write the datatype header message */
772     if(H5O_msg_append_oh(file, oh, H5O_DTYPE_ID, H5O_MSG_FLAG_CONSTANT, 0, type) < 0)
773         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update datatype header message")
774 
775     /* Write new fill value message */
776     if(H5O_msg_append_oh(file, oh, H5O_FILL_NEW_ID, H5O_MSG_FLAG_CONSTANT, 0, fill_prop) < 0)
777         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update new fill value header message")
778 
779     /* If there is valid information for the old fill value struct, add it */
780     /* (only if we aren't using v18 format versions and above */
781     if(fill_prop->buf && !use_at_least_v18) {
782         H5O_fill_t old_fill_prop;       /* Copy of fill value property, for writing as "old" fill value */
783 
784         /* Shallow copy the fill value property */
785         /* (we only want to make certain that the shared component isn't modified) */
786         HDmemcpy(&old_fill_prop, fill_prop, sizeof(old_fill_prop));
787 
788         /* Reset shared component info */
789         H5O_msg_reset_share(H5O_FILL_ID, &old_fill_prop);
790 
791         /* Write old fill value */
792         if(H5O_msg_append_oh(file, oh, H5O_FILL_ID, H5O_MSG_FLAG_CONSTANT, 0, &old_fill_prop) < 0)
793             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update old fill value header message")
794     } /* end if */
795 
796     /* Update/create the layout (and I/O pipeline & EFL) messages */
797     if(H5D__layout_oh_create(file, oh, dset, dapl_id) < 0)
798         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout/pline/efl header message")
799 
800     /* Indicate that the layout information was initialized */
801     layout_init = TRUE;
802 
803 #ifdef H5O_ENABLE_BOGUS
804 {
805     H5P_genplist_t     *dc_plist;               /* Dataset's creation property list */
806 
807     /* Get dataset's property list object */
808     if(NULL == (dc_plist = (H5P_genplist_t *)H5I_object(dset->shared->dcpl_id)))
809         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get dataset creation property list")
810 
811     /* Check whether to add a "bogus" message */
812     if( (H5P_exist_plist(dc_plist, H5O_BOGUS_MSG_FLAGS_NAME) > 0) &&
813         (H5P_exist_plist(dc_plist, H5O_BOGUS_MSG_ID_NAME) > 0) ) {
814 
815         uint8_t bogus_flags = 0;        /* Flags for creating "bogus" message */
816         unsigned bogus_id;        /* "bogus" ID */
817 
818         /* Retrieve "bogus" message ID */
819         if(H5P_get(dc_plist, H5O_BOGUS_MSG_ID_NAME, &bogus_id) < 0)
820             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get bogus ID options")
821         /* Retrieve "bogus" message flags */
822         if(H5P_get(dc_plist, H5O_BOGUS_MSG_FLAGS_NAME, &bogus_flags) < 0)
823             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get bogus message options")
824 
825         /* Add a "bogus" message (for error testing). */
826         if(H5O_bogus_oh(file, oh, bogus_id, (unsigned)bogus_flags) < 0)
827             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create 'bogus' message")
828     } /* end if */
829 }
830 #endif /* H5O_ENABLE_BOGUS */
831 
832     /* Add a modification time message, if using older format. */
833     /* (If using v18 format versions and above, the the modification time is part of the object
834      *  header and doesn't use a separate message -QAK)
835      */
836     if(!use_at_least_v18)
837         if(H5O_touch_oh(file, oh, TRUE) < 0)
838             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time message")
839 
840 done:
841     /* Release pointer to object header itself */
842     if(oh != NULL)
843         if(H5O_unpin(oh) < 0)
844             HDONE_ERROR(H5E_DATASET, H5E_CANTUNPIN, FAIL, "unable to unpin dataset object header")
845 
846     /* Error cleanup */
847     if(ret_value < 0)
848         if(layout_init)
849             /* Destroy the layout information for the dataset */
850             if(dset->shared->layout.ops->dest && (dset->shared->layout.ops->dest)(dset) < 0)
851                 HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to destroy layout info")
852 
853     FUNC_LEAVE_NOAPI(ret_value)
854 } /* end H5D__update_oh_info() */
855 
856 
857 
858 /*--------------------------------------------------------------------------
859  * Function:    H5D__build_file_prefix
860  *
861  * Purpose:     Determine the file prefix to be used and store
862  *              it in file_prefix. Stores an empty string if no prefix
863  *              should be used.
864  *
865  * Return:      SUCCEED/FAIL
866  *--------------------------------------------------------------------------
867  */
868 static herr_t
H5D__build_file_prefix(const H5D_t * dset,hid_t dapl_id,const char * prefix_type,char ** file_prefix)869 H5D__build_file_prefix(const H5D_t *dset, hid_t dapl_id, const char *prefix_type,
870     char **file_prefix /*out*/)
871 {
872     char            *prefix = NULL;       /* prefix used to look for the file               */
873     char            *filepath = NULL;     /* absolute path of directory the HDF5 file is in */
874     size_t          filepath_len;         /* length of file path                            */
875     size_t          prefix_len;           /* length of prefix                               */
876     size_t          file_prefix_len;      /* length of expanded prefix                      */
877     H5P_genplist_t  *plist = NULL;        /* Property list pointer                          */
878     herr_t          ret_value = SUCCEED;  /* Return value                                   */
879 
880     FUNC_ENTER_STATIC
881 
882     /* Sanity checks */
883     HDassert(dset);
884     HDassert(dset->oloc.file);
885     filepath = H5F_EXTPATH(dset->oloc.file);
886     HDassert(filepath);
887 
888     /* XXX: Future thread-safety note - getenv is not required
889      *      to be reentrant.
890      */
891     if(HDstrcmp(prefix_type, H5D_ACS_VDS_PREFIX_NAME) == 0)
892         prefix = HDgetenv("HDF5_VDS_PREFIX");
893     else if (HDstrcmp(prefix_type, H5D_ACS_EFILE_PREFIX_NAME) == 0)
894         prefix = HDgetenv("HDF5_EXTFILE_PREFIX");
895     else
896         HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "prefix name is not sensible")
897 
898     if(prefix == NULL || *prefix == '\0') {
899         /* Set prefix to value of prefix_type property */
900         if(NULL == (plist = H5P_object_verify(dapl_id, H5P_DATASET_ACCESS)))
901             HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
902         if(H5P_peek(plist, prefix_type, &prefix) < 0)
903             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file prefix")
904     } /* end if */
905 
906     /* Prefix has to be checked for NULL / empty string again because the
907      * code above might have updated it.
908      */
909     if(prefix == NULL || *prefix == '\0' || HDstrcmp(prefix, ".") == 0) {
910         /* filename is interpreted as relative to the current directory,
911          * does not need to be expanded
912          */
913         if(NULL == (*file_prefix = (char *)H5MM_strdup("")))
914             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
915     } /* end if */
916     else {
917         if (HDstrncmp(prefix, "${ORIGIN}", HDstrlen("${ORIGIN}")) == 0) {
918             /* Replace ${ORIGIN} at beginning of prefix by directory of HDF5 file */
919             filepath_len = HDstrlen(filepath);
920             prefix_len = HDstrlen(prefix);
921             file_prefix_len = filepath_len + prefix_len - HDstrlen("${ORIGIN}") + 1;
922 
923             if(NULL == (*file_prefix = (char *)H5MM_malloc(file_prefix_len)))
924                 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate buffer")
925             HDsnprintf(*file_prefix, file_prefix_len, "%s%s", filepath, prefix + HDstrlen("${ORIGIN}"));
926         } /* end if */
927         else {
928             if(NULL == (*file_prefix = (char *)H5MM_strdup(prefix)))
929                 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
930         } /* end else */
931     } /* end else */
932 
933 done:
934     FUNC_LEAVE_NOAPI(ret_value)
935 } /* H5D__build_file_prefix() */
936 
937 
938 /*-------------------------------------------------------------------------
939  * Function:    H5D__create
940  *
941  * Purpose:    Creates a new dataset with name NAME in file F and associates
942  *        with it a datatype TYPE for each element as stored in the
943  *        file, dimensionality information or dataspace SPACE, and
944  *        other miscellaneous properties CREATE_PARMS.  All arguments
945  *        are deep-copied before being associated with the new dataset,
946  *        so the caller is free to subsequently modify them without
947  *        affecting the dataset.
948  *
949  * Return:    Success:    Pointer to a new dataset
950  *            Failure:    NULL
951  *-------------------------------------------------------------------------
952  */
953 H5D_t *
H5D__create(H5F_t * file,hid_t type_id,const H5S_t * space,hid_t dcpl_id,hid_t dapl_id)954 H5D__create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
955     hid_t dapl_id)
956 {
957     const H5T_t        *type;                   /* Datatype for dataset */
958     H5D_t              *new_dset = NULL;
959     H5P_genplist_t     *dc_plist = NULL;        /* New Property list */
960     hbool_t             has_vl_type = FALSE;    /* Flag to indicate a VL-type for dataset */
961     hbool_t             layout_init = FALSE;    /* Flag to indicate that chunk information was initialized */
962     hbool_t             layout_copied = FALSE;  /* Flag to indicate that layout message was copied */
963     hbool_t             fill_copied = FALSE;    /* Flag to indicate that fill-value message was copied */
964     hbool_t             pline_copied = FALSE;   /* Flag to indicate that pipeline message was copied */
965     hbool_t             efl_copied = FALSE;     /* Flag to indicate that external file list message was copied */
966     H5G_loc_t           dset_loc;               /* Dataset location */
967     H5D_t              *ret_value = NULL;       /* Return value */
968 
969     FUNC_ENTER_PACKAGE
970 
971     /* check args */
972     HDassert(file);
973     HDassert(H5I_DATATYPE == H5I_get_type(type_id));
974     HDassert(space);
975     HDassert(H5I_GENPROP_LST == H5I_get_type(dcpl_id));
976 
977     /* Get the dataset's datatype */
978     if(NULL == (type = (const H5T_t *)H5I_object(type_id)))
979         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a datatype")
980 
981     /* Check if the datatype is "sensible" for use in a dataset */
982     if(H5T_is_sensible(type) != TRUE)
983         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "datatype is not sensible")
984 
985     /* Check if the datatype is/contains a VL-type */
986     if(H5T_detect_class(type, H5T_VLEN, FALSE))
987         has_vl_type = TRUE;
988 
989     /* Check if the dataspace has an extent set (or is NULL) */
990     if(!H5S_has_extent(space))
991         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "dataspace extent has not been set.")
992 
993     /* Initialize the dataset object */
994     if(NULL == (new_dset = H5FL_CALLOC(H5D_t)))
995         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
996 
997     /* Set up & reset dataset location */
998     dset_loc.oloc = &(new_dset->oloc);
999     dset_loc.path = &(new_dset->path);
1000     H5G_loc_reset(&dset_loc);
1001 
1002     /* Initialize the shared dataset space */
1003     if(NULL == (new_dset->shared = H5D__new(dcpl_id, TRUE, has_vl_type)))
1004         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
1005 
1006     /* Copy & initialize datatype for dataset */
1007     if(H5D__init_type(file, new_dset, type_id, type) < 0)
1008         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't copy datatype")
1009 
1010     /* Copy & initialize dataspace for dataset */
1011     if(H5D__init_space(file, new_dset, space) < 0)
1012         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't copy dataspace")
1013 
1014     /* Set the dataset's checked_filters flag to enable writing */
1015     new_dset->shared->checked_filters = TRUE;
1016 
1017     /* Check if the dataset has a non-default DCPL & get important values, if so */
1018     if(new_dset->shared->dcpl_id != H5P_DATASET_CREATE_DEFAULT) {
1019         H5O_layout_t    *layout;        /* Dataset's layout information */
1020         H5O_pline_t     *pline;         /* Dataset's I/O pipeline information */
1021         H5O_fill_t      *fill;          /* Dataset's fill value info */
1022         H5O_efl_t       *efl;           /* Dataset's external file list info */
1023 
1024         /* Check if the filters in the DCPL can be applied to this dataset */
1025         if(H5Z_can_apply(new_dset->shared->dcpl_id, new_dset->shared->type_id) < 0)
1026             HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, NULL, "I/O filters can't operate on this dataset")
1027 
1028         /* Make the "set local" filter callbacks for this dataset */
1029         if(H5Z_set_local(new_dset->shared->dcpl_id, new_dset->shared->type_id) < 0)
1030             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to set local filter parameters")
1031 
1032         /* Get new dataset's property list object */
1033         if(NULL == (dc_plist = (H5P_genplist_t *)H5I_object(new_dset->shared->dcpl_id)))
1034             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get dataset creation property list")
1035 
1036         /* Retrieve the properties we need */
1037         pline = &new_dset->shared->dcpl_cache.pline;
1038         if(H5P_get(dc_plist, H5O_CRT_PIPELINE_NAME, pline) < 0)
1039             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't retrieve pipeline filter")
1040         pline_copied = TRUE;
1041         layout = &new_dset->shared->layout;
1042         if(H5P_get(dc_plist, H5D_CRT_LAYOUT_NAME, layout) < 0)
1043             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't retrieve layout")
1044         layout_copied = TRUE;
1045         fill = &new_dset->shared->dcpl_cache.fill;
1046         if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, fill) < 0)
1047             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't retrieve fill value info")
1048         fill_copied = TRUE;
1049         efl = &new_dset->shared->dcpl_cache.efl;
1050         if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, efl) < 0)
1051             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't retrieve external file list")
1052         efl_copied = TRUE;
1053 
1054         /* Check that chunked layout is used if filters are enabled */
1055         if(pline->nused > 0 && H5D_CHUNKED != layout->type)
1056             HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "filters can only be used with chunked layout")
1057 
1058         /* Check if the alloc_time is the default and error out */
1059         if(fill->alloc_time == H5D_ALLOC_TIME_DEFAULT)
1060             HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "invalid space allocation state")
1061 
1062         /* Don't allow compact datasets to allocate space later */
1063         if(layout->type == H5D_COMPACT && fill->alloc_time != H5D_ALLOC_TIME_EARLY)
1064             HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "compact dataset must have early space allocation")
1065     } /* end if */
1066 
1067     /* Set the version for the I/O pipeline message */
1068     if(H5O_pline_set_version(file, &new_dset->shared->dcpl_cache.pline) < 0)
1069         HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set latest version of I/O filter pipeline")
1070 
1071     /* Set the version for the fill message */
1072     if(H5O_fill_set_version(file, &new_dset->shared->dcpl_cache.fill) < 0)
1073         HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set latest version of fill value")
1074 
1075     /* Set the latest version for the layout message */
1076     if(H5D__layout_set_version(file, &new_dset->shared->layout) < 0)
1077         HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set latest version of layout")
1078 
1079     if(new_dset->shared->layout.version >= H5O_LAYOUT_VERSION_4) {
1080         /* Use latest indexing type for layout message version >= 4 */
1081         if(H5D__layout_set_latest_indexing(&new_dset->shared->layout, new_dset->shared->space, &new_dset->shared->dcpl_cache) < 0)
1082             HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set latest indexing")
1083     } /* end if */
1084 
1085     /* Check if this dataset is going into a parallel file and set space allocation time */
1086     if(H5F_HAS_FEATURE(file, H5FD_FEAT_ALLOCATE_EARLY))
1087         new_dset->shared->dcpl_cache.fill.alloc_time = H5D_ALLOC_TIME_EARLY;
1088 
1089     /* Set the dataset's I/O operations */
1090     if(H5D__layout_set_io_ops(new_dset) < 0)
1091         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize I/O operations")
1092 
1093     /* Create the layout information for the new dataset */
1094     if(new_dset->shared->layout.ops->construct && (new_dset->shared->layout.ops->construct)(file, new_dset) < 0)
1095         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to construct layout information")
1096 
1097     /* Update the dataset's object header info. */
1098     if(H5D__update_oh_info(file, new_dset, dapl_id) < 0)
1099         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't update the metadata cache")
1100 
1101     /* Indicate that the layout information was initialized */
1102     layout_init = TRUE;
1103 
1104     /* Set up append flush parameters for the dataset */
1105     if(H5D__append_flush_setup(new_dset, dapl_id) < 0)
1106         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to set up flush append property")
1107 
1108     /* Set the external file prefix */
1109     if(H5D__build_file_prefix(new_dset, dapl_id, H5D_ACS_EFILE_PREFIX_NAME, &new_dset->shared->extfile_prefix) < 0)
1110         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize external file prefix")
1111 
1112     /* Set the VDS file prefix */
1113     if(H5D__build_file_prefix(new_dset, dapl_id, H5D_ACS_VDS_PREFIX_NAME, &new_dset->shared->vds_prefix) < 0)
1114         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize VDS prefix")
1115 
1116     /* Add the dataset to the list of opened objects in the file */
1117     if(H5FO_top_incr(new_dset->oloc.file, new_dset->oloc.addr) < 0)
1118         HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't incr object ref. count")
1119     if(H5FO_insert(new_dset->oloc.file, new_dset->oloc.addr, new_dset->shared, TRUE) < 0)
1120         HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, NULL, "can't insert dataset into list of open objects")
1121     new_dset->shared->fo_count = 1;
1122 
1123     /* Success */
1124     ret_value = new_dset;
1125 
1126 done:
1127     if(!ret_value && new_dset && new_dset->shared) {
1128         if(new_dset->shared) {
1129             if(layout_init)
1130                 if(new_dset->shared->layout.ops->dest && (new_dset->shared->layout.ops->dest)(new_dset) < 0)
1131                     HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, NULL, "unable to destroy layout info")
1132             if(pline_copied)
1133                 if(H5O_msg_reset(H5O_PLINE_ID, &new_dset->shared->dcpl_cache.pline) < 0)
1134                     HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, NULL, "unable to reset I/O pipeline info")
1135             if(layout_copied)
1136                 if(H5O_msg_reset(H5O_LAYOUT_ID, &new_dset->shared->layout) < 0)
1137                     HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, NULL, "unable to reset layout info")
1138             if(fill_copied)
1139                 if(H5O_msg_reset(H5O_FILL_ID, &new_dset->shared->dcpl_cache.fill) < 0)
1140                     HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, NULL, "unable to reset fill-value info")
1141             if(efl_copied)
1142                 if(H5O_msg_reset(H5O_EFL_ID, &new_dset->shared->dcpl_cache.efl) < 0)
1143                     HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, NULL, "unable to reset external file list info")
1144             if(new_dset->shared->space && H5S_close(new_dset->shared->space) < 0)
1145                 HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release dataspace")
1146             if(new_dset->shared->type && H5I_dec_ref(new_dset->shared->type_id) < 0)
1147                 HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release datatype")
1148             if(H5F_addr_defined(new_dset->oloc.addr)) {
1149                 if(H5O_dec_rc_by_loc(&(new_dset->oloc)) < 0)
1150                     HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, NULL, "unable to decrement refcount on newly created object")
1151                 if(H5O_close(&(new_dset->oloc), NULL) < 0)
1152                     HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release object header")
1153                 if(file) {
1154                     if(H5O_delete(file, new_dset->oloc.addr) < 0)
1155                         HDONE_ERROR(H5E_DATASET, H5E_CANTDELETE, NULL, "unable to delete object header")
1156                 } /* end if */
1157             } /* end if */
1158             if(new_dset->shared->dcpl_id != 0 && H5I_dec_ref(new_dset->shared->dcpl_id) < 0)
1159                 HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, NULL, "unable to decrement ref count on property list")
1160             new_dset->shared->extfile_prefix = (char *)H5MM_xfree(new_dset->shared->extfile_prefix);
1161             new_dset->shared->vds_prefix = (char *)H5MM_xfree(new_dset->shared->vds_prefix);
1162             new_dset->shared = H5FL_FREE(H5D_shared_t, new_dset->shared);
1163         } /* end if */
1164         new_dset->oloc.file = NULL;
1165         new_dset = H5FL_FREE(H5D_t, new_dset);
1166     } /* end if */
1167 
1168     FUNC_LEAVE_NOAPI(ret_value)
1169 } /* end H5D__create() */
1170 
1171 
1172 /*-------------------------------------------------------------------------
1173  * Function:    H5D__open_name
1174  *
1175  * Purpose:     Opens an existing dataset by name.
1176  *
1177  * Return:      Success:        Ptr to a new dataset.
1178  *              Failure:        NULL
1179  *-------------------------------------------------------------------------
1180  */
1181 H5D_t *
H5D__open_name(const H5G_loc_t * loc,const char * name,hid_t dapl_id)1182 H5D__open_name(const H5G_loc_t *loc, const char *name, hid_t dapl_id)
1183 {
1184     H5D_t       *dset = NULL;
1185     H5G_loc_t   dset_loc;               /* Object location of dataset */
1186     H5G_name_t  path;                   /* Dataset group hier. path */
1187     H5O_loc_t   oloc;                   /* Dataset object location */
1188     H5O_type_t  obj_type;               /* Type of object at location */
1189     hbool_t     loc_found = FALSE;      /* Location at 'name' found */
1190     H5D_t       *ret_value = NULL;      /* Return value */
1191 
1192     FUNC_ENTER_PACKAGE_VOL
1193 
1194     /* Check args */
1195     HDassert(loc);
1196     HDassert(name);
1197 
1198     /* Set up dataset location to fill in */
1199     dset_loc.oloc = &oloc;
1200     dset_loc.path = &path;
1201     H5G_loc_reset(&dset_loc);
1202 
1203     /* Find the dataset object */
1204     if(H5G_loc_find(loc, name, &dset_loc) < 0)
1205         HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, NULL, "not found")
1206     loc_found = TRUE;
1207 
1208     /* Check that the object found is the correct type */
1209     if(H5O_obj_type(&oloc, &obj_type) < 0)
1210         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't get object type")
1211     if(obj_type != H5O_TYPE_DATASET)
1212         HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, NULL, "not a dataset")
1213 
1214     /* Open the dataset */
1215     if(NULL == (dset = H5D_open(&dset_loc, dapl_id)))
1216         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't open dataset")
1217 
1218     /* Set return value */
1219     ret_value = dset;
1220 
1221 done:
1222     if(!ret_value)
1223         if(loc_found && H5G_loc_free(&dset_loc) < 0)
1224             HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, NULL, "can't free location")
1225 
1226     FUNC_LEAVE_NOAPI_VOL(ret_value)
1227 } /* end H5D__open_name() */
1228 
1229 
1230 /*
1231  *-------------------------------------------------------------------------
1232  * Function: H5D_open
1233  *
1234  * Purpose:  Checks if dataset is already open, or opens a dataset for
1235  *              access.
1236  *
1237  * Return:   Success:    Dataset ID
1238  *           Failure:    FAIL
1239  *-------------------------------------------------------------------------
1240  */
1241 H5D_t *
H5D_open(const H5G_loc_t * loc,hid_t dapl_id)1242 H5D_open(const H5G_loc_t *loc, hid_t dapl_id)
1243 {
1244     H5D_shared_t    *shared_fo = NULL;
1245     H5D_t           *dataset = NULL;
1246     char            *extfile_prefix = NULL;  /* Expanded external file prefix */
1247     char            *vds_prefix = NULL;      /* Expanded vds prefix */
1248     H5D_t           *ret_value = NULL;       /* Return value */
1249 
1250     FUNC_ENTER_NOAPI(NULL)
1251 
1252     /* check args */
1253     HDassert(loc);
1254 
1255     /* Allocate the dataset structure */
1256     if(NULL == (dataset = H5FL_CALLOC(H5D_t)))
1257         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
1258 
1259     /* Shallow copy (take ownership) of the object location object */
1260     if(H5O_loc_copy(&(dataset->oloc), loc->oloc, H5_COPY_SHALLOW) < 0)
1261         HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, NULL, "can't copy object location")
1262 
1263     /* Shallow copy (take ownership) of the group hier. path */
1264     if(H5G_name_copy(&(dataset->path), loc->path, H5_COPY_SHALLOW) < 0)
1265         HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, NULL, "can't copy path")
1266 
1267     /* Get the external file prefix */
1268     if(H5D__build_file_prefix(dataset, dapl_id, H5D_ACS_EFILE_PREFIX_NAME, &extfile_prefix) < 0)
1269         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize external file prefix")
1270 
1271     /* Get the VDS prefix */
1272     if(H5D__build_file_prefix(dataset, dapl_id, H5D_ACS_VDS_PREFIX_NAME, &vds_prefix) < 0)
1273         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize VDS prefix")
1274 
1275     /* Check if dataset was already open */
1276     if(NULL == (shared_fo = (H5D_shared_t *)H5FO_opened(dataset->oloc.file, dataset->oloc.addr))) {
1277         /* Clear any errors from H5FO_opened() */
1278         H5E_clear_stack(NULL);
1279 
1280         /* Open the dataset object */
1281         if(H5D__open_oid(dataset, dapl_id) < 0)
1282             HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, NULL, "not found")
1283 
1284         /* Add the dataset to the list of opened objects in the file */
1285         if(H5FO_insert(dataset->oloc.file, dataset->oloc.addr, dataset->shared, FALSE) < 0)
1286             HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, NULL, "can't insert dataset into list of open objects")
1287 
1288         /* Increment object count for the object in the top file */
1289         if(H5FO_top_incr(dataset->oloc.file, dataset->oloc.addr) < 0)
1290             HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't increment object count")
1291 
1292         /* We're the first dataset to use the the shared info */
1293         dataset->shared->fo_count = 1;
1294 
1295         /* Set the external file prefix */
1296         dataset->shared->extfile_prefix = extfile_prefix;
1297         /* Prevent string from being freed during done: */
1298         extfile_prefix = NULL;
1299 
1300         /* Set the vds file prefix */
1301         dataset->shared->vds_prefix = vds_prefix;
1302         /* Prevent string from being freed during done: */
1303         vds_prefix = NULL;
1304 
1305     } /* end if */
1306     else {
1307         /* Point to shared info */
1308         dataset->shared = shared_fo;
1309 
1310         /* Increment # of datasets using shared information */
1311         shared_fo->fo_count++;
1312 
1313         /* Check whether the external file prefix of the already open dataset
1314          * matches the new external file prefix
1315          */
1316         if(HDstrcmp(extfile_prefix, dataset->shared->extfile_prefix) != 0)
1317             HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "new external file prefix does not match external file prefix of already open dataset")
1318 
1319         /* Check if the object has been opened through the top file yet */
1320         if(H5FO_top_count(dataset->oloc.file, dataset->oloc.addr) == 0) {
1321             /* Open the object through this top file */
1322             if(H5O_open(&(dataset->oloc)) < 0)
1323                 HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "unable to open object header")
1324         } /* end if */
1325 
1326         /* Increment object count for the object in the top file */
1327         if(H5FO_top_incr(dataset->oloc.file, dataset->oloc.addr) < 0)
1328             HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't increment object count")
1329     } /* end else */
1330 
1331     /* Set the dataset to return */
1332     ret_value = dataset;
1333 
1334 done:
1335     extfile_prefix = (char *)H5MM_xfree(extfile_prefix);
1336     vds_prefix = (char *)H5MM_xfree(vds_prefix);
1337 
1338     if(ret_value == NULL) {
1339         /* Free the location--casting away const*/
1340         if(dataset) {
1341             if(shared_fo == NULL && dataset->shared) {   /* Need to free shared fo */
1342                 dataset->shared->extfile_prefix = (char *)H5MM_xfree(dataset->shared->extfile_prefix);
1343                 dataset->shared->vds_prefix = (char *)H5MM_xfree(dataset->shared->vds_prefix);
1344                 dataset->shared = H5FL_FREE(H5D_shared_t, dataset->shared);
1345             } /* end if */
1346 
1347             H5O_loc_free(&(dataset->oloc));
1348             H5G_name_free(&(dataset->path));
1349 
1350             dataset = H5FL_FREE(H5D_t, dataset);
1351         } /* end if */
1352         if(shared_fo)
1353             shared_fo->fo_count--;
1354     } /* end if */
1355 
1356     FUNC_LEAVE_NOAPI(ret_value)
1357 } /* end H5D_open() */
1358 
1359 
1360 /*
1361  *-------------------------------------------------------------------------
1362  * Function: H5D__flush_append_setup
1363  *
1364  * Purpose:  Set the append flush parameters for a dataset
1365  *
1366  * Return:   Non-negative on success/Negative on failure
1367  *-------------------------------------------------------------------------
1368  */
1369 static herr_t
H5D__append_flush_setup(H5D_t * dset,hid_t dapl_id)1370 H5D__append_flush_setup(H5D_t *dset, hid_t dapl_id)
1371 {
1372     herr_t ret_value = SUCCEED;         /* return value */
1373 
1374     FUNC_ENTER_STATIC
1375 
1376     /* Check args */
1377     HDassert(dset);
1378     HDassert(dset->shared);
1379 
1380     /* Set default append flush values */
1381     HDmemset(&dset->shared->append_flush,  0, sizeof(dset->shared->append_flush));
1382 
1383     /* If the dataset is chunked and there is a non-default DAPL */
1384     if(dapl_id != H5P_DATASET_ACCESS_DEFAULT && dset->shared->layout.type == H5D_CHUNKED) {
1385         H5P_genplist_t *dapl;               /* data access property list object pointer */
1386 
1387         /* Get dataset access property list */
1388         if(NULL == (dapl = (H5P_genplist_t *)H5I_object(dapl_id)))
1389             HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for dapl ID");
1390 
1391         /* Check if append flush property exists */
1392         if(H5P_exist_plist(dapl, H5D_ACS_APPEND_FLUSH_NAME) > 0) {
1393             H5D_append_flush_t info;
1394 
1395             /* Get append flush property */
1396             if(H5P_get(dapl, H5D_ACS_APPEND_FLUSH_NAME, &info) < 0)
1397                 HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get append flush info")
1398             if(info.ndims > 0) {
1399                 hsize_t curr_dims[H5S_MAX_RANK];    /* current dimension sizes */
1400                 hsize_t max_dims[H5S_MAX_RANK];     /* current dimension sizes */
1401                 int rank;                           /* dataspace # of dimensions */
1402                 unsigned u;                         /* local index variable */
1403 
1404                 /* Get dataset rank */
1405                 if((rank = H5S_get_simple_extent_dims(dset->shared->space, curr_dims, max_dims)) < 0)
1406                     HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
1407                 if(info.ndims != (unsigned)rank)
1408                     HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "boundary dimension rank does not match dataset rank")
1409 
1410                 /* Validate boundary sizes */
1411                 for(u = 0; u < info.ndims; u++)
1412                     if(info.boundary[u] != 0) /* when a non-zero boundary is set */
1413                         /* the dimension is extendible? */
1414                         if(max_dims[u] != H5S_UNLIMITED && max_dims[u] == curr_dims[u])
1415                             break;
1416 
1417                 /* At least one boundary dimension is not extendible */
1418                 if(u != info.ndims)
1419                     HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "boundary dimension is not valid")
1420 
1421                 /* Copy append flush settings */
1422                 dset->shared->append_flush.ndims = info.ndims;
1423                 dset->shared->append_flush.func = info.func;
1424                 dset->shared->append_flush.udata = info.udata;
1425                 HDmemcpy(dset->shared->append_flush.boundary, info.boundary, sizeof(info.boundary));
1426             } /* end if */
1427         } /* end if */
1428     } /* end if */
1429 
1430 done:
1431     FUNC_LEAVE_NOAPI(ret_value)
1432 } /* H5D__append_flush_setup() */
1433 
1434 
1435 /*-------------------------------------------------------------------------
1436  * Function: H5D__open_oid
1437  *
1438  * Purpose:  Opens a dataset for access.
1439  *
1440  * Return:   Dataset pointer on success, NULL on failure
1441  *-------------------------------------------------------------------------
1442  */
1443 static herr_t
H5D__open_oid(H5D_t * dataset,hid_t dapl_id)1444 H5D__open_oid(H5D_t *dataset, hid_t dapl_id)
1445 {
1446     H5P_genplist_t *plist;              /* Property list */
1447     H5O_fill_t *fill_prop;              /* Pointer to dataset's fill value info */
1448     unsigned alloc_time_state;          /* Allocation time state */
1449     htri_t msg_exists;                  /* Whether a particular type of message exists */
1450     hbool_t layout_init = FALSE;        /* Flag to indicate that chunk information was initialized */
1451     herr_t ret_value = SUCCEED;         /* Return value */
1452 
1453     FUNC_ENTER_STATIC_TAG(dataset->oloc.addr)
1454 
1455     /* check args */
1456     HDassert(dataset);
1457 
1458     /* (Set the 'vl_type' parameter to FALSE since it doesn't matter from here) */
1459     if(NULL == (dataset->shared = H5D__new(H5P_DATASET_CREATE_DEFAULT, FALSE, FALSE)))
1460         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
1461 
1462     /* Open the dataset object */
1463     if(H5O_open(&(dataset->oloc)) < 0)
1464         HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open")
1465 
1466     /* Get the type and space */
1467     if(NULL == (dataset->shared->type = (H5T_t *)H5O_msg_read(&(dataset->oloc), H5O_DTYPE_ID, NULL)))
1468         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load type info from dataset header")
1469 
1470     if(H5T_set_loc(dataset->shared->type, dataset->oloc.file, H5T_LOC_DISK) < 0)
1471         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
1472 
1473     if(NULL == (dataset->shared->space = H5S_read(&(dataset->oloc))))
1474         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load dataspace info from dataset header")
1475 
1476     /* Cache the dataset's dataspace info */
1477     if(H5D__cache_dataspace_info(dataset) < 0)
1478         HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't cache dataspace info")
1479 
1480     /* Get a datatype ID for the dataset's datatype */
1481     if((dataset->shared->type_id = H5I_register(H5I_DATATYPE, dataset->shared->type, FALSE)) < 0)
1482         HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register type")
1483 
1484     /* Get dataset creation property list object */
1485     if(NULL == (plist = (H5P_genplist_t *)H5I_object(dataset->shared->dcpl_id)))
1486         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get dataset creation property list")
1487 
1488     /* Get the layout/pline/efl message information */
1489     if(H5D__layout_oh_read(dataset, dapl_id, plist) < 0)
1490         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get layout/pline/efl info")
1491 
1492     /* Indicate that the layout information was initialized */
1493     layout_init = TRUE;
1494 
1495     /* Set up flush append property */
1496     if(H5D__append_flush_setup(dataset, dapl_id))
1497         HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set up flush append property")
1498 
1499     /* Point at dataset's copy, to cache it for later */
1500     fill_prop = &dataset->shared->dcpl_cache.fill;
1501 
1502     /* Try to get the new fill value message from the object header */
1503     if((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_FILL_NEW_ID)) < 0)
1504         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists")
1505     if(msg_exists) {
1506         if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_NEW_ID, fill_prop))
1507             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message")
1508     } /* end if */
1509     else {
1510     /* For backward compatibility, try to retrieve the old fill value message */
1511         if((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_FILL_ID)) < 0)
1512             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists")
1513         if(msg_exists) {
1514             if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_ID, fill_prop))
1515                 HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message")
1516         } /* end if */
1517         else {
1518             /* Set the space allocation time appropriately, based on the type of dataset storage */
1519             switch(dataset->shared->layout.type) {
1520                 case H5D_COMPACT:
1521                     fill_prop->alloc_time = H5D_ALLOC_TIME_EARLY;
1522                     break;
1523 
1524                 case H5D_CONTIGUOUS:
1525                     fill_prop->alloc_time = H5D_ALLOC_TIME_LATE;
1526                     break;
1527 
1528                 case H5D_CHUNKED:
1529                     fill_prop->alloc_time = H5D_ALLOC_TIME_INCR;
1530                     break;
1531 
1532                 case H5D_VIRTUAL:
1533                     fill_prop->alloc_time = H5D_ALLOC_TIME_INCR;
1534                     break;
1535 
1536                 case H5D_LAYOUT_ERROR:
1537                 case H5D_NLAYOUTS:
1538                 default:
1539                     HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "not implemented yet")
1540             } /* end switch */ /*lint !e788 All appropriate cases are covered */
1541         } /* end else */
1542 
1543         /* If "old" fill value size is 0 (undefined), map it to -1 */
1544         if(fill_prop->size == 0)
1545             fill_prop->size = (ssize_t)-1;
1546     } /* end if */
1547     alloc_time_state = 0;
1548     if((dataset->shared->layout.type == H5D_COMPACT && fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY)
1549             || (dataset->shared->layout.type == H5D_CONTIGUOUS && fill_prop->alloc_time == H5D_ALLOC_TIME_LATE)
1550             || (dataset->shared->layout.type == H5D_CHUNKED && fill_prop->alloc_time == H5D_ALLOC_TIME_INCR)
1551             || (dataset->shared->layout.type == H5D_VIRTUAL && fill_prop->alloc_time == H5D_ALLOC_TIME_INCR))
1552         alloc_time_state = 1;
1553 
1554     /* Set revised fill value properties, if they are different from the defaults */
1555     if(H5P_fill_value_cmp(&H5D_def_dset.dcpl_cache.fill, fill_prop, sizeof(H5O_fill_t))) {
1556         if(H5P_set(plist, H5D_CRT_FILL_VALUE_NAME, fill_prop) < 0)
1557             HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set fill value")
1558         if(H5P_set(plist, H5D_CRT_ALLOC_TIME_STATE_NAME, &alloc_time_state) < 0)
1559             HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set allocation time state")
1560     } /* end if */
1561 
1562     /*
1563      * Make sure all storage is properly initialized.
1564      * This is important only for parallel I/O where the space must
1565      * be fully allocated before I/O can happen.
1566      */
1567     if((H5F_INTENT(dataset->oloc.file) & H5F_ACC_RDWR)
1568             && !(*dataset->shared->layout.ops->is_space_alloc)(&dataset->shared->layout.storage)
1569             && H5F_HAS_FEATURE(dataset->oloc.file, H5FD_FEAT_ALLOCATE_EARLY)) {
1570         H5D_io_info_t io_info;
1571 
1572         io_info.dset = dataset;
1573 
1574         if(H5D__alloc_storage(&io_info, H5D_ALLOC_OPEN, FALSE, NULL) < 0)
1575             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file storage")
1576     } /* end if */
1577 
1578 done:
1579     if(ret_value < 0) {
1580         if(H5F_addr_defined(dataset->oloc.addr) && H5O_close(&(dataset->oloc), NULL) < 0)
1581             HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release object header")
1582         if(dataset->shared) {
1583             if(layout_init)
1584                 if(dataset->shared->layout.ops->dest && (dataset->shared->layout.ops->dest)(dataset) < 0)
1585                     HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to destroy layout info")
1586             if(dataset->shared->space && H5S_close(dataset->shared->space) < 0)
1587                 HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
1588             if(dataset->shared->type) {
1589                 if(dataset->shared->type_id > 0) {
1590                     if(H5I_dec_ref(dataset->shared->type_id) < 0)
1591                         HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype")
1592                 } /* end if */
1593                 else {
1594                     if(H5T_close_real(dataset->shared->type) < 0)
1595                         HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype")
1596                 } /* end else */
1597             } /* end if */
1598         } /* end if */
1599     } /* end if */
1600 
1601     FUNC_LEAVE_NOAPI_TAG(ret_value)
1602 } /* end H5D__open_oid() */
1603 
1604 
1605 /*-------------------------------------------------------------------------
1606  * Function: H5D__close_cb
1607  *
1608  * Purpose:  Callback routine for closing a dataset ID.  Closes the dataset
1609  *           object that was attached to the ID.
1610  *
1611  * Return:   Non-negative on success/Negative on failure
1612  *
1613  *-------------------------------------------------------------------------
1614  */
1615 static herr_t
H5D__close_cb(H5D_t * dataset)1616 H5D__close_cb(H5D_t *dataset)
1617 {
1618     herr_t ret_value = SUCCEED;                 /* Return value */
1619 
1620     FUNC_ENTER_STATIC_VOL
1621 
1622     /* check args */
1623     HDassert(dataset && dataset->oloc.file && dataset->shared);
1624     HDassert(dataset->shared->fo_count > 0);
1625 
1626     /* Call actual dataset close routine */
1627     if(H5D_close(dataset) < 0)
1628         HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't close dataset");
1629 
1630 done:
1631     FUNC_LEAVE_NOAPI_VOL(ret_value)
1632 } /* end H5D__close_cb() */
1633 
1634 
1635 /*-------------------------------------------------------------------------
1636  * Function: H5D_close
1637  *
1638  * Purpose:  Insures that all data has been saved to the file, closes the
1639  *           dataset object header, and frees all resources used by the
1640  *           descriptor.
1641  *
1642  * Return:   Non-negative on success/Negative on failure
1643  *-------------------------------------------------------------------------
1644  */
1645 herr_t
H5D_close(H5D_t * dataset)1646 H5D_close(H5D_t *dataset)
1647 {
1648     hbool_t free_failed = FALSE;    /* Set if freeing sub-components failed */
1649     hbool_t corked;                 /* Whether the dataset is corked or not */
1650     hbool_t file_closed = TRUE;     /* H5O_close also closed the file?      */
1651     herr_t ret_value = SUCCEED;     /* Return value                         */
1652 
1653     FUNC_ENTER_NOAPI(FAIL)
1654 
1655     /* check args */
1656     HDassert(dataset && dataset->oloc.file && dataset->shared);
1657     HDassert(dataset->shared->fo_count > 0);
1658 
1659     /* Dump debugging info */
1660 #ifdef H5D_CHUNK_DEBUG
1661     H5D__chunk_stats(dataset, FALSE);
1662 #endif /* H5D_CHUNK_DEBUG */
1663 
1664     dataset->shared->fo_count--;
1665     if(dataset->shared->fo_count == 0) {
1666 
1667         /* Flush the dataset's information.  Continue to close even if it fails. */
1668         if(H5D__flush_real(dataset) < 0)
1669             HDONE_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to flush cached dataset info")
1670 
1671         /* Set a flag to indicate the dataset is closing, before we start freeing things */
1672         /* (Avoids problems with flushing datasets twice, when one is holding
1673          *      the file open and it iterates through dataset to flush them -QAK)
1674          */
1675         dataset->shared->closing = TRUE;
1676 
1677         /* Free cached information for each kind of dataset */
1678         switch(dataset->shared->layout.type) {
1679             case H5D_CONTIGUOUS:
1680                 /* Free the data sieve buffer, if it's been allocated */
1681                 if(dataset->shared->cache.contig.sieve_buf)
1682                     dataset->shared->cache.contig.sieve_buf = (unsigned char *)H5FL_BLK_FREE(sieve_buf,dataset->shared->cache.contig.sieve_buf);
1683                 break;
1684 
1685             case H5D_CHUNKED:
1686                 /* Check for skip list for iterating over chunks during I/O to close */
1687                 if(dataset->shared->cache.chunk.sel_chunks) {
1688                     HDassert(H5SL_count(dataset->shared->cache.chunk.sel_chunks) == 0);
1689                     H5SL_close(dataset->shared->cache.chunk.sel_chunks);
1690                     dataset->shared->cache.chunk.sel_chunks = NULL;
1691                 } /* end if */
1692 
1693                 /* Check for cached single chunk dataspace */
1694                 if(dataset->shared->cache.chunk.single_space) {
1695                     (void)H5S_close(dataset->shared->cache.chunk.single_space);
1696                     dataset->shared->cache.chunk.single_space = NULL;
1697                 } /* end if */
1698 
1699                 /* Check for cached single element chunk info */
1700                 if(dataset->shared->cache.chunk.single_chunk_info) {
1701                     dataset->shared->cache.chunk.single_chunk_info = H5FL_FREE(H5D_chunk_info_t, dataset->shared->cache.chunk.single_chunk_info);
1702                     dataset->shared->cache.chunk.single_chunk_info = NULL;
1703                 } /* end if */
1704                 break;
1705 
1706             case H5D_COMPACT:
1707                 /* Nothing special to do (info freed in the layout destroy) */
1708                 break;
1709 
1710             case H5D_VIRTUAL:
1711             {
1712                 size_t i, j;
1713 
1714                 HDassert(dataset->shared->layout.storage.u.virt.list || (dataset->shared->layout.storage.u.virt.list_nused == 0));
1715 
1716                 /* Close source datasets */
1717                 for(i = 0; i < dataset->shared->layout.storage.u.virt.list_nused; i++) {
1718                     /* Close source dataset */
1719                     if(dataset->shared->layout.storage.u.virt.list[i].source_dset.dset) {
1720                         HDassert(dataset->shared->layout.storage.u.virt.list[i].source_dset.dset != dataset);
1721                         if(H5D_close(dataset->shared->layout.storage.u.virt.list[i].source_dset.dset) < 0)
1722                             HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to close source dataset")
1723                         dataset->shared->layout.storage.u.virt.list[i].source_dset.dset = NULL;
1724                     } /* end if */
1725 
1726                     /* Close sub datasets */
1727                     for(j = 0; j < dataset->shared->layout.storage.u.virt.list[i].sub_dset_nused; j++)
1728                         if(dataset->shared->layout.storage.u.virt.list[i].sub_dset[j].dset) {
1729                             HDassert(dataset->shared->layout.storage.u.virt.list[i].sub_dset[j].dset != dataset);
1730                             if(H5D_close(dataset->shared->layout.storage.u.virt.list[i].sub_dset[j].dset) < 0)
1731                                 HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to close source dataset")
1732                             dataset->shared->layout.storage.u.virt.list[i].sub_dset[j].dset = NULL;
1733                         } /* end if */
1734                 } /* end for */
1735             } /* end block */
1736             break;
1737 
1738             case H5D_LAYOUT_ERROR:
1739             case H5D_NLAYOUTS:
1740             default:
1741                 HDassert("not implemented yet" && 0);
1742 #ifdef NDEBUG
1743                 HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout")
1744 #endif /* NDEBUG */
1745         } /* end switch */ /*lint !e788 All appropriate cases are covered */
1746 
1747         /* Destroy any cached layout information for the dataset */
1748         if(dataset->shared->layout.ops->dest && (dataset->shared->layout.ops->dest)(dataset) < 0)
1749             HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to destroy layout info")
1750 
1751         /* Free the external file prefix */
1752         dataset->shared->extfile_prefix = (char *)H5MM_xfree(dataset->shared->extfile_prefix);
1753 
1754         /* Free the vds file prefix */
1755         dataset->shared->vds_prefix = (char *)H5MM_xfree(dataset->shared->vds_prefix);
1756 
1757         /* Release layout, fill-value, efl & pipeline messages */
1758         if(dataset->shared->dcpl_id != H5P_DATASET_CREATE_DEFAULT)
1759             free_failed |= (H5O_msg_reset(H5O_PLINE_ID, &dataset->shared->dcpl_cache.pline) < 0) ||
1760                     (H5O_msg_reset(H5O_LAYOUT_ID, &dataset->shared->layout) < 0) ||
1761                     (H5O_msg_reset(H5O_FILL_ID, &dataset->shared->dcpl_cache.fill) < 0) ||
1762                     (H5O_msg_reset(H5O_EFL_ID, &dataset->shared->dcpl_cache.efl) < 0);
1763 
1764         /* Uncork cache entries with object address tag */
1765         if(H5AC_cork(dataset->oloc.file, dataset->oloc.addr, H5AC__GET_CORKED, &corked) < 0)
1766             HDONE_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status")
1767         if(corked)
1768             if(H5AC_cork(dataset->oloc.file, dataset->oloc.addr, H5AC__UNCORK, NULL) < 0)
1769                 HDONE_ERROR(H5E_DATASET, H5E_CANTUNCORK, FAIL, "unable to uncork an object")
1770 
1771         /*
1772          * Release datatype, dataspace and creation property list -- there isn't
1773          * much we can do if one of these fails, so we just continue.
1774          */
1775         free_failed |= (H5I_dec_ref(dataset->shared->type_id) < 0) ||
1776                           (H5S_close(dataset->shared->space) < 0) ||
1777                           (H5I_dec_ref(dataset->shared->dcpl_id) < 0);
1778 
1779         /* Remove the dataset from the list of opened objects in the file */
1780         if(H5FO_top_decr(dataset->oloc.file, dataset->oloc.addr) < 0)
1781             HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't decrement count for object")
1782         if(H5FO_delete(dataset->oloc.file, dataset->oloc.addr) < 0)
1783             HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't remove dataset from list of open objects")
1784 
1785         /* Close the dataset object */
1786         /* (This closes the file, if this is the last object open) */
1787         if(H5O_close(&(dataset->oloc), &file_closed) < 0)
1788             HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release object header")
1789 
1790         /* Evict dataset metadata if evicting on close */
1791         if(!file_closed && H5F_SHARED(dataset->oloc.file) && H5F_EVICT_ON_CLOSE(dataset->oloc.file)) {
1792             if(H5AC_flush_tagged_metadata(dataset->oloc.file, dataset->oloc.addr) < 0)
1793                 HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush tagged metadata")
1794             if(H5AC_evict_tagged_metadata(dataset->oloc.file, dataset->oloc.addr, FALSE) < 0)
1795                 HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to evict tagged metadata")
1796         } /* end if */
1797 
1798         /*
1799          * Free memory.  Before freeing the memory set the file pointer to NULL.
1800          * We always check for a null file pointer in other H5D functions to be
1801          * sure we're not accessing an already freed dataset (see the HDassert()
1802          * above).
1803          */
1804         dataset->oloc.file = NULL;
1805         dataset->shared = H5FL_FREE(H5D_shared_t, dataset->shared);
1806     } /* end if */
1807     else {
1808         /* Decrement the ref. count for this object in the top file */
1809         if(H5FO_top_decr(dataset->oloc.file, dataset->oloc.addr) < 0)
1810             HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't decrement count for object")
1811 
1812         /* Check reference count for this object in the top file */
1813         if(H5FO_top_count(dataset->oloc.file, dataset->oloc.addr) == 0) {
1814             if(H5O_close(&(dataset->oloc), NULL) < 0)
1815                 HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to close")
1816         } /* end if */
1817         else
1818             /* Free object location (i.e. "unhold" the file if appropriate) */
1819             if(H5O_loc_free(&(dataset->oloc)) < 0)
1820                 HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "problem attempting to free location")
1821     } /* end else */
1822 
1823     /* Release the dataset's path info */
1824     if(H5G_name_free(&(dataset->path)) < 0)
1825         free_failed = TRUE;
1826 
1827     /* Free the dataset's memory structure */
1828     dataset = H5FL_FREE(H5D_t, dataset);
1829 
1830     /* Check if anything failed in the middle... */
1831     if(free_failed)
1832         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't free a component of the dataset, but the dataset was freed anyway.")
1833 
1834 done:
1835     FUNC_LEAVE_NOAPI(ret_value)
1836 } /* end H5D_close() */
1837 
1838 
1839 /*-------------------------------------------------------------------------
1840  * Function: H5D_mult_refresh_close
1841  *
1842  * Purpose:  Closing down the needed information when the dataset has
1843  *           multiple opens.  (From H5O_refresh_metadata_close())
1844  *
1845  * Return:   Non-negative on success/Negative on failure
1846  *-------------------------------------------------------------------------
1847  */
1848 herr_t
H5D_mult_refresh_close(hid_t dset_id)1849 H5D_mult_refresh_close(hid_t dset_id)
1850 {
1851     H5D_t       *dataset;                 /* Dataset to refresh */
1852     herr_t      ret_value = SUCCEED;      /* return value */
1853 
1854     FUNC_ENTER_NOAPI(FAIL)
1855 
1856     if(NULL == (dataset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
1857         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
1858 
1859     /* check args */
1860     HDassert(dataset && dataset->oloc.file && dataset->shared);
1861     HDassert(dataset->shared->fo_count > 0);
1862 
1863     if(dataset->shared->fo_count > 1) {
1864         /* Free cached information for each kind of dataset */
1865         switch(dataset->shared->layout.type) {
1866             case H5D_CONTIGUOUS:
1867                 /* Free the data sieve buffer, if it's been allocated */
1868                 if(dataset->shared->cache.contig.sieve_buf)
1869                     dataset->shared->cache.contig.sieve_buf = (unsigned char *)H5FL_BLK_FREE(sieve_buf,dataset->shared->cache.contig.sieve_buf);
1870                 break;
1871 
1872             case H5D_CHUNKED:
1873                 /* Check for skip list for iterating over chunks during I/O to close */
1874                 if(dataset->shared->cache.chunk.sel_chunks) {
1875                     HDassert(H5SL_count(dataset->shared->cache.chunk.sel_chunks) == 0);
1876                     H5SL_close(dataset->shared->cache.chunk.sel_chunks);
1877                     dataset->shared->cache.chunk.sel_chunks = NULL;
1878                 } /* end if */
1879 
1880                 /* Check for cached single chunk dataspace */
1881                 if(dataset->shared->cache.chunk.single_space) {
1882                     (void)H5S_close(dataset->shared->cache.chunk.single_space);
1883                     dataset->shared->cache.chunk.single_space = NULL;
1884                 } /* end if */
1885 
1886                 /* Check for cached single element chunk info */
1887                 if(dataset->shared->cache.chunk.single_chunk_info) {
1888                     dataset->shared->cache.chunk.single_chunk_info = H5FL_FREE(H5D_chunk_info_t, dataset->shared->cache.chunk.single_chunk_info);
1889                     dataset->shared->cache.chunk.single_chunk_info = NULL;
1890                 } /* end if */
1891                 break;
1892 
1893             case H5D_COMPACT:
1894             case H5D_VIRTUAL:
1895                 /* Nothing special to do (info freed in the layout destroy) */
1896                 break;
1897 
1898             case H5D_LAYOUT_ERROR:
1899             case H5D_NLAYOUTS:
1900             default:
1901                 HDassert("not implemented yet" && 0);
1902 #ifdef NDEBUG
1903                 HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout")
1904 #endif /* NDEBUG */
1905         } /* end switch */ /*lint !e788 All appropriate cases are covered */
1906 
1907         /* Destroy any cached layout information for the dataset */
1908         if(dataset->shared->layout.ops->dest && (dataset->shared->layout.ops->dest)(dataset) < 0)
1909             HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to destroy layout info")
1910     } /* end if */
1911 
1912 done:
1913     FUNC_LEAVE_NOAPI(ret_value)
1914 } /* end H5D_mult_refresh_close() */
1915 
1916 
1917 /*-------------------------------------------------------------------------
1918  * Function: H5D_mult_refresh_reopen
1919  *
1920  * Purpose:  Re-initialize the needed info when the dataset has multiple
1921  *           opens.
1922  *
1923  * Return:   Non-negative on success/Negative on failure
1924  *-------------------------------------------------------------------------
1925  */
1926 herr_t
H5D_mult_refresh_reopen(H5D_t * dataset)1927 H5D_mult_refresh_reopen(H5D_t *dataset)
1928 {
1929     herr_t ret_value = SUCCEED;         /* Return value */
1930 
1931     FUNC_ENTER_NOAPI(FAIL)
1932 
1933     /* check args */
1934     HDassert(dataset && dataset->oloc.file && dataset->shared);
1935     HDassert(dataset->shared->fo_count > 0);
1936 
1937     if(dataset->shared->fo_count > 1) {
1938         /* Release dataspace info */
1939         if(H5S_close(dataset->shared->space) < 0)
1940             HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
1941 
1942         /* Re-load dataspace info */
1943         if(NULL == (dataset->shared->space = H5S_read(&(dataset->oloc))))
1944             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load dataspace info from dataset header")
1945 
1946         /* Cache the dataset's dataspace info */
1947         if(H5D__cache_dataspace_info(dataset) < 0)
1948             HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't cache dataspace info")
1949 
1950         /* Release layout info */
1951         if(H5O_msg_reset(H5O_LAYOUT_ID, &dataset->shared->layout) < 0)
1952             HGOTO_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset layout info")
1953 
1954         /* Re-load layout message info */
1955         if(NULL == H5O_msg_read(&(dataset->oloc), H5O_LAYOUT_ID, &(dataset->shared->layout)))
1956             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read data layout message")
1957     } /* end if */
1958 
1959 done:
1960     FUNC_LEAVE_NOAPI(ret_value)
1961 } /* H5D_mult_refresh_reopen() */
1962 
1963 
1964 /*-------------------------------------------------------------------------
1965  * Function: H5D_oloc
1966  *
1967  * Purpose:  Returns a pointer to the object location for a dataset.
1968  *
1969  * Return:   Success:    Ptr to location
1970  *           Failure:    NULL
1971  *-------------------------------------------------------------------------
1972  */
1973 H5O_loc_t *
H5D_oloc(H5D_t * dataset)1974 H5D_oloc(H5D_t *dataset)
1975 {
1976     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
1977     FUNC_ENTER_NOAPI_NOINIT_NOERR
1978 
1979     FUNC_LEAVE_NOAPI(dataset ? &(dataset->oloc) : (H5O_loc_t *)NULL)
1980 } /* end H5D_oloc() */
1981 
1982 
1983 /*-------------------------------------------------------------------------
1984  * Function: H5D_nameof
1985  *
1986  * Purpose:  Returns a pointer to the group hier. path for a dataset.
1987  *
1988  * Return:   Success:    Ptr to entry
1989  *           Failure:    NULL
1990  *-------------------------------------------------------------------------
1991  */
1992 H5G_name_t *
H5D_nameof(H5D_t * dataset)1993 H5D_nameof(H5D_t *dataset)
1994 {
1995     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
1996     FUNC_ENTER_NOAPI_NOINIT_NOERR
1997 
1998     FUNC_LEAVE_NOAPI(dataset ? &(dataset->path) : (H5G_name_t *)NULL)
1999 } /* end H5D_nameof() */
2000 
2001 
2002 /*-------------------------------------------------------------------------
2003  * Function: H5D_typeof
2004  *
2005  * Purpose:  Returns a pointer to the dataset's datatype.  The datatype
2006  *           is not copied.
2007  *
2008  * Return:   Success:    Ptr to the dataset's datatype, uncopied.
2009  *           Failure:    NULL
2010  *-------------------------------------------------------------------------
2011  */
2012 H5T_t *
H5D_typeof(const H5D_t * dset)2013 H5D_typeof(const H5D_t *dset)
2014 {
2015     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2016     FUNC_ENTER_NOAPI_NOINIT_NOERR
2017 
2018     HDassert(dset);
2019     HDassert(dset->shared);
2020     HDassert(dset->shared->type);
2021 
2022     FUNC_LEAVE_NOAPI(dset->shared->type)
2023 } /* end H5D_typeof() */
2024 
2025 
2026 /*-------------------------------------------------------------------------
2027  * Function: H5D__alloc_storage
2028  *
2029  * Purpose:  Allocate storage for the raw data of a dataset.
2030  *
2031  * Return:   Non-negative on success/Negative on failure
2032  *-------------------------------------------------------------------------
2033  */
2034 herr_t
H5D__alloc_storage(const H5D_io_info_t * io_info,H5D_time_alloc_t time_alloc,hbool_t full_overwrite,hsize_t old_dim[])2035 H5D__alloc_storage(const H5D_io_info_t *io_info, H5D_time_alloc_t time_alloc,
2036     hbool_t full_overwrite, hsize_t old_dim[])
2037 {
2038     const H5D_t *dset = io_info->dset;   /* The dataset object */
2039     H5F_t *f = dset->oloc.file;          /* The dataset's file pointer */
2040     H5O_layout_t *layout;                /* The dataset's layout information */
2041     hbool_t must_init_space = FALSE;     /* Flag to indicate that space should be initialized */
2042     hbool_t addr_set = FALSE;            /* Flag to indicate that the dataset's storage address was set */
2043     herr_t  ret_value = SUCCEED;         /* Return value */
2044 
2045     FUNC_ENTER_PACKAGE
2046 
2047     /* check args */
2048     HDassert(dset);
2049     HDassert(f);
2050 
2051     /* If the data is stored in external files, don't set an address for the layout
2052      * We assume that external storage is already
2053      * allocated by the caller, or at least will be before I/O is performed.
2054      */
2055     if(!(H5S_NULL == H5S_GET_EXTENT_TYPE(dset->shared->space) || dset->shared->dcpl_cache.efl.nused > 0)) {
2056         /* Get a pointer to the dataset's layout information */
2057         layout = &(dset->shared->layout);
2058 
2059         switch(layout->type) {
2060             case H5D_CONTIGUOUS:
2061                 if(!(*dset->shared->layout.ops->is_space_alloc)(&dset->shared->layout.storage)) {
2062                     /* Check if we have a zero-sized dataset */
2063                     if(layout->storage.u.contig.size > 0) {
2064                         /* Reserve space in the file for the entire array */
2065                         if(H5D__contig_alloc(f, &layout->storage.u.contig/*out*/) < 0)
2066                             HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize contiguous storage")
2067 
2068                         /* Indicate that we should initialize storage space */
2069                         must_init_space = TRUE;
2070                     } /* end if */
2071                     else
2072                         layout->storage.u.contig.addr = HADDR_UNDEF;
2073 
2074                     /* Indicate that we set the storage addr */
2075                     addr_set = TRUE;
2076                 } /* end if */
2077                 break;
2078 
2079             case H5D_CHUNKED:
2080                 if(!(*dset->shared->layout.ops->is_space_alloc)(&dset->shared->layout.storage)) {
2081                     /* Create the root of the index that manages chunked storage */
2082                     if(H5D__chunk_create(dset /*in,out*/) < 0)
2083                         HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize chunked storage")
2084 
2085                     /* Indicate that we set the storage addr */
2086                     addr_set = TRUE;
2087 
2088                     /* Indicate that we should initialize storage space */
2089                     must_init_space = TRUE;
2090                 } /* end if */
2091 
2092                 /* If space allocation is set to 'early' and we are extending
2093                  * the dataset, indicate that space should be allocated, so the
2094                  * index gets expanded. -QAK
2095                  */
2096                 if(dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_EARLY && time_alloc == H5D_ALLOC_EXTEND)
2097                     must_init_space = TRUE;
2098                 break;
2099 
2100             case H5D_COMPACT:
2101                 /* Check if space is already allocated */
2102                 if(NULL == layout->storage.u.compact.buf) {
2103                     /* Reserve space in layout header message for the entire array.
2104                      * Starting from the 1.8.7 release, we allow dataspace to have
2105                      * zero dimension size.  So the storage size can be zero.
2106                      * SLU 2011/4/4 */
2107                     if(layout->storage.u.compact.size > 0) {
2108                         if(NULL == (layout->storage.u.compact.buf = H5MM_malloc(layout->storage.u.compact.size)))
2109                             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory for compact dataset")
2110                         if(!full_overwrite)
2111                             HDmemset(layout->storage.u.compact.buf, 0, layout->storage.u.compact.size);
2112                         layout->storage.u.compact.dirty = TRUE;
2113 
2114                         /* Indicate that we should initialize storage space */
2115                         must_init_space = TRUE;
2116                     }
2117                     else {
2118                         layout->storage.u.compact.dirty = FALSE;
2119                         must_init_space = FALSE;
2120                     }
2121                 } /* end if */
2122                 break;
2123 
2124             case H5D_VIRTUAL:
2125                 /* No-op, as the raw data is stored elsewhere and the global
2126                  * heap object containing the mapping information is created
2127                  * when the layout message is encoded.  We may wish to move the
2128                  * creation of the global heap object here at some point, but we
2129                  * will have to make sure is it always created before the
2130                  * dataset is closed. */
2131                 break;
2132 
2133             case H5D_LAYOUT_ERROR:
2134             case H5D_NLAYOUTS:
2135             default:
2136                 HDassert("not implemented yet" && 0);
2137 #ifdef NDEBUG
2138                 HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout")
2139 #endif /* NDEBUG */
2140         } /* end switch */ /*lint !e788 All appropriate cases are covered */
2141 
2142         /* Check if we need to initialize the space */
2143         if(must_init_space) {
2144             if(layout->type == H5D_CHUNKED) {
2145                 /* If we are doing incremental allocation and the index got
2146                  * created during a H5Dwrite call, don't initialize the storage
2147                  * now, wait for the actual writes to each block and let the
2148                  * low-level chunking routines handle initialize the fill-values.
2149                  * Otherwise, pass along the space initialization call and let
2150                  * the low-level chunking routines sort out whether to write
2151                  * fill values to the chunks they allocate space for.  Yes,
2152                  * this is icky. -QAK
2153                  */
2154                 if(!(dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_INCR && time_alloc == H5D_ALLOC_WRITE))
2155                     if(H5D__init_storage(io_info, full_overwrite, old_dim) < 0)
2156                         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value")
2157             } /* end if */
2158             else {
2159                 H5D_fill_value_t    fill_status;    /* The fill value status */
2160 
2161                 /* Check the dataset's fill-value status */
2162                 if(H5P_is_fill_value_defined(&dset->shared->dcpl_cache.fill, &fill_status) < 0)
2163                     HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
2164 
2165                 /* If we are filling the dataset on allocation or "if set" and
2166                  * the fill value _is_ set, do that now */
2167                 if(dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC ||
2168                         (dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET && fill_status == H5D_FILL_VALUE_USER_DEFINED))
2169                     if(H5D__init_storage(io_info, full_overwrite, old_dim) < 0)
2170                         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value")
2171             } /* end else */
2172         } /* end if */
2173 
2174         /* If we set the address (and aren't in the middle of creating the
2175          *      dataset), mark the layout header message for later writing to
2176          *      the file.  (this improves forward compatibility).
2177          */
2178         /* (The layout message is already in the dataset's object header, this
2179          *      operation just sets the address and makes it constant)
2180          */
2181         if(time_alloc != H5D_ALLOC_CREATE && addr_set)
2182             /* Mark the layout as dirty, for later writing to the file */
2183             if(H5D__mark(dset, H5D_MARK_LAYOUT) < 0)
2184                 HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to mark dataspace as dirty")
2185     } /* end if */
2186 
2187 done:
2188     FUNC_LEAVE_NOAPI(ret_value)
2189 } /* end H5D__alloc_storage() */
2190 
2191 
2192 /*-------------------------------------------------------------------------
2193  * Function: H5D__init_storage
2194  *
2195  * Purpose:  Initialize the data for a new dataset.  If a selection is
2196  *           defined for SPACE then initialize only that part of the
2197  *           dataset.
2198  *
2199  * Return:   Non-negative on success/Negative on failure
2200  *-------------------------------------------------------------------------
2201  */
2202 static herr_t
H5D__init_storage(const H5D_io_info_t * io_info,hbool_t full_overwrite,hsize_t old_dim[])2203 H5D__init_storage(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_t old_dim[])
2204 {
2205     const H5D_t *dset = io_info->dset;     /* dataset pointer */
2206     herr_t ret_value = SUCCEED;            /* Return value */
2207 
2208     FUNC_ENTER_STATIC
2209 
2210     HDassert(dset);
2211 
2212     switch (dset->shared->layout.type) {
2213         case H5D_COMPACT:
2214             /* If we will be immediately overwriting the values, don't bother to clear them */
2215             if(!full_overwrite) {
2216                 /* Fill the compact dataset storage */
2217                 if(H5D__compact_fill(dset) < 0)
2218                     HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize compact dataset storage")
2219             } /* end if */
2220             break;
2221 
2222         case H5D_CONTIGUOUS:
2223             /* Don't write default fill values to external files */
2224             /* If we will be immediately overwriting the values, don't bother to clear them */
2225             if((dset->shared->dcpl_cache.efl.nused == 0 || dset->shared->dcpl_cache.fill.buf) && !full_overwrite)
2226                 if(H5D__contig_fill(io_info) < 0)
2227                     HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset")
2228             break;
2229 
2230         case H5D_CHUNKED:
2231             /*
2232              * Allocate file space
2233              * for all chunks now and initialize each chunk with the fill value.
2234              */
2235             {
2236                 hsize_t             zero_dim[H5O_LAYOUT_NDIMS] = {0};
2237 
2238                 /* Use zeros for old dimensions if not specified */
2239                 if(old_dim == NULL)
2240                     old_dim = zero_dim;
2241 
2242                 if(H5D__chunk_allocate(io_info, full_overwrite, old_dim) < 0)
2243                     HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset")
2244                 break;
2245             } /* end block */
2246 
2247         case H5D_VIRTUAL:
2248             /* No-op, as the raw data is stored elsewhere */
2249 
2250         case H5D_LAYOUT_ERROR:
2251         case H5D_NLAYOUTS:
2252         default:
2253             HDassert("not implemented yet" && 0);
2254 #ifdef NDEBUG
2255             HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout")
2256 #endif /* NDEBUG */
2257     } /* end switch */ /*lint !e788 All appropriate cases are covered */
2258 
2259 done:
2260     FUNC_LEAVE_NOAPI(ret_value)
2261 } /* end H5D__init_storage() */
2262 
2263 
2264 /*-------------------------------------------------------------------------
2265  * Function: H5D__get_storage_size_real
2266  *
2267  * Purpose:  Determines how much space has been reserved to store the raw
2268  *           data of a dataset.
2269  *
2270  * Return:   Non-negative on success, negative on failure
2271  *-------------------------------------------------------------------------
2272  */
2273 static herr_t
H5D__get_storage_size_real(const H5D_t * dset,hsize_t * storage_size)2274 H5D__get_storage_size_real(const H5D_t *dset, hsize_t *storage_size)
2275 {
2276     herr_t    ret_value = SUCCEED;    /* Return value */
2277 
2278     FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
2279 
2280     switch(dset->shared->layout.type) {
2281         case H5D_CHUNKED:
2282             if((*dset->shared->layout.ops->is_space_alloc)(&dset->shared->layout.storage)) {
2283                 if(H5D__chunk_allocated(dset, storage_size) < 0)
2284                     HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve chunked dataset allocated size")
2285             } /* end if */
2286             else
2287                 *storage_size = 0;
2288             break;
2289 
2290         case H5D_CONTIGUOUS:
2291             /* Datasets which are not allocated yet are using no space on disk */
2292             if((*dset->shared->layout.ops->is_space_alloc)(&dset->shared->layout.storage))
2293                 *storage_size = dset->shared->layout.storage.u.contig.size;
2294             else
2295                 *storage_size = 0;
2296             break;
2297 
2298         case H5D_COMPACT:
2299             *storage_size = dset->shared->layout.storage.u.compact.size;
2300             break;
2301 
2302         case H5D_VIRTUAL:
2303             /* Just set to 0, as virtual datasets do not actually store raw data
2304              */
2305             *storage_size = 0;
2306             break;
2307 
2308         case H5D_LAYOUT_ERROR:
2309         case H5D_NLAYOUTS:
2310         default:
2311             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset type")
2312     } /*lint !e788 All appropriate cases are covered */
2313 
2314 done:
2315     FUNC_LEAVE_NOAPI_TAG(ret_value)
2316 } /* end H5D__get_storage_size_real() */
2317 
2318 
2319 /*-------------------------------------------------------------------------
2320  * Function: H5D__get_storage_size
2321  *
2322  * Purpose:  Determines how much space has been reserved to store the raw
2323  *           data of a dataset.
2324  *
2325  * Note:        This routine is needed so that there's a non-API routine for
2326  *              creating attributes that can set up VOL / SWMR info
2327  *              (which need a DXPL).
2328  *
2329  * Return:   Non-negative on success, negative on failure
2330  *-------------------------------------------------------------------------
2331  */
2332 herr_t
H5D__get_storage_size(const H5D_t * dset,hsize_t * storage_size)2333 H5D__get_storage_size(const H5D_t *dset, hsize_t *storage_size)
2334 {
2335     herr_t    ret_value = SUCCEED;    /* Return value */
2336 
2337     FUNC_ENTER_PACKAGE_VOL
2338 
2339     /* Difficult to error check, since the error value is 0 and 0 is a valid value... :-/ */
2340     if(H5D__get_storage_size_real(dset, storage_size) < 0)
2341         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get size of dataset's storage")
2342 
2343 done:
2344     FUNC_LEAVE_NOAPI_VOL(ret_value)
2345 } /* end H5D__get_storage_size() */
2346 
2347 
2348 /*-------------------------------------------------------------------------
2349  * Function: H5D__get_offset
2350  *
2351  * Purpose:  Private function for H5D__get_offset.  Returns the address
2352  *           of dataset in file.
2353  *
2354  * Return:   Success:        the address of dataset
2355  *           Failure:    HADDR_UNDEF
2356  *-------------------------------------------------------------------------
2357  */
2358 haddr_t
H5D__get_offset(const H5D_t * dset)2359 H5D__get_offset(const H5D_t *dset)
2360 {
2361     haddr_t    ret_value = HADDR_UNDEF;
2362 
2363     FUNC_ENTER_PACKAGE
2364 
2365     HDassert(dset);
2366 
2367     switch(dset->shared->layout.type) {
2368         case H5D_VIRTUAL:
2369         case H5D_CHUNKED:
2370         case H5D_COMPACT:
2371             break;
2372 
2373         case H5D_CONTIGUOUS:
2374             /* If dataspace hasn't been allocated or dataset is stored in
2375              * an external file, the value will be HADDR_UNDEF. */
2376             if(dset->shared->dcpl_cache.efl.nused == 0 || H5F_addr_defined(dset->shared->layout.storage.u.contig.addr))
2377                 /* Return the absolute dataset offset from the beginning of file. */
2378                 ret_value = dset->shared->layout.storage.u.contig.addr + H5F_BASE_ADDR(dset->oloc.file);
2379             break;
2380 
2381         case H5D_LAYOUT_ERROR:
2382         case H5D_NLAYOUTS:
2383         default:
2384             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, HADDR_UNDEF, "unknown dataset layout type")
2385     } /*lint !e788 All appropriate cases are covered */
2386 
2387 done:
2388     FUNC_LEAVE_NOAPI(ret_value)
2389 } /* end H5D__get_offset() */
2390 
2391 
2392 /*-------------------------------------------------------------------------
2393  * Function: H5D_vlen_reclaim
2394  *
2395  * Purpose:  Frees the buffers allocated for storing variable-length data
2396  *           in memory.  Only frees the VL data in the selection defined in the
2397  *           dataspace.
2398  *
2399  * Return:   Non-negative on success, negative on failure
2400  *-------------------------------------------------------------------------
2401  */
2402 herr_t
H5D_vlen_reclaim(hid_t type_id,H5S_t * space,void * buf)2403 H5D_vlen_reclaim(hid_t type_id, H5S_t *space, void *buf)
2404 {
2405     H5T_t *type;                /* Datatype */
2406     H5S_sel_iter_op_t dset_op;  /* Operator for iteration */
2407     H5T_vlen_alloc_info_t vl_alloc_info;   /* VL allocation info */
2408     herr_t ret_value = FAIL;    /* Return value */
2409 
2410     FUNC_ENTER_NOAPI(FAIL)
2411 
2412     /* Check args */
2413     HDassert(H5I_DATATYPE == H5I_get_type(type_id));
2414     HDassert(space);
2415     HDassert(buf);
2416 
2417     if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
2418         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype")
2419 
2420     /* Get the allocation info */
2421     if(H5CX_get_vlen_alloc_info(&vl_alloc_info) < 0)
2422         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info")
2423 
2424     /* Call H5S_select_iterate with args, etc. */
2425     dset_op.op_type = H5S_SEL_ITER_OP_APP;
2426     dset_op.u.app_op.op = H5T_vlen_reclaim;
2427     dset_op.u.app_op.type_id = type_id;
2428 
2429     ret_value = H5S_select_iterate(buf, type, space, &dset_op, &vl_alloc_info);
2430 
2431 done:
2432     FUNC_LEAVE_NOAPI(ret_value)
2433 }   /* end H5D_vlen_reclaim() */
2434 
2435 
2436 /*-------------------------------------------------------------------------
2437  * Function: H5D__vlen_get_buf_size_alloc
2438  *
2439  * Purpose:  This routine makes certain there is enough space in the temporary
2440  *           buffer for the new data to read in.  All the VL data read in is actually
2441  *           placed in this buffer, overwriting the previous data.  Needless to say,
2442  *           this data is not actually usable.
2443  *
2444  * Return:   Non-negative on success, negative on failure
2445  *-------------------------------------------------------------------------
2446  */
2447 void *
H5D__vlen_get_buf_size_alloc(size_t size,void * info)2448 H5D__vlen_get_buf_size_alloc(size_t size, void *info)
2449 {
2450     H5D_vlen_bufsize_t *vlen_bufsize = (H5D_vlen_bufsize_t *)info;
2451     void *ret_value = NULL;     /* Return value */
2452 
2453     FUNC_ENTER_PACKAGE_NOERR
2454 
2455     /* Get a temporary pointer to space for the VL data */
2456     if((vlen_bufsize->vl_tbuf = H5FL_BLK_REALLOC(vlen_vl_buf, vlen_bufsize->vl_tbuf, size)) != NULL)
2457         vlen_bufsize->size += size;
2458 
2459     /* Set return value */
2460     ret_value = vlen_bufsize->vl_tbuf;
2461 
2462     FUNC_LEAVE_NOAPI(ret_value)
2463 } /* end H5D__vlen_get_buf_size_alloc() */
2464 
2465 
2466 /*-------------------------------------------------------------------------
2467  * Function: H5D__vlen_get_buf_size
2468  *
2469  * Purpose:  This routine checks the number of bytes required to store a single
2470  *           element from a dataset in memory, creating a selection with just the
2471  *           single element selected to read in the element and using a custom memory
2472  *           allocator for any VL data encountered.
2473  *           The *size value is modified according to how many bytes are
2474  *           required to store the element in memory.
2475  *
2476  * Implementation: This routine actually performs the read with a custom
2477  *      memory manager which basically just counts the bytes requested and
2478  *      uses a temporary memory buffer (through the H5FL API) to make certain
2479  *      enough space is available to perform the read.  Then the temporary
2480  *      buffer is released and the number of bytes allocated is returned.
2481  *      Kinda kludgy, but easier than the other method of trying to figure out
2482  *      the sizes without actually reading the data in... - QAK
2483  *
2484  * Return:   Non-negative on success, negative on failure
2485  *-------------------------------------------------------------------------
2486  */
2487 herr_t
H5D__vlen_get_buf_size(void H5_ATTR_UNUSED * elem,hid_t type_id,unsigned H5_ATTR_UNUSED ndim,const hsize_t * point,void * op_data)2488 H5D__vlen_get_buf_size(void H5_ATTR_UNUSED *elem, hid_t type_id,
2489     unsigned H5_ATTR_UNUSED ndim, const hsize_t *point, void *op_data)
2490 {
2491     H5D_vlen_bufsize_t *vlen_bufsize = (H5D_vlen_bufsize_t *)op_data;
2492     H5T_t *dt;                          /* Datatype for operation */
2493     herr_t ret_value = SUCCEED;         /* Return value */
2494 
2495     FUNC_ENTER_PACKAGE
2496 
2497     HDassert(op_data);
2498     HDassert(H5I_DATATYPE == H5I_get_type(type_id));
2499 
2500     /* Check args */
2501     if(NULL == (dt = (H5T_t *)H5I_object(type_id)))
2502         HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a datatype")
2503 
2504     /* Make certain there is enough fixed-length buffer available */
2505     if(NULL == (vlen_bufsize->fl_tbuf = H5FL_BLK_REALLOC(vlen_fl_buf, vlen_bufsize->fl_tbuf, H5T_get_size(dt))))
2506         HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't resize tbuf")
2507 
2508     /* Select point to read in */
2509     if(H5S_select_elements(vlen_bufsize->fspace, H5S_SELECT_SET, (hsize_t)1, point) < 0)
2510         HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't select point")
2511 
2512     /* Read in the point (with the custom VL memory allocator) */
2513     if(H5D__read(vlen_bufsize->dset, type_id, vlen_bufsize->mspace, vlen_bufsize->fspace, vlen_bufsize->fl_tbuf) < 0)
2514         HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read point")
2515 
2516 done:
2517     FUNC_LEAVE_NOAPI(ret_value)
2518 } /* end H5D__vlen_get_buf_size() */
2519 
2520 
2521 /*-------------------------------------------------------------------------
2522  * Function: H5D__check_filters
2523  *
2524  * Purpose:  Check if the filters have be initialized for the dataset
2525  *
2526  * Return:   Non-negative on success/Negative on failure
2527  *-------------------------------------------------------------------------
2528  */
2529 herr_t
H5D__check_filters(H5D_t * dataset)2530 H5D__check_filters(H5D_t *dataset)
2531 {
2532     H5O_fill_t *fill;                   /* Dataset's fill value */
2533     herr_t ret_value = SUCCEED;         /* Return value */
2534 
2535     FUNC_ENTER_PACKAGE
2536 
2537     /* Check args */
2538     HDassert(dataset);
2539 
2540     /* Check if the filters in the DCPL will need to encode, and if so, can they?
2541      *
2542      * Filters need encoding if fill value is defined and a fill policy is set
2543      * that requires writing on an extend.
2544      */
2545     fill = &dataset->shared->dcpl_cache.fill;
2546     if(!dataset->shared->checked_filters) {
2547         H5D_fill_value_t fill_status;       /* Whether the fill value is defined */
2548 
2549         /* Retrieve the "defined" status of the fill value */
2550         if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
2551             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Couldn't retrieve fill value from dataset.")
2552 
2553         /* See if we can check the filter status */
2554         if(fill_status == H5D_FILL_VALUE_DEFAULT || fill_status == H5D_FILL_VALUE_USER_DEFINED) {
2555             if(fill->fill_time == H5D_FILL_TIME_ALLOC ||
2556                     (fill->fill_time == H5D_FILL_TIME_IFSET && fill_status == H5D_FILL_VALUE_USER_DEFINED)) {
2557                 /* Filters must have encoding enabled. Ensure that all filters can be applied */
2558                 if(H5Z_can_apply(dataset->shared->dcpl_id, dataset->shared->type_id) < 0)
2559                     HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "can't apply filters")
2560 
2561                 dataset->shared->checked_filters = TRUE;
2562             } /* end if */
2563         } /* end if */
2564     } /* end if */
2565 
2566 done:
2567     FUNC_LEAVE_NOAPI(ret_value)
2568 } /* end H5D__check_filters() */
2569 
2570 
2571 /*-------------------------------------------------------------------------
2572  * Function: H5D__set_extent
2573  *
2574  * Purpose:  Based on H5D_extend, allows change to a lower dimension,
2575  *           calls H5S_set_extent and H5D__chunk_prune_by_extent instead
2576  *
2577  * Return:   Non-negative on success, negative on failure
2578  *-------------------------------------------------------------------------
2579  */
2580 herr_t
H5D__set_extent(H5D_t * dset,const hsize_t * size)2581 H5D__set_extent(H5D_t *dset, const hsize_t *size)
2582 {
2583     hsize_t  curr_dims[H5S_MAX_RANK];   /* Current dimension sizes */
2584     htri_t   changed;                   /* Whether the dataspace changed size */
2585     size_t   u, v;                      /* Local index variable */
2586     unsigned dim_idx;                   /* Dimension index */
2587     herr_t   ret_value = SUCCEED;       /* Return value */
2588 
2589     FUNC_ENTER_PACKAGE_VOL_TAG(dset->oloc.addr)
2590 
2591     /* Check args */
2592     HDassert(dset);
2593     HDassert(size);
2594 
2595     /* Check if we are allowed to modify this file */
2596     if(0 == (H5F_INTENT(dset->oloc.file) & H5F_ACC_RDWR))
2597         HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file")
2598 
2599     /* Check if we are allowed to modify the space; only datasets with chunked and external storage are allowed to be modified */
2600     if(H5D_COMPACT == dset->shared->layout.type)
2601         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "dataset has compact storage")
2602     if(H5D_CONTIGUOUS == dset->shared->layout.type && 0 == dset->shared->dcpl_cache.efl.nused)
2603         HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "dataset has contiguous storage")
2604 
2605     /* Check if the filters in the DCPL will need to encode, and if so, can they? */
2606     if(H5D__check_filters(dset) < 0)
2607         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't apply filters")
2608 
2609     /* Keep the current dataspace dimensions for later */
2610     HDcompile_assert(sizeof(curr_dims) == sizeof(dset->shared->curr_dims));
2611     HDmemcpy(curr_dims, dset->shared->curr_dims, H5S_MAX_RANK * sizeof(curr_dims[0]));
2612 
2613     /* Modify the size of the dataspace */
2614     if((changed = H5S_set_extent(dset->shared->space, size)) < 0)
2615         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of dataspace")
2616 
2617     /* Don't bother updating things, unless they've changed */
2618     if(changed) {
2619         hbool_t shrink = FALSE;         /* Flag to indicate a dimension has shrank */
2620         hbool_t expand = FALSE;         /* Flag to indicate a dimension has grown */
2621         hbool_t update_chunks = FALSE;  /* Flag to indicate chunk cache update is needed */
2622 
2623         /* Determine if we are shrinking and/or expanding any dimensions */
2624         for(dim_idx = 0; dim_idx < dset->shared->ndims; dim_idx++) {
2625             /* Check for various status changes */
2626             if(size[dim_idx] < curr_dims[dim_idx])
2627                 shrink = TRUE;
2628             if(size[dim_idx] > curr_dims[dim_idx])
2629                 expand = TRUE;
2630 
2631             /* Chunked storage specific checks */
2632             if(H5D_CHUNKED == dset->shared->layout.type && dset->shared->ndims > 1) {
2633                 hsize_t scaled;             /* Scaled value */
2634 
2635                 /* Compute the scaled dimension size value */
2636                 if(dset->shared->layout.u.chunk.dim[dim_idx] == 0)
2637                     HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", dim_idx)
2638 
2639                 scaled = size[dim_idx] / dset->shared->layout.u.chunk.dim[dim_idx];
2640 
2641                 /* Check if scaled dimension size changed */
2642                 if(scaled != dset->shared->cache.chunk.scaled_dims[dim_idx]) {
2643                     hsize_t scaled_power2up;    /* Scaled value, rounded to next power of 2 */
2644 
2645                     /* Update the scaled dimension size value for the current dimension */
2646                     dset->shared->cache.chunk.scaled_dims[dim_idx] = scaled;
2647 
2648                     /* Check if algorithm for computing hash values will change */
2649                     if((scaled > dset->shared->cache.chunk.nslots &&
2650                                 dset->shared->cache.chunk.scaled_dims[dim_idx] <= dset->shared->cache.chunk.nslots)
2651                             || (scaled <= dset->shared->cache.chunk.nslots &&
2652                                 dset->shared->cache.chunk.scaled_dims[dim_idx] > dset->shared->cache.chunk.nslots))
2653                         update_chunks = TRUE;
2654 
2655                     if(!(scaled_power2up = H5VM_power2up(scaled)))
2656                         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get the next power of 2")
2657 
2658                     /* Check if the number of bits required to encode the scaled size value changed */
2659                     if(dset->shared->cache.chunk.scaled_power2up[dim_idx] != scaled_power2up) {
2660                         /* Update the 'power2up' & 'encode_bits' values for the current dimension */
2661                         dset->shared->cache.chunk.scaled_power2up[dim_idx] = scaled_power2up;
2662                         dset->shared->cache.chunk.scaled_encode_bits[dim_idx] = H5VM_log2_gen(scaled_power2up);
2663 
2664                         /* Indicate that the cached chunk indices need to be updated */
2665                         update_chunks = TRUE;
2666                     } /* end if */
2667                 } /* end if */
2668             } /* end if */
2669 
2670             /* Update the cached copy of the dataset's dimensions */
2671             dset->shared->curr_dims[dim_idx] = size[dim_idx];
2672         } /* end for */
2673 
2674         /*-------------------------------------------------------------------------
2675          * Modify the dataset storage
2676          *-------------------------------------------------------------------------
2677          */
2678         /* Update the index values for the cached chunks for this dataset */
2679         if(H5D_CHUNKED == dset->shared->layout.type) {
2680             /* Set the cached chunk info */
2681             if(H5D__chunk_set_info(dset) < 0)
2682                 HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to update # of chunks")
2683 
2684             /* Check if updating the chunk cache indices is necessary */
2685             if(update_chunks)
2686                 /* Update the chunk cache indices */
2687                 if(H5D__chunk_update_cache(dset) < 0)
2688                     HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update cached chunk indices")
2689         } /* end if */
2690 
2691         /* Operations for virtual datasets */
2692         if(H5D_VIRTUAL == dset->shared->layout.type) {
2693             /* Check that the dimensions of the VDS are large enough */
2694             if(H5D_virtual_check_min_dims(dset) < 0)
2695                 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "virtual dataset dimensions not large enough to contain all limited dimensions in all selections")
2696 
2697             /* Patch the virtual selection dataspaces */
2698             for(u = 0; u < dset->shared->layout.storage.u.virt.list_nused; u++) {
2699                 /* Patch extent */
2700                 if(H5S_set_extent(dset->shared->layout.storage.u.virt.list[u].source_dset.virtual_select, size) < 0)
2701                     HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of dataspace")
2702                 dset->shared->layout.storage.u.virt.list[u].virtual_space_status = H5O_VIRTUAL_STATUS_CORRECT;
2703 
2704                 /* Patch sub-source datasets */
2705                 for(v = 0; v < dset->shared->layout.storage.u.virt.list[u].sub_dset_nalloc; v++)
2706                     if(H5S_set_extent(dset->shared->layout.storage.u.virt.list[u].sub_dset[v].virtual_select, size) < 0)
2707                         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of dataspace")
2708             } /* end for */
2709 
2710             /* Mark virtual datasets as not fully initialized so internal
2711              * selections are recalculated (at next I/O operation) */
2712             dset->shared->layout.storage.u.virt.init = FALSE;
2713         } /* end if */
2714 
2715         /* Allocate space for the new parts of the dataset, if appropriate */
2716         if(expand && dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_EARLY) {
2717             H5D_io_info_t io_info;
2718 
2719             io_info.dset = dset;
2720 
2721             if(H5D__alloc_storage(&io_info, H5D_ALLOC_EXTEND, FALSE, curr_dims) < 0)
2722                 HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to extend dataset storage")
2723         } /* end if */
2724         /*-------------------------------------------------------------------------
2725          * Remove chunk information in the case of chunked datasets
2726          * This removal takes place only in case we are shrinking the dateset
2727          * and if the chunks are written
2728          *-------------------------------------------------------------------------
2729          */
2730         if(H5D_CHUNKED == dset->shared->layout.type) {
2731             if(shrink && (*dset->shared->layout.ops->is_space_alloc)(&dset->shared->layout.storage))
2732                 /* Remove excess chunks */
2733                 if(H5D__chunk_prune_by_extent(dset, curr_dims) < 0)
2734                     HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to remove chunks")
2735 
2736             /* Update chunks that are no longer edge chunks as a result of
2737              * expansion */
2738             if(expand && (dset->shared->layout.u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS)
2739                     && (dset->shared->dcpl_cache.pline.nused > 0))
2740                 if(H5D__chunk_update_old_edge_chunks(dset, curr_dims) < 0)
2741                     HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to do update old edge chunks")
2742         } /* end if */
2743 
2744         /* Mark the dataspace as dirty, for later writing to the file */
2745         if(H5D__mark(dset, H5D_MARK_SPACE) < 0)
2746             HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to mark dataspace as dirty")
2747     } /* end if */
2748 
2749 done:
2750     FUNC_LEAVE_NOAPI_VOL_TAG(ret_value)
2751 } /* end H5D__set_extent() */
2752 
2753 
2754 /*-------------------------------------------------------------------------
2755  * Function: H5D__flush_sieve_buf
2756  *
2757  * Purpose:  Flush any dataset sieve buffer info cached in memory
2758  *
2759  * Return:   Success:    Non-negative
2760  *           Failure:    Negative
2761  *-------------------------------------------------------------------------
2762  */
2763 herr_t
H5D__flush_sieve_buf(H5D_t * dataset)2764 H5D__flush_sieve_buf(H5D_t *dataset)
2765 {
2766     herr_t ret_value = SUCCEED;         /* Return value */
2767 
2768     FUNC_ENTER_PACKAGE
2769 
2770     /* Check args */
2771     HDassert(dataset);
2772 
2773     /* Flush the raw data buffer, if we have a dirty one */
2774     if(dataset->shared->cache.contig.sieve_buf && dataset->shared->cache.contig.sieve_dirty) {
2775         HDassert(dataset->shared->layout.type != H5D_COMPACT);      /* We should never have a sieve buffer for compact storage */
2776 
2777         /* Write dirty data sieve buffer to file */
2778         if(H5F_block_write(dataset->oloc.file, H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc,
2779                 dataset->shared->cache.contig.sieve_size, dataset->shared->cache.contig.sieve_buf) < 0)
2780             HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
2781 
2782         /* Reset sieve buffer dirty flag */
2783         dataset->shared->cache.contig.sieve_dirty = FALSE;
2784     } /* end if */
2785 
2786 done:
2787     FUNC_LEAVE_NOAPI(ret_value)
2788 } /* end H5D__flush_sieve_buf() */
2789 
2790 
2791 /*-------------------------------------------------------------------------
2792  * Function: H5D__flush_real
2793  *
2794  * Purpose:  Flush any dataset information cached in memory
2795  *
2796  * Return:   Success:    Non-negative
2797  *           Failure:    Negative
2798  *-------------------------------------------------------------------------
2799  */
2800 herr_t
H5D__flush_real(H5D_t * dataset)2801 H5D__flush_real(H5D_t *dataset)
2802 {
2803     herr_t ret_value = SUCCEED;         /* Return value */
2804 
2805     FUNC_ENTER_PACKAGE_TAG(dataset->oloc.addr)
2806 
2807     /* Check args */
2808     HDassert(dataset);
2809     HDassert(dataset->shared);
2810 
2811     /* Avoid flushing the dataset (again) if it's closing */
2812     if(!dataset->shared->closing)
2813         /* Flush cached raw data for each kind of dataset layout */
2814         if(dataset->shared->layout.ops->flush && (dataset->shared->layout.ops->flush)(dataset) < 0)
2815             HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush raw data")
2816 
2817 done:
2818     FUNC_LEAVE_NOAPI_TAG(ret_value)
2819 } /* end H5D__flush_real() */
2820 
2821 
2822 /*-------------------------------------------------------------------------
2823  * Function: H5D__flush
2824  *
2825  * Purpose:  Flush dataset information cached in memory
2826  *
2827  * Return:   Success:    Non-negative
2828  *           Failure:    Negative
2829  *-------------------------------------------------------------------------
2830  */
2831 herr_t
H5D__flush(H5D_t * dset,hid_t dset_id)2832 H5D__flush(H5D_t *dset, hid_t dset_id)
2833 {
2834     herr_t ret_value = SUCCEED;         /* Return value */
2835 
2836     FUNC_ENTER_PACKAGE_VOL
2837 
2838     /* Check args */
2839     HDassert(dset);
2840     HDassert(dset->shared);
2841 
2842     /* Flush any dataset information still cached in memory */
2843     if(H5D__flush_real(dset) < 0)
2844         HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush cached dataset info")
2845 
2846     /* Flush object's metadata to file */
2847     if(H5O_flush_common(&dset->oloc, dset_id) < 0)
2848         HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush dataset and object flush callback")
2849 
2850 done:
2851     FUNC_LEAVE_NOAPI_VOL(ret_value)
2852 } /* end H5D__flush() */
2853 
2854 
2855 /*-------------------------------------------------------------------------
2856  * Function: H5D__format_convert
2857  *
2858  * Purpose:  For chunked: downgrade the chunk indexing type to version 1 B-tree
2859  *           For compact/contiguous: downgrade layout version to 3
2860  *
2861  * Return:   Success:    Non-negative
2862  *           Failure:    Negative
2863  *-------------------------------------------------------------------------
2864  */
2865 herr_t
H5D__format_convert(H5D_t * dataset)2866 H5D__format_convert(H5D_t *dataset)
2867 {
2868     H5D_chk_idx_info_t new_idx_info;        /* Index info for the new layout */
2869     H5D_chk_idx_info_t idx_info;            /* Index info for the current layout */
2870     H5O_layout_t *newlayout = NULL;         /* The new layout */
2871     hbool_t init_new_index = FALSE;         /* Indicate that the new chunk index is initialized */
2872     hbool_t delete_old_layout = FALSE;      /* Indicate that the old layout message is deleted */
2873     hbool_t add_new_layout = FALSE;         /* Indicate that the new layout message is added */
2874     herr_t ret_value = SUCCEED;             /* Return value */
2875 
2876     FUNC_ENTER_PACKAGE_VOL_TAG(dataset->oloc.addr)
2877 
2878     /* Check args */
2879     HDassert(dataset);
2880 
2881     switch(dataset->shared->layout.type) {
2882         case H5D_CHUNKED:
2883             HDassert(dataset->shared->layout.u.chunk.idx_type != H5D_CHUNK_IDX_BTREE);
2884 
2885             if(NULL == (newlayout = (H5O_layout_t *)H5MM_calloc(sizeof(H5O_layout_t))))
2886                 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate buffer")
2887 
2888             /* Set up the current index info */
2889             idx_info.f = dataset->oloc.file;
2890             idx_info.pline = &dataset->shared->dcpl_cache.pline;
2891             idx_info.layout = &dataset->shared->layout.u.chunk;
2892             idx_info.storage = &dataset->shared->layout.storage.u.chunk;
2893 
2894             /* Copy the current layout info to the new layout */
2895             HDmemcpy(newlayout, &dataset->shared->layout, sizeof(H5O_layout_t));
2896 
2897             /* Set up info for version 1 B-tree in the new layout */
2898             newlayout->version = H5O_LAYOUT_VERSION_3;
2899             newlayout->storage.u.chunk.idx_type = H5D_CHUNK_IDX_BTREE;
2900             newlayout->storage.u.chunk.idx_addr = HADDR_UNDEF;
2901             newlayout->storage.u.chunk.ops = H5D_COPS_BTREE;
2902             newlayout->storage.u.chunk.u.btree.shared = NULL;
2903 
2904             /* Set up the index info to version 1 B-tree */
2905             new_idx_info.f = dataset->oloc.file;
2906             new_idx_info.pline = &dataset->shared->dcpl_cache.pline;
2907             new_idx_info.layout = &(newlayout->u).chunk;
2908             new_idx_info.storage = &(newlayout->storage).u.chunk;
2909 
2910             /* Initialize version 1 B-tree */
2911             if(new_idx_info.storage->ops->init && (new_idx_info.storage->ops->init)(&new_idx_info, dataset->shared->space, dataset->oloc.addr) < 0)
2912                 HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize indexing information")
2913             init_new_index = TRUE;
2914 
2915             /* If the current chunk index exists */
2916             if(H5F_addr_defined(idx_info.storage->idx_addr)) {
2917 
2918                 /* Create v1 B-tree chunk index */
2919                 if((new_idx_info.storage->ops->create)(&new_idx_info) < 0)
2920                     HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create chunk index")
2921 
2922                 /* Iterate over the chunks in the current index and insert the chunk addresses
2923                  * into the version 1 B-tree chunk index
2924                  */
2925                 if(H5D__chunk_format_convert(dataset, &idx_info, &new_idx_info) < 0)
2926                     HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate/convert chunk index")
2927             } /* end if */
2928 
2929             /* Delete the old "current" layout message */
2930             if(H5O_msg_remove(&dataset->oloc, H5O_LAYOUT_ID, H5O_ALL, FALSE) < 0)
2931                 HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete layout message")
2932 
2933             delete_old_layout = TRUE;
2934 
2935             /* Append the new layout message to the object header */
2936             if(H5O_msg_create(&dataset->oloc, H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, newlayout) < 0)
2937                 HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout header message")
2938 
2939             add_new_layout = TRUE;
2940 
2941             /* Release the old (current) chunk index */
2942             if(idx_info.storage->ops->dest && (idx_info.storage->ops->dest)(&idx_info) < 0)
2943                 HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to release chunk index info")
2944 
2945             /* Copy the new layout to the dataset's layout */
2946             HDmemcpy(&dataset->shared->layout, newlayout, sizeof(H5O_layout_t));
2947 
2948             break;
2949 
2950         case H5D_CONTIGUOUS:
2951         case H5D_COMPACT:
2952             HDassert(dataset->shared->layout.version > H5O_LAYOUT_VERSION_DEFAULT);
2953             dataset->shared->layout.version = H5O_LAYOUT_VERSION_DEFAULT;
2954             if(H5O_msg_write(&(dataset->oloc), H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &(dataset->shared->layout)) < 0)
2955                 HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message")
2956             break;
2957 
2958         case H5D_VIRTUAL:
2959             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "virtual dataset layout not supported")
2960 
2961         case H5D_LAYOUT_ERROR:
2962         case H5D_NLAYOUTS:
2963             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset layout type")
2964 
2965         default:
2966             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown dataset layout type")
2967     } /* end switch */
2968 
2969 done:
2970     if(ret_value < 0 && dataset->shared->layout.type == H5D_CHUNKED) {
2971         /* Remove new layout message */
2972         if(add_new_layout)
2973             if(H5O_msg_remove(&dataset->oloc, H5O_LAYOUT_ID, H5O_ALL, FALSE) < 0)
2974                 HDONE_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete layout message")
2975 
2976         /* Add back old layout message */
2977         if(delete_old_layout)
2978             if(H5O_msg_create(&dataset->oloc, H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &dataset->shared->layout) < 0)
2979                 HDONE_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to add layout header message")
2980 
2981         /* Clean up v1 b-tree chunk index */
2982         if(init_new_index) {
2983             if(H5F_addr_defined(new_idx_info.storage->idx_addr)) {
2984                 /* Check for valid address i.e. tag */
2985                 if(!H5F_addr_defined(dataset->oloc.addr))
2986                     HDONE_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "address undefined")
2987 
2988                 /* Expunge from cache all v1 B-tree type entries associated with tag */
2989                 if(H5AC_expunge_tag_type_metadata(dataset->oloc.file, dataset->oloc.addr, H5AC_BT_ID, H5AC__NO_FLAGS_SET))
2990                     HDONE_ERROR(H5E_DATASET, H5E_CANTEXPUNGE, FAIL, "unable to expunge index metadata")
2991             } /* end if */
2992 
2993             /* Delete v1 B-tree chunk index */
2994             if(new_idx_info.storage->ops->dest && (new_idx_info.storage->ops->dest)(&new_idx_info) < 0)
2995                 HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to release chunk index info")
2996         } /* end if */
2997     } /* end if */
2998 
2999     if(newlayout != NULL)
3000         newlayout = (H5O_layout_t *)H5MM_xfree(newlayout);
3001 
3002     FUNC_LEAVE_NOAPI_VOL_TAG(ret_value)
3003 } /* end H5D__format_convert() */
3004 
3005 
3006 /*-------------------------------------------------------------------------
3007  * Function: H5D__mark
3008  *
3009  * Purpose:  Mark some aspect of a dataset as dirty
3010  *
3011  * Return:   Success:    Non-negative
3012  *           Failure:    Negative
3013  *-------------------------------------------------------------------------
3014  */
3015 herr_t
H5D__mark(const H5D_t * dataset,unsigned flags)3016 H5D__mark(const H5D_t *dataset, unsigned flags)
3017 {
3018     H5O_t *oh = NULL;                   /* Pointer to dataset's object header */
3019     herr_t ret_value = SUCCEED;         /* Return value */
3020 
3021     FUNC_ENTER_PACKAGE
3022 
3023     /* Check args */
3024     HDassert(dataset);
3025     HDassert(!(flags & (unsigned)~(H5D_MARK_SPACE | H5D_MARK_LAYOUT)));
3026 
3027     /* Mark aspects of the dataset as dirty */
3028     if(flags) {
3029         unsigned update_flags = H5O_UPDATE_TIME;        /* Modification time flag */
3030 
3031         /* Pin the object header */
3032         if(NULL == (oh = H5O_pin(&dataset->oloc)))
3033             HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header")
3034 
3035         /* Update the layout on disk, if it's been changed */
3036         if(flags & H5D_MARK_LAYOUT) {
3037             if(H5D__layout_oh_write(dataset, oh, update_flags) < 0)
3038                 HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update layout info")
3039 
3040             /* Reset the "update the modification time" flag, so we only do it once */
3041             update_flags = 0;
3042         } /* end if */
3043 
3044         /* Update the dataspace on disk, if it's been changed */
3045         if(flags & H5D_MARK_SPACE) {
3046             if(H5S_write(dataset->oloc.file, oh, update_flags, dataset->shared->space) < 0)
3047                 HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace")
3048 
3049             /* Reset the "update the modification time" flag, so we only do it once */
3050             update_flags = 0;
3051         } /* end if */
3052 
3053         /* _Somebody_ should have update the modification time! */
3054         HDassert(update_flags == 0);
3055     } /* end if */
3056 
3057 done:
3058     /* Release pointer to object header */
3059     if(oh != NULL)
3060         if(H5O_unpin(oh) < 0)
3061             HDONE_ERROR(H5E_DATASET, H5E_CANTUNPIN, FAIL, "unable to unpin dataset object header")
3062 
3063     FUNC_LEAVE_NOAPI(ret_value)
3064 } /* end H5D__mark() */
3065 
3066 
3067 /*-------------------------------------------------------------------------
3068  * Function: H5D__flush_all_cb
3069  *
3070  * Purpose:  Flush any dataset information cached in memory
3071  *
3072  * Return:   Success:    Non-negative
3073  *           Failure:    Negative
3074  *-------------------------------------------------------------------------
3075  */
3076 static int
H5D__flush_all_cb(void * _dataset,hid_t H5_ATTR_UNUSED id,void * _udata)3077 H5D__flush_all_cb(void *_dataset, hid_t H5_ATTR_UNUSED id, void *_udata)
3078 {
3079     H5D_t *dataset = (H5D_t *)_dataset; /* Dataset pointer */
3080     H5F_t *f = (H5F_t *)_udata;         /* User data for callback */
3081     int   ret_value = H5_ITER_CONT;     /* Return value */
3082 
3083     FUNC_ENTER_STATIC
3084 
3085     /* Check args */
3086     HDassert(dataset);
3087     HDassert(f);
3088 
3089     /* Check for dataset in same file */
3090     if(f == dataset->oloc.file)
3091         /* Flush the dataset's information */
3092         if(H5D__flush_real(dataset) < 0)
3093             HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, H5_ITER_ERROR, "unable to flush cached dataset info")
3094 
3095 done:
3096     FUNC_LEAVE_NOAPI(ret_value)
3097 } /* end H5D__flush_all_cb() */
3098 
3099 
3100 /*-------------------------------------------------------------------------
3101  * Function: H5D_flush_all
3102  *
3103  * Purpose:  Flush any dataset information cached in memory
3104  *
3105  * Return:   Success:    Non-negative
3106  *           Failure:    Negative
3107  *-------------------------------------------------------------------------
3108  */
3109 herr_t
H5D_flush_all(const H5F_t * f)3110 H5D_flush_all(const H5F_t *f)
3111 {
3112     herr_t         ret_value = SUCCEED;    /* Return value */
3113 
3114     FUNC_ENTER_NOAPI(FAIL)
3115 
3116     /* Check args */
3117     HDassert(f);
3118 
3119     /* Iterate over all the open datasets */
3120     if(H5I_iterate(H5I_DATASET, H5D__flush_all_cb, (void *)f, FALSE) < 0) /* Casting away const OK -QAK */
3121         HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to flush cached dataset info")
3122 
3123 done:
3124     FUNC_LEAVE_NOAPI(ret_value)
3125 } /* end H5D_flush_all() */
3126 
3127 
3128 /*-------------------------------------------------------------------------
3129  * Function:    H5D__get_create_plist
3130  *
3131  * Purpose:     Internal routine to retrieve a dataset's creation property list.
3132  *
3133  * Note:        This routine is needed so that there's a non-API routine
3134  *              that can set up VOL / SWMR info (which need a DXPL).
3135  *
3136  * Return:	Success:	ID for a copy of the dataset creation property
3137  *				list.  The property list ID should be released
3138  *				by calling H5Pclose().
3139  *
3140  *		Failure:	FAIL
3141  *
3142  * Programmer:	Quincey Koziol
3143  *		December 18, 2017
3144  *
3145  *-------------------------------------------------------------------------
3146  */
3147 hid_t
H5D__get_create_plist(const H5D_t * dset)3148 H5D__get_create_plist(const H5D_t *dset)
3149 {
3150     hid_t ret_value = FAIL;     /* Return value */
3151 
3152     FUNC_ENTER_PACKAGE_VOL
3153 
3154     /* Check arguments */
3155     HDassert(dset);
3156 
3157     /* Retrieve the DCPL */
3158     if((ret_value = H5D_get_create_plist(dset)) < 0)
3159 	HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset's creation property list")
3160 
3161 done:
3162     FUNC_LEAVE_NOAPI_VOL(ret_value)
3163 } /* end H5D__get_create_plist() */
3164 
3165 
3166 /*-------------------------------------------------------------------------
3167  * Function: H5D_get_create_plist
3168  *
3169  * Purpose:  Private function for H5Dget_create_plist
3170  *
3171  * Return:   Success:    ID for a copy of the dataset creation
3172  *                property list.  The template should be
3173  *                released by calling H5P_close().
3174  *           Failure:    FAIL
3175  *-------------------------------------------------------------------------
3176  */
3177 hid_t
H5D_get_create_plist(const H5D_t * dset)3178 H5D_get_create_plist(const H5D_t *dset)
3179 {
3180     H5P_genplist_t      *dcpl_plist;            /* Dataset's DCPL */
3181     H5P_genplist_t      *new_plist;             /* Copy of dataset's DCPL */
3182     H5O_layout_t        copied_layout;          /* Layout to tweak */
3183     H5O_fill_t          copied_fill;            /* Fill value to tweak */
3184     H5O_efl_t           copied_efl;             /* External file list to tweak */
3185     hid_t               new_dcpl_id = FAIL;
3186     hid_t               ret_value = H5I_INVALID_HID;    /* Return value */
3187 
3188     FUNC_ENTER_NOAPI(FAIL)
3189 
3190     /* Check args */
3191     if(NULL == (dcpl_plist = (H5P_genplist_t *)H5I_object(dset->shared->dcpl_id)))
3192         HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "can't get property list")
3193 
3194     /* Copy the creation property list */
3195     if((new_dcpl_id = H5P_copy_plist(dcpl_plist, TRUE)) < 0)
3196         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to copy the creation property list")
3197     if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dcpl_id)))
3198         HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "can't get property list")
3199 
3200     /* Retrieve any object creation properties */
3201     if(H5O_get_create_plist(&dset->oloc, new_plist) < 0)
3202         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get object creation info")
3203 
3204     /* Get the layout property */
3205     if(H5P_peek(new_plist, H5D_CRT_LAYOUT_NAME, &copied_layout) < 0)
3206         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get layout")
3207 
3208     /* Reset layout values set when dataset is created */
3209     copied_layout.ops = NULL;
3210     switch(copied_layout.type) {
3211         case H5D_COMPACT:
3212             copied_layout.storage.u.compact.buf = H5MM_xfree(copied_layout.storage.u.compact.buf);
3213             HDmemset(&copied_layout.storage.u.compact, 0, sizeof(copied_layout.storage.u.compact));
3214             break;
3215 
3216         case H5D_CONTIGUOUS:
3217             copied_layout.storage.u.contig.addr = HADDR_UNDEF;
3218             copied_layout.storage.u.contig.size = 0;
3219             break;
3220 
3221         case H5D_CHUNKED:
3222             /* Reset chunk size */
3223             copied_layout.u.chunk.size = 0;
3224 
3225             /* Reset index info, if the chunk ops are set */
3226             if(copied_layout.storage.u.chunk.ops)
3227                 /* Reset address and pointer of the array struct for the chunked storage index */
3228                 if(H5D_chunk_idx_reset(&copied_layout.storage.u.chunk, TRUE) < 0)
3229                     HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to reset chunked storage index in dest")
3230 
3231             /* Reset chunk index ops */
3232             copied_layout.storage.u.chunk.ops = NULL;
3233             break;
3234 
3235         case H5D_VIRTUAL:
3236             copied_layout.storage.u.virt.serial_list_hobjid.addr = HADDR_UNDEF;
3237             copied_layout.storage.u.virt.serial_list_hobjid.idx = 0;
3238             break;
3239 
3240         case H5D_LAYOUT_ERROR:
3241         case H5D_NLAYOUTS:
3242         default:
3243             HDassert(0 && "Unknown layout type!");
3244     } /* end switch */
3245 
3246     /* Set back the (possibly modified) layout property to property list */
3247     if(H5P_poke(new_plist, H5D_CRT_LAYOUT_NAME, &copied_layout) < 0)
3248         HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set layout")
3249 
3250     /* Get the fill value property */
3251     if(H5P_peek(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0)
3252         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value")
3253 
3254     /* Check if there is a fill value, but no type yet */
3255     if(copied_fill.buf != NULL && copied_fill.type == NULL) {
3256         H5T_path_t *tpath;      /* Conversion information*/
3257 
3258         /* Copy the dataset type into the fill value message */
3259         if(NULL == (copied_fill.type = H5T_copy(dset->shared->type, H5T_COPY_TRANSIENT)))
3260             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy dataset datatype for fill value")
3261 
3262         /* Set up type conversion function */
3263         if(NULL == (tpath = H5T_path_find(dset->shared->type, copied_fill.type)))
3264             HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types")
3265 
3266         /* Convert disk form of fill value into memory form */
3267         if(!H5T_path_noop(tpath)) {
3268             hid_t dst_id, src_id;       /* Source & destination datatypes for type conversion */
3269             uint8_t *bkg_buf = NULL;    /* Background conversion buffer */
3270             size_t bkg_size;            /* Size of background buffer */
3271 
3272             /* Wrap copies of types to convert */
3273             dst_id = H5I_register(H5I_DATATYPE, H5T_copy(copied_fill.type, H5T_COPY_TRANSIENT), FALSE);
3274             if(dst_id < 0)
3275                 HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
3276             src_id = H5I_register(H5I_DATATYPE, H5T_copy(dset->shared->type, H5T_COPY_ALL), FALSE);
3277             if(src_id < 0) {
3278                 H5I_dec_ref(dst_id);
3279                 HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
3280             } /* end if */
3281 
3282             /* Allocate a background buffer */
3283             bkg_size = MAX(H5T_GET_SIZE(copied_fill.type), H5T_GET_SIZE(dset->shared->type));
3284             if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size))) {
3285                 H5I_dec_ref(src_id);
3286                 H5I_dec_ref(dst_id);
3287                 HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed")
3288             } /* end if */
3289 
3290             /* Convert fill value */
3291             if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, copied_fill.buf, bkg_buf) < 0) {
3292                 H5I_dec_ref(src_id);
3293                 H5I_dec_ref(dst_id);
3294                 if(bkg_buf)
3295                     bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf);
3296                 HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
3297             } /* end if */
3298 
3299             /* Release local resources */
3300             if(H5I_dec_ref(src_id) < 0)
3301                 HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object")
3302             if(H5I_dec_ref(dst_id) < 0)
3303                 HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object")
3304             if(bkg_buf)
3305                 bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf);
3306         } /* end if */
3307     } /* end if */
3308 
3309     /* Set back the (possibly modified) fill value property to property list */
3310     if(H5P_poke(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0)
3311         HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set fill value")
3312 
3313     /* Get the fill value property */
3314     if(H5P_peek(new_plist, H5D_CRT_EXT_FILE_LIST_NAME, &copied_efl) < 0)
3315         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get external file list")
3316 
3317     /* Reset efl name_offset and heap_addr, these are the values when the dataset is created */
3318     if(copied_efl.slot) {
3319         unsigned u;
3320 
3321         copied_efl.heap_addr = HADDR_UNDEF;
3322         for(u = 0; u < copied_efl.nused; u++)
3323             copied_efl.slot[u].name_offset = 0;
3324     } /* end if */
3325 
3326     /* Set back the (possibly modified) external file list property to property list */
3327     if(H5P_poke(new_plist, H5D_CRT_EXT_FILE_LIST_NAME, &copied_efl) < 0)
3328         HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set external file list")
3329 
3330     /* Set the return value */
3331     ret_value = new_dcpl_id;
3332 
3333 done:
3334     if(ret_value < 0)
3335         if(new_dcpl_id > 0)
3336             if(H5I_dec_app_ref(new_dcpl_id) < 0)
3337                 HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object")
3338 
3339     FUNC_LEAVE_NOAPI(ret_value)
3340 } /* end H5D_get_create_plist() */
3341 
3342 
3343 /*-------------------------------------------------------------------------
3344  * Function: H5D_get_access_plist
3345  *
3346  * Purpose:  Returns a copy of the dataset access property list.
3347  *
3348  * Return:   Success:    ID for a copy of the dataset access
3349  *                       property list.
3350  *           Failure:    FAIL
3351  *-------------------------------------------------------------------------
3352  */
3353 hid_t
H5D_get_access_plist(const H5D_t * dset)3354 H5D_get_access_plist(const H5D_t *dset)
3355 {
3356     H5P_genplist_t      *old_plist;     /* Default DAPL */
3357     H5P_genplist_t      *new_plist;     /* New DAPL */
3358     hid_t               new_dapl_id = FAIL;
3359     hid_t               ret_value = FAIL;
3360 
3361     FUNC_ENTER_NOAPI_NOINIT
3362 
3363     /* Make a copy of the default dataset access property list */
3364     if(NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_DATASET_ACCESS_ID_g)))
3365         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
3366     if((new_dapl_id = H5P_copy_plist(old_plist, TRUE)) < 0)
3367         HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy dataset access property list")
3368     if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dapl_id)))
3369         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
3370 
3371     /* If the dataset is chunked then copy the rdcc & append flush parameters */
3372     if(dset->shared->layout.type == H5D_CHUNKED) {
3373         if(H5P_set(new_plist, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(dset->shared->cache.chunk.nslots)) < 0)
3374             HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots")
3375         if(H5P_set(new_plist, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(dset->shared->cache.chunk.nbytes_max)) < 0)
3376             HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size")
3377         if(H5P_set(new_plist, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &(dset->shared->cache.chunk.w0)) < 0)
3378             HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks")
3379         if(H5P_set(new_plist, H5D_ACS_APPEND_FLUSH_NAME, &dset->shared->append_flush) < 0)
3380             HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set append flush property")
3381     } /* end if */
3382 
3383     /* Set the VDS view & printf gap options */
3384     if(H5P_set(new_plist, H5D_ACS_VDS_VIEW_NAME, &(dset->shared->layout.storage.u.virt.view)) < 0)
3385         HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VDS view")
3386     if(H5P_set(new_plist, H5D_ACS_VDS_PRINTF_GAP_NAME, &(dset->shared->layout.storage.u.virt.printf_gap)) < 0)
3387         HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VDS printf gap")
3388 
3389     /* Set the vds prefix option */
3390     if(H5P_set(new_plist, H5D_ACS_VDS_PREFIX_NAME, &(dset->shared->vds_prefix)) < 0)
3391         HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set vds prefix")
3392 
3393     /* Set the external file prefix option */
3394     if(H5P_set(new_plist, H5D_ACS_EFILE_PREFIX_NAME, &(dset->shared->extfile_prefix)) < 0)
3395         HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set external file prefix")
3396 
3397     /* Set the return value */
3398     ret_value = new_dapl_id;
3399 
3400 done:
3401     if(ret_value < 0)
3402         if(new_dapl_id > 0)
3403             if(H5I_dec_app_ref(new_dapl_id) < 0)
3404                 HDONE_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "can't free")
3405 
3406     FUNC_LEAVE_NOAPI(ret_value)
3407 } /* end H5D_get_access_plist() */
3408 
3409 
3410 /*-------------------------------------------------------------------------
3411  * Function: H5D__get_space
3412  *
3413  * Purpose:  Returns and ID for the dataspace of the dataset.
3414  *
3415  * Return:   Success:    ID for dataspace
3416  *           Failure:    FAIL
3417  *-------------------------------------------------------------------------
3418  */
3419 hid_t
H5D__get_space(const H5D_t * dset)3420 H5D__get_space(const H5D_t *dset)
3421 {
3422     H5S_t    *space = NULL;
3423     hid_t     ret_value = H5I_INVALID_HID;
3424 
3425     FUNC_ENTER_PACKAGE_VOL
3426 
3427     /* If the layout is virtual, update the extent */
3428     if(dset->shared->layout.type == H5D_VIRTUAL)
3429         if(H5D__virtual_set_extent_unlim(dset) < 0)
3430             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update virtual dataset extent")
3431 
3432     /* Read the dataspace message and return a dataspace object */
3433     if(NULL == (space = H5S_copy(dset->shared->space, FALSE, TRUE)))
3434         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get dataspace")
3435 
3436     /* Create an atom */
3437     if((ret_value = H5I_register(H5I_DATASPACE, space, TRUE)) < 0)
3438         HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace")
3439 
3440 done:
3441     if(ret_value < 0)
3442         if(space != NULL)
3443             if(H5S_close(space) < 0)
3444                 HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
3445 
3446     FUNC_LEAVE_NOAPI_VOL(ret_value)
3447 } /* end H5D__get_space() */
3448 
3449 
3450 /*-------------------------------------------------------------------------
3451  * Function: H5D__get_type
3452  *
3453  * Purpose:  Returns and ID for the datatype of the dataset.
3454  *
3455  * Return:   Success:    ID for datatype
3456  *           Failure:    FAIL
3457  *
3458  *-------------------------------------------------------------------------
3459  */
3460 hid_t
H5D__get_type(const H5D_t * dset)3461 H5D__get_type(const H5D_t *dset)
3462 {
3463     H5T_t    *dt = NULL;
3464     hid_t     ret_value = FAIL;
3465 
3466     FUNC_ENTER_PACKAGE
3467 
3468     /* Patch the datatype's "top level" file pointer */
3469     if(H5T_patch_file(dset->shared->type, dset->oloc.file) < 0)
3470         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to patch datatype's file pointer")
3471 
3472     /* Copy the dataset's datatype */
3473     if(NULL == (dt = H5T_copy(dset->shared->type, H5T_COPY_REOPEN)))
3474         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy datatype")
3475 
3476     /* Mark any datatypes as being in memory now */
3477     if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
3478         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
3479 
3480     /* Lock copied type */
3481     if(H5T_lock(dt, FALSE) < 0)
3482         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
3483 
3484     if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
3485         HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype")
3486 
3487 done:
3488     if(ret_value < 0)
3489         if(dt && H5T_close(dt) < 0)
3490             HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype")
3491 
3492     FUNC_LEAVE_NOAPI(ret_value)
3493 } /* end H5D__get_type() */
3494 
3495 
3496 /*-------------------------------------------------------------------------
3497  * Function: H5D__refresh
3498  *
3499  * Purpose:  Refreshes all buffers associated with a dataset.
3500  *
3501  * Return:   SUCCEED/FAIL
3502  *-------------------------------------------------------------------------
3503  */
3504 herr_t
H5D__refresh(hid_t dset_id,H5D_t * dset)3505 H5D__refresh(hid_t dset_id, H5D_t *dset)
3506 {
3507     H5D_virtual_held_file_t *head = NULL;       /* Pointer to list of files held open */
3508     hbool_t virt_dsets_held = FALSE;            /* Whether virtual datasets' files are held open */
3509     herr_t      ret_value   = SUCCEED;          /* Return value */
3510 
3511     FUNC_ENTER_PACKAGE_VOL
3512 
3513     /* Sanity check */
3514     HDassert(dset);
3515     HDassert(dset->shared);
3516 
3517     /* If the layout is virtual... */
3518     if(dset->shared->layout.type == H5D_VIRTUAL) {
3519         /* Hold open the source datasets' files */
3520         if(H5D__virtual_hold_source_dset_files(dset, &head) < 0)
3521             HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, FAIL, "unable to hold VDS source files open")
3522         virt_dsets_held = TRUE;
3523 
3524         /* Refresh source datasets for virtual dataset */
3525         if(H5D__virtual_refresh_source_dsets(dset) < 0)
3526             HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to refresh VDS source datasets")
3527     } /* end if */
3528 
3529     /* Refresh dataset object */
3530     if((H5O_refresh_metadata(dset_id, dset->oloc)) < 0)
3531         HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to refresh dataset")
3532 
3533 done:
3534     /* Release hold on (source) virtual datasets' files */
3535     if(virt_dsets_held)
3536         if(H5D__virtual_release_source_dset_files(head) < 0)
3537             HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "can't release VDS source files held open")
3538 
3539     FUNC_LEAVE_NOAPI_VOL(ret_value)
3540 } /* end H5D__refresh() */
3541 
3542