diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2009-03-17 17:08:12 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2009-03-17 17:08:12 (GMT) |
commit | cbd0928d89170db56dba6c6b8c3fd7d02fe18ce6 (patch) | |
tree | 4e01bad49a84d4180baa6235972a17cbd62d5dc1 /src | |
parent | 5b9b684c890bf2694b0fab26b05f1c9d87f256d1 (diff) | |
download | hdf5-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.c | 410 | ||||
-rw-r--r-- | src/H5Cprivate.h | 22 | ||||
-rw-r--r-- | src/H5Edefin.h | 2 | ||||
-rw-r--r-- | src/H5Einit.h | 10 | ||||
-rw-r--r-- | src/H5Epubgen.h | 4 | ||||
-rw-r--r-- | src/H5Eterm.h | 4 | ||||
-rw-r--r-- | src/H5err.txt | 2 | ||||
-rw-r--r-- | src/H5private.h | 5 |
8 files changed, 408 insertions, 51 deletions
@@ -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 |