summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2009-03-17 17:08:12 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2009-03-17 17:08:12 (GMT)
commitcbd0928d89170db56dba6c6b8c3fd7d02fe18ce6 (patch)
tree4e01bad49a84d4180baa6235972a17cbd62d5dc1 /src
parent5b9b684c890bf2694b0fab26b05f1c9d87f256d1 (diff)
downloadhdf5-cbd0928d89170db56dba6c6b8c3fd7d02fe18ce6.zip
hdf5-cbd0928d89170db56dba6c6b8c3fd7d02fe18ce6.tar.gz
hdf5-cbd0928d89170db56dba6c6b8c3fd7d02fe18ce6.tar.bz2
[svn-r16587] Description:
Add infrastructure & tests for "flush dependencies" in metadata cache, which allow relationships that specify which order to flush metadata entries in. Tested on: FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (jam) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode Mac OS X/32 10.5.6 (amazon) in debug mode Mac OS X/32 10.5.6 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode
Diffstat (limited to 'src')
-rw-r--r--src/H5C.c410
-rw-r--r--src/H5Cprivate.h22
-rw-r--r--src/H5Edefin.h2
-rw-r--r--src/H5Einit.h10
-rw-r--r--src/H5Epubgen.h4
-rw-r--r--src/H5Eterm.h4
-rw-r--r--src/H5err.txt2
-rw-r--r--src/H5private.h5
8 files changed, 408 insertions, 51 deletions
diff --git a/src/H5C.c b/src/H5C.c
index 49e7921..ad1bd57 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -3147,6 +3147,10 @@ H5C_create(size_t max_cache_size,
cache_ptr->epoch_marker_ringbuf_last = 0;
cache_ptr->epoch_marker_ringbuf_size = 0;
+ /* Initialize all epoch marker entries' fields to zero/FALSE/NULL */
+ HDmemset(cache_ptr->epoch_markers, 0, sizeof(cache_ptr->epoch_markers));
+
+ /* Set non-zero/FALSE/NULL fields for epoch markers */
for ( i = 0; i < H5C__MAX_EPOCH_MARKERS; i++ )
{
(cache_ptr->epoch_marker_active)[i] = FALSE;
@@ -3155,27 +3159,7 @@ H5C_create(size_t max_cache_size,
H5C__H5C_CACHE_ENTRY_T_MAGIC;
#endif /* NDEBUG */
((cache_ptr->epoch_markers)[i]).addr = (haddr_t)i;
- ((cache_ptr->epoch_markers)[i]).size = (size_t)0;
((cache_ptr->epoch_markers)[i]).type = &epoch_marker_class;
- ((cache_ptr->epoch_markers)[i]).is_dirty = FALSE;
- ((cache_ptr->epoch_markers)[i]).dirtied = FALSE;
- ((cache_ptr->epoch_markers)[i]).is_protected = FALSE;
- ((cache_ptr->epoch_markers)[i]).is_read_only = FALSE;
- ((cache_ptr->epoch_markers)[i]).ro_ref_count = 0;
- ((cache_ptr->epoch_markers)[i]).is_pinned = FALSE;
- ((cache_ptr->epoch_markers)[i]).in_slist = FALSE;
- ((cache_ptr->epoch_markers)[i]).ht_next = NULL;
- ((cache_ptr->epoch_markers)[i]).ht_prev = NULL;
- ((cache_ptr->epoch_markers)[i]).next = NULL;
- ((cache_ptr->epoch_markers)[i]).prev = NULL;
- ((cache_ptr->epoch_markers)[i]).aux_next = NULL;
- ((cache_ptr->epoch_markers)[i]).aux_prev = NULL;
-#if H5C_COLLECT_CACHE_ENTRY_STATS
- ((cache_ptr->epoch_markers)[i]).accesses = 0;
- ((cache_ptr->epoch_markers)[i]).clears = 0;
- ((cache_ptr->epoch_markers)[i]).flushes = 0;
- ((cache_ptr->epoch_markers)[i]).pins = 0;
-#endif /* H5C_COLLECT_CACHE_ENTRY_STATS */
}
if ( H5C_reset_cache_hit_rate_stats(cache_ptr) != SUCCEED ) {
@@ -3836,10 +3820,7 @@ H5C_flush_cache(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"next_entry_ptr == NULL 1 ?!?!");
}
-#ifndef NDEBUG
- HDassert( next_entry_ptr->magic ==
- H5C__H5C_CACHE_ENTRY_T_MAGIC );
-#endif /* NDEBUG */
+ HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
HDassert( next_entry_ptr->is_dirty );
HDassert( next_entry_ptr->in_slist );
@@ -3955,10 +3936,7 @@ H5C_flush_cache(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"next_entry_ptr == NULL 2 ?!?!");
}
-#ifndef NDEBUG
- HDassert( next_entry_ptr->magic ==
- H5C__H5C_CACHE_ENTRY_T_MAGIC );
-#endif /* NDEBUG */
+ HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
HDassert( next_entry_ptr->is_dirty );
HDassert( next_entry_ptr->in_slist );
} else {
@@ -4802,9 +4780,7 @@ H5C_insert_entry(H5F_t * f,
void * thing,
unsigned int flags)
{
- /* const char * fcn_name = "H5C_insert_entry()"; */
herr_t result;
- herr_t ret_value = SUCCEED; /* Return value */
hbool_t first_flush = TRUE;
hbool_t insert_pinned;
hbool_t set_flush_marker;
@@ -4812,6 +4788,8 @@ H5C_insert_entry(H5F_t * f,
size_t empty_space;
H5C_cache_entry_t * entry_ptr;
H5C_cache_entry_t * test_entry_ptr;
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5C_insert_entry, FAIL)
@@ -4900,6 +4878,12 @@ H5C_insert_entry(H5F_t * f,
entry_ptr->destroy_in_progress = FALSE;
entry_ptr->free_file_space_on_destroy = FALSE;
+ /* Initialize flush dependency height fields */
+ entry_ptr->flush_dep_parent = NULL;
+ for(u = 0; u < H5C__NUM_FLUSH_DEP_HEIGHTS; u++)
+ entry_ptr->child_flush_dep_height_rc[u] = 0;
+ entry_ptr->flush_dep_height = 0;
+
entry_ptr->ht_next = NULL;
entry_ptr->ht_prev = NULL;
@@ -7661,20 +7645,14 @@ H5C_stats__reset(H5C_t UNUSED * cache_ptr)
/*-------------------------------------------------------------------------
* Function: H5C_unpin_entry()
*
- * Purpose: Unpin a cache entry. The entry must be unprotected at
- * the time of call, and must be pinned.
+ * Purpose: Unpin a cache entry. The entry can be either protected or
+ * unprotected at the time of call, but must be pinned.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: John Mainzer
* 3/22/06
*
- * Modifications:
- *
- * JRM -- 4/26/06
- * Modified routine to allow it to operate on protected
- * entries.
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -8490,6 +8468,341 @@ done:
} /* H5C_validate_resize_config() */
+/*-------------------------------------------------------------------------
+ * Function: H5C_adjust_flush_dependency_rc()
+ *
+ * Purpose: "Atomicly" adjust flush dependency ref. counts for an entry,
+ * as a result of a flush dependency child's height changing.
+ *
+ * Note: Entry will remain in flush dependency relationship with its
+ * child entry (i.e. it's not going to get unpinned as a result
+ * of this change), but change could trickle upward, if this
+ * entry's height changes and it has a flush dependency parent.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * 3/05/09
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+H5C_adjust_flush_dependency_rc(H5C_cache_entry_t * cache_entry,
+ unsigned old_child_height, unsigned new_child_height)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5C_adjust_flush_dependency_rc)
+
+ /* Sanity checks */
+ HDassert(cache_entry);
+ HDassert(cache_entry->is_pinned);
+ HDassert(cache_entry->flush_dep_height > 0);
+ HDassert(cache_entry->flush_dep_height < H5C__NUM_FLUSH_DEP_HEIGHTS);
+ HDassert(cache_entry->child_flush_dep_height_rc[old_child_height] > 0);
+ HDassert(old_child_height < H5C__NUM_FLUSH_DEP_HEIGHTS);
+ HDassert(old_child_height != new_child_height);
+ HDassert(new_child_height < H5C__NUM_FLUSH_DEP_HEIGHTS);
+
+ /* Adjust ref. counts for entry's flush dependency children heights */
+ cache_entry->child_flush_dep_height_rc[new_child_height]++;
+ cache_entry->child_flush_dep_height_rc[old_child_height]--;
+
+ /* Check for flush dependency height of entry increasing */
+ if((new_child_height + 1) > cache_entry->flush_dep_height) {
+
+ /* Check if entry has _its_ own parent flush dependency entry */
+ if(NULL != cache_entry->flush_dep_parent) {
+ /* Adjust flush dependency ref. counts on entry's parent */
+ H5C_adjust_flush_dependency_rc(cache_entry->flush_dep_parent, cache_entry->flush_dep_height, new_child_height + 1);
+ } /* end if */
+
+ /* Set new flush dependency height of entry */
+ cache_entry->flush_dep_height = new_child_height + 1;
+ } /* end if */
+ else {
+ /* Check for child's flush dep. height decreasing and ref. count of
+ * old child height going to zero, it could mean the parent's
+ * flush dependency height dropped.
+ */
+ if((new_child_height < old_child_height)
+ && ((old_child_height + 1) == cache_entry->flush_dep_height)
+ && (0 == cache_entry->child_flush_dep_height_rc[old_child_height])) {
+ int i; /* Local index variable */
+
+ /* Re-scan child flush dependency height ref. counts to determine
+ * this entry's height.
+ */
+#ifndef NDEBUG
+ for(i = (H5C__NUM_FLUSH_DEP_HEIGHTS - 1); i > (int)new_child_height; i--)
+ HDassert(0 == cache_entry->child_flush_dep_height_rc[i]);
+#endif /* NDEBUG */
+ for(i = (int)new_child_height; i >= 0; i--)
+ /* Check for child flush dependencies of this height */
+ if(cache_entry->child_flush_dep_height_rc[i] > 0)
+ break;
+
+ /* Sanity checks */
+ HDassert((unsigned)(i + 1) < cache_entry->flush_dep_height);
+
+ /* Check if entry has _its_ own parent flush dependency entry */
+ if(NULL != cache_entry->flush_dep_parent) {
+ /* Adjust flush dependency ref. counts on entry's parent */
+ H5C_adjust_flush_dependency_rc(cache_entry->flush_dep_parent, cache_entry->flush_dep_height, (unsigned)(i + 1));
+ } /* end if */
+
+ /* Set new flush dependency height of entry */
+ cache_entry->flush_dep_height = (unsigned)(i + 1);
+ } /* end if */
+ } /* end else */
+
+
+ /* Post-conditions, for successful operation */
+ HDassert(cache_entry->is_pinned);
+ HDassert(cache_entry->flush_dep_height > 0);
+ HDassert(cache_entry->flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS);
+ HDassert(cache_entry->child_flush_dep_height_rc[new_child_height] > 0);
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* H5C_adjust_flush_dependency_rc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_create_flush_dependency()
+ *
+ * Purpose: Initiates a parent<->child entry flush dependency. The parent
+ * entry must be protected at the time of call, and must have all
+ * dependencies removed before the cache can shut down.
+ *
+ * Note: Flush dependencies in the cache indicate that a child entry
+ * must be flushed to the file before its parent. (This is
+ * currently used to implement Single-Writer/Multiple-Reader (SWMR)
+ * I/O access for data structures in the file).
+ *
+ * Each child entry can have only one parent entry, but parent
+ * entries can have >1 child entries. The flush dependency
+ * height of a parent entry is one greater than the max. flush
+ * dependency height of its children.
+ *
+ * Creating a flush dependency between two entries will also pin
+ * the parent entry. (The parent entry must _not_ be pinned
+ * through some other mechanism)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * 3/05/09
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NDEBUG
+herr_t
+H5C_create_flush_dependency(H5C_t * cache_ptr, void * parent_thing,
+ void * child_thing)
+#else
+herr_t
+H5C_create_flush_dependency(H5C_t UNUSED * cache_ptr, void * parent_thing,
+ void * child_thing)
+#endif
+{
+ H5C_cache_entry_t * parent_entry = (H5C_cache_entry_t *)parent_thing; /* Ptr to parent thing's entry */
+ H5C_cache_entry_t * child_entry = (H5C_cache_entry_t *)child_thing; /* Ptr to child thing's entry */
+#ifndef NDEBUG
+ unsigned prev_flush_dep_height = parent_entry->flush_dep_height; /* Previous flush height for parent entry */
+#endif /* NDEBUG */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5C_create_flush_dependency, FAIL)
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(parent_entry);
+ HDassert(parent_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(parent_entry->flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS);
+ HDassert(H5F_addr_defined(parent_entry->addr));
+ HDassert(child_entry);
+ HDassert(child_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(H5F_addr_defined(child_entry->addr));
+ HDassert(child_entry->flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS);
+
+ /* More sanity checks */
+ if(child_entry == parent_entry)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Child entry flush dependency parent can't be itself")
+ if(!parent_entry->is_protected)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Parent entry isn't protected")
+ if(NULL != child_entry->flush_dep_parent)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Child entry already has flush dependency parent")
+ {
+ H5C_cache_entry_t *tmp_entry = parent_entry; /* Temporary cache entry in flush dependency chain */
+ unsigned tmp_flush_height = 0; /* Different in heights of parent entry */
+
+ /* Find the top entry in the flush dependency list */
+ while(NULL != tmp_entry->flush_dep_parent) {
+ tmp_flush_height++;
+ tmp_entry = tmp_entry->flush_dep_parent;
+ } /* end while */
+
+ /* Check if we will make the dependency chain too long */
+ if((tmp_flush_height + child_entry->flush_dep_height + 1)
+ > H5C__NUM_FLUSH_DEP_HEIGHTS)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Combined flush dependency height too large")
+ }
+
+ /* Check for parent already pinned */
+ if(parent_entry->is_pinned) {
+ /* Verify that the parent entry was pinned through a flush dependency relationship */
+ if(0 == parent_entry->flush_dep_height)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Parent entry wasn't pinned through flush dependency")
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(parent_entry->flush_dep_height == 0);
+
+ /* Pin the parent entry */
+ parent_entry->is_pinned = TRUE;
+ H5C__UPDATE_STATS_FOR_PIN(cache_ptr, parent_entry)
+ } /* end else */
+
+ /* Increment ref. count for parent's flush dependency children heights */
+ parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height]++;
+
+ /* Check for increasing parent flush dependency height */
+ if((child_entry->flush_dep_height + 1) > parent_entry->flush_dep_height) {
+
+ /* Check if parent entry has _its_ own parent flush dependency entry */
+ if(NULL != parent_entry->flush_dep_parent) {
+ /* Adjust flush dependency ref. counts on parent entry's parent */
+ H5C_adjust_flush_dependency_rc(parent_entry->flush_dep_parent, parent_entry->flush_dep_height, (child_entry->flush_dep_height + 1));
+ } /* end if */
+
+ /* Increase flush dependency height of parent entry */
+ parent_entry->flush_dep_height = child_entry->flush_dep_height + 1;
+ } /* end if */
+
+ /* Set parent for child entry */
+ child_entry->flush_dep_parent = parent_entry;
+
+
+ /* Post-conditions, for successful operation */
+ HDassert(parent_entry->is_pinned);
+ HDassert(parent_entry->flush_dep_height > 0);
+ HDassert(parent_entry->flush_dep_height < H5C__NUM_FLUSH_DEP_HEIGHTS);
+ HDassert(prev_flush_dep_height <= parent_entry->flush_dep_height);
+ HDassert(parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height] > 0);
+ HDassert(NULL != child_entry->flush_dep_parent);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_create_flush_dependency() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_destroy_flush_dependency()
+ *
+ * Purpose: Terminates a parent<-> child entry flush dependency. The
+ * parent entry must be pinned and have a positive flush
+ * dependency height (which could go to zero as a result of
+ * this operation).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * 3/05/09
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_destroy_flush_dependency(H5C_t * cache_ptr, void *parent_thing,
+ void * child_thing)
+{
+ H5C_cache_entry_t * parent_entry = (H5C_cache_entry_t *)parent_thing; /* Ptr to parent entry */
+ H5C_cache_entry_t * child_entry = (H5C_cache_entry_t *)child_thing; /* Ptr to child entry */
+#ifndef NDEBUG
+ unsigned prev_flush_dep_height = parent_entry->flush_dep_height; /* Previous flush height for parent entry */
+#endif /* NDEBUG */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5C_destroy_flush_dependency, FAIL)
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(parent_entry);
+ HDassert(parent_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(H5F_addr_defined(parent_entry->addr));
+ HDassert(parent_entry->flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS);
+ HDassert(child_entry);
+ HDassert(child_entry->flush_dep_parent != child_entry);
+ HDassert(child_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(H5F_addr_defined(child_entry->addr));
+
+ /* Usage checks */
+ if(!parent_entry->is_protected)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry isn't pinned")
+ if(!parent_entry->is_pinned)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry isn't pinned")
+ if(0 == parent_entry->flush_dep_height)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry isn't a flush dependency parent")
+ if(NULL == child_entry->flush_dep_parent)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Child entry doesn't have a flush dependency parent")
+ if(0 == parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height])
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry flush dependency ref. count has no child entries of this height")
+ if(child_entry->flush_dep_parent != parent_entry)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry isn't flush dependency parent for child entry")
+
+ /* Decrement the ref. count for flush dependency height of children for parent entry */
+ parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height]--;
+
+ /* Check for flush dependency ref. count at this height going to zero and
+ * parent entry flush dependency height dropping
+ */
+ if(((child_entry->flush_dep_height + 1) == parent_entry->flush_dep_height) &&
+ 0 == parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height]) {
+ int i; /* Local index variable */
+
+ /* Reverse scan for new flush dependency height of parent */
+#ifndef NDEBUG
+ for(i = (H5C__NUM_FLUSH_DEP_HEIGHTS - 1); i > (int)child_entry->flush_dep_height; i--)
+ HDassert(0 == parent_entry->child_flush_dep_height_rc[i]);
+#endif /* NDEBUG */
+ for(i = (int)child_entry->flush_dep_height; i >= 0; i--)
+ /* Check for child flush dependencies of this height */
+ if(parent_entry->child_flush_dep_height_rc[i] > 0)
+ break;
+
+ /* Sanity check */
+ HDassert((unsigned)(i + 1) < parent_entry->flush_dep_height);
+
+ /* Check if parent entry is a child in another flush dependency relationship */
+ if(NULL != parent_entry->flush_dep_parent) {
+ /* Change flush dependency ref. counts of parent's parent */
+ H5C_adjust_flush_dependency_rc(parent_entry->flush_dep_parent, parent_entry->flush_dep_height, (unsigned)(i + 1));
+ } /* end if */
+
+ /* Increase flush dependency height of parent entry */
+ parent_entry->flush_dep_height = (unsigned)(i + 1);
+
+ /* Check for height of parent dropping to zero (i.e. no longer a
+ * parent of _any_ child flush dependencies).
+ */
+ if(0 == parent_entry->flush_dep_height) {
+ /* Unpin parent entry */
+ parent_entry->is_pinned = FALSE;
+ H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, parent_entry)
+ } /* end if */
+ } /* end if */
+
+ /* Reset parent of child entry */
+ child_entry->flush_dep_parent = NULL;
+
+ /* Post-conditions, for successful operation */
+ HDassert(prev_flush_dep_height >= parent_entry->flush_dep_height);
+ HDassert(NULL == child_entry->flush_dep_parent);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_destroy_flush_dependency() */
+
+
/*************************************************************************/
/**************************** Private Functions: *************************/
/*************************************************************************/
@@ -9976,9 +10289,7 @@ H5C_flush_invalidate_cache(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"next_entry_ptr == NULL 1 ?!?!");
}
-#ifndef NDEBUG
HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
-#endif /* NDEBUG */
HDassert( next_entry_ptr->is_dirty );
HDassert( next_entry_ptr->in_slist );
@@ -10074,10 +10385,7 @@ H5C_flush_invalidate_cache(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"next_entry_ptr == NULL 2 ?!?!");
}
-#ifndef NDEBUG
- HDassert( next_entry_ptr->magic ==
- H5C__H5C_CACHE_ENTRY_T_MAGIC );
-#endif /* NDEBUG */
+ HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
HDassert( next_entry_ptr->is_dirty );
HDassert( next_entry_ptr->in_slist );
@@ -10217,11 +10525,8 @@ H5C_flush_invalidate_cache(H5F_t * f,
entry_ptr = next_entry_ptr;
next_entry_ptr = entry_ptr->ht_next;
-#ifndef NDEBUG
HDassert ( ( next_entry_ptr == NULL ) ||
- ( next_entry_ptr->magic ==
- H5C__H5C_CACHE_ENTRY_T_MAGIC ) );
-#endif /* NDEBUG */
+ ( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC ) );
if ( entry_ptr->is_protected ) {
/* we have major problems -- but lets flush and destroy
@@ -11023,8 +11328,9 @@ H5C_load_entry(H5F_t * f,
#endif /* NDEBUG */
{
void * thing = NULL;
- void * ret_value = NULL;
H5C_cache_entry_t * entry_ptr = NULL;
+ unsigned u; /* Local index variable */
+ void * ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5C_load_entry)
@@ -11091,6 +11397,12 @@ H5C_load_entry(H5F_t * f,
HDassert( entry_ptr->size < H5C_MAX_ENTRY_SIZE );
+ /* Initialize flush dependency height fields */
+ entry_ptr->flush_dep_parent = NULL;
+ for(u = 0; u < H5C__NUM_FLUSH_DEP_HEIGHTS; u++)
+ entry_ptr->child_flush_dep_height_rc[u] = 0;
+ entry_ptr->flush_dep_height = 0;
+
entry_ptr->ht_next = NULL;
entry_ptr->ht_prev = NULL;
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index 4ce321c..65e6f6c 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -32,7 +32,7 @@
#include "H5Cpublic.h" /*public prototypes */
-/* Pivate headers needed by this header */
+/* Private headers needed by this header */
#include "H5private.h" /* Generic Functions */
#include "H5Fprivate.h" /* File access */
@@ -183,6 +183,14 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr,
#define H5C__DEFAULT_MAX_CACHE_SIZE ((size_t)(4 * 1024 * 1024))
#define H5C__DEFAULT_MIN_CLEAN_SIZE ((size_t)(2 * 1024 * 1024))
+/* Maximum height of flush dependency relationships between entries. This is
+ * currently tuned to the extensible array (H5EA) data structure, which only
+ * requires 4 levels of dependency (i.e. heights 0-3).
+ */
+
+#define H5C__NUM_FLUSH_DEP_HEIGHTS 4
+
+
/****************************************************************************
*
@@ -496,6 +504,12 @@ typedef struct H5C_cache_entry_t
hbool_t destroy_in_progress;
hbool_t free_file_space_on_destroy;
+ /* fields supporting the 'flush dependency height': */
+
+ struct H5C_cache_entry_t * flush_dep_parent;
+ uint64_t child_flush_dep_height_rc[H5C__NUM_FLUSH_DEP_HEIGHTS];
+ unsigned flush_dep_height;
+
/* fields supporting the hash table: */
struct H5C_cache_entry_t * ht_next;
@@ -1040,6 +1054,9 @@ H5_DLL herr_t H5C_rename_entry(H5C_t * cache_ptr,
H5_DLL herr_t H5C_pin_protected_entry(H5C_t * cache_ptr,
void * thing);
+H5_DLL herr_t H5C_create_flush_dependency(H5C_t *cache_ptr, void *parent_thing,
+ void *child_thing);
+
H5_DLL void * H5C_protect(H5F_t * f,
hid_t primary_dxpl_id,
hid_t secondary_dxpl_id,
@@ -1079,6 +1096,9 @@ H5_DLL void H5C_stats__reset(H5C_t * cache_ptr);
H5_DLL herr_t H5C_unpin_entry(H5C_t * cache_ptr, void * thing);
+H5_DLL herr_t H5C_destroy_flush_dependency(H5C_t *cache_ptr, void *parent_thing,
+ void *child_thing);
+
H5_DLL herr_t H5C_unprotect(H5F_t * f,
hid_t primary_dxpl_id,
hid_t secondary_dxpl_id,
diff --git a/src/H5Edefin.h b/src/H5Edefin.h
index 612fcb1..b31b31b 100644
--- a/src/H5Edefin.h
+++ b/src/H5Edefin.h
@@ -164,6 +164,8 @@ hid_t H5E_CANTMARKDIRTY_g = FAIL; /* Unable to mark a pinned entry as dirt
hid_t H5E_CANTDIRTY_g = FAIL; /* Unable to mark metadata as dirty */
hid_t H5E_CANTEXPUNGE_g = FAIL; /* Unable to expunge a metadata cache entry */
hid_t H5E_CANTRESIZE_g = FAIL; /* Unable to resize a metadata cache entry */
+hid_t H5E_CANTDEPEND_g = FAIL; /* Unable to create a flush dependency */
+hid_t H5E_CANTUNDEPEND_g = FAIL; /* Unable to destroy a flush dependency */
/* Link related errors */
hid_t H5E_TRAVERSE_g = FAIL; /* Link traversal failure */
diff --git a/src/H5Einit.h b/src/H5Einit.h
index 20e156c..204644f 100644
--- a/src/H5Einit.h
+++ b/src/H5Einit.h
@@ -622,6 +622,16 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to resize a metadata cache entr
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
if((H5E_CANTRESIZE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
+assert(H5E_CANTDEPEND_g==(-1));
+if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to create a flush dependency"))==NULL)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
+if((H5E_CANTDEPEND_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
+assert(H5E_CANTUNDEPEND_g==(-1));
+if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to destroy a flush dependency"))==NULL)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
+if((H5E_CANTUNDEPEND_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Link related errors */
assert(H5E_TRAVERSE_g==(-1));
diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h
index 4e981dc..736349a 100644
--- a/src/H5Epubgen.h
+++ b/src/H5Epubgen.h
@@ -266,6 +266,8 @@ H5_DLLVAR hid_t H5E_NOIDS_g; /* Out of IDs for group */
#define H5E_CANTDIRTY (H5OPEN H5E_CANTDIRTY_g)
#define H5E_CANTEXPUNGE (H5OPEN H5E_CANTEXPUNGE_g)
#define H5E_CANTRESIZE (H5OPEN H5E_CANTRESIZE_g)
+#define H5E_CANTDEPEND (H5OPEN H5E_CANTDEPEND_g)
+#define H5E_CANTUNDEPEND (H5OPEN H5E_CANTUNDEPEND_g)
H5_DLLVAR hid_t H5E_CANTFLUSH_g; /* Unable to flush data from cache */
H5_DLLVAR hid_t H5E_CANTSERIALIZE_g; /* Unable to serialize data from cache */
H5_DLLVAR hid_t H5E_CANTLOAD_g; /* Unable to load metadata into cache */
@@ -282,6 +284,8 @@ H5_DLLVAR hid_t H5E_CANTMARKDIRTY_g; /* Unable to mark a pinned entry as dirty *
H5_DLLVAR hid_t H5E_CANTDIRTY_g; /* Unable to mark metadata as dirty */
H5_DLLVAR hid_t H5E_CANTEXPUNGE_g; /* Unable to expunge a metadata cache entry */
H5_DLLVAR hid_t H5E_CANTRESIZE_g; /* Unable to resize a metadata cache entry */
+H5_DLLVAR hid_t H5E_CANTDEPEND_g; /* Unable to create a flush dependency */
+H5_DLLVAR hid_t H5E_CANTUNDEPEND_g; /* Unable to destroy a flush dependency */
/* Link related errors */
#define H5E_TRAVERSE (H5OPEN H5E_TRAVERSE_g)
diff --git a/src/H5Eterm.h b/src/H5Eterm.h
index 7595e7f..8936dc0 100644
--- a/src/H5Eterm.h
+++ b/src/H5Eterm.h
@@ -165,7 +165,9 @@ H5E_CANTUNPIN_g=
H5E_CANTMARKDIRTY_g=
H5E_CANTDIRTY_g=
H5E_CANTEXPUNGE_g=
-H5E_CANTRESIZE_g=
+H5E_CANTRESIZE_g=
+H5E_CANTDEPEND_g=
+H5E_CANTUNDEPEND_g=
/* Link related errors */
H5E_TRAVERSE_g=
diff --git a/src/H5err.txt b/src/H5err.txt
index 7f110b8..64e9729 100644
--- a/src/H5err.txt
+++ b/src/H5err.txt
@@ -169,6 +169,8 @@ MINOR, CACHE, H5E_CANTMARKDIRTY, Unable to mark a pinned entry as dirty
MINOR, CACHE, H5E_CANTDIRTY, Unable to mark metadata as dirty
MINOR, CACHE, H5E_CANTEXPUNGE, Unable to expunge a metadata cache entry
MINOR, CACHE, H5E_CANTRESIZE, Unable to resize a metadata cache entry
+MINOR, CACHE, H5E_CANTDEPEND, Unable to create a flush dependency
+MINOR, CACHE, H5E_CANTUNDEPEND, Unable to destroy a flush dependency
# B-tree related errors
MINOR, BTREE, H5E_NOTFOUND, Object not found
diff --git a/src/H5private.h b/src/H5private.h
index ea55a61..695b015 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -1898,6 +1898,11 @@ static herr_t H5_INTERFACE_INIT_FUNC(void);
} /*end scope from beginning of FUNC_ENTER*/
+/* Macro for "stringizing" an integer in the C preprocessor (use H5_TOSTRING) */
+/* (use H5_TOSTRING, H5_STRINGIZE is just part of the implementation) */
+#define H5_STRINGIZE(x) #x
+#define H5_TOSTRING(x) H5_STRINGIZE(x)
+
/* Macro for "glueing" together items, for re-scanning macros */
#define H5_GLUE(x,y) x##y
#define H5_GLUE3(x,y,z) x##y##z