mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-03-01 16:28:09 +08:00
Added new testframe.h header to document testing framework functions and split them away from h5test.h and from test programs that don't integrate with the testframe.c testing framework Added new test setup callback to testframe.c testing framework Added parameters to AddTest() to specify size of test parameters so they can be copied for later use Enabled HDF5 error stacks in testframe.c framework by default and added some error stack suppressions to some testhdf5 tests Added new maxthreads option to testframe.c framework to allow specifying the maximum number of threads a multi-threaded test can use Moved TestExpress functionality out of testframe.c and into more general h5test.c for wider use by tests through getter and setter Updated some tests to not mix and match functionality between h5test.c/h and testframe.c/h Moved some functionality from testphdf5.h into testpar.h for parallel tests that aren't part of testphdf5 Added new parallel test library that contains common shared functionality for parallel tests (similar to h5test library)
2489 lines
89 KiB
C
2489 lines
89 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* 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. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
/*
|
|
*
|
|
* Purpose: Tests chunk query API functions
|
|
*
|
|
* Test structure:
|
|
* main()
|
|
* test_basic_query()
|
|
* test_get_chunk_info_highest_v18()
|
|
* test_get_chunk_info_v110()
|
|
* test_chunk_info_single_chunk()
|
|
* test_chunk_info_implicit()
|
|
* test_chunk_info_fixed_array()
|
|
* test_chunk_info_extensible_array()
|
|
* test_chunk_info_version2_btrees()
|
|
* test_failed_attempts()
|
|
* test_flt_msk_with_skip_compress()
|
|
*
|
|
* Helper functions:
|
|
* verify_idx_nchunks()
|
|
* verify_get_chunk_info()
|
|
* verify_get_chunk_info_by_coord()
|
|
* verify_empty_chunk_info()
|
|
* index_type_str()
|
|
*
|
|
*/
|
|
#define H5D_FRIEND
|
|
#define H5D_TESTING /* to use H5D__ functions */
|
|
#include "H5Dpkg.h"
|
|
|
|
#include "h5test.h"
|
|
#ifdef H5_HAVE_FILTER_DEFLATE
|
|
#include "zlib.h"
|
|
#endif
|
|
|
|
/* Test file names, using H5F_libver_t as indices */
|
|
static const char *FILENAME[] = {"tchunk_info_earliest",
|
|
"tchunk_info_v18",
|
|
"tchunk_info_v110",
|
|
"tchunk_info_v112",
|
|
"tchunk_info_v114",
|
|
"tchunk_info_v116",
|
|
NULL};
|
|
|
|
/* File to be used in test_failed_attempts */
|
|
#define FILTERMASK_FILE "tflt_msk"
|
|
#define BASIC_FILE "basic_query"
|
|
|
|
/* Parameters for testing chunk querying */
|
|
#define SIMPLE_CHUNKED_DSET_NAME "Chunked Dataset"
|
|
#define CONTIGUOUS_DSET_NAME "Contiguous Dataset"
|
|
#define EMPTY_DSET_NAME "Empty Dataset"
|
|
#define EMPTY_EARLY_ALLOC_DSET_NAME "Empty Dataset with ALLOC_TIME_EARLY"
|
|
#define SINGLE_CHUNK_DSET_NAME "Single Chunk Index Dataset"
|
|
#define IMPLICIT_INDEX_DSET_NAME "Implicit Index Dataset"
|
|
#define FIXED_ARR_INDEX_DSET_NAME "Fixed Array Index Dataset"
|
|
#define EXT_ARR_INDEX_DSET_NAME "Extensible Array Index Dataset"
|
|
#define V2_BTREE_INDEX_DSET_NAME "Version 2 B-Tree Index Dataset"
|
|
#define SKIP_FILTER_DSET_NAME "Dataset with Skipping One Filter"
|
|
#define FILENAME_BUF_SIZE 256 /* Size for file names */
|
|
#define RANK 2 /* Rank for datasets */
|
|
|
|
/* Dimension of the dataset */
|
|
#define NX 24
|
|
#define NY 16
|
|
|
|
/* Dimension of the chunk */
|
|
#define CHUNK_NX 6
|
|
#define CHUNK_NY 4
|
|
|
|
/* X/Y coords of first chunk written */
|
|
#define START_CHK_X 0
|
|
#define START_CHK_Y 2
|
|
|
|
/* X/Y coord of last chunk written */
|
|
#define END_CHK_X 2
|
|
#define END_CHK_Y 4
|
|
|
|
/* X and Y coords of an empty chunk */
|
|
#define EMPTY_CHK_X 0
|
|
#define EMPTY_CHK_Y 0
|
|
|
|
/* Size of a chunk when the entire dataset is a one single chunk */
|
|
#define SINGLE_CHK_SIZE (NX * NY * sizeof(int))
|
|
|
|
/* Size of a chunk */
|
|
#define CHK_SIZE (CHUNK_NX * CHUNK_NY * sizeof(int))
|
|
|
|
/* Size of an empty chunk */
|
|
#define EMPTY_CHK_SIZE 0
|
|
|
|
/* Number of maximum chunks without extending */
|
|
#define NUM_CHUNKS ((NX / CHUNK_NX) * (NY / CHUNK_NY))
|
|
|
|
/* Number of chunks that have been written */
|
|
#define NUM_CHUNKS_WRITTEN 4
|
|
#define ONE_CHUNK_WRITTEN 1
|
|
#define TWO_CHUNKS_WRITTEN 2
|
|
#define NO_CHUNK_WRITTEN 0
|
|
|
|
/* For testing invalid arguments */
|
|
#define NONEXIST_CHK_INDEX 3
|
|
#define OUTOFRANGE_CHK_INDEX 5
|
|
#define INVALID_CHK_INDEX 5
|
|
|
|
/* For compressed data */
|
|
#define DEFLATE_SIZE_ADJUST(s) (ceil(((double)(s)) * 1.001) + 12.0)
|
|
|
|
/* Utility function to initialize arguments */
|
|
void reinit_vars(unsigned *read_flt_msk, haddr_t *addr, hsize_t *size);
|
|
|
|
/* Helper function containing common code that verifies indexing type
|
|
* and number of chunks
|
|
*/
|
|
static herr_t verify_idx_nchunks(hid_t dset, hid_t dspace, H5D_chunk_index_t exp_idx_type,
|
|
hsize_t exp_num_chunks);
|
|
static herr_t verify_get_chunk_info(hid_t dset, hid_t dspace, hsize_t chk_index, hsize_t exp_chk_size,
|
|
const hsize_t *exp_offset, unsigned exp_flt_msk);
|
|
static herr_t verify_get_chunk_info_by_coord(hid_t dset, hsize_t *offset, hsize_t exp_chk_size,
|
|
unsigned exp_flt_msk);
|
|
static herr_t verify_empty_chunk_info(hid_t dset, hsize_t *offset);
|
|
static const char *index_type_str(H5D_chunk_index_t idx_type);
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: reinit_vars (helper function)
|
|
*
|
|
* Purpose: Wipes out variables for the next use, used in various tests.
|
|
*
|
|
* Return: void
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
reinit_vars(unsigned *read_flt_msk, haddr_t *addr, hsize_t *size)
|
|
{
|
|
if (read_flt_msk)
|
|
*read_flt_msk = 0;
|
|
if (addr)
|
|
*addr = 0;
|
|
if (size)
|
|
*size = 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: verify_get_chunk_info (helper function)
|
|
*
|
|
* Purpose: Verifies that H5Dget_chunk_info returns correct
|
|
* values for a chunk.
|
|
*
|
|
* Return: SUCCEED/FAIL
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
verify_get_chunk_info(hid_t dset, hid_t dspace, hsize_t chk_index, hsize_t exp_chk_size,
|
|
const hsize_t *exp_offset, unsigned exp_flt_msk)
|
|
{
|
|
uint32_t read_flt_msk = 0; /* Read filter mask */
|
|
hsize_t out_offset[2] = {0, 0}; /* Buffer to get offset coordinates */
|
|
hsize_t size = 0; /* Size of an allocated/written chunk */
|
|
haddr_t addr = 0; /* Address of an allocated/written chunk */
|
|
|
|
if (H5Dget_chunk_info(dset, dspace, chk_index, out_offset, &read_flt_msk, &addr, &size) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (HADDR_UNDEF == addr)
|
|
FAIL_PUTS_ERROR("address cannot be HADDR_UNDEF");
|
|
if (size != exp_chk_size)
|
|
FAIL_PUTS_ERROR("unexpected chunk size");
|
|
if (read_flt_msk != exp_flt_msk)
|
|
FAIL_PUTS_ERROR("unexpected filter mask");
|
|
if (out_offset[0] != exp_offset[0])
|
|
FAIL_PUTS_ERROR("unexpected offset[0]");
|
|
if (out_offset[1] != exp_offset[1])
|
|
FAIL_PUTS_ERROR("unexpected offset[1]");
|
|
|
|
return SUCCEED;
|
|
|
|
error:
|
|
return FAIL;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: verify_get_chunk_info_by_coord (helper function)
|
|
*
|
|
* Purpose: Verifies that H5Dget_chunk_info_by_coord returns correct
|
|
* values for a chunk.
|
|
*
|
|
* Return: SUCCEED/FAIL
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
verify_get_chunk_info_by_coord(hid_t dset, hsize_t *offset, hsize_t exp_chk_size, unsigned exp_flt_msk)
|
|
{
|
|
uint32_t read_flt_msk = 0; /* Read filter mask */
|
|
hsize_t size = 0; /* Size of an allocated/written chunk */
|
|
haddr_t addr = 0; /* Address of an allocated/written chunk */
|
|
|
|
/* Get info of the chunk at logical coordinates specified by offset */
|
|
if (H5Dget_chunk_info_by_coord(dset, offset, &read_flt_msk, &addr, &size) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (HADDR_UNDEF == addr)
|
|
FAIL_PUTS_ERROR("address cannot be HADDR_UNDEF");
|
|
if (size != exp_chk_size)
|
|
FAIL_PUTS_ERROR("unexpected chunk size");
|
|
if (read_flt_msk != exp_flt_msk)
|
|
FAIL_PUTS_ERROR("unexpected filter mask");
|
|
|
|
return SUCCEED;
|
|
|
|
error:
|
|
return FAIL;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: verify_empty_chunk_info (helper function)
|
|
*
|
|
* Purpose: Verifies that H5Dget_chunk_info_by_coord returns correct
|
|
* values for an empty chunk.
|
|
*
|
|
* Return: SUCCEED/FAIL
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
verify_empty_chunk_info(hid_t dset, hsize_t *offset)
|
|
{
|
|
uint32_t read_flt_msk = 0; /* Read filter mask */
|
|
hsize_t size = 0; /* Size of an allocated/written chunk */
|
|
haddr_t addr = 0; /* Address of an allocated/written chunk */
|
|
|
|
/* Get info of the chunk at logical coordinates specified by offset */
|
|
if (H5Dget_chunk_info_by_coord(dset, offset, &read_flt_msk, &addr, &size) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (HADDR_UNDEF != addr)
|
|
FAIL_PUTS_ERROR("address was not HADDR_UNDEF");
|
|
if (EMPTY_CHK_SIZE != size)
|
|
FAIL_PUTS_ERROR("size was not EMPTY_CHK_SIZE");
|
|
|
|
return SUCCEED;
|
|
|
|
error:
|
|
return FAIL;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: index_type_str (helper function)
|
|
*
|
|
* Purpose: Returns the string containing the text associated with the
|
|
* given indexing scheme. For use in error messages.
|
|
*
|
|
* Return: Success: a valid indexing scheme string
|
|
* Failure: a note indicating the indexing type is invalid
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static const char *
|
|
index_type_str(H5D_chunk_index_t idx_type)
|
|
{
|
|
switch (idx_type) {
|
|
case H5D_CHUNK_IDX_SINGLE:
|
|
return ("Single Chunk index type");
|
|
case H5D_CHUNK_IDX_NONE:
|
|
return ("Implicit index type");
|
|
case H5D_CHUNK_IDX_FARRAY:
|
|
return ("Fixed Array index type");
|
|
case H5D_CHUNK_IDX_EARRAY:
|
|
return ("Extensible Array index type");
|
|
case H5D_CHUNK_IDX_BT2:
|
|
return ("Version 2 B-tree index type");
|
|
case H5D_CHUNK_IDX_BTREE:
|
|
return ("Version 1 B-tree index type (default)");
|
|
case H5D_CHUNK_IDX_NTYPES:
|
|
default:
|
|
return "invalid index type";
|
|
}
|
|
} /* index_type_str */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: verify_selected_chunks (helper function)
|
|
*
|
|
* Purpose: Reads the chunks within the boundary {start,end} and verify
|
|
* the values against the populated data.
|
|
*
|
|
* Return: SUCCEED/FAIL
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
verify_selected_chunks(hid_t dset, hid_t plist, const hsize_t *start, const hsize_t *end)
|
|
{
|
|
int read_buf[CHUNK_NX][CHUNK_NY];
|
|
int expected_buf[NUM_CHUNKS][CHUNK_NX][CHUNK_NY]; /* Expected data */
|
|
uint32_t read_flt_msk = 0; /* Filter mask read back */
|
|
hsize_t offset[2] = {0, 0}; /* Offset coordinates of a chunk */
|
|
hsize_t chk_index; /* Chunk index */
|
|
hsize_t ii, jj; /* Array indices */
|
|
int n;
|
|
|
|
memset(&read_buf, 0, sizeof(read_buf));
|
|
|
|
/* Initialize the array of chunk data for all NUM_CHUNKS chunks, this is
|
|
* the same as the written data and will be used to verify the read data
|
|
*/
|
|
for (n = 0; n < NUM_CHUNKS; n++)
|
|
for (ii = 0; ii < CHUNK_NX; ii++)
|
|
for (jj = 0; jj < CHUNK_NY; jj++)
|
|
expected_buf[n][ii][jj] = (int)(ii * jj) + 1;
|
|
|
|
/* Read each chunk within the boundary of {start,end} and verify the
|
|
* values against the expected data
|
|
*/
|
|
chk_index = 0;
|
|
for (ii = start[0]; ii < end[0]; ii++)
|
|
for (jj = start[1]; jj < end[1]; jj++, chk_index++) {
|
|
offset[0] = ii * CHUNK_NX;
|
|
offset[1] = jj * CHUNK_NY;
|
|
|
|
/* Read the current chunk */
|
|
if (H5Dread_chunk(dset, plist, offset, &read_flt_msk, read_buf) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Verify that read chunk is the same as the corresponding written one */
|
|
if (memcmp(expected_buf[chk_index], read_buf, CHUNK_NX * CHUNK_NY) != 0) {
|
|
fprintf(stderr,
|
|
"Read chunk differs from written chunk at offset (%" PRIuHSIZE ",%" PRIuHSIZE ")\n",
|
|
offset[0], offset[1]);
|
|
return FAIL;
|
|
}
|
|
}
|
|
|
|
return SUCCEED;
|
|
|
|
error:
|
|
return FAIL;
|
|
} /* verify_selected_chunks */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: write_selected_chunks (helper function)
|
|
*
|
|
* Purpose: Verifies that chunk indexing scheme and number of chunks of
|
|
* the dataset matches the expected values, then write data to
|
|
* a subset of chunks. This function opens the dataset then
|
|
* closes it after writing.
|
|
*
|
|
* Return: SUCCEED/FAIL
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
write_selected_chunks(hid_t dset, hid_t plist, const hsize_t *start, const hsize_t *end, unsigned flt_msk)
|
|
{
|
|
int direct_buf[NUM_CHUNKS][CHUNK_NX][CHUNK_NY]; /* Data in chunks */
|
|
hsize_t offset[2]; /* Offset coordinates of a chunk */
|
|
hsize_t chk_index; /* Chunk index */
|
|
hsize_t ii, jj; /* Array indices */
|
|
int n;
|
|
|
|
/* Initialize the array of chunk data for all NUM_CHUNKS chunks */
|
|
for (n = 0; n < NUM_CHUNKS; n++)
|
|
for (ii = 0; ii < CHUNK_NX; ii++)
|
|
for (jj = 0; jj < CHUNK_NY; jj++)
|
|
direct_buf[n][ii][jj] = (int)(ii * jj) + 1;
|
|
|
|
/* Write NUM_CHUNKS_WRITTEN chunks at the following logical coords:
|
|
* (0,2) (0,3) (1,2) (1,3)
|
|
*/
|
|
chk_index = 0;
|
|
for (ii = start[0]; ii < end[0]; ii++)
|
|
for (jj = start[1]; jj < end[1]; jj++, chk_index++) {
|
|
offset[0] = ii * CHUNK_NX;
|
|
offset[1] = jj * CHUNK_NY;
|
|
if (H5Dwrite_chunk(dset, plist, flt_msk, offset, CHK_SIZE, (void *)direct_buf[chk_index]) < 0)
|
|
TEST_ERROR;
|
|
}
|
|
|
|
return SUCCEED;
|
|
|
|
error:
|
|
return FAIL;
|
|
} /* write_selected_chunks */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: verify_idx_nchunks (helper function)
|
|
*
|
|
* Purpose: Verifies that chunk indexing scheme and number of chunks of
|
|
* the dataset match the expected values.
|
|
*
|
|
* Return: SUCCEED/FAIL
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
verify_idx_nchunks(hid_t dset, hid_t dspace, H5D_chunk_index_t exp_idx_type, hsize_t exp_num_chunks)
|
|
{
|
|
H5D_chunk_index_t idx_type; /* Dataset chunk index type */
|
|
hsize_t nchunks = 0; /* Number of chunks */
|
|
|
|
/* Get the chunk indexing type of the dataset */
|
|
if (H5Dget_chunk_index_type(dset, &idx_type) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Ensure the correct chunk indexing scheme is used */
|
|
if (idx_type != exp_idx_type) {
|
|
char msg[256];
|
|
snprintf(msg, sizeof(msg), "Should be using %s.\n", index_type_str(idx_type));
|
|
FAIL_PUTS_ERROR(msg);
|
|
}
|
|
|
|
/* Get and verify the number of chunks */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (nchunks != exp_num_chunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
/* Get and verify the number of chunks again, passing in H5S_ALL */
|
|
if (H5Dget_num_chunks(dset, H5S_ALL, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (nchunks != exp_num_chunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
return SUCCEED;
|
|
|
|
error:
|
|
return FAIL;
|
|
} /* verify_idx_nchunks */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_get_chunk_info_highest_v18
|
|
*
|
|
* Purpose: Test getting various chunk information
|
|
*
|
|
* Return: # of errors
|
|
*
|
|
* Note: Note that the dataspace argument in these new functions is
|
|
* currently not used. The functionality involved the dataspace
|
|
* will be implemented in the next version.
|
|
*
|
|
* Description:
|
|
* This function tests the new API functions added for EED-343:
|
|
* H5Dget_num_chunks, H5Dget_chunk_info, and
|
|
* H5Dget_chunk_info_by_coord for high bound up to 1.8.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_get_chunk_info_highest_v18(hid_t fapl)
|
|
{
|
|
char filename[FILENAME_BUF_SIZE]; /* File name */
|
|
hid_t chunkfile = H5I_INVALID_HID; /* File ID */
|
|
hid_t dspace = H5I_INVALID_HID; /* Dataspace ID */
|
|
hid_t dset = H5I_INVALID_HID; /* Dataset ID */
|
|
hid_t cparms = H5I_INVALID_HID; /* Creation plist */
|
|
hsize_t chunk_dims[2] = {CHUNK_NX, CHUNK_NY}; /* Chunk dimensions */
|
|
int direct_buf[CHUNK_NX][CHUNK_NY]; /* Data chunk */
|
|
hsize_t maxdims[2] = {H5S_UNLIMITED, H5S_UNLIMITED}; /* 2 unlimited dims */
|
|
hsize_t out_offset[2]; /* Buffer to get offset coordinates */
|
|
hsize_t size = 0; /* Size of an allocated/written chunk */
|
|
hsize_t nchunks = 0; /* Number of chunks */
|
|
haddr_t addr = 0; /* Address of an allocated/written chunk */
|
|
hsize_t chk_index = 0; /* Index of a chunk */
|
|
hsize_t dims[2] = {NX, NY}; /* Dataset dimensions */
|
|
uint32_t flt_msk = 0; /* Filter mask */
|
|
uint32_t read_flt_msk = 0; /* Filter mask after direct read */
|
|
int fillvalue = -1; /* Fill value */
|
|
hsize_t offset[2] = {0, 0}; /* Offset coordinates of a chunk */
|
|
#ifdef H5_HAVE_FILTER_DEFLATE
|
|
int aggression = 9; /* Compression aggression setting */
|
|
const Bytef *z_src = (const Bytef *)(direct_buf);
|
|
Bytef *z_dst; /* Destination buffer */
|
|
uLongf z_dst_nbytes = (uLongf)DEFLATE_SIZE_ADJUST(CHK_SIZE);
|
|
uLong z_src_nbytes = (uLong)CHK_SIZE;
|
|
#endif
|
|
void *inbuf = NULL; /* Pointer to new buffer */
|
|
hsize_t chunk_size = CHK_SIZE; /* Size of a chunk, can be compressed or not */
|
|
hsize_t ii, jj; /* Array indices */
|
|
int n; /* Used as chunk index, but int to avoid conversion warning */
|
|
herr_t ret; /* Temporary returned value for verifying failure */
|
|
|
|
TESTING("getting chunk information in file with version prior to 1.10");
|
|
|
|
/* Create the file */
|
|
h5_fixname(FILENAME[H5F_LIBVER_V18], fapl, filename, sizeof filename);
|
|
|
|
/* Set version bounds for creating the file. High bound to V18 to test
|
|
* chunked dataset that use B-tree v1 structures to index chunks.
|
|
*/
|
|
if (H5Pset_libver_bounds(fapl, H5F_LIBVER_EARLIEST, H5F_LIBVER_V18) < 0)
|
|
TEST_ERROR;
|
|
|
|
chunkfile = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
|
|
if (chunkfile < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create the file and memory dataspace */
|
|
if ((dspace = H5Screate_simple(RANK, dims, maxdims)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Set dset creation properties with chunking, compression, and fillvalue */
|
|
if ((cparms = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
|
TEST_ERROR;
|
|
if (H5Pset_chunk(cparms, RANK, chunk_dims) < 0)
|
|
TEST_ERROR;
|
|
|
|
#ifdef H5_HAVE_FILTER_DEFLATE
|
|
if (H5Pset_deflate(cparms, (unsigned)aggression) < 0)
|
|
TEST_ERROR;
|
|
#endif /* end H5_HAVE_FILTER_DEFLATE */
|
|
|
|
/* Set fill value */
|
|
if (H5Pset_fill_value(cparms, H5T_NATIVE_INT, &fillvalue) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create a new dataset using cparms creation properties */
|
|
dset = H5Dcreate2(chunkfile, SIMPLE_CHUNKED_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, cparms,
|
|
H5P_DEFAULT);
|
|
if (dset < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Initialize a chunk of data */
|
|
for (ii = 0; ii < CHUNK_NX; ii++)
|
|
for (jj = 0; jj < CHUNK_NY; jj++)
|
|
direct_buf[ii][jj] = (int)(ii * jj) + 1;
|
|
|
|
#ifdef H5_HAVE_FILTER_DEFLATE
|
|
/* Allocate input (compressed) buffer */
|
|
inbuf = calloc(1, z_dst_nbytes);
|
|
|
|
/* zlib-friendly alias for the input buffer */
|
|
z_dst = (Bytef *)inbuf;
|
|
|
|
/* Perform compression from the source to the destination buffer */
|
|
ret = compress2(z_dst, &z_dst_nbytes, z_src, z_src_nbytes, aggression);
|
|
|
|
/* Set the chunk size to the compressed chunk size */
|
|
chunk_size = (hsize_t)z_dst_nbytes;
|
|
|
|
/* Check for various zlib errors */
|
|
if (Z_BUF_ERROR == ret) {
|
|
fprintf(stderr, "overflow");
|
|
TEST_ERROR;
|
|
}
|
|
else if (Z_MEM_ERROR == ret) {
|
|
fprintf(stderr, "deflate memory error");
|
|
TEST_ERROR;
|
|
}
|
|
else if (Z_OK != ret) {
|
|
fprintf(stderr, "other deflate error");
|
|
TEST_ERROR;
|
|
}
|
|
#else
|
|
/* Allocate input (non-compressed) buffer */
|
|
if (NULL == (inbuf = calloc(1, CHK_SIZE)))
|
|
TEST_ERROR;
|
|
memcpy(inbuf, direct_buf, CHK_SIZE);
|
|
#endif /* end H5_HAVE_FILTER_DEFLATE */
|
|
|
|
/* Write only NUM_CHUNKS_WRITTEN chunks at the following logical coords:
|
|
* (0,2) (0,3) (1,2) (1,3)
|
|
*/
|
|
n = 0;
|
|
for (ii = START_CHK_X; ii < END_CHK_X; ii++)
|
|
for (jj = START_CHK_Y; jj < END_CHK_Y; jj++, n++) {
|
|
offset[0] = ii * CHUNK_NX;
|
|
offset[1] = jj * CHUNK_NY;
|
|
ret = H5Dwrite_chunk(dset, H5P_DEFAULT, flt_msk, offset, chunk_size, (void *)inbuf);
|
|
if (ret < 0)
|
|
TEST_ERROR;
|
|
}
|
|
|
|
/* Free the input buffer */
|
|
if (inbuf)
|
|
free(inbuf);
|
|
|
|
if (H5Fflush(dset, H5F_SCOPE_LOCAL) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close the dataset */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* ...open it again to test the chunk query functions */
|
|
if ((dset = H5Dopen2(chunkfile, SIMPLE_CHUNKED_DSET_NAME, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Get and verify the number of chunks written */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (NUM_CHUNKS_WRITTEN != nchunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
/* Get and verify info of the last written chunk again, passing in H5S_ALL
|
|
* this time
|
|
*/
|
|
offset[0] = 6;
|
|
offset[1] = 12;
|
|
if (verify_get_chunk_info(dset, H5S_ALL, NUM_CHUNKS_WRITTEN - 1, chunk_size, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info failed\n");
|
|
|
|
/* Attempt to get info of a non-existing chunk, should fail */
|
|
chk_index = OUTOFRANGE_CHK_INDEX;
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dget_chunk_info(dset, H5S_ALL, chk_index, out_offset, &read_flt_msk, &addr, &size);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret != FAIL)
|
|
FAIL_PUTS_ERROR(" Attempt to get info of a non-existing chunk.");
|
|
|
|
/* Attempt to get info of empty chunks, verify the returned addr and size */
|
|
offset[0] = 0;
|
|
offset[1] = 0;
|
|
if (verify_empty_chunk_info(dset, offset) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on empty chunk failed\n");
|
|
|
|
offset[0] = 3 * CHUNK_NX;
|
|
offset[1] = 3 * CHUNK_NY;
|
|
if (verify_empty_chunk_info(dset, offset) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on empty chunk failed\n");
|
|
|
|
/* Go through all written chunks, get their info and verify the values */
|
|
chk_index = 0;
|
|
for (ii = START_CHK_X; ii < END_CHK_X; ii++)
|
|
for (jj = START_CHK_Y; jj < END_CHK_Y; jj++, chk_index++) {
|
|
offset[0] = ii * CHUNK_NX;
|
|
offset[1] = jj * CHUNK_NY;
|
|
|
|
if (verify_get_chunk_info(dset, dspace, chk_index, chunk_size, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info failed\n");
|
|
|
|
/* Use the same offset to pass into the next ...by_coord function */
|
|
if (verify_get_chunk_info_by_coord(dset, offset, chunk_size, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord failed\n");
|
|
}
|
|
|
|
/* Close the first dataset */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create an empty dataset and close it */
|
|
dset = H5Dcreate2(chunkfile, EMPTY_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, cparms, H5P_DEFAULT);
|
|
if (dset < 0)
|
|
TEST_ERROR;
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Reopen the empty dataset to verify the chunk query functions on it */
|
|
if ((dset = H5Dopen2(chunkfile, EMPTY_DSET_NAME, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Verify that the number of chunks is 0 */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (NO_CHUNK_WRITTEN != nchunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
/* Attempt to get info of a chunk from an empty dataset, should fail */
|
|
chk_index = OUTOFRANGE_CHK_INDEX;
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dget_chunk_info(dset, dspace, chk_index, out_offset, &read_flt_msk, &addr, &size);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret != FAIL)
|
|
FAIL_PUTS_ERROR(" Attempt to get info of a non-existing chunk.");
|
|
|
|
/* Attempt to get info of a chunk given its coords from an empty dataset,
|
|
* should succeed with the returned address as HADDR_UNDEF and size as 0
|
|
*/
|
|
offset[0] = EMPTY_CHK_X;
|
|
offset[1] = EMPTY_CHK_Y;
|
|
if (verify_empty_chunk_info(dset, offset) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on empty chunk failed\n");
|
|
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/************************************************************************
|
|
* Test empty dataset with H5D_ALLOC_TIME_EARLY *
|
|
************************************************************************/
|
|
|
|
/* Set space allocation to early so that chunk query functions will
|
|
* retrieve chunk information even though the dataset is empty
|
|
*/
|
|
if (H5Pset_alloc_time(cparms, H5D_ALLOC_TIME_EARLY) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create an empty dataset and close it */
|
|
dset = H5Dcreate2(chunkfile, EMPTY_EARLY_ALLOC_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, cparms,
|
|
H5P_DEFAULT);
|
|
if (dset < 0)
|
|
TEST_ERROR;
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Reopen the empty dataset to verify the chunk query functions on it */
|
|
if ((dset = H5Dopen2(chunkfile, EMPTY_EARLY_ALLOC_DSET_NAME, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Verify that the number of chunks is NUM_CHUNKS */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (nchunks != NUM_CHUNKS)
|
|
TEST_ERROR;
|
|
|
|
/* Attempt to get info of a chunk from an empty dataset, verify the
|
|
* returned address and size in the case of H5D_ALLOC_TIME_EARLY
|
|
*/
|
|
chk_index = NONEXIST_CHK_INDEX;
|
|
reinit_vars(&read_flt_msk, &addr, &size);
|
|
ret = H5Dget_chunk_info(dset, dspace, chk_index, out_offset, &read_flt_msk, &addr, &size);
|
|
if (ret < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Because of H5D_ALLOC_TIME_EARLY, addr cannot be HADDR_UNDEF and size not 0 */
|
|
if (addr == HADDR_UNDEF)
|
|
TEST_ERROR;
|
|
if (size == EMPTY_CHK_SIZE)
|
|
TEST_ERROR;
|
|
|
|
chk_index = 10;
|
|
reinit_vars(&read_flt_msk, &addr, &size);
|
|
ret = H5Dget_chunk_info(dset, dspace, chk_index, out_offset, &read_flt_msk, &addr, &size);
|
|
if (ret < 0)
|
|
TEST_ERROR;
|
|
/* Because of H5D_ALLOC_TIME_EARLY, addr cannot be HADDR_UNDEF and size not 0 */
|
|
if (addr == HADDR_UNDEF)
|
|
TEST_ERROR;
|
|
if (size == EMPTY_CHK_SIZE)
|
|
TEST_ERROR;
|
|
|
|
/* Attempt to get info of a chunk given its coords from an empty dataset,
|
|
* verify the returned address and size
|
|
*/
|
|
offset[0] = 0;
|
|
offset[1] = 0;
|
|
if (H5Dget_chunk_info_by_coord(dset, offset, &read_flt_msk, &addr, &size) < 0)
|
|
TEST_ERROR;
|
|
/* Because of H5D_ALLOC_TIME_EARLY, addr cannot be HADDR_UNDEF and size not 0 */
|
|
if (addr == HADDR_UNDEF)
|
|
TEST_ERROR;
|
|
if (size == 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close/release resources. */
|
|
if (H5Sclose(dspace) < 0)
|
|
TEST_ERROR;
|
|
if (H5Pclose(cparms) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(chunkfile) < 0)
|
|
TEST_ERROR;
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Dclose(dset);
|
|
H5Sclose(dspace);
|
|
H5Pclose(cparms);
|
|
H5Fclose(chunkfile);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
return 1;
|
|
} /* test_get_chunk_info_highest_v18() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_chunk_info_single_chunk
|
|
*
|
|
* Purpose: Test getting various chunk information when Single Chunk
|
|
* index type is used
|
|
*
|
|
* Return: # of errors
|
|
*
|
|
* Note: Note that the dataspace argument in these new functions are
|
|
* currently not used. The functionality involved the dataspace
|
|
* will be implemented in the next version.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_chunk_info_single_chunk(const char *filename, hid_t fapl)
|
|
{
|
|
hid_t chunkfile = H5I_INVALID_HID; /* File ID */
|
|
hid_t dspace = H5I_INVALID_HID; /* Dataspace ID */
|
|
hid_t dset = H5I_INVALID_HID; /* Dataset ID */
|
|
hid_t cparms = H5I_INVALID_HID; /* Creation plist */
|
|
hsize_t dims[2] = {NX, NY}; /* Dataset dimensions */
|
|
hsize_t chunk_dims[2] = {NX, NY}; /* Chunk dimensions */
|
|
int data_buf[NX][NY]; /* Input buffer */
|
|
H5D_chunk_index_t idx_type; /* Dataset chunk index type */
|
|
uint32_t flt_msk = 0; /* Filter mask */
|
|
uint32_t read_flt_msk = 0; /* Filter mask after direct read */
|
|
hsize_t offset[2]; /* Offset coordinates of a chunk */
|
|
hsize_t out_offset[2] = {0, 0}; /* Buffer to get offset coordinates */
|
|
hsize_t size = 0; /* Size of an allocated/written chunk */
|
|
hsize_t nchunks = 0; /* Number of chunks */
|
|
haddr_t addr = 0; /* Address of an allocated/written chunk */
|
|
hsize_t chk_index = 0; /* Index of a chunk */
|
|
hsize_t ii, jj; /* Array indices */
|
|
herr_t ret; /* Temporary returned value for verifying failure */
|
|
|
|
TESTING(" Single Chunk index");
|
|
|
|
/* Open the file for reading/writing */
|
|
if ((chunkfile = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create dataspace */
|
|
if ((dspace = H5Screate_simple(RANK, dims, NULL)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Enable chunking */
|
|
if ((cparms = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Pset_chunk(cparms, RANK, chunk_dims) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create a new dataset using cparms creation properties */
|
|
dset = H5Dcreate2(chunkfile, SINGLE_CHUNK_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, cparms,
|
|
H5P_DEFAULT);
|
|
if (dset < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close the dataset */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* ...open it again to test the chunk query functions on a single empty chunk */
|
|
if ((dset = H5Dopen2(chunkfile, SINGLE_CHUNK_DSET_NAME, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Ensure the correct chunk indexing scheme is used */
|
|
if (H5Dget_chunk_index_type(dset, &idx_type) < 0)
|
|
TEST_ERROR;
|
|
if (idx_type != H5D_CHUNK_IDX_SINGLE)
|
|
FAIL_PUTS_ERROR("Should be using Single Chunk index type");
|
|
|
|
/* Get the number of chunks and verify that no chunk has been written */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (nchunks != NO_CHUNK_WRITTEN)
|
|
TEST_ERROR;
|
|
|
|
/* Initialize the array of chunk data for the single chunk */
|
|
for (ii = 0; ii < NX; ii++)
|
|
for (jj = 0; jj < NY; jj++)
|
|
data_buf[ii][jj] = (int)(ii * jj);
|
|
|
|
/* Write the chunk */
|
|
if (H5Dwrite(dset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data_buf) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Get and verify that one chunk had been written */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (nchunks != ONE_CHUNK_WRITTEN)
|
|
TEST_ERROR;
|
|
|
|
/* Offset of the only chunk */
|
|
offset[0] = 0;
|
|
offset[1] = 0;
|
|
|
|
/* Get and verify info of the first and only chunk */
|
|
if (verify_get_chunk_info(dset, H5S_ALL, 0, SINGLE_CHK_SIZE, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification H5Dget_chunk_info failed\n");
|
|
|
|
/* Get and verify info of the chunk at logical coordinates (0,0) */
|
|
if (verify_get_chunk_info_by_coord(dset, offset, SINGLE_CHK_SIZE, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord failed\n");
|
|
|
|
/* Attempt to get chunk info given an invalid chunk index and verify
|
|
* that failure occurs
|
|
*/
|
|
chk_index = INVALID_CHK_INDEX;
|
|
reinit_vars(&read_flt_msk, &addr, &size);
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dget_chunk_info(dset, dspace, chk_index, out_offset, &read_flt_msk, &addr, &size);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret != FAIL)
|
|
TEST_ERROR;
|
|
|
|
/* Release resource */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(dspace) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(chunkfile) < 0)
|
|
TEST_ERROR;
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Dclose(dset);
|
|
H5Sclose(dspace);
|
|
H5Pclose(cparms);
|
|
H5Fclose(chunkfile);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
return 1;
|
|
} /* test_chunk_info_single_chunk() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_chunk_info_implicit
|
|
*
|
|
* Purpose: Test getting various chunk information when Implicit
|
|
* index type is used
|
|
*
|
|
* Return: # of errors
|
|
*
|
|
* Note: Note that the dataspace argument in these new functions are
|
|
* currently not used. The functionality involved the dataspace
|
|
* will be implemented in the next version.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_chunk_info_implicit(char *filename, hid_t fapl)
|
|
{
|
|
hid_t chunkfile = H5I_INVALID_HID; /* File ID */
|
|
hid_t dspace = H5I_INVALID_HID; /* Dataspace ID */
|
|
hid_t dset = H5I_INVALID_HID; /* Dataset ID */
|
|
hid_t cparms = H5I_INVALID_HID; /* Creation plist */
|
|
hsize_t dims[2] = {NX, NY}; /* Dataset dimensions */
|
|
hsize_t chunk_dims[2] = {CHUNK_NX, CHUNK_NY}; /* Chunk dimensions */
|
|
uint32_t flt_msk = 0; /* Filter mask */
|
|
hsize_t chk_index = 0; /* Index of a chunk */
|
|
hsize_t ii, jj; /* Array indices */
|
|
hsize_t start[2] = {START_CHK_X, START_CHK_Y}; /* Start position */
|
|
hsize_t end[2] = {END_CHK_X, END_CHK_Y}; /* End position */
|
|
|
|
TESTING(" Implicit index");
|
|
|
|
/* Open the file for reading/writing */
|
|
if ((chunkfile = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create dataspace */
|
|
if ((dspace = H5Screate_simple(RANK, dims, NULL)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Enable chunking */
|
|
if ((cparms = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Pset_chunk(cparms, RANK, chunk_dims) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Set allocation time to early */
|
|
if (H5Pset_alloc_time(cparms, H5D_ALLOC_TIME_EARLY) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create a new dataset using cparms creation properties */
|
|
dset = H5Dcreate2(chunkfile, IMPLICIT_INDEX_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, cparms,
|
|
H5P_DEFAULT);
|
|
if (dset < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close the dataset */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Open the dataset again to test getting chunk info */
|
|
if ((dset = H5Dopen2(chunkfile, IMPLICIT_INDEX_DSET_NAME, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Verify chunk indexing scheme and number of chunks */
|
|
if (verify_idx_nchunks(dset, dspace, H5D_CHUNK_IDX_NONE, NUM_CHUNKS) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification and write failed\n");
|
|
|
|
/* Write NUM_CHUNKS_WRITTEN chunks at the following logical coords:
|
|
* (0,2) (0,3) (1,2) (1,3)
|
|
*/
|
|
if (write_selected_chunks(dset, H5P_DEFAULT, start, end, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Writing to selected chunks failed\n");
|
|
|
|
/* Go through all chunks, and get their info and verify the values */
|
|
chk_index = 0;
|
|
for (ii = 0; ii < NX / CHUNK_NX; ii++)
|
|
for (jj = 0; jj < NY / CHUNK_NY; jj++, chk_index++) {
|
|
hsize_t offset[2] = {ii * CHUNK_NX, jj * CHUNK_NY};
|
|
|
|
if (verify_get_chunk_info(dset, H5S_ALL, chk_index, CHK_SIZE, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info failed\n");
|
|
|
|
/* Get info of a chunk and verify its information. Note that
|
|
* all chunks in this dataset are allocated because of the property
|
|
* H5D_ALLOC_TIME_EARLY
|
|
*/
|
|
if (verify_get_chunk_info_by_coord(dset, offset, CHK_SIZE, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord failed\n");
|
|
}
|
|
|
|
/* Release resource */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(dspace) < 0)
|
|
TEST_ERROR;
|
|
if (H5Pclose(cparms) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(chunkfile) < 0)
|
|
TEST_ERROR;
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Dclose(dset);
|
|
H5Sclose(dspace);
|
|
H5Pclose(cparms);
|
|
H5Fclose(chunkfile);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
return 1;
|
|
} /* test_chunk_info_implicit() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_chunk_info_fixed_array
|
|
*
|
|
* Purpose: Test getting various chunk information when Fixed Array
|
|
* index type is used
|
|
*
|
|
* Return: # of errors
|
|
*
|
|
* Note: Note that the dataspace argument in these new functions are
|
|
* currently not used. The functionality involved the dataspace
|
|
* will be implemented in the next version.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_chunk_info_fixed_array(const char *filename, hid_t fapl)
|
|
{
|
|
hid_t chunkfile = H5I_INVALID_HID; /* File ID */
|
|
hid_t dspace = H5I_INVALID_HID; /* Dataspace ID */
|
|
hid_t dset = H5I_INVALID_HID; /* Dataset ID */
|
|
hid_t cparms = H5I_INVALID_HID; /* Creation plist */
|
|
hsize_t dims[2] = {NX, NY}; /* Dataset dimensions */
|
|
hsize_t chunk_dims[2] = {CHUNK_NX, CHUNK_NY}; /* Chunk dimensions */
|
|
uint32_t flt_msk = 0; /* Filter mask */
|
|
uint32_t read_flt_msk = 0; /* Filter mask after direct read */
|
|
hsize_t offset[2]; /* Offset coordinates of a chunk */
|
|
hsize_t start[2] = {START_CHK_X, START_CHK_Y}; /* Start position */
|
|
hsize_t end[2] = {END_CHK_X, END_CHK_Y}; /* End position */
|
|
hsize_t out_offset[2] = {0, 0}; /* Buffer to get offset coordinates */
|
|
hsize_t size = 0; /* Size of an allocated/written chunk */
|
|
hsize_t nchunks = 0; /* Number of chunks */
|
|
haddr_t addr = 0; /* Address of an allocated/written chunk */
|
|
hsize_t chk_index = 0; /* Index of a chunk */
|
|
hsize_t ii, jj; /* Array indices */
|
|
herr_t ret; /* Temporary returned value for verifying failure */
|
|
|
|
TESTING(" Fixed Array index");
|
|
|
|
/* Open the file for reading/writing */
|
|
if ((chunkfile = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create dataspace */
|
|
if ((dspace = H5Screate_simple(RANK, dims, NULL)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Enable chunking */
|
|
if ((cparms = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Pset_chunk(cparms, RANK, chunk_dims) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create a new dataset using cparms creation properties */
|
|
dset = H5Dcreate2(chunkfile, FIXED_ARR_INDEX_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, cparms,
|
|
H5P_DEFAULT);
|
|
if (dset < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close the dataset */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Open the dataset again to test getting chunk info */
|
|
if ((dset = H5Dopen2(chunkfile, FIXED_ARR_INDEX_DSET_NAME, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Verify chunk indexing scheme and number of chunks */
|
|
if (verify_idx_nchunks(dset, dspace, H5D_CHUNK_IDX_FARRAY, NO_CHUNK_WRITTEN) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification and write failed\n");
|
|
|
|
/* Write NUM_CHUNKS_WRITTEN chunks at the following logical coords:
|
|
* (0,2) (0,3) (1,2) (1,3)
|
|
*/
|
|
if (write_selected_chunks(dset, H5P_DEFAULT, start, end, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Writing to selected chunks failed\n");
|
|
|
|
/* Get and verify the number of chunks written */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (NUM_CHUNKS_WRITTEN != nchunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
/* Get and verify info of each written chunk */
|
|
chk_index = 0;
|
|
for (ii = START_CHK_X; ii < END_CHK_X; ii++)
|
|
for (jj = START_CHK_Y; jj < END_CHK_Y; jj++, chk_index++) {
|
|
offset[0] = ii * CHUNK_NX;
|
|
offset[1] = jj * CHUNK_NY;
|
|
if (verify_get_chunk_info(dset, dspace, chk_index, CHK_SIZE, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info failed\n");
|
|
}
|
|
|
|
/* Attempt to get info using an out-of-range index, chk_index is now > NUM_CHUNKS_WRITTEN. should fail */
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dget_chunk_info(dset, dspace, chk_index, out_offset, &read_flt_msk, &addr, &size);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret != FAIL)
|
|
FAIL_PUTS_ERROR(" Attempted to get info of a chunk using an out-of-range index.");
|
|
|
|
/* Attempt to get info of empty chunks, verify the returned address and size */
|
|
offset[0] = 0;
|
|
offset[1] = 0;
|
|
if (verify_empty_chunk_info(dset, offset) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on empty chunk failed\n");
|
|
|
|
offset[0] = 3 * CHUNK_NX;
|
|
offset[1] = 3 * CHUNK_NY;
|
|
if (verify_empty_chunk_info(dset, offset) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on empty chunk failed\n");
|
|
|
|
/* Read and verify values of selected chunks */
|
|
if (verify_selected_chunks(dset, H5P_DEFAULT, start, end) < 0)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on selected chunks failed\n");
|
|
|
|
/* Release resource */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(dspace) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(chunkfile) < 0)
|
|
TEST_ERROR;
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Dclose(dset);
|
|
H5Sclose(dspace);
|
|
H5Pclose(cparms);
|
|
H5Fclose(chunkfile);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
return 1;
|
|
} /* test_chunk_info_fixed_array() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_chunk_info_extensible_array
|
|
*
|
|
* Purpose: Test getting various chunk information when Extensible Array
|
|
* index type is used
|
|
*
|
|
* Return: # of errors
|
|
*
|
|
* Note: Note that the dataspace argument in these new functions are
|
|
* currently not used. The functionality involved the dataspace
|
|
* will be implemented in the next version.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_chunk_info_extensible_array(const char *filename, hid_t fapl)
|
|
{
|
|
hid_t chunkfile = H5I_INVALID_HID; /* File ID */
|
|
hid_t dspace = H5I_INVALID_HID; /* Dataspace ID */
|
|
hid_t dset = H5I_INVALID_HID; /* Dataset ID */
|
|
hid_t cparms = H5I_INVALID_HID; /* Creation plist */
|
|
hsize_t dims[2] = {NX, NY}; /* Dataset dimensions */
|
|
hsize_t chunk_dims[2] = {CHUNK_NX, CHUNK_NY}; /* Chunk dimensions */
|
|
hsize_t maxdims[2] = {H5S_UNLIMITED, NY}; /* One unlimited dimension */
|
|
uint32_t flt_msk = 0; /* Filter mask */
|
|
uint32_t read_flt_msk = 0; /* Filter mask after direct read */
|
|
hsize_t offset[2]; /* Offset coordinates of a chunk */
|
|
hsize_t start[2] = {START_CHK_X, START_CHK_Y}; /* Start position */
|
|
hsize_t end[2] = {END_CHK_X, END_CHK_Y}; /* End position */
|
|
hsize_t out_offset[2] = {0, 0}; /* Buffer to get offset coordinates */
|
|
hsize_t size = 0; /* Size of an allocated/written chunk */
|
|
hsize_t nchunks = 0; /* Number of chunks */
|
|
haddr_t addr = 0; /* Address of an allocated/written chunk */
|
|
hsize_t chk_index = 0; /* Index of a chunk */
|
|
hsize_t ii, jj; /* Array indices */
|
|
herr_t ret; /* Temporary returned value for verifying failure */
|
|
|
|
TESTING(" Extensible Array index");
|
|
|
|
/* Open the file for reading/writing */
|
|
if ((chunkfile = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create dataspace */
|
|
if ((dspace = H5Screate_simple(RANK, dims, maxdims)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Enable chunking */
|
|
if ((cparms = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Pset_chunk(cparms, RANK, chunk_dims) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create a new dataset using cparms creation properties */
|
|
dset = H5Dcreate2(chunkfile, EXT_ARR_INDEX_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, cparms,
|
|
H5P_DEFAULT);
|
|
if (dset < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close the dataset */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Open the dataset again to test getting chunk info */
|
|
if ((dset = H5Dopen2(chunkfile, EXT_ARR_INDEX_DSET_NAME, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Verify chunk indexing scheme and number of chunks */
|
|
if (verify_idx_nchunks(dset, dspace, H5D_CHUNK_IDX_EARRAY, NO_CHUNK_WRITTEN) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification and write failed\n");
|
|
|
|
/* Write NUM_CHUNKS_WRITTEN chunks at the following logical coords:
|
|
* (0,2) (0,3) (1,2) (1,3)
|
|
*/
|
|
if (write_selected_chunks(dset, H5P_DEFAULT, start, end, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Writing to selected chunks failed\n");
|
|
|
|
/* Get and verify the number of chunks written */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (NUM_CHUNKS_WRITTEN != nchunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
/* Get and verify info of each written chunk */
|
|
chk_index = 0;
|
|
for (ii = START_CHK_X; ii < END_CHK_X; ii++)
|
|
for (jj = START_CHK_Y; jj < END_CHK_Y; jj++, chk_index++) {
|
|
offset[0] = ii * CHUNK_NX;
|
|
offset[1] = jj * CHUNK_NY;
|
|
|
|
if (verify_get_chunk_info(dset, dspace, chk_index, CHK_SIZE, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info failed\n");
|
|
|
|
if (verify_get_chunk_info_by_coord(dset, offset, CHK_SIZE, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord failed\n");
|
|
}
|
|
|
|
/* Attempt to get info using an out-of-range index, should fail */
|
|
chk_index = OUTOFRANGE_CHK_INDEX;
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dget_chunk_info(dset, dspace, chk_index, out_offset, &read_flt_msk, &addr, &size);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret != FAIL)
|
|
FAIL_PUTS_ERROR(" Attempted to get info of a chunk using an out-of-range index.");
|
|
|
|
/* Attempt to get info of empty chunks, verify the returned address and size */
|
|
offset[0] = 0;
|
|
offset[1] = 0;
|
|
if (verify_empty_chunk_info(dset, offset) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on empty chunk failed\n");
|
|
|
|
offset[0] = 3 * CHUNK_NX;
|
|
offset[1] = 3 * CHUNK_NY;
|
|
if (verify_empty_chunk_info(dset, offset) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on empty chunk failed\n");
|
|
|
|
/* Read and verify values of selected chunks */
|
|
if (verify_selected_chunks(dset, H5P_DEFAULT, start, end) < 0)
|
|
|
|
/* Release resource */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(dspace) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(chunkfile) < 0)
|
|
TEST_ERROR;
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Dclose(dset);
|
|
H5Sclose(dspace);
|
|
H5Pclose(cparms);
|
|
H5Fclose(chunkfile);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
return 1;
|
|
} /* test_chunk_info_extensible_array() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_chunk_info_version2_btrees
|
|
*
|
|
* Purpose: Test getting various chunk information when Version 2 B-trees
|
|
* index type is used
|
|
*
|
|
* Return: # of errors
|
|
*
|
|
* Note: Note that the dataspace argument in these new functions are
|
|
* currently not used. The functionality involved the dataspace
|
|
* will be implemented in the next version.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_chunk_info_version2_btrees(const char *filename, hid_t fapl)
|
|
{
|
|
hid_t chunkfile = H5I_INVALID_HID; /* File ID */
|
|
hid_t dspace = H5I_INVALID_HID; /* Dataspace ID */
|
|
hid_t dset = H5I_INVALID_HID; /* Dataset ID */
|
|
hid_t cparms = H5I_INVALID_HID; /* Creation plist */
|
|
hsize_t dims[2] = {NX, NY}; /* Dataset dimensions */
|
|
hsize_t chunk_dims[2] = {CHUNK_NX, CHUNK_NY}; /* Chunk dimensions */
|
|
hsize_t maxdims[2] = {H5S_UNLIMITED, H5S_UNLIMITED}; /* Two unlimited dims */
|
|
uint32_t flt_msk = 0; /* Filter mask */
|
|
uint32_t read_flt_msk = 0; /* Filter mask after direct read */
|
|
hsize_t offset[2]; /* Offset coordinates of a chunk */
|
|
hsize_t start[2] = {START_CHK_X, START_CHK_Y}; /* Start position */
|
|
hsize_t end[2] = {END_CHK_X, END_CHK_Y}; /* End position */
|
|
hsize_t out_offset[2] = {0, 0}; /* Buffer to get offset coordinates */
|
|
hsize_t size = 0; /* Size of an allocated/written chunk */
|
|
hsize_t nchunks = 0; /* Number of chunks */
|
|
haddr_t addr = 0; /* Address of an allocated/written chunk */
|
|
hsize_t chk_index = 0; /* Index of a chunk */
|
|
hsize_t ii, jj; /* Array indices */
|
|
herr_t ret; /* Temporary returned value for verifying failure */
|
|
|
|
TESTING(" Version 2 B-trees index");
|
|
|
|
/* Open the file for reading/writing */
|
|
if ((chunkfile = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create dataspace */
|
|
if ((dspace = H5Screate_simple(RANK, dims, maxdims)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Enable chunking */
|
|
if ((cparms = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Pset_chunk(cparms, RANK, chunk_dims) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create a new dataset using cparms creation properties */
|
|
dset = H5Dcreate2(chunkfile, V2_BTREE_INDEX_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, cparms,
|
|
H5P_DEFAULT);
|
|
if (dset < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close the dataset */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Open the dataset again to test getting chunk info */
|
|
if ((dset = H5Dopen2(chunkfile, V2_BTREE_INDEX_DSET_NAME, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Verify chunk indexing scheme and number of chunks */
|
|
if (verify_idx_nchunks(dset, dspace, H5D_CHUNK_IDX_BT2, NO_CHUNK_WRITTEN) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification and write failed\n");
|
|
|
|
/* Write NUM_CHUNKS_WRITTEN chunks at the following logical coords:
|
|
* (0,2) (0,3) (1,2) (1,3)
|
|
*/
|
|
if (write_selected_chunks(dset, H5P_DEFAULT, start, end, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Writing to selected chunks failed\n");
|
|
|
|
/* Get and verify the number of chunks written */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (NUM_CHUNKS_WRITTEN != nchunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
/* Go through all written chunks, get their info and verify the values */
|
|
chk_index = 0;
|
|
for (ii = START_CHK_X; ii < END_CHK_X; ii++)
|
|
for (jj = START_CHK_Y; jj < END_CHK_Y; jj++, chk_index++) {
|
|
offset[0] = ii * CHUNK_NX;
|
|
offset[1] = jj * CHUNK_NY;
|
|
|
|
if (verify_get_chunk_info(dset, dspace, chk_index, CHK_SIZE, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info failed\n");
|
|
|
|
if (verify_get_chunk_info_by_coord(dset, offset, CHK_SIZE, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord failed\n");
|
|
}
|
|
|
|
/* Attempt to provide out-of-range offsets, should fail */
|
|
chk_index = OUTOFRANGE_CHK_INDEX;
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dget_chunk_info(dset, dspace, chk_index, out_offset, &read_flt_msk, &addr, &size);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret != FAIL)
|
|
FAIL_PUTS_ERROR(" Attempted to get info of a chunk using an out-of-range index.");
|
|
|
|
/* Attempt to get info of empty chunks, verify the returned address and size */
|
|
offset[0] = 0;
|
|
offset[1] = 0;
|
|
if (verify_empty_chunk_info(dset, offset) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on empty chunk failed\n");
|
|
|
|
offset[0] = 3 * CHUNK_NX;
|
|
offset[1] = 3 * CHUNK_NY;
|
|
if (verify_empty_chunk_info(dset, offset) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on empty chunk failed\n");
|
|
|
|
/* Read and verify values of selected chunks */
|
|
if (verify_selected_chunks(dset, H5P_DEFAULT, start, end) < 0)
|
|
|
|
/* Release resource */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(dspace) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(chunkfile) < 0)
|
|
TEST_ERROR;
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Dclose(dset);
|
|
H5Sclose(dspace);
|
|
H5Pclose(cparms);
|
|
H5Fclose(chunkfile);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
return 1;
|
|
} /* test_chunk_info_version2_btrees() */
|
|
|
|
typedef struct chunk_iter_info_t {
|
|
hsize_t offset[2];
|
|
unsigned filter_mask;
|
|
haddr_t addr;
|
|
hsize_t size;
|
|
} chunk_iter_info_t;
|
|
|
|
typedef struct chunk_iter_udata_t {
|
|
chunk_iter_info_t *chunk_info;
|
|
int last_index;
|
|
} chunk_iter_udata_t;
|
|
|
|
static int
|
|
iter_cb(const hsize_t *offset, unsigned filter_mask, haddr_t addr, hsize_t size, void *op_data)
|
|
{
|
|
chunk_iter_udata_t *cidata = (chunk_iter_udata_t *)op_data;
|
|
int idx = cidata->last_index + 1;
|
|
|
|
cidata->chunk_info[idx].offset[0] = offset[0];
|
|
cidata->chunk_info[idx].offset[1] = offset[1];
|
|
cidata->chunk_info[idx].filter_mask = filter_mask;
|
|
cidata->chunk_info[idx].addr = addr;
|
|
cidata->chunk_info[idx].size = size;
|
|
|
|
cidata->last_index++;
|
|
|
|
return H5_ITER_CONT;
|
|
}
|
|
|
|
static int
|
|
iter_cb_stop(const hsize_t H5_ATTR_UNUSED *offset, unsigned H5_ATTR_UNUSED filter_mask,
|
|
haddr_t H5_ATTR_UNUSED addr, hsize_t H5_ATTR_UNUSED size, void *op_data)
|
|
{
|
|
chunk_iter_info_t **chunk_info = (chunk_iter_info_t **)op_data;
|
|
*chunk_info += 1;
|
|
return H5_ITER_STOP;
|
|
}
|
|
|
|
static int
|
|
iter_cb_fail(const hsize_t H5_ATTR_UNUSED *offset, unsigned H5_ATTR_UNUSED filter_mask,
|
|
haddr_t H5_ATTR_UNUSED addr, hsize_t H5_ATTR_UNUSED size, void *op_data)
|
|
{
|
|
chunk_iter_info_t **chunk_info = (chunk_iter_info_t **)op_data;
|
|
*chunk_info += 1;
|
|
return H5_ITER_ERROR;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_basic_query
|
|
*
|
|
* Purpose: Tests basic operations to ensure the chunk query functions
|
|
* work properly.
|
|
*
|
|
* Return: # of errors
|
|
*
|
|
* Note: Note that the dataspace argument in these new functions are
|
|
* currently not used. The functionality involved the dataspace
|
|
* will be implemented in the next version.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_basic_query(hid_t fapl)
|
|
{
|
|
char filename[FILENAME_BUF_SIZE]; /* File name */
|
|
hid_t basicfile = H5I_INVALID_HID; /* File ID */
|
|
hid_t dspace = H5I_INVALID_HID; /* Dataspace ID */
|
|
hid_t dset = H5I_INVALID_HID; /* Dataset ID */
|
|
hid_t cparms = H5I_INVALID_HID; /* Creation plist */
|
|
hsize_t dims[2] = {NX, NY}; /* Dataset dimensions */
|
|
hsize_t chunk_dims[2] = {CHUNK_NX, CHUNK_NY}; /* Chunk dimensions */
|
|
int direct_buf[CHUNK_NX][CHUNK_NY]; /* Data in chunks */
|
|
uint32_t flt_msk = 0; /* Filter mask */
|
|
uint32_t read_flt_msk = 0; /* Filter mask after direct read */
|
|
hsize_t offset[2]; /* Offset coordinates of a chunk */
|
|
hsize_t out_offset[2] = {0, 0}; /* Buffer to get offset coordinates */
|
|
hsize_t size = 0; /* Size of an allocated/written chunk */
|
|
hsize_t nchunks = 0; /* Number of chunks */
|
|
haddr_t addr = 0; /* Address of an allocated/written chunk */
|
|
hsize_t chk_index = 0; /* Index of a chunk */
|
|
hsize_t ii, jj; /* Array indices */
|
|
chunk_iter_info_t chunk_infos[2]; /* Chunk infos filled up by iterator */
|
|
chunk_iter_info_t *cptr; /* Pointer to array of chunks */
|
|
chunk_iter_udata_t udata; /* udata for iteration */
|
|
herr_t ret; /* Temporary returned value for verifying failure */
|
|
|
|
TESTING("basic operations");
|
|
|
|
/* Create the file */
|
|
h5_fixname(BASIC_FILE, fapl, filename, sizeof filename);
|
|
|
|
/* Create a new file. */
|
|
if ((basicfile = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create dataspace */
|
|
if ((dspace = H5Screate_simple(RANK, dims, NULL)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Enable chunking */
|
|
if ((cparms = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Pset_chunk(cparms, RANK, chunk_dims) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create a new dataset using cparms creation properties */
|
|
dset = H5Dcreate2(basicfile, SIMPLE_CHUNKED_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, cparms,
|
|
H5P_DEFAULT);
|
|
if (dset < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Get the number of chunks and verify that no chunk has been written */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (NO_CHUNK_WRITTEN != nchunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
/* Initialize the array of chunk data for the single chunk */
|
|
for (ii = 0; ii < CHUNK_NX; ii++)
|
|
for (jj = 0; jj < CHUNK_NY; jj++)
|
|
direct_buf[ii][jj] = (int)(ii * jj);
|
|
|
|
/* Write the chunk of data */
|
|
offset[0] = CHUNK_NX;
|
|
offset[1] = CHUNK_NY;
|
|
if (H5Dwrite_chunk(dset, H5P_DEFAULT, flt_msk, offset, CHK_SIZE, direct_buf) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Get and verify that one chunk had been written */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (ONE_CHUNK_WRITTEN != nchunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
/* Get and verify info of the first and only chunk */
|
|
if (verify_get_chunk_info(dset, H5S_ALL, 0, CHK_SIZE, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification H5Dget_chunk_info failed\n");
|
|
|
|
/* Get and verify info of the chunk at the offset (CHUNK_NX,CHUNK_NY) */
|
|
if (verify_get_chunk_info_by_coord(dset, offset, CHK_SIZE, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord failed\n");
|
|
|
|
/* Attempt to get chunk info given an invalid chunk index and verify
|
|
* that failure occurs */
|
|
chk_index = INVALID_CHK_INDEX;
|
|
reinit_vars(&read_flt_msk, &addr, &size);
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dget_chunk_info(dset, dspace, chk_index, out_offset, &read_flt_msk, &addr, &size);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret != FAIL)
|
|
TEST_ERROR;
|
|
|
|
/* Write the chunk of data to another location */
|
|
offset[0] = 0;
|
|
offset[1] = 0;
|
|
if (H5Dwrite_chunk(dset, H5P_DEFAULT, flt_msk, offset, CHK_SIZE, direct_buf) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Get and verify that two chunks had been written */
|
|
if (H5Dget_num_chunks(dset, dspace, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (TWO_CHUNKS_WRITTEN != nchunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
/* Get and verify info of the first written chunk in the dataset, its
|
|
offset should be (0,0) */
|
|
if (verify_get_chunk_info(dset, H5S_ALL, 0, CHK_SIZE, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification H5Dget_chunk_info failed\n");
|
|
|
|
/* Get and verify info of the chunk at the offset (0,0) */
|
|
if (verify_get_chunk_info_by_coord(dset, offset, CHK_SIZE, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord failed\n");
|
|
|
|
/* Get and verify info of the second written chunk in the dataset, its
|
|
offset should be (CHUNK_NX, CHUNK_NY) */
|
|
offset[0] = CHUNK_NX;
|
|
offset[1] = CHUNK_NY;
|
|
if (verify_get_chunk_info(dset, H5S_ALL, 1, CHK_SIZE, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification H5Dget_chunk_info failed\n");
|
|
|
|
/* Get and verify info of the chunk at the offset (CHUNK_NX, CHUNK_NY) */
|
|
if (verify_get_chunk_info_by_coord(dset, offset, CHK_SIZE, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord failed\n");
|
|
|
|
/* Get and verify info of an empty chunk, at offset
|
|
(2*CHUNK_NX, 2*CHUNK_NY) */
|
|
offset[0] = 2 * CHUNK_NX;
|
|
offset[1] = 2 * CHUNK_NY;
|
|
/* Get and verify info of the chunk at the offset (CHUNK_NX, CHUNK_NY) */
|
|
if (verify_empty_chunk_info(dset, offset) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord on empty chunk failed\n");
|
|
|
|
/* Iterate over all chunks */
|
|
udata.chunk_info = chunk_infos;
|
|
udata.last_index = -1;
|
|
if (H5Dchunk_iter(dset, H5P_DEFAULT, &iter_cb, &udata) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (udata.last_index != 1)
|
|
FAIL_PUTS_ERROR("Iterator did not iterate over all chunks");
|
|
if (chunk_infos[0].offset[0] != 0)
|
|
FAIL_PUTS_ERROR("offset[0] mismatch");
|
|
if (chunk_infos[0].offset[1] != 0)
|
|
FAIL_PUTS_ERROR("offset[1] mismatch");
|
|
if (chunk_infos[0].filter_mask != 0)
|
|
FAIL_PUTS_ERROR("filter mask mismatch");
|
|
if (chunk_infos[0].size != 96)
|
|
FAIL_PUTS_ERROR("size mismatch");
|
|
|
|
if (chunk_infos[1].offset[0] != CHUNK_NX)
|
|
FAIL_PUTS_ERROR("offset[0] mismatch");
|
|
if (chunk_infos[1].offset[1] != CHUNK_NY)
|
|
FAIL_PUTS_ERROR("offset[1] mismatch");
|
|
|
|
/* Iterate and stop after one iteration */
|
|
cptr = &(chunk_infos[0]);
|
|
if (H5Dchunk_iter(dset, H5P_DEFAULT, &iter_cb_stop, &cptr) < 0)
|
|
TEST_ERROR;
|
|
if (cptr != &(chunk_infos[1]))
|
|
FAIL_PUTS_ERROR("Verification of halted iterator failed");
|
|
|
|
/* Iterate and fail after one iteration */
|
|
cptr = &(chunk_infos[0]);
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dchunk_iter(dset, H5P_DEFAULT, &iter_cb_fail, &cptr);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret >= 0)
|
|
TEST_ERROR;
|
|
if (cptr != &(chunk_infos[1]))
|
|
FAIL_PUTS_ERROR("Verification of halted iterator failed");
|
|
|
|
/* Release resource */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(dspace) < 0)
|
|
TEST_ERROR;
|
|
if (H5Pclose(cparms) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(basicfile) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Remove the test file */
|
|
HDremove(filename);
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Dclose(dset);
|
|
H5Sclose(dspace);
|
|
H5Pclose(cparms);
|
|
H5Fclose(basicfile);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
return 1;
|
|
} /* test_basic_query() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_failed_attempts
|
|
*
|
|
* Purpose: Test attempting to use chunk query functions incorrectly.
|
|
*
|
|
* Return: # of errors
|
|
*
|
|
* Note: Note that the dataspace argument in these new functions are
|
|
* currently not used. The functionality involved the dataspace
|
|
* will be implemented in the next version.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_failed_attempts(const char *filename, hid_t fapl)
|
|
{
|
|
hid_t chunkfile = H5I_INVALID_HID; /* File ID */
|
|
hid_t dspace = H5I_INVALID_HID; /* Dataspace ID */
|
|
hid_t dset = H5I_INVALID_HID; /* Dataset ID */
|
|
hsize_t dims[2] = {NX, NY}; /* Dataset dimensions */
|
|
int data_buf[NX][NY]; /* Input buffer */
|
|
uint32_t read_flt_msk = 0; /* Filter mask after direct read */
|
|
hsize_t offset[2]; /* Offset coordinates of a chunk */
|
|
hsize_t out_offset[2] = {0, 0}; /* Buffer to get offset coordinates */
|
|
hsize_t size = 0; /* Size of an allocated/written chunk */
|
|
hsize_t nchunks = 0; /* Number of chunks */
|
|
haddr_t addr = 0; /* Address of an allocated/written chunk */
|
|
hsize_t chk_index = 0; /* Index of a chunk */
|
|
hsize_t ii, jj; /* Array indices */
|
|
herr_t ret; /* Temporary returned value for verifying failure */
|
|
|
|
TESTING(" Invalid Operations");
|
|
|
|
/* Open the file for reading/writing */
|
|
if ((chunkfile = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create dataspace */
|
|
if ((dspace = H5Screate_simple(RANK, dims, NULL)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create a contiguous dataset */
|
|
dset = H5Dcreate2(chunkfile, CONTIGUOUS_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, H5P_DEFAULT,
|
|
H5P_DEFAULT);
|
|
if (dset < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Initialize the array of data */
|
|
for (ii = 0; ii < NX; ii++)
|
|
for (jj = 0; jj < NY; jj++)
|
|
data_buf[ii][jj] = (int)(ii * jj);
|
|
|
|
/* Write the data */
|
|
if (H5Dwrite(dset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data_buf) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close the dataset */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Open it again to test the chunk query functions on contiguous dataset */
|
|
if ((dset = H5Dopen2(chunkfile, CONTIGUOUS_DSET_NAME, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Attempt to get the number of chunks on contiguous dataset, should fail */
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dget_num_chunks(dset, dspace, &nchunks);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret != FAIL)
|
|
FAIL_PUTS_ERROR(" Attempt a chunk query function on a contiguous dataset.");
|
|
|
|
/* Attempt to get chunk info on contiguous data, should fail */
|
|
chk_index = 0;
|
|
reinit_vars(&read_flt_msk, &addr, &size);
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dget_chunk_info(dset, dspace, chk_index, out_offset, &read_flt_msk, &addr, &size);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret != FAIL)
|
|
FAIL_PUTS_ERROR(" Attempt a chunk query function on a contiguous dataset.");
|
|
|
|
/* Attempt to get chunk info at logical coordinates (0,0) on contiguous
|
|
* dataset, should fail */
|
|
offset[0] = 0;
|
|
offset[1] = 0;
|
|
H5E_BEGIN_TRY
|
|
{
|
|
ret = H5Dget_chunk_info_by_coord(dset, offset, &read_flt_msk, &addr, &size);
|
|
}
|
|
H5E_END_TRY
|
|
if (ret != FAIL)
|
|
FAIL_PUTS_ERROR(" Attempt a chunk query function on a contiguous dataset.");
|
|
|
|
/* Release resource */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(dspace) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(chunkfile) < 0)
|
|
TEST_ERROR;
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Dclose(dset);
|
|
H5Sclose(dspace);
|
|
H5Fclose(chunkfile);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
return 1;
|
|
} /* test_failed_attempts() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_get_chunk_info_v110
|
|
*
|
|
* Purpose: Test getting various chunk information in version 1.10.
|
|
*
|
|
* Return: # of errors
|
|
*
|
|
* Note: Note that the dataspace argument in these new functions are
|
|
* currently not used. The functionality involved the dataspace
|
|
* will be implemented in the next version.
|
|
*
|
|
* Description:
|
|
* This function tests the new API functions added for HDFFV-10677:
|
|
* H5Dget_num_chunks, H5Dget_chunk_info, and
|
|
* H5Dget_chunk_info_by_coord for low bound beyond 1.8.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_get_chunk_info_v110(hid_t fapl)
|
|
{
|
|
char filename[FILENAME_BUF_SIZE]; /* File name */
|
|
hid_t chunkfile = H5I_INVALID_HID; /* File ID */
|
|
H5F_libver_t low, high; /* File format bounds */
|
|
|
|
TESTING("getting chunk information in file with versions 1.10 and later");
|
|
printf("\n"); /* to list sub-tests */
|
|
|
|
/* Set high bound to the current latest version */
|
|
high = H5F_LIBVER_LATEST;
|
|
|
|
/* Test getting info of chunked datasets in version combo up to 1.10 */
|
|
for (low = H5F_LIBVER_V110; low <= H5F_LIBVER_LATEST; low++) {
|
|
/* Set version bounds for creating file */
|
|
if (H5Pset_libver_bounds(fapl, low, high) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create the file */
|
|
h5_fixname(FILENAME[low], fapl, filename, sizeof filename);
|
|
chunkfile = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
|
if (chunkfile < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close the file, individual tests will re-open the file with different
|
|
libvers via the fapl */
|
|
if (H5Fclose(chunkfile) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Test getting chunk info when Single Chunk index type is used */
|
|
if (test_chunk_info_single_chunk(filename, fapl) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Test getting chunk info when Implicit index type is used */
|
|
if (test_chunk_info_implicit(filename, fapl) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Test getting chunk info when Fixed Array index type is used */
|
|
if (test_chunk_info_fixed_array(filename, fapl) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Test getting chunk info when Extensible Array index type is used */
|
|
if (test_chunk_info_extensible_array(filename, fapl) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Test getting chunk info when Version 2 B-trees index type is used */
|
|
if (test_chunk_info_version2_btrees(filename, fapl) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Test various attempts to use the functions incorrectly */
|
|
if (test_failed_attempts(filename, fapl) < 0)
|
|
TEST_ERROR;
|
|
|
|
} /* for low libver bound */
|
|
|
|
return 0;
|
|
|
|
error:
|
|
return 1;
|
|
} /* test_get_chunk_info_v110() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_flt_msk_with_skip_compress
|
|
*
|
|
* Purpose: Test getting chunk info when compression filter is skipped
|
|
*
|
|
* Return: # of errors
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_flt_msk_with_skip_compress(hid_t fapl)
|
|
{
|
|
char filename[FILENAME_BUF_SIZE]; /* File name */
|
|
hid_t filter_file = H5I_INVALID_HID; /* File ID for filter mask */
|
|
hid_t dspace = H5I_INVALID_HID; /* Dataspace ID */
|
|
hid_t mem_space = H5I_INVALID_HID; /* Dataspace ID */
|
|
hid_t dset = H5I_INVALID_HID; /* Dataset ID */
|
|
hid_t cparms = H5I_INVALID_HID; /* Creation plist */
|
|
hid_t dxpl = H5I_INVALID_HID; /* Transfer plist */
|
|
hsize_t dims[2] = {NX, NY}; /* Dataset dimensions */
|
|
hsize_t maxdims[2] = {H5S_UNLIMITED, H5S_UNLIMITED}; /* 2 unlimited dims */
|
|
hsize_t chunk_dims[2] = {CHUNK_NX, CHUNK_NY}; /* Chunk dimensions */
|
|
int direct_buf[CHUNK_NX][CHUNK_NY]; /* One chunk of data */
|
|
int check_chunk[CHUNK_NX][CHUNK_NY]; /* Buffer to read data in */
|
|
int read_direct_buf[CHUNK_NX][CHUNK_NY]; /* Buffer to read a chunk */
|
|
hsize_t read_buf_size = 0; /* buf size */
|
|
uint32_t flt_msk = 0; /* Filter mask */
|
|
uint32_t read_flt_msk = 0; /* Filter mask after direct read */
|
|
hsize_t offset[2] = {0, 0}; /* Offset coordinates of a chunk */
|
|
hsize_t nchunks = 0; /* Number of chunks */
|
|
hsize_t chk_index = 0; /* Index of a chunk */
|
|
int aggression = 9; /* Compression aggression setting */
|
|
hsize_t start[2]; /* Start of hyperslab */
|
|
hsize_t stride[2]; /* Stride of hyperslab */
|
|
hsize_t count[2]; /* Block count */
|
|
hsize_t block[2]; /* Block sizes */
|
|
int ii, jj; /* Array indices */
|
|
|
|
TESTING("getting filter mask when compression filter is skipped");
|
|
|
|
/* Create the file */
|
|
h5_fixname(FILTERMASK_FILE, fapl, filename, sizeof filename);
|
|
|
|
/* Create a new file. */
|
|
if ((filter_file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create file data space with unlimited dimensions. */
|
|
if ((dspace = H5Screate_simple(RANK, dims, maxdims)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create memory data space. */
|
|
if ((mem_space = H5Screate_simple(RANK, chunk_dims, NULL)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create dataset create property list with chunking and compression
|
|
enabled. */
|
|
if ((cparms = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Pset_chunk(cparms, RANK, chunk_dims) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Pset_deflate(cparms, (unsigned)aggression) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create a new dataset using cparms creation properties. */
|
|
if ((dset = H5Dcreate2(filter_file, SKIP_FILTER_DSET_NAME, H5T_NATIVE_INT, dspace, H5P_DEFAULT, cparms,
|
|
H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create transfer property list for writing */
|
|
if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Initialize data for one chunk */
|
|
for (ii = 0; ii < CHUNK_NX; ii++)
|
|
for (jj = 0; jj < CHUNK_NY; jj++)
|
|
direct_buf[ii][jj] = (int)(ii * jj);
|
|
|
|
/* Indicate the compression filter is to be skipped. */
|
|
flt_msk = 0x00000001;
|
|
|
|
/* Write a chunk of uncompressed data */
|
|
offset[0] = CHUNK_NX;
|
|
offset[1] = CHUNK_NY;
|
|
if (H5Dwrite_chunk(dset, H5P_DEFAULT, flt_msk, offset, CHK_SIZE, direct_buf) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Fflush(dset, H5F_SCOPE_LOCAL) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close and re-open the dataset */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
if ((dset = H5Dopen2(filter_file, SKIP_FILTER_DSET_NAME, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Select hyperslab for the chunk just written in the file */
|
|
start[0] = CHUNK_NX;
|
|
start[1] = CHUNK_NY;
|
|
stride[0] = 1;
|
|
stride[1] = 1;
|
|
count[0] = 1;
|
|
count[1] = 1;
|
|
block[0] = CHUNK_NX;
|
|
block[1] = CHUNK_NY;
|
|
if (H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, stride, count, block) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Read the chunk back */
|
|
if (H5Dread(dset, H5T_NATIVE_INT, mem_space, dspace, H5P_DEFAULT, check_chunk) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Check that the values read are the same as the values written */
|
|
for (ii = 0; ii < CHUNK_NX; ii++)
|
|
for (jj = 0; jj < CHUNK_NY; jj++)
|
|
if (direct_buf[ii][jj] != check_chunk[ii][jj]) {
|
|
printf(" 1. Read different values than written.");
|
|
printf(" At index %d,%d\n", ii, jj);
|
|
printf(" direct_buf=%d, check_chunk=%d\n", direct_buf[ii][jj], check_chunk[ii][jj]);
|
|
TEST_ERROR;
|
|
}
|
|
|
|
/* Query chunk storage size */
|
|
if (H5Dget_chunk_storage_size(dset, offset, &read_buf_size) < 0)
|
|
TEST_ERROR;
|
|
if (read_buf_size != CHK_SIZE)
|
|
TEST_ERROR;
|
|
|
|
/* Read the raw chunk back with H5Dread_chunk */
|
|
memset(&read_direct_buf, 0, sizeof(read_direct_buf));
|
|
if (H5Dread_chunk(dset, H5P_DEFAULT, offset, &read_flt_msk, read_direct_buf) < 0)
|
|
TEST_ERROR;
|
|
if (read_flt_msk != flt_msk)
|
|
TEST_ERROR;
|
|
|
|
/* Check that the direct chunk read is the same as the chunk written */
|
|
for (ii = 0; ii < CHUNK_NX; ii++)
|
|
for (jj = 0; jj < CHUNK_NY; jj++)
|
|
if (direct_buf[ii][jj] != read_direct_buf[ii][jj]) {
|
|
printf(" 1. Read different values than written.");
|
|
printf(" At index %d,%d\n", ii, jj);
|
|
printf(" direct_buf=%d, read_direct_buf=%d\n", direct_buf[ii][jj],
|
|
read_direct_buf[ii][jj]);
|
|
TEST_ERROR;
|
|
}
|
|
|
|
/* Get and verify the number of chunks written */
|
|
if (H5Dget_num_chunks(dset, H5S_ALL, &nchunks) < 0)
|
|
TEST_ERROR;
|
|
if (ONE_CHUNK_WRITTEN != nchunks)
|
|
FAIL_PUTS_ERROR("unexpected number of chunks");
|
|
|
|
/* Get and verify info of the first and only chunk */
|
|
chk_index = 0;
|
|
offset[0] = CHUNK_NX;
|
|
offset[1] = CHUNK_NY;
|
|
if (verify_get_chunk_info(dset, H5S_ALL, chk_index, CHK_SIZE, offset, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info failed\n");
|
|
|
|
/* Get info of the chunk at the specified offsets and verify its info */
|
|
if (verify_get_chunk_info_by_coord(dset, offset, CHK_SIZE, flt_msk) == FAIL)
|
|
FAIL_PUTS_ERROR("Verification of H5Dget_chunk_info_by_coord failed\n");
|
|
|
|
/* Release resource */
|
|
if (H5Dclose(dset) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(mem_space) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(dspace) < 0)
|
|
TEST_ERROR;
|
|
if (H5Pclose(cparms) < 0)
|
|
TEST_ERROR;
|
|
if (H5Pclose(dxpl) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(filter_file) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Remove the test file */
|
|
HDremove(filename);
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Dclose(dset);
|
|
H5Sclose(mem_space);
|
|
H5Sclose(dspace);
|
|
H5Pclose(cparms);
|
|
H5Pclose(dxpl);
|
|
H5Fclose(filter_file);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
return 1;
|
|
} /* test_flt_msk_with_skip_compress() */
|
|
|
|
#define UBLOCK_FILE_NAME "file_with_userblock.h5"
|
|
#define NO_UBLOCK_FILE_NAME "file_without_userblock.h5"
|
|
#define UBLOCK_DSET_NAME "ublock_dset"
|
|
#define UBLOCK_SIZE 2048
|
|
|
|
/* Helper function to create userblock files and datasets */
|
|
static herr_t
|
|
create_userblock_file(const char *filename, hid_t fcpl_id, hid_t fapl_id)
|
|
{
|
|
hid_t fid = H5I_INVALID_HID;
|
|
hid_t did = H5I_INVALID_HID;
|
|
hid_t sid = H5I_INVALID_HID;
|
|
hid_t dcpl_id = H5I_INVALID_HID;
|
|
|
|
/* The chunk size is set to 1 so we get a lot of chunks without
|
|
* writing a lot of data.
|
|
*/
|
|
int rank = 1;
|
|
hsize_t dims = {256};
|
|
hsize_t chunk_dims = {1};
|
|
|
|
int *data = NULL;
|
|
|
|
/* Create a new file */
|
|
if ((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create file data space for the dataset */
|
|
if ((sid = H5Screate_simple(rank, &dims, &dims)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create dataset create property list with chunking */
|
|
if ((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
|
TEST_ERROR;
|
|
if (H5Pset_chunk(dcpl_id, rank, &chunk_dims) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create a new dataset */
|
|
if ((did = H5Dcreate2(fid, UBLOCK_DSET_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create some arbitrary data */
|
|
if (NULL == (data = (int *)malloc(256 * sizeof(int))))
|
|
TEST_ERROR;
|
|
for (int i = 0; i < 256; i++)
|
|
data[i] = i;
|
|
|
|
/* Write the data to the dataset */
|
|
if (H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Close everything */
|
|
if (H5Pclose(dcpl_id) < 0)
|
|
TEST_ERROR;
|
|
if (H5Dclose(did) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(sid) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(fid) < 0)
|
|
TEST_ERROR;
|
|
|
|
free(data);
|
|
|
|
return SUCCEED;
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Pclose(dcpl_id);
|
|
H5Dclose(did);
|
|
H5Sclose(sid);
|
|
H5Fclose(fid);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
free(data);
|
|
|
|
return FAIL;
|
|
}
|
|
|
|
/* op_data for the userblock iterator */
|
|
struct ub_op_data {
|
|
haddr_t *addresses;
|
|
hsize_t i;
|
|
hsize_t max;
|
|
};
|
|
|
|
/* Callback function for iterating over dataset chunks is files both with
|
|
* and without a userblock
|
|
*/
|
|
static int
|
|
ublock_iter_cb(const hsize_t H5_ATTR_UNUSED *offset, unsigned H5_ATTR_UNUSED filter_mask, haddr_t addr,
|
|
hsize_t H5_ATTR_UNUSED size, void *op_data)
|
|
{
|
|
struct ub_op_data *od = (struct ub_op_data *)op_data;
|
|
|
|
/* Error if we try to iterate over too many chunks */
|
|
if (od->i == od->max)
|
|
return H5_ITER_ERROR;
|
|
|
|
/* Store the address for later comparison */
|
|
od->addresses[od->i] = addr;
|
|
od->i += 1;
|
|
|
|
return H5_ITER_CONT;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_chunk_address_with_userblock
|
|
*
|
|
* Purpose: Test that chunk addresses are correct when a file has
|
|
* a userblock
|
|
*
|
|
* Return: # of errors
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
test_chunk_address_with_userblock(hid_t fapl_id)
|
|
{
|
|
hid_t fid = H5I_INVALID_HID;
|
|
hid_t fid_ub = H5I_INVALID_HID;
|
|
hid_t did = H5I_INVALID_HID;
|
|
hid_t did_ub = H5I_INVALID_HID;
|
|
hid_t fcpl_id = H5I_INVALID_HID;
|
|
|
|
hsize_t num_chunks = HSIZE_UNDEF;
|
|
hsize_t num_chunks_ub = 0;
|
|
|
|
haddr_t *addresses = NULL;
|
|
haddr_t *addresses_ub = NULL;
|
|
|
|
struct ub_op_data od;
|
|
struct ub_op_data od_ub;
|
|
|
|
int fd = -1;
|
|
int fd_ub = -1;
|
|
|
|
bool default_vfd_compatible;
|
|
|
|
TESTING("if chunk addresses are correct when a file has a userblock");
|
|
|
|
if (h5_driver_is_default_vfd_compatible(fapl_id, &default_vfd_compatible) < 0)
|
|
TEST_ERROR;
|
|
if (!default_vfd_compatible) {
|
|
puts(" -- SKIPPED for incompatible VFD --");
|
|
return 0;
|
|
}
|
|
|
|
/* Create files with and without a userblock */
|
|
if (create_userblock_file(NO_UBLOCK_FILE_NAME, H5P_DEFAULT, fapl_id) < 0)
|
|
TEST_ERROR;
|
|
|
|
if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) == H5I_INVALID_HID)
|
|
TEST_ERROR;
|
|
if (H5Pset_userblock(fcpl_id, UBLOCK_SIZE) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (create_userblock_file(UBLOCK_FILE_NAME, fcpl_id, fapl_id) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Open both files and datasets */
|
|
if ((fid = H5Fopen(NO_UBLOCK_FILE_NAME, H5F_ACC_RDONLY, fapl_id)) == H5I_INVALID_HID)
|
|
TEST_ERROR;
|
|
if ((did = H5Dopen2(fid, UBLOCK_DSET_NAME, H5P_DEFAULT)) == H5I_INVALID_HID)
|
|
TEST_ERROR;
|
|
if ((fid_ub = H5Fopen(UBLOCK_FILE_NAME, H5F_ACC_RDONLY, fapl_id)) == H5I_INVALID_HID)
|
|
TEST_ERROR;
|
|
if ((did_ub = H5Dopen2(fid_ub, UBLOCK_DSET_NAME, H5P_DEFAULT)) == H5I_INVALID_HID)
|
|
TEST_ERROR;
|
|
|
|
/* Get the number of chunks */
|
|
if (H5Dget_num_chunks(did, H5S_ALL, &num_chunks) < 0)
|
|
TEST_ERROR;
|
|
if (H5Dget_num_chunks(did_ub, H5S_ALL, &num_chunks_ub) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (num_chunks != num_chunks_ub)
|
|
TEST_ERROR;
|
|
|
|
/* Check the chunk information to make sure that the userblock file takes
|
|
* the block's size into account.
|
|
*/
|
|
for (hsize_t i = 0; i < num_chunks; i++) {
|
|
haddr_t addr = HADDR_UNDEF;
|
|
haddr_t addr_ub = 0;
|
|
|
|
/* H5Dget_chunk_info() */
|
|
if (H5Dget_chunk_info(did, H5S_ALL, i, NULL, NULL, &addr, NULL) < 0)
|
|
TEST_ERROR;
|
|
if (H5Dget_chunk_info(did_ub, H5S_ALL, i, NULL, NULL, &addr_ub, NULL) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (addr + UBLOCK_SIZE != addr_ub)
|
|
TEST_ERROR;
|
|
|
|
addr = HADDR_UNDEF;
|
|
addr_ub = 0;
|
|
|
|
/* H5Dget_chunk_info_by_coord() */
|
|
if (H5Dget_chunk_info_by_coord(did, &i, NULL, &addr, NULL) < 0)
|
|
TEST_ERROR;
|
|
if (H5Dget_chunk_info_by_coord(did_ub, &i, NULL, &addr_ub, NULL) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (addr + UBLOCK_SIZE != addr_ub)
|
|
TEST_ERROR;
|
|
}
|
|
|
|
/* Allocate arrays to hold the chunk addresses */
|
|
if (NULL == (addresses = (haddr_t *)calloc(num_chunks, sizeof(haddr_t))))
|
|
TEST_ERROR;
|
|
if (NULL == (addresses_ub = (haddr_t *)calloc(num_chunks, sizeof(haddr_t))))
|
|
TEST_ERROR;
|
|
|
|
od.addresses = addresses;
|
|
od.i = 0;
|
|
od.max = num_chunks;
|
|
|
|
od_ub.addresses = addresses_ub;
|
|
od_ub.i = 0;
|
|
od_ub.max = num_chunks;
|
|
|
|
/* Iterate over the chunks, storing the chunk addresses */
|
|
if (H5Dchunk_iter(did, H5P_DEFAULT, ublock_iter_cb, &od) < 0)
|
|
TEST_ERROR;
|
|
if (H5Dchunk_iter(did_ub, H5P_DEFAULT, ublock_iter_cb, &od_ub) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Compare the chunk addresses to ensure the userblock file takes the
|
|
* chunk's size into account.
|
|
*/
|
|
if (od.i != od_ub.i)
|
|
TEST_ERROR;
|
|
for (hsize_t i = 0; i < num_chunks; i++)
|
|
if (od.addresses[i] + UBLOCK_SIZE != od_ub.addresses[i])
|
|
TEST_ERROR;
|
|
|
|
/* Compare the raw chunk data */
|
|
if ((fd = HDopen(NO_UBLOCK_FILE_NAME, O_RDONLY)) < 0)
|
|
TEST_ERROR;
|
|
if ((fd_ub = HDopen(UBLOCK_FILE_NAME, O_RDONLY)) < 0)
|
|
TEST_ERROR;
|
|
|
|
for (hsize_t i = 0; i < num_chunks; i++) {
|
|
int data = -1;
|
|
int data_ub = -1;
|
|
|
|
if (HDlseek(fd, (HDoff_t)(od.addresses[i]), SEEK_SET) < 0)
|
|
TEST_ERROR;
|
|
if (HDlseek(fd_ub, (HDoff_t)(od_ub.addresses[i]), SEEK_SET) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (HDread(fd, &data, sizeof(int)) != sizeof(int))
|
|
TEST_ERROR;
|
|
if (HDread(fd_ub, &data_ub, sizeof(int)) != sizeof(int))
|
|
TEST_ERROR;
|
|
|
|
if (data != data_ub)
|
|
TEST_ERROR;
|
|
}
|
|
|
|
HDclose(fd);
|
|
fd = -1;
|
|
HDclose(fd_ub);
|
|
fd_ub = -1;
|
|
|
|
/* Close everything */
|
|
if (H5Pclose(fcpl_id) < 0)
|
|
TEST_ERROR;
|
|
if (H5Dclose(did) < 0)
|
|
TEST_ERROR;
|
|
if (H5Dclose(did_ub) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(fid) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fclose(fid_ub) < 0)
|
|
TEST_ERROR;
|
|
|
|
free(addresses);
|
|
free(addresses_ub);
|
|
|
|
if (H5Fdelete(UBLOCK_FILE_NAME, fapl_id) < 0)
|
|
TEST_ERROR;
|
|
if (H5Fdelete(NO_UBLOCK_FILE_NAME, fapl_id) < 0)
|
|
TEST_ERROR;
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Pclose(fcpl_id);
|
|
H5Dclose(did);
|
|
H5Dclose(did_ub);
|
|
H5Fclose(fid);
|
|
H5Fclose(fid_ub);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
if (fd >= 0)
|
|
HDclose(fd);
|
|
if (fd_ub >= 0)
|
|
HDclose(fd_ub);
|
|
|
|
free(addresses);
|
|
free(addresses_ub);
|
|
|
|
return 1;
|
|
} /* test_chunk_address_with_userblock() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: main
|
|
*
|
|
* Purpose: Tests functions related to chunk information
|
|
*
|
|
* Return: EXIT_SUCCESS/EXIT_FAILURE
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
main(void)
|
|
{
|
|
hid_t fapl = H5I_INVALID_HID; /* File access property list */
|
|
int nerrors = 0; /* Number of errors so far */
|
|
|
|
h5_test_init();
|
|
|
|
/* Create a copy of file access property list */
|
|
if ((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
|
|
goto error;
|
|
|
|
/* Test basic operations on the chunk query functions */
|
|
nerrors += test_basic_query(fapl);
|
|
|
|
/* Tests getting chunk information of version 1.8 and prior */
|
|
nerrors += test_get_chunk_info_highest_v18(fapl);
|
|
|
|
/* Tests getting chunk information of version 1.10 */
|
|
nerrors += test_get_chunk_info_v110(fapl);
|
|
|
|
/* Tests getting filter mask when compression filter is skipped */
|
|
nerrors += test_flt_msk_with_skip_compress(fapl);
|
|
|
|
/* Test that chunk addresses are correct when files have a userblock */
|
|
nerrors += test_chunk_address_with_userblock(fapl);
|
|
|
|
if (nerrors)
|
|
goto error;
|
|
|
|
printf("All chunk query tests passed.\n");
|
|
|
|
h5_cleanup(FILENAME, fapl);
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Pclose(fapl);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
nerrors = MAX(1, nerrors);
|
|
printf("***** %d QUERY CHUNK INFO TEST%s FAILED! *****\n", nerrors, 1 == nerrors ? "" : "S");
|
|
return EXIT_FAILURE;
|
|
}
|