mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-21 01:04:10 +08:00
5425a571e0
Switches previous 1.16/17/18 values to 2.0
2498 lines
90 KiB
C
2498 lines
90 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 LICENSE 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 "h5test.h"
|
|
#include "H5Dpkg.h"
|
|
#ifdef H5_HAVE_FILTER_DEFLATE
|
|
#if defined(H5_HAVE_ZLIB_H) && !defined(H5_ZLIB_HEADER)
|
|
#define H5_ZLIB_HEADER "zlib.h"
|
|
#endif
|
|
#if defined(H5_ZLIB_HEADER)
|
|
#include H5_ZLIB_HEADER /* "zlib.h" */
|
|
#endif
|
|
#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_v200",
|
|
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 */
|
|
#if defined(H5_HAVE_ZLIBNG_H)
|
|
ret = zng_compress2(z_dst, &z_dst_nbytes, z_src, z_src_nbytes, aggression);
|
|
#else
|
|
ret = compress2(z_dst, &z_dst_nbytes, z_src, z_src_nbytes, aggression);
|
|
#endif
|
|
|
|
/* 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;
|
|
}
|