Coverage Report

Created: 2026-10-17 06:56

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