diff options
Diffstat (limited to 'src/H5Cdbg.c')
-rw-r--r-- | src/H5Cdbg.c | 780 |
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 */ + |