/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the COPYING file, which can be found at the root of the source code       *
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*
 * This program illustrates assertion errors when linked
 * to HDF5 1.4.1-post2 or 1.4.2-pre3 debug library.
 *
 * If the assertion errors are ignored, the program eventually causes
 * an error in H5Gcreate2 when writing object 83381.
 *
 * When writing in single file mode, the assertion errors still occur
 * but the H5Gcreate2 error does not.
 */

#include "h5test.h"

#define FILEN "testmeta.h5"

#define CHUNK_SIZE 512

#define NDATAARRAYS 3
/*#define NPOINTS         2048*/
#define NPOINTS      20
#define NEXTARRAYS   10
#define NDATAOBJECTS 100000

int
main(void)
{
    hid_t    file_id, prop_id, memspace_id, type_id;
    hid_t    group_id;
    hid_t    dataset_id, dataspace_id;
    herr_t   status;
    hsize_t  dims[1];
    hsize_t  maxdims[1];
    float    data[NPOINTS];
    float    floatval;
    unsigned numdataobj = 0;
    unsigned i, j;
    char     name[80];
    hsize_t  start[1]  = {0};
    hsize_t  stride[1] = {1};
    hsize_t  count[1]  = {1};

    /* Create a file */
    file_id = H5Fcreate(FILEN, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

    /* Create a dataset to hold the number of data objects */
    /* Create the data space */
    dataspace_id = H5Screate(H5S_SCALAR);

    /* Create dataset */
    dataset_id = H5Dcreate2(file_id, "/NumDataObj", H5T_NATIVE_UINT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT,
                            H5P_DEFAULT);

    /* Write value to NumDataObj dataset */
    status = H5Dwrite(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &numdataobj);

    /* Close the identifiers */
    status = H5Dclose(dataset_id);
    status = H5Sclose(dataspace_id);

    /* Create extendible arrays */
    /* Set up for extendible dataset */
    prop_id = H5Pcreate(H5P_DATASET_CREATE);
    dims[0] = CHUNK_SIZE;
    status  = H5Pset_chunk(prop_id, 1, dims);

    /* Create dataspace */
    dims[0]      = 1;
    maxdims[0]   = H5S_UNLIMITED;
    dataspace_id = H5Screate_simple(1, dims, maxdims);

    for (i = 0; i < NEXTARRAYS; i++) {
        /* Create dataset */
        HDsnprintf(name, sizeof(name), "/ExtArray%06d", i);
        dataset_id =
            H5Dcreate2(file_id, name, H5T_NATIVE_FLOAT, dataspace_id, H5P_DEFAULT, prop_id, H5P_DEFAULT);

        /* Close the identifier */
        status = H5Dclose(dataset_id);
    }

    /* Close the identifiers */
    status = H5Sclose(dataspace_id);
    status = H5Pclose(prop_id);

    /* Create group to hold data object data arrays */
    group_id = H5Gcreate2(file_id, "/DataArray", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
    H5Gclose(group_id);

    for (j = 0; j < NDATAOBJECTS; j++) {
        /* Removed print statement as it would lock system resources on Windows */
        /*
         * HDprintf("\rWriting Object #%d of %d", j+1, NDATAOBJECTS);
         * HDfflush(stdout);
         */
        floatval = (float)j;

        /* Create group to hold data arrays for this object */
        HDsnprintf(name, sizeof(name), "/DataArray/%06d", j);
        group_id = H5Gcreate2(file_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
        if (group_id < 0) {
            HDfprintf(stderr, "Failed to create DataArray group.\n");
            status = H5Fclose(file_id);
            return -1;
        }

        /* Loop over data arrays */
        for (i = 0; i < NDATAARRAYS; i++) {
            /* Create dataspace */
            dims[0]      = NPOINTS;
            maxdims[0]   = NPOINTS;
            dataspace_id = H5Screate_simple(1, dims, maxdims);

            /* Create dataset */
            HDsnprintf(name, sizeof(name), "DataArray%06d", i);
            dataset_id = H5Dcreate2(group_id, name, H5T_NATIVE_FLOAT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT,
                                    H5P_DEFAULT);
            if (dataset_id < 0) {
                HDfprintf(stderr, "Failed to create DataArray dataset.\n");
                status = H5Fclose(file_id);
                return -1;
            }

            /* Write the data array data */
            status = H5Dwrite(dataset_id, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
            if (status < 0) {
                HDfprintf(stderr, "Failed to write DataArray dataset.\n");
                status = H5Fclose(file_id);
                return -1;
            }

            /* Close the identifiers */
            status = H5Dclose(dataset_id);
            status = H5Sclose(dataspace_id);
        }

        /* Open NumDataObj dataset */
        dataset_id = H5Dopen2(file_id, "/NumDataObj", H5P_DEFAULT);
        if (dataset_id < 0) {
            HDfprintf(stderr, "Failed to open NumDataObj dataset.\n");
            status = H5Fclose(file_id);
            return -1;
        }

        /* Write value to NumDataObj dataset */
        numdataobj = j + 1;
        status     = H5Dwrite(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &numdataobj);
        if (status < 0) {
            HDfprintf(stderr, "Failed to write NumDataObj dataset.\n");
            status = H5Fclose(file_id);
            return -1;
        }

        /* Close identifiers */
        status = H5Dclose(dataset_id);
        status = H5Gclose(group_id);

        /* Extend attribute arrays */
        for (i = 0; i < NEXTARRAYS; i++) {
            /* Open extendable dataset */
            HDsnprintf(name, sizeof(name), "/ExtArray%06d", i);
            dataset_id = H5Dopen2(file_id, name, H5P_DEFAULT);
            if (dataset_id < 0) {
                HDfprintf(stderr, "Failed to open ExtArray dataset.\n");
                status = H5Fclose(file_id);
                return -1;
            } /* end if */

            /* Extend attribute dataset */
            dims[0] = (hsize_t)j + 1;
            status  = H5Dset_extent(dataset_id, dims);
            if (status < 0) {
                HDfprintf(stderr, "Failed to extend DataArray dataset.\n");
                status = H5Fclose(file_id);
                return -1;
            } /* end if */

            /* Select element and write value to attribute dataset */
            dims[0]      = 1;
            memspace_id  = H5Screate_simple(1, dims, dims);
            dataspace_id = H5Dget_space(dataset_id);
            type_id      = H5Dget_type(dataset_id);

            start[0] = 0;
            status   = H5Sselect_hyperslab(memspace_id, H5S_SELECT_SET, start, stride, count, NULL);
            start[0] = (hsize_t)j;
            status   = H5Sselect_hyperslab(dataspace_id, H5S_SELECT_SET, start, stride, count, NULL);
            status   = H5Dwrite(dataset_id, type_id, memspace_id, dataspace_id, H5P_DEFAULT, &floatval);
            if (status < 0) {
                HDfprintf(stderr, "Failed to write DataArray dataset.\n");
                status = H5Fclose(file_id);
                return -1;
            }

            /* Close identifiers */
            status = H5Tclose(type_id);
            status = H5Sclose(dataspace_id);
            status = H5Sclose(memspace_id);
            status = H5Dclose(dataset_id);
        }
    }

    /* Close the file */
    status = H5Fclose(file_id);

    HDprintf("\n");

    return 0;
}
