summaryrefslogtreecommitdiffstats
path: root/src/H5Cdbg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Cdbg.c')
-rw-r--r--src/H5Cdbg.c780
1 files changed, 698 insertions, 82 deletions
diff --git a/src/H5Cdbg.c b/src/H5Cdbg.c
index 16077c8..4a08d9b 100644
--- a/src/H5Cdbg.c
+++ b/src/H5Cdbg.c
@@ -5,12 +5,10 @@
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
- * the files COPYING and Copyright.html. COPYING can be found at the root *
- * of the source code distribution tree; Copyright.html can be found at the *
- * root level of an installed copy of the electronic HDF5 document set and *
- * is linked from the top-level documents page. It can also be found at *
- * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
- * access to either file, you may request a copy from help@hdfgroup.org. *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*-------------------------------------------------------------------------
@@ -30,13 +28,18 @@
#include "H5Cmodule.h" /* This source code file is part of the H5C module */
+#define H5AC_FRIEND
+
+
+
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5Cpkg.h" /* Cache */
-#include "H5Eprivate.h" /* Error handling */
+#include "H5private.h" /* Generic Functions */
+#include "H5ACpkg.h" /* Metadata Cache */
+#include "H5Cpkg.h" /* Cache */
+#include "H5Eprivate.h" /* Error Handling */
/****************/
@@ -53,10 +56,6 @@
/* Local Prototypes */
/********************/
-#if 0 /* debugging routines */
-herr_t H5C_dump_cache_skip_list(H5C_t *cache_ptr, char *calling_fcn);
-#endif /* debugging routines */
-
/*********************/
/* Package Variables */
@@ -73,6 +72,7 @@ herr_t H5C_dump_cache_skip_list(H5C_t *cache_ptr, char *calling_fcn);
/*******************/
+#ifndef NDEBUG
/*-------------------------------------------------------------------------
* Function: H5C_dump_cache
@@ -104,7 +104,7 @@ H5C_dump_cache(H5C_t * cache_ptr, const char * cache_name)
/* First, create a skip list */
if(NULL == (slist_ptr = H5SL_create(H5SL_TYPE_HADDR, NULL)))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "can't create skip list.")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "can't create skip list")
/* Next, scan the index, and insert all entries in the skip list.
* Do this, as we want to display cache entries in increasing address
@@ -178,6 +178,85 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C_dump_cache() */
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_dump_cache_LRU
+ *
+ * Purpose: Print a summary of the contents of the metadata cache
+ * LRU for debugging purposes.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 10/10/10
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_dump_cache_LRU(H5C_t *cache_ptr, const char *cache_name)
+{
+ H5C_cache_entry_t * entry_ptr;
+ int i = 0;
+
+ FUNC_ENTER_NOAPI_NOERR
+
+ /* Sanity check */
+ HDassert(cache_ptr != NULL);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_name != NULL );
+
+ HDfprintf(stdout, "\n\nDump of metadata cache LRU \"%s\"\n", cache_name);
+ HDfprintf(stdout, "LRU len = %d, LRU size = %d\n",
+ cache_ptr->LRU_list_len, (int)(cache_ptr->LRU_list_size));
+ HDfprintf(stdout, "index_size = %d, max_cache_size = %d, delta = %d\n\n",
+ (int)(cache_ptr->index_size), (int)(cache_ptr->max_cache_size),
+ (int)(cache_ptr->max_cache_size) - (int)(cache_ptr->index_size));
+
+ /* Print header */
+ HDfprintf(stdout, "Entry ");
+ HDfprintf(stdout, "| Address ");
+ HDfprintf(stdout, "| Tag ");
+ HDfprintf(stdout, "| Size ");
+ HDfprintf(stdout, "| Ring ");
+ HDfprintf(stdout, "| Type ");
+ HDfprintf(stdout, "| Dirty");
+ HDfprintf(stdout, "\n");
+
+ HDfprintf(stdout, "----------------------------------------------------------------------------------------------------------------\n");
+
+ entry_ptr = cache_ptr->LRU_head_ptr;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ /* Print entry */
+ HDfprintf(stdout, "%s%5d ", cache_ptr->prefix, i);
+ HDfprintf(stdout, " 0x%16llx ", (long long)(entry_ptr->addr));
+
+ if(NULL == entry_ptr->tag_info)
+ HDfprintf(stdout, " %16s ", "N/A");
+ else
+ HDfprintf(stdout, " 0x%16llx ",
+ (long long)(entry_ptr->tag_info->tag));
+
+ HDfprintf(stdout, " %5lld ", (long long)(entry_ptr->size));
+ HDfprintf(stdout, " %d ", (int)(entry_ptr->ring));
+ HDfprintf(stdout, " %2d %-32s ", (int)(entry_ptr->type->id),
+ (entry_ptr->type->name));
+ HDfprintf(stdout, " %d", (int)(entry_ptr->is_dirty));
+ HDfprintf(stdout, "\n");
+
+ i++;
+ entry_ptr = entry_ptr->next;
+ } /* end while */
+
+ HDfprintf(stdout, "----------------------------------------------------------------------------------------------------------------\n");
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5C_dump_cache_LRU() */
+#endif /* NDEBUG */
/*-------------------------------------------------------------------------
@@ -194,7 +273,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-#if 0 /* debugging routine */
+#ifndef NDEBUG
herr_t
H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn)
{
@@ -203,14 +282,14 @@ H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn)
H5C_cache_entry_t * entry_ptr = NULL;
H5SL_node_t * node_ptr = NULL;
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI_NOERR
HDassert(cache_ptr != NULL);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(calling_fcn != NULL);
HDfprintf(stdout, "\n\nDumping metadata cache skip list from %s.\n", calling_fcn);
- HDfprintf(stdout, " slist len = %d.\n", cache_ptr->slist_len);
+ HDfprintf(stdout, " slist len = %u.\n", cache_ptr->slist_len);
HDfprintf(stdout, " slist size = %lld.\n", (long long)(cache_ptr->slist_size));
if(cache_ptr->slist_len > 0) {
@@ -240,9 +319,9 @@ H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn)
(int)(entry_ptr->is_dirty),
entry_ptr->type->name);
- HDfprintf(stdout, " node_ptr = 0x%llx, item = 0x%llx\n",
+ HDfprintf(stdout, " node_ptr = 0x%llx, item = %p\n",
(unsigned long long)node_ptr,
- (unsigned long long)H5SL_item(node_ptr));
+ H5SL_item(node_ptr));
/* increment node_ptr before we delete its target */
node_ptr = H5SL_next(node_ptr);
@@ -257,10 +336,110 @@ H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn)
HDfprintf(stdout, "\n\n");
-done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C_dump_cache_skip_list() */
-#endif /* debugging routine */
+#endif /* NDEBUG */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_dump_coll_write_list
+ *
+ * Purpose: Debugging routine that prints a summary of the contents of
+ * the collective write skip list used by the metadata cache
+ * in the parallel case to maintain a list of entries to write
+ * collectively at a sync point.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 4/1/17
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5_HAVE_PARALLEL
+#ifndef NDEBUG
+herr_t
+H5C_dump_coll_write_list(H5C_t * cache_ptr, char * calling_fcn)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ int i;
+ int list_len;
+ H5AC_aux_t * aux_ptr = NULL;
+ H5C_cache_entry_t * entry_ptr = NULL;
+ H5SL_node_t * node_ptr = NULL;
+
+ FUNC_ENTER_NOAPI_NOERR
+
+ HDassert(cache_ptr != NULL);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->aux_ptr);
+
+ aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
+
+ HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC);
+
+ HDassert(calling_fcn != NULL);
+
+ list_len = (int)H5SL_count(cache_ptr->coll_write_list);
+
+ HDfprintf(stdout, "\n\nDumping MDC coll write list from %d:%s.\n",
+ aux_ptr->mpi_rank, calling_fcn);
+ HDfprintf(stdout, " slist len = %u.\n", cache_ptr->slist_len);
+
+ if ( list_len > 0 ) {
+
+ /* scan the collective write list generating the desired output */
+ HDfprintf(stdout,
+ "Num: Addr: Len: Prot/Pind: Dirty: Type:\n");
+
+ i = 0;
+
+ node_ptr = H5SL_first(cache_ptr->coll_write_list);
+
+ if ( node_ptr != NULL )
+
+ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ else
+
+ entry_ptr = NULL;
+
+ while ( entry_ptr != NULL ) {
+
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ HDfprintf(stdout,
+ "%s%d 0x%016llx %4lld %d/%d %d %s\n",
+ cache_ptr->prefix, i,
+ (long long)(entry_ptr->addr),
+ (long long)(entry_ptr->size),
+ (int)(entry_ptr->is_protected),
+ (int)(entry_ptr->is_pinned),
+ (int)(entry_ptr->is_dirty),
+ entry_ptr->type->name);
+
+ node_ptr = H5SL_next(node_ptr);
+
+ if ( node_ptr != NULL )
+
+ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ else
+
+ entry_ptr = NULL;
+
+ i++;
+
+ } /* end while */
+ } /* end if */
+
+ HDfprintf(stdout, "\n\n");
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C_dump_coll_write_list() */
+#endif /* NDEBUG */
+#endif /* H5_HAVE_PARALLEL */
/*-------------------------------------------------------------------------
@@ -285,7 +464,7 @@ H5C_set_prefix(H5C_t * cache_ptr, char * prefix)
if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC) ||
(prefix == NULL) || (HDstrlen(prefix) >= H5C__PREFIX_LEN))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad param(s) on entry.")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad param(s) on entry")
HDstrncpy(&(cache_ptr->prefix[0]), prefix, (size_t)(H5C__PREFIX_LEN));
@@ -342,19 +521,6 @@ done:
* Programmer: John Mainzer
* 6/2/04
*
- * JRM -- 11/13/08
- * Added code displaying the max_clean_index_size and
- * max_dirty_index_size.
- *
- * MAM -- 01/06/09
- * Added code displaying the calls_to_msic,
- * total_entries_skipped_in_msic, total_entries_scanned_in_msic,
- * and max_entries_skipped_in_msic fields.
- *
- * JRM -- 4/11/15
- * Added code displaying the new slist_scan_restarts,
- * LRU_scan_restarts, and hash_bucket_scan_restarts fields;
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -398,9 +564,11 @@ H5C_stats(H5C_t * cache_ptr,
size_t aggregate_max_size = 0;
int32_t aggregate_max_pins = 0;
double hit_rate;
+ double prefetch_use_rate;
double average_successful_search_depth = 0.0f;
double average_failed_search_depth = 0.0f;
double average_entries_skipped_per_calls_to_msic = 0.0f;
+ double average_dirty_pf_entries_skipped_per_call_to_msic = 0.0f;
double average_entries_scanned_per_calls_to_msic = 0.0f;
#endif /* H5C_COLLECT_CACHE_STATS */
herr_t ret_value = SUCCEED; /* Return value */
@@ -503,12 +671,12 @@ H5C_stats(H5C_t * cache_ptr,
average_failed_search_depth);
HDfprintf(stdout,
- "%s current (max) index size / length = %ld (%ld) / %ld (%ld)\n",
+ "%s current (max) index size / length = %ld (%ld) / %lu (%lu)\n",
cache_ptr->prefix,
(long)(cache_ptr->index_size),
(long)(cache_ptr->max_index_size),
- (long)(cache_ptr->index_len),
- (long)(cache_ptr->max_index_len));
+ (unsigned long)(cache_ptr->index_len),
+ (unsigned long)(cache_ptr->max_index_len));
HDfprintf(stdout,
"%s current (max) clean/dirty idx size = %ld (%ld) / %ld (%ld)\n",
@@ -519,46 +687,46 @@ H5C_stats(H5C_t * cache_ptr,
(long)(cache_ptr->max_dirty_index_size));
HDfprintf(stdout,
- "%s current (max) slist size / length = %ld (%ld) / %ld (%ld)\n",
+ "%s current (max) slist size / length = %ld (%ld) / %lu (%lu)\n",
cache_ptr->prefix,
(long)(cache_ptr->slist_size),
(long)(cache_ptr->max_slist_size),
- (long)(cache_ptr->slist_len),
- (long)(cache_ptr->max_slist_len));
+ (unsigned long)(cache_ptr->slist_len),
+ (unsigned long)(cache_ptr->max_slist_len));
HDfprintf(stdout,
- "%s current (max) PL size / length = %ld (%ld) / %ld (%ld)\n",
+ "%s current (max) PL size / length = %ld (%ld) / %lu (%lu)\n",
cache_ptr->prefix,
(long)(cache_ptr->pl_size),
(long)(cache_ptr->max_pl_size),
- (long)(cache_ptr->pl_len),
- (long)(cache_ptr->max_pl_len));
+ (unsigned long)(cache_ptr->pl_len),
+ (unsigned long)(cache_ptr->max_pl_len));
HDfprintf(stdout,
- "%s current (max) PEL size / length = %ld (%ld) / %ld (%ld)\n",
+ "%s current (max) PEL size / length = %ld (%ld) / %lu (%lu)\n",
cache_ptr->prefix,
(long)(cache_ptr->pel_size),
(long)(cache_ptr->max_pel_size),
- (long)(cache_ptr->pel_len),
- (long)(cache_ptr->max_pel_len));
+ (unsigned long)(cache_ptr->pel_len),
+ (unsigned long)(cache_ptr->max_pel_len));
HDfprintf(stdout,
- "%s current LRU list size / length = %ld / %ld\n",
+ "%s current LRU list size / length = %ld / %lu\n",
cache_ptr->prefix,
(long)(cache_ptr->LRU_list_size),
- (long)(cache_ptr->LRU_list_len));
+ (unsigned long)(cache_ptr->LRU_list_len));
HDfprintf(stdout,
- "%s current clean LRU size / length = %ld / %ld\n",
+ "%s current clean LRU size / length = %ld / %lu\n",
cache_ptr->prefix,
(long)(cache_ptr->cLRU_list_size),
- (long)(cache_ptr->cLRU_list_len));
+ (unsigned long)(cache_ptr->cLRU_list_len));
HDfprintf(stdout,
- "%s current dirty LRU size / length = %ld / %ld\n",
+ "%s current dirty LRU size / length = %ld / %lu\n",
cache_ptr->prefix,
(long)(cache_ptr->dLRU_list_size),
- (long)(cache_ptr->dLRU_list_len));
+ (unsigned long)(cache_ptr->dLRU_list_len));
HDfprintf(stdout,
"%s Total hits / misses / hit_rate = %ld / %ld / %f\n",
@@ -625,11 +793,10 @@ H5C_stats(H5C_t * cache_ptr,
cache_ptr->prefix,
(long long)(cache_ptr->calls_to_msic));
- if (cache_ptr->calls_to_msic > 0) {
+ if (cache_ptr->calls_to_msic > 0)
average_entries_skipped_per_calls_to_msic =
(((double)(cache_ptr->total_entries_skipped_in_msic)) /
((double)(cache_ptr->calls_to_msic)));
- }
HDfprintf(stdout, "%s MSIC: Average/max entries skipped = %lf / %ld\n",
cache_ptr->prefix,
@@ -637,6 +804,17 @@ H5C_stats(H5C_t * cache_ptr,
(long)(cache_ptr->max_entries_skipped_in_msic));
if(cache_ptr->calls_to_msic > 0)
+ average_dirty_pf_entries_skipped_per_call_to_msic =
+ (((double)(cache_ptr->total_dirty_pf_entries_skipped_in_msic)) /
+ ((double)(cache_ptr->calls_to_msic)));
+
+ HDfprintf(stdout,
+ "%s MSIC: Average/max dirty pf entries skipped = %lf / %ld\n",
+ cache_ptr->prefix,
+ average_dirty_pf_entries_skipped_per_call_to_msic,
+ (long)(cache_ptr->max_dirty_pf_entries_skipped_in_msic));
+
+ if(cache_ptr->calls_to_msic > 0)
average_entries_scanned_per_calls_to_msic =
(((double)(cache_ptr->total_entries_scanned_in_msic)) /
((double)(cache_ptr->calls_to_msic)));
@@ -656,11 +834,44 @@ H5C_stats(H5C_t * cache_ptr,
cache_ptr->entries_scanned_to_make_space));
HDfprintf(stdout,
- "%s slist/LRU/hash bkt scan restarts = %lld / %lld / %lld.\n",
+ "%s slist/LRU/index scan restarts = %lld / %lld / %lld.\n",
cache_ptr->prefix,
(long long)(cache_ptr->slist_scan_restarts),
(long long)(cache_ptr->LRU_scan_restarts),
- (long long)(cache_ptr->hash_bucket_scan_restarts));
+ (long long)(cache_ptr->index_scan_restarts));
+
+ HDfprintf(stdout,
+ "%s cache image creations/reads/loads/size = %d / %d /%d / %Hu\n",
+ cache_ptr->prefix,
+ cache_ptr->images_created,
+ cache_ptr->images_read,
+ cache_ptr->images_loaded,
+ cache_ptr->last_image_size);
+
+ HDfprintf(stdout,
+ "%s prefetches / dirty prefetches = %lld / %lld\n",
+ cache_ptr->prefix,
+ (long long)(cache_ptr->prefetches),
+ (long long)(cache_ptr->dirty_prefetches));
+
+ HDfprintf(stdout,
+ "%s prefetch hits/flushes/evictions = %lld / %lld / %lld\n",
+ cache_ptr->prefix,
+ (long long)(cache_ptr->prefetch_hits),
+ (long long)(cache_ptr->flushes[H5AC_PREFETCHED_ENTRY_ID]),
+ (long long)(cache_ptr->evictions[H5AC_PREFETCHED_ENTRY_ID]));
+
+ if(cache_ptr->prefetches > 0)
+ prefetch_use_rate =
+ (double)100.0f * ((double)(cache_ptr->prefetch_hits)) /
+ ((double)(cache_ptr->prefetches));
+ else
+ prefetch_use_rate = 0.0f;
+
+ HDfprintf(stdout,
+ "%s prefetched entry use rate = %lf\n",
+ cache_ptr->prefix,
+ prefetch_use_rate);
#if H5C_COLLECT_CACHE_ENTRY_STATS
@@ -687,7 +898,7 @@ H5C_stats(H5C_t * cache_ptr,
HDfprintf(stdout, "%s Stats on %s:\n",
cache_ptr->prefix,
- ((cache_ptr->type_name_table_ptr))[i]);
+ ((cache_ptr->class_table_ptr))[i]->name);
if((cache_ptr->hits[i] > 0) || (cache_ptr->misses[i] > 0))
hit_rate = (double)100.0f * ((double)(cache_ptr->hits[i])) /
@@ -804,20 +1015,6 @@ done:
*
* Programmer: John Mainzer, 4/28/04
*
- * JRM 11/13/08
- * Added initialization for the new max_clean_index_size and
- * max_dirty_index_size fields.
- *
- * MAM -- 01/06/09
- * Added code to initalize the calls_to_msic,
- * total_entries_skipped_in_msic, total_entries_scanned_in_msic,
- * and max_entries_skipped_in_msic fields.
- *
- * JRM 4/11/15
- * Added code to initialize the new slist_scan_restarts,
- * LRU_scan_restarts, hash_bucket_scan_restarts, and
- * take_ownerships fields.
- *
*-------------------------------------------------------------------------
*/
void
@@ -886,16 +1083,27 @@ H5C_stats__reset(H5C_t H5_ATTR_UNUSED * cache_ptr)
cache_ptr->max_pel_len = 0;
cache_ptr->max_pel_size = (size_t)0;
- cache_ptr->calls_to_msic = 0;
- cache_ptr->total_entries_skipped_in_msic = 0;
- cache_ptr->total_entries_scanned_in_msic = 0;
- cache_ptr->max_entries_skipped_in_msic = 0;
- cache_ptr->max_entries_scanned_in_msic = 0;
- cache_ptr->entries_scanned_to_make_space = 0;
+ cache_ptr->calls_to_msic = 0;
+ cache_ptr->total_entries_skipped_in_msic = 0;
+ cache_ptr->total_dirty_pf_entries_skipped_in_msic = 0;
+ cache_ptr->total_entries_scanned_in_msic = 0;
+ cache_ptr->max_entries_skipped_in_msic = 0;
+ cache_ptr->max_dirty_pf_entries_skipped_in_msic = 0;
+ cache_ptr->max_entries_scanned_in_msic = 0;
+ cache_ptr->entries_scanned_to_make_space = 0;
cache_ptr->slist_scan_restarts = 0;
cache_ptr->LRU_scan_restarts = 0;
- cache_ptr->hash_bucket_scan_restarts = 0;
+ cache_ptr->index_scan_restarts = 0;
+
+ cache_ptr->images_created = 0;
+ cache_ptr->images_read = 0;
+ cache_ptr->images_loaded = 0;
+ cache_ptr->last_image_size = (hsize_t)0;
+
+ cache_ptr->prefetches = 0;
+ cache_ptr->dirty_prefetches = 0;
+ cache_ptr->prefetch_hits = 0;
#if H5C_COLLECT_CACHE_ENTRY_STATS
for(i = 0; i <= cache_ptr->max_type_id; i++) {
@@ -910,6 +1118,7 @@ H5C_stats__reset(H5C_t H5_ATTR_UNUSED * cache_ptr)
#endif /* H5C_COLLECT_CACHE_ENTRY_STATS */
#endif /* H5C_COLLECT_CACHE_STATS */
+ return;
} /* H5C_stats__reset() */
extern void
@@ -948,7 +1157,7 @@ H5C__dump_children_cb(H5C_cache_entry_t *entry_ptr, void *_ctx)
} /* end if */
return(H5_ITER_CONT);
-}
+} /* end H5C__dump_children_cb() */
static void
H5C__dump_children(H5C_t *cache_ptr, const H5C_cache_entry_t *entry_ptr,
@@ -964,7 +1173,7 @@ H5C__dump_children(H5C_t *cache_ptr, const H5C_cache_entry_t *entry_ptr,
ctx.prefix = prefix;
ctx.indent = indent;
H5C__iter_tagged_entries(cache_ptr, entry_ptr->tag_info->tag, FALSE, H5C__dump_children_cb, &ctx);
-}
+} /* end H5C__dump_children() */
void
H5C__dump_entry(H5C_t *cache_ptr, const H5C_cache_entry_t *entry_ptr,
@@ -978,4 +1187,411 @@ H5C__dump_entry(H5C_t *cache_ptr, const H5C_cache_entry_t *entry_ptr,
H5C__dump_parents(cache_ptr, entry_ptr, "Parent", indent);
if(entry_ptr->flush_dep_nchildren)
H5C__dump_children(cache_ptr, entry_ptr, FALSE, "Child", indent);
-}
+} /* end H5C__dump_entry() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_flush_dependency_exists()
+ *
+ * Purpose: Test to see if a flush dependency relationship exists
+ * between the supplied parent and child. Both parties
+ * are indicated by addresses so as to avoid the necessity
+ * of protect / unprotect calls prior to this call.
+ *
+ * If either the parent or the child is not in the metadata
+ * cache, the function sets *fd_exists_ptr to FALSE.
+ *
+ * If both are in the cache, the childs list of parents is
+ * searched for the proposed parent. If the proposed parent
+ * is found in the childs parent list, the function sets
+ * *fd_exists_ptr to TRUE. In all other non-error cases,
+ * the function sets *fd_exists_ptr FALSE.
+ *
+ * Return: SUCCEED on success/FAIL on failure. Note that
+ * *fd_exists_ptr is undefined on failure.
+ *
+ * Programmer: John Mainzer
+ * 9/28/16
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NDEBUG
+herr_t
+H5C_flush_dependency_exists(H5C_t *cache_ptr, haddr_t parent_addr, haddr_t child_addr,
+ hbool_t *fd_exists_ptr)
+{
+ hbool_t fd_exists = FALSE; /* whether flush dependency exists */
+ H5C_cache_entry_t * parent_ptr; /* Ptr to parent entry */
+ H5C_cache_entry_t * child_ptr; /* Ptr to child entry */
+ hbool_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(H5F_addr_defined(parent_addr));
+ HDassert(H5F_addr_defined(child_addr));
+ HDassert(fd_exists_ptr);
+
+ H5C__SEARCH_INDEX(cache_ptr, parent_addr, parent_ptr, FAIL)
+ H5C__SEARCH_INDEX(cache_ptr, child_addr, child_ptr, FAIL)
+
+ if(parent_ptr && child_ptr) {
+ HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(child_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ if(child_ptr->flush_dep_nparents > 0) {
+ unsigned u; /* Local index variable */
+
+ HDassert(child_ptr->flush_dep_parent);
+ HDassert(child_ptr->flush_dep_parent_nalloc >= child_ptr->flush_dep_nparents);
+
+ for(u = 0; u < child_ptr->flush_dep_nparents; u++) {
+ if(child_ptr->flush_dep_parent[u] == parent_ptr) {
+ fd_exists = TRUE;
+ HDassert(parent_ptr->flush_dep_nchildren > 0);
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
+ *fd_exists_ptr = fd_exists;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_flush_dependency_exists() */
+#endif /* NDEBUG */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5C_validate_index_list
+ *
+ * Purpose: Debugging function that scans the index list for errors.
+ *
+ * If an error is detected, the function generates a
+ * diagnostic and returns FAIL. If no error is detected,
+ * the function returns SUCCEED.
+ *
+ * Return: FAIL if error is detected, SUCCEED otherwise.
+ *
+ * Programmer: John Mainzer, 9/16/16
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NDEBUG
+herr_t
+H5C_validate_index_list(H5C_t *cache_ptr)
+{
+ H5C_cache_entry_t * entry_ptr = NULL;
+ uint32_t len = 0;
+ int32_t index_ring_len[H5C_RING_NTYPES];
+ size_t size = 0;
+ size_t clean_size = 0;
+ size_t dirty_size = 0;
+ size_t index_ring_size[H5C_RING_NTYPES];
+ size_t clean_index_ring_size[H5C_RING_NTYPES];
+ size_t dirty_index_ring_size[H5C_RING_NTYPES];
+ int i;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ for(i = 0; i < H5C_RING_NTYPES; i++) {
+ index_ring_len[i] = 0;
+ index_ring_size[i] = 0;
+ clean_index_ring_size[i] = 0;
+ dirty_index_ring_size[i] = 0;
+ } /* end if */
+
+ if(((cache_ptr->il_head == NULL) || (cache_ptr->il_tail == NULL))
+ && (cache_ptr->il_head != cache_ptr->il_tail))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointer validation failed")
+
+ if((cache_ptr->index_len == 1) && ((cache_ptr->il_head != cache_ptr->il_tail)
+ || (cache_ptr->il_head == NULL) || (cache_ptr->il_head->size != cache_ptr->index_size)))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointer sanity checks failed")
+
+ if((cache_ptr->index_len >= 1)
+ && ((cache_ptr->il_head == NULL)
+ || (cache_ptr->il_head->il_prev != NULL)
+ || (cache_ptr->il_tail == NULL)
+ || (cache_ptr->il_tail->il_next != NULL)))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list length sanity checks failed")
+
+ entry_ptr = cache_ptr->il_head;
+ while(entry_ptr != NULL) {
+ if((entry_ptr != cache_ptr->il_head)
+ && ((entry_ptr->il_prev == NULL) || (entry_ptr->il_prev->il_next != entry_ptr)))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointers for entry are invalid")
+
+ if((entry_ptr != cache_ptr->il_tail)
+ && ((entry_ptr->il_next == NULL) || (entry_ptr->il_next->il_prev != entry_ptr)))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointers for entry are invalid")
+
+ HDassert(entry_ptr->ring > 0);
+ HDassert(entry_ptr->ring < H5C_RING_NTYPES);
+
+ len++;
+ index_ring_len[entry_ptr->ring] += 1;
+
+ size += entry_ptr->size;
+ index_ring_size[entry_ptr->ring] += entry_ptr->size;
+
+ if(entry_ptr->is_dirty) {
+ dirty_size += entry_ptr->size;
+ dirty_index_ring_size[entry_ptr->ring] += entry_ptr->size;
+ } /* end if */
+ else {
+ clean_size += entry_ptr->size;
+ clean_index_ring_size[entry_ptr->ring] += entry_ptr->size;
+ } /* end else */
+
+ entry_ptr = entry_ptr->il_next;
+ } /* end while */
+
+ if((cache_ptr->index_len != len) || (cache_ptr->il_len != len)
+ || (cache_ptr->index_size != size) || (cache_ptr->il_size != size)
+ || (cache_ptr->clean_index_size != clean_size)
+ || (cache_ptr->dirty_index_size != dirty_size)
+ || (clean_size + dirty_size != size))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index, clean and dirty sizes for cache are invalid")
+
+ size = 0;
+ clean_size = 0;
+ dirty_size = 0;
+ for(i = 0; i < H5C_RING_NTYPES; i++) {
+ size += clean_index_ring_size[i] + dirty_index_ring_size[i];
+ clean_size += clean_index_ring_size[i];
+ dirty_size += dirty_index_ring_size[i];
+ } /* end for */
+
+ if((cache_ptr->index_size != size)
+ || (cache_ptr->clean_index_size != clean_size)
+ || (cache_ptr->dirty_index_size != dirty_size))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index, clean and dirty sizes for cache are invalid")
+
+done:
+ if(ret_value != SUCCEED)
+ HDassert(0);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_validate_index_list() */
+#endif /* NDEBUG */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5C_get_entry_ptr_from_addr()
+ *
+ * Purpose: Debugging function that attempts to look up an entry in the
+ * cache by its file address, and if found, returns a pointer
+ * to the entry in *entry_ptr_ptr. If the entry is not in the
+ * cache, *entry_ptr_ptr is set to NULL.
+ *
+ * WARNING: This call should be used only in debugging
+ * routines, and it should be avoided when
+ * possible.
+ *
+ * Further, if we ever multi-thread the cache,
+ * this routine will have to be either discarded
+ * or heavily re-worked.
+ *
+ * Finally, keep in mind that the entry whose
+ * pointer is obtained in this fashion may not
+ * be in a stable state.
+ *
+ * Note that this function is only defined if NDEBUG
+ * is not defined.
+ *
+ * As heavy use of this function is almost certainly a
+ * bad idea, the metadata cache tracks the number of
+ * successful calls to this function, and (if
+ * H5C_DO_SANITY_CHECKS is defined) displays any
+ * non-zero count on cache shutdown.
+ *
+ * Return: FAIL if error is detected, SUCCEED otherwise.
+ *
+ * Programmer: John Mainzer, 5/30/14
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NDEBUG
+herr_t
+H5C_get_entry_ptr_from_addr(H5C_t *cache_ptr, haddr_t addr, void **entry_ptr_ptr)
+{
+ H5C_cache_entry_t * entry_ptr = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(entry_ptr_ptr);
+
+ H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
+
+ if(entry_ptr == NULL)
+ /* the entry doesn't exist in the cache -- report this
+ * and quit.
+ */
+ *entry_ptr_ptr = NULL;
+ else {
+ *entry_ptr_ptr = entry_ptr;
+
+ /* increment call counter */
+ (cache_ptr->get_entry_ptr_from_addr_counter)++;
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_get_entry_ptr_from_addr() */
+#endif /* NDEBUG */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_get_serialization_in_progress
+ *
+ * Purpose: Return the current value of
+ * cache_ptr->serialization_in_progress.
+ *
+ * Return: Current value of cache_ptr->serialization_in_progress.
+ *
+ * Programmer: John Mainzer
+ * 8/24/15
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NDEBUG
+hbool_t
+H5C_get_serialization_in_progress(const H5C_t *cache_ptr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ FUNC_LEAVE_NOAPI(cache_ptr->serialization_in_progress)
+} /* H5C_get_serialization_in_progress() */
+#endif /* NDEBUG */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5C_cache_is_clean()
+ *
+ * Purpose: Debugging function that verifies that all rings in the
+ * metadata cache are clean from the outermost ring, inwards
+ * to the inner ring specified.
+ *
+ * Returns TRUE if all specified rings are clean, and FALSE
+ * if not. Throws an assertion failure on error.
+ *
+ * Return: TRUE if the indicated ring(s) are clean, and FALSE otherwise.
+ *
+ * Programmer: John Mainzer, 6/18/16
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NDEBUG
+hbool_t
+H5C_cache_is_clean(const H5C_t *cache_ptr, H5C_ring_t inner_ring)
+{
+ H5C_ring_t ring = H5C_RING_USER;
+ hbool_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(inner_ring >= H5C_RING_USER);
+ HDassert(inner_ring <= H5C_RING_SB);
+
+ while(ring <= inner_ring) {
+ if(cache_ptr->dirty_index_ring_size[ring] > 0)
+ HGOTO_DONE(FALSE)
+
+ ring++;
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_cache_is_clean() */
+#endif /* NDEBUG */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5C_verify_entry_type()
+ *
+ * Purpose: Debugging function that attempts to look up an entry in the
+ * cache by its file address, and if found, test to see if its
+ * type field contains the expted value.
+ *
+ * If the specified entry is in cache, *in_cache_ptr is set
+ * to TRUE, and *type_ok_ptr is set to TRUE or FALSE depending
+ * on whether the entries type field matches the expected_type
+ * parameter.
+ *
+ * If the target entry is not in cache, *in_cache_ptr is
+ * set to FALSE, and *type_ok_ptr is undefined.
+ *
+ * Note that this function is only defined if NDEBUG
+ * is not defined.
+ *
+ * Return: FAIL if error is detected, SUCCEED otherwise.
+ *
+ * Programmer: John Mainzer, 5/30/14
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NDEBUG
+herr_t
+H5C_verify_entry_type(H5C_t *cache_ptr, haddr_t addr,
+ const H5C_class_t *expected_type, hbool_t *in_cache_ptr,
+ hbool_t *type_ok_ptr)
+{
+ H5C_cache_entry_t * entry_ptr = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(expected_type);
+ HDassert(in_cache_ptr);
+ HDassert(type_ok_ptr);
+
+ H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
+
+ if(entry_ptr == NULL)
+ /* the entry doesn't exist in the cache -- report this
+ * and quit.
+ */
+ *in_cache_ptr = FALSE;
+ else {
+ *in_cache_ptr = TRUE;
+
+ if(entry_ptr->prefetched)
+ *type_ok_ptr = (expected_type->id == entry_ptr->prefetch_type_id);
+ else
+ *type_ok_ptr = (expected_type == entry_ptr->type);
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_verify_entry_type() */
+#endif /* NDEBUG */
+