Coverage Report

Created: 2026-01-16 06:15

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