summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--src/H5AC.c4
-rw-r--r--src/H5ACprivate.h2
-rw-r--r--src/H5Cprivate.h2
-rw-r--r--src/H5Ctag.c14
-rw-r--r--src/H5D.c20
-rw-r--r--src/H5Dint.c37
-rw-r--r--src/H5Dpkg.h1
-rw-r--r--src/H5Dtest.c41
-rw-r--r--src/H5Fint.c16
-rw-r--r--src/H5Fio.c2
-rw-r--r--src/H5Fpkg.h1
-rw-r--r--src/H5Fprivate.h4
-rw-r--r--src/H5Fquery.c27
-rw-r--r--src/H5G.c4
-rw-r--r--src/H5Gint.c4
-rw-r--r--src/H5O.c2
-rw-r--r--src/H5Pfapl.c99
-rw-r--r--src/H5Ppublic.h2
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/CMakeTests.cmake2
-rw-r--r--test/Makefile.am2
-rw-r--r--test/evict_on_close.c779
-rw-r--r--test/h5test.c2
24 files changed, 1027 insertions, 42 deletions
diff --git a/MANIFEST b/MANIFEST
index 60f9bb6..fb454c5 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -906,6 +906,7 @@
./test/enc_dec_plist.c
./test/enc_dec_plist_cross_platform.c
./test/enum.c
+./test/evict_on_close.c
./test/extend.c
./test/external.c
./test/error_test.c
diff --git a/src/H5AC.c b/src/H5AC.c
index 77a58fc..4dac680 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -2383,7 +2383,7 @@ done:
*------------------------------------------------------------------------------
*/
herr_t
-H5AC_evict_tagged_metadata(H5F_t * f, haddr_t metadata_tag, hid_t dxpl_id)
+H5AC_evict_tagged_metadata(H5F_t * f, haddr_t metadata_tag, hbool_t match_global, hid_t dxpl_id)
{
/* Variable Declarations */
herr_t ret_value = SUCCEED;
@@ -2396,7 +2396,7 @@ H5AC_evict_tagged_metadata(H5F_t * f, haddr_t metadata_tag, hid_t dxpl_id)
HDassert(f->shared);
/* Call cache level function to evict metadata entries with specified tag */
- if(H5C_evict_tagged_entries(f, dxpl_id, metadata_tag) < 0)
+ if(H5C_evict_tagged_entries(f, dxpl_id, metadata_tag, match_global) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Cannot evict metadata")
done:
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index d1d41c9..84c9e93 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -364,7 +364,7 @@ H5_DLL herr_t H5AC_validate_config(H5AC_cache_config_t *config_ptr);
/* Tag & Ring routines */
H5_DLL herr_t H5AC_tag(hid_t dxpl_id, haddr_t metadata_tag, haddr_t *prev_tag);
H5_DLL herr_t H5AC_flush_tagged_metadata(H5F_t * f, haddr_t metadata_tag, hid_t dxpl_id);
-H5_DLL herr_t H5AC_evict_tagged_metadata(H5F_t * f, haddr_t metadata_tag, hid_t dxpl_id);
+H5_DLL herr_t H5AC_evict_tagged_metadata(H5F_t * f, haddr_t metadata_tag, hbool_t match_global, hid_t dxpl_id);
H5_DLL herr_t H5AC_retag_copied_metadata(const H5F_t *f, haddr_t metadata_tag);
H5_DLL herr_t H5AC_ignore_tags(const H5F_t *f);
H5_DLL herr_t H5AC_cork(H5F_t *f, haddr_t obj_addr, unsigned action, hbool_t *corked);
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index 975ea3e..4137edf 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -1970,7 +1970,7 @@ H5_DLL herr_t H5C_expunge_entry(H5F_t *f, hid_t dxpl_id,
const H5C_class_t *type, haddr_t addr, unsigned flags);
H5_DLL herr_t H5C_flush_cache(H5F_t *f, hid_t dxpl_id, unsigned flags);
H5_DLL herr_t H5C_flush_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag);
-H5_DLL herr_t H5C_evict_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag);
+H5_DLL herr_t H5C_evict_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag, hbool_t match_global);
H5_DLL herr_t H5C_expunge_tag_type_metadata(H5F_t *f, hid_t dxpl_id, haddr_t tag, int type_id, unsigned flags);
#if H5C_DO_TAGGING_SANITY_CHECKS
herr_t H5C_verify_tag(int id, haddr_t tag, H5C_tag_globality_t globality);
diff --git a/src/H5Ctag.c b/src/H5Ctag.c
index d560e25..e1b4df6 100644
--- a/src/H5Ctag.c
+++ b/src/H5Ctag.c
@@ -352,7 +352,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5C_evict_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag)
+H5C_evict_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag, hbool_t match_global)
{
H5C_t *cache; /* Pointer to cache structure */
H5C_tag_iter_evict_ctx_t ctx; /* Context for iterator callback */
@@ -374,15 +374,15 @@ H5C_evict_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag)
/* Start evicting entries */
do {
- /* Reset pinned/evicted tracking flags */
- ctx.pinned_entries_need_evicted = FALSE;
- ctx.evicted_entries_last_pass = FALSE;
+ /* Reset pinned/evicted tracking flags */
+ ctx.pinned_entries_need_evicted = FALSE;
+ ctx.evicted_entries_last_pass = FALSE;
- /* Iterate through entries in the cache */
- if(H5C__iter_tagged_entries(cache, tag, TRUE, H5C__evict_tagged_entries_cb, &ctx) < 0)
+ /* Iterate through entries in the cache */
+ if(H5C__iter_tagged_entries(cache, tag, match_global, H5C__evict_tagged_entries_cb, &ctx) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADITER, FAIL, "Iteration of tagged entries failed")
- /* Keep doing this until we have stopped evicted entries */
+ /* Keep doing this until we have stopped evicted entries */
} while(TRUE == ctx.evicted_entries_last_pass);
/* Fail if we have finished evicting entries and pinned entries still need evicted */
diff --git a/src/H5D.c b/src/H5D.c
index 23397ad..44e4baa 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -308,37 +308,37 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Dclose
+ * Function: H5Dclose
*
- * Purpose: Closes access to a dataset (DATASET_ID) and releases
- * resources used by it. It is illegal to subsequently use that
- * same dataset ID in calls to other dataset functions.
+ * Purpose: Closes access to a dataset (DATASET_ID) and releases
+ * resources used by it. It is illegal to subsequently use that
+ * same dataset ID in calls to other dataset functions.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
- * Thursday, December 4, 1997
+ * Programmer: Robb Matzke
+ * Thursday, December 4, 1997
*
*-------------------------------------------------------------------------
*/
herr_t
H5Dclose(hid_t dset_id)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", dset_id);
/* Check args */
if(NULL == H5I_object_verify(dset_id, H5I_DATASET))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
/*
* Decrement the counter on the dataset. It will be freed if the count
* reaches zero.
*/
if(H5I_dec_app_ref_always_close(dset_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "can't decrement count on dataset ID")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "can't decrement count on dataset ID")
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5Dint.c b/src/H5Dint.c
index 8a00be2..59fe3e9 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -1780,9 +1780,9 @@ done:
herr_t
H5D_close(H5D_t *dataset)
{
- hbool_t free_failed = FALSE;
- hbool_t corked; /* Whether the dataset is corked or not */
- herr_t ret_value = SUCCEED; /* Return value */
+ hbool_t free_failed = FALSE; /* Set if freeing sub-components failed */
+ hbool_t corked; /* Whether the dataset is corked or not */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1797,6 +1797,7 @@ H5D_close(H5D_t *dataset)
dataset->shared->fo_count--;
if(dataset->shared->fo_count == 0) {
+
/* Flush the dataset's information. Continue to close even if it fails. */
if(H5D__flush_real(dataset, H5AC_ind_read_dxpl_id) < 0)
HDONE_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to flush cached dataset info")
@@ -1891,12 +1892,12 @@ H5D_close(H5D_t *dataset)
(H5O_msg_reset(H5O_FILL_ID, &dataset->shared->dcpl_cache.fill) < 0) ||
(H5O_msg_reset(H5O_EFL_ID, &dataset->shared->dcpl_cache.efl) < 0);
- /* Uncork cache entries with object address tag */
- if(H5AC_cork(dataset->oloc.file, dataset->oloc.addr, H5AC__GET_CORKED, &corked) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status")
- if(corked)
- if(H5AC_cork(dataset->oloc.file, dataset->oloc.addr, H5AC__UNCORK, NULL) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTUNCORK, FAIL, "unable to uncork an object")
+ /* Uncork cache entries with object address tag */
+ if(H5AC_cork(dataset->oloc.file, dataset->oloc.addr, H5AC__GET_CORKED, &corked) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status")
+ if(corked)
+ if(H5AC_cork(dataset->oloc.file, dataset->oloc.addr, H5AC__UNCORK, NULL) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTUNCORK, FAIL, "unable to uncork an object")
/*
* Release datatype, dataspace and creation property list -- there isn't
@@ -1917,6 +1918,14 @@ H5D_close(H5D_t *dataset)
if(H5O_close(&(dataset->oloc)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release object header")
+ /* Evict dataset metadata if evicting on close */
+ if(H5F_SHARED(dataset->oloc.file) && H5F_EVICT_ON_CLOSE(dataset->oloc.file)) {
+ if(H5AC_flush_tagged_metadata(dataset->oloc.file, dataset->oloc.addr, H5AC_ind_read_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush tagged metadata")
+ if(H5AC_evict_tagged_metadata(dataset->oloc.file, dataset->oloc.addr, FALSE, H5AC_ind_read_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to evict tagged metadata")
+ } /* end if */
+
/*
* Free memory. Before freeing the memory set the file pointer to NULL.
* We always check for a null file pointer in other H5D functions to be
@@ -1924,8 +1933,8 @@ H5D_close(H5D_t *dataset)
* above).
*/
dataset->oloc.file = NULL;
-
dataset->shared = H5FL_FREE(H5D_shared_t, dataset->shared);
+
} /* end if */
else {
/* Decrement the ref. count for this object in the top file */
@@ -1943,16 +1952,16 @@ H5D_close(H5D_t *dataset)
HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "problem attempting to free location")
} /* end else */
- /* Release the dataset's path info */
- if(H5G_name_free(&(dataset->path)) < 0)
- free_failed = TRUE;
+ /* Release the dataset's path info */
+ if(H5G_name_free(&(dataset->path)) < 0)
+ free_failed = TRUE;
/* Free the dataset's memory structure */
dataset = H5FL_FREE(H5D_t, dataset);
/* Check if anything failed in the middle... */
if(free_failed)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't free a component of the dataset, but the dataset was freed anyway.")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't free a component of the dataset, but the dataset was freed anyway.")
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index 05f49d1..2190f8c 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -770,6 +770,7 @@ H5_DLL htri_t H5D__mpio_opt_possible(const H5D_io_info_t *io_info,
H5_DLL herr_t H5D__layout_version_test(hid_t did, unsigned *version);
H5_DLL herr_t H5D__layout_contig_size_test(hid_t did, hsize_t *size);
H5_DLL herr_t H5D__layout_idx_type_test(hid_t did, H5D_chunk_index_t *idx_type);
+H5_DLL herr_t H5D__layout_type_test(hid_t did, H5D_layout_t *layout_type);
H5_DLL herr_t H5D__current_cache_size_test(hid_t did, size_t *nbytes_used, int *nused);
#endif /* H5D_TESTING */
diff --git a/src/H5Dtest.c b/src/H5Dtest.c
index c3b0b19..56f14f7 100644
--- a/src/H5Dtest.c
+++ b/src/H5Dtest.c
@@ -144,6 +144,47 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5D__layout_type_test
+ PURPOSE
+ Determine the storage layout type for a dataset
+ USAGE
+ herr_t H5D__layout_type_test(did, layout_type)
+ hid_t did; IN: Dataset to query
+ H5D_layout_t *layout_type; OUT: Pointer to location to place layout info
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Checks the layout type for a dataset.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5D__layout_type_test(hid_t did, H5D_layout_t *layout_type)
+{
+ H5D_t *dset; /* Pointer to dataset to query */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(layout_type);
+
+ /* Check args */
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(did, H5I_DATASET)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
+
+ if(layout_type)
+ *layout_type = dset->shared->layout.type;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D__layout_type_test() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5D__layout_idx_type_test
PURPOSE
Determine the storage layout index type for a dataset's layout information
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 80c593b..5b7fdda 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -954,6 +954,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
H5FD_class_t *drvr; /*file driver class info */
H5P_genplist_t *a_plist; /*file access property list */
H5F_close_degree_t fc_degree; /*file close degree */
+ hbool_t evict_on_close; /* evict on close value from plist */
H5F_t *ret_value = NULL; /*actual return value */
FUNC_ENTER_NOAPI(NULL)
@@ -1118,6 +1119,21 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
} /* end if */
+ /* Record the evict-on-close MDC behavior. If it's the first time opening
+ * the file, set it to access property list value; if it's the second time
+ * or later, verify that the access property list value matches the value
+ * in shared file structure.
+ */
+ if(H5P_get(a_plist, H5F_ACS_EVICT_ON_CLOSE_FLAG_NAME, &evict_on_close) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get evict on close value")
+
+ if(shared->nrefs == 1) {
+ shared->evict_on_close = evict_on_close;
+ } else if(shared->nrefs > 1) {
+ if(shared->evict_on_close != evict_on_close)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file evict-on-close value doesn't match")
+ } /* end if */
+
/* Formulate the absolute path for later search of target file for external links */
if(H5_build_extpath(name, &file->extpath) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath")
diff --git a/src/H5Fio.c b/src/H5Fio.c
index b9bd354..2ccd3f3 100644
--- a/src/H5Fio.c
+++ b/src/H5Fio.c
@@ -271,7 +271,7 @@ H5F_evict_tagged_metadata(H5F_t * f, haddr_t tag, hid_t dxpl_id)
f->shared->sblock = NULL;
/* Evict the object's metadata */
- if(H5AC_evict_tagged_metadata(f, tag, dxpl_id)<0)
+ if(H5AC_evict_tagged_metadata(f, tag, TRUE, dxpl_id) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "unable to evict tagged metadata")
/* Re-read the superblock. */
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index c5aed3b..8ec2a93 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -261,6 +261,7 @@ struct H5F_file_t {
/* not change thereafter. */
hid_t fcpl_id; /* File creation property list ID */
H5F_close_degree_t fc_degree; /* File close behavior degree */
+ hbool_t evict_on_close; /* If the file's objects should be evicted from the metadata cache on close */
size_t rdcc_nslots; /* Size of raw data chunk cache (slots) */
size_t rdcc_nbytes; /* Size of raw data chunk cache (bytes) */
double rdcc_w0; /* Preempt read chunks first? [0.0..1.0]*/
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index b5c24e9..40e5ff2 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -303,6 +303,7 @@
#define H5F_SET_SOHM_NINDEXES(F, N) ((F)->shared->sohm_nindexes = (N))
#define H5F_FCPL(F) ((F)->shared->fcpl_id)
#define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree)
+#define H5F_EVICT_ON_CLOSE(F) ((F)->shared->evict_on_close)
#define H5F_RDCC_NSLOTS(F) ((F)->shared->rdcc_nslots)
#define H5F_RDCC_NBYTES(F) ((F)->shared->rdcc_nbytes)
#define H5F_RDCC_W0(F) ((F)->shared->rdcc_w0)
@@ -348,6 +349,7 @@
#define H5F_SET_SOHM_NINDEXES(F, N) (H5F_set_sohm_nindexes((F), (N)))
#define H5F_FCPL(F) (H5F_get_fcpl(F))
#define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F))
+#define H5F_EVICT_ON_CLOSE(F) (H5F_get_evict_on_close(F))
#define H5F_RDCC_NSLOTS(F) (H5F_rdcc_nslots(F))
#define H5F_RDCC_NBYTES(F) (H5F_rdcc_nbytes(F))
#define H5F_RDCC_W0(F) (H5F_rdcc_w0(F))
@@ -463,6 +465,7 @@
#define H5F_ACS_EFC_SIZE_NAME "efc_size" /* Size of external file cache */
#define H5F_ACS_FILE_IMAGE_INFO_NAME "file_image_info" /* struct containing initial file image and callback info */
#define H5F_ACS_CORE_WRITE_TRACKING_FLAG_NAME "core_write_tracking_flag" /* Whether or not core VFD backing store write tracking is enabled */
+#define H5F_ACS_EVICT_ON_CLOSE_FLAG_NAME "evict_on_close_flag" /* Whether or not the metadata cache will evict objects on close */
#define H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_NAME "core_write_tracking_page_size" /* The page size in kiB when core VFD write tracking is enabled */
#define H5F_ACS_COLL_MD_WRITE_FLAG_NAME "collective_metadata_write" /* property indicating whether metadata writes are done collectively or not */
@@ -660,6 +663,7 @@ H5_DLL unsigned H5F_get_sohm_nindexes(const H5F_t *f);
H5_DLL herr_t H5F_set_sohm_nindexes(H5F_t *f, unsigned nindexes);
H5_DLL hid_t H5F_get_fcpl(const H5F_t *f);
H5_DLL H5F_close_degree_t H5F_get_fc_degree(const H5F_t *f);
+H5_DLL hbool_t H5F_get_evict_on_close(const H5F_t *f);
H5_DLL size_t H5F_rdcc_nbytes(const H5F_t *f);
H5_DLL size_t H5F_rdcc_nslots(const H5F_t *f);
H5_DLL double H5F_rdcc_w0(const H5F_t *f);
diff --git a/src/H5Fquery.c b/src/H5Fquery.c
index dd6e8e3..f59a9b7 100644
--- a/src/H5Fquery.c
+++ b/src/H5Fquery.c
@@ -835,6 +835,33 @@ H5F_get_fc_degree(const H5F_t *f)
/*-------------------------------------------------------------------------
+ * Function: H5F_get_evict_on_close
+ *
+ * Purpose: Retrieve the 'file close degree' for the file.
+ *
+ * Return: Success: Flag indicating whether the evict-on-close
+ * property was set for the file.
+ * Failure: (can't happen)
+ *
+ * Programmer: Dana Robinson
+ * Spring 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_get_evict_on_close(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->evict_on_close)
+} /* end H5F_get_evict_on_close() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_store_msg_crt_idx
*
* Purpose: Retrieve the 'store message creation index' flag for the file.
diff --git a/src/H5G.c b/src/H5G.c
index 5d920a4..1a18dc0 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -715,14 +715,14 @@ done:
herr_t
H5Gclose(hid_t group_id)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", group_id);
/* Check args */
if(NULL == H5I_object_verify(group_id,H5I_GROUP))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/*
* Decrement the counter on the group atom. It will be freed if the count
diff --git a/src/H5Gint.c b/src/H5Gint.c
index f5bccc3..a0e06f3 100644
--- a/src/H5Gint.c
+++ b/src/H5Gint.c
@@ -486,7 +486,7 @@ H5G_close(H5G_t *grp)
if(0 == grp->shared->fo_count) {
HDassert(grp != H5G_rootof(H5G_fileof(grp)));
- /* Uncork cache entries with object address tag */
+ /* Uncork cache entries with object address tag */
if(H5AC_cork(grp->oloc.file, grp->oloc.addr, H5AC__GET_CORKED, &corked) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status")
if(corked)
@@ -500,6 +500,8 @@ H5G_close(H5G_t *grp)
HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects")
if(H5O_close(&(grp->oloc)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close")
+
+ /* Free memory */
grp->shared = H5FL_FREE(H5G_shared_t, grp->shared);
} else {
/* Decrement the ref. count for this object in the top file */
diff --git a/src/H5O.c b/src/H5O.c
index 3daf09e..d1806a1 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -1051,7 +1051,7 @@ done:
* the same effect as calling H5Gclose, H5Dclose, or H5Tclose.
*
* Return: Success: Non-negative
- * Failure: Negative
+ * Failure: Negative
*
* Programmer: James Laird
* July 14 2006
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c
index 96de39c..8801061 100644
--- a/src/H5Pfapl.c
+++ b/src/H5Pfapl.c
@@ -181,6 +181,11 @@
/* Definition for object flush callback */
#define H5F_ACS_OBJECT_FLUSH_CB_SIZE sizeof(H5F_object_flush_t)
#define H5F_ACS_OBJECT_FLUSH_CB_DEF {NULL, NULL}
+/* Definition for evict on close property */
+#define H5F_ACS_EVICT_ON_CLOSE_FLAG_SIZE sizeof(hbool_t)
+#define H5F_ACS_EVICT_ON_CLOSE_FLAG_DEF FALSE
+#define H5F_ACS_EVICT_ON_CLOSE_FLAG_ENC H5P__encode_hbool_t
+#define H5F_ACS_EVICT_ON_CLOSE_FLAG_DEC H5P__decode_hbool_t
#ifdef H5_HAVE_PARALLEL
/* Definition of collective metadata read mode flag */
#define H5F_ACS_COLL_MD_READ_FLAG_SIZE sizeof(H5P_coll_md_read_flag_t)
@@ -296,6 +301,7 @@ static const H5FD_file_image_info_t H5F_def_file_image_info_g = H5F_ACS_FILE_IMA
static const hbool_t H5F_def_core_write_tracking_flag_g = H5F_ACS_CORE_WRITE_TRACKING_FLAG_DEF; /* Default setting for core VFD write tracking */
static const size_t H5F_def_core_write_tracking_page_size_g = H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_DEF; /* Default core VFD write tracking page size */
static const H5F_object_flush_t H5F_def_object_flush_cb_g = H5F_ACS_OBJECT_FLUSH_CB_DEF; /* Default setting for object flush callback */
+static const hbool_t H5F_def_evict_on_close_flag_g = H5F_ACS_EVICT_ON_CLOSE_FLAG_DEF; /* Default setting for evict on close property */
#ifdef H5_HAVE_PARALLEL
static const H5P_coll_md_read_flag_t H5F_def_coll_md_read_flag_g = H5F_ACS_COLL_MD_READ_FLAG_DEF; /* Default setting for the collective metedata read flag */
static const hbool_t H5F_def_coll_md_write_flag_g = H5F_ACS_COLL_MD_WRITE_FLAG_DEF; /* Default setting for the collective metedata write flag */
@@ -462,6 +468,12 @@ H5P__facc_reg_prop(H5P_genclass_t *pclass)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register the evict on close flag */
+ if(H5P_register_real(pclass, H5F_ACS_EVICT_ON_CLOSE_FLAG_NAME, H5F_ACS_EVICT_ON_CLOSE_FLAG_SIZE, &H5F_def_evict_on_close_flag_g,
+ NULL, NULL, NULL, H5F_ACS_EVICT_ON_CLOSE_FLAG_ENC, H5F_ACS_EVICT_ON_CLOSE_FLAG_DEC,
+ NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
#ifdef H5_HAVE_PARALLEL
/* Register the metadata collective read flag */
if(H5P_register_real(pclass, H5_COLL_MD_READ_FLAG_NAME, H5F_ACS_COLL_MD_READ_FLAG_SIZE, &H5F_def_coll_md_read_flag_g,
@@ -3605,6 +3617,93 @@ done:
FUNC_LEAVE_API(ret_value)
} /* H5Pget_obj_flush_cb() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_evict_on_close
+ *
+ * Purpose: Sets the evict_on_close property value.
+ *
+ * When this property is set, closing an HDF5 object will
+ * cause the object's metadata cache entries to be flushed
+ * and evicted from the cache.
+ *
+ * Currently only implemented for datasets.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Spring 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_evict_on_close(hid_t fapl_id, hbool_t evict_on_close)
+{
+ H5P_genplist_t *plist; /* property list pointer */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "ib", fapl_id, evict_on_close);
+
+ /* Compare the property list's class against the other class */
+ if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "property list is not a file access plist")
+
+ /* Get the plist structure */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Set values */
+ if(H5P_set(plist, H5F_ACS_EVICT_ON_CLOSE_FLAG_NAME, &evict_on_close) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set evict on close property")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_evict_on_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_evict_on_close
+ *
+ * Purpose: Gets the evict_on_close property value.
+ *
+ * When this property is set, closing an HDF5 object will
+ * cause the object's metadata cache entries to be flushed
+ * and evicted from the cache.
+ *
+ * Currently only implemented for datasets.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Spring 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_evict_on_close(hid_t fapl_id, hbool_t *evict_on_close)
+{
+ H5P_genplist_t *plist; /* property list pointer */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*b", fapl_id, evict_on_close);
+
+ /* Compare the property list's class against the other class */
+ if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "property list is not an access plist")
+
+ /* Get the plist structure */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ if(H5P_get(plist, H5F_ACS_EVICT_ON_CLOSE_FLAG_NAME, evict_on_close) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get evict on close property")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_evict_on_close() */
+
#ifdef H5_HAVE_PARALLEL
/*-------------------------------------------------------------------------
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index 0318c8f..b807a37 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -353,6 +353,8 @@ H5_DLL herr_t H5Pset_core_write_tracking(hid_t fapl_id, hbool_t is_enabled, size
H5_DLL herr_t H5Pget_core_write_tracking(hid_t fapl_id, hbool_t *is_enabled, size_t *page_size);
H5_DLL herr_t H5Pset_object_flush_cb(hid_t plist_id, H5F_flush_cb_t func, void *udata);
H5_DLL herr_t H5Pget_object_flush_cb(hid_t plist_id, H5F_flush_cb_t *func, void **udata);
+H5_DLL herr_t H5Pset_evict_on_close(hid_t fapl_id, hbool_t evict_on_close);
+H5_DLL herr_t H5Pget_evict_on_close(hid_t fapl_id, hbool_t *evict_on_close);
#ifdef H5_HAVE_PARALLEL
H5_DLL herr_t H5Pset_all_coll_metadata_ops(hid_t plist_id, hbool_t is_collective);
H5_DLL herr_t H5Pget_all_coll_metadata_ops(hid_t plist_id, hbool_t *is_collective);
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 1ab4165..6e6a0b9 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -204,6 +204,7 @@ set (H5_TESTS
ohdr
stab
gheap
+ evict_on_close
farray
earray
btree2
diff --git a/test/CMakeTests.cmake b/test/CMakeTests.cmake
index ca890ba..1e7940a 100644
--- a/test/CMakeTests.cmake
+++ b/test/CMakeTests.cmake
@@ -513,6 +513,7 @@ set (H5TEST_TESTS
ohdr
stab
gheap
+ evict_on_close
farray
earray
btree2
@@ -865,6 +866,7 @@ if (HDF5_TEST_VFD)
ohdr
stab
gheap
+ evict_on_close
pool
# accum
farray
diff --git a/test/Makefile.am b/test/Makefile.am
index 9e0f9c5..7d062f4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -42,7 +42,7 @@ 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_tagging lheap ohdr stab gheap \
- farray earray btree2 fheap \
+ evict_on_close farray earray btree2 fheap \
pool accum hyperslab istore bittests dt_arith \
dtypes dsets cmpd_dset filter_fail extend external efc objcopy links unlink \
big mtime fillval mount flush1 flush2 app_ref enum \
diff --git a/test/evict_on_close.c b/test/evict_on_close.c
new file mode 100644
index 0000000..0657b1b
--- /dev/null
+++ b/test/evict_on_close.c
@@ -0,0 +1,779 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Dana Robinson
+ * Spring 2016
+ *
+ * Purpose: Tests the basic operation of the evict-on-close cache
+ * behavior. Tests that ensure the tagging is handled correctly
+ * are located in cache.c.
+ */
+
+#define H5C_FRIEND /*suppress error about including H5Cpkg */
+#define H5D_FRIEND /*suppress error about including H5Dpkg */
+#define H5D_TESTING
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+#define H5F_TESTING
+#define H5I_FRIEND /*suppress error about including H5Ipkg */
+#define H5I_TESTING
+
+
+#include "h5test.h"
+#include "H5Cpkg.h"
+#include "H5Dpkg.h"
+#include "H5Fpkg.h"
+#include "H5Ipkg.h"
+
+/* Uncomment to manually inspect cache states */
+/* #define EOC_MANUAL_INSPECTION */
+
+const char *FILENAMES[] = {
+ "evict-on-close", /* 0 */
+ NULL
+};
+#define FILENAME_BUF_SIZE 1024
+
+/* Dataset names */
+#define DSET_COMPACT_NAME "compact"
+#define DSET_CONTIGUOUS_NAME "contiguous"
+#define DSET_BTREE_NAME "v1_btree"
+#define DSET_EARRAY_NAME "earray"
+#define DSET_BT2_NAME "v2_btree"
+#define DSET_FARRAY_NAME "farray"
+#define DSET_SINGLE_NAME "single"
+
+/* All datasets store 1000 elements */
+#define NELEMENTS 1024
+
+static hbool_t verify_tag_not_in_cache(H5F_t *f, haddr_t tag);
+static herr_t check_evict_on_close_api(void);
+static hid_t generate_eoc_test_file(hid_t fapl_id);
+static herr_t check_configuration(hid_t fid, const char *dset_name);
+
+
+/*-------------------------------------------------------------------------
+ * Function: verify_tag_not_in_cache()
+ *
+ * Purpose: Ensure that metadata cache entries with a given tag are not
+ * present in the cache.
+ *
+ * Return: TRUE/FALSE
+ *
+ * Programmer: Dana Robinson
+ * Fall 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+verify_tag_not_in_cache(H5F_t *f, haddr_t tag)
+{
+ H5C_t *cache_ptr = NULL; /* cache pointer */
+ int i = 0; /* iterator */
+ H5C_cache_entry_t *entry_ptr = NULL; /* entry pointer */
+
+ cache_ptr = f->shared->cache;
+
+ for(i = 0; i < H5C__HASH_TABLE_LEN; i++) {
+
+ entry_ptr = cache_ptr->index[i];
+
+ while(entry_ptr != NULL) {
+
+ if(tag == entry_ptr->tag)
+ return TRUE;
+ else
+ entry_ptr = entry_ptr->ht_next;
+
+ } /* end while */
+ } /* end for */
+
+ return FALSE;
+
+} /* end verify_tag_not_in_cache() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: generate_eoc_test_file()
+ *
+ * Purpose: Generate the evict-on-close test file.
+ *
+ * Return: Success: The file ID of the created file
+ * Failure: -1
+ *
+ * Programmer: Dana Robinson
+ * Fall 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+generate_eoc_test_file(hid_t fapl_id)
+{
+ char filename[FILENAME_BUF_SIZE]; /* decorated file name */
+ hid_t fid = -1; /* file ID (returned) */
+ hid_t fapl_copy_id = -1; /* ID of copied fapl */
+ hid_t sid = -1; /* dataspace ID */
+ hid_t dcpl_id = -1; /* dataset creation plist */
+ hid_t did = -1; /* dataset ID */
+ int rank; /* # of array dimensions */
+ hsize_t current_dims[2]; /* current dataset size */
+ hsize_t maximum_dims[2]; /* maximum dataset size */
+ hsize_t chunk_dims[2]; /* chunk dimensions */
+ H5D_chunk_index_t idx_type; /* dataset chunk index type */
+ H5D_layout_t layout_type; /* dataset layout type */
+ int *data = NULL; /* buffer for fake data */
+ int n; /* # of data elements */
+
+ TESTING("generating evict-on-close test file");
+
+ /* Get a VFD-specific filename */
+ h5_fixname(FILENAMES[0], fapl_id, filename, sizeof(filename));
+
+ /* Create file */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0)
+ TEST_ERROR;
+
+ /***********************************************************/
+ /* Generate datasets and ensure that the scheme is correct */
+ /***********************************************************/
+
+ /* Create the data buffer */
+ if(NULL == (data = (int *)HDcalloc(NELEMENTS, sizeof(int))))
+ TEST_ERROR;
+
+ /****************************************************/
+ /* Old file format data structures (v1 B-tree only) */
+ /****************************************************/
+
+ /********************/
+ /* Version 1 B-tree */
+ /********************/
+
+ /* Create dataspace */
+ n = NELEMENTS;
+ rank = 1;
+ current_dims[0] = (hsize_t)n;
+ maximum_dims[0] = H5S_UNLIMITED;
+ if((sid = H5Screate_simple(rank, current_dims, maximum_dims)) < 0)
+ TEST_ERROR;
+
+ /* Create dcpl and set up chunking */
+ if((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR;
+ chunk_dims[0] = 1;
+ if(H5Pset_chunk(dcpl_id, rank, chunk_dims) < 0)
+ TEST_ERROR;
+
+ /* Create dataset */
+ if((did = H5Dcreate(fid, DSET_BTREE_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Ensure we're using the correct chunk indexing scheme */
+ if(H5D__layout_idx_type_test(did, &idx_type) < 0)
+ TEST_ERROR;
+ if(idx_type != H5D_CHUNK_IDX_BTREE)
+ FAIL_PUTS_ERROR("should be using version 1 B-tree as the chunk index");
+
+ /* Write a bunch of fake data */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
+ TEST_ERROR;
+
+ /* Close IDs for this dataset */
+ if(H5Dclose(did) < 0)
+ TEST_ERROR;
+ if(H5Sclose(sid) < 0)
+ TEST_ERROR;
+ if(H5Pclose(dcpl_id) < 0)
+ TEST_ERROR;
+
+ /***********************************/
+ /* New file format data structures */
+ /***********************************/
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ TEST_ERROR;
+
+ /* Copy the fapl and set the latest file format */
+ if((fapl_copy_id = H5Pcopy(fapl_id)) < 0)
+ TEST_ERROR;
+ if(H5Pset_libver_bounds(fapl_copy_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ TEST_ERROR;
+
+ /* Reopen the file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl_copy_id)) < 0)
+ TEST_ERROR;
+
+ /********************/
+ /* Extensible Array */
+ /********************/
+
+ /* Create dataspace */
+ n = NELEMENTS;
+ rank = 1;
+ current_dims[0] = (hsize_t)n;
+ maximum_dims[0] = H5S_UNLIMITED;
+ if((sid = H5Screate_simple(rank, current_dims, maximum_dims)) < 0)
+ TEST_ERROR;
+
+ /* Create dcpl and set up chunking */
+ if((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR;
+ chunk_dims[0] = 1;
+ if(H5Pset_chunk(dcpl_id, rank, chunk_dims) < 0)
+ TEST_ERROR;
+
+ /* Create dataset */
+ if((did = H5Dcreate(fid, DSET_EARRAY_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Ensure we're using the correct chunk indexing scheme */
+ if(H5D__layout_idx_type_test(did, &idx_type) < 0)
+ TEST_ERROR;
+ if(idx_type != H5D_CHUNK_IDX_EARRAY)
+ FAIL_PUTS_ERROR("should be using extensible array as the chunk index");
+
+ /* Write a bunch of fake data */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
+ TEST_ERROR;
+
+ /* Close IDs for this dataset */
+ if(H5Dclose(did) < 0)
+ TEST_ERROR;
+ if(H5Sclose(sid) < 0)
+ TEST_ERROR;
+ if(H5Pclose(dcpl_id) < 0)
+ TEST_ERROR;
+
+ /********************/
+ /* Version 2 B-Tree */
+ /********************/
+
+ /* Create dataspace */
+ n = NELEMENTS;
+ rank = 2;
+ current_dims[0] = (hsize_t)2;
+ current_dims[1] = (hsize_t)(n/2);
+ maximum_dims[0] = H5S_UNLIMITED;
+ maximum_dims[1] = H5S_UNLIMITED;
+ if((sid = H5Screate_simple(rank, current_dims, maximum_dims)) < 0)
+ TEST_ERROR;
+
+ /* Create dcpl and set up chunking */
+ if((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR;
+ chunk_dims[0] = 1;
+ chunk_dims[1] = 1;
+ if(H5Pset_chunk(dcpl_id, rank, chunk_dims) < 0)
+ TEST_ERROR;
+
+ /* Create dataset */
+ if((did = H5Dcreate(fid, DSET_BT2_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Ensure we're using the correct chunk indexing scheme */
+ if(H5D__layout_idx_type_test(did, &idx_type) < 0)
+ TEST_ERROR;
+ if(idx_type != H5D_CHUNK_IDX_BT2)
+ FAIL_PUTS_ERROR("should be using version 2 B-tree as the chunk index");
+
+ /* Write a bunch of fake data */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
+ TEST_ERROR;
+
+ /* Close IDs for this dataset */
+ if(H5Dclose(did) < 0)
+ TEST_ERROR;
+ if(H5Sclose(sid) < 0)
+ TEST_ERROR;
+ if(H5Pclose(dcpl_id) < 0)
+ TEST_ERROR;
+
+ /***************/
+ /* Fixed Array */
+ /***************/
+
+ /* Create dataspace */
+ n = NELEMENTS;
+ rank = 1;
+ current_dims[0] = (hsize_t)n;
+ maximum_dims[0] = (hsize_t)n;
+ if((sid = H5Screate_simple(rank, current_dims, maximum_dims)) < 0)
+ TEST_ERROR;
+
+ /* Create dcpl and set up chunking */
+ if((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR;
+ chunk_dims[0] = 1;
+ chunk_dims[1] = 1;
+ if(H5Pset_chunk(dcpl_id, rank, chunk_dims) < 0)
+ TEST_ERROR;
+
+ /* Create dataset */
+ if((did = H5Dcreate(fid, DSET_FARRAY_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Ensure we're using the correct chunk indexing scheme */
+ if(H5D__layout_idx_type_test(did, &idx_type) < 0)
+ TEST_ERROR;
+ if(idx_type != H5D_CHUNK_IDX_FARRAY)
+ FAIL_PUTS_ERROR("should be using fixed array as the chunk index");
+
+ /* Write a bunch of fake data */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
+ TEST_ERROR;
+
+ /* Close IDs for this dataset */
+ if(H5Dclose(did) < 0)
+ TEST_ERROR;
+ if(H5Sclose(sid) < 0)
+ TEST_ERROR;
+ if(H5Pclose(dcpl_id) < 0)
+ TEST_ERROR;
+
+ /****************/
+ /* Single Chunk */
+ /****************/
+
+ /* Create dataspace */
+ n = NELEMENTS;
+ rank = 1;
+ current_dims[0] = (hsize_t)n;
+ maximum_dims[0] = (hsize_t)n;
+ if((sid = H5Screate_simple(rank, current_dims, maximum_dims)) < 0)
+ TEST_ERROR;
+
+ /* Create dcpl and set up chunking */
+ if((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR;
+ chunk_dims[0] = (hsize_t)n;
+ chunk_dims[1] = (hsize_t)n;
+ if(H5Pset_chunk(dcpl_id, rank, chunk_dims) < 0)
+ TEST_ERROR;
+
+ /* Create dataset */
+ if((did = H5Dcreate(fid, DSET_SINGLE_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Ensure we're using the correct chunk indexing scheme */
+ if(H5D__layout_idx_type_test(did, &idx_type) < 0)
+ TEST_ERROR;
+ if(idx_type != H5D_CHUNK_IDX_SINGLE)
+ FAIL_PUTS_ERROR("should be using single chunk as the chunk index");
+
+ /* Write a bunch of fake data */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
+ TEST_ERROR;
+
+ /* Close IDs for this dataset */
+ if(H5Dclose(did) < 0)
+ TEST_ERROR;
+ if(H5Sclose(sid) < 0)
+ TEST_ERROR;
+ if(H5Pclose(dcpl_id) < 0)
+ TEST_ERROR;
+
+ /**************/
+ /* Contiguous */
+ /**************/
+
+ /* Create dataspace */
+ n = NELEMENTS;
+ rank = 1;
+ current_dims[0] = (hsize_t)n;
+ maximum_dims[0] = (hsize_t)n;
+ if((sid = H5Screate_simple(rank, current_dims, maximum_dims)) < 0)
+ TEST_ERROR;
+
+ /* Create dataset */
+ if((did = H5Dcreate(fid, DSET_CONTIGUOUS_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Ensure we're using the correct layout scheme */
+ if(H5D__layout_type_test(did, &layout_type) < 0)
+ TEST_ERROR;
+ if(layout_type != H5D_CONTIGUOUS)
+ FAIL_PUTS_ERROR("should be using contiguous layout");
+
+ /* Write a bunch of fake data */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
+ TEST_ERROR;
+
+ /* Close IDs for this dataset */
+ if(H5Dclose(did) < 0)
+ TEST_ERROR;
+ if(H5Sclose(sid) < 0)
+ TEST_ERROR;
+
+ /***********/
+ /* Compact */
+ /***********/
+
+ /* Create dataspace */
+ n = 1;
+ rank = 1;
+ current_dims[0] = (hsize_t)n;
+ maximum_dims[0] = (hsize_t)n;
+ if((sid = H5Screate_simple(rank, current_dims, maximum_dims)) < 0)
+ TEST_ERROR;
+
+ /* Create dcpl and set up compact layout */
+ if((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR;
+ if(H5Pset_layout(dcpl_id, H5D_COMPACT) < 0)
+ TEST_ERROR;
+
+ /* Create dataset */
+ if((did = H5Dcreate(fid, DSET_COMPACT_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Ensure we're using the correct layout scheme */
+ if(H5D__layout_type_test(did, &layout_type) < 0)
+ TEST_ERROR;
+ if(layout_type != H5D_COMPACT)
+ FAIL_PUTS_ERROR("should be using compact layout");
+
+ /* Write a bunch of fake data */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
+ TEST_ERROR;
+
+ /* Close IDs for this dataset */
+ if(H5Dclose(did) < 0)
+ TEST_ERROR;
+ if(H5Sclose(sid) < 0)
+ TEST_ERROR;
+ if(H5Pclose(dcpl_id) < 0)
+ TEST_ERROR;
+
+ /********/
+ /* DONE */
+ /********/
+
+ /* Close/free everything else */
+ if(H5Pclose(fapl_copy_id) < 0)
+ TEST_ERROR;
+
+ HDfree(data);
+
+ PASSED();
+ return fid;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Fclose(fid);
+ H5Dclose(did);
+ H5Sclose(sid);
+ H5Pclose(dcpl_id);
+ H5Pclose(fapl_copy_id);
+ } H5E_END_TRY;
+
+ HDfree(data);
+
+ H5_FAILED();
+ return -1;
+
+} /* end generate_eoc_test_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_configuration()
+ *
+ * Purpose: Verify that the evict-on-close feature works for a given
+ * dataset layout and/or chunk index.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+check_configuration(hid_t fid, const char *dset_name)
+{
+ H5F_t *file_ptr = NULL; /* ptr to internal file struct */
+ hid_t did = -1; /* dataset ID */
+ H5D_t *dset_ptr = NULL; /* ptr to internal dset struct */
+ haddr_t tag; /* MD cache tag for dataset */
+ int *data = NULL; /* buffer for fake data */
+ int32_t before, during, after; /* cache sizes */
+
+ /* NOTE: The TESTING() macro is called in main() */
+
+ /* Get a pointer to the file struct */
+ if(NULL == (file_ptr = (H5F_t *)H5I_object_verify(fid, H5I_FILE)))
+ TEST_ERROR;
+
+ /* Create the data buffer */
+ if(NULL == (data = (int *)HDcalloc(NELEMENTS, sizeof(int))))
+ TEST_ERROR;
+
+ /* Record the number of cache entries */
+ before = file_ptr->shared->cache->index_len;
+
+#ifdef EOC_MANUAL_INSPECTION
+ HDprintf("\nCACHE BEFORE DATASET OPEN:\n");
+ if(H5AC_dump_cache(file_ptr) < 0)
+ TEST_ERROR;
+ HDprintf("NUMBER OF CACHE ENTRIES: %d\n", before);
+#endif
+
+ /* Open dataset and get the metadata tag */
+ if((did = H5Dopen2(fid, dset_name, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+ if(NULL == (dset_ptr = (H5D_t *)H5I_object_verify(did, H5I_DATASET)))
+ TEST_ERROR;
+ tag = dset_ptr->oloc.addr;
+
+ /* Read data from the dataset so the cache gets populated with chunk
+ * and the like.
+ */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
+ TEST_ERROR;
+
+ /* Record the number of cache entries */
+ during = file_ptr->shared->cache->index_len;
+
+#ifdef EOC_MANUAL_INSPECTION
+ HDprintf("\nCACHE AFTER DATA READ (WHILE OPEN):\n");
+ if(H5AC_dump_cache(file_ptr) < 0)
+ TEST_ERROR;
+ HDprintf("TAG: %#X\n", tag);
+ HDprintf("NUMBER OF CACHE ENTRIES: %d\n", during);
+#endif
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ TEST_ERROR;
+
+ /* Record the number of cache entries */
+ after = file_ptr->shared->cache->index_len;
+
+#ifdef EOC_MANUAL_INSPECTION
+ HDprintf("\nCACHE AFTER DATASET CLOSE:\n");
+ if(H5AC_dump_cache(file_ptr) < 0)
+ TEST_ERROR;
+ HDprintf("NUMBER OF CACHE ENTRIES: %d\n", after);
+#endif
+
+ /* Ensure that the cache does not contain data items with the tag */
+ if(TRUE == verify_tag_not_in_cache(file_ptr, tag))
+ TEST_ERROR;
+
+ /* Compare the number of cache entries */
+ if(before != after || before == during)
+ TEST_ERROR;
+
+ HDfree(data);
+
+ PASSED();
+ return SUCCEED;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Dclose(did);
+ } H5E_END_TRY;
+
+ H5_FAILED();
+ return FAIL;
+
+} /* check_configuration() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_evict_on_close_api()
+ *
+ * Purpose: Verify that the H5Pset/get_evict_on_close() calls behave
+ * correctly.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Spring 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+check_evict_on_close_api(void)
+{
+ hid_t fapl_id = -1;
+ hid_t dapl_id = -1;
+ hbool_t evict_on_close;
+ herr_t status;
+
+ TESTING("evict on close API");
+
+ /* Create a fapl */
+ if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ TEST_ERROR;
+
+ /* Check the default */
+ evict_on_close = TRUE;
+ if(H5Pget_evict_on_close(fapl_id, &evict_on_close) < 0)
+ TEST_ERROR;
+ if(evict_on_close != FALSE)
+ FAIL_PUTS_ERROR("Incorrect default evict on close value.");
+
+ /* Set the evict on close property */
+ evict_on_close = TRUE;
+ if(H5Pset_evict_on_close(fapl_id, evict_on_close) < 0)
+ TEST_ERROR;
+
+ /* Make sure we can get it back out */
+ evict_on_close = FALSE;
+ if(H5Pget_evict_on_close(fapl_id, &evict_on_close) < 0)
+ TEST_ERROR;
+ if(evict_on_close != TRUE)
+ FAIL_PUTS_ERROR("Incorrect evict on close value.");
+
+ /* close fapl */
+ if(H5Pclose(fapl_id) < 0)
+ TEST_ERROR;
+
+ /**********************************************/
+ /* Trying passing in a non-fapl property list */
+ /**********************************************/
+
+ if((dapl_id = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ TEST_ERROR;
+
+ /* ensure using an incorrect access plist fails */
+ H5E_BEGIN_TRY {
+ status = H5Pset_evict_on_close(dapl_id, evict_on_close);
+ } H5E_END_TRY;
+ if(status >= 0)
+ FAIL_PUTS_ERROR("H5Pset_evict_on_close() accepted invalid access plist.");
+
+ /* ensure an invalid plist fails */
+ H5E_BEGIN_TRY {
+ status = H5Pget_evict_on_close((hid_t)-1, &evict_on_close);
+ } H5E_END_TRY;
+ if(status >= 0)
+ FAIL_PUTS_ERROR("H5Pget_evict_on_close() accepted invalid hid_t.");
+
+ /* close dapl */
+ if(H5Pclose(dapl_id) < 0)
+ TEST_ERROR;
+
+ PASSED();
+ return SUCCEED;
+
+error:
+ H5_FAILED();
+ return FAIL;
+
+} /* check_evict_on_close_api() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Return: EXIT_FAILURE/EXIT_SUCCESS
+ *
+ * Programmer: Dana Robinson
+ * Spring 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ hid_t fapl_id = -1; /* VFD-specific fapl */
+ hid_t fid = -1; /* file ID */
+ unsigned nerrors = 0; /* number of test errors */
+
+ HDprintf("Testing evict-on-close cache behavior.\n");
+
+ /* Initialize */
+ h5_reset();
+
+ /* Test H5P call to set up EoC (does not require VFD-specific fapl) */
+ nerrors += check_evict_on_close_api() < 0 ? 1 : 0;
+
+ /* Set up VFD-specific fapl */
+ if((fapl_id = h5_fileaccess()) < 0) {
+ nerrors++;
+ PUTS_ERROR("Unable to get VFD-specific fapl\n");
+ } /* end if */
+
+ /* Set evict-on-close property */
+ if(H5Pset_evict_on_close(fapl_id, TRUE) < 0) {
+ nerrors++;
+ PUTS_ERROR("Unable to set evict-on-close property\n");
+ } /* end if */
+
+ /*************************/
+ /* Test EoC for datasets */
+ /*************************/
+
+ /* Generate the test file */
+ if((fid = generate_eoc_test_file(fapl_id)) < 0) {
+ nerrors++;
+ PUTS_ERROR("Unable to generate test file\n");
+ } /* end if */
+
+ /* Run tests with a variety of dataset configurations
+ * PASSED() and H5_FAILED() are handled in check_configuration()
+ */
+ TESTING("evict on close with version 1 B-tree chunk index");
+ nerrors += check_configuration(fid, DSET_BTREE_NAME) < 0 ? 1 : 0;
+ TESTING("evict on close with extensible array chunk index");
+ nerrors += check_configuration(fid, DSET_EARRAY_NAME) < 0 ? 1 : 0;
+ TESTING("evict on close with version 2 B-tree chunk index");
+ nerrors += check_configuration(fid, DSET_BT2_NAME) < 0 ? 1 : 0;
+ TESTING("evict on close with fixed array chunk index");
+ nerrors += check_configuration(fid, DSET_FARRAY_NAME) < 0 ? 1 : 0;
+ TESTING("evict on close with \'single chunk\' chunk index");
+ nerrors += check_configuration(fid, DSET_SINGLE_NAME) < 0 ? 1 : 0;
+ TESTING("evict on close with contiguous layout");
+ nerrors += check_configuration(fid, DSET_CONTIGUOUS_NAME) < 0 ? 1 : 0;
+ TESTING("evict on close with compact layout");
+ nerrors += check_configuration(fid, DSET_COMPACT_NAME) < 0 ? 1 : 0;
+
+ /* Close the test file */
+ if(H5Fclose(fid) < 0) {
+ nerrors++;
+ PUTS_ERROR("Unable to close the test file.\n");
+ } /* end if */
+
+ /* Clean up files and close the VFD-specific fapl */
+ h5_delete_all_test_files(FILENAMES, fapl_id);
+ if(H5Pclose(fapl_id) < 0) {
+ nerrors++;
+ PUTS_ERROR("Unable to close VFD-specific fapl.\n");
+ } /* end if */
+
+ if(nerrors)
+ goto error;
+
+ HDprintf("All evict-on-close tests passed.\n");
+
+ return EXIT_SUCCESS;
+
+error:
+
+ HDprintf("***** %u evict-on-close test%s FAILED! *****\n",
+ nerrors, nerrors > 1 ? "S" : "");
+
+ h5_delete_all_test_files(FILENAMES, fapl_id);
+ H5E_BEGIN_TRY {
+ H5Fclose(fid);
+ H5Pclose(fapl_id);
+ } H5E_END_TRY;
+
+ return EXIT_FAILURE;
+
+} /* end main() */
+
diff --git a/test/h5test.c b/test/h5test.c
index 2ab8855..c126da8 100644
--- a/test/h5test.c
+++ b/test/h5test.c
@@ -199,7 +199,7 @@ h5_clean_files(const char *base_name[], hid_t fapl)
*
* Purpose Clean up temporary test files.
*
- * When a test calls h5_fixname() get a VFD-dependent
+ * When a test calls h5_fixname() to get a VFD-dependent
* test file name, this function can be used to clean it up.
*
* Return: void