mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-27 02:10:55 +08:00
1732 lines
65 KiB
C
1732 lines
65 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* Copyright by the Board of Trustees of the University of Illinois. *
|
|
* 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://support.hdfgroup.org/ftp/HDF5/releases. *
|
|
* If you do not have access to either file, you may request a copy from *
|
|
* help@hdfgroup.org. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
/*
|
|
* Programmer: Peter X. Cao
|
|
* May 01, 2005
|
|
*
|
|
* Purpose: Test H5Ocopy() for references.
|
|
*/
|
|
|
|
#include "testhdf5.h"
|
|
|
|
#define H5F_FRIEND /*suppress error about including H5Fpkg */
|
|
#define H5F_TESTING
|
|
#include "H5Fpkg.h" /* File access */
|
|
|
|
const char *FILENAME[] = {
|
|
"objcopy_ref_src",
|
|
"objcopy_ref_dst",
|
|
"objcopy_ref_ext",
|
|
"objcopy_ref_src2",
|
|
"verbound_ref_src",
|
|
"verbound_ref_dst",
|
|
NULL
|
|
};
|
|
|
|
/* Configuration, really a series of bit flags. Maximum value is all three
|
|
* bit flags enabled.
|
|
*/
|
|
#define CONFIG_SHARE_SRC 1
|
|
#define CONFIG_SHARE_DST 2
|
|
#define CONFIG_SRC_NEW_FORMAT 4
|
|
#define CONFIG_DST_NEW_FORMAT 8
|
|
#define CONFIG_DENSE 16
|
|
#define MAX_CONFIGURATION 31
|
|
|
|
#define NAME_DATATYPE_SIMPLE "H5T_NATIVE_INT"
|
|
#define NAME_DATATYPE_SIMPLE2 "H5T_NATIVE_INT-2"
|
|
#define NAME_DATATYPE_VL "vlen of int"
|
|
#define NAME_DATATYPE_VL_VL "vlen of vlen of int"
|
|
#define NAME_DATASET_SIMPLE "dataset_simple"
|
|
#define NAME_DATASET_SIMPLE2 "dataset_simple_copy"
|
|
#define NAME_DATASET_SIMPLE3 "dataset_simple_another_copy"
|
|
#define NAME_DATASET_COMPOUND "dataset_compound"
|
|
#define NAME_DATASET_CHUNKED "dataset_chunked"
|
|
#define NAME_DATASET_CHUNKED_SINGLE "dataset_chunked_single"
|
|
#define NAME_DATASET_CHUNKED2 "dataset_chunked2"
|
|
#define NAME_DATASET_CHUNKED2_SINGLE "dataset_chunked2_single"
|
|
#define NAME_DATASET_CHUNKED3 "dataset_chunked3"
|
|
#define NAME_DATASET_CHUNKED3_SINGLE "dataset_chunked3_single"
|
|
#define NAME_DATASET_CHUNKED4 "dataset_chunked4"
|
|
#define NAME_DATASET_CHUNKED4_SINGLE "dataset_chunked4_single"
|
|
#define NAME_DATASET_COMPACT "dataset_compact"
|
|
#define NAME_DATASET_EXTERNAL "dataset_ext"
|
|
#define NAME_DATASET_NAMED_DTYPE "dataset_named_dtype"
|
|
#define NAME_DATASET_NAMED_DTYPE2 "dataset_named_dtype2"
|
|
#define NAME_DATASET_MULTI_OHDR "dataset_multi_ohdr"
|
|
#define NAME_DATASET_MULTI_OHDR2 "dataset_multi_ohdr2"
|
|
#define NAME_DATASET_VL "dataset_vl"
|
|
#define NAME_DATASET_VL2 "dataset_vl2"
|
|
#define NAME_DATASET_VL_VL "dataset_vl_vl"
|
|
#define NAME_DATASET_VL_VL2 "dataset_vl_vl2"
|
|
#define NAME_DATASET_CMPD_VL "dataset_cmpd_vl"
|
|
#define NAME_DATASET_SUB_SUB "/g0/g00/g000/dataset_simple"
|
|
#define NAME_GROUP_UNCOPIED "/uncopied"
|
|
#define NAME_GROUP_EMPTY "/empty"
|
|
#define NAME_GROUP_TOP "/g0"
|
|
#define NAME_GROUP_TOP2 "/g1"
|
|
#define NAME_GROUP_TOP3 "/g2"
|
|
#define NAME_GROUP_TOP4 "/g3"
|
|
#define NAME_GROUP_SUB "/g0/g00"
|
|
#define NAME_GROUP_SUB_2 "/g0/g01"
|
|
#define NAME_GROUP_SUB_SUB "/g0/g00/g000"
|
|
#define NAME_GROUP_SUB_SUB2 "g000"
|
|
#define NAME_GROUP_DATASET "/g0/dataset_simple"
|
|
#define NAME_GROUP_LINK "/g_links"
|
|
#define NAME_GROUP_LINK2 "/g_links2"
|
|
#define NAME_GROUP_LOOP "g_loop"
|
|
#define NAME_GROUP_LOOP2 "g_loop2"
|
|
#define NAME_GROUP_LOOP3 "g_loop3"
|
|
#define NAME_GROUP_REF "ref_grp"
|
|
#define NAME_LINK_DATASET "/g_links/dataset_simple"
|
|
#define NAME_LINK_HARD "/g_links/hard_link_to_dataset_simple"
|
|
#define NAME_LINK_SOFT "/g_links/soft_link_to_dataset_simple"
|
|
#define NAME_LINK_SOFT2 "/g_links2/soft_link_to_dataset_simple"
|
|
#define NAME_LINK_EXTERN "/g_links/external_link_to_dataset_simple"
|
|
#define NAME_LINK_EXTERN2 "/g_links2/external_link_to_dataset_simple"
|
|
#define NAME_LINK_SOFT_DANGLE "/g_links/soft_link_to_nowhere"
|
|
#define NAME_LINK_SOFT_DANGLE2 "/g_links2/soft_link_to_nowhere"
|
|
#define NAME_LINK_EXTERN_DANGLE "/g_links/external_link_to_nowhere"
|
|
#define NAME_LINK_EXTERN_DANGLE2 "/g_links2/external_link_to_nowhere"
|
|
#define NAME_OLD_FORMAT "/dset1"
|
|
|
|
#define NAME_BUF_SIZE 1024
|
|
#define ATTR_NAME_LEN 80
|
|
#define DIM_SIZE_1 12
|
|
#define DIM_SIZE_2 6
|
|
#define MAX_DIM_SIZE_1 100
|
|
#define MAX_DIM_SIZE_2 80
|
|
#define CHUNK_SIZE_1 5 /* Not an even fraction of dimension sizes, so we test copying partial chunks */
|
|
#define CHUNK_SIZE_2 5
|
|
#define NUM_SUB_GROUPS 20
|
|
#define NUM_WIDE_LOOP_GROUPS 10
|
|
#define NUM_DATASETS 10
|
|
|
|
unsigned num_attributes_g; /* Number of attributes created */
|
|
|
|
/* Table containing object id and object name */
|
|
/* (Used for detecting duplicate objects when comparing groups */
|
|
static struct {
|
|
size_t nalloc; /* number of slots allocated */
|
|
size_t nobjs; /* number of objects */
|
|
haddr_t *obj; /* Addresses of objects seen */
|
|
} idtab_g;
|
|
|
|
/* Local function prototypes */
|
|
static int
|
|
compare_data(hid_t parent1, hid_t parent2, hid_t pid, hid_t tid, size_t nelmts,
|
|
const void *buf1, const void *buf2, hid_t obj_owner);
|
|
static int
|
|
compare_datasets(hid_t did, hid_t did2, hid_t pid, const void *wbuf);
|
|
static int
|
|
compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth, unsigned copy_flags);
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: addr_insert
|
|
*
|
|
* Purpose: Add an address to the table.
|
|
*
|
|
* Return: void
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Saturday, November 5, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
addr_insert(H5O_info_t *oi)
|
|
{
|
|
size_t n;
|
|
|
|
/* Don't add it if the link count is 1 because such an object can only
|
|
* be encountered once. */
|
|
if(oi->rc < 2)
|
|
return;
|
|
|
|
/* Extend the table */
|
|
if(idtab_g.nobjs >= idtab_g.nalloc) {
|
|
idtab_g.nalloc = MAX(256, 2*idtab_g.nalloc);
|
|
idtab_g.obj = (haddr_t *)HDrealloc(idtab_g.obj, idtab_g.nalloc * sizeof(idtab_g.obj[0]));
|
|
} /* end if */
|
|
|
|
/* Insert the entry */
|
|
n = idtab_g.nobjs++;
|
|
idtab_g.obj[n] = oi->addr;
|
|
} /* end addr_insert() */
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: addr_lookup
|
|
*
|
|
* Purpose: Check if address has already been encountered
|
|
*
|
|
* Return: Success: TRUE/FALSE
|
|
*
|
|
* Failure: (can't fail)
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Saturday, November 5, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static H5_ATTR_PURE hbool_t
|
|
addr_lookup(H5O_info_t *oi)
|
|
{
|
|
size_t n;
|
|
|
|
if(oi->rc < 2) return FALSE; /*only one link possible*/
|
|
|
|
for(n = 0; n < idtab_g.nobjs; n++)
|
|
if(H5F_addr_eq(idtab_g.obj[n], oi->addr))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
} /* end addr_lookup() */
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: addr_reset
|
|
*
|
|
* Purpose: Reset the address tracking data structures
|
|
*
|
|
* Return: void
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Saturday, November 5, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
addr_reset(void)
|
|
{
|
|
if(idtab_g.obj)
|
|
HDfree(idtab_g.obj);
|
|
idtab_g.obj = NULL;
|
|
idtab_g.nalloc = idtab_g.nobjs = 0;
|
|
} /* end addr_reset() */
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: attach_ref_attr
|
|
*
|
|
* Purpose: Create an attribute with object references
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
attach_ref_attr(hid_t file_id, hid_t loc_id)
|
|
{
|
|
char dsetname1[] = "dataset1_pointed_by_ref_attr";
|
|
char dsetname2[] = "dataset2_pointed_by_ref_attr";
|
|
hid_t did1 = (-1), did2 = (-1), aid = (-1), sid = (-1), sid_ref = (-1);
|
|
hsize_t dims[2] = {2,9};
|
|
hsize_t dims_ref[1] = {2};
|
|
H5R_ref_t ref[2];
|
|
int data1[2][9] = {{1,1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1,18}};
|
|
int data2[2][9] = {{2,2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2,18}};
|
|
|
|
/* creates two simple datasets */
|
|
if((sid = H5Screate_simple(2, dims, NULL)) < 0) TEST_ERROR
|
|
if((sid_ref = H5Screate_simple(1, dims_ref, NULL)) < 0) TEST_ERROR
|
|
if((did1 = H5Dcreate2(file_id, dsetname1, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Dwrite(did1, H5T_NATIVE_INT, H5S_ALL , H5S_ALL, H5P_DEFAULT,data1) < 0) TEST_ERROR
|
|
if((did2 = H5Dcreate2(file_id, dsetname2, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Dwrite(did2, H5T_NATIVE_INT, H5S_ALL , H5S_ALL, H5P_DEFAULT,data2) < 0) TEST_ERROR
|
|
|
|
/* create an attribute with two object references */
|
|
if(H5Rcreate_object(file_id, dsetname1, &ref[0]) < 0) TEST_ERROR
|
|
if(H5Rcreate_object(file_id, dsetname2, &ref[1]) < 0) TEST_ERROR
|
|
if((aid = H5Acreate2(loc_id, "obj_ref_attr", H5T_STD_REF, sid_ref, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Awrite(aid, H5T_STD_REF, ref) < 0) TEST_ERROR
|
|
|
|
if(H5Sclose(sid) < 0) TEST_ERROR
|
|
if(H5Sclose(sid_ref) < 0) TEST_ERROR
|
|
if(H5Dclose(did1) < 0) TEST_ERROR
|
|
if(H5Dclose(did2) < 0) TEST_ERROR
|
|
if(H5Aclose(aid) < 0) TEST_ERROR
|
|
if(H5Rdestroy(&ref[0]) < 0) TEST_ERROR
|
|
if(H5Rdestroy(&ref[1]) < 0) TEST_ERROR
|
|
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY {
|
|
H5Sclose(sid);
|
|
H5Sclose(sid_ref);
|
|
H5Dclose(did1);
|
|
H5Dclose(did2);
|
|
H5Aclose(aid);
|
|
H5Rdestroy(&ref[0]);
|
|
H5Rdestroy(&ref[1]);
|
|
} H5E_END_TRY;
|
|
|
|
return(-1);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: attach_reg_ref_attr
|
|
*
|
|
* Purpose: Create an attribute with object references
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Peter Cao
|
|
* Monday, March 5, 2006
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
attach_reg_ref_attr(hid_t file_id, hid_t loc_id)
|
|
{
|
|
const char dsetnamev[] = "dataset_pointed_by_reg_ref_attr";
|
|
hid_t aid = (-1);
|
|
hid_t space_id = (-1); /* dataspace identifiers */
|
|
hid_t spacer_id = (-1); /* dataspace identifiers */
|
|
hid_t dsetv_id = (-1); /*dataset identifiers*/
|
|
hsize_t dims[2] = {2,9};
|
|
hsize_t dimsr[1] = {2};
|
|
int rank = 2;
|
|
int rankr =1;
|
|
H5R_ref_t ref[2];
|
|
int data[2][9] = {{1,1,2,3,3,4,5,5,999},{1,2,2,3,4,4,5,6,999}};
|
|
hsize_t start[2] = {0, 3};
|
|
hsize_t count[2] = {2, 3};
|
|
hsize_t coord[3][2] = {{0, 0}, {1, 6}, {0, 8}};
|
|
size_t num_points = 3;
|
|
|
|
/* create a 2D dataset */
|
|
if((space_id = H5Screate_simple(rank, dims, NULL)) < 0) TEST_ERROR
|
|
if((spacer_id = H5Screate_simple(rankr, dimsr, NULL)) < 0) TEST_ERROR
|
|
if((dsetv_id = H5Dcreate2(file_id, dsetnamev, H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Dwrite(dsetv_id, H5T_NATIVE_INT, H5S_ALL , H5S_ALL, H5P_DEFAULT,data) < 0) TEST_ERROR
|
|
|
|
/* create reg_ref of block selection */
|
|
if(H5Sselect_hyperslab(space_id,H5S_SELECT_SET,start,NULL,count,NULL) < 0) TEST_ERROR
|
|
if(H5Rcreate_region(file_id, dsetnamev, space_id, &ref[0]) < 0) TEST_ERROR
|
|
|
|
/* create reg_ref of point selection */
|
|
if(H5Sselect_none(space_id) < 0) TEST_ERROR
|
|
if(H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, (const hsize_t *)coord) < 0) TEST_ERROR
|
|
if(H5Rcreate_region(file_id, dsetnamev, space_id, &ref[1]) < 0) TEST_ERROR
|
|
|
|
/* create reg_ref attribute */
|
|
if((aid = H5Acreate2(loc_id, "reg_ref_attr", H5T_STD_REF, spacer_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Awrite(aid, H5T_STD_REF, ref) < 0) TEST_ERROR
|
|
|
|
/* attach the reg_ref attribute to the dataset itself */
|
|
if(H5Aclose(aid) < 0) TEST_ERROR
|
|
if((aid = H5Acreate2(dsetv_id, "reg_ref_attr", H5T_STD_REF, spacer_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Awrite(aid, H5T_STD_REF, ref) < 0) TEST_ERROR
|
|
|
|
if(H5Sclose(spacer_id) < 0) TEST_ERROR
|
|
if(H5Sclose(space_id) < 0) TEST_ERROR
|
|
if(H5Dclose(dsetv_id) < 0) TEST_ERROR
|
|
if(H5Aclose(aid) < 0) TEST_ERROR
|
|
if(H5Rdestroy(&ref[0]) < 0) TEST_ERROR
|
|
if(H5Rdestroy(&ref[1]) < 0) TEST_ERROR
|
|
|
|
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY {
|
|
H5Sclose(spacer_id);
|
|
H5Sclose(space_id);
|
|
H5Dclose(dsetv_id);
|
|
H5Aclose(aid);
|
|
H5Rdestroy(&ref[0]);
|
|
H5Rdestroy(&ref[1]);
|
|
} H5E_END_TRY;
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: create_reg_ref_dataset
|
|
*
|
|
* Purpose: Create a dataset with region references
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Peter Cao
|
|
* Friday, August 4, 2006
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
create_reg_ref_dataset(hid_t file_id, hid_t loc_id)
|
|
{
|
|
const char dsetnamev[] = "dataset_pointed_by_ref_dset";
|
|
const char dsetnamer[] = "dataset_with_reg_ref";
|
|
const char dsetnamer1[] = "compact_dataset_with_reg_ref";
|
|
const char dsetnamer2[] = "compressed_dataset_with_reg_ref";
|
|
hid_t space_id = (-1); /* dataspace identifiers */
|
|
hid_t spacer_id = (-1);
|
|
hid_t dsetv_id = (-1); /*dataset identifiers*/
|
|
hid_t dsetr_id = (-1);
|
|
hsize_t dims[2] = {2,9};
|
|
hsize_t dimsr[1] = {2};
|
|
int rank = 2;
|
|
int rankr =1;
|
|
hsize_t chunk_size=1;
|
|
H5R_ref_t ref[2];
|
|
int data[2][9] = {{1,1,2,3,3,4,5,5,6},{1,2,2,3,4,4,5,6,6}};
|
|
hsize_t start[2];
|
|
hsize_t count[2];
|
|
hsize_t coord[3][2] = {{0, 0}, {1, 6}, {0, 8}};
|
|
size_t num_points = 3;
|
|
hid_t pid = (-1);
|
|
|
|
if((space_id = H5Screate_simple(rank, dims, NULL)) < 0) TEST_ERROR
|
|
if((spacer_id = H5Screate_simple(rankr, dimsr, NULL)) < 0) TEST_ERROR
|
|
if((dsetv_id = H5Dcreate2(file_id, dsetnamev, H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Dwrite(dsetv_id, H5T_NATIVE_INT, H5S_ALL , H5S_ALL, H5P_DEFAULT,data) < 0) TEST_ERROR
|
|
if((dsetr_id = H5Dcreate2(loc_id, dsetnamer, H5T_STD_REF, spacer_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
|
|
start[0] = 0;
|
|
start[1] = 3;
|
|
count[0] = 2;
|
|
count[1] = 3;
|
|
if(H5Sselect_hyperslab(space_id,H5S_SELECT_SET,start,NULL,count,NULL) < 0) TEST_ERROR
|
|
if(H5Rcreate_region(file_id, dsetnamev, space_id, &ref[0]) < 0) TEST_ERROR
|
|
if(H5Sselect_none(space_id) < 0) TEST_ERROR
|
|
if(H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, (const hsize_t *)coord) < 0) TEST_ERROR
|
|
if(H5Rcreate_region(file_id, dsetnamev, space_id, &ref[1]) < 0) TEST_ERROR
|
|
if(H5Dwrite(dsetr_id, H5T_STD_REF, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref) < 0) TEST_ERROR
|
|
if(H5Dclose(dsetr_id) < 0) TEST_ERROR
|
|
|
|
/* create and set compact plist */
|
|
if((pid = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR
|
|
if(H5Pset_layout(pid, H5D_COMPACT) < 0) TEST_ERROR
|
|
|
|
if((dsetr_id = H5Dcreate2(loc_id, dsetnamer1, H5T_STD_REF, spacer_id, H5P_DEFAULT, pid, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Pclose(pid) < 0) TEST_ERROR
|
|
if(H5Dwrite(dsetr_id, H5T_STD_REF, H5S_ALL, H5S_ALL, H5P_DEFAULT, ref) < 0) TEST_ERROR
|
|
if(H5Dclose(dsetr_id) < 0) TEST_ERROR
|
|
|
|
/* create and set comp & chunk plist */
|
|
if((pid = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR
|
|
if(H5Pset_chunk(pid, 1, &chunk_size) < 0) TEST_ERROR
|
|
if(H5Pset_deflate(pid, 9) < 0) TEST_ERROR
|
|
|
|
if((dsetr_id = H5Dcreate2(loc_id, dsetnamer2, H5T_STD_REF, spacer_id, H5P_DEFAULT, pid, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Pclose(pid) < 0) TEST_ERROR
|
|
if(H5Dwrite(dsetr_id, H5T_STD_REF, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref) < 0) TEST_ERROR
|
|
if(H5Dclose(dsetr_id) < 0) TEST_ERROR
|
|
|
|
if(H5Sclose(space_id) < 0) TEST_ERROR
|
|
if(H5Sclose(spacer_id) < 0) TEST_ERROR
|
|
if(H5Dclose(dsetv_id) < 0) TEST_ERROR
|
|
if(H5Rdestroy(&ref[0]) < 0) TEST_ERROR
|
|
if(H5Rdestroy(&ref[1]) < 0) TEST_ERROR
|
|
|
|
return 0;
|
|
|
|
|
|
error:
|
|
H5E_BEGIN_TRY {
|
|
H5Sclose(space_id);
|
|
H5Sclose(spacer_id);
|
|
H5Dclose(dsetr_id);
|
|
H5Dclose(dsetv_id);
|
|
H5Pclose(pid);
|
|
H5Rdestroy(&ref[0]);
|
|
H5Rdestroy(&ref[1]);
|
|
} H5E_END_TRY;
|
|
|
|
return(-1);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_copy_attach_attributes
|
|
*
|
|
* Purpose: Attach NUM_ATTRIBUTES attributes to the object to be copied
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Peter Cao
|
|
* Friday, September 30, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_copy_attach_attributes(hid_t loc_id, hid_t type_id)
|
|
{
|
|
hid_t aid = -1, sid = -1;
|
|
char attr_name[ATTR_NAME_LEN];
|
|
int attr_data[2];
|
|
hsize_t dim1 = 2;
|
|
hid_t acpl = -1;
|
|
unsigned u;
|
|
int ret_value = -1;
|
|
|
|
if((sid = H5Screate_simple(1, &dim1, NULL)) < 0 )
|
|
goto done;
|
|
|
|
/* Create attribute creation plist */
|
|
if((acpl = H5Pcreate(H5P_ATTRIBUTE_CREATE)) < 0)
|
|
goto done;
|
|
|
|
for(u = 0; u < num_attributes_g; u++) {
|
|
HDsprintf(attr_name, "%u attr", u);
|
|
|
|
/* Set attribute data */
|
|
attr_data[0] = (int)(100 * u);
|
|
attr_data[1] = (int)(200 * u);
|
|
|
|
/* Set attribute character set (alternate) */
|
|
if(u % 2) {
|
|
if(H5Pset_char_encoding(acpl, H5T_CSET_ASCII) < 0)
|
|
goto done;
|
|
} /* end if */
|
|
else
|
|
if(H5Pset_char_encoding(acpl, H5T_CSET_UTF8) < 0)
|
|
goto done;
|
|
|
|
if((aid = H5Acreate2(loc_id, attr_name, type_id, sid, acpl, H5P_DEFAULT)) < 0)
|
|
goto done;
|
|
|
|
if(H5Awrite(aid, H5T_NATIVE_INT, attr_data) < 0)
|
|
goto done;
|
|
|
|
if(aid > 0)
|
|
H5Aclose(aid);
|
|
|
|
aid = -1;
|
|
}
|
|
|
|
ret_value = 0;
|
|
|
|
done:
|
|
if(sid > 0)
|
|
H5Sclose(sid);
|
|
if(aid > 0)
|
|
H5Aclose(aid);
|
|
if(acpl > 0)
|
|
H5Pclose(acpl);
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: compare_attribute
|
|
*
|
|
* Purpose: Compare two attributes to check that they are equal
|
|
*
|
|
* Return: TRUE if attributes are equal/FALSE if they are different
|
|
*
|
|
* Programmer: Peter Cao
|
|
* Saturday, December 17, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
compare_attribute(hid_t aid, hid_t aid2, hid_t pid, const void *wbuf, hid_t obj_owner)
|
|
{
|
|
hid_t sid = -1, sid2 = -1; /* Dataspace IDs */
|
|
hid_t tid = -1, tid2 = -1; /* Datatype IDs */
|
|
size_t elmt_size; /* Size of datatype */
|
|
htri_t is_committed; /* If the datatype is committed */
|
|
htri_t is_committed2; /* If the datatype is committed */
|
|
H5A_info_t ainfo; /* Attribute info */
|
|
H5A_info_t ainfo2; /* Attribute info */
|
|
hssize_t nelmts; /* # of elements in dataspace */
|
|
void *rbuf = NULL; /* Buffer for reading raw data */
|
|
void *rbuf2 = NULL; /* Buffer for reading raw data */
|
|
|
|
/* Check the character sets are equal */
|
|
if(H5Aget_info(aid, &ainfo) < 0) TEST_ERROR
|
|
if(H5Aget_info(aid2, &ainfo2) < 0) TEST_ERROR
|
|
if(ainfo.cset != ainfo2.cset) TEST_ERROR
|
|
|
|
/* Check the creation orders are equal (if appropriate) */
|
|
if(ainfo.corder_valid != ainfo2.corder_valid) TEST_ERROR
|
|
if(ainfo.corder_valid)
|
|
if(ainfo.corder != ainfo2.corder) TEST_ERROR
|
|
|
|
/* Check the datatypes are equal */
|
|
|
|
/* Open the datatype for the source attribute */
|
|
if((tid = H5Aget_type(aid)) < 0) TEST_ERROR
|
|
|
|
/* Open the datatype for the destination attribute */
|
|
if((tid2 = H5Aget_type(aid2)) < 0) TEST_ERROR
|
|
|
|
/* Check that both datatypes are committed/not committed */
|
|
if((is_committed = H5Tcommitted(tid)) < 0) TEST_ERROR
|
|
if((is_committed2 = H5Tcommitted(tid2)) < 0) TEST_ERROR
|
|
if(is_committed != is_committed2) TEST_ERROR
|
|
|
|
/* Compare the datatypes */
|
|
if(H5Tequal(tid, tid2) != TRUE) TEST_ERROR
|
|
|
|
/* Determine the size of datatype (for later) */
|
|
if((elmt_size = H5Tget_size(tid)) == 0) TEST_ERROR
|
|
|
|
/* Check the dataspaces are equal */
|
|
|
|
/* Open the dataspace for the source attribute */
|
|
if((sid = H5Aget_space(aid)) < 0) TEST_ERROR
|
|
|
|
/* Open the dataspace for the destination attribute */
|
|
if((sid2 = H5Aget_space(aid2)) < 0) TEST_ERROR
|
|
|
|
/* Compare the dataspaces */
|
|
if(H5Sextent_equal(sid, sid2) != TRUE) TEST_ERROR
|
|
|
|
/* Determine the number of elements in dataspace (for later) */
|
|
if((nelmts = H5Sget_simple_extent_npoints(sid2)) < 0) TEST_ERROR
|
|
|
|
/* Check the raw data is equal */
|
|
|
|
/* Allocate & initialize space for the raw data buffers */
|
|
if((rbuf = HDcalloc( elmt_size, (size_t)nelmts)) == NULL) TEST_ERROR
|
|
if((rbuf2 = HDcalloc( elmt_size, (size_t)nelmts)) == NULL) TEST_ERROR
|
|
|
|
/* Read data from the source attribute */
|
|
if(H5Aread(aid, tid, rbuf) < 0) TEST_ERROR
|
|
|
|
/* Read data from the destination attribute */
|
|
if(H5Aread(aid2, tid2, rbuf2) < 0) TEST_ERROR
|
|
|
|
/* Check raw data read in against data written out */
|
|
if(wbuf) {
|
|
if(!compare_data(aid, (hid_t)0, pid, tid, (size_t)nelmts, wbuf, rbuf, obj_owner)) TEST_ERROR
|
|
if(!compare_data(aid2, (hid_t)0, pid, tid2, (size_t)nelmts, wbuf, rbuf2, obj_owner)) TEST_ERROR
|
|
} /* end if */
|
|
/* Don't have written data, just compare data between the two attributes */
|
|
else
|
|
if(!compare_data(aid, aid2, pid, tid, (size_t)nelmts, rbuf, rbuf2, obj_owner)) TEST_ERROR
|
|
|
|
/* Reclaim vlen data, if necessary */
|
|
if(H5Tdetect_class(tid, H5T_VLEN) == TRUE || H5Tdetect_class(tid, H5T_REFERENCE) == TRUE)
|
|
if(H5Treclaim(tid, sid, H5P_DEFAULT, rbuf) < 0) TEST_ERROR
|
|
if(H5Tdetect_class(tid2, H5T_VLEN) == TRUE || H5Tdetect_class(tid2, H5T_REFERENCE) == TRUE)
|
|
if(H5Treclaim(tid2, sid2, H5P_DEFAULT, rbuf2) < 0) TEST_ERROR
|
|
|
|
/* Release raw data buffers */
|
|
HDfree(rbuf);
|
|
rbuf = NULL;
|
|
HDfree(rbuf2);
|
|
rbuf2 = NULL;
|
|
|
|
/* close the source dataspace */
|
|
if(H5Sclose(sid) < 0) TEST_ERROR
|
|
|
|
/* close the destination dataspace */
|
|
if(H5Sclose(sid2) < 0) TEST_ERROR
|
|
|
|
/* close the source datatype */
|
|
if(H5Tclose(tid) < 0) TEST_ERROR
|
|
|
|
/* close the destination datatype */
|
|
if(H5Tclose(tid2) < 0) TEST_ERROR
|
|
|
|
return TRUE;
|
|
|
|
error:
|
|
if(rbuf)
|
|
HDfree(rbuf);
|
|
if(rbuf2)
|
|
HDfree(rbuf2);
|
|
H5E_BEGIN_TRY {
|
|
H5Sclose(sid2);
|
|
H5Sclose(sid);
|
|
H5Tclose(tid2);
|
|
H5Tclose(tid);
|
|
} H5E_END_TRY;
|
|
return FALSE;
|
|
} /* end compare_attribute() */
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: compare_std_attributes
|
|
*
|
|
* Purpose: Compare "standard" attributes on two objects to check that they are equal
|
|
*
|
|
* Return: TRUE if objects have same attributes/FALSE if they are different
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Monday, October 31, 2005
|
|
*
|
|
* Note: This isn't very general, the attributes are assumed to be
|
|
* those written in test_copy_attach_attributes().
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
compare_std_attributes(hid_t oid, hid_t oid2, hid_t pid)
|
|
{
|
|
hid_t aid = -1, aid2 = -1; /* Attribute IDs */
|
|
H5O_info_t oinfo1, oinfo2; /* Object info */
|
|
unsigned cpy_flags; /* Object copy flags */
|
|
|
|
/* Retrieve the object copy flags from the property list, if it's non-DEFAULT */
|
|
if(pid != H5P_DEFAULT) {
|
|
if(H5Pget_copy_object(pid, &cpy_flags) < 0) TEST_ERROR
|
|
} /* end if */
|
|
else
|
|
cpy_flags = 0;
|
|
|
|
/* Check the number of attributes on source dataset */
|
|
if(H5Oget_info2(oid, &oinfo1, H5O_INFO_NUM_ATTRS) < 0) TEST_ERROR
|
|
|
|
/* Check the number of attributes on destination dataset */
|
|
if(H5Oget_info2(oid2, &oinfo2, H5O_INFO_NUM_ATTRS) < 0) TEST_ERROR
|
|
|
|
if(cpy_flags & H5O_COPY_WITHOUT_ATTR_FLAG) {
|
|
/* Check that the destination has no attributes */
|
|
if(oinfo2.num_attrs != 0) TEST_ERROR
|
|
} /* end if */
|
|
else {
|
|
char attr_name[ATTR_NAME_LEN]; /* Attribute name */
|
|
unsigned i; /* Local index variable */
|
|
|
|
/* Compare the number of attributes */
|
|
if(oinfo1.num_attrs != oinfo2.num_attrs) TEST_ERROR
|
|
|
|
/* Check the attributes are equal */
|
|
for(i = 0; i < (unsigned)oinfo1.num_attrs; i++) {
|
|
if((aid = H5Aopen_by_idx(oid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)i, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Aget_name(aid, (size_t)ATTR_NAME_LEN, attr_name) < 0) TEST_ERROR
|
|
|
|
if((aid2 = H5Aopen(oid2, attr_name, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
|
|
/* Check the attributes are equal */
|
|
if(!compare_attribute(aid, aid2, pid, NULL, oid)) TEST_ERROR
|
|
|
|
/* Close the attributes */
|
|
if(H5Aclose(aid) < 0) TEST_ERROR
|
|
if(H5Aclose(aid2) < 0) TEST_ERROR
|
|
} /* end for */
|
|
} /* end if */
|
|
|
|
/* Objects should be the same. :-) */
|
|
return TRUE;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY {
|
|
H5Aclose(aid2);
|
|
H5Aclose(aid);
|
|
} H5E_END_TRY;
|
|
return FALSE;
|
|
} /* end compare_std_attributes() */
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: compare_data
|
|
*
|
|
* Purpose: Compare two buffers of data to check that they are equal
|
|
*
|
|
* Return: TRUE if buffer are equal/FALSE if they are different
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Monday, November 21, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
compare_data(hid_t parent1, hid_t parent2, hid_t pid, hid_t tid, size_t nelmts,
|
|
const void *buf1, const void *buf2, hid_t obj_owner)
|
|
{
|
|
size_t elmt_size; /* Size of an element */
|
|
|
|
/* Check size of each element */
|
|
if((elmt_size = H5Tget_size(tid)) == 0) TEST_ERROR
|
|
|
|
/* If the type is a compound containing a vlen, loop over all elements for
|
|
* each compound member. Compounds containing reference are not supported
|
|
* yet. */
|
|
if((H5Tget_class(tid) == H5T_COMPOUND)
|
|
&& (H5Tdetect_class(tid, H5T_VLEN) == TRUE)) {
|
|
hid_t memb_id; /* Member id */
|
|
const uint8_t *memb1; /* Pointer to current member */
|
|
const uint8_t *memb2; /* Pointer to current member */
|
|
int nmembs; /* Number of members */
|
|
size_t memb_off; /* Member offset */
|
|
size_t memb_size; /* Member size */
|
|
unsigned memb_idx; /* Member index */
|
|
size_t elmt; /* Current element */
|
|
|
|
/* Get number of members in compound */
|
|
if((nmembs = H5Tget_nmembers(tid)) < 0) TEST_ERROR
|
|
|
|
/* Loop over members */
|
|
for(memb_idx=0; memb_idx<(unsigned)nmembs; memb_idx++) {
|
|
/* Get member offset. Note that we cannot check for an error here.
|
|
*/
|
|
memb_off = H5Tget_member_offset(tid, memb_idx);
|
|
|
|
/* Get member id */
|
|
if((memb_id = H5Tget_member_type(tid, memb_idx)) < 0) TEST_ERROR
|
|
|
|
/* Get member size */
|
|
if((memb_size = H5Tget_size(memb_id)) == 0) TEST_ERROR
|
|
|
|
/* Set up pointers to member in the first element */
|
|
memb1 = (const uint8_t *)buf1 + memb_off;
|
|
memb2 = (const uint8_t *)buf2 + memb_off;
|
|
|
|
/* Check if this member contains (or is) a vlen */
|
|
if(H5Tget_class(memb_id) == H5T_VLEN) {
|
|
hid_t base_id; /* vlen base type id */
|
|
|
|
/* Get base type of vlen datatype */
|
|
if((base_id = H5Tget_super(memb_id)) < 0) TEST_ERROR
|
|
|
|
/* Iterate over all elements, recursively calling this function
|
|
* for each */
|
|
for(elmt=0; elmt<nelmts; elmt++) {
|
|
/* Check vlen lengths */
|
|
if(((const hvl_t *)((const void *)memb1))->len
|
|
!= ((const hvl_t *)((const void *)memb2))->len)
|
|
TEST_ERROR
|
|
|
|
/* Check vlen data */
|
|
if(!compare_data(parent1, parent2, pid, base_id,
|
|
((const hvl_t *)((const void *)memb1))->len,
|
|
((const hvl_t *)((const void *)memb1))->p,
|
|
((const hvl_t *)((const void *)memb2))->p, obj_owner))
|
|
TEST_ERROR
|
|
|
|
/* Update member pointers */
|
|
memb1 += elmt_size;
|
|
memb2 += elmt_size;
|
|
} /* end for */
|
|
} else {
|
|
/* vlens cannot currently be nested below the top layer of a
|
|
* compound */
|
|
HDassert(H5Tdetect_class(memb_id, H5T_VLEN) == FALSE);
|
|
|
|
/* Iterate over all elements, calling memcmp() for each */
|
|
for(elmt=0; elmt<nelmts; elmt++) {
|
|
if(HDmemcmp(memb1, memb2, memb_size))
|
|
TEST_ERROR
|
|
|
|
/* Update member pointers */
|
|
memb1 += elmt_size;
|
|
memb2 += elmt_size;
|
|
} /* end for */
|
|
} /* end else */
|
|
} /* end for */
|
|
} else if(H5Tdetect_class(tid, H5T_VLEN) == TRUE) {
|
|
const hvl_t *vl_buf1, *vl_buf2; /* Aliases for buffers to compare */
|
|
hid_t base_tid; /* Base type of vlen datatype */
|
|
size_t u; /* Local index variable */
|
|
|
|
/* Check for "simple" vlen datatype */
|
|
if(H5Tget_class(tid) != H5T_VLEN) TEST_ERROR
|
|
|
|
/* Get base type of vlen datatype */
|
|
if((base_tid = H5Tget_super(tid)) < 0) TEST_ERROR
|
|
|
|
/* Loop over elements in buffers */
|
|
vl_buf1 = (const hvl_t *)buf1;
|
|
vl_buf2 = (const hvl_t *)buf2;
|
|
for(u = 0; u < nelmts; u++, vl_buf1++, vl_buf2++) {
|
|
/* Check vlen lengths */
|
|
if(vl_buf1->len != vl_buf2->len) TEST_ERROR
|
|
|
|
/* Check vlen data */
|
|
if(!compare_data(parent1, parent2, pid, base_tid, vl_buf1->len, vl_buf1->p, vl_buf2->p, obj_owner)) TEST_ERROR
|
|
} /* end for */
|
|
|
|
if(H5Tclose(base_tid) < 0) TEST_ERROR
|
|
} /* end if */
|
|
else if(H5Tdetect_class(tid, H5T_REFERENCE) == TRUE) {
|
|
size_t u; /* Local index variable */
|
|
|
|
/* Check for "simple" reference datatype */
|
|
if(H5Tget_class(tid) != H5T_REFERENCE) TEST_ERROR
|
|
|
|
/* Check for object or region reference */
|
|
if(H5Tequal(tid, H5T_STD_REF) > 0) {
|
|
const H5R_ref_t *ref_buf1, *ref_buf2; /* Aliases for buffers to compare */
|
|
|
|
/* Loop over elements in buffers */
|
|
ref_buf1 = (const H5R_ref_t *)buf1;
|
|
ref_buf2 = (const H5R_ref_t *)buf2;
|
|
for(u = 0; u < nelmts; u++, ref_buf1++, ref_buf2++) {
|
|
hid_t obj1_id, obj2_id; /* IDs for objects referenced */
|
|
H5O_type_t obj1_type, obj2_type; /* Types of objects referenced */
|
|
|
|
/* Check for types of objects handled */
|
|
if(H5Rget_obj_type3(ref_buf1, H5P_DEFAULT, &obj1_type) < 0) TEST_ERROR
|
|
if(H5Rget_obj_type3(ref_buf2, H5P_DEFAULT, &obj2_type) < 0) TEST_ERROR
|
|
if(obj1_type != obj2_type) TEST_ERROR
|
|
|
|
/* Open referenced objects */
|
|
if((obj1_id = H5Ropen_object(ref_buf1, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if((obj2_id = H5Ropen_object(ref_buf2, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
|
|
/* break the infinite loop when the ref_object points to itself */
|
|
if(obj_owner > 0) {
|
|
H5O_info_t oinfo1, oinfo2;
|
|
|
|
if(H5Oget_info2(obj_owner, &oinfo1, H5O_INFO_BASIC) < 0) TEST_ERROR
|
|
if(H5Oget_info2(obj1_id, &oinfo2, H5O_INFO_BASIC) < 0) TEST_ERROR
|
|
if(H5F_addr_eq(oinfo1.addr, oinfo2.addr)) {
|
|
if(H5Oclose(obj1_id) < 0) TEST_ERROR
|
|
if(H5Oclose(obj2_id) < 0) TEST_ERROR
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/* Check for types of objects handled */
|
|
switch(obj1_type) {
|
|
case H5O_TYPE_DATASET:
|
|
if(compare_datasets(obj1_id, obj2_id, pid, NULL) != TRUE) TEST_ERROR
|
|
break;
|
|
|
|
case H5O_TYPE_GROUP:
|
|
if(compare_groups(obj1_id, obj2_id, pid, -1, 0) != TRUE) TEST_ERROR
|
|
break;
|
|
|
|
case H5O_TYPE_NAMED_DATATYPE:
|
|
if(H5Tequal(obj1_id, obj2_id) != TRUE) TEST_ERROR
|
|
break;
|
|
|
|
case H5O_TYPE_MAP:
|
|
/* Maps not supported in native VOL connector */
|
|
|
|
case H5O_TYPE_UNKNOWN:
|
|
case H5O_TYPE_NTYPES:
|
|
default:
|
|
TEST_ERROR
|
|
} /* end switch */
|
|
|
|
/* Close objects */
|
|
if(H5Oclose(obj1_id) < 0) TEST_ERROR
|
|
if(H5Oclose(obj2_id) < 0) TEST_ERROR
|
|
|
|
if(H5Rget_type(ref_buf1) == H5R_DATASET_REGION2) {
|
|
hid_t obj1_sid, obj2_sid; /* Dataspace IDs for objects referenced */
|
|
|
|
/* Get regions for referenced datasets */
|
|
if((obj1_sid = H5Ropen_region(ref_buf1, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if((obj2_sid = H5Ropen_region(ref_buf2, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
|
|
/* Check if dataspaces are the same shape */
|
|
if(H5Sselect_shape_same(obj1_sid, obj2_sid) < 0) TEST_ERROR
|
|
|
|
/* Close dataspaces */
|
|
if(H5Sclose(obj1_sid) < 0) TEST_ERROR
|
|
if(H5Sclose(obj2_sid) < 0) TEST_ERROR
|
|
} /* end if */
|
|
} /* end for */
|
|
} /* end if */
|
|
else
|
|
TEST_ERROR
|
|
} /* end else */
|
|
else
|
|
if(HDmemcmp(buf1, buf2, (elmt_size * nelmts))) TEST_ERROR
|
|
|
|
/* Data should be the same. :-) */
|
|
return TRUE;
|
|
|
|
error:
|
|
return FALSE;
|
|
} /* end compare_data() */
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: compare_datasets
|
|
*
|
|
* Purpose: Compare two datasets to check that they are equal
|
|
*
|
|
* Return: TRUE if datasets are equal/FALSE if they are different
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Tuesday, October 25, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
compare_datasets(hid_t did, hid_t did2, hid_t pid, const void *wbuf)
|
|
{
|
|
hid_t sid = -1, sid2 = -1; /* Dataspace IDs */
|
|
hid_t tid = -1, tid2 = -1; /* Datatype IDs */
|
|
hid_t dcpl = -1, dcpl2 = -1; /* Dataset creation property list IDs */
|
|
size_t elmt_size; /* Size of datatype */
|
|
htri_t is_committed; /* If the datatype is committed */
|
|
htri_t is_committed2; /* If the datatype is committed */
|
|
int nfilters; /* Number of filters applied to dataset */
|
|
hssize_t nelmts; /* # of elements in dataspace */
|
|
void *rbuf = NULL; /* Buffer for reading raw data */
|
|
void *rbuf2 = NULL; /* Buffer for reading raw data */
|
|
H5D_space_status_t space_status; /* Dataset's raw dataspace status */
|
|
H5D_space_status_t space_status2; /* Dataset's raw dataspace status */
|
|
|
|
/* Check the datatypes are equal */
|
|
|
|
/* Open the datatype for the source dataset */
|
|
if((tid = H5Dget_type(did)) < 0) TEST_ERROR
|
|
|
|
/* Open the datatype for the destination dataset */
|
|
if((tid2 = H5Dget_type(did2)) < 0) TEST_ERROR
|
|
|
|
/* Check that both datatypes are committed/not committed */
|
|
if((is_committed = H5Tcommitted(tid)) < 0) TEST_ERROR
|
|
if((is_committed2 = H5Tcommitted(tid2)) < 0) TEST_ERROR
|
|
if(is_committed != is_committed2) TEST_ERROR
|
|
|
|
/* Compare the datatypes */
|
|
if(H5Tequal(tid, tid2) != TRUE) TEST_ERROR
|
|
|
|
/* Determine the size of datatype (for later) */
|
|
if((elmt_size = H5Tget_size(tid)) == 0) TEST_ERROR
|
|
|
|
|
|
/* Check the dataspaces are equal */
|
|
|
|
/* Open the dataspace for the source dataset */
|
|
if((sid = H5Dget_space(did)) < 0) TEST_ERROR
|
|
|
|
/* Open the dataspace for the destination dataset */
|
|
if((sid2 = H5Dget_space(did2)) < 0) TEST_ERROR
|
|
|
|
/* Compare the dataspaces */
|
|
if(H5Sextent_equal(sid, sid2) != TRUE) TEST_ERROR
|
|
|
|
/* Determine the number of elements in dataspace (for later) */
|
|
if((nelmts = H5Sget_simple_extent_npoints(sid)) < 0) TEST_ERROR
|
|
|
|
|
|
/* Check the dataset creation property lists are equal */
|
|
|
|
/* Open the dataset creation property list for the source dataset */
|
|
if((dcpl = H5Dget_create_plist(did)) < 0) TEST_ERROR
|
|
|
|
/* Open the dataset creation property list for the destination dataset */
|
|
if((dcpl2 = H5Dget_create_plist(did2)) < 0) TEST_ERROR
|
|
|
|
/* Compare the rest of the dataset creation property lists */
|
|
if(H5Pequal(dcpl, dcpl2) != TRUE) TEST_ERROR
|
|
|
|
/* Get the number of filters on dataset (for later) */
|
|
if((nfilters = H5Pget_nfilters(dcpl)) < 0) TEST_ERROR
|
|
|
|
/* close the source dataset creation property list */
|
|
if(H5Pclose(dcpl) < 0) TEST_ERROR
|
|
|
|
/* close the destination dataset creation property list */
|
|
if(H5Pclose(dcpl2) < 0) TEST_ERROR
|
|
|
|
|
|
/* Check the allocated storage is the same */
|
|
|
|
/* Check that the space allocation status is the same */
|
|
if(H5Dget_space_status(did, &space_status) < 0) TEST_ERROR
|
|
if(H5Dget_space_status(did2, &space_status2) < 0) TEST_ERROR
|
|
if(space_status != space_status2) TEST_ERROR
|
|
|
|
/* Check that the space used is the same */
|
|
/* (Don't check if the dataset is filtered (i.e. compressed, etc.) and
|
|
* the datatype is VLEN, since the addresses for the vlen
|
|
* data in each dataset will (probably) be different and the storage
|
|
* size will thus vary)
|
|
*/
|
|
if(!(nfilters > 0 && (H5Tdetect_class(tid, H5T_VLEN) ||
|
|
(H5Tdetect_class(tid, H5T_REFERENCE) && H5Tequal(tid, H5T_STD_REF))))) {
|
|
hsize_t storage_size = H5Dget_storage_size(did); /* Dataset's raw data storage size */
|
|
hsize_t storage_size2 = H5Dget_storage_size(did2); /* 2nd Dataset's raw data storage size */
|
|
|
|
if(storage_size != storage_size2) TEST_ERROR
|
|
} /* end if */
|
|
|
|
/* Check the raw data is equal */
|
|
|
|
/* Allocate & initialize space for the raw data buffers */
|
|
if((rbuf = HDcalloc( elmt_size, (size_t)nelmts)) == NULL) TEST_ERROR
|
|
if((rbuf2 = HDcalloc( elmt_size, (size_t)nelmts)) == NULL) TEST_ERROR
|
|
|
|
/* Read data from datasets */
|
|
if(H5Dread(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0) TEST_ERROR
|
|
if(H5Dread(did2, tid2, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf2) < 0) TEST_ERROR
|
|
|
|
/* Check raw data read in against data written out */
|
|
if(wbuf) {
|
|
if(!compare_data(did, (hid_t)0, pid, tid, (size_t)nelmts, wbuf, rbuf, did)) TEST_ERROR
|
|
if(!compare_data(did2, (hid_t)0, pid, tid2, (size_t)nelmts, wbuf, rbuf2, did2)) TEST_ERROR
|
|
} /* end if */
|
|
/* Don't have written data, just compare data between the two datasets */
|
|
else
|
|
if(!compare_data(did, did2, pid, tid, (size_t)nelmts, rbuf, rbuf2, did)) TEST_ERROR
|
|
|
|
/* Reclaim vlen data, if necessary */
|
|
if(H5Tdetect_class(tid, H5T_VLEN) == TRUE || H5Tdetect_class(tid, H5T_REFERENCE) == TRUE)
|
|
if(H5Treclaim(tid, sid, H5P_DEFAULT, rbuf) < 0) TEST_ERROR
|
|
if(H5Tdetect_class(tid2, H5T_VLEN) == TRUE || H5Tdetect_class(tid2, H5T_REFERENCE) == TRUE)
|
|
if(H5Treclaim(tid2, sid2, H5P_DEFAULT, rbuf2) < 0) TEST_ERROR
|
|
|
|
/* Release raw data buffers */
|
|
HDfree(rbuf);
|
|
rbuf = NULL;
|
|
HDfree(rbuf2);
|
|
rbuf2 = NULL;
|
|
|
|
/* close the source dataspace */
|
|
if(H5Sclose(sid) < 0) TEST_ERROR
|
|
|
|
/* close the destination dataspace */
|
|
if(H5Sclose(sid2) < 0) TEST_ERROR
|
|
|
|
/* close the source datatype */
|
|
if(H5Tclose(tid) < 0) TEST_ERROR
|
|
|
|
/* close the destination datatype */
|
|
if(H5Tclose(tid2) < 0) TEST_ERROR
|
|
|
|
|
|
/* Check if the attributes are equal */
|
|
if(compare_std_attributes(did, did2, pid) != TRUE) TEST_ERROR
|
|
|
|
|
|
/* Datasets should be the same. :-) */
|
|
return TRUE;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY {
|
|
if(rbuf)
|
|
HDfree(rbuf);
|
|
if(rbuf2)
|
|
HDfree(rbuf2);
|
|
H5Pclose(dcpl2);
|
|
H5Pclose(dcpl);
|
|
H5Sclose(sid2);
|
|
H5Sclose(sid);
|
|
H5Tclose(tid2);
|
|
H5Tclose(tid);
|
|
} H5E_END_TRY;
|
|
return FALSE;
|
|
} /* end compare_datasets() */
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: compare_groups
|
|
*
|
|
* Purpose: Compare two groups to check that they are "equal"
|
|
*
|
|
* Return: TRUE if group are equal/FALSE if they are different
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Monday, October 31, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth, unsigned copy_flags)
|
|
{
|
|
H5G_info_t ginfo; /* Group info struct */
|
|
H5G_info_t ginfo2; /* Group info struct */
|
|
hsize_t idx; /* Index over the objects in group */
|
|
unsigned cpy_flags; /* Object copy flags */
|
|
|
|
/* Retrieve the object copy flags from the property list, if it's non-DEFAULT */
|
|
if(pid != H5P_DEFAULT) {
|
|
if(H5Pget_copy_object(pid, &cpy_flags) < 0) TEST_ERROR
|
|
} /* end if */
|
|
else
|
|
cpy_flags = 0;
|
|
|
|
/* Check if both groups have the same # of objects */
|
|
if(H5Gget_info(gid, &ginfo) < 0) TEST_ERROR
|
|
if(H5Gget_info(gid2, &ginfo2) < 0) TEST_ERROR
|
|
if((cpy_flags & H5O_COPY_SHALLOW_HIERARCHY_FLAG) && depth == 0) {
|
|
if(ginfo2.nlinks != 0) TEST_ERROR
|
|
} /* end if */
|
|
else {
|
|
if(ginfo.nlinks != ginfo2.nlinks) TEST_ERROR
|
|
} /* end if */
|
|
|
|
/* Check contents of groups */
|
|
if(ginfo2.nlinks > 0) {
|
|
char objname[NAME_BUF_SIZE]; /* Name of object in group */
|
|
char objname2[NAME_BUF_SIZE]; /* Name of object in group */
|
|
H5L_info_t linfo; /* Link information */
|
|
H5L_info_t linfo2; /* Link information */
|
|
|
|
/* Loop over contents of groups */
|
|
for(idx = 0; idx < ginfo.nlinks; idx++) {
|
|
/* Check name of objects */
|
|
if(H5Lget_name_by_idx(gid, ".", H5_INDEX_NAME, H5_ITER_INC, idx, objname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT) < 0) TEST_ERROR
|
|
if(H5Lget_name_by_idx(gid2, ".", H5_INDEX_NAME, H5_ITER_INC, idx, objname2, (size_t)NAME_BUF_SIZE, H5P_DEFAULT) < 0) TEST_ERROR
|
|
if(HDstrcmp(objname, objname2)) TEST_ERROR
|
|
|
|
/* Get link info */
|
|
if(H5Lget_info(gid, objname, &linfo, H5P_DEFAULT) < 0) TEST_ERROR
|
|
if(H5Lget_info(gid2, objname2, &linfo2, H5P_DEFAULT) < 0) TEST_ERROR
|
|
if(linfo.type != linfo2.type) TEST_ERROR
|
|
|
|
/* Extra checks for "real" objects */
|
|
if(linfo.type == H5L_TYPE_HARD) {
|
|
hid_t oid, oid2; /* IDs of objects within group */
|
|
H5O_info_t oinfo, oinfo2; /* Object info */
|
|
|
|
/* Compare some pieces of the object info */
|
|
if(H5Oget_info_by_name2(gid, objname, &oinfo, H5O_INFO_BASIC|H5O_INFO_HDR, H5P_DEFAULT) < 0) TEST_ERROR
|
|
if(H5Oget_info_by_name2(gid2, objname2, &oinfo2, H5O_INFO_BASIC|H5O_INFO_HDR, H5P_DEFAULT) < 0) TEST_ERROR
|
|
|
|
if(oinfo.type != oinfo2.type) TEST_ERROR
|
|
if(oinfo.rc != oinfo2.rc) TEST_ERROR
|
|
|
|
/* If NULL messages are preserved, the number of messages
|
|
* should be the same in the destination.
|
|
* Otherwise, it should simply be true that the number
|
|
* of messages hasn't increased.
|
|
*/
|
|
if(H5O_COPY_PRESERVE_NULL_FLAG & copy_flags) {
|
|
if(oinfo.hdr.nmesgs != oinfo2.hdr.nmesgs)
|
|
;
|
|
else
|
|
if(oinfo.hdr.nmesgs < oinfo2.hdr.nmesgs) TEST_ERROR
|
|
}
|
|
|
|
/* Check for object already having been compared */
|
|
if(addr_lookup(&oinfo))
|
|
continue;
|
|
else
|
|
addr_insert(&oinfo);
|
|
|
|
/* Open objects */
|
|
if((oid = H5Oopen(gid, objname, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
if((oid2 = H5Oopen(gid2, objname2, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
|
|
/* Compare objects within group */
|
|
switch(oinfo.type) {
|
|
case H5O_TYPE_GROUP:
|
|
/* Compare groups */
|
|
if(compare_groups(oid, oid2, pid, depth - 1, copy_flags) != TRUE) TEST_ERROR
|
|
break;
|
|
|
|
case H5O_TYPE_DATASET:
|
|
/* Compare datasets */
|
|
if(compare_datasets(oid, oid2, pid, NULL) != TRUE) TEST_ERROR
|
|
break;
|
|
|
|
case H5O_TYPE_NAMED_DATATYPE:
|
|
/* Compare datatypes */
|
|
if(H5Tequal(oid, oid2) != TRUE) TEST_ERROR
|
|
break;
|
|
|
|
case H5O_TYPE_MAP:
|
|
HDassert(0 && "maps not supported in native VOL connector");
|
|
|
|
case H5O_TYPE_UNKNOWN:
|
|
case H5O_TYPE_NTYPES:
|
|
default:
|
|
HDassert(0 && "Unknown type of object");
|
|
break;
|
|
} /* end switch */
|
|
|
|
/* Close objects */
|
|
if(H5Oclose(oid) < 0) TEST_ERROR
|
|
if(H5Oclose(oid2) < 0) TEST_ERROR
|
|
} /* end if */
|
|
else {
|
|
/* Check that both links are the same size */
|
|
if(linfo.u.val_size != linfo2.u.val_size) TEST_ERROR
|
|
|
|
/* Compare link values */
|
|
if(linfo.type == H5L_TYPE_SOFT ||
|
|
(linfo.type >= H5L_TYPE_UD_MIN && linfo.type <= H5L_TYPE_MAX)) {
|
|
char linkval[NAME_BUF_SIZE]; /* Link value */
|
|
char linkval2[NAME_BUF_SIZE]; /* Link value */
|
|
|
|
/* Get link values */
|
|
HDassert(linfo.u.val_size <= NAME_BUF_SIZE);
|
|
if(H5Lget_val(gid, objname, linkval, (size_t)NAME_BUF_SIZE, H5P_DEFAULT) < 0) TEST_ERROR
|
|
if(H5Lget_val(gid2, objname2, linkval2, (size_t)NAME_BUF_SIZE, H5P_DEFAULT) < 0) TEST_ERROR
|
|
|
|
/* Compare link data */
|
|
if(HDmemcmp(linkval, linkval2, linfo.u.val_size)) TEST_ERROR
|
|
} /* end else-if */
|
|
else {
|
|
HDassert(0 && "Unknown type of link");
|
|
} /* end else */
|
|
} /* end else */
|
|
} /* end for */
|
|
} /* end if */
|
|
|
|
/* Check if the attributes are equal */
|
|
if(compare_std_attributes(gid, gid2, pid) != TRUE) TEST_ERROR
|
|
|
|
/* Groups should be the same. :-) */
|
|
return TRUE;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY {
|
|
} H5E_END_TRY;
|
|
return FALSE;
|
|
} /* end compare_groups() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_copy_option
|
|
*
|
|
* Purpose: Create a group in SRC file and copy it to DST file
|
|
*
|
|
* Return: Success: 0
|
|
* Failure: number of errors
|
|
*
|
|
* Programmer: Peter Cao
|
|
* March 11, 2006
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_copy_option(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, hid_t dst_fapl,
|
|
unsigned flag, hbool_t crt_intermediate_grp, const char* test_desciption)
|
|
{
|
|
hid_t fid_src = -1, fid_dst = -1, fid_ext = -1; /* File IDs */
|
|
hid_t sid = -1; /* Dataspace ID */
|
|
hid_t did = -1; /* Dataset ID */
|
|
hid_t gid=-1, gid2=-1, gid_ref=-1; /* Group IDs */
|
|
hid_t gid_sub=-1, gid_sub_sub=-1; /* Sub-group ID */
|
|
hid_t pid=-1, lcpl_id=-1; /* Property IDs */
|
|
unsigned cpy_flags; /* Object copy flags */
|
|
int depth = -1; /* Copy depth */
|
|
hsize_t dim2d[2];
|
|
int buf[DIM_SIZE_1][DIM_SIZE_2];
|
|
int i, j;
|
|
char src_filename[NAME_BUF_SIZE];
|
|
char dst_filename[NAME_BUF_SIZE];
|
|
|
|
TESTING(test_desciption);
|
|
|
|
/* set initial data values */
|
|
for (i=0; i<DIM_SIZE_1; i++)
|
|
for (j=0; j<DIM_SIZE_2; j++)
|
|
buf[i][j] = 10000 + 100*i+j;
|
|
|
|
/* Initialize the filenames */
|
|
h5_fixname(FILENAME[0], src_fapl, src_filename, sizeof src_filename);
|
|
h5_fixname(FILENAME[1], dst_fapl, dst_filename, sizeof dst_filename);
|
|
|
|
/* Reset file address checking info */
|
|
addr_reset();
|
|
|
|
/* create source file */
|
|
if((fid_src = H5Fcreate(src_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR
|
|
|
|
/* create group at the SRC file */
|
|
if((gid = H5Gcreate2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
|
|
/* attach attributes to the group */
|
|
if(test_copy_attach_attributes(gid, H5T_NATIVE_INT) < 0) TEST_ERROR
|
|
|
|
/* Set dataspace dimensions */
|
|
dim2d[0]=DIM_SIZE_1;
|
|
dim2d[1]=DIM_SIZE_2;
|
|
|
|
/* create dataspace */
|
|
if((sid = H5Screate_simple(2, dim2d, NULL)) < 0) TEST_ERROR
|
|
|
|
/* add a dataset to the top group */
|
|
if((did = H5Dcreate2(gid, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
|
|
if(H5Dclose(did) < 0) TEST_ERROR
|
|
|
|
/* create a sub-group */
|
|
if((gid_sub = H5Gcreate2(fid_src, NAME_GROUP_SUB, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
|
|
/* add a dataset to the sub group */
|
|
if((did = H5Dcreate2(gid_sub, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
|
|
if(H5Dclose(did) < 0) TEST_ERROR
|
|
|
|
/* create sub-sub-group */
|
|
if((gid_sub_sub = H5Gcreate2(gid_sub, NAME_GROUP_SUB_SUB2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
|
|
/* add a dataset to the sub sub group */
|
|
if((did = H5Dcreate2(gid_sub_sub, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
|
|
|
|
/* close dataset */
|
|
if(H5Dclose(did) < 0) TEST_ERROR
|
|
|
|
/* close dataspace */
|
|
if(H5Sclose(sid) < 0) TEST_ERROR
|
|
|
|
if(H5Gclose(gid_sub_sub) < 0) TEST_ERROR
|
|
|
|
if(H5Gclose(gid_sub) < 0) TEST_ERROR
|
|
|
|
/* close the group */
|
|
if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
|
|
|
|
if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) {
|
|
/* Create group to copy */
|
|
if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
if(H5Lcreate_soft(NAME_DATASET_SUB_SUB, fid_src, NAME_LINK_SOFT, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
|
|
if(H5Lcreate_soft("nowhere", fid_src, NAME_LINK_SOFT_DANGLE, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
|
|
if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
|
|
|
|
/* Create group to compare with */
|
|
if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
if(H5Lcreate_hard(fid_src, NAME_DATASET_SUB_SUB, H5L_SAME_LOC, NAME_LINK_SOFT2, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
|
|
if(H5Lcreate_soft("nowhere", fid_src, NAME_LINK_SOFT_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
|
|
if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
|
|
} /* end if */
|
|
|
|
if((flag & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0) {
|
|
char ext_filename[NAME_BUF_SIZE];
|
|
|
|
h5_fixname(FILENAME[2], src_fapl, ext_filename, sizeof ext_filename);
|
|
|
|
/* Create the external file and dataset */
|
|
if((fid_ext = H5Fcreate(ext_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR
|
|
if((sid = H5Screate_simple(2, dim2d, NULL)) < 0) TEST_ERROR
|
|
if((did = H5Dcreate2(fid_ext, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
|
|
if(H5Dclose(did) < 0) TEST_ERROR
|
|
if(H5Fclose(fid_ext) < 0) TEST_ERROR
|
|
|
|
/* Create group to copy */
|
|
if(!(flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG)) {
|
|
if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
} /* end if */
|
|
else
|
|
if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Lcreate_external(ext_filename, NAME_DATASET_SIMPLE, fid_src, NAME_LINK_EXTERN, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
|
|
if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
|
|
if(H5Gclose(gid) < 0) TEST_ERROR
|
|
|
|
/* Create group to compare with */
|
|
if(!(flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG)) {
|
|
if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
} /* end if */
|
|
else
|
|
if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if((did = H5Dcreate2(fid_src, NAME_LINK_EXTERN2, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
|
|
if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
|
|
if(H5Dclose(did) < 0) TEST_ERROR
|
|
if(H5Gclose(gid) < 0) TEST_ERROR
|
|
|
|
/* Close dataspace */
|
|
if(H5Sclose(sid) < 0) TEST_ERROR
|
|
} /* end if */
|
|
|
|
if((flag & H5O_COPY_EXPAND_REFERENCE_FLAG) > 0) {
|
|
if((gid_ref = H5Gcreate2(fid_src, NAME_GROUP_REF, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
|
|
/* create an attribute of new object references */
|
|
if(attach_ref_attr(fid_src, gid_ref) < 0) TEST_ERROR
|
|
|
|
/* create an attribute of region references */
|
|
if(attach_reg_ref_attr(fid_src, gid_ref) < 0) TEST_ERROR
|
|
|
|
/* create a dataset of region references */
|
|
if(create_reg_ref_dataset(fid_src, gid_ref) < 0) TEST_ERROR
|
|
|
|
/* Close group holding reference objects */
|
|
if(H5Gclose(gid_ref) < 0) TEST_ERROR
|
|
} /* end if */
|
|
|
|
/* close the SRC file */
|
|
if(H5Fclose(fid_src) < 0) TEST_ERROR
|
|
|
|
/* open the source file with read-only */
|
|
/* (except when expanding soft links */
|
|
if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) {
|
|
if((fid_src = H5Fopen(src_filename, H5F_ACC_RDWR, src_fapl)) < 0) TEST_ERROR
|
|
} /* end if */
|
|
else
|
|
if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR
|
|
|
|
/* create destination file */
|
|
if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR
|
|
|
|
/* Create an uncopied object in destination file so that addresses in source and destination
|
|
files aren't the same */
|
|
if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
|
|
|
|
/* create property to pass copy options */
|
|
if((pid = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR
|
|
|
|
/* set options for object copy */
|
|
if(H5Pset_copy_object(pid, flag) < 0) TEST_ERROR
|
|
|
|
/* Verify object copy flags */
|
|
if(H5Pget_copy_object(pid, &cpy_flags) < 0) TEST_ERROR
|
|
if(cpy_flags != flag) TEST_ERROR
|
|
|
|
/* copy the group from SRC to DST */
|
|
if(crt_intermediate_grp) {
|
|
/* Create link creation plist to pass in intermediate group creation */
|
|
if((lcpl_id = H5Pcreate(H5P_LINK_CREATE)) < 0) TEST_ERROR
|
|
if(H5Pset_create_intermediate_group(lcpl_id, TRUE) < 0) TEST_ERROR
|
|
|
|
if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, "/new_g0/new_g00", pid, lcpl_id) < 0) TEST_ERROR
|
|
|
|
if(H5Pclose(lcpl_id) < 0) TEST_ERROR
|
|
|
|
/* open the group for copy */
|
|
if((gid = H5Gopen2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
|
|
/* open the destination group */
|
|
if((gid2 = H5Gopen2(fid_dst, "/new_g0/new_g00", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
|
|
} else if(((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0)
|
|
|| ((flag & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0)) {
|
|
if(H5Ocopy(fid_src, NAME_GROUP_LINK, fid_dst, NAME_GROUP_LINK, pid, H5P_DEFAULT) < 0) TEST_ERROR
|
|
|
|
if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0)
|
|
/* Unlink dataset to copy from original location */
|
|
/* (So group comparison works properly) */
|
|
if(H5Ldelete(fid_src, NAME_DATASET_SUB_SUB, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
|
|
|
|
/* open the group for copy */
|
|
if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
|
|
/* open the destination group */
|
|
if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
|
|
} else if(flag & (H5O_COPY_WITHOUT_ATTR_FLAG | H5O_COPY_PRESERVE_NULL_FLAG)) {
|
|
if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, NAME_GROUP_TOP, pid, H5P_DEFAULT) < 0) TEST_ERROR
|
|
|
|
/* open the group for copy */
|
|
if((gid = H5Gopen2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
|
|
/* open the destination group */
|
|
if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
} else if(flag & H5O_COPY_SHALLOW_HIERARCHY_FLAG) {
|
|
if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, NAME_GROUP_TOP, pid, H5P_DEFAULT) < 0) TEST_ERROR
|
|
|
|
/* open the group for copy */
|
|
if((gid = H5Gopen2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
|
|
/* open the destination group */
|
|
if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
|
|
/* Set the copy depth */
|
|
depth = 1;
|
|
} else if((flag & H5O_COPY_EXPAND_REFERENCE_FLAG) > 0) {
|
|
if(H5Ocopy(fid_src, NAME_GROUP_REF, fid_dst, NAME_GROUP_REF, pid, H5P_DEFAULT) < 0) TEST_ERROR
|
|
|
|
/* open the group for copy */
|
|
if((gid = H5Gopen2(fid_src, NAME_GROUP_REF, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
|
|
/* open the destination group */
|
|
if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_REF, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
|
|
} else {
|
|
/* Unknown flag */
|
|
TEST_ERROR
|
|
} /* end else */
|
|
|
|
/* Check if the groups are equal */
|
|
if(compare_groups(gid, gid2, pid, depth, flag) != TRUE) TEST_ERROR
|
|
if(H5Gclose(gid2) < 0) TEST_ERROR
|
|
if(H5Gclose(gid) < 0) TEST_ERROR
|
|
|
|
/* close the SRC file */
|
|
if(H5Fclose(fid_src) < 0) TEST_ERROR
|
|
|
|
/* close the DST file */
|
|
if(H5Fclose(fid_dst) < 0) TEST_ERROR
|
|
|
|
/* close properties */
|
|
if(H5Pclose(pid) < 0) TEST_ERROR
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY {
|
|
H5Pclose(lcpl_id);
|
|
H5Pclose(pid);
|
|
H5Sclose(sid);
|
|
H5Dclose(did);
|
|
H5Gclose(gid_ref);
|
|
H5Gclose(gid_sub);
|
|
H5Gclose(gid2);
|
|
H5Gclose(gid);
|
|
H5Fclose(fid_dst);
|
|
H5Fclose(fid_src);
|
|
H5Fclose(fid_ext);
|
|
} H5E_END_TRY;
|
|
return 1;
|
|
} /* end test_copy_option */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: main
|
|
*
|
|
* Purpose: Test H5Ocopy()
|
|
*
|
|
* Tests a number of cases: messages can be stored in the
|
|
* new or old format, messages can be shared in either,
|
|
* both, or neither of the source and destination files.
|
|
*
|
|
* Return: EXIT_SUCCESS/EXIT_FAILURE
|
|
*
|
|
* Programmer: Peter Cao
|
|
* Friday, September 30, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
main(void)
|
|
{
|
|
int nerrors = 0;
|
|
hid_t fapl, fapl2;
|
|
hid_t fcpl_shared, ocpl;
|
|
unsigned max_compact, min_dense;
|
|
int configuration; /* Configuration of tests. */
|
|
int ExpressMode;
|
|
|
|
/* Setup */
|
|
h5_reset();
|
|
fapl = h5_fileaccess();
|
|
|
|
ExpressMode = GetTestExpress();
|
|
if (ExpressMode > 1)
|
|
HDprintf("***Express test mode on. Some tests may be skipped\n");
|
|
|
|
/* Copy the file access property list */
|
|
if((fapl2 = H5Pcopy(fapl)) < 0) TEST_ERROR
|
|
|
|
/* Set the "use the latest version of the format" bounds for creating objects in the file */
|
|
if(H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) TEST_ERROR
|
|
|
|
/* Create an FCPL with sharing enabled */
|
|
if((fcpl_shared = H5Pcreate(H5P_FILE_CREATE)) < 0) TEST_ERROR
|
|
if(H5Pset_shared_mesg_nindexes(fcpl_shared, 1) < 0) TEST_ERROR
|
|
if(H5Pset_shared_mesg_index(fcpl_shared, 0, H5O_SHMESG_ALL_FLAG, 10) < 0) TEST_ERROR
|
|
|
|
/* Obtain the default attribute storage phase change values */
|
|
if((ocpl = H5Pcreate(H5P_OBJECT_CREATE)) < 0) TEST_ERROR
|
|
if(H5Pget_attr_phase_change(ocpl, &max_compact, &min_dense) < 0) TEST_ERROR
|
|
if(H5Pclose(ocpl) < 0) TEST_ERROR
|
|
|
|
/* Test in all configurations */
|
|
for(configuration = 0; configuration <= MAX_CONFIGURATION; configuration++) {
|
|
hid_t src_fapl;
|
|
hid_t dst_fapl;
|
|
hid_t fcpl_src;
|
|
hid_t fcpl_dst;
|
|
|
|
/* No need to test dense attributes with old format */
|
|
if(!(configuration & CONFIG_SRC_NEW_FORMAT) && (configuration & CONFIG_DENSE))
|
|
continue;
|
|
|
|
/* TODO Region references currently do not support copy from new format to old format
|
|
* (this may be fixed once H5Sencode/decode and H5CXis fixed) */
|
|
if((configuration & CONFIG_SRC_NEW_FORMAT) && !(configuration & CONFIG_DST_NEW_FORMAT))
|
|
continue;
|
|
|
|
/* Test with and without shared messages */
|
|
if(configuration & CONFIG_SHARE_SRC) {
|
|
HDputs("\nTesting with shared src messages:");
|
|
fcpl_src = fcpl_shared;
|
|
}
|
|
else {
|
|
HDputs("\nTesting without shared src messages:");
|
|
fcpl_src = H5P_DEFAULT;
|
|
}
|
|
if(configuration & CONFIG_SHARE_DST) {
|
|
HDputs("Testing with shared dst messages:");
|
|
fcpl_dst = fcpl_shared;
|
|
}
|
|
else {
|
|
HDputs("Testing without shared dst messages:");
|
|
fcpl_dst = H5P_DEFAULT;
|
|
}
|
|
|
|
/* Set the FAPL for the source file's type of format */
|
|
if(configuration & CONFIG_SRC_NEW_FORMAT) {
|
|
HDputs("Testing with latest format for source file:");
|
|
src_fapl = fapl2;
|
|
|
|
/* Test with and without dense attributes */
|
|
if(configuration & CONFIG_DENSE) {
|
|
HDputs("Testing with dense attributes:");
|
|
num_attributes_g = max_compact + 1;
|
|
}
|
|
else {
|
|
HDputs("Testing without dense attributes:");
|
|
num_attributes_g = MAX(min_dense, 2) - 2;
|
|
}
|
|
} /* end if */
|
|
else {
|
|
HDputs("Testing with oldest file format for source file:");
|
|
src_fapl = fapl;
|
|
num_attributes_g = 4;
|
|
} /* end else */
|
|
|
|
/* Set the FAPL for the destination file's type of format */
|
|
if(configuration & CONFIG_DST_NEW_FORMAT) {
|
|
HDputs("Testing with latest format for destination file:");
|
|
dst_fapl = fapl2;
|
|
} /* end if */
|
|
else {
|
|
HDputs("Testing with oldest file format for destination file:");
|
|
dst_fapl = fapl;
|
|
} /* end else */
|
|
|
|
/* The tests... */
|
|
nerrors += test_copy_option(fcpl_src, fcpl_dst, src_fapl, dst_fapl,
|
|
H5O_COPY_EXPAND_REFERENCE_FLAG,
|
|
FALSE, "H5Ocopy(): expand object reference");
|
|
} /* end for */
|
|
|
|
/* Reset file address checking info */
|
|
addr_reset();
|
|
|
|
/* Verify symbol table messages are cached */
|
|
nerrors += (h5_verify_cached_stabs(FILENAME, fapl) < 0 ? 1 : 0);
|
|
|
|
/* Results */
|
|
if(nerrors) {
|
|
HDprintf("***** %d OBJECT COPY TEST%s FAILED! *****\n",
|
|
nerrors, (1 == nerrors ? "" : "S"));
|
|
HDexit(EXIT_FAILURE);
|
|
} /* end if */
|
|
|
|
HDputs ("All object copying tests passed.");
|
|
|
|
/* close property list.
|
|
* NOTE: if this property list is not closed and the test is
|
|
* run with the split or multi driver, an interesting
|
|
* problem is exposed in the property list shutdown code.
|
|
*
|
|
* Namely, since the split/multi driver copies property
|
|
* lists for internal use, there's a (high) chance that
|
|
* leaving the FAPL open and having the library's shutdown
|
|
* code close it will cause the underlying property lists
|
|
* to be cleaned up first, causing the actual property list
|
|
* close operation to fail (since it won't be able to close
|
|
* the already closed underlying property list).
|
|
*
|
|
* The could be addressed by converting the split/multi to
|
|
* use non-public API routines, or putting some way into the
|
|
* public H5I routines to indicate ordering at shutdown.
|
|
*
|
|
* For now, we just make certain to close the property list.
|
|
* (QAK - 2016/04/06)
|
|
*
|
|
*/
|
|
H5Pclose(fapl2);
|
|
|
|
h5_cleanup(FILENAME, fapl);
|
|
|
|
HDexit(EXIT_SUCCESS);
|
|
|
|
error:
|
|
HDexit(EXIT_FAILURE);
|
|
} /* main */
|
|
|