summaryrefslogtreecommitdiffstats
path: root/src/H5C.c
diff options
context:
space:
mode:
authorLarry Knox <lrknox@hdfgroup.org>2020-10-16 22:47:27 (GMT)
committerLarry Knox <lrknox@hdfgroup.org>2020-10-16 22:47:27 (GMT)
commitdb30c2da68ece4a155e9e50c28ec16d6057509b2 (patch)
tree1d36f673c36dfee71c266bba39511da21ecc782e /src/H5C.c
parent5b9cf732caab9daa6ed1e00f2df4f5a792340196 (diff)
parent2e2b87d1cbdee3b919e6e5cba6c5ecd1b9434434 (diff)
downloadhdf5-db30c2da68ece4a155e9e50c28ec16d6057509b2.zip
hdf5-db30c2da68ece4a155e9e50c28ec16d6057509b2.tar.gz
hdf5-db30c2da68ece4a155e9e50c28ec16d6057509b2.tar.bz2
Merge HDF5 1.10.7 release files into 1.10/masterhdf5-1_10_7
Diffstat (limited to 'src/H5C.c')
-rw-r--r--src/H5C.c2295
1 files changed, 1665 insertions, 630 deletions
diff --git a/src/H5C.c b/src/H5C.c
index 288f3db..20182da 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -168,7 +168,7 @@ static herr_t H5C__verify_len_eoa(H5F_t *f, const H5C_class_t * type,
haddr_t addr, size_t *len, hbool_t actual);
#if H5C_DO_SLIST_SANITY_CHECKS
-static hbool_t H5C_entry_in_skip_list(H5C_t * cache_ptr,
+static hbool_t H5C_entry_in_skip_list(H5C_t * cache_ptr,
H5C_cache_entry_t *target_ptr);
#endif /* H5C_DO_SLIST_SANITY_CHECKS */
@@ -234,6 +234,82 @@ H5FL_BLK_DEFINE_STATIC(parent);
* Programmer: John Mainzer
* 6/2/04
*
+ * Modifications:
+ *
+ * JRM -- 7/20/04
+ * Updated for the addition of the hash table.
+ *
+ * JRM -- 10/5/04
+ * Added call to H5C_reset_cache_hit_rate_stats(). Also
+ * added initialization for cache_is_full flag and for
+ * resize_ctl.
+ *
+ * JRM -- 11/12/04
+ * Added initialization for the new size_decreased field.
+ *
+ * JRM -- 11/17/04
+ * Added/updated initialization for the automatic cache
+ * size control data structures.
+ *
+ * JRM -- 6/24/05
+ * Added support for the new write_permitted field of
+ * the H5C_t structure.
+ *
+ * JRM -- 7/5/05
+ * Added the new log_flush parameter and supporting code.
+ *
+ * JRM -- 9/21/05
+ * Added the new aux_ptr parameter and supporting code.
+ *
+ * JRM -- 1/20/06
+ * Added initialization of the new prefix field in H5C_t.
+ *
+ * JRM -- 3/16/06
+ * Added initialization for the pinned entry related fields.
+ *
+ * JRM -- 5/31/06
+ * Added initialization for the trace_file_ptr field.
+ *
+ * JRM -- 8/19/06
+ * Added initialization for the flush_in_progress field.
+ *
+ * JRM -- 8/25/06
+ * Added initialization for the slist_len_increase and
+ * slist_size_increase fields. These fields are used
+ * for sanity checking in the flush process, and are not
+ * compiled in unless H5C_DO_SANITY_CHECKS is TRUE.
+ *
+ * JRM -- 3/28/07
+ * Added initialization for the new is_read_only and
+ * ro_ref_count fields.
+ *
+ * JRM -- 7/27/07
+ * Added initialization for the new evictions_enabled
+ * field of H5C_t.
+ *
+ * JRM -- 12/31/07
+ * Added initialization for the new flash cache size increase
+ * related fields of H5C_t.
+ *
+ * JRM -- 11/5/08
+ * Added initialization for the new clean_index_size and
+ * dirty_index_size fields of H5C_t.
+ *
+ *
+ * Missing entries?
+ *
+ *
+ * JRM -- 4/20/20
+ * Added initialization for the slist_enabled field. Recall
+ * that the slist is used to flush metadata cache entries
+ * in (roughly) increasing address order. While this is
+ * needed at flush and close, it is not used elsewhere.
+ * The slist_enabled field exists to allow us to construct
+ * the slist when needed, and leave it empty otherwise -- thus
+ * avoiding the overhead of maintaining it.
+ *
+ * JRM -- 4/29/20
+ *
*-------------------------------------------------------------------------
*/
H5C_t *
@@ -308,30 +384,36 @@ H5C_create(size_t max_cache_size,
cache_ptr->dirty_index_size = (size_t)0;
for(i = 0; i < H5C_RING_NTYPES; i++) {
- cache_ptr->index_ring_len[i] = 0;
- cache_ptr->index_ring_size[i] = (size_t)0;
- cache_ptr->clean_index_ring_size[i] = (size_t)0;
- cache_ptr->dirty_index_ring_size[i] = (size_t)0;
+ cache_ptr->index_ring_len[i] = 0;
+ cache_ptr->index_ring_size[i] = (size_t)0;
+ cache_ptr->clean_index_ring_size[i] = (size_t)0;
+ cache_ptr->dirty_index_ring_size[i] = (size_t)0;
- cache_ptr->slist_ring_len[i] = 0;
- cache_ptr->slist_ring_size[i] = (size_t)0;
+ cache_ptr->slist_ring_len[i] = 0;
+ cache_ptr->slist_ring_size[i] = (size_t)0;
} /* end for */
for(i = 0; i < H5C__HASH_TABLE_LEN; i++)
(cache_ptr->index)[i] = NULL;
- cache_ptr->il_len = 0;
- cache_ptr->il_size = (size_t)0;
- cache_ptr->il_head = NULL;
- cache_ptr->il_tail = NULL;
+ cache_ptr->il_len = 0;
+ cache_ptr->il_size = (size_t)0;
+ cache_ptr->il_head = NULL;
+ cache_ptr->il_tail = NULL;
/* Tagging Field Initializations */
cache_ptr->ignore_tags = FALSE;
cache_ptr->num_objs_corked = 0;
- cache_ptr->slist_changed = FALSE;
- cache_ptr->slist_len = 0;
- cache_ptr->slist_size = (size_t)0;
+ /* slist field initializations */
+ cache_ptr->slist_enabled = ! H5C__SLIST_OPT_ENABLED;
+ cache_ptr->slist_changed = FALSE;
+ cache_ptr->slist_len = 0;
+ cache_ptr->slist_size = (size_t)0;
+
+ /* slist_ring_len, slist_ring_size, and
+ * slist_ptr initializaed above.
+ */
#if H5C_DO_SANITY_CHECKS
cache_ptr->slist_len_increase = 0;
@@ -719,10 +801,10 @@ H5C_free_tag_list_cb(void *_item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED
*
* Function: H5C_prep_for_file_close
*
- * Purpose: This function should be called just prior to the cache
- * flushes at file close. There should be no protected
+ * Purpose: This function should be called just prior to the cache
+ * flushes at file close. There should be no protected
* entries in the cache at this point.
- *
+ *
* Return: Non-negative on success/Negative on failure
*
* Programmer: John Mainzer
@@ -747,8 +829,8 @@ H5C_prep_for_file_close(H5F_t *f)
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
- /* For now at least, it is possible to receive the
- * close warning more than once -- the following
+ /* For now at least, it is possible to receive the
+ * close warning more than once -- the following
* if statement handles this.
*/
if(cache_ptr->close_warning_received)
@@ -764,8 +846,8 @@ H5C_prep_for_file_close(H5F_t *f)
#ifdef H5_HAVE_PARALLEL
if ( ( H5F_INTENT(f) & H5F_ACC_RDWR ) &&
- ( ! image_generated ) &&
- ( cache_ptr->aux_ptr != NULL ) &&
+ ( ! image_generated ) &&
+ ( cache_ptr->aux_ptr != NULL ) &&
( f->shared->fs_persist ) ) {
/* If persistent free space managers are enabled, flushing the
* metadata cache may result in the deletion, insertion, and/or
@@ -825,6 +907,20 @@ done:
* Programmer: John Mainzer
* 6/2/04
*
+ * Modifications:
+ *
+ * JRM -- 5/15/20
+ *
+ * Updated the function to enable the slist prior to the
+ * call to H5C__flush_invalidate_cache().
+ *
+ * Arguably, it shouldn't be necessary to re-enable the
+ * slist after the call to H5C__flush_invalidate_cache(), as
+ * the metadata cache should be discarded. However, in the
+ * test code, we make multiple calls to H5C_dest(). Thus
+ * we re-enable the slist on failure if it and the cache
+ * still exist.
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -845,33 +941,60 @@ H5C_dest(H5F_t * f)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't display cache image stats")
#endif /* H5AC_DUMP_IMAGE_STATS_ON_CLOSE */
+ /* Enable the slist, as it is needed in the flush */
+ if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist enabled failed")
+
/* Flush and invalidate all cache entries */
- if(H5C__flush_invalidate_cache(f, H5C__NO_FLAGS_SET) < 0 )
+ if ( H5C__flush_invalidate_cache(f, H5C__NO_FLAGS_SET) < 0 )
+
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
/* Generate & write cache image if requested */
- if(cache_ptr->image_ctl.generate_image)
- if(H5C__generate_cache_image(f, cache_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "Can't generate metadata cache image")
+ if ( cache_ptr->image_ctl.generate_image ) {
+
+ if ( H5C__generate_cache_image(f, cache_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, \
+ "Can't generate metadata cache image")
+ }
+
+ /* Question: Is it possible for cache_ptr->slist be non-null at this
+ * point? If no, shouldn't this if statement be an assert?
+ */
+ if ( cache_ptr->slist_ptr != NULL ) {
+
+ HDassert(cache_ptr->slist_len == 0);
+ HDassert(cache_ptr->slist_size == 0);
- if(cache_ptr->slist_ptr != NULL) {
H5SL_close(cache_ptr->slist_ptr);
+
cache_ptr->slist_ptr = NULL;
+
} /* end if */
if(cache_ptr->tag_list != NULL) {
+
H5SL_destroy(cache_ptr->tag_list, H5C_free_tag_list_cb, NULL);
cache_ptr->tag_list = NULL;
+
} /* end if */
- if(cache_ptr->log_info != NULL)
+ if(cache_ptr->log_info != NULL) {
+
H5MM_xfree(cache_ptr->log_info);
+ }
#ifndef NDEBUG
#if H5C_DO_SANITY_CHECKS
- if(cache_ptr->get_entry_ptr_from_addr_counter > 0)
- HDfprintf(stdout, "*** %ld calls to H5C_get_entry_ptr_from_add(). ***\n",
- cache_ptr->get_entry_ptr_from_addr_counter);
+
+ if ( cache_ptr->get_entry_ptr_from_addr_counter > 0 ) {
+
+ HDfprintf(stdout,
+ "*** %ld calls to H5C_get_entry_ptr_from_add(). ***\n",
+ cache_ptr->get_entry_ptr_from_addr_counter);
+ }
#endif /* H5C_DO_SANITY_CHECKS */
cache_ptr->magic = 0;
@@ -880,7 +1003,19 @@ H5C_dest(H5F_t * f)
cache_ptr = H5FL_FREE(H5C_t, cache_ptr);
done:
+
+ if ( ( ret_value < 0 ) && ( cache_ptr ) && ( cache_ptr->slist_ptr ) ) {
+
+ /* need this for test code -- see change note for details */
+
+ if ( H5C_set_slist_enabled(f->shared->cache, FALSE, FALSE) < 0 )
+
+ HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "disable slist on flush dest failure failed")
+ }
+
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C_dest() */
@@ -894,6 +1029,14 @@ done:
* Programmer: Vailin Choi
* Dec 2013
*
+ * Modifications:
+ *
+ * JRM -- 5/5/20
+ *
+ * Added code to enable the skip list prior to the call
+ * to H5C__flush_invalidate_cache(), and disable it
+ * afterwards.
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -906,9 +1049,22 @@ H5C_evict(H5F_t * f)
/* Sanity check */
HDassert(f);
+ /* Enable the slist, as it is needed in the flush */
+ if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist enabled failed")
+
/* Flush and invalidate all cache entries except the pinned entries */
- if(H5C__flush_invalidate_cache(f, H5C__EVICT_ALLOW_LAST_PINS_FLAG) < 0 )
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to evict entries in the cache")
+ if ( H5C__flush_invalidate_cache(f, H5C__EVICT_ALLOW_LAST_PINS_FLAG) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL,
+ "unable to evict entries in the cache")
+
+ /* Disable the slist,
+ */
+ if ( H5C_set_slist_enabled(f->shared->cache, FALSE, TRUE) < 0)
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist disabled failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1008,31 +1164,31 @@ done:
* Programmer: John Mainzer
* 6/2/04
*
- * Changes: Modified function to test for slist chamges in
+ * Changes: Modified function to test for slist chamges in
* pre_serialize and serialize callbacks, and re-start
* scans through the slist when such changes occur.
*
* This has been a potential problem for some time,
- * and there has been code in this function to deal
- * with elements of this issue. However the shift
+ * and there has been code in this function to deal
+ * with elements of this issue. However the shift
* to the V3 cache in combination with the activities
- * of some of the cache clients (in particular the
+ * of some of the cache clients (in particular the
* free space manager and the fractal heap) have
* made this re-work necessary.
*
* JRM -- 12/13/14
*
- * Modified function to support rings. Basic idea is that
+ * Modified function to support rings. Basic idea is that
* every entry in the cache is assigned to a ring. Entries
- * in the outermost ring are flushed first, followed by
- * those in the next outermost ring, and so on until the
- * innermost ring is flushed. See header comment on
- * H5C_ring_t in H5Cprivate.h for a more detailed
+ * in the outermost ring are flushed first, followed by
+ * those in the next outermost ring, and so on until the
+ * innermost ring is flushed. See header comment on
+ * H5C_ring_t in H5Cprivate.h for a more detailed
* discussion.
*
* JRM -- 8/30/15
*
- * Modified function to call the free space manager
+ * Modified function to call the free space manager
* settling functions.
* JRM -- 6/9/16
*
@@ -1110,7 +1266,7 @@ H5C_flush_cache(H5F_t *f, unsigned flags)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "flush invalidate failed")
} /* end if */
else {
- /* flush each ring, starting from the outermost ring and
+ /* flush each ring, starting from the outermost ring and
* working inward.
*/
ring = H5C_RING_USER;
@@ -1286,7 +1442,7 @@ H5C_insert_entry(H5F_t * f,
insert_pinned = ( (flags & H5C__PIN_ENTRY_FLAG) != 0 );
flush_last = ( (flags & H5C__FLUSH_LAST_FLAG) != 0 );
- /* Get the ring type from the DXPL */
+ /* Get the ring type from the API context */
ring = H5CX_get_ring();
entry_ptr = (H5C_cache_entry_t *)thing;
@@ -2244,7 +2400,7 @@ H5C_protect(H5F_t * f,
if(entry_ptr->prefetched) {
/* This call removes the prefetched entry from the cache,
- * and replaces it with an entry deserialized from the
+ * and replaces it with an entry deserialized from the
* image of the prefetched entry.
*/
if(H5C__deserialize_prefetched_entry(f, cache_ptr, &entry_ptr, type, addr, udata) < 0)
@@ -2285,7 +2441,7 @@ H5C_protect(H5F_t * f,
if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
if(0 == mpi_rank)
if(H5C__generate_image(f, cache_ptr, entry_ptr) < 0)
@@ -2313,15 +2469,15 @@ H5C_protect(H5F_t * f,
if(cache_ptr->ignore_tags != TRUE) {
haddr_t tag; /* Tag value */
- /* The entry is already in the cache, but make sure that the tag value
- is still legal. This will ensure that had
- the entry NOT been in the cache, tagging was still set up correctly
- and it would have received a legal tag value after getting loaded
- from disk. */
+ /* The entry is already in the cache, but make sure that the tag value
+ * is still legal. This will ensure that had the entry NOT been in the
+ * cache, tagging was still set up correctly and it would have received
+ * a legal tag value after getting loaded from disk.
+ */
/* Get the tag */
tag = H5CX_get_tag();
-
+
if(H5C_verify_tag(entry_ptr->type->id, tag) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, NULL, "tag verification failed")
} /* end if */
@@ -2337,9 +2493,9 @@ H5C_protect(H5F_t * f,
hit = FALSE;
- if(NULL == (thing = H5C_load_entry(f,
+ if(NULL == (thing = H5C_load_entry(f,
#ifdef H5_HAVE_PARALLEL
- coll_access,
+ coll_access,
#endif /* H5_HAVE_PARALLEL */
type, addr, udata)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "can't load entry")
@@ -2372,10 +2528,10 @@ H5C_protect(H5F_t * f,
else
empty_space = cache_ptr->max_cache_size - cache_ptr->index_size;
- /* try to free up if necceary and if evictions are permitted. Note
- * that if evictions are enabled, we will call H5C__make_space_in_cache()
- * regardless if the min_free_space requirement is not met.
- */
+ /* try to free up if necceary and if evictions are permitted. Note
+ * that if evictions are enabled, we will call H5C__make_space_in_cache()
+ * regardless if the min_free_space requirement is not met.
+ */
if ( ( cache_ptr->evictions_enabled ) &&
( ( (cache_ptr->index_size + entry_ptr->size) >
cache_ptr->max_cache_size)
@@ -2421,10 +2577,10 @@ H5C_protect(H5F_t * f,
*
* Second, when writes are not permitted it is also possible
* for the cache to grow without bound.
- *
- * Third, the user may choose to disable evictions -- causing
- * the cache to grow without bound until evictions are
- * re-enabled.
+ *
+ * Third, the user may choose to disable evictions -- causing
+ * the cache to grow without bound until evictions are
+ * re-enabled.
*
* Finally, we usually don't check to see if the cache is
* oversized at the end of an unprotect. As a result, it is
@@ -2448,12 +2604,12 @@ H5C_protect(H5F_t * f,
* *******************************************
*
* Set the flush_last field
- * of the newly loaded entry before inserting it into the
- * index. Must do this, as the index tracked the number of
- * entries with the flush_last field set, but assumes that
+ * of the newly loaded entry before inserting it into the
+ * index. Must do this, as the index tracked the number of
+ * entries with the flush_last field set, but assumes that
* the field will not change after insertion into the index.
*
- * Note that this means that the H5C__FLUSH_LAST_FLAG flag
+ * Note that this means that the H5C__FLUSH_LAST_FLAG flag
* is ignored if the entry is already in cache.
*/
entry_ptr->flush_me_last = flush_last;
@@ -2485,7 +2641,7 @@ H5C_protect(H5F_t * f,
HDassert(entry_ptr->ro_ref_count > 0);
(entry_ptr->ro_ref_count)++;
} /* end if */
- else
+ else
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, "Target already protected & not read only?!?")
} /* end if */
else {
@@ -2878,6 +3034,179 @@ done:
/*-------------------------------------------------------------------------
+ *
+ * Function: H5C_set_slist_enabled()
+ *
+ * Purpose: Enable or disable the slist as directed.
+ *
+ * The slist (skip list) is an address ordered list of
+ * dirty entries in the metadata cache. However, this
+ * list is only needed during flush and close, where we
+ * use it to write entries in more or less increasing
+ * address order.
+ *
+ * This function sets up and enables further operations
+ * on the slist, or disable the slist. This in turn
+ * allows us to avoid the overhead of maintaining the
+ * slist when it is not needed.
+ *
+ *
+ * If the slist_enabled parameter is TRUE, the function
+ *
+ * 1) Verifies that the slist is empty.
+ *
+ * 2) Scans the index list, and inserts all dirty entries
+ * into the slist.
+ *
+ * 3) Sets cache_ptr->slist_enabled = TRUE.
+ *
+ * Note that the clear_slist parameter is ignored if
+ * the slist_enabed parameter is TRUE.
+ *
+ *
+ * If the slist_enabled_parameter is FALSE, the function
+ * shuts down the slist.
+ *
+ * Normally the slist will be empty at this point, however
+ * that need not be the case if H5C_flush_cache() has been
+ * called with the H5C__FLUSH_MARKED_ENTRIES_FLAG.
+ *
+ * Thus shutdown proceeds as follows:
+ *
+ * 1) Test to see if the slist is empty. If it is, proceed
+ * to step 3.
+ *
+ * 2) Test to see if the clear_slist parameter is TRUE.
+ *
+ * If it is, remove all entries from the slist.
+ *
+ * If it isn't, throw an error.
+ *
+ * 3) set cache_ptr->slist_enabled = FALSE.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: John Mainzer
+ * 5/1/20
+ *
+ * Modifications:
+ *
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_set_slist_enabled(H5C_t *cache_ptr, hbool_t slist_enabled,
+ hbool_t clear_slist)
+{
+ H5C_cache_entry_t * entry_ptr;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C__H5C_T_MAGIC ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry")
+
+#if H5C__SLIST_OPT_ENABLED
+
+ if ( slist_enabled ) {
+
+ if ( cache_ptr->slist_enabled ) {
+
+ HDassert(FALSE);
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist already enabled?")
+ }
+
+ if ( ( cache_ptr->slist_len != 0 ) ||
+ ( cache_ptr->slist_size != 0 ) ) {
+
+ HDassert(FALSE);
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist not empty (1)?")
+ }
+
+
+ /* set cache_ptr->slist_enabled to TRUE so that the slist
+ * mainenance macros will be enabled.
+ */
+ cache_ptr->slist_enabled = TRUE;
+
+
+ /* scan the index list and insert all dirty entries in the slist */
+ entry_ptr = cache_ptr->il_head;
+
+ while ( entry_ptr != NULL ) {
+
+ HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
+
+ if ( entry_ptr->is_dirty ) {
+
+ H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
+ }
+
+ entry_ptr = entry_ptr->il_next;
+ }
+
+ /* we don't maintain a dirty index len, so we can't do a cross
+ * check against it. Note that there is no point in cross checking
+ * against the dirty LRU size, as the dirty LRU may not be maintained,
+ * and in any case, there is no requirement that all dirty entries
+ * will reside on the dirty LRU.
+ */
+ HDassert( cache_ptr->dirty_index_size == cache_ptr->slist_size );
+
+ } else { /* take down the skip list */
+
+ if ( ! cache_ptr->slist_enabled ) {
+
+ HDassert(FALSE);
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist already disabled?")
+ }
+
+ if ( ( cache_ptr->slist_len != 0 ) ||
+ ( cache_ptr->slist_size != 0 ) ) {
+
+ if ( clear_slist ) {
+
+ H5SL_node_t *node_ptr;
+
+ node_ptr = H5SL_first(cache_ptr->slist_ptr);
+
+ while ( node_ptr != NULL ) {
+
+ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE);
+
+ node_ptr = H5SL_first(cache_ptr->slist_ptr);
+ }
+ } else {
+
+ HDassert(FALSE);
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist not empty (2)?")
+ }
+ }
+
+ cache_ptr->slist_enabled = FALSE;
+
+ HDassert( 0 == cache_ptr->slist_len );
+ HDassert( 0 == cache_ptr->slist_size );
+ }
+
+#else /* H5C__SLIST_OPT_ENABLED is FALSE */
+
+ HDassert(cache_ptr->slist_enabled);
+
+#endif /* H5C__SLIST_OPT_ENABLED is FALSE */
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C_set_slist_enabled() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5C_unpin_entry()
*
* Purpose: Unpin a cache entry. The entry can be either protected or
@@ -2888,8 +3217,8 @@ done:
* Programmer: John Mainzer
* 3/22/06
*
- * Changes: Added extreme sanity checks on entry and exit.
- JRM -- 4/26/14
+ * Changes: Added extreme sanity checks on entry and exit.
+ * JRM -- 4/26/14
*
*-------------------------------------------------------------------------
*/
@@ -2955,6 +3284,81 @@ done:
* Programmer: John Mainzer
* 6/2/04
*
+ * Modifications:
+ *
+ * JRM -- 7/21/04
+ * Updated for the addition of the hash table.
+ *
+ * JRM -- 10/28/04
+ * Added code to set cache_full to TRUE whenever we try to
+ * make space in the cache.
+ *
+ * JRM -- 11/12/04
+ * Added code to call to H5C_make_space_in_cache() after the
+ * call to H5C__auto_adjust_cache_size() if that function
+ * sets the size_decreased flag is TRUE.
+ *
+ * JRM -- 4/25/05
+ * The size_decreased flag can also be set to TRUE in
+ * H5C_set_cache_auto_resize_config() if a new configuration
+ * forces an immediate reduction in cache size. Modified
+ * the code to deal with this eventuallity.
+ *
+ * JRM -- 6/24/05
+ * Added support for the new write_permitted field of H5C_t.
+ *
+ * JRM -- 10/22/05
+ * Hand optimizations.
+ *
+ * JRM -- 5/3/06
+ * Added code to set the new dirtied field in
+ * H5C_cache_entry_t to FALSE prior to return.
+ *
+ * JRM -- 6/23/06
+ * Modified code to allow dirty entries to be loaded from
+ * disk. This is necessary as a bug fix in the object
+ * header code requires us to modify a header as it is read.
+ *
+ * JRM -- 3/28/07
+ * Added the flags parameter and supporting code. At least
+ * for now, this parameter is used to allow the entry to
+ * be protected read only, thus allowing multiple protects.
+ *
+ * Also added code to allow multiple read only protects
+ * of cache entries.
+ *
+ * JRM -- 7/27/07
+ * Added code supporting the new evictions_enabled field
+ * in H5C_t.
+ *
+ * JRM -- 1/3/08
+ * Added to do a flash cache size increase if appropriate
+ * when a large entry is loaded.
+ *
+ * JRM -- 11/13/08
+ * Modified function to call H5C_make_space_in_cache() when
+ * the min_clean_size is violated, not just when there isn't
+ * enough space for and entry that has just been loaded.
+ *
+ * The purpose of this modification is to avoid "metadata
+ * blizzards" in the write only case. In such instances,
+ * the cache was allowed to fill with dirty metadata. When
+ * we finally needed to evict an entry to make space, we had
+ * to flush out a whole cache full of metadata -- which has
+ * interesting performance effects. We hope to avoid (or
+ * perhaps more accurately hide) this effect by maintaining
+ * the min_clean_size, which should force us to start flushing
+ * entries long before we actually have to evict something
+ * to make space.
+ *
+ *
+ * Missing entries?
+ *
+ *
+ * JRM -- 5/8/20
+ * Updated for the possibility that the slist will be
+ * disabled.
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -2996,9 +3400,15 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags)
HDassert( H5F_addr_defined(addr) );
HDassert( thing );
HDassert( ! ( pin_entry && unpin_entry ) );
- HDassert( ( ! free_file_space ) || ( deleted ) ); /* deleted flag must accompany free_file_space */
- HDassert( ( ! take_ownership ) || ( deleted ) ); /* deleted flag must accompany take_ownership */
- HDassert( ! ( free_file_space && take_ownership ) ); /* can't have both free_file_space & take_ownership */
+
+ /* deleted flag must accompany free_file_space */
+ HDassert( ( ! free_file_space ) || ( deleted ) );
+
+ /* deleted flag must accompany take_ownership */
+ HDassert( ( ! take_ownership ) || ( deleted ) );
+
+ /* can't have both free_file_space & take_ownership */
+ HDassert( ! ( free_file_space && take_ownership ) );
entry_ptr = (H5C_cache_entry_t *)thing;
@@ -3011,48 +3421,66 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags)
was_clean = ! ( entry_ptr->is_dirty );
#if H5C_DO_EXTREME_SANITY_CHECKS
- if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
- (H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
- (H5C_validate_lru_list(cache_ptr) < 0))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry")
+ if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) ||
+ ( H5C_validate_pinned_entry_list(cache_ptr) < 0 ) ||
+ ( H5C_validate_lru_list(cache_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "an extreme sanity check failed on entry")
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
/* if the entry has multiple read only protects, just decrement
* the ro_ref_counter. Don't actually unprotect until the ref count
* drops to zero.
*/
- if(entry_ptr->ro_ref_count > 1) {
+ if ( entry_ptr->ro_ref_count > 1 ) {
+
/* Sanity check */
- HDassert(entry_ptr->is_protected);
+ HDassert(entry_ptr->is_protected);
HDassert(entry_ptr->is_read_only);
- if(dirtied)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Read only entry modified??")
+ if ( dirtied )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "Read only entry modified??")
/* Reduce the RO ref count */
- (entry_ptr->ro_ref_count)--;
+ (entry_ptr->ro_ref_count)--;
/* Pin or unpin the entry as requested. */
- if(pin_entry) {
+ if ( pin_entry ) {
+
/* Pin the entry from a client */
- if(H5C__pin_entry_from_client(cache_ptr, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "Can't pin entry by client")
- } else if(unpin_entry) {
+ if ( H5C__pin_entry_from_client(cache_ptr, entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, \
+ "Can't pin entry by client")
+
+ } else if ( unpin_entry ) {
+
/* Unpin the entry from a client */
- if(H5C__unpin_entry_from_client(cache_ptr, entry_ptr, FALSE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "Can't unpin entry by client")
+ if ( H5C__unpin_entry_from_client(cache_ptr, entry_ptr, FALSE) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, \
+ "Can't unpin entry by client")
+
} /* end if */
} else {
- if(entry_ptr->is_read_only) {
+
+ if ( entry_ptr->is_read_only ) {
+
/* Sanity check */
- HDassert(entry_ptr->ro_ref_count == 1);
+ HDassert(entry_ptr->ro_ref_count == 1);
- if(dirtied)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Read only entry modified??")
+ if ( dirtied )
- entry_ptr->is_read_only = FALSE;
- entry_ptr->ro_ref_count = 0;
- } /* end if */
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "Read only entry modified??")
+
+ entry_ptr->is_read_only = FALSE;
+ entry_ptr->ro_ref_count = 0;
+
+ } /* end if */
#ifdef H5_HAVE_PARALLEL
/* When the H5C code is used to implement the metadata cache in the
@@ -3080,63 +3508,102 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags)
} /* end if */
#endif /* H5_HAVE_PARALLEL */
- if(!entry_ptr->is_protected)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Entry already unprotected??")
+ if ( ! entry_ptr->is_protected )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "Entry already unprotected??")
/* Mark the entry as dirty if appropriate */
entry_ptr->is_dirty = (entry_ptr->is_dirty || dirtied);
- if(dirtied)
- if(entry_ptr->image_up_to_date) {
- entry_ptr->image_up_to_date = FALSE;
- if(entry_ptr->flush_dep_nparents > 0)
- if(H5C__mark_flush_dep_unserialized(entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate serialization status to fd parents")
+ if ( dirtied ) {
+
+ if ( entry_ptr->image_up_to_date ) {
+
+ entry_ptr->image_up_to_date = FALSE;
+
+ if ( entry_ptr->flush_dep_nparents > 0 ) {
+
+ if ( H5C__mark_flush_dep_unserialized(entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "Can't propagate serialization status to fd parents")
+
+ } /* end if */
} /* end if */
+ } /* end if */
/* Check for newly dirtied entry */
- if(was_clean && entry_ptr->is_dirty) {
+ if ( was_clean && entry_ptr->is_dirty ) {
+
/* Update index for newly dirtied entry */
H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr)
- /* If the entry's type has a 'notify' callback send a 'entry dirtied'
- * notice now that the entry is fully integrated into the cache.
+ /* If the entry's type has a 'notify' callback send a
+ * 'entry dirtied' notice now that the entry is fully
+ * integrated into the cache.
*/
- if(entry_ptr->type->notify &&
- (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_DIRTIED, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag set")
+ if ( ( entry_ptr->type->notify ) &&
+ ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_DIRTIED,
+ entry_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "can't notify client about entry dirty flag set")
/* Propagate the flush dep dirty flag up the flush dependency chain
- * if appropriate */
- if(entry_ptr->flush_dep_nparents > 0)
- if(H5C__mark_flush_dep_dirty(entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "Can't propagate flush dep dirty flag")
- } /* end if */
+ * if appropriate
+ */
+ if ( entry_ptr->flush_dep_nparents > 0 ) {
+
+ if ( H5C__mark_flush_dep_dirty(entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \
+ "Can't propagate flush dep dirty flag")
+ }
+ } /* end if */
/* Check for newly clean entry */
- else if(!was_clean && !entry_ptr->is_dirty) {
- /* If the entry's type has a 'notify' callback send a 'entry cleaned'
- * notice now that the entry is fully integrated into the cache.
+ else if ( ! was_clean && ! entry_ptr->is_dirty ) {
+
+ /* If the entry's type has a 'notify' callback send a
+ * 'entry cleaned' notice now that the entry is fully
+ * integrated into the cache.
*/
- if(entry_ptr->type->notify &&
- (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag cleared")
+ if ( ( entry_ptr->type->notify ) &&
+ ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED,
+ entry_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "can't notify client about entry dirty flag cleared")
/* Propagate the flush dep clean flag up the flush dependency chain
- * if appropriate */
- if(entry_ptr->flush_dep_nparents > 0)
- if(H5C__mark_flush_dep_clean(entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "Can't propagate flush dep dirty flag")
+ * if appropriate
+ */
+ if ( entry_ptr->flush_dep_nparents > 0 ) {
+
+ if ( H5C__mark_flush_dep_clean(entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \
+ "Can't propagate flush dep dirty flag")
+
+ }
} /* end else-if */
/* Pin or unpin the entry as requested. */
- if(pin_entry) {
+ if ( pin_entry ) {
+
/* Pin the entry from a client */
- if(H5C__pin_entry_from_client(cache_ptr, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "Can't pin entry by client")
- } else if(unpin_entry) {
+ if ( H5C__pin_entry_from_client(cache_ptr, entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, \
+ "Can't pin entry by client")
+
+ } else if ( unpin_entry ) {
+
/* Unpin the entry from a client */
- if(H5C__unpin_entry_from_client(cache_ptr, entry_ptr, FALSE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "Can't unpin entry by client")
+ if ( H5C__unpin_entry_from_client(cache_ptr, entry_ptr, FALSE) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, \
+ "Can't unpin entry by client")
} /* end if */
/* H5C__UPDATE_RP_FOR_UNPROTECT will place the unprotected entry on
@@ -3149,10 +3616,15 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags)
/* if the entry is dirty, 'or' its flush_marker with the set flush flag,
* and then add it to the skip list if it isn't there already.
*/
- if(entry_ptr->is_dirty) {
+ if ( entry_ptr->is_dirty ) {
+
entry_ptr->flush_marker |= set_flush_marker;
- if(!entry_ptr->in_slist)
+
+ if ( !entry_ptr->in_slist ) {
+
+ /* this is a no-op if cache_ptr->slist_enabled is FALSE */
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
+ }
} /* end if */
/* this implementation of the "deleted" option is a bit inefficient, as
@@ -3164,44 +3636,71 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags)
* makes good use of existing code.
* JRM - 5/19/04
*/
- if(deleted) {
- unsigned flush_flags = (H5C__FLUSH_CLEAR_ONLY_FLAG |
- H5C__FLUSH_INVALIDATE_FLAG);
+ if ( deleted ) {
+
+ unsigned flush_flags = (H5C__FLUSH_CLEAR_ONLY_FLAG |
+ H5C__FLUSH_INVALIDATE_FLAG);
/* verify that the target entry is in the cache. */
H5C__SEARCH_INDEX(cache_ptr, addr, test_entry_ptr, FAIL)
- if(test_entry_ptr == NULL)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "entry not in hash table?!?")
- else if(test_entry_ptr != entry_ptr)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "hash table contains multiple entries for addr?!?")
+
+ if ( test_entry_ptr == NULL )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "entry not in hash table?!?")
+
+ else if ( test_entry_ptr != entry_ptr )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "hash table contains multiple entries for addr?!?")
/* Set the 'free file space' flag for the flush, if needed */
- if(free_file_space)
+ if ( free_file_space ) {
+
flush_flags |= H5C__FREE_FILE_SPACE_FLAG;
+ }
/* Set the "take ownership" flag for the flush, if needed */
- if(take_ownership)
+ if ( take_ownership ) {
+
flush_flags |= H5C__TAKE_OWNERSHIP_FLAG;
+ }
/* Delete the entry from the skip list on destroy */
flush_flags |= H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG;
- HDassert(((!was_clean) || dirtied) == entry_ptr->in_slist);
- if(H5C__flush_single_entry(f, entry_ptr, flush_flags) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Can't flush entry")
+ HDassert( ( ! cache_ptr->slist_enabled ) || \
+ ( ( ( ! was_clean ) || dirtied ) == \
+ ( entry_ptr->in_slist ) ) );
+
+ if ( H5C__flush_single_entry(f, entry_ptr, flush_flags) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "Can't flush entry")
+
} /* end if */
#ifdef H5_HAVE_PARALLEL
- else if(clear_entry) {
+ else if ( clear_entry ) {
/* verify that the target entry is in the cache. */
H5C__SEARCH_INDEX(cache_ptr, addr, test_entry_ptr, FAIL)
- if(test_entry_ptr == NULL)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "entry not in hash table?!?")
- else if(test_entry_ptr != entry_ptr)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "hash table contains multiple entries for addr?!?")
- if(H5C__flush_single_entry(f, entry_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Can't clear entry")
+ if ( test_entry_ptr == NULL )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "entry not in hash table?!?")
+
+ else if ( test_entry_ptr != entry_ptr )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "hash table contains multiple entries for addr?!?")
+
+ if ( H5C__flush_single_entry(f, entry_ptr,
+ H5C__FLUSH_CLEAR_ONLY_FLAG |
+ H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0 )
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "Can't clear entry")
+
} /* end else if */
#endif /* H5_HAVE_PARALLEL */
}
@@ -3209,14 +3708,18 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags)
H5C__UPDATE_STATS_FOR_UNPROTECT(cache_ptr)
done:
+
#if H5C_DO_EXTREME_SANITY_CHECKS
- if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
- (H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
- (H5C_validate_lru_list(cache_ptr) < 0)) {
- HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit")
+ if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) ||
+ ( H5C_validate_pinned_entry_list(cache_ptr) < 0 ) ||
+ ( H5C_validate_lru_list(cache_ptr) < 0 ) ) {
+
+ HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "an extreme sanity check failed on exit")
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C_unprotect() */
@@ -3962,8 +4465,8 @@ H5C__auto_adjust_cache_size(H5F_t *f, hbool_t write_permitted)
HDassert( (cache_ptr->resize_ctl).min_clean_fraction <= (double)100.0f );
/* check to see if cache_ptr->resize_in_progress is TRUE. If it, this
- * is a re-entrant call via a client callback called in the resize
- * process. To avoid an infinite recursion, set reentrant_call to
+ * is a re-entrant call via a client callback called in the resize
+ * process. To avoid an infinite recursion, set reentrant_call to
* TRUE, and goto done.
*/
if(cache_ptr->resize_in_progress) {
@@ -4260,11 +4763,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5C__autoadjust__ageout(H5F_t * f,
- double hit_rate,
- enum H5C_resize_status * status_ptr,
- size_t * new_max_cache_size_ptr,
- hbool_t write_permitted)
+H5C__autoadjust__ageout(H5F_t * f, double hit_rate, enum H5C_resize_status * status_ptr,
+ size_t * new_max_cache_size_ptr, hbool_t write_permitted)
{
H5C_t * cache_ptr = f->shared->cache;
size_t test_size;
@@ -5031,6 +5531,7 @@ done:
/*-------------------------------------------------------------------------
+ *
* Function: H5C__flush_invalidate_cache
*
* Purpose: Flush and destroy the entries contained in the target
@@ -5060,6 +5561,51 @@ done:
* Programmer: John Mainzer
* 3/24/065
*
+ * Modifications:
+ *
+ * To support the fractal heap, the cache must now deal with
+ * entries being dirtied, resized, and/or renamed inside
+ * flush callbacks. Updated function to support this.
+ *
+ * -- JRM 8/27/06
+ *
+ * Added code to detect and manage the case in which a
+ * flush callback changes the s-list out from under
+ * the function. The only way I can think of in which this
+ * can happen is if a flush function loads an entry
+ * into the cache that isn't there already. Quincey tells
+ * me that this will never happen, but I'm not sure I
+ * believe him.
+ *
+ * Note that this is a pretty bad scenario if it ever
+ * happens. The code I have added should allow us to
+ * handle the situation under all but the worst conditions,
+ * but one can argue that we should just scream and die if
+ * we ever detect the condition.
+ *
+ * -- JRM 10/13/07
+ *
+ * Missing entries?
+ *
+ *
+ * Added support for the H5C__EVICT_ALLOW_LAST_PINS_FLAG.
+ * This flag is used to flush and evict all entries in
+ * the metadata cache that are not pinned -- typically,
+ * everything other than the superblock.
+ *
+ * ??? -- ??/??/??
+ *
+ * Added sanity checks to verify that the skip list is
+ * enabled on entry. On the face of it, it would make
+ * sense to enable the slist on entry, and disable it
+ * on exit, as this function is not called repeatedly.
+ * However, since this function can be called from
+ * H5C_flush_cache(), this would create cases in the test
+ * code where we would have to check the flags to determine
+ * whether we must setup and take down the slist.
+ *
+ * JRM -- 5/5/20
+ *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -5077,6 +5623,7 @@ H5C__flush_invalidate_cache(H5F_t *f, unsigned flags)
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->slist_ptr);
+ HDassert(cache_ptr->slist_enabled);
#if H5C_DO_SANITY_CHECKS
{
@@ -5095,7 +5642,8 @@ H5C__flush_invalidate_cache(H5F_t *f, unsigned flags)
HDassert(cache_ptr->slist_ring_len[H5C_RING_UNDEFINED] == 0);
HDassert(cache_ptr->slist_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
- for(i = H5C_RING_USER; i < H5C_RING_NTYPES; i++) {
+ for ( i = H5C_RING_USER; i < H5C_RING_NTYPES; i++ ) {
+
index_len += cache_ptr->index_ring_len[i];
index_size += cache_ptr->index_ring_size[i];
clean_index_size += cache_ptr->clean_index_ring_size[i];
@@ -5103,6 +5651,7 @@ H5C__flush_invalidate_cache(H5F_t *f, unsigned flags)
slist_len += cache_ptr->slist_ring_len[i];
slist_size += cache_ptr->slist_ring_size[i];
+
} /* end for */
HDassert(cache_ptr->index_len == index_len);
@@ -5115,49 +5664,68 @@ H5C__flush_invalidate_cache(H5F_t *f, unsigned flags)
#endif /* H5C_DO_SANITY_CHECKS */
/* remove ageout markers if present */
- if(cache_ptr->epoch_markers_active > 0)
- if(H5C__autoadjust__ageout__remove_all_markers(cache_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "error removing all epoch markers")
+ if ( cache_ptr->epoch_markers_active > 0 ) {
+
+ if ( H5C__autoadjust__ageout__remove_all_markers(cache_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "error removing all epoch markers")
+ }
/* flush invalidate each ring, starting from the outermost ring and
* working inward.
*/
ring = H5C_RING_USER;
- while(ring < H5C_RING_NTYPES) {
+
+ while ( ring < H5C_RING_NTYPES) {
+
if(H5C_flush_invalidate_ring(f, ring, flags) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "flush invalidate ring failed")
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL,
+ "flush invalidate ring failed")
ring++;
+
} /* end while */
/* Invariants, after destroying all entries in the hash table */
- if(!(flags & H5C__EVICT_ALLOW_LAST_PINS_FLAG)) {
+ if( ! ( flags & H5C__EVICT_ALLOW_LAST_PINS_FLAG ) ) {
+
HDassert(cache_ptr->index_size == 0);
HDassert(cache_ptr->clean_index_size == 0);
HDassert(cache_ptr->pel_len == 0);
HDassert(cache_ptr->pel_size == 0);
+
} /* end if */
else {
+
H5C_cache_entry_t *entry_ptr; /* Cache entry */
unsigned u; /* Local index variable */
/* All rings except ring 4 should be empty now */
/* (Ring 4 has the superblock) */
- for(u = H5C_RING_USER; u < H5C_RING_SB; u++) {
+ for ( u = H5C_RING_USER; u < H5C_RING_SB; u++ ) {
+
HDassert(cache_ptr->index_ring_len[u] == 0);
HDassert(cache_ptr->index_ring_size[u] == 0);
HDassert(cache_ptr->clean_index_ring_size[u] == 0);
+
} /* end for */
/* Check that any remaining pinned entries are in the superblock ring */
+
entry_ptr = cache_ptr->pel_head_ptr;
+
while(entry_ptr) {
+
/* Check ring */
HDassert(entry_ptr->ring == H5C_RING_SB);
-
+
/* Advance to next entry in pinned entry list */
entry_ptr = entry_ptr->next;
+
} /* end while */
} /* end else */
+
HDassert(cache_ptr->dirty_index_size == 0);
HDassert(cache_ptr->slist_len == 0);
HDassert(cache_ptr->slist_size == 0);
@@ -5167,43 +5735,59 @@ H5C__flush_invalidate_cache(H5F_t *f, unsigned flags)
HDassert(cache_ptr->LRU_list_size == 0);
done:
+
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C__flush_invalidate_cache() */
/*-------------------------------------------------------------------------
* Function: H5C_flush_invalidate_ring
*
- * Purpose: Flush and destroy the entries contained in the target
- * cache and ring.
+ * Purpose: Flush and destroy the entries contained in the target
+ * cache and ring.
*
- * If the ring contains protected entries, the function will
- * fail, as protected entries cannot be either flushed or
- * destroyed. However all unprotected entries should be
- * flushed and destroyed before the function returns failure.
+ * If the ring contains protected entries, the function will
+ * fail, as protected entries cannot be either flushed or
+ * destroyed. However all unprotected entries should be
+ * flushed and destroyed before the function returns failure.
*
- * While pinned entries can usually be flushed, they cannot
- * be destroyed. However, they should be unpinned when all
- * the entries that reference them have been destroyed (thus
- * reduding the pinned entry's reference count to 0, allowing
- * it to be unpinned).
+ * While pinned entries can usually be flushed, they cannot
+ * be destroyed. However, they should be unpinned when all
+ * the entries that reference them have been destroyed (thus
+ * reduding the pinned entry's reference count to 0, allowing
+ * it to be unpinned).
*
- * If pinned entries are present, the function makes repeated
- * passes through the cache, flushing all dirty entries
- * (including the pinned dirty entries where permitted) and
- * destroying all unpinned entries. This process is repeated
- * until either the cache is empty, or the number of pinned
- * entries stops decreasing on each pass.
+ * If pinned entries are present, the function makes repeated
+ * passes through the cache, flushing all dirty entries
+ * (including the pinned dirty entries where permitted) and
+ * destroying all unpinned entries. This process is repeated
+ * until either the cache is empty, or the number of pinned
+ * entries stops decreasing on each pass.
*
- * If flush dependencies appear in the target ring, the
- * function makes repeated passes through the cache flushing
- * entries in flush dependency order.
+ * If flush dependencies appear in the target ring, the
+ * function makes repeated passes through the cache flushing
+ * entries in flush dependency order.
*
* Return: Non-negative on success/Negative on failure or if there was
- * a request to flush all items and something was protected.
+ * a request to flush all items and something was protected.
*
* Programmer: John Mainzer
- * 9/1/15
+ * 9/1/15
+ *
+ * Changes: Added support for the H5C__EVICT_ALLOW_LAST_PINS_FLAG.
+ * This flag is used to flush and evict all entries in
+ * the metadata cache that are not pinned -- typically,
+ * everything other than the superblock.
+ *
+ * ??? -- ??/??/??
+ *
+ * A recent optimization turns off the slist unless a flush
+ * is in progress. This should not effect this function, as
+ * it is only called during a flush. Added an assertion to
+ * verify this.
+ *
+ * JRM -- 5/6/20
*
*-------------------------------------------------------------------------
*/
@@ -5231,9 +5815,12 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
HDassert(f);
HDassert(f->shared);
+
cache_ptr = f->shared->cache;
+
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->slist_enabled);
HDassert(cache_ptr->slist_ptr);
HDassert(ring > H5C_RING_UNDEFINED);
HDassert(ring < H5C_RING_NTYPES);
@@ -5248,8 +5835,8 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
/* The flush procedure here is a bit strange.
*
* In the outer while loop we make at least one pass through the
- * cache, and then repeat until either all the pinned entries in
- * the ring unpin themselves, or until the number of pinned entries
+ * cache, and then repeat until either all the pinned entries in
+ * the ring unpin themselves, or until the number of pinned entries
* in the ring stops declining. In this later case, we scream and die.
*
* Since the fractal heap can dirty, resize, and/or move entries
@@ -5275,19 +5862,25 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
*/
/* compute the number of pinned entries in this ring */
+
entry_ptr = cache_ptr->pel_head_ptr;
cur_ring_pel_len = 0;
- while(entry_ptr != NULL) {
+
+ while ( entry_ptr != NULL ) {
+
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring >= ring);
if(entry_ptr->ring == ring)
cur_ring_pel_len++;
entry_ptr = entry_ptr->next;
+
} /* end while */
old_ring_pel_len = cur_ring_pel_len;
+
while(cache_ptr->index_ring_len[ring] > 0) {
+
/* first, try to flush-destroy any dirty entries. Do this by
* making a scan through the slist. Note that new dirty entries
* may be created by the flush call backs. Thus it is possible
@@ -5305,9 +5898,9 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
/* There is also the possibility that entries will be
* dirtied, resized, moved, and/or removed from the cache
- * as the result of calls to the flush callbacks. We use
- * the slist_len_increase and slist_size_increase increase
- * fields in struct H5C_t to track these changes for purpose
+ * as the result of calls to the flush callbacks. We use
+ * the slist_len_increase and slist_size_increase increase
+ * fields in struct H5C_t to track these changes for purpose
* of sanity checking.
*
* To this end, we must zero these fields before we start
@@ -5322,45 +5915,53 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
* This flag is set to TRUE by H5C__flush_single_entry if the slist
* is modified by a pre_serialize, serialize, or notify callback.
*
- * H5C_flush_invalidate_ring() uses this flag to detect any
- * modifications to the slist that might corrupt the scan of
+ * H5C_flush_invalidate_ring() uses this flag to detect any
+ * modifications to the slist that might corrupt the scan of
* the slist -- and restart the scan in this event.
*/
cache_ptr->slist_changed = FALSE;
/* this done, start the scan of the slist */
restart_slist_scan = TRUE;
- while(restart_slist_scan || (node_ptr != NULL)) {
- if(restart_slist_scan) {
+
+ while ( restart_slist_scan || ( node_ptr != NULL ) ) {
+
+ if ( restart_slist_scan ) {
+
restart_slist_scan = FALSE;
/* Start at beginning of skip list */
node_ptr = H5SL_first(cache_ptr->slist_ptr);
- if(node_ptr == NULL)
+
+ if ( node_ptr == NULL )
/* the slist is empty -- break out of inner loop */
break;
/* Get cache entry for this node */
next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
- if(NULL == next_entry_ptr)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!")
+
+ if ( NULL == next_entry_ptr )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "next_entry_ptr == NULL ?!?!")
HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(next_entry_ptr->is_dirty);
HDassert(next_entry_ptr->in_slist);
HDassert(next_entry_ptr->ring >= ring);
+
} /* end if */
entry_ptr = next_entry_ptr;
- /* It is possible that entries will be dirtied, resized,
+ /* It is possible that entries will be dirtied, resized,
* flushed, or removed from the cache via the take ownership
- * flag as the result of pre_serialize or serialized callbacks.
- *
+ * flag as the result of pre_serialize or serialized callbacks.
+ *
* This in turn can corrupt the scan through the slist.
*
- * We test for slist modifications in the pre_serialize
- * and serialize callbacks, and restart the scan of the
+ * We test for slist modifications in the pre_serialize
+ * and serialize callbacks, and restart the scan of the
* slist if we find them. However, best we do some extra
* sanity checking just in case.
*/
@@ -5374,18 +5975,26 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
* from the slist.
*/
node_ptr = H5SL_next(node_ptr);
+
if(node_ptr != NULL) {
+
next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
if(NULL == next_entry_ptr)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!")
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "next_entry_ptr == NULL ?!?!")
+
HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(next_entry_ptr->is_dirty);
HDassert(next_entry_ptr->in_slist);
HDassert(next_entry_ptr->ring >= ring);
HDassert(entry_ptr != next_entry_ptr);
} /* end if */
- else
+ else {
+
next_entry_ptr = NULL;
+ }
/* Note that we now remove nodes from the slist as we flush
* the associated entries, instead of leaving them there
@@ -5397,22 +6006,31 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
* flush, we must keep the slist in canonical form at all
* times.
*/
- if(((!entry_ptr->flush_me_last) ||
- ((entry_ptr->flush_me_last) &&
- (cache_ptr->num_last_entries >= cache_ptr->slist_len))) &&
- (entry_ptr->flush_dep_nchildren == 0) &&
- (entry_ptr->ring == ring)) {
- if(entry_ptr->is_protected) {
+ if ( ( ( !entry_ptr->flush_me_last ) ||
+ ( ( entry_ptr->flush_me_last ) &&
+ ( cache_ptr->num_last_entries >= cache_ptr->slist_len ) )
+ ) &&
+ ( entry_ptr->flush_dep_nchildren == 0 ) &&
+ ( entry_ptr->ring == ring ) ) {
+
+ if ( entry_ptr->is_protected ) {
+
/* we have major problems -- but lets flush
* everything we can before we flag an error.
*/
protected_entries++;
+
} /* end if */
- else if(entry_ptr->is_pinned) {
- if(H5C__flush_single_entry(f, entry_ptr, H5C__DURING_FLUSH_FLAG) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty pinned entry flush failed")
+ else if ( entry_ptr->is_pinned ) {
+
+ if ( H5C__flush_single_entry(f, entry_ptr,
+ H5C__DURING_FLUSH_FLAG) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "dirty pinned entry flush failed")
+
+ if ( cache_ptr->slist_changed ) {
- if(cache_ptr->slist_changed) {
/* The slist has been modified by something
* other than the simple removal of the
* of the flushed entry after the flush.
@@ -5423,13 +6041,22 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
restart_slist_scan = TRUE;
cache_ptr->slist_changed = FALSE;
H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr);
+
} /* end if */
} /* end else-if */
else {
- if(H5C__flush_single_entry(f, entry_ptr, (cooked_flags | H5C__DURING_FLUSH_FLAG | H5C__FLUSH_INVALIDATE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG)) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry flush destroy failed")
- if(cache_ptr->slist_changed) {
+ if ( H5C__flush_single_entry(f, entry_ptr,
+ (cooked_flags |
+ H5C__DURING_FLUSH_FLAG |
+ H5C__FLUSH_INVALIDATE_FLAG |
+ H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) ) < 0)
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL,
+ "dirty entry flush destroy failed")
+
+ if ( cache_ptr->slist_changed ) {
+
/* The slist has been modified by something
* other than the simple removal of the
* of the flushed entry after the flush.
@@ -5455,9 +6082,15 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
* out from under us.
*/
- if(node_ptr == NULL) {
- HDassert(cache_ptr->slist_len == (uint32_t)((int32_t)initial_slist_len + cache_ptr->slist_len_increase));
- HDassert(cache_ptr->slist_size == (size_t)((ssize_t)initial_slist_size + cache_ptr->slist_size_increase));
+ if ( node_ptr == NULL ) {
+
+ HDassert(cache_ptr->slist_len ==
+ (uint32_t)((int32_t)initial_slist_len +
+ cache_ptr->slist_len_increase));
+
+ HDassert(cache_ptr->slist_size ==
+ (size_t)((ssize_t)initial_slist_size +
+ cache_ptr->slist_size_increase));
} /* end if */
#endif /* H5C_DO_SANITY_CHECKS */
@@ -5481,7 +6114,9 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
cache_ptr->entries_relocated_counter = 0;
next_entry_ptr = cache_ptr->il_head;
- while(next_entry_ptr != NULL) {
+
+ while ( next_entry_ptr != NULL ) {
+
entry_ptr = next_entry_ptr;
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring >= ring);
@@ -5490,21 +6125,31 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
HDassert((next_entry_ptr == NULL) ||
(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC));
- if((!entry_ptr->flush_me_last || (entry_ptr->flush_me_last && cache_ptr->num_last_entries >= cache_ptr->slist_len))
- && entry_ptr->flush_dep_nchildren == 0 && entry_ptr->ring == ring) {
- if(entry_ptr->is_protected) {
- /* we have major problems -- but lets flush and
- * destroy everything we can before we flag an
+ if ( ( ( ! entry_ptr->flush_me_last ) ||
+ ( entry_ptr->flush_me_last &&
+ ( cache_ptr->num_last_entries >= cache_ptr->slist_len ) )
+ ) &&
+ ( entry_ptr->flush_dep_nchildren == 0 ) &&
+ ( entry_ptr->ring == ring ) ) {
+
+ if ( entry_ptr->is_protected ) {
+
+ /* we have major problems -- but lets flush and
+ * destroy everything we can before we flag an
* error.
*/
protected_entries++;
- if(!entry_ptr->in_slist)
+
+ if ( ! entry_ptr->in_slist ) {
+
HDassert(!(entry_ptr->is_dirty));
+ }
} /* end if */
- else if(!(entry_ptr->is_pinned)) {
- /* if *entry_ptr is dirty, it is possible
- * that one or more other entries may be
- * either removed from the cache, loaded
+ else if ( ! ( entry_ptr->is_pinned ) ) {
+
+ /* if *entry_ptr is dirty, it is possible
+ * that one or more other entries may be
+ * either removed from the cache, loaded
* into the cache, or moved to a new location
* in the file as a side effect of the flush.
*
@@ -5513,14 +6158,14 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
* entry, allowing it to be removed also and
* invalidating the next_entry_ptr.
*
- * If either of these happen, and one of the target
- * or proxy entries happens to be the next entry in
+ * If either of these happen, and one of the target
+ * or proxy entries happens to be the next entry in
* the hash bucket, we could either find ourselves
* either scanning a non-existant entry, scanning
* through a different bucket, or skipping an entry.
*
- * Neither of these are good, so restart the
- * the scan at the head of the hash bucket
+ * Neither of these are good, so restart the
+ * the scan at the head of the hash bucket
* after the flush if we detect that the next_entry_ptr
* becomes invalid.
*
@@ -5530,21 +6175,29 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
*/
cache_ptr->entry_watched_for_removal = next_entry_ptr;
- if(H5C__flush_single_entry(f, entry_ptr, (cooked_flags | H5C__DURING_FLUSH_FLAG | H5C__FLUSH_INVALIDATE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG)) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Entry flush destroy failed")
+ if ( H5C__flush_single_entry(f, entry_ptr,
+ (cooked_flags |
+ H5C__DURING_FLUSH_FLAG |
+ H5C__FLUSH_INVALIDATE_FLAG |
+ H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG)) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "Entry flush destroy failed")
/* Restart the index list scan if necessary. Must
- * do this if the next entry is evicted, and also if
+ * do this if the next entry is evicted, and also if
* one or more entries are inserted, loaded, or moved
* as these operations can result in part of the scan
* being skipped -- which can cause a spurious failure
- * if this results in the size of the pinned entry
+ * if this results in the size of the pinned entry
* failing to decline during the pass.
*/
- if((NULL != next_entry_ptr && NULL == cache_ptr->entry_watched_for_removal)
- || (cache_ptr->entries_loaded_counter > 0)
- || (cache_ptr->entries_inserted_counter > 0)
- || (cache_ptr->entries_relocated_counter > 0)) {
+ if ( ( ( NULL != next_entry_ptr ) &&
+ ( NULL == cache_ptr->entry_watched_for_removal )
+ ) ||
+ ( cache_ptr->entries_loaded_counter > 0 ) ||
+ ( cache_ptr->entries_inserted_counter > 0 ) ||
+ ( cache_ptr->entries_relocated_counter > 0 ) ) {
next_entry_ptr = cache_ptr->il_head;
@@ -5553,9 +6206,12 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
cache_ptr->entries_relocated_counter = 0;
H5C__UPDATE_STATS_FOR_INDEX_SCAN_RESTART(cache_ptr)
+
} /* end if */
- else
+ else {
+
cache_ptr->entry_watched_for_removal = NULL;
+ }
} /* end if */
} /* end if */
} /* end for loop scanning hash table */
@@ -5571,35 +6227,53 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
old_ring_pel_len = cur_ring_pel_len;
entry_ptr = cache_ptr->pel_head_ptr;
cur_ring_pel_len = 0;
- while(entry_ptr != NULL) {
+
+ while ( entry_ptr != NULL ) {
+
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring >= ring);
- if(entry_ptr->ring == ring)
+ if ( entry_ptr->ring == ring ) {
+
cur_ring_pel_len++;
+ }
entry_ptr = entry_ptr->next;
+
} /* end while */
- /* Check if the number of pinned entries in the ring is positive, and
+ /* Check if the number of pinned entries in the ring is positive, and
* it is not declining. Scream and die if so.
*/
- if(cur_ring_pel_len > 0 && cur_ring_pel_len >= old_ring_pel_len) {
+ if ( ( cur_ring_pel_len > 0 ) &&
+ ( cur_ring_pel_len >= old_ring_pel_len ) ) {
+
/* Don't error if allowed to have pinned entries remaining */
- if(evict_flags)
+ if ( evict_flags ) {
+
HGOTO_DONE(TRUE)
+ }
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Pinned entry count not decreasing, cur_ring_pel_len = %d, old_ring_pel_len = %d, ring = %d", (int)cur_ring_pel_len, (int)old_ring_pel_len, (int)ring)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "Pinned entry count not decreasing, cur_ring_pel_len = %d, old_ring_pel_len = %d, ring = %d", \
+ (int)cur_ring_pel_len, \
+ (int)old_ring_pel_len, (int)ring)
} /* end if */
HDassert(protected_entries == cache_ptr->pl_len);
- if(protected_entries > 0 && protected_entries == cache_ptr->index_len)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Only protected entries left in cache, protected_entries = %d", (int)protected_entries)
+ if ( ( protected_entries > 0 ) &&
+ ( protected_entries == cache_ptr->index_len ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "Only protected entries left in cache, protected_entries = %d",\
+ (int)protected_entries)
+
} /* main while loop */
/* Invariants, after destroying all entries in the ring */
- for(i = (int)H5C_RING_UNDEFINED; i <= (int)ring; i++) {
+ for ( i = (int)H5C_RING_UNDEFINED; i <= (int)ring; i++ ) {
+
HDassert(cache_ptr->index_ring_len[i] == 0);
HDassert(cache_ptr->index_ring_size[i] == (size_t)0);
HDassert(cache_ptr->clean_index_ring_size[i] == (size_t)0);
@@ -5607,41 +6281,59 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
HDassert(cache_ptr->slist_ring_len[i] == 0);
HDassert(cache_ptr->slist_ring_size[i] == (size_t)0);
+
} /* end for */
HDassert(protected_entries <= cache_ptr->pl_len);
- if(protected_entries > 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Cache has protected entries")
- else if(cur_ring_pel_len > 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't unpin all pinned entries in ring")
+ if ( protected_entries > 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "Cache has protected entries")
+
+ } else if ( cur_ring_pel_len > 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "Can't unpin all pinned entries in ring")
+ }
done:
+
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C_flush_invalidate_ring() */
/*-------------------------------------------------------------------------
+ *
* Function: H5C__flush_ring
*
- * Purpose: Flush the entries contained in the specified cache and
- * ring. All entries in rings outside the specified ring
- * must have been flushed on entry.
+ * Purpose: Flush the entries contained in the specified cache and
+ * ring. All entries in rings outside the specified ring
+ * must have been flushed on entry.
*
- * If the cache contains protected entries in the specified
- * ring, the function will fail, as protected entries cannot
- * be flushed. However all unprotected entries in the target
- * ring should be flushed before the function returns failure.
+ * If the cache contains protected entries in the specified
+ * ring, the function will fail, as protected entries cannot
+ * be flushed. However all unprotected entries in the target
+ * ring should be flushed before the function returns failure.
*
- * If flush dependencies appear in the target ring, the
- * function makes repeated passes through the slist flushing
- * entries in flush dependency order.
+ * If flush dependencies appear in the target ring, the
+ * function makes repeated passes through the slist flushing
+ * entries in flush dependency order.
*
* Return: Non-negative on success/Negative on failure or if there was
- * a request to flush all items and something was protected.
+ * a request to flush all items and something was protected.
*
* Programmer: John Mainzer
- * 9/1/15
+ * 9/1/15
+ *
+ * Changes: A recent optimization turns off the slist unless a flush
+ * is in progress. This should not effect this function, as
+ * it is only called during a flush. Added an assertion to
+ * verify this.
+ *
+ * JRM -- 5/6/20
+ *
*
*-------------------------------------------------------------------------
*/
@@ -5669,24 +6361,31 @@ H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags)
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->slist_enabled);
HDassert(cache_ptr->slist_ptr);
HDassert((flags & H5C__FLUSH_INVALIDATE_FLAG) == 0);
HDassert(ring > H5C_RING_UNDEFINED);
HDassert(ring < H5C_RING_NTYPES);
#if H5C_DO_EXTREME_SANITY_CHECKS
- if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
- (H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
- (H5C_validate_lru_list(cache_ptr) < 0))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry")
+ if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) ||
+ ( H5C_validate_pinned_entry_list(cache_ptr ) < 0 ) ||
+ ( H5C_validate_lru_list(cache_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL,
+ "an extreme sanity check failed on entry")
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
ignore_protected = ( (flags & H5C__FLUSH_IGNORE_PROTECTED_FLAG) != 0 );
flush_marked_entries = ( (flags & H5C__FLUSH_MARKED_ENTRIES_FLAG) != 0 );
- if(!flush_marked_entries)
- for(i = (int)H5C_RING_UNDEFINED; i < (int)ring; i++)
- HDassert(cache_ptr->slist_ring_len[i] == 0);
+ if ( ! flush_marked_entries ) {
+
+ for ( i = (int)H5C_RING_UNDEFINED; i < (int)ring; i++ ) {
+
+ HDassert(cache_ptr->slist_ring_len[i] == 0);
+ }
+ }
HDassert(cache_ptr->flush_in_progress);
@@ -5699,17 +6398,18 @@ H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags)
/* Set the cache_ptr->slist_changed to false.
*
- * This flag is set to TRUE by H5C__flush_single_entry if the
+ * This flag is set to TRUE by H5C__flush_single_entry if the
* slist is modified by a pre_serialize, serialize, or notify callback.
* H5C_flush_cache uses this flag to detect any modifications
- * to the slist that might corrupt the scan of the slist -- and
+ * to the slist that might corrupt the scan of the slist -- and
* restart the scan in this event.
*/
cache_ptr->slist_changed = FALSE;
- while((cache_ptr->slist_ring_len[ring] > 0) &&
- (protected_entries == 0) &&
- (flushed_entries_last_pass)) {
+ while ( ( cache_ptr->slist_ring_len[ring] > 0 ) &&
+ ( protected_entries == 0 ) &&
+ ( flushed_entries_last_pass ) ) {
+
flushed_entries_last_pass = FALSE;
#if H5C_DO_SANITY_CHECKS
@@ -5722,8 +6422,8 @@ H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags)
*
* To make things more entertaining, with the advent of the
* fractal heap, the entry serialize callback can cause entries
- * to be dirtied, resized, and/or moved. Also, the
- * pre_serialize callback can result in an entry being
+ * to be dirtied, resized, and/or moved. Also, the
+ * pre_serialize callback can result in an entry being
* removed from the cache via the take ownership flag.
*
* To deal with this, we first make note of the initial
@@ -5753,136 +6453,177 @@ H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags)
restart_slist_scan = TRUE;
- while((restart_slist_scan ) || (node_ptr != NULL)) {
- if(restart_slist_scan) {
+ while ( ( restart_slist_scan ) || ( node_ptr != NULL ) ) {
+
+ if ( restart_slist_scan ) {
+
restart_slist_scan = FALSE;
/* Start at beginning of skip list */
node_ptr = H5SL_first(cache_ptr->slist_ptr);
- if(node_ptr == NULL)
+ if ( node_ptr == NULL ) {
+
/* the slist is empty -- break out of inner loop */
break;
+ }
/* Get cache entry for this node */
next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
- if(NULL == next_entry_ptr)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!")
+ if ( NULL == next_entry_ptr )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "next_entry_ptr == NULL ?!?!")
HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(next_entry_ptr->is_dirty);
HDassert(next_entry_ptr->in_slist);
+
} /* end if */
-
+
entry_ptr = next_entry_ptr;
/* With the advent of the fractal heap, the free space
* manager, and the version 3 cache, it is possible
- * that the pre-serialize or serialize callback will
- * dirty, resize, or take ownership of other entries
- * in the cache.
+ * that the pre-serialize or serialize callback will
+ * dirty, resize, or take ownership of other entries
+ * in the cache.
*
* To deal with this, I have inserted code to detect any
* change in the skip list not directly under the control
* of this function. If such modifications are detected,
- * we must re-start the scan of the skip list to avoid
+ * we must re-start the scan of the skip list to avoid
* the possibility that the target of the next_entry_ptr
* may have been flushed or deleted from the cache.
*
* To verify that all such possibilities have been dealt
- * with, we do a bit of extra sanity checking on
+ * with, we do a bit of extra sanity checking on
* entry_ptr.
*/
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->in_slist);
HDassert(entry_ptr->is_dirty);
- if(!flush_marked_entries || entry_ptr->flush_marker)
+
+ if ( ( ! flush_marked_entries ) || ( entry_ptr->flush_marker ) ) {
+
HDassert(entry_ptr->ring >= ring);
+ }
/* Advance node pointer now, before we delete its target
* from the slist.
*/
node_ptr = H5SL_next(node_ptr);
- if(node_ptr != NULL) {
+
+ if ( node_ptr != NULL ) {
+
next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
- if(NULL == next_entry_ptr)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!")
+
+ if ( NULL == next_entry_ptr )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "next_entry_ptr == NULL ?!?!")
HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(next_entry_ptr->is_dirty);
HDassert(next_entry_ptr->in_slist);
- if(!flush_marked_entries || next_entry_ptr->flush_marker)
+ if ( ! flush_marked_entries || next_entry_ptr->flush_marker ) {
+
HDassert(next_entry_ptr->ring >= ring);
+ }
HDassert(entry_ptr != next_entry_ptr);
+
} /* end if */
- else
+ else {
+
next_entry_ptr = NULL;
+ }
- if((!flush_marked_entries || entry_ptr->flush_marker)
- && (!entry_ptr->flush_me_last ||
- (entry_ptr->flush_me_last
- && (cache_ptr->num_last_entries >= cache_ptr->slist_len
- || (flush_marked_entries && entry_ptr->flush_marker))))
- && (entry_ptr->flush_dep_nchildren == 0
- || entry_ptr->flush_dep_ndirty_children == 0)
- && entry_ptr->ring == ring) {
+ if ( ( ! flush_marked_entries || entry_ptr->flush_marker ) &&
+ ( ( ! entry_ptr->flush_me_last ) ||
+ ( ( entry_ptr->flush_me_last ) &&
+ ( ( cache_ptr->num_last_entries >= cache_ptr->slist_len )||
+ ( flush_marked_entries && entry_ptr->flush_marker ) )
+ )
+ ) &&
+ ( ( entry_ptr->flush_dep_nchildren == 0 ) ||
+ ( entry_ptr->flush_dep_ndirty_children == 0 ) ) &&
+ ( entry_ptr->ring == ring ) ) {
HDassert(entry_ptr->flush_dep_nunser_children == 0);
- if(entry_ptr->is_protected) {
- /* we probably have major problems -- but lets
- * flush everything we can before we decide
+ if ( entry_ptr->is_protected ) {
+
+ /* we probably have major problems -- but lets
+ * flush everything we can before we decide
* whether to flag an error.
*/
tried_to_flush_protected_entry = TRUE;
protected_entries++;
+
} /* end if */
else {
- if(H5C__flush_single_entry(f, entry_ptr, (flags | H5C__DURING_FLUSH_FLAG)) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush entry")
- if(cache_ptr->slist_changed) {
+ if ( H5C__flush_single_entry(f, entry_ptr,
+ (flags | H5C__DURING_FLUSH_FLAG)) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "Can't flush entry")
+
+ if ( cache_ptr->slist_changed ) {
+
/* The slist has been modified by something
- * other than the simple removal of the
+ * other than the simple removal of the
* of the flushed entry after the flush.
- *
+ *
* This has the potential to corrupt the
* scan through the slist, so restart it.
*/
restart_slist_scan = TRUE;
cache_ptr->slist_changed = FALSE;
H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr)
+
} /* end if */
flushed_entries_last_pass = TRUE;
+
} /* end else */
} /* end if */
} /* while ( ( restart_slist_scan ) || ( node_ptr != NULL ) ) */
#if H5C_DO_SANITY_CHECKS
/* Verify that the slist size and length are as expected. */
- HDassert((uint32_t)((int32_t)initial_slist_len + cache_ptr->slist_len_increase) == cache_ptr->slist_len);
- HDassert((size_t)((ssize_t)initial_slist_size + cache_ptr->slist_size_increase) == cache_ptr->slist_size);
+ HDassert((uint32_t)((int32_t)initial_slist_len + \
+ cache_ptr->slist_len_increase) == cache_ptr->slist_len);
+ HDassert((size_t)((ssize_t)initial_slist_size + \
+ cache_ptr->slist_size_increase) == cache_ptr->slist_size);
#endif /* H5C_DO_SANITY_CHECKS */
+
} /* while */
HDassert(protected_entries <= cache_ptr->pl_len);
- if(((cache_ptr->pl_len > 0) && (!ignore_protected)) || (tried_to_flush_protected_entry))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "cache has protected items")
+ if ( ( ( cache_ptr->pl_len > 0 ) && ( ! ignore_protected ) ) ||
+ ( tried_to_flush_protected_entry ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "cache has protected items")
#if H5C_DO_SANITY_CHECKS
- if(!flush_marked_entries) {
+ if ( ! flush_marked_entries ) {
+
HDassert(cache_ptr->slist_ring_len[ring] == 0);
HDassert(cache_ptr->slist_ring_size[ring] == 0);
+
} /* end if */
#endif /* H5C_DO_SANITY_CHECKS */
done:
+
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C__flush_ring() */
@@ -5891,53 +6632,110 @@ done:
* Function: H5C__flush_single_entry
*
* Purpose: Flush or clear (and evict if requested) the cache entry
- * with the specified address and type. If the type is NULL,
- * any unprotected entry at the specified address will be
- * flushed (and possibly evicted).
+ * with the specified address and type. If the type is NULL,
+ * any unprotected entry at the specified address will be
+ * flushed (and possibly evicted).
*
- * Attempts to flush a protected entry will result in an
- * error.
+ * Attempts to flush a protected entry will result in an
+ * error.
*
- * If the H5C__FLUSH_INVALIDATE_FLAG flag is set, the entry will
- * be cleared and not flushed, and the call can't be part of a
+ * If the H5C__FLUSH_INVALIDATE_FLAG flag is set, the entry will
+ * be cleared and not flushed, and the call can't be part of a
* sequence of flushes.
*
- * If the caller knows the address of the skip list node at
- * which the target entry resides, it can avoid a lookup
- * by supplying that address in the tgt_node_ptr parameter.
- * If this parameter is NULL, the function will do a skip list
- * search for the entry instead.
- *
- * The function does nothing silently if there is no entry
- * at the supplied address, or if the entry found has the
- * wrong type.
+ * The function does nothing silently if there is no entry
+ * at the supplied address, or if the entry found has the
+ * wrong type.
*
* Return: Non-negative on success/Negative on failure or if there was
- * an attempt to flush a protected item.
+ * an attempt to flush a protected item.
*
* Programmer: John Mainzer, 5/5/04
*
+ * Modifications:
+ *
+ * JRM -- 7/21/04
+ * Updated function for the addition of the hash table.
+ *
+ * QAK -- 11/26/04
+ * Updated function for the switch from TBBTs to skip lists.
+ *
+ * JRM -- 1/6/05
+ * Updated function to reset the flush_marker field.
+ * Also replace references to H5F_FLUSH_INVALIDATE and
+ * H5F_FLUSH_CLEAR_ONLY with references to
+ * H5C__FLUSH_INVALIDATE_FLAG and H5C__FLUSH_CLEAR_ONLY_FLAG
+ * respectively.
+ *
+ * JRM -- 6/24/05
+ * Added code to remove dirty entries from the slist after
+ * they have been flushed. Also added a sanity check that
+ * will scream if we attempt a write when writes are
+ * completely disabled.
+ *
+ * JRM -- 7/5/05
+ * Added code to call the new log_flush callback whenever
+ * a dirty entry is written to disk. Note that the callback
+ * is not called if the H5C__FLUSH_CLEAR_ONLY_FLAG is set,
+ * as there is no write to file in this case.
+ *
+ * JRM -- 8/21/06
+ * Added code maintaining the flush_in_progress and
+ * destroy_in_progress fields in H5C_cache_entry_t.
+ *
+ * Also added flush_flags parameter to the call to
+ * type_ptr->flush() so that the flush routine can report
+ * whether the entry has been resized or renamed. Added
+ * code using the flush_flags variable to detect the case
+ * in which the target entry is resized during flush, and
+ * update the caches data structures accordingly.
+ *
+ * JRM -- 3/29/07
+ * Added sanity checks on the new is_read_only and
+ * ro_ref_count fields.
+ *
+ * QAK -- 2/07/08
+ * Separated "destroy entry" concept from "remove entry from
+ * cache" concept, by adding the 'take_ownership' flag and
+ * the "destroy_entry" variable.
+ *
+ * JRM -- 11/5/08
+ * Added call to H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN() to
+ * maintain the new clean_index_size and clean_index_size
+ * fields of H5C_t.
+ *
+ *
+ * Missing entries??
+ *
+ *
+ * JRM -- 5/8/20
+ * Updated sanity checks for the possibility that the slist
+ * is disabled.
+ *
+ * Also updated main comment to conform more closely with
+ * the current state of the code.
+ *
*-------------------------------------------------------------------------
*/
herr_t
H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
{
- H5C_t * cache_ptr; /* Cache for file */
- hbool_t destroy; /* external flag */
- hbool_t clear_only; /* external flag */
- hbool_t free_file_space; /* external flag */
- hbool_t take_ownership; /* external flag */
- hbool_t del_from_slist_on_destroy; /* external flag */
- hbool_t during_flush; /* external flag */
- hbool_t write_entry; /* internal flag */
- hbool_t destroy_entry; /* internal flag */
- hbool_t generate_image; /* internal flag */
- hbool_t update_page_buffer; /* internal flag */
- hbool_t was_dirty;
- hbool_t suppress_image_entry_writes = FALSE;
- hbool_t suppress_image_entry_frees = FALSE;
- haddr_t entry_addr = HADDR_UNDEF;
- herr_t ret_value = SUCCEED; /* Return value */
+ H5C_t * cache_ptr; /* Cache for file */
+ hbool_t destroy; /* external flag */
+ hbool_t clear_only; /* external flag */
+ hbool_t free_file_space; /* external flag */
+ hbool_t take_ownership; /* external flag */
+ hbool_t del_from_slist_on_destroy; /* external flag */
+ hbool_t during_flush; /* external flag */
+ hbool_t write_entry; /* internal flag */
+ hbool_t destroy_entry; /* internal flag */
+ hbool_t generate_image; /* internal flag */
+ hbool_t update_page_buffer; /* internal flag */
+ hbool_t was_dirty;
+ hbool_t suppress_image_entry_writes = FALSE;
+ hbool_t suppress_image_entry_frees = FALSE;
+ haddr_t entry_addr = HADDR_UNDEF;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -5951,40 +6749,52 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
HDassert(entry_ptr->type);
/* setup external flags from the flags parameter */
- destroy = ((flags & H5C__FLUSH_INVALIDATE_FLAG) != 0);
- clear_only = ((flags & H5C__FLUSH_CLEAR_ONLY_FLAG) != 0);
- free_file_space = ((flags & H5C__FREE_FILE_SPACE_FLAG) != 0);
- take_ownership = ((flags & H5C__TAKE_OWNERSHIP_FLAG) != 0);
- del_from_slist_on_destroy = ((flags & H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) != 0);
- during_flush = ((flags & H5C__DURING_FLUSH_FLAG) != 0);
- generate_image = ((flags & H5C__GENERATE_IMAGE_FLAG) != 0);
- update_page_buffer = ((flags & H5C__UPDATE_PAGE_BUFFER_FLAG) != 0);
+ destroy = ((flags & H5C__FLUSH_INVALIDATE_FLAG) != 0);
+ clear_only = ((flags & H5C__FLUSH_CLEAR_ONLY_FLAG) != 0);
+ free_file_space = ((flags & H5C__FREE_FILE_SPACE_FLAG) != 0);
+ take_ownership = ((flags & H5C__TAKE_OWNERSHIP_FLAG) != 0);
+ del_from_slist_on_destroy =
+ ((flags & H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) != 0);
+ during_flush = ((flags & H5C__DURING_FLUSH_FLAG) != 0);
+ generate_image = ((flags & H5C__GENERATE_IMAGE_FLAG) != 0);
+ update_page_buffer = ((flags & H5C__UPDATE_PAGE_BUFFER_FLAG) != 0);
/* Set the flag for destroying the entry, based on the 'take ownership'
* and 'destroy' flags
*/
- if(take_ownership)
+ if ( take_ownership ) {
+
destroy_entry = FALSE;
- else
+
+ } else {
+
destroy_entry = destroy;
+ }
/* we will write the entry to disk if it exists, is dirty, and if the
* clear only flag is not set.
*/
- if(entry_ptr->is_dirty && !clear_only)
+ if ( entry_ptr->is_dirty && !clear_only ) {
+
write_entry = TRUE;
- else
+
+ } else {
+
write_entry = FALSE;
+ }
- /* if we have received close warning, and we have been instructed to
+ /* if we have received close warning, and we have been instructed to
* generate a metadata cache image, and we have actually constructed
* the entry images, set suppress_image_entry_frees to TRUE.
*
- * Set suppress_image_entry_writes to TRUE if indicated by the
+ * Set suppress_image_entry_writes to TRUE if indicated by the
* image_ctl flags.
*/
- if(cache_ptr->close_warning_received && cache_ptr->image_ctl.generate_image
- && cache_ptr->num_entries_in_image > 0 && cache_ptr->image_entries) {
+ if ( ( cache_ptr->close_warning_received ) &&
+ ( cache_ptr->image_ctl.generate_image ) &&
+ ( cache_ptr->num_entries_in_image > 0 ) &&
+ ( cache_ptr->image_entries != NULL ) ) {
+
/* Sanity checks */
HDassert(entry_ptr->image_up_to_date || !(entry_ptr->include_in_image));
HDassert(entry_ptr->image_ptr || !(entry_ptr->include_in_image));
@@ -5994,32 +6804,60 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
suppress_image_entry_frees = TRUE;
- if(cache_ptr->image_ctl.flags & H5C_CI__SUPRESS_ENTRY_WRITES)
+ if ( cache_ptr->image_ctl.flags & H5C_CI__SUPRESS_ENTRY_WRITES ) {
+
suppress_image_entry_writes = TRUE;
+
+ } /* end if */
} /* end if */
- /* run initial sanity checks */
-#if H5C_DO_SANITY_CHECKS
- if(entry_ptr->in_slist) {
- HDassert(entry_ptr->is_dirty);
+ /* run initial sanity checks */
+#if H5C_DO_SANITY_CHECKS
+ if ( cache_ptr->slist_enabled ) {
- if((entry_ptr->flush_marker) && (!entry_ptr->is_dirty))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry in slist failed sanity checks")
- } /* end if */
- else {
- HDassert(!entry_ptr->is_dirty);
- HDassert(!entry_ptr->flush_marker);
+ if ( entry_ptr->in_slist ) {
- if((entry_ptr->is_dirty) || (entry_ptr->flush_marker))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry failed sanity checks")
- } /* end else */
+ HDassert(entry_ptr->is_dirty);
+
+ if ( ( entry_ptr->flush_marker ) && ( ! entry_ptr->is_dirty ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "entry in slist failed sanity checks")
+ } /* end if */
+ else {
+
+ HDassert(!entry_ptr->is_dirty);
+ HDassert(!entry_ptr->flush_marker);
+
+ if ( ( entry_ptr->is_dirty ) || ( entry_ptr->flush_marker ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "entry failed sanity checks")
+
+ } /* end else */
+ } else { /* slist is disabled */
+
+ HDassert( ! entry_ptr->in_slist );
+
+ if ( ! entry_ptr->is_dirty ) {
+
+ if ( entry_ptr->flush_marker )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "flush marked clean entry?")
+
+ }
+ }
#endif /* H5C_DO_SANITY_CHECKS */
- if(entry_ptr->is_protected) {
+ if ( entry_ptr->is_protected ) {
+
HDassert(!entry_ptr->is_protected);
/* Attempt to flush a protected entry -- scream and die. */
- HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, FAIL, "Attempt to flush a protected entry")
+ HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, FAIL, \
+ "Attempt to flush a protected entry")
+
} /* end if */
/* Set entry_ptr->flush_in_progress = TRUE and set
@@ -6038,104 +6876,144 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
* been requested to generate an image. In those cases, serialize the
* entry.
*/
- if(write_entry || generate_image) {
+ if ( write_entry || generate_image ) {
+
HDassert(entry_ptr->is_dirty);
- if(NULL == entry_ptr->image_ptr) {
- if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
+ if ( NULL == entry_ptr->image_ptr ) {
+
+ if ( NULL == (entry_ptr->image_ptr =
+ H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, \
+ "memory allocation failed for on disk image buffer")
+
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size,
+ H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
} /* end if */
- if(!(entry_ptr->image_up_to_date)) {
+ if ( ! ( entry_ptr->image_up_to_date ) ) {
+
/* Sanity check */
HDassert(!entry_ptr->prefetched);
/* Generate the entry's image */
- if(H5C__generate_image(f, cache_ptr, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "can't generate entry's image")
+ if ( H5C__generate_image(f, cache_ptr, entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, \
+ "can't generate entry's image")
+
} /* end if ( ! (entry_ptr->image_up_to_date) ) */
} /* end if */
- /* Finally, write the image to disk.
- *
- * Note that if the H5AC__CLASS_SKIP_WRITES flag is set in the
+ /* Finally, write the image to disk.
+ *
+ * Note that if the H5AC__CLASS_SKIP_WRITES flag is set in the
* in the entry's type, we silently skip the write. This
- * flag should only be used in test code.
+ * flag should only be used in test code.
*/
- if(write_entry) {
+ if ( write_entry ) {
+
HDassert(entry_ptr->is_dirty);
#if H5C_DO_SANITY_CHECKS
- if(cache_ptr->check_write_permitted && !(cache_ptr->write_permitted))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Write when writes are always forbidden!?!?!")
+ if ( ( cache_ptr->check_write_permitted ) &&
+ ( ! ( cache_ptr->write_permitted ) ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Write when writes are always forbidden!?!?!")
#endif /* H5C_DO_SANITY_CHECKS */
/* Write the image to disk unless the write is suppressed.
*
- * This happens if both suppress_image_entry_writes and
- * entry_ptr->include_in_image are TRUE, or if the
+ * This happens if both suppress_image_entry_writes and
+ * entry_ptr->include_in_image are TRUE, or if the
* H5AC__CLASS_SKIP_WRITES is set in the entry's type. This
* flag should only be used in test code
*/
- if((!suppress_image_entry_writes || !entry_ptr->include_in_image)
- && (((entry_ptr->type->flags) & H5C__CLASS_SKIP_WRITES) == 0)) {
+ if ( ( ( ! suppress_image_entry_writes ) ||
+ ( ! entry_ptr->include_in_image ) ) &&
+ ( ( (entry_ptr->type->flags) & H5C__CLASS_SKIP_WRITES) == 0 ) ) {
+
H5FD_mem_t mem_type = H5FD_MEM_DEFAULT;
#ifdef H5_HAVE_PARALLEL
- if(cache_ptr->coll_write_list) {
- if(H5SL_insert(cache_ptr->coll_write_list, entry_ptr, &entry_ptr->addr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, "unable to insert skip list item")
+ if ( cache_ptr->coll_write_list ) {
+
+ if ( H5SL_insert(cache_ptr->coll_write_list, entry_ptr,
+ &entry_ptr->addr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, \
+ "unable to insert skip list item")
} /* end if */
else
{
#endif /* H5_HAVE_PARALLEL */
- if(entry_ptr->prefetched) {
+ if ( entry_ptr->prefetched ) {
+
HDassert(entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID);
+
mem_type = cache_ptr->
class_table_ptr[entry_ptr->prefetch_type_id]->
mem_type;
} /* end if */
- else
+ else {
+
mem_type = entry_ptr->type->mem_type;
+ }
+
+ if ( H5F_block_write(f, mem_type, entry_ptr->addr,
+ entry_ptr->size, entry_ptr->image_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "Can't write image to file")
- if(H5F_block_write(f, mem_type, entry_ptr->addr, entry_ptr->size, entry_ptr->image_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't write image to file")
#ifdef H5_HAVE_PARALLEL
}
#endif /* H5_HAVE_PARALLEL */
+
} /* end if */
- /* if the entry has a notify callback, notify it that we have
+ /* if the entry has a notify callback, notify it that we have
* just flushed the entry.
*/
- if(entry_ptr->type->notify &&
- (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_FLUSH, entry_ptr) < 0 )
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client of entry flush")
+ if ( ( entry_ptr->type->notify ) &&
+ ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_FLUSH,
+ entry_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "can't notify client of entry flush")
+
} /* if ( write_entry ) */
/* At this point, all pre-serialize and serialize calls have been
* made if it was appropriate to make them. Similarly, the entry
* has been written to disk if desired.
*
- * Thus it is now safe to update the cache data structures for the
+ * Thus it is now safe to update the cache data structures for the
* flush.
*/
/* start by updating the statistics */
- if(clear_only) {
+ if ( clear_only ) {
+
/* only log a clear if the entry was dirty */
- if(was_dirty) {
+ if ( was_dirty ) {
+
H5C__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr)
+
} /* end if */
} else if(write_entry) {
+
HDassert(was_dirty);
/* only log a flush if we actually wrote to disk */
H5C__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr)
+
} /* end else if */
/* Note that the algorithm below is (very) similar to the set of operations
@@ -6144,12 +7022,18 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
*/
/* Update the cache internal data structures. */
- if(destroy) {
+ if ( destroy ) {
+
/* Sanity checks */
- if(take_ownership)
+ if ( take_ownership ) {
+
HDassert(!destroy_entry);
- else
+
+ } else {
+
HDassert(destroy_entry);
+ }
+
HDassert(!entry_ptr->is_pinned);
/* Update stats, while entry is still in the cache */
@@ -6159,8 +7043,12 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
* to be removed from the cache, send a 'before eviction' notice while
* the entry is still fully integrated in the cache.
*/
- if(entry_ptr->type->notify && (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_BEFORE_EVICT, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry to evict")
+ if ( ( entry_ptr->type->notify ) &&
+ ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_BEFORE_EVICT,
+ entry_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "can't notify client about entry to evict")
/* Update the cache internal data structures as appropriate
* for a destroy. Specifically:
@@ -6175,52 +7063,61 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
*
* 5) Remove it from the tag list for this object
*
- * Finally, if the destroy_entry flag is set, discard the
+ * Finally, if the destroy_entry flag is set, discard the
* entry.
*/
H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr, FAIL)
- if(entry_ptr->in_slist && del_from_slist_on_destroy)
+ if ( ( entry_ptr->in_slist ) && ( del_from_slist_on_destroy ) ) {
+
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, during_flush)
+ }
#ifdef H5_HAVE_PARALLEL
/* Check for collective read access flag */
- if(entry_ptr->coll_access) {
+ if ( entry_ptr->coll_access ) {
+
entry_ptr->coll_access = FALSE;
+
H5C__REMOVE_FROM_COLL_LIST(cache_ptr, entry_ptr, FAIL)
+
} /* end if */
#endif /* H5_HAVE_PARALLEL */
H5C__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, FAIL)
/* Remove entry from tag list */
- if(H5C__untag_entry(cache_ptr, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove entry from tag list")
+ if ( H5C__untag_entry(cache_ptr, entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, \
+ "can't remove entry from tag list")
- /* verify that the entry is no longer part of any flush dependencies */
+ /* verify that the entry is no longer part of any flush dependencies */
HDassert(entry_ptr->flush_dep_nparents == 0);
- HDassert(entry_ptr->flush_dep_nchildren == 0);
+ HDassert(entry_ptr->flush_dep_nchildren == 0);
+
} /* end if */
else {
+
HDassert(clear_only || write_entry);
HDassert(entry_ptr->is_dirty);
- HDassert(entry_ptr->in_slist);
+ HDassert((!cache_ptr->slist_enabled) || (entry_ptr->in_slist));
/* We are either doing a flush or a clear.
*
* A clear and a flush are the same from the point of
- * view of the replacement policy and the slist.
+ * view of the replacement policy and the slist.
* Hence no differentiation between them.
*
- * JRM -- 7/7/07
+ * JRM -- 7/7/07
*/
H5C__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, FAIL)
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, during_flush)
- /* mark the entry as clean and update the index for
- * entry clean. Also, call the clear callback
+ /* mark the entry as clean and update the index for
+ * entry clean. Also, call the clear callback
* if defined.
*/
entry_ptr->is_dirty = FALSE;
@@ -6228,20 +7125,34 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN(cache_ptr, entry_ptr);
/* Check for entry changing status and do notifications, etc. */
- if(was_dirty) {
- /* If the entry's type has a 'notify' callback send a 'entry cleaned'
- * notice now that the entry is fully integrated into the cache.
+ if ( was_dirty ) {
+
+ /* If the entry's type has a 'notify' callback send a
+ * 'entry cleaned' notice now that the entry is fully
+ * integrated into the cache.
*/
- if(entry_ptr->type->notify &&
- (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag cleared")
+ if ( ( entry_ptr->type->notify ) &&
+ ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED,
+ entry_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "can't notify client about entry dirty flag cleared")
+
+ /* Propagate the clean flag up the flush dependency chain
+ * if appropriate
+ */
+ if ( entry_ptr->flush_dep_ndirty_children != 0 ) {
- /* Propagate the clean flag up the flush dependency chain if appropriate */
- if(entry_ptr->flush_dep_ndirty_children != 0)
HDassert(entry_ptr->flush_dep_ndirty_children == 0);
- if(entry_ptr->flush_dep_nparents > 0)
- if(H5C__mark_flush_dep_clean(entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKCLEAN, FAIL, "Can't propagate flush dep clean flag")
+ }
+
+ if ( entry_ptr->flush_dep_nparents > 0 ) {
+
+ if ( H5C__mark_flush_dep_clean(entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKCLEAN, FAIL, \
+ "Can't propagate flush dep clean flag")
+ }
} /* end if */
} /* end else */
@@ -6249,45 +7160,54 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
entry_ptr->flush_in_progress = FALSE;
/* capture the cache entry address for the log_flush call at the
- end before the entry_ptr gets freed */
+ * end before the entry_ptr gets freed
+ */
entry_addr = entry_ptr->addr;
- /* Internal cache data structures should now be up to date, and
- * consistent with the status of the entry.
+ /* Internal cache data structures should now be up to date, and
+ * consistent with the status of the entry.
*
* Now discard the entry if appropriate.
*/
- if(destroy) {
+ if ( destroy ) {
+
/* Sanity check */
HDassert(0 == entry_ptr->flush_dep_nparents);
/* if both suppress_image_entry_frees and entry_ptr->include_in_image
- * are true, simply set entry_ptr->image_ptr to NULL, as we have
+ * are true, simply set entry_ptr->image_ptr to NULL, as we have
* another pointer to the buffer in an instance of H5C_image_entry_t
* in cache_ptr->image_entries.
*
* Otherwise, free the buffer if it exists.
*/
- if(suppress_image_entry_frees && entry_ptr->include_in_image)
+ if ( suppress_image_entry_frees && entry_ptr->include_in_image ) {
+
entry_ptr->image_ptr = NULL;
- else if(entry_ptr->image_ptr != NULL)
+
+ } else if ( entry_ptr->image_ptr != NULL ) {
+
entry_ptr->image_ptr = H5MM_xfree(entry_ptr->image_ptr);
+ }
- /* If the entry is not a prefetched entry, verify that the flush
+ /* If the entry is not a prefetched entry, verify that the flush
* dependency parents addresses array has been transferred.
*
* If the entry is prefetched, the free_isr routine will dispose of
* the flush dependency parents addresses array if necessary.
*/
- if(!entry_ptr->prefetched) {
+ if ( ! entry_ptr->prefetched ) {
+
HDassert(0 == entry_ptr->fd_parent_count);
HDassert(NULL == entry_ptr->fd_parent_addrs);
+
} /* end if */
- /* Check whether we should free the space in the file that
- * the entry occupies
+ /* Check whether we should free the space in the file that
+ * the entry occupies
*/
- if(free_file_space) {
+ if ( free_file_space ) {
+
hsize_t fsf_size;
/* Sanity checks */
@@ -6307,29 +7227,40 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
* it to get the size of the block of file space to free.
* Otherwise use entry_ptr->size.
*/
- if(entry_ptr->type->fsf_size) {
- if((entry_ptr->type->fsf_size)((void *)entry_ptr, &fsf_size) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "unable to get file space free size")
+ if ( entry_ptr->type->fsf_size ) {
+
+ if ( (entry_ptr->type->fsf_size)((void *)entry_ptr, &fsf_size)
+ < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, \
+ "unable to get file space free size")
+
} /* end if */
- else /* no file space free size callback -- use entry size */
+ else { /* no file space free size callback -- use entry size */
+
fsf_size = entry_ptr->size;
+ }
/* Release the space on disk */
- if(H5MF_xfree(f, entry_ptr->type->mem_type, entry_ptr->addr, fsf_size) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "unable to free file space for cache entry")
+ if ( H5MF_xfree(f, entry_ptr->type->mem_type,
+ entry_ptr->addr, fsf_size) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, \
+ "unable to free file space for cache entry")
+
} /* end if ( free_file_space ) */
/* Reset the pointer to the cache the entry is within. -QAK */
entry_ptr->cache_ptr = NULL;
- /* increment entries_removed_counter and set
- * last_entry_removed_ptr. As we are likely abuut to
- * free the entry, recall that last_entry_removed_ptr
+ /* increment entries_removed_counter and set
+ * last_entry_removed_ptr. As we are likely abuut to
+ * free the entry, recall that last_entry_removed_ptr
* must NEVER be dereferenced.
*
* Recall that these fields are maintained to allow functions
- * that perform scans of lists of entries to detect the
- * unexpected removal of entries (via expunge, eviction,
+ * that perform scans of lists of entries to detect the
+ * unexpected removal of entries (via expunge, eviction,
* or take ownership at present), so that they can re-start
* their scans if necessary.
*
@@ -6339,22 +7270,32 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
*/
cache_ptr->entries_removed_counter++;
cache_ptr->last_entry_removed_ptr = entry_ptr;
- if(entry_ptr == cache_ptr->entry_watched_for_removal)
+
+ if ( entry_ptr == cache_ptr->entry_watched_for_removal ) {
+
cache_ptr->entry_watched_for_removal = NULL;
+ }
/* Check for actually destroying the entry in memory */
/* (As opposed to taking ownership of it) */
- if(destroy_entry) {
- if(entry_ptr->is_dirty) {
+ if ( destroy_entry ) {
+
+ if ( entry_ptr->is_dirty ) {
+
/* Reset dirty flag */
entry_ptr->is_dirty = FALSE;
- /* If the entry's type has a 'notify' callback send a 'entry cleaned'
- * notice now that the entry is fully integrated into the cache.
+ /* If the entry's type has a 'notify' callback send a
+ * 'entry cleaned' notice now that the entry is fully
+ * integrated into the cache.
*/
- if(entry_ptr->type->notify &&
- (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag cleared")
+ if ( ( entry_ptr->type->notify ) &&
+ ( (entry_ptr->type->notify)
+ (H5C_NOTIFY_ACTION_ENTRY_CLEANED, entry_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "can't notify client about entry dirty flag cleared")
+
} /* end if */
/* we are about to discard the in core representation --
@@ -6366,44 +7307,65 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
/* verify that the image has been freed */
HDassert(entry_ptr->image_ptr == NULL);
- if(entry_ptr->type->free_icr((void *)entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "free_icr callback failed")
+ if ( entry_ptr->type->free_icr((void *)entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "free_icr callback failed")
+
} /* end if */
else {
+
HDassert(take_ownership);
/* client is taking ownership of the entry.
- * set bad magic here too so the cache will choke
+ * set bad magic here too so the cache will choke
* unless the entry is re-inserted properly
*/
entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC;
+
} /* end else */
} /* if (destroy) */
- /* Check if we have to update the page buffer with cleared entries
- * so it doesn't go out of date
+ /* Check if we have to update the page buffer with cleared entries
+ * so it doesn't go out of date
*/
- if(update_page_buffer) {
+ if ( update_page_buffer ) {
+
/* Sanity check */
HDassert(!destroy);
HDassert(entry_ptr->image_ptr);
- if(f->shared->page_buf && f->shared->page_buf->page_size >= entry_ptr->size)
- if(H5PB_update_entry(f->shared->page_buf, entry_ptr->addr, entry_ptr->size, entry_ptr->image_ptr) > 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Failed to update PB with metadata cache")
+ if ( ( f->shared->page_buf ) &&
+ ( f->shared->page_buf->page_size >= entry_ptr->size ) ) {
+
+ if ( H5PB_update_entry(f->shared->page_buf, entry_ptr->addr,
+ entry_ptr->size, entry_ptr->image_ptr) > 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Failed to update PB with metadata cache")
+ } /* end if */
} /* end if */
- if(cache_ptr->log_flush)
- if((cache_ptr->log_flush)(cache_ptr, entry_addr, was_dirty, flags) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "log_flush callback failed")
+ if ( cache_ptr->log_flush ) {
+
+ if ( (cache_ptr->log_flush)(cache_ptr, entry_addr,
+ was_dirty, flags) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "log_flush callback failed")
+
+ } /* end if */
done:
- HDassert( ( ret_value != SUCCEED ) || ( destroy_entry ) ||
+
+ HDassert( ( ret_value != SUCCEED ) || ( destroy_entry ) ||
( ! entry_ptr->flush_in_progress ) );
- HDassert( ( ret_value != SUCCEED ) || ( destroy_entry ) ||
+
+ HDassert( ( ret_value != SUCCEED ) || ( destroy_entry ) ||
( take_ownership ) || ( ! entry_ptr->is_dirty ) );
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C__flush_single_entry() */
@@ -6417,7 +7379,7 @@ done:
* If exceed, adjust 'len' accordingly.
*
* Verify that 'len' should not exceed eoa when 'actual' is
- * true i.e. 'len' is the actual length from get_load_size
+ * true i.e. 'len' is the actual length from get_load_size
* callback with non-null image pointer.
* If exceed, return error.
*
@@ -6438,7 +7400,7 @@ H5C__verify_len_eoa(H5F_t *f, const H5C_class_t *type, haddr_t addr,
FUNC_ENTER_STATIC
- /* if type == H5FD_MEM_GHEAP, H5F_block_read() forces
+ /* if type == H5FD_MEM_GHEAP, H5F_block_read() forces
* type to H5FD_MEM_DRAW via its call to H5F__accum_read().
* Thus we do the same for purposes of computing the EOA
* for sanity checks.
@@ -6545,7 +7507,7 @@ H5C_load_entry(H5F_t * f,
if(NULL == (image = (uint8_t *)H5MM_malloc(len + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(image + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(image + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
#ifdef H5_HAVE_PARALLEL
@@ -6570,7 +7532,7 @@ H5C_load_entry(H5F_t * f,
/* Get the # of read attempts */
max_tries = tries = H5F_GET_READ_ATTEMPTS(f);
- /*
+ /*
* This do/while loop performs the following till the metadata checksum
* is correct or the file's number of allowed read attempts are reached.
* --read the metadata
@@ -6583,7 +7545,7 @@ H5C_load_entry(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "image null after H5MM_realloc()")
image = (uint8_t *)new_image;
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(image + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(image + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
} /* end if */
@@ -6627,7 +7589,7 @@ H5C_load_entry(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "image null after H5MM_realloc()")
image = (uint8_t *)new_image;
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(image + actual_len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(image + actual_len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
if(actual_len > len) {
@@ -6870,8 +7832,8 @@ H5C__make_space_in_cache(H5F_t *f, size_t space_needed, hbool_t write_permitted)
HDassert(cache_ptr->index_size == (cache_ptr->clean_index_size + cache_ptr->dirty_index_size));
/* check to see if cache_ptr->msic_in_progress is TRUE. If it, this
- * is a re-entrant call via a client callback called in the make
- * space in cache process. To avoid an infinite recursion, set
+ * is a re-entrant call via a client callback called in the make
+ * space in cache process. To avoid an infinite recursion, set
* reentrant_call to TRUE, and goto done.
*/
if(cache_ptr->msic_in_progress) {
@@ -6943,9 +7905,9 @@ H5C__make_space_in_cache(H5F_t *f, size_t space_needed, hbool_t write_permitted)
}
#endif /* H5C_COLLECT_CACHE_STATS */
- /* reset entries_removed_counter and
- * last_entry_removed_ptr prior to the call to
- * H5C__flush_single_entry() so that we can spot
+ /* reset entries_removed_counter and
+ * last_entry_removed_ptr prior to the call to
+ * H5C__flush_single_entry() so that we can spot
* unexpected removals of entries from the cache,
* and set the restart_scan flag if proceeding
* would be likely to cause us to scan an entry
@@ -6962,7 +7924,7 @@ H5C__make_space_in_cache(H5F_t *f, size_t space_needed, hbool_t write_permitted)
restart_scan = TRUE;
- } else if ( (cache_ptr->index_size + space_needed) > cache_ptr->max_cache_size
+ } else if ( (cache_ptr->index_size + space_needed) > cache_ptr->max_cache_size
#ifdef H5_HAVE_PARALLEL
&& !(entry_ptr->coll_access)
#endif /* H5_HAVE_PARALLEL */
@@ -7120,7 +8082,7 @@ H5C__make_space_in_cache(H5F_t *f, size_t space_needed, hbool_t write_permitted)
prev_ptr = entry_ptr->aux_prev;
- if ( ( !(entry_ptr->prefetched_dirty) )
+ if ( ( !(entry_ptr->prefetched_dirty) )
#ifdef H5_HAVE_PARALLEL
&& ( ! (entry_ptr->coll_access) )
#endif /* H5_HAVE_PARALLEL */
@@ -7170,7 +8132,7 @@ done:
*
* Changes:
*
- * Added code to verify that the LRU contains no pinned
+ * Added code to verify that the LRU contains no pinned
* entries. JRM -- 4/25/14
*
*-------------------------------------------------------------------------
@@ -7250,7 +8212,7 @@ H5C_validate_lru_list(H5C_t * cache_ptr)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed")
}
- if ( ( entry_ptr->is_pinned ) ||
+ if ( ( entry_ptr->is_pinned ) ||
( entry_ptr->pinned_from_client ) ||
( entry_ptr->pinned_from_cache ) ) {
@@ -7286,7 +8248,7 @@ done:
*
* Function: H5C_validate_pinned_entry_list
*
- * Purpose: Debugging function that scans the pinned entry list for
+ * Purpose: Debugging function that scans the pinned entry list for
* errors.
*
* If an error is detected, the function generates a
@@ -7418,7 +8380,7 @@ done:
*
* Function: H5C_validate_protected_entry_list
*
- * Purpose: Debugging function that scans the protected entry list for
+ * Purpose: Debugging function that scans the protected entry list for
* errors.
*
* If an error is detected, the function generates a
@@ -7543,11 +8505,11 @@ done:
*
* Function: H5C_entry_in_skip_list
*
- * Purpose: Debugging function that scans skip list to see if it
- * is in present. We need this, as it is possible for
+ * Purpose: Debugging function that scans skip list to see if it
+ * is in present. We need this, as it is possible for
* an entry to be in the skip list twice.
*
- * Return: FALSE if the entry is not in the skip list, and TRUE
+ * Return: FALSE if the entry is not in the skip list, and TRUE
* if it is.
*
* Programmer: John Mainzer, 11/1/14
@@ -7609,11 +8571,21 @@ H5C_entry_in_skip_list(H5C_t * cache_ptr, H5C_cache_entry_t *target_ptr)
* Programmer: Mike McGreevy
* November 3, 2010
*
+ * Changes: Modified function to setup the slist before calling
+ * H%C_flush_cache(), and take it down afterwards. Note
+ * that the slist need not be empty after the call to
+ * H5C_flush_cache() since we are only flushing marked
+ * entries. Thus must set the clear_slist parameter
+ * of H5C_set_slist_enabled to TRUE.
+ *
+ * JRM -- 5/6/20
+ *
*-------------------------------------------------------------------------
*/
+
herr_t
H5C__flush_marked_entries(H5F_t * f)
-{
+{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
@@ -7621,12 +8593,31 @@ H5C__flush_marked_entries(H5F_t * f)
/* Assertions */
HDassert(f != NULL);
+
+ /* Enable the slist, as it is needed in the flush */
+ if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist enabled failed")
+
+
/* Flush all marked entries */
- if(H5C_flush_cache(f, H5C__FLUSH_MARKED_ENTRIES_FLAG | H5C__FLUSH_IGNORE_PROTECTED_FLAG) < 0)
+ if ( H5C_flush_cache(f, H5C__FLUSH_MARKED_ENTRIES_FLAG |
+ H5C__FLUSH_IGNORE_PROTECTED_FLAG) < 0 )
+
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush cache")
+ /* Disable the slist. Set the clear_slist parameter to TRUE
+ * since we called H5C_flush_cache() with the
+ * H5C__FLUSH_MARKED_ENTRIES_FLAG.
+ */
+ if ( H5C_set_slist_enabled(f->shared->cache, FALSE, TRUE) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "disable slist failed")
+
done:
+
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C__flush_marked_entries */
@@ -7635,7 +8626,7 @@ done:
* Function: H5C_cork
*
* Purpose: To cork/uncork/get cork status of an object depending on "action":
- * H5C__SET_CORK:
+ * H5C__SET_CORK:
* To cork the object
* Return error if the object is already corked
* H5C__UNCORK:
@@ -7644,7 +8635,7 @@ done:
* H5C__GET_CORKED:
* To retrieve the cork status of an object in
* the parameter "corked"
- *
+ *
* Return: Success: Non-negative
* Failure: Negative
*
@@ -7654,7 +8645,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5C_cork(H5C_t *cache_ptr, haddr_t obj_addr, unsigned action, hbool_t *corked)
+H5C_cork(H5C_t *cache_ptr, haddr_t obj_addr, unsigned action, hbool_t *corked)
{
H5C_tag_info_t *tag_info; /* Points to a tag info struct */
herr_t ret_value = SUCCEED;
@@ -7836,8 +8827,8 @@ done:
/*-------------------------------------------------------------------------
* Function: H5C__mark_flush_dep_serialized()
*
- * Purpose: Decrement the flush_dep_nunser_children fields of all the
- * target entry's flush dependency parents in response to
+ * Purpose: Decrement the flush_dep_nunser_children fields of all the
+ * target entry's flush dependency parents in response to
* the target entry becoming serialized.
*
* Return: Non-negative on success/Negative on failure
@@ -7886,7 +8877,7 @@ done:
* Function: H5C__mark_flush_dep_unserialized()
*
* Purpose: Increment the flush_dep_nunser_children fields of all the
- * target entry's flush dependency parents in response to
+ * target entry's flush dependency parents in response to
* the target entry becoming unserialized.
*
* Return: Non-negative on success/Negative on failure
@@ -7912,7 +8903,7 @@ H5C__mark_flush_dep_unserialized(H5C_cache_entry_t * entry_ptr)
/* Sanity check */
HDassert(entry_ptr->flush_dep_parent);
HDassert(entry_ptr->flush_dep_parent[u]->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
- HDassert(entry_ptr->flush_dep_parent[u]->flush_dep_nunser_children <
+ HDassert(entry_ptr->flush_dep_parent[u]->flush_dep_nunser_children <
entry_ptr->flush_dep_parent[u]->flush_dep_nchildren);
/* increment parents number of usserialized children */
@@ -7972,11 +8963,11 @@ H5C__assert_flush_dep_nocycle(const H5C_cache_entry_t * entry,
/*-------------------------------------------------------------------------
* Function: H5C__serialize_cache
*
- * Purpose: Serialize (i.e. construct an on disk image) for all entries
- * in the metadata cache including clean entries.
+ * Purpose: Serialize (i.e. construct an on disk image) for all entries
+ * in the metadata cache including clean entries.
*
* Note that flush dependencies and "flush me last" flags
- * must be observed in the serialization process.
+ * must be observed in the serialization process.
*
* Note also that entries may be loaded, flushed, evicted,
* expunged, relocated, resized, or removed from the cache
@@ -7984,17 +8975,17 @@ H5C__assert_flush_dep_nocycle(const H5C_cache_entry_t * entry,
* a regular flush.
*
* However, we are given that the cache will contain no protected
- * entries on entry to this routine (although entries may be
- * briefly protected and then unprotected during the serialize
- * process).
+ * entries on entry to this routine (although entries may be
+ * briefly protected and then unprotected during the serialize
+ * process).
*
- * The objective of this routine is serialize all entries and
- * to force all entries into their actual locations on disk.
+ * The objective of this routine is serialize all entries and
+ * to force all entries into their actual locations on disk.
*
- * The initial need for this routine is to settle all entries
- * in the cache prior to construction of the metadata cache
+ * The initial need for this routine is to settle all entries
+ * in the cache prior to construction of the metadata cache
* image so that the size of the cache image can be calculated.
- * However, I gather that other uses for the routine are
+ * However, I gather that other uses for the routine are
* under consideration.
*
* Return: Non-negative on success/Negative on failure or if there was
@@ -8065,10 +9056,10 @@ H5C__serialize_cache(H5F_t *f)
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
#ifndef NDEBUG
- /* if this is a debug build, set the serialization_count field of
+ /* if this is a debug build, set the serialization_count field of
* each entry in the cache to zero before we start the serialization.
* This allows us to detect the case in which any entry is serialized
- * more than once (a performance issues), and more importantly, the
+ * more than once (a performance issues), and more importantly, the
* case is which any flush depencency parent is serializes more than
* once (a correctness issue).
*/
@@ -8084,10 +9075,10 @@ H5C__serialize_cache(H5F_t *f)
} /* end block */
#endif /* NDEBUG */
- /* set cache_ptr->serialization_in_progress to TRUE, and back
+ /* set cache_ptr->serialization_in_progress to TRUE, and back
* to FALSE at the end of the function. Must maintain this flag
- * to support H5C_get_serialization_in_progress(), which is in
- * turn required to support sanity checking in some cache
+ * to support H5C_get_serialization_in_progress(), which is in
+ * turn required to support sanity checking in some cache
* clients.
*/
HDassert(!cache_ptr->serialization_in_progress);
@@ -8165,16 +9156,16 @@ done:
*
* If the cache contains protected entries in the specified
* ring, the function will fail, as protected entries cannot
- * be serialized. However all unprotected entries in the
- * target ring should be serialized before the function
+ * be serialized. However all unprotected entries in the
+ * target ring should be serialized before the function
* returns failure.
*
* If flush dependencies appear in the target ring, the
* function makes repeated passes through the index list
* serializing entries in flush dependency order.
*
- * All entries outside the H5C_RING_SBE are marked for
- * inclusion in the cache image. Entries in H5C_RING_SBE
+ * All entries outside the H5C_RING_SBE are marked for
+ * inclusion in the cache image. Entries in H5C_RING_SBE
* and below are marked for exclusion from the image.
*
* Return: Non-negative on success/Negative on failure or if there was
@@ -8209,76 +9200,76 @@ H5C__serialize_ring(H5F_t *f, H5C_ring_t ring)
/* The objective here is to serialize all entries in the cache ring
* in flush dependency order.
*
- * The basic algorithm is to scan the cache index list looking for
+ * The basic algorithm is to scan the cache index list looking for
* unserialized entries that are either not in a flush dependency
* relationship, or which have no unserialized children. Any such
- * entry is serialized and its flush dependency parents (if any) are
+ * entry is serialized and its flush dependency parents (if any) are
* informed -- allowing them to decrement their userialized child counts.
*
* However, this algorithm is complicated by the ability
- * of client serialization callbacks to perform operations on
- * on the cache which can result in the insertion, deletion,
+ * of client serialization callbacks to perform operations on
+ * on the cache which can result in the insertion, deletion,
* relocation, resize, dirty, flush, eviction, or removal (via the
* take ownership flag) of entries. Changes in the flush dependency
* structure are also possible.
*
- * On the other hand, the algorithm is simplified by the fact that
- * we are serializing, not flushing. Thus, as long as all entries
+ * On the other hand, the algorithm is simplified by the fact that
+ * we are serializing, not flushing. Thus, as long as all entries
* are serialized correctly, it doesn't matter if we have to go back
* and serialize an entry a second time.
*
- * These possible actions result in the following modfications to
+ * These possible actions result in the following modfications to
* tha basic algorithm:
*
- * 1) In the event of an entry expunge, eviction or removal, we must
- * restart the scan as it is possible that the next entry in our
+ * 1) In the event of an entry expunge, eviction or removal, we must
+ * restart the scan as it is possible that the next entry in our
* scan is no longer in the cache. Were we to examine this entry,
* we would be accessing deallocated memory.
*
- * 2) A resize, dirty, or insertion of an entry may result in the
- * the increment of a flush dependency parent's dirty and/or
- * unserialized child count. In the context of serializing the
- * the cache, this is a non-issue, as even if we have already
- * serialized the parent, it will be marked dirty and its image
- * marked out of date if appropriate when the child is serialized.
- *
+ * 2) A resize, dirty, or insertion of an entry may result in the
+ * the increment of a flush dependency parent's dirty and/or
+ * unserialized child count. In the context of serializing the
+ * the cache, this is a non-issue, as even if we have already
+ * serialized the parent, it will be marked dirty and its image
+ * marked out of date if appropriate when the child is serialized.
+ *
* However, this is a major issue for a flush, as were this to happen
* in a flush, it would violate the invariant that the flush dependency
- * feature is intended to enforce. As the metadata cache has no
- * control over the behavior of cache clients, it has no way of
+ * feature is intended to enforce. As the metadata cache has no
+ * control over the behavior of cache clients, it has no way of
* preventing this behaviour. However, it should detect it if at all
- * possible.
+ * possible.
*
* Do this by maintaining a count of the number of times each entry is
- * serialized during a cache serialization. If any flush dependency
+ * serialized during a cache serialization. If any flush dependency
* parent is serialized more than once, throw an assertion failure.
*
- * 3) An entry relocation will typically change the location of the
- * entry in the index list. This shouldn't cause problems as we
- * will scan the index list until we make a complete pass without
- * finding anything to serialize -- making relocations of either
+ * 3) An entry relocation will typically change the location of the
+ * entry in the index list. This shouldn't cause problems as we
+ * will scan the index list until we make a complete pass without
+ * finding anything to serialize -- making relocations of either
* the current or next entries irrelevant.
*
- * Note that since a relocation may result in our skipping part of
+ * Note that since a relocation may result in our skipping part of
* the index list, we must always do at least one more pass through
* the index list after an entry relocation.
*
- * 4) Changes in the flush dependency structure are possible on
+ * 4) Changes in the flush dependency structure are possible on
* entry insertion, load, expunge, evict, or remove. Destruction
- * of a flush dependency has no effect, as it can only relax the
+ * of a flush dependency has no effect, as it can only relax the
* flush dependencies. Creation of a flush dependency can create
- * an unserialized child of a flush dependency parent where all
+ * an unserialized child of a flush dependency parent where all
* flush dependency children were previously serialized. Should
* this child dirty the flush dependency parent when it is serialized,
* the parent will be re-serialized.
*
- * Per the discussion of 2) above, this is a non issue for cache
+ * Per the discussion of 2) above, this is a non issue for cache
* serialization, and a major problem for cache flush. Using the
- * same detection mechanism, throw an assertion failure if this
- * condition appears.
+ * same detection mechanism, throw an assertion failure if this
+ * condition appears.
*
- * Observe that either eviction or removal of entries as a result of
- * a serialization is not a problem as long as the flush depencency
+ * Observe that either eviction or removal of entries as a result of
+ * a serialization is not a problem as long as the flush depencency
* tree does not change beyond the removal of a leaf.
*/
while(!done) {
@@ -8296,7 +9287,7 @@ H5C__serialize_ring(H5F_t *f, H5C_ring_t ring)
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
/* Verify that either the entry is already serialized, or
- * that it is assigned to either the target or an inner
+ * that it is assigned to either the target or an inner
* ring.
*/
HDassert((entry_ptr->ring >= ring) || (entry_ptr->image_up_to_date));
@@ -8363,9 +9354,9 @@ H5C__serialize_ring(H5F_t *f, H5C_ring_t ring)
cache_ptr->entries_relocated_counter = 0;
/* At this point, all entries not marked "flush me last" and in
- * the current ring or outside it should be serialized and have up
- * to date images. Scan the index list again to serialize the
- * "flush me last" entries (if they are in the current ring) and to
+ * the current ring or outside it should be serialized and have up
+ * to date images. Scan the index list again to serialize the
+ * "flush me last" entries (if they are in the current ring) and to
* verify that all other entries have up to date images.
*/
entry_ptr = cache_ptr->il_head;
@@ -8418,7 +9409,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5C__serialize_single_entry
*
- * Purpose: Serialize the cache entry pointed to by the entry_ptr
+ * Purpose: Serialize the cache entry pointed to by the entry_ptr
* parameter.
*
* Return: Non-negative on success/Negative on failure
@@ -8459,7 +9450,7 @@ H5C__serialize_single_entry(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry
if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + image_size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + image_size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
} /* end if */
@@ -8482,13 +9473,13 @@ done:
*
* Purpose: Serialize an entry and generate its image.
*
- * Note: This may cause the entry to be re-sized and/or moved in
- * the cache.
+ * Note: This may cause the entry to be re-sized and/or moved in
+ * the cache.
*
- * As we will not update the metadata cache's data structures
- * until we we finish the write, we must touch up these
- * data structures for size and location changes even if we
- * are about to delete the entry from the cache (i.e. on a
+ * As we will not update the metadata cache's data structures
+ * until we we finish the write, we must touch up these
+ * data structures for size and location changes even if we
+ * are about to delete the entry from the cache (i.e. on a
* flush destroy).
*
* Return: Non-negative on success/Negative on failure
@@ -8496,14 +9487,18 @@ done:
* Programmer: Mohamad Chaarawi
* 2/10/16
*
+ * Changes: Updated sanity checks for the possibility that the skip
+ * list is disabled.
+ * JRM 5/16/20
+ *
*-------------------------------------------------------------------------
*/
herr_t
H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
{
- haddr_t new_addr = HADDR_UNDEF;
- haddr_t old_addr = HADDR_UNDEF;
- size_t new_len = 0;
+ haddr_t new_addr = HADDR_UNDEF;
+ haddr_t old_addr = HADDR_UNDEF;
+ size_t new_len = 0;
unsigned serialize_flags = H5C__SERIALIZE_NO_FLAGS_SET;
herr_t ret_value = SUCCEED;
@@ -8524,16 +9519,24 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
old_addr = entry_ptr->addr;
/* Call client's pre-serialize callback, if there's one */
- if(entry_ptr->type->pre_serialize &&
- (entry_ptr->type->pre_serialize)(f, (void *)entry_ptr,
- entry_ptr->addr, entry_ptr->size, &new_addr, &new_len, &serialize_flags) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to pre-serialize entry")
+ if ( ( entry_ptr->type->pre_serialize ) &&
+ ( (entry_ptr->type->pre_serialize)(f, (void *)entry_ptr,
+ entry_ptr->addr, entry_ptr->size,
+ &new_addr, &new_len,
+ &serialize_flags) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "unable to pre-serialize entry")
/* Check for any flags set in the pre-serialize callback */
- if(serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET) {
+ if ( serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET ) {
+
/* Check for unexpected flags from serialize callback */
- if(serialize_flags & ~(H5C__SERIALIZE_RESIZED_FLAG | H5C__SERIALIZE_MOVED_FLAG))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unknown serialize flag(s)")
+ if ( serialize_flags & ~(H5C__SERIALIZE_RESIZED_FLAG |
+ H5C__SERIALIZE_MOVED_FLAG) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "unknown serialize flag(s)")
#ifdef H5_HAVE_PARALLEL
/* In the parallel case, resizes and moves in
@@ -8562,28 +9565,40 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
* If that ceases to be the case, further
* tests will be necessary.
*/
- if(cache_ptr->aux_ptr != NULL)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "resize/move in serialize occurred in parallel case")
+ if ( cache_ptr->aux_ptr != NULL )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "resize/move in serialize occurred in parallel case")
#endif
/* If required, resize the buffer and update the entry and the cache
- * data structures */
- if(serialize_flags & H5C__SERIALIZE_RESIZED_FLAG) {
+ * data structures
+ */
+ if ( serialize_flags & H5C__SERIALIZE_RESIZED_FLAG ) {
+
/* Sanity check */
HDassert(new_len > 0);
/* Allocate a new image buffer */
- if(NULL == (entry_ptr->image_ptr = H5MM_realloc(entry_ptr->image_ptr, new_len + H5C_IMAGE_EXTRA_SPACE)))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
+ if ( NULL == (entry_ptr->image_ptr =
+ H5MM_realloc(entry_ptr->image_ptr,
+ new_len + H5C_IMAGE_EXTRA_SPACE)) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, \
+ "memory allocation failed for on disk image buffer")
+
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + new_len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + new_len,
+ H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
/* Update statistics for resizing the entry */
- H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, new_len);
+ H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, \
+ new_len);
/* Update the hash table for the size change */
- H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, new_len, entry_ptr, !(entry_ptr->is_dirty));
+ H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, \
+ new_len, entry_ptr, !(entry_ptr->is_dirty));
/* The entry can't be protected since we are in the process of
* flushing it. Thus we must update the replacement policy data
@@ -8592,27 +9607,34 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
*/
H5C__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_len);
- /* As we haven't updated the cache data structures for
+ /* As we haven't updated the cache data structures for
* for the flush or flush destroy yet, the entry should
- * be in the slist. Thus update it for the size change.
+ * be in the slist if the slist is enabled. Since
+ * H5C__UPDATE_SLIST_FOR_SIZE_CHANGE() is a no-op if the
+ * slist is enabled, call it un-conditionally.
*/
HDassert(entry_ptr->is_dirty);
- HDassert(entry_ptr->in_slist);
- H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, new_len);
+ HDassert((entry_ptr->in_slist) || (!cache_ptr->slist_enabled));
+
+ H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, \
+ new_len);
/* Finally, update the entry for its new size */
entry_ptr->size = new_len;
+
} /* end if */
- /* If required, udate the entry and the cache data structures
- * for a move
+ /* If required, udate the entry and the cache data structures
+ * for a move
*/
- if(serialize_flags & H5C__SERIALIZE_MOVED_FLAG) {
+ if ( serialize_flags & H5C__SERIALIZE_MOVED_FLAG ) {
+
/* Update stats and entries relocated counter */
H5C__UPDATE_STATS_FOR_MOVE(cache_ptr, entry_ptr)
/* We must update cache data structures for the change in address */
- if(entry_ptr->addr == old_addr) {
+ if ( entry_ptr->addr == old_addr ) {
+
/* Delete the entry from the hash table and the slist */
H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr, FAIL);
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE);
@@ -8623,30 +9645,43 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
/* And then reinsert in the index and slist */
H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL);
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL);
+
} /* end if */
- else /* move is already done for us -- just do sanity checks */
+ else { /* move is already done for us -- just do sanity checks */
+
HDassert(entry_ptr->addr == new_addr);
+ }
} /* end if */
} /* end if(serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET) */
/* Serialize object into buffer */
- if(entry_ptr->type->serialize(f, entry_ptr->image_ptr, entry_ptr->size, (void *)entry_ptr) < 0)
+ if ( entry_ptr->type->serialize(f, entry_ptr->image_ptr, entry_ptr->size,
+ (void *)entry_ptr) < 0 )
+
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to serialize entry")
+
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDassert(0 == HDmemcmp(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE));
+ HDassert(0 == HDmemcmp(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size,\
+ H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE));
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
entry_ptr->image_up_to_date = TRUE;
- /* Propagate the fact that the entry is serialized up the
+ /* Propagate the fact that the entry is serialized up the
* flush dependency chain if appropriate. Since the image must
* have been out of date for this function to have been called
* (see assertion on entry), no need to check that -- only check
* for flush dependency parents.
*/
HDassert(entry_ptr->flush_dep_nunser_children == 0);
- if(entry_ptr->flush_dep_nparents > 0)
- if(H5C__mark_flush_dep_serialized(entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate serialization status to fd parents")
+
+ if ( entry_ptr->flush_dep_nparents > 0 ) {
+
+ if ( H5C__mark_flush_dep_serialized(entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "Can't propagate serialization status to fd parents")
+ }
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -8762,8 +9797,8 @@ H5C_remove_entry(void *_entry)
if(entry == cache->entry_watched_for_removal)
cache->entry_watched_for_removal = NULL;
- /* Internal cache data structures should now be up to date, and
- * consistent with the status of the entry.
+ /* Internal cache data structures should now be up to date, and
+ * consistent with the status of the entry.
*
* Now clean up internal cache fields if appropriate.
*/