summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Smith <jake.smith@hdfgroup.org>2018-09-11 21:37:14 (GMT)
committerJacob Smith <jake.smith@hdfgroup.org>2018-09-11 21:37:14 (GMT)
commit602dd3ac15c9f5cd47fc78985266ce66a68a8789 (patch)
tree149023d5992abebe5a5a36e45e8132ab478a8c63
parent5647dea421be9dc8429f08632aa72a8a22904292 (diff)
downloadhdf5-602dd3ac15c9f5cd47fc78985266ce66a68a8789.zip
hdf5-602dd3ac15c9f5cd47fc78985266ce66a68a8789.tar.gz
hdf5-602dd3ac15c9f5cd47fc78985266ce66a68a8789.tar.bz2
Stash work on object header reduction code and tests.
CMake stuff is not verified.
-rw-r--r--MANIFEST1
-rw-r--r--src/H5Dint.c306
-rw-r--r--src/H5Dprivate.h1
-rw-r--r--src/H5F.c94
-rw-r--r--src/H5Fint.c3
-rw-r--r--src/H5Fpkg.h1
-rw-r--r--src/H5Fpublic.h2
-rw-r--r--src/H5Oint.c382
-rw-r--r--src/H5Oprivate.h12
-rw-r--r--src/H5Pdcpl.c126
-rw-r--r--src/H5Ppublic.h2
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/CMakeTests.cmake2
-rw-r--r--test/Makefile.am15
-rw-r--r--test/dsets.c109
-rw-r--r--test/enc_dec_plist.c3
-rw-r--r--test/gen_plist.c3
-rw-r--r--test/tfile.c139
18 files changed, 1101 insertions, 101 deletions
diff --git a/MANIFEST b/MANIFEST
index 1165240..68763aa 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1041,6 +1041,7 @@
./test/none.h5
./test/ntypes.c
./test/ohdr.c
+./test/ohdr_min.c
./test/objcopy.c
./test/page_buffer.c
./test/paged_nopersist.h5
diff --git a/src/H5Dint.c b/src/H5Dint.c
index e8874a2..6d095aa 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -61,7 +61,9 @@ static herr_t H5D__init_storage(const H5D_io_info_t *io_info, hbool_t full_overw
static herr_t H5D__get_storage_size_real(const H5D_t *dset, hsize_t *storage_size);
static herr_t H5D__append_flush_setup(H5D_t *dset, hid_t dapl_id);
static herr_t H5D__close_cb(H5D_t *dataset);
-
+static herr_t H5D__use_minimized_dset_headers(H5F_t *file, H5D_t *dset, hbool_t *minimize);
+static herr_t H5D__prepare_minimized_oh(H5F_t *file, H5D_t *dset, H5O_loc_t *oloc);
+static size_t H5D__calculate_minimum_header_size(H5F_t *file, H5D_t *dset, H5O_t *ohdr);
/*********************/
/* Package Variables */
/*********************/
@@ -662,6 +664,272 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D__use_minimized_dset_headers
+ *
+ * Purpose: Compartmentalize check for file- or dcpl-set values indicating
+ * to create a "minimized" dataset object header.
+ * Upon success, write resulting value to out pointer `minimize`.
+ *
+ * Return: Success: SUCCEED (0) (non-negative value)
+ * Failure: FAIL (-1) (negative value)
+ *
+ * Programmer: Jacob Smith
+ * 16 August 2018
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__use_minimized_dset_headers( \
+ H5F_t *file, \
+ H5D_t *dset, \
+ hbool_t *minimize)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT;
+
+ HDassert(file);
+ HDassert(dset);
+ HDassert(minimize);
+
+ if (FAIL == H5Pget_dset_no_attrs_hint(dset->shared->dcpl_id, minimize))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL,
+ "can't get minimize value from dcpl")
+
+#if 1 /* TODO: problem getting file id? */
+ /* error kicks in when tring to create dset through external link */
+ if (FALSE == *minimize) {
+#if 1 /* API or direct */
+ /* problems getting/verifying object id */
+ hid_t file_id = -1;
+ file_id = H5F_get_file_id((const H5F_t *)file);
+ if (0 > file_id)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL,
+ "can't get file id")
+
+#if 1 /* which file-id verification */
+ if (NULL == H5I_object(file_id))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL,
+ "file id seems to be invalid")
+#else
+ if (NULL == H5I_object_verify(file_id, H5I_FILE))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL,
+ "file id seems to be invalid")
+#endif /* which file-id verification */
+
+ if (FAIL == H5Fget_dset_no_attrs_hint(file_id, minimize))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL,
+ "can't get minimize value from file")
+#else
+ /* direct access -- "incomplete type" */
+ HDassert(file->shared);
+ minimize = file->shared->crt_dset_min_ohdr_flag;
+#endif /* API or direct */
+ } /* if to look in file for flag */
+#endif /* TODO */
+
+done:
+ if (FAIL == ret_value)
+ *minimize = FALSE;
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5D__use_minimized_dset_headers */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__calculate_minimium_header_size
+ *
+ * Purpose: Calculate the size required for the minimized object header.
+ *
+ * Return: Success: SUCCEED (0) (non-negative value)
+ * Failure: FAIL (-1) (negative value)
+ *
+ * Programmer: Jacob Smith
+ * 16 August 2018
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5D__calculate_minimum_header_size( \
+ H5F_t *file, \
+ H5D_t *dset, \
+ H5O_t *ohdr)
+{
+ H5T_t *type = NULL;
+ H5O_fill_t *fill_prop = NULL;
+ hbool_t use_at_least_v18 = FALSE;
+ size_t ret_value = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR;
+
+ HDassert(file);
+ HDassert(dset);
+ HDassert(ohdr);
+
+ type = dset->shared->type;
+ fill_prop = &(dset->shared->dcpl_cache.fill);
+ use_at_least_v18 = (H5F_LOW_BOUND(file) >= H5F_LIBVER_V18);
+
+ /* Datatype message size */
+ ret_value += H5O_msg_size_oh(
+ file,
+ ohdr,
+ H5O_DTYPE_ID,
+ type,
+ 0);
+
+ /* Shared Dataspace message size */
+ ret_value += H5O_msg_size_oh(
+ file,
+ ohdr,
+ H5O_SDSPACE_ID,
+ dset->shared->space,
+ 0);
+
+ /* "Layout" message size */
+ ret_value += H5O_msg_size_oh(
+ file,
+ ohdr,
+ H5O_LAYOUT_ID,
+ &dset->shared->layout,
+ 0);
+
+ /* Fill Value message size */
+ ret_value += H5O_msg_size_oh(
+ file,
+ ohdr,
+ H5O_FILL_NEW_ID,
+ fill_prop,
+ 0);
+
+#if 1 /* DEBUG H5Omessage */
+ /* "Continuation" message size */
+#if 0
+ ret_value += H5O_msg_raw_size(
+ file,
+ H5O_CONT_ID,
+ FALSE,
+ NULL);
+#else
+ {
+ char tmp[1] = "\0";
+ ret_value += H5O_msg_size_oh(
+ file,
+ ohdr,
+ H5O_CONT_ID,
+ tmp, /* NULL, */ /* UNUSED? */ /*intercepted by assert before passed through */
+ 0);
+ }
+#endif
+#endif /* DEBUG H5Omessage */
+
+ /* Fill Value (backwards compatability) message size */
+ if (fill_prop->buf && !use_at_least_v18) {
+ H5O_fill_t old_fill_prop; /* Copy for writing "old" fill value */
+
+ /* Shallow copy the fill value property */
+ /* guards against shared component modification */
+ HDmemcpy(&old_fill_prop, fill_prop, sizeof(old_fill_prop));
+
+ H5O_msg_reset_share(H5O_FILL_ID, &old_fill_prop);
+
+ ret_value += H5O_msg_size_oh(
+ file,
+ ohdr,
+ H5O_FILL_ID,
+ &old_fill_prop,
+ 0);
+ }
+
+ /* Filter/Pipeline message size */
+ if (H5D_CHUNKED == dset->shared->layout.type) {
+ H5O_pline_t *pline = &dset->shared->dcpl_cache.pline;
+ if (pline->nused > 0) {
+ ret_value += H5O_msg_size_oh(
+ file,
+ ohdr,
+ H5O_PLINE_ID,
+ pline,
+ 0);
+ }
+ }
+
+ /* External File Link message size */
+ if (dset->shared->dcpl_cache.efl.nused > 0) {
+ ret_value += H5O_msg_size_oh(
+ file,
+ ohdr,
+ H5O_EFL_ID,
+ &dset->shared->dcpl_cache.efl,
+ 0);
+ }
+
+ /* Modification Time message size */
+ if ((H5O_OH_GET_VERSION(ohdr) > 1) && /* TODO: H5O_VERSION_1 in H5Opkg.h */
+ (H5O_HDR_STORE_TIMES & H5O_OH_GET_FLAGS(ohdr)))
+ {
+ time_t mtime = H5O_OH_GET_MTIME(ohdr);
+ ret_value += H5O_msg_size_oh(
+ file,
+ ohdr,
+ H5O_MTIME_NEW_ID,
+ &mtime,
+ 0);
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5D__calculate_minimum_header_size */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__prepare_minimized_oh
+ *
+ * Purpose: Create an object header (H5O_t) allocated with the smallest
+ * possible size.
+ *
+ * Return: Success: SUCCEED (0) (non-negative value)
+ * Failure: FAIL (-1) (negative value)
+ *
+ * Programmer: Jacob Smith
+ * 16 August 2018
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__prepare_minimized_oh( \
+ H5F_t *file, \
+ H5D_t *dset, \
+ H5O_loc_t *oloc)
+{
+ H5O_t *oh = NULL;
+ size_t ohdr_size = 0;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT;
+
+ HDassert(file);
+ HDassert(dset);
+ HDassert(oloc);
+
+ oh = H5O__create_ohdr(file, dset->shared->dcpl_id);
+ if (NULL == oh)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL,
+ "can't instantiate object header")
+
+ ohdr_size = H5D__calculate_minimum_header_size(file, dset, oh);
+
+ if (FAIL == H5O__apply_ohdr(
+ file,
+ oh,
+ dset->shared->dcpl_id,
+ ohdr_size,
+ (size_t)1,
+ oloc))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL,
+ "can't apply object header to file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5D_prepare_minimized_oh */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D__update_oh_info
*
* Purpose: Create and fill object header for dataset
@@ -683,6 +951,7 @@ H5D__update_oh_info(H5F_t *file, H5D_t *dset, hid_t dapl_id)
hbool_t fill_changed = FALSE; /* Flag indicating the fill value was changed */
hbool_t layout_init = FALSE; /* Flag to indicate that chunk information was initialized */
hbool_t use_at_least_v18; /* Flag indicating to use at least v18 format versions */
+ hbool_t minimize_header = FALSE;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -751,19 +1020,42 @@ H5D__update_oh_info(H5F_t *file, H5D_t *dset, hid_t dapl_id)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set fill value info")
} /* end if */
- /* Add the dataset's raw data size to the size of the header, if the raw data will be stored as compact */
- if(layout->type == H5D_COMPACT)
- ohdr_size += layout->storage.u.compact.size;
+ if (FAIL == H5D__use_minimized_dset_headers(file, dset, &minimize_header))
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL,
+ "can't get minimize settings")
+ if (TRUE == minimize_header) {
+ if (FAIL == H5D__prepare_minimized_oh(file, dset, oloc))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
+ "can't create minimized dataset object header")
+ } else {
+ /* Add the dataset's raw data size to the size of the header, if the
+ * raw data will be stored as compact
+ */
+ if (H5D_COMPACT == layout->type)
+ ohdr_size += layout->storage.u.compact.size;
+
+ /* Create an object header for the dataset */
+ if (0 > H5O_create(
+ file,
+ ohdr_size,
+ (size_t)1,
+ dset->shared->dcpl_id,
+ oloc/*out*/))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
+ "unable to create dataset object header")
+ } /* If use minimum/standard object header space */
- /* Create an object header for the dataset */
- if(H5O_create(file, ohdr_size, (size_t)1, dset->shared->dcpl_id, oloc/*out*/) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset object header")
HDassert(file == dset->oloc.file);
/* Pin the object header */
if(NULL == (oh = H5O_pin(oloc)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header")
+#if 0
+ HDprintf("DATATYPE SIZE: %lu\n",
+ H5O_msg_size_oh(file, oh, H5O_DTYPE_ID, type, 0));
+#endif /* TESTING DEBUG */
+
/* Write the dataspace header message */
if(H5S_append(file, oh, dset->shared->space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update dataspace header message")
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index cbee0de..e136c80 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -45,6 +45,7 @@
#define H5D_CRT_FILL_VALUE_NAME "fill_value" /* Fill value */
#define H5D_CRT_ALLOC_TIME_STATE_NAME "alloc_time_state" /* Space allocation time state */
#define H5D_CRT_EXT_FILE_LIST_NAME "efl" /* External file list */
+#define H5D_CRT_MIN_DSET_HDR_SIZE_NAME "dset_oh_minimize"/* Minimize object header */
/* ======== Dataset access property names ======== */
#define H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME "rdcc_nslots" /* Size of raw data chunk cache(slots) */
diff --git a/src/H5F.c b/src/H5F.c
index 01fd7db..7e206bb 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1713,3 +1713,97 @@ H5Fincrement_filesize(hid_t file_id, hsize_t increment)
done:
FUNC_LEAVE_API(ret_value)
} /* H5Fincrement_filesize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Fget_dset_no_attrs_hint
+ *
+ * Purpose:
+ *
+ * Get the file-level setting to create minimized dataset object headers.
+ * Result is stored at pointer `minimize`.
+ *
+ * Return:
+ *
+ * Success: SUCCEED (0) (non-negative value)
+ * Failure: FAIL (-1) (negative value)
+ *
+ * Programmer:
+ *
+ * Jacob Smith
+ * 15 August 2018
+ *
+ * Changes: None.
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fget_dset_no_attrs_hint(hid_t file_id,
+ hbool_t *minimize)
+{
+ H5F_t *f = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*b", file_id, minimize);
+
+ if (NULL == minimize)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "out pointer 'minimize' cannot be NULL")
+
+ f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE);
+ if (NULL == f)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "can't get file from id")
+
+ HDassert(f->shared);
+
+ *minimize = f->shared->crt_dset_min_ohdr_flag;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Fget_dset_no_attrs_hint */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Fset_dset_no_attrs_hint
+ *
+ * Purpose:
+ *
+ * Set the file-level setting to create minimized dataset object headers.
+ *
+ * Return:
+ *
+ * Success: SUCCEED (0) (non-negative value)
+ * Failure: FAIL (-1) (negative value)
+ *
+ * Programmer:
+ *
+ * Jacob Smith
+ * 15 August 2018
+ *
+ * Changes: None.
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fset_dset_no_attrs_hint(hid_t file_id,
+ hbool_t minimize)
+{
+ H5F_t *f = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "ib", file_id, minimize);
+
+ f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE);
+ if (NULL == f)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "can't get file from id")
+
+ HDassert(f->shared);
+
+ f->shared->crt_dset_min_ohdr_flag = minimize;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Fset_dset_no_attrs_hint */
+
diff --git a/src/H5Fint.c b/src/H5Fint.c
index abc638a..c3fe07a 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -880,6 +880,9 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_
/* intialize point of no return */
f->shared->point_of_no_return = FALSE;
+ /* set default value for minimizing dataset object headers */
+ f->shared->crt_dset_min_ohdr_flag = FALSE;
+
/* Copy the file creation and file access property lists into the
* new file handle. We do this early because some values might need
* to change as the file is being opened.
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 2ab41de..edbd460 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -353,6 +353,7 @@ struct H5F_file_t {
/* Object flush info */
H5F_object_flush_t object_flush; /* Information for object flush callback */
+ hbool_t crt_dset_min_ohdr_flag; /* flag to minimize created dataset object header */
};
/*
diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h
index 73c59f5..6274eb0 100644
--- a/src/H5Fpublic.h
+++ b/src/H5Fpublic.h
@@ -273,6 +273,8 @@ H5_DLL herr_t H5Freset_page_buffering_stats(hid_t file_id);
H5_DLL herr_t H5Fget_page_buffering_stats(hid_t file_id, unsigned accesses[2],
unsigned hits[2], unsigned misses[2], unsigned evictions[2], unsigned bypasses[2]);
H5_DLL herr_t H5Fget_mdc_image_info(hid_t file_id, haddr_t *image_addr, hsize_t *image_size);
+H5_DLL herr_t H5Fget_dset_no_attrs_hint(hid_t file_id, hbool_t *minimize);
+H5_DLL herr_t H5Fset_dset_no_attrs_hint(hid_t file_id, hbool_t minimize);
#ifdef H5_HAVE_PARALLEL
H5_DLL herr_t H5Fset_mpi_atomicity(hid_t file_id, hbool_t flag);
diff --git a/src/H5Oint.c b/src/H5Oint.c
index 2752a25..1d07415 100644
--- a/src/H5Oint.c
+++ b/src/H5Oint.c
@@ -83,7 +83,6 @@ static herr_t H5O__visit_cb(hid_t group, const char *name, const H5L_info_t *lin
void *_udata);
static const H5O_obj_class_t *H5O__obj_class_real(const H5O_t *oh);
-
/*********************/
/* Package Variables */
/*********************/
@@ -277,130 +276,276 @@ done:
* matzke@llnl.gov
* Aug 5 1997
*
+ * Changes: 17 August 2018
+ * Jacob Smith
+ * Refactor out the operations into two separate steps --
+ * preparation and application -- to facilitate overriding the
+ * library-default size allocated for the object header. This
+ * function is retained as a wrapper, to minimize changes to
+ * unaffected calling functions.
+ *
*-------------------------------------------------------------------------
*/
herr_t
-H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id,
- H5O_loc_t *loc/*out*/)
+H5O_create( \
+ H5F_t *f, \
+ size_t size_hint, \
+ size_t initial_rc, \
+ hid_t ocpl_id, \
+ H5O_loc_t *loc) /*out*/
{
- H5P_genplist_t *oc_plist; /* Object creation property list */
- H5O_t *oh = NULL; /* Object header created */
- haddr_t oh_addr; /* Address of initial object header */
- size_t oh_size; /* Size of initial object header */
- uint8_t oh_flags; /* Object header's initial status flags */
- unsigned insert_flags = H5AC__NO_FLAGS_SET; /* Flags for inserting object header into cache */
- hbool_t store_msg_crt_idx; /* Whether to always store message creation indices for this file */
- herr_t ret_value = SUCCEED; /* return value */
+ H5O_t *oh = NULL;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
- /* check args */
HDassert(f);
HDassert(loc);
HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
+ /* create object header in freelist
+ * header version is set internally
+ */
+ oh = H5O__create_ohdr(f, ocpl_id);
+ if (NULL == oh)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL,
+ "Can't instantiate object header")
+
+ /* apply object header information to file
+ */
+ if (0 > H5O__apply_ohdr(
+ f,
+ oh,
+ ocpl_id,
+ size_hint,
+ initial_rc,
+ loc))
+ {
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL,
+ "Can't apply object header to file")
+ }
+
+done:
+ if (FAIL == ret_value &&
+ NULL != oh &&
+ 0 > H5O__free(oh))
+ {
+ HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL,
+ "can't delete object header")
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_create() */
+
+
+/*-----------------------------------------------------------------------------
+ * Function: H5O__create_ohdr
+ *
+ * Purpose: Create the object header, set version and flags.
+ *
+ * Return: Success: Pointer to the newly-crated header object.
+ * Failure: NULL
+ *
+ * Programmer: Jacob Smith
+ * 17 August 2018
+ *
+ *-----------------------------------------------------------------------------
+ */
+H5O_t *
+H5O__create_ohdr( \
+ H5F_t *f, \
+ hid_t ocpl_id)
+{
+ H5P_genplist_t *oc_plist;
+ H5O_t *oh = NULL; /* Object header in Freelist */
+ uint8_t oh_flags; /* Initial status flags */
+ H5O_t *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ HDassert(f);
+ HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
+
/* Check for invalid access request */
- if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "no write intent on file")
+ if (0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
+ "no write intent on file")
- /* Make certain we allocate at least a reasonable size for the object header */
- size_hint = H5O_ALIGN_F(f, MAX(H5O_MIN_SIZE, size_hint));
+ oh = H5FL_CALLOC(H5O_t);
+ if (NULL == oh)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
+ "memory allocation failed")
- /* Get the property list */
- if(NULL == (oc_plist = (H5P_genplist_t *)H5I_object(ocpl_id)))
- HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property list")
+ oc_plist = (H5P_genplist_t *)H5I_object(ocpl_id);
+ if (NULL == oc_plist)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, NULL,
+ "not a property list")
/* Get any object header status flags set by properties */
- if(H5P_get(oc_plist, H5O_CRT_OHDR_FLAGS_NAME, &oh_flags) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object header flags")
+ if (0 > H5P_get(oc_plist, H5O_CRT_OHDR_FLAGS_NAME, &oh_flags))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL,
+ "can't get object header flags")
- /* Allocate the object header and zero out header fields */
- if(NULL == (oh = H5FL_CALLOC(H5O_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if (0 > H5O_set_version(f, oh, oh_flags, H5F_STORE_MSG_CRT_IDX(f)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, NULL,
+ "can't set version of object header")
- /* Initialize file-specific information for object header */
- store_msg_crt_idx = H5F_STORE_MSG_CRT_IDX(f);
+ oh->flags = oh_flags;
- if(H5O_set_version(f, oh, oh_flags, store_msg_crt_idx) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set version of objecdt header")
+ ret_value = oh;
+
+done:
+ if (NULL == ret_value &&
+ NULL != oh &&
+ 0 > H5O__free(oh))
+ {
+ HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, NULL,
+ "can't delete object header")
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O__create_ohdr */
+
+
+/*-----------------------------------------------------------------------------
+ * Function: H5O__apply_ohdr
+ *
+ * Purpose: Initialize and set the object header in the file.
+ * Record some information at `loc_out`.
+ *
+ * Return: Success: SUCCEED (0) (non-negative value)
+ * Failure: FAI (-1) (negative value)
+ *
+ * Programmer: Jacob Smith
+ * 17 August 2018
+ *
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5O__apply_ohdr( \
+ H5F_t *f, \
+ H5O_t *oh, \
+ hid_t ocpl_id, \
+ size_t size_hint, \
+ size_t initial_rc, \
+ H5O_loc_t *loc_out)
+{
+ haddr_t oh_addr;
+ size_t oh_size;
+ H5P_genplist_t *oc_plist = NULL;
+ unsigned insert_flags = H5AC__NO_FLAGS_SET;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(f);
+ HDassert(loc_out);
+ HDassert(oh);
+ HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
+
+ /* Allocate at least a reasonable size for the object header */
+ size_hint = H5O_ALIGN_F(f, MAX(H5O_MIN_SIZE, size_hint));
oh->sizeof_size = H5F_SIZEOF_SIZE(f);
oh->sizeof_addr = H5F_SIZEOF_ADDR(f);
- oh->swmr_write = !!(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE);
+ oh->swmr_write = !!(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE); /* funky cast */
+
#ifdef H5O_ENABLE_BAD_MESG_COUNT
- /* Check whether the "bad message count" property is set */
- if(H5P_exist_plist(oc_plist, H5O_BAD_MESG_COUNT_NAME) > 0) {
- /* Retrieve bad message count flag */
- if(H5P_get(oc_plist, H5O_BAD_MESG_COUNT_NAME, &oh->store_bad_mesg_count) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get bad message count flag")
+ if (0 < H5P_exist_plist(oc_plist, H5O_BAD_MESG_COUNT_NAME)) {
+ /* Set bad message count flag -- from property list */
+ if (0 > H5P_get(oc_plist,
+ H5O_BAD_MESG_COUNT_NAME,
+ &oh->store_bad_mesg_count))
+ {
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL,
+ "can't get bad message count flag")
+ }
}
#endif /* H5O_ENABLE_BAD_MESG_COUNT */
/* Create object header proxy if doing SWMR writes */
- if(oh->swmr_write) {
- /* Create virtual entry, for use as proxy */
- if(NULL == (oh->proxy = H5AC_proxy_entry_create()))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create object header proxy")
- }
- else
+ if (oh->swmr_write) {
+ oh->proxy = H5AC_proxy_entry_create();
+ if (NULL == oh->proxy)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL,
+ "can't create object header proxy")
+ } else {
oh->proxy = NULL;
+ }
- /* Set initial status flags */
- oh->flags = oh_flags;
+ oc_plist = (H5P_genplist_t *)H5I_object(ocpl_id);
+ if (NULL == oc_plist)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL,
+ "not a property list")
/* Initialize version-specific fields */
- if(oh->version > H5O_VERSION_1) {
- /* Initialize all time fields with current time, if we are storing them */
- if(oh->flags & H5O_HDR_STORE_TIMES)
+ if (oh->version > H5O_VERSION_1) {
+ /* Initialize all time fields */
+ if (oh->flags & H5O_HDR_STORE_TIMES)
oh->atime = oh->mtime = oh->ctime = oh->btime = H5_now();
else
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
- /* Make certain attribute creation order tracking is enabled if
- * attributes can be shared in this file.
- */
- if(store_msg_crt_idx)
+ if (H5F_STORE_MSG_CRT_IDX(f))
+ /* flag to record message creation indices */
oh->flags |= H5O_HDR_ATTR_CRT_ORDER_TRACKED;
- /* Retrieve attribute storage phase change values from property list */
- if(H5P_get(oc_plist, H5O_CRT_ATTR_MAX_COMPACT_NAME, &oh->max_compact) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get max. # of compact attributes")
- if(H5P_get(oc_plist, H5O_CRT_ATTR_MIN_DENSE_NAME, &oh->min_dense) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get min. # of dense attributes")
+ /* Set attribute storage phase change values -- from property list */
+ if (0 > H5P_get(oc_plist,
+ H5O_CRT_ATTR_MAX_COMPACT_NAME,
+ &oh->max_compact))
+ {
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL,
+ "can't get max. # of compact attributes")
+ }
+ if (0 > H5P_get(oc_plist,
+ H5O_CRT_ATTR_MIN_DENSE_NAME,
+ &oh->min_dense))
+ {
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL,
+ "can't get min. # of dense attributes")
+ }
/* Check for non-default attribute storage phase change values */
- if(oh->max_compact != H5O_CRT_ATTR_MAX_COMPACT_DEF || oh->min_dense != H5O_CRT_ATTR_MIN_DENSE_DEF)
+ if (H5O_CRT_ATTR_MAX_COMPACT_DEF != oh->max_compact || \
+ H5O_CRT_ATTR_MIN_DENSE_DEF != oh->min_dense )
+ {
oh->flags |= H5O_HDR_ATTR_STORE_PHASE_CHANGE;
+ }
/* Determine correct value for chunk #0 size bits */
/* Avoid compiler warning on 32-bit machines */
#if H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T
- if(size_hint > 4294967295UL)
+ if (size_hint > 4294967295UL)
oh->flags |= H5O_HDR_CHUNK0_8;
else
#endif /* H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T */
- if(size_hint > 65535)
+ if (size_hint > 65535)
oh->flags |= H5O_HDR_CHUNK0_4;
- else if(size_hint > 255)
+ else if (size_hint > 255)
oh->flags |= H5O_HDR_CHUNK0_2;
- } /* end if */
- else {
+ } else {
/* Reset unused time fields */
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
- } /* end else */
+ } /* end if/else header version >1 */
/* Compute total size of initial object header */
/* (i.e. object header prefix and first chunk) */
oh_size = (size_t)H5O_SIZEOF_HDR(oh) + size_hint;
/* Allocate disk space for header and first chunk */
- if(HADDR_UNDEF == (oh_addr = H5MF_alloc(f, H5FD_MEM_OHDR, (hsize_t)oh_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header")
+ oh_addr = H5MF_alloc(f, H5FD_MEM_OHDR, (hsize_t)oh_size);
+ if (HADDR_UNDEF == oh_addr)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "file allocation failed for object header")
/* Create the chunk list */
- oh->nchunks = oh->alloc_nchunks = 1;
- if(NULL == (oh->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->alloc_nchunks)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ oh->nchunks = 1;
+ oh->alloc_nchunks = 1;
+ oh->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->alloc_nchunks);
+ if (NULL == oh->chunk)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "memory allocation failed")
/* Initialize the first chunk */
oh->chunk[0].addr = oh_addr;
@@ -409,30 +554,37 @@ H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id,
/* Allocate enough space for the first chunk */
/* (including space for serializing the object header prefix */
- if(NULL == (oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, oh_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, oh_size);
+ if(NULL == oh->chunk[0].image)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "memory allocation failed")
oh->chunk[0].chunk_proxy = NULL;
/* Put magic # for object header in first chunk */
- if(oh->version > H5O_VERSION_1)
+ if (H5O_VERSION_1 < oh->version)
HDmemcpy(oh->chunk[0].image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
/* Create the message list */
oh->nmesgs = 1;
oh->alloc_nmesgs = H5O_NMESGS;
- if(NULL == (oh->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh->alloc_nmesgs)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ oh->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh->alloc_nmesgs);
+ if (NULL == oh->mesg)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "memory allocation failed")
- /* Initialize the initial "null" message, covering the entire first chunk */
+ /* Initialize the initial "null" message; covers the entire first chunk */
oh->mesg[0].type = H5O_MSG_NULL;
oh->mesg[0].dirty = TRUE;
oh->mesg[0].native = NULL;
- oh->mesg[0].raw = oh->chunk[0].image + (H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)) + H5O_SIZEOF_MSGHDR_OH(oh);
+ oh->mesg[0].raw = oh->chunk[0].image \
+ + H5O_SIZEOF_HDR(oh) \
+ - H5O_SIZEOF_CHKSUM_OH(oh) \
+ + H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[0].raw_size = size_hint - (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[0].chunkno = 0;
/* Check for non-zero initial refcount on the object header */
- if(initial_rc > 0) {
+ if (initial_rc > 0) {
/* Set the initial refcount & pin the header when its inserted */
oh->rc = initial_rc;
insert_flags |= H5AC__PIN_ENTRY_FLAG;
@@ -442,9 +594,11 @@ H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id,
H5_BEGIN_TAG(oh_addr);
/* Cache object header */
- if(H5AC_insert_entry(f, H5AC_OHDR, oh_addr, oh, insert_flags) < 0)
- HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header")
+ if (0 > H5AC_insert_entry(f, H5AC_OHDR, oh_addr, oh, insert_flags))
+ HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTINSERT, FAIL,
+ "unable to cache object header")
+ /* TODO: is this relevant to the BEGIN/END TAG region? if not, delete */
/* Reset object header pointer, now that it's been inserted into the cache */
oh = NULL;
@@ -452,20 +606,16 @@ H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id,
H5_END_TAG
/* Set up object location */
- loc->file = f;
- loc->addr = oh_addr;
+ loc_out->file = f;
+ loc_out->addr = oh_addr;
- /* Open it */
- if(H5O_open(loc) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object header")
+ if (0 > H5O_open(loc_out))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL,
+ "unable to open object header")
done:
- if(ret_value < 0 && oh)
- if(H5O__free(oh) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_create() */
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5O__apply_ohdr */
/*-------------------------------------------------------------------------
@@ -2686,6 +2836,64 @@ H5O_get_oh_addr(const H5O_t *oh)
/*-------------------------------------------------------------------------
+ * Function: H5O_get_oh_flags
+ *
+ * Programmer: Jacob Smith
+ * 17 August 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+uint8_t
+H5O_get_oh_flags(const H5O_t *oh)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+ HDassert(oh);
+ HDassert(oh->flags);
+ FUNC_LEAVE_NOAPI(oh->flags);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_get_oh_mtime
+ *
+ * Purpose: Retrieve an object's modification time. Assumes that the
+ * caller has verified that accessing this variable is appropriate
+ * to the header in question.
+ *
+ * Programmer: Jacob Smith
+ * 17 August 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+time_t
+H5O_get_oh_mtime(const H5O_t *oh)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+ HDassert(oh);
+ HDassert(oh->mtime);
+ FUNC_LEAVE_NOAPI(oh->mtime);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_get_oh_version
+ *
+ * Programmer: Jacob Smith
+ * 17 August 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+uint8_t
+H5O_get_oh_version(const H5O_t *oh)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+ HDassert(oh);
+ HDassert(oh->version);
+ FUNC_LEAVE_NOAPI(oh->version);
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_get_rc_and_type
*
* Purpose: Retrieve an object's reference count and type
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 10063d5..f8154c4 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -120,8 +120,14 @@ typedef struct H5O_mesg_t H5O_mesg_t;
/* If the module using this macro is allowed access to the private variables, access them directly */
#ifdef H5O_MODULE
#define H5O_OH_GET_ADDR(O) ((O)->chunk[0].addr)
+#define H5O_OH_GET_VERSION(O) ((O)->version)
+#define H5O_OH_GET_FLAGS(O) ((O)->flags)
+#define H5O_OH_GET_MTIME(O) ((O)->mtime)
#else /* H5O_MODULE */
#define H5O_OH_GET_ADDR(O) (H5O_get_oh_addr(O))
+#define H5O_OH_GET_VERSION(O) (H5O_get_oh_version(O))
+#define H5O_OH_GET_FLAGS(O) (H5O_get_oh_flags(O))
+#define H5O_OH_GET_MTIME(O) (H5O_get_oh_mtime(O))
#endif /* H5O_MODULE */
/* Set the fields in a shared message structure */
@@ -865,6 +871,9 @@ struct H5P_genplist_t;
H5_DLL herr_t H5O_init(void);
H5_DLL herr_t H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc,
hid_t ocpl_id, H5O_loc_t *loc/*out*/);
+H5_DLL H5O_t *H5O__create_ohdr(H5F_t *f, hid_t ocpl_id);
+H5_DLL herr_t H5O__apply_ohdr(H5F_t *f, H5O_t *oh, hid_t ocpl_id,
+ size_t size_hint, size_t initial_rc, H5O_loc_t *loc_out);
H5_DLL herr_t H5O_open(H5O_loc_t *loc);
H5_DLL herr_t H5O_close(H5O_loc_t *loc, hbool_t *file_closed/*out*/);
H5_DLL int H5O_link(const H5O_loc_t *loc, int adjust);
@@ -888,6 +897,9 @@ H5_DLL hid_t H5O_open_name(const H5G_loc_t *loc, const char *name, hbool_t app_r
H5_DLL herr_t H5O_get_nlinks(const H5O_loc_t *loc, hsize_t *nlinks);
H5_DLL void *H5O_obj_create(H5F_t *f, H5O_type_t obj_type, void *crt_info, H5G_loc_t *obj_loc);
H5_DLL haddr_t H5O_get_oh_addr(const H5O_t *oh);
+H5_DLL uint8_t H5O_get_oh_flags(const H5O_t *oh);
+H5_DLL time_t H5O_get_oh_mtime(const H5O_t *oh);
+H5_DLL uint8_t H5O_get_oh_version(const H5O_t *oh);
H5_DLL herr_t H5O_get_rc_and_type(const H5O_loc_t *oloc, unsigned *rc, H5O_type_t *otype);
H5_DLL H5AC_proxy_entry_t *H5O_get_proxy(const H5O_t *oh);
diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c
index cb13ff3..a1799ad 100644
--- a/src/H5Pdcpl.c
+++ b/src/H5Pdcpl.c
@@ -119,6 +119,11 @@
#define H5D_CRT_EXT_FILE_LIST_COPY H5P__dcrt_ext_file_list_copy
#define H5D_CRT_EXT_FILE_LIST_CMP H5P__dcrt_ext_file_list_cmp
#define H5D_CRT_EXT_FILE_LIST_CLOSE H5P__dcrt_ext_file_list_close
+/* Definitions for dataset object header minimization */
+#define H5D_CRT_MIN_DSET_HDR_SIZE_SIZE sizeof(hbool_t)
+#define H5D_CRT_MIN_DSET_HDR_SIZE_DEF FALSE
+#define H5D_CRT_MIN_DSET_HDR_SIZE_ENC H5P__encode_hbool_t
+#define H5D_CRT_MIN_DSET_HDR_SIZE_DEC H5P__decode_hbool_t
/******************/
@@ -211,6 +216,7 @@ static const H5O_layout_t H5D_def_layout_g = H5D_CRT_LAYOUT_DEF; /* Defau
static const H5O_fill_t H5D_def_fill_g = H5D_CRT_FILL_VALUE_DEF; /* Default fill value */
static const unsigned H5D_def_alloc_time_state_g = H5D_CRT_ALLOC_TIME_STATE_DEF; /* Default allocation time state */
static const H5O_efl_t H5D_def_efl_g = H5D_CRT_EXT_FILE_LIST_DEF; /* Default external file list */
+static const H5O_ohdr_min_g = H5D_CRT_MIN_DSET_HDR_SIZE_DEF; /* Default object header minimization */
/* Defaults for each type of layout */
#ifdef H5_HAVE_C99_DESIGNATED_INITIALIZER
@@ -270,6 +276,26 @@ H5P__dcrt_reg_prop(H5P_genclass_t *pclass)
H5D_CRT_EXT_FILE_LIST_DEL, H5D_CRT_EXT_FILE_LIST_COPY, H5D_CRT_EXT_FILE_LIST_CMP, H5D_CRT_EXT_FILE_LIST_CLOSE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register the object header minimization property */
+ if (0 > H5P_register_real(
+ pclass, /* class */
+ H5D_CRT_MIN_DSET_HDR_SIZE_NAME, /* name */
+ H5D_CRT_MIN_DSET_HDR_SIZE_SIZE, /* size */
+ &H5O_ohdr_min_g, /* default */
+ NULL, /* create */
+ NULL, /* set */
+ NULL, /* get */
+ H5D_CRT_MIN_DSET_HDR_SIZE_ENC, /* encode */
+ H5D_CRT_MIN_DSET_HDR_SIZE_DEC, /* decode */
+ NULL, /* delete */
+ NULL, /* copy */
+ NULL, /* compare */
+ NULL)) /* close */
+ {
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL,
+ "can't insert property into class")
+ }
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P__dcrt_reg_prop() */
@@ -3733,3 +3759,103 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_fill_time() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5Pget_dset_no_attrs_hint
+ *
+ * Purpose:
+ *
+ * Access the flag for whether or not datasets created by the given dcpl
+ * will be created with a "minimized" object header.
+ *
+ * Return:
+ *
+ * Failure: Negative value (FAIL)
+ * Success: Non-negative value (SUCCEED)
+ *
+ * Programmer: Jacob Smith
+ * 14 August 2018
+ *
+ * Modifications: None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_dset_no_attrs_hint(hid_t dcpl_id,
+ hbool_t *minimize)
+{
+ hbool_t setting = FALSE;
+ H5P_genplist_t *plist = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*b", dcpl_id, minimize);
+
+ if (NULL == minimize)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "receiving pointer cannot be NULL")
+
+ plist = H5P_object_verify(dcpl_id, H5P_DATASET_CREATE);
+ if (NULL == plist)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL,
+ "can't find object for ID")
+
+ if (0 > H5P_peek(plist, H5D_CRT_MIN_DSET_HDR_SIZE_NAME, &setting))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL,
+ "can't get dset oh minimize flag value")
+
+ *minimize = setting;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pget_dset_no_attrs_hint */
+
+
+/*-----------------------------------------------------------------------------
+ * Function: H5Pset_dset_no_attrs_hint
+ *
+ * Purpose:
+ *
+ * Set the dcpl to minimize (or explicitly to not minimized) dataset object
+ * headers upon creation.
+ *
+ * Return:
+ *
+ * Failure: Negative value (FAIL)
+ * Success: Non-negative value (SUCCEED)
+ *
+ * Programmer: Jacob Smith
+ * 14 August 2018
+ *
+ * Modifications: None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_dset_no_attrs_hint(hid_t dcpl_id,
+ hbool_t minimize)
+{
+ H5P_genplist_t *plist = NULL;
+ hbool_t prev_set = FALSE;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "ib", dcpl_id, minimize);
+
+ plist = H5P_object_verify(dcpl_id, H5P_DATASET_CREATE);
+ if (NULL == plist)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL,
+ "can't find object for ID")
+
+ if (0 > H5P_peek(plist, H5D_CRT_MIN_DSET_HDR_SIZE_NAME, &prev_set))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL,
+ "can't get extant dset oh minimize flag value")
+
+ if (0 > H5P_poke(plist, H5D_CRT_MIN_DSET_HDR_SIZE_NAME, &minimize))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL,
+ "can't get dset oh minimize flag value")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pset_dset_no_attrs_hint */
+
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index c5596e5..c2f9b4c 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -409,6 +409,8 @@ H5_DLL herr_t H5Pget_alloc_time(hid_t plist_id, H5D_alloc_time_t
H5_DLL herr_t H5Pset_fill_time(hid_t plist_id, H5D_fill_time_t fill_time);
H5_DLL herr_t H5Pget_fill_time(hid_t plist_id, H5D_fill_time_t
*fill_time/*out*/);
+H5_DLL herr_t H5Pget_dset_no_attrs_hint(hid_t dcpl_id, hbool_t *minimize);
+H5_DLL herr_t H5Pset_dset_no_attrs_hint(hid_t dcpl_id, hbool_t minimize);
/* Dataset access property list (DAPL) routines */
H5_DLL herr_t H5Pset_chunk_cache(hid_t dapl_id, size_t rdcc_nslots,
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 517a620..6c1e0eb 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -234,6 +234,7 @@ set (H5_TESTS
cache_logging
cork
swmr
+ ohdr_min
)
macro (ADD_H5_EXE file)
diff --git a/test/CMakeTests.cmake b/test/CMakeTests.cmake
index cc6ebb8..44494e9 100644
--- a/test/CMakeTests.cmake
+++ b/test/CMakeTests.cmake
@@ -359,6 +359,8 @@ set (test_CLEANFILES
lheap.h5
fheap.h5
ohdr.h5
+ ohdr_min_a.h5
+ ohdr_min_b.h5
stab.h5
extern_*.h5
extern_*.raw
diff --git a/test/Makefile.am b/test/Makefile.am
index b9aa3fb..551c5ee 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -52,15 +52,15 @@ check_SCRIPTS = $(TEST_SCRIPT)
# As an exception, long-running tests should occur earlier in the list.
# This gives them more time to run when tests are executing in parallel.
TEST_PROG= testhdf5 \
- cache cache_api cache_image cache_tagging lheap ohdr stab gheap \
- evict_on_close farray earray btree2 fheap \
+ cache cache_api cache_image cache_tagging lheap ohdr ohdr_min stab \
+ gheap evict_on_close farray earray btree2 fheap \
pool accum hyperslab istore bittests dt_arith page_buffer \
dtypes dsets cmpd_dset filter_fail extend direct_chunk external efc \
- objcopy links unlink twriteorder big mtime fillval mount \
- flush1 flush2 app_ref enum set_extent ttsafe enc_dec_plist \
- enc_dec_plist_cross_platform getname vfd ntypes dangle dtransform \
- reserved cross_read freespace mf vds file_image unregister \
- cache_logging cork swmr
+ objcopy links unlink twriteorder big mtime fillval mount \
+ flush1 flush2 app_ref enum set_extent ttsafe enc_dec_plist \
+ enc_dec_plist_cross_platform getname vfd ntypes dangle dtransform \
+ reserved cross_read freespace mf vds file_image unregister \
+ cache_logging cork swmr
# List programs to be built when testing here.
# error_test and err_compat are built at the same time as the other tests, but executed by testerror.sh.
@@ -165,6 +165,7 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse
extend.h5 istore.h5 extlinks*.h5 frspace.h5 links*.h5 \
sys_file1 tfile[1-7].h5 th5s[1-4].h5 lheap.h5 fheap.h5 ohdr.h5 \
stab.h5 extern_[1-5].h5 extern_[1-4][rw].raw gheap[0-4].h5 \
+ ohdr_min_a.h5 ohdr_min_b.h5 \
dt_arith[1-2] links.h5 links[0-6]*.h5 extlinks[0-15].h5 tmp \
big.data big[0-9][0-9][0-9][0-9][0-9].h5 \
stdio.h5 sec2.h5 dtypes[0-9].h5 dtypes1[0].h5 dt_arith[1-2].h5 tattr.h5 \
diff --git a/test/dsets.c b/test/dsets.c
index d23f438..94c967e 100644
--- a/test/dsets.c
+++ b/test/dsets.c
@@ -13034,6 +13034,113 @@ test_versionbounds()
return -1;
} /* test_versionbounds() */
+
+/*-----------------------------------------------------------------------------
+ * Function: test_object_header_minimization_dcpl
+ *
+ * Purpose: Test the "datset object header minimization" property as part of
+ * the DCPL.
+ *
+ * Return: Success/pass: 0
+ * Failure/error: -1
+ *
+ * Programmer: Jacob Smith
+ * 15 Aug 2018
+ *
+ * Changes: None.
+ *-----------------------------------------------------------------------------
+ */
+static herr_t
+test_object_header_minimization_dcpl(void)
+{
+ hid_t dcpl_id = -1;
+ hid_t file_id = -1;
+ hbool_t minimize = FALSE;
+
+ TESTING("dcpl flags to minimize dataset object header");
+
+ /*********/
+ /* SETUP */
+ /*********/
+
+ file_id = H5Fcreate(
+ "some_arbitrary_filename",
+ H5F_ACC_TRUNC,
+ H5P_DEFAULT,
+ H5P_DEFAULT);
+ if (0 > file_id)
+ FAIL_PUTS_ERROR("unable to create test file\n");
+
+ dcpl_id = H5Pcreate(H5P_DATASET_CREATE);
+ if (0 > dcpl_id)
+ FAIL_PUTS_ERROR("unable to create DCPL\n");
+
+ /*********/
+ /* TESTS */
+ /*********/
+
+ /* TEST default value (not set explicitly)
+ */
+ if (FAIL == H5Pget_dset_no_attrs_hint(dcpl_id, &minimize))
+ FAIL_PUTS_ERROR("unable to get minimize value\n");
+ if (FALSE != minimize)
+ FAIL_PUTS_ERROR("Expected FALSE default but was not!\n");
+
+ /* TEST FALSE-set value
+ */
+ if (FAIL == H5Pset_dset_no_attrs_hint(dcpl_id, FALSE))
+ FAIL_PUTS_ERROR("unable to set minimize value to FALSE\n");
+ if (FAIL == H5Pget_dset_no_attrs_hint(dcpl_id, &minimize))
+ FAIL_PUTS_ERROR("unable to get minimize value\n");
+ if (FALSE != minimize)
+ FAIL_PUTS_ERROR("Expected FALSE default but was not!\n");
+
+ /* TEST TRUE-set value
+ */
+ if (FAIL == H5Pset_dset_no_attrs_hint(dcpl_id, TRUE))
+ FAIL_PUTS_ERROR("unable to set minimize value to TRUE\n");
+ if (FAIL == H5Pget_dset_no_attrs_hint(dcpl_id, &minimize))
+ FAIL_PUTS_ERROR("unable to get minimize value\n");
+ if (TRUE != minimize)
+ FAIL_PUTS_ERROR("Expected TRUE default but was not!\n");
+
+ /* TEST error cases
+ */
+ H5E_BEGIN_TRY {
+ if (SUCCEED == H5Pget_dset_no_attrs_hint(-1, &minimize))
+ FAIL_PUTS_ERROR("Invalid DCPL ID should fail\n");
+
+ if (SUCCEED == H5Pset_dset_no_attrs_hint(-1, FALSE))
+ FAIL_PUTS_ERROR("Invalid DCPL ID should fail\n");
+
+ if (SUCCEED == H5Pset_dset_no_attrs_hint(-1, TRUE))
+ FAIL_PUTS_ERROR("Invalid DCPL ID should fail\n");
+
+ if (SUCCEED == H5Pget_dset_no_attrs_hint(dcpl_id, NULL))
+ FAIL_PUTS_ERROR("NULL out pointer should fail\n");
+ } H5E_END_TRY;
+
+ /************/
+ /* TEARDOWN */
+ /************/
+
+ if (FAIL == H5Fclose(file_id))
+ FAIL_PUTS_ERROR("can't close FILE");
+
+ if (FAIL == H5Pclose(dcpl_id))
+ FAIL_PUTS_ERROR("unable to close DCPL\n");
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dcpl_id);
+ H5Fclose(file_id);
+ } H5E_END_TRY;
+ return -1;
+} /* test_object_header_minimization_dcpl */
+
/*-------------------------------------------------------------------------
* Function: main
@@ -13234,6 +13341,8 @@ main(void)
/* Tests version bounds using its own file */
nerrors += (test_versionbounds() < 0 ? 1 : 0);
+ nerrors += (test_object_header_minimization_dcpl() < 0 ? 1 : 0);
+
/* Run misc tests */
nerrors += dls_01_main();
diff --git a/test/enc_dec_plist.c b/test/enc_dec_plist.c
index 36db2d0..cee38f3 100644
--- a/test/enc_dec_plist.c
+++ b/test/enc_dec_plist.c
@@ -146,6 +146,9 @@ main(void)
if((H5Pset_fill_value(dcpl, H5T_NATIVE_DOUBLE, &fill)) < 0)
FAIL_STACK_ERROR
+ if((H5Pset_dset_no_attrs_hint(dcpl, FALSE)) < 0)
+ FAIL_STACK_ERROR
+
max_size[0] = 100;
if((H5Pset_external(dcpl, "ext1.data", (off_t)0,
(hsize_t)(max_size[0] * sizeof(int)/4))) < 0)
diff --git a/test/gen_plist.c b/test/gen_plist.c
index 62693bd..d8096e3 100644
--- a/test/gen_plist.c
+++ b/test/gen_plist.c
@@ -125,6 +125,9 @@ main(void)
if((ret = H5Pset_fill_value(dcpl1, H5T_STD_I32BE, &fill)) < 0)
assert(ret > 0);
+ if((ret = H5Pset_dset_no_attrs_hint(dcpl1, FALSE)) < 0)
+ assert(ret > 0);
+
max_size[0] = 100;
if((ret = H5Pset_external(dcpl1, "ext1.data", (off_t)0,
(hsize_t)(max_size[0] * sizeof(int)/4))) < 0)
diff --git a/test/tfile.c b/test/tfile.c
index d3134f8..96e469c 100644
--- a/test/tfile.c
+++ b/test/tfile.c
@@ -7051,6 +7051,144 @@ test_incr_filesize(void)
/****************************************************************
**
+** test_min_dset_ohdr():
+** Test API calls to toggle dataset object header minimization.
+**
+** TODO (as separate function?):
+** + setting persists between close and (re)open?
+** + dataset header sizes created while changing value of toggle
+**
+****************************************************************/
+static void
+test_min_dset_ohdr(void)
+{
+ const char my_filename[] = "some_arbitrary_filename";
+ hid_t file_id = -1;
+ hid_t file2_id = -1;
+ hbool_t minimize;
+
+ MESSAGE(5, ("Testing dataset object header minimization\n"));
+
+ /*********/
+ /* SETUP */
+ /*********/
+
+ file_id = H5Fcreate(
+ my_filename,
+ H5F_ACC_TRUNC,
+ H5P_DEFAULT,
+ H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fcreate");
+
+ /*********/
+ /* TESTS */
+ /*********/
+
+ /*----------------------------------------
+ * TEST default value
+ */
+ VERIFY(H5Fget_dset_no_attrs_hint(file_id, &minimize),
+ SUCCEED,
+ "H5Fget_dset_no_attrs_hint");
+ VERIFY(minimize,
+ FALSE,
+ "getting default dset minimize flag value");
+
+ /*----------------------------------------
+ * TEST set to TRUE
+ */
+ VERIFY(H5Fset_dset_no_attrs_hint(file_id, TRUE),
+ SUCCEED,
+ "H5Fset_dset_no_attrs_hint");
+ VERIFY(H5Fget_dset_no_attrs_hint(file_id, &minimize),
+ SUCCEED,
+ "H5Fget_dset_no_attrs_hint");
+ VERIFY(minimize,
+ TRUE,
+ "getting set-TRUE dset minimize flag value");
+
+ /*----------------------------------------
+ * TEST second file open on same filename
+ */
+ file2_id = H5Fopen(
+ my_filename,
+ H5F_ACC_RDWR,
+ H5P_DEFAULT);
+ CHECK_I(file2_id, "H5Fopen");
+
+ /* verify TRUE setting on second open */
+ VERIFY(H5Fget_dset_no_attrs_hint(file_id, &minimize),
+ SUCCEED,
+ "H5Fget_dset_no_attrs_hint");
+ VERIFY(minimize,
+ TRUE,
+ "getting set-TRUE dset minimize flag value");
+
+ /* re-set to FALSE on first open */
+ VERIFY(H5Fset_dset_no_attrs_hint(file_id, FALSE),
+ SUCCEED,
+ "H5Fset_dset_no_attrs_hint");
+
+ /* verify FALSE set on both opens */
+ VERIFY(H5Fget_dset_no_attrs_hint(file_id, &minimize),
+ SUCCEED,
+ "H5Fget_dset_no_attrs_hint");
+ VERIFY(minimize,
+ FALSE,
+ "getting set-FALSE dset minimize flag value");
+ VERIFY(H5Fget_dset_no_attrs_hint(file2_id, &minimize),
+ SUCCEED,
+ "H5Fget_dset_no_attrs_hint");
+ VERIFY(minimize,
+ FALSE,
+ "getting set-FALSE dset minimize flag value");
+
+ /* re-set to TRUE on second open */
+ VERIFY(H5Fset_dset_no_attrs_hint(file2_id, TRUE),
+ SUCCEED,
+ "H5Fset_dset_no_attrs_hint");
+
+ /* verify TRUE set on both opens */
+ VERIFY(H5Fget_dset_no_attrs_hint(file_id, &minimize),
+ SUCCEED,
+ "H5Fget_dset_no_attrs_hint");
+ VERIFY(minimize,
+ TRUE,
+ "getting set-FALSE dset minimize flag value");
+ VERIFY(H5Fget_dset_no_attrs_hint(file2_id, &minimize),
+ SUCCEED,
+ "H5Fget_dset_no_attrs_hint");
+ VERIFY(minimize,
+ TRUE,
+ "getting set-FALSE dset minimize flag value");
+
+ /*----------------------------------------
+ * TEST error cases
+ */
+ H5E_BEGIN_TRY {
+ VERIFY(H5Fset_dset_no_attrs_hint(-1, TRUE),
+ FAIL,
+ "trying to set with invalid file ID");
+
+ VERIFY(H5Fget_dset_no_attrs_hint(-1, &minimize),
+ FAIL,
+ "trying to get with invalid file ID");
+
+ VERIFY(H5Fget_dset_no_attrs_hint(file_id, NULL),
+ FAIL,
+ "trying to get with invalid pointer");
+ } H5E_END_TRY;
+
+ /************/
+ /* TEARDOWN */
+ /************/
+
+ VERIFY(H5Fclose(file_id), SUCCEED, "H5Fclose");
+ VERIFY(H5Fclose(file2_id), SUCCEED, "H5Fclose");
+} /* end test_min_dset_ohdr() */
+
+/****************************************************************
+**
** test_deprec():
** Test deprecated functionality.
**
@@ -7336,6 +7474,7 @@ test_file(void)
test_libver_macros(); /* Test the macros for library version comparison */
test_libver_macros2(); /* Test the macros for library version comparison */
test_incr_filesize(); /* Test H5Fincrement_filesize() and H5Fget_eoa() */
+ test_min_dset_ohdr(); /* Test datset object header minimization */
#ifndef H5_NO_DEPRECATED_SYMBOLS
test_deprec(); /* Test deprecated routines */
#endif /* H5_NO_DEPRECATED_SYMBOLS */