1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /*-------------------------------------------------------------------------
15  *
16  * Created:     H5Cdbg.c
17  *              July 8 2016
18  *              Quincey Koziol
19  *
20  * Purpose:     Debugging Routines for the generic cache structure or entries.
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #include "H5Cmodule.h" /* This source code file is part of the H5C module */
30 
31 /***********/
32 /* Headers */
33 /***********/
34 #include "H5private.h"   /* Generic Functions            */
35 #include "H5ACprivate.h" /* Metadata Cache               */
36 #include "H5Cpkg.h"      /* Cache                        */
37 #include "H5Eprivate.h"  /* Error Handling               */
38 
39 /****************/
40 /* Local Macros */
41 /****************/
42 
43 /******************/
44 /* Local Typedefs */
45 /******************/
46 
47 /********************/
48 /* Local Prototypes */
49 /********************/
50 
51 /*********************/
52 /* Package Variables */
53 /*********************/
54 
55 /*****************************/
56 /* Library Private Variables */
57 /*****************************/
58 
59 /*******************/
60 /* Local Variables */
61 /*******************/
62 
63 #ifndef NDEBUG
64 
65 /*-------------------------------------------------------------------------
66  * Function:    H5C_dump_cache
67  *
68  * Purpose:     Print a summary of the contents of the metadata cache for
69  *              debugging purposes.
70  *
71  * Return:      Non-negative on success/Negative on failure
72  *
73  * Programmer:  John Mainzer
74  *              10/10/10
75  *
76  *-------------------------------------------------------------------------
77  */
78 herr_t
H5C_dump_cache(H5C_t * cache_ptr,const char * cache_name)79 H5C_dump_cache(H5C_t *cache_ptr, const char *cache_name)
80 {
81     H5C_cache_entry_t *entry_ptr;
82     H5SL_t *           slist_ptr = NULL;
83     int                i;                   /* Local index variable */
84     herr_t             ret_value = SUCCEED; /* Return value */
85 
86     FUNC_ENTER_NOAPI(FAIL)
87 
88     /* Sanity check */
89     HDassert(cache_ptr != NULL);
90     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
91     HDassert(cache_name != NULL);
92 
93     /* First, create a skip list */
94     if (NULL == (slist_ptr = H5SL_create(H5SL_TYPE_HADDR, NULL)))
95         HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "can't create skip list")
96 
97     /* Next, scan the index, and insert all entries in the skip list.
98      * Do this, as we want to display cache entries in increasing address
99      * order.
100      */
101     for (i = 0; i < H5C__HASH_TABLE_LEN; i++) {
102         entry_ptr = cache_ptr->index[i];
103 
104         while (entry_ptr != NULL) {
105             HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
106             if (H5SL_insert(slist_ptr, entry_ptr, &(entry_ptr->addr)) < 0)
107                 HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "can't insert entry in skip list")
108 
109             entry_ptr = entry_ptr->ht_next;
110         } /* end while */
111     }     /* end for */
112 
113     /* If we get this far, all entries in the cache are listed in the
114      * skip list -- scan the skip list generating the desired output.
115      */
116 
117     HDfprintf(stdout, "\n\nDump of metadata cache \"%s\"\n", cache_name);
118 
119     /* Print header */
120     HDfprintf(stdout, "Entry ");
121     HDfprintf(stdout, "|       Address      ");
122     HDfprintf(stdout, "|         Tag        ");
123     HDfprintf(stdout, "|  Size ");
124     HDfprintf(stdout, "| Ring ");
125     HDfprintf(stdout, "|              Type              ");
126     HDfprintf(stdout, "| Prot/Pin/Dirty");
127     HDfprintf(stdout, "\n");
128 
129     HDfprintf(stdout, "--------------------------------------------------------------------------------------"
130                       "--------------------------\n");
131 
132     i         = 0;
133     entry_ptr = (H5C_cache_entry_t *)H5SL_remove_first(slist_ptr);
134     while (entry_ptr != NULL) {
135         HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
136 
137         /* Print entry */
138         HDfprintf(stdout, "%s%5d ", cache_ptr->prefix, i);
139         HDfprintf(stdout, "  0x%16llx ", (long long)(entry_ptr->addr));
140         if (NULL == entry_ptr->tag_info)
141             HDfprintf(stdout, "    %16s ", "N/A");
142         else
143             HDfprintf(stdout, "  0x%16llx ", (long long)(entry_ptr->tag_info->tag));
144         HDfprintf(stdout, "  %5lld ", (long long)(entry_ptr->size));
145         HDfprintf(stdout, "    %d  ", (int)(entry_ptr->ring));
146         HDfprintf(stdout, "  %2d %-32s ", (int)(entry_ptr->type->id), (entry_ptr->type->name));
147         HDfprintf(stdout, " %d", (int)(entry_ptr->is_protected));
148         HDfprintf(stdout, " %d", (int)(entry_ptr->is_pinned));
149         HDfprintf(stdout, " %d", (int)(entry_ptr->is_dirty));
150         HDfprintf(stdout, "\n");
151 
152         /* remove the next (first) item in the skip list */
153         entry_ptr = (H5C_cache_entry_t *)H5SL_remove_first(slist_ptr);
154 
155         i++;
156     } /* end while */
157 
158     HDfprintf(stdout, "\n\n");
159 
160     /* Verify that all the entries were removed from the skip list */
161     HDassert(H5SL_count(slist_ptr) == 0);
162 
163 done:
164     /* Discard the skip list */
165     if (slist_ptr)
166         H5SL_close(slist_ptr);
167 
168     FUNC_LEAVE_NOAPI(ret_value)
169 } /* H5C_dump_cache() */
170 #endif /* NDEBUG */
171 
172 #ifndef NDEBUG
173 
174 /*-------------------------------------------------------------------------
175  * Function:    H5C_dump_cache_LRU
176  *
177  * Purpose:     Print a summary of the contents of the metadata cache
178  *              LRU for debugging purposes.
179  *
180  * Return:      Non-negative on success/Negative on failure
181  *
182  * Programmer:  John Mainzer
183  *              10/10/10
184  *
185  *-------------------------------------------------------------------------
186  */
187 herr_t
H5C_dump_cache_LRU(H5C_t * cache_ptr,const char * cache_name)188 H5C_dump_cache_LRU(H5C_t *cache_ptr, const char *cache_name)
189 {
190     H5C_cache_entry_t *entry_ptr;
191     int                i = 0;
192 
193     FUNC_ENTER_NOAPI_NOERR
194 
195     /* Sanity check */
196     HDassert(cache_ptr != NULL);
197     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
198     HDassert(cache_name != NULL);
199 
200     HDfprintf(stdout, "\n\nDump of metadata cache LRU \"%s\"\n", cache_name);
201     HDfprintf(stdout, "LRU len = %d, LRU size = %d\n", cache_ptr->LRU_list_len,
202               (int)(cache_ptr->LRU_list_size));
203     HDfprintf(stdout, "index_size = %d, max_cache_size = %d, delta = %d\n\n", (int)(cache_ptr->index_size),
204               (int)(cache_ptr->max_cache_size),
205               (int)(cache_ptr->max_cache_size) - (int)(cache_ptr->index_size));
206 
207     /* Print header */
208     HDfprintf(stdout, "Entry ");
209     HDfprintf(stdout, "|       Address      ");
210     HDfprintf(stdout, "|         Tag        ");
211     HDfprintf(stdout, "|  Size ");
212     HDfprintf(stdout, "| Ring ");
213     HDfprintf(stdout, "|              Type              ");
214     HDfprintf(stdout, "| Dirty");
215     HDfprintf(stdout, "\n");
216 
217     HDfprintf(stdout, "--------------------------------------------------------------------------------------"
218                       "--------------------------\n");
219 
220     entry_ptr = cache_ptr->LRU_head_ptr;
221     while (entry_ptr != NULL) {
222         HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
223 
224         /* Print entry */
225         HDfprintf(stdout, "%s%5d ", cache_ptr->prefix, i);
226         HDfprintf(stdout, "  0x%16llx ", (long long)(entry_ptr->addr));
227 
228         if (NULL == entry_ptr->tag_info)
229             HDfprintf(stdout, "    %16s ", "N/A");
230         else
231             HDfprintf(stdout, "  0x%16llx ", (long long)(entry_ptr->tag_info->tag));
232 
233         HDfprintf(stdout, "  %5lld ", (long long)(entry_ptr->size));
234         HDfprintf(stdout, "    %d  ", (int)(entry_ptr->ring));
235         HDfprintf(stdout, "  %2d %-32s ", (int)(entry_ptr->type->id), (entry_ptr->type->name));
236         HDfprintf(stdout, " %d", (int)(entry_ptr->is_dirty));
237         HDfprintf(stdout, "\n");
238 
239         i++;
240         entry_ptr = entry_ptr->next;
241     } /* end while */
242 
243     HDfprintf(stdout, "--------------------------------------------------------------------------------------"
244                       "--------------------------\n");
245 
246     FUNC_LEAVE_NOAPI(SUCCEED)
247 } /* H5C_dump_cache_LRU() */
248 #endif /* NDEBUG */
249 
250 /*-------------------------------------------------------------------------
251  *
252  * Function:    H5C_dump_cache_skip_list
253  *
254  * Purpose:     Debugging routine that prints a summary of the contents of
255  *              the skip list used by the metadata cache metadata cache to
256  *              maintain an address sorted list of dirty entries.
257  *
258  * Return:      Non-negative on success/Negative on failure
259  *
260  * Programmer:  John Mainzer
261  *              11/15/14
262  *
263  * Changes:     Updated function for the slist_enabled field in H5C_t.
264  *              Recall that to minimize slist overhead, the slist is
265  *              empty and not maintained if cache_ptr->slist_enabled is
266  *              false.
267  *                                             JRM -- 5/6/20
268  *
269  *-------------------------------------------------------------------------
270  */
271 #ifndef NDEBUG
272 herr_t
H5C_dump_cache_skip_list(H5C_t * cache_ptr,char * calling_fcn)273 H5C_dump_cache_skip_list(H5C_t *cache_ptr, char *calling_fcn)
274 {
275     herr_t             ret_value = SUCCEED; /* Return value */
276     int                i;
277     H5C_cache_entry_t *entry_ptr = NULL;
278     H5SL_node_t *      node_ptr  = NULL;
279 
280     FUNC_ENTER_NOAPI_NOERR
281 
282     HDassert(cache_ptr != NULL);
283     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
284     HDassert(calling_fcn != NULL);
285 
286     HDfprintf(stdout, "\n\nDumping metadata cache skip list from %s.\n", calling_fcn);
287     HDfprintf(stdout, " slist %s.\n", cache_ptr->slist_enabled ? "enabled" : "disabled");
288     HDfprintf(stdout, "	slist len = %" PRIu32 ".\n", cache_ptr->slist_len);
289     HDfprintf(stdout, "	slist size = %zu.\n", cache_ptr->slist_size);
290 
291     if (cache_ptr->slist_len > 0) {
292 
293         /* If we get this far, all entries in the cache are listed in the
294          * skip list -- scan the skip list generating the desired output.
295          */
296         HDfprintf(stdout, "Num:    Addr:               Len: Prot/Pind: Dirty: Type:\n");
297 
298         i = 0;
299 
300         node_ptr = H5SL_first(cache_ptr->slist_ptr);
301 
302         if (node_ptr != NULL) {
303 
304             entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
305         }
306         else {
307 
308             entry_ptr = NULL;
309         }
310 
311         while (entry_ptr != NULL) {
312 
313             HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
314 
315             HDfprintf(stdout, "%s%d       0x%016llx  %4lld    %d/%d       %d    %s\n", cache_ptr->prefix, i,
316                       (long long)(entry_ptr->addr), (long long)(entry_ptr->size),
317                       (int)(entry_ptr->is_protected), (int)(entry_ptr->is_pinned), (int)(entry_ptr->is_dirty),
318                       entry_ptr->type->name);
319 
320             HDfprintf(stdout, "		node_ptr = %p, item = %p\n", (void *)node_ptr, H5SL_item(node_ptr));
321 
322             /* increment node_ptr before we delete its target */
323 
324             node_ptr = H5SL_next(node_ptr);
325 
326             if (node_ptr != NULL) {
327 
328                 entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
329             }
330             else {
331 
332                 entry_ptr = NULL;
333             }
334 
335             i++;
336 
337         } /* end while */
338     }     /* end if */
339 
340     HDfprintf(stdout, "\n\n");
341 
342     FUNC_LEAVE_NOAPI(ret_value)
343 
344 } /* H5C_dump_cache_skip_list() */
345 #endif /* NDEBUG */
346 
347 /*-------------------------------------------------------------------------
348  * Function:    H5C_set_prefix
349  *
350  * Purpose:     Set the values of the prefix field of H5C_t.  This
351  *		filed is used to label some debugging output.
352  *
353  * Return:      Non-negative on success/Negative on failure
354  *
355  * Programmer:  John Mainzer
356  *              1/20/06
357  *
358  *-------------------------------------------------------------------------
359  */
360 herr_t
H5C_set_prefix(H5C_t * cache_ptr,char * prefix)361 H5C_set_prefix(H5C_t *cache_ptr, char *prefix)
362 {
363     herr_t ret_value = SUCCEED; /* Return value */
364 
365     FUNC_ENTER_NOAPI(FAIL)
366 
367     if ((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC) || (prefix == NULL) ||
368         (HDstrlen(prefix) >= H5C__PREFIX_LEN))
369         HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad param(s) on entry")
370 
371     HDstrncpy(&(cache_ptr->prefix[0]), prefix, (size_t)(H5C__PREFIX_LEN));
372 
373     cache_ptr->prefix[H5C__PREFIX_LEN - 1] = '\0';
374 
375 done:
376     FUNC_LEAVE_NOAPI(ret_value)
377 } /* H5C_set_prefix() */
378 
379 /*-------------------------------------------------------------------------
380  * Function:    H5C_stats
381  *
382  * Purpose:     Prints statistics about the cache.
383  *
384  * Return:      Non-negative on success/Negative on failure
385  *
386  * Programmer:  John Mainzer
387  *              6/2/04
388  *
389  *-------------------------------------------------------------------------
390  */
391 herr_t
H5C_stats(H5C_t * cache_ptr,const char * cache_name,hbool_t H5_ATTR_UNUSED display_detailed_stats)392 H5C_stats(H5C_t *cache_ptr, const char *cache_name,
393           hbool_t
394 #if !H5C_COLLECT_CACHE_STATS
395               H5_ATTR_UNUSED
396 #endif /* H5C_COLLECT_CACHE_STATS */
397                   display_detailed_stats)
398 {
399 #if H5C_COLLECT_CACHE_STATS
400     int     i;
401     int64_t total_hits                     = 0;
402     int64_t total_misses                   = 0;
403     int64_t total_write_protects           = 0;
404     int64_t total_read_protects            = 0;
405     int64_t max_read_protects              = 0;
406     int64_t total_insertions               = 0;
407     int64_t total_pinned_insertions        = 0;
408     int64_t total_clears                   = 0;
409     int64_t total_flushes                  = 0;
410     int64_t total_evictions                = 0;
411     int64_t total_take_ownerships          = 0;
412     int64_t total_moves                    = 0;
413     int64_t total_entry_flush_moves        = 0;
414     int64_t total_cache_flush_moves        = 0;
415     int64_t total_size_increases           = 0;
416     int64_t total_size_decreases           = 0;
417     int64_t total_entry_flush_size_changes = 0;
418     int64_t total_cache_flush_size_changes = 0;
419     int64_t total_pins                     = 0;
420     int64_t total_unpins                   = 0;
421     int64_t total_dirty_pins               = 0;
422     int64_t total_pinned_flushes           = 0;
423     int64_t total_pinned_clears            = 0;
424     int32_t aggregate_max_accesses         = 0;
425     int32_t aggregate_min_accesses         = 1000000;
426     int32_t aggregate_max_clears           = 0;
427     int32_t aggregate_max_flushes          = 0;
428     size_t  aggregate_max_size             = 0;
429     int32_t aggregate_max_pins             = 0;
430     double  hit_rate;
431     double  prefetch_use_rate;
432     double  average_successful_search_depth                   = 0.0;
433     double  average_failed_search_depth                       = 0.0;
434     double  average_entries_skipped_per_calls_to_msic         = 0.0;
435     double  average_dirty_pf_entries_skipped_per_call_to_msic = 0.0;
436     double  average_entries_scanned_per_calls_to_msic         = 0.0;
437 #endif                          /* H5C_COLLECT_CACHE_STATS */
438     herr_t ret_value = SUCCEED; /* Return value */
439 
440     FUNC_ENTER_NOAPI(FAIL)
441 
442     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
443 
444     /* This would normally be an assert, but we need to use an HGOTO_ERROR
445      * call to shut up the compiler.
446      */
447     if ((NULL == cache_ptr) || (cache_ptr->magic != H5C__H5C_T_MAGIC) || (NULL == cache_name))
448         HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr or cache_name")
449 
450 #if H5C_COLLECT_CACHE_STATS
451     for (i = 0; i <= cache_ptr->max_type_id; i++) {
452         total_hits += cache_ptr->hits[i];
453         total_misses += cache_ptr->misses[i];
454         total_write_protects += cache_ptr->write_protects[i];
455         total_read_protects += cache_ptr->read_protects[i];
456         if (max_read_protects < cache_ptr->max_read_protects[i])
457             max_read_protects = cache_ptr->max_read_protects[i];
458         total_insertions += cache_ptr->insertions[i];
459         total_pinned_insertions += cache_ptr->pinned_insertions[i];
460         total_clears += cache_ptr->clears[i];
461         total_flushes += cache_ptr->flushes[i];
462         total_evictions += cache_ptr->evictions[i];
463         total_take_ownerships += cache_ptr->take_ownerships[i];
464         total_moves += cache_ptr->moves[i];
465         total_entry_flush_moves += cache_ptr->entry_flush_moves[i];
466         total_cache_flush_moves += cache_ptr->cache_flush_moves[i];
467         total_size_increases += cache_ptr->size_increases[i];
468         total_size_decreases += cache_ptr->size_decreases[i];
469         total_entry_flush_size_changes += cache_ptr->entry_flush_size_changes[i];
470         total_cache_flush_size_changes += cache_ptr->cache_flush_size_changes[i];
471         total_pins += cache_ptr->pins[i];
472         total_unpins += cache_ptr->unpins[i];
473         total_dirty_pins += cache_ptr->dirty_pins[i];
474         total_pinned_flushes += cache_ptr->pinned_flushes[i];
475         total_pinned_clears += cache_ptr->pinned_clears[i];
476 #if H5C_COLLECT_CACHE_ENTRY_STATS
477         if (aggregate_max_accesses < cache_ptr->max_accesses[i])
478             aggregate_max_accesses = cache_ptr->max_accesses[i];
479         if (aggregate_min_accesses > aggregate_max_accesses)
480             aggregate_min_accesses = aggregate_max_accesses;
481         if (aggregate_min_accesses > cache_ptr->min_accesses[i])
482             aggregate_min_accesses = cache_ptr->min_accesses[i];
483         if (aggregate_max_clears < cache_ptr->max_clears[i])
484             aggregate_max_clears = cache_ptr->max_clears[i];
485         if (aggregate_max_flushes < cache_ptr->max_flushes[i])
486             aggregate_max_flushes = cache_ptr->max_flushes[i];
487         if (aggregate_max_size < cache_ptr->max_size[i])
488             aggregate_max_size = cache_ptr->max_size[i];
489         if (aggregate_max_pins < cache_ptr->max_pins[i])
490             aggregate_max_pins = cache_ptr->max_pins[i];
491 #endif /* H5C_COLLECT_CACHE_ENTRY_STATS */
492     }  /* end for */
493 
494     if ((total_hits > 0) || (total_misses > 0))
495         hit_rate = 100.0 * ((double)(total_hits)) / ((double)(total_hits + total_misses));
496     else
497         hit_rate = 0.0;
498 
499     if (cache_ptr->successful_ht_searches > 0)
500         average_successful_search_depth = ((double)(cache_ptr->total_successful_ht_search_depth)) /
501                                           ((double)(cache_ptr->successful_ht_searches));
502 
503     if (cache_ptr->failed_ht_searches > 0)
504         average_failed_search_depth =
505             ((double)(cache_ptr->total_failed_ht_search_depth)) / ((double)(cache_ptr->failed_ht_searches));
506 
507     HDfprintf(stdout, "\n%sH5C: cache statistics for %s\n", cache_ptr->prefix, cache_name);
508 
509     HDfprintf(stdout, "\n");
510 
511     HDfprintf(stdout, "%s  hash table insertion / deletions   = %ld / %ld\n", cache_ptr->prefix,
512               (long)(cache_ptr->total_ht_insertions), (long)(cache_ptr->total_ht_deletions));
513 
514     HDfprintf(stdout, "%s  HT successful / failed searches    = %ld / %ld\n", cache_ptr->prefix,
515               (long)(cache_ptr->successful_ht_searches), (long)(cache_ptr->failed_ht_searches));
516 
517     HDfprintf(stdout, "%s  Av. HT suc / failed search depth   = %f / %f\n", cache_ptr->prefix,
518               average_successful_search_depth, average_failed_search_depth);
519 
520     HDfprintf(stdout, "%s  current (max) index size / length  = %ld (%ld) / %lu (%lu)\n", cache_ptr->prefix,
521               (long)(cache_ptr->index_size), (long)(cache_ptr->max_index_size),
522               (unsigned long)(cache_ptr->index_len), (unsigned long)(cache_ptr->max_index_len));
523 
524     HDfprintf(stdout, "%s  current (max) clean/dirty idx size = %ld (%ld) / %ld (%ld)\n", cache_ptr->prefix,
525               (long)(cache_ptr->clean_index_size), (long)(cache_ptr->max_clean_index_size),
526               (long)(cache_ptr->dirty_index_size), (long)(cache_ptr->max_dirty_index_size));
527 
528     HDfprintf(stdout, "%s  current (max) slist size / length  = %ld (%ld) / %lu (%lu)\n", cache_ptr->prefix,
529               (long)(cache_ptr->slist_size), (long)(cache_ptr->max_slist_size),
530               (unsigned long)(cache_ptr->slist_len), (unsigned long)(cache_ptr->max_slist_len));
531 
532     HDfprintf(stdout, "%s  current (max) PL size / length     = %ld (%ld) / %lu (%lu)\n", cache_ptr->prefix,
533               (long)(cache_ptr->pl_size), (long)(cache_ptr->max_pl_size), (unsigned long)(cache_ptr->pl_len),
534               (unsigned long)(cache_ptr->max_pl_len));
535 
536     HDfprintf(stdout, "%s  current (max) PEL size / length    = %ld (%ld) / %lu (%lu)\n", cache_ptr->prefix,
537               (long)(cache_ptr->pel_size), (long)(cache_ptr->max_pel_size),
538               (unsigned long)(cache_ptr->pel_len), (unsigned long)(cache_ptr->max_pel_len));
539 
540     HDfprintf(stdout, "%s  current LRU list size / length     = %ld / %lu\n", cache_ptr->prefix,
541               (long)(cache_ptr->LRU_list_size), (unsigned long)(cache_ptr->LRU_list_len));
542 
543 #if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
544     HDfprintf(stdout, "%s  current clean LRU size / length    = %ld / %lu\n", cache_ptr->prefix,
545               (long)(cache_ptr->cLRU_list_size), (unsigned long)(cache_ptr->cLRU_list_len));
546 
547     HDfprintf(stdout, "%s  current dirty LRU size / length    = %ld / %lu\n", cache_ptr->prefix,
548               (long)(cache_ptr->dLRU_list_size), (unsigned long)(cache_ptr->dLRU_list_len));
549 #endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
550 
551     HDfprintf(stdout, "%s  Total hits / misses / hit_rate     = %ld / %ld / %f\n", cache_ptr->prefix,
552               (long)total_hits, (long)total_misses, hit_rate);
553 
554     HDfprintf(stdout, "%s  Total write / read (max) protects  = %ld / %ld (%ld)\n", cache_ptr->prefix,
555               (long)total_write_protects, (long)total_read_protects, (long)max_read_protects);
556 
557     HDfprintf(stdout, "%s  Total clears / flushes             = %ld / %ld\n", cache_ptr->prefix,
558               (long)total_clears, (long)total_flushes);
559 
560     HDfprintf(stdout, "%s  Total evictions / take ownerships  = %ld / %ld\n", cache_ptr->prefix,
561               (long)total_evictions, (long)total_take_ownerships);
562 
563     HDfprintf(stdout, "%s  Total insertions(pinned) / moves   = %ld(%ld) / %ld\n", cache_ptr->prefix,
564               (long)total_insertions, (long)total_pinned_insertions, (long)total_moves);
565 
566     HDfprintf(stdout, "%s  Total entry / cache flush moves    = %ld / %ld\n", cache_ptr->prefix,
567               (long)total_entry_flush_moves, (long)total_cache_flush_moves);
568 
569     HDfprintf(stdout, "%s  Total entry size incrs / decrs     = %ld / %ld\n", cache_ptr->prefix,
570               (long)total_size_increases, (long)total_size_decreases);
571 
572     HDfprintf(stdout, "%s  Ttl entry/cache flush size changes = %ld / %ld\n", cache_ptr->prefix,
573               (long)total_entry_flush_size_changes, (long)total_cache_flush_size_changes);
574 
575     HDfprintf(stdout, "%s  Total entry pins (dirty) / unpins  = %ld (%ld) / %ld\n", cache_ptr->prefix,
576               (long)total_pins, (long)total_dirty_pins, (long)total_unpins);
577 
578     HDfprintf(stdout, "%s  Total pinned flushes / clears      = %ld / %ld\n", cache_ptr->prefix,
579               (long)total_pinned_flushes, (long)total_pinned_clears);
580 
581     HDfprintf(stdout, "%s  MSIC: (make space in cache) calls  = %lld\n", cache_ptr->prefix,
582               (long long)(cache_ptr->calls_to_msic));
583 
584     if (cache_ptr->calls_to_msic > 0)
585         average_entries_skipped_per_calls_to_msic =
586             (((double)(cache_ptr->total_entries_skipped_in_msic)) / ((double)(cache_ptr->calls_to_msic)));
587 
588     HDfprintf(stdout, "%s  MSIC: Average/max entries skipped  = %lf / %ld\n", cache_ptr->prefix,
589               (double)average_entries_skipped_per_calls_to_msic,
590               (long)(cache_ptr->max_entries_skipped_in_msic));
591 
592     if (cache_ptr->calls_to_msic > 0)
593         average_dirty_pf_entries_skipped_per_call_to_msic =
594             (((double)(cache_ptr->total_dirty_pf_entries_skipped_in_msic)) /
595              ((double)(cache_ptr->calls_to_msic)));
596 
597     HDfprintf(stdout, "%s  MSIC: Average/max dirty pf entries skipped  = %lf / %ld\n", cache_ptr->prefix,
598               average_dirty_pf_entries_skipped_per_call_to_msic,
599               (long)(cache_ptr->max_dirty_pf_entries_skipped_in_msic));
600 
601     if (cache_ptr->calls_to_msic > 0)
602         average_entries_scanned_per_calls_to_msic =
603             (((double)(cache_ptr->total_entries_scanned_in_msic)) / ((double)(cache_ptr->calls_to_msic)));
604 
605     HDfprintf(stdout, "%s  MSIC: Average/max entries scanned  = %lf / %ld\n", cache_ptr->prefix,
606               (double)average_entries_scanned_per_calls_to_msic,
607               (long)(cache_ptr->max_entries_scanned_in_msic));
608 
609     HDfprintf(stdout, "%s  MSIC: Scanned to make space(evict) = %lld\n", cache_ptr->prefix,
610               (long long)(cache_ptr->entries_scanned_to_make_space));
611 
612     HDfprintf(
613         stdout, "%s  MSIC: Scanned to satisfy min_clean = %lld\n", cache_ptr->prefix,
614         (long long)(cache_ptr->total_entries_scanned_in_msic - cache_ptr->entries_scanned_to_make_space));
615 
616     HDfprintf(stdout, "%s  slist/LRU/index scan restarts   = %lld / %lld / %lld.\n", cache_ptr->prefix,
617               (long long)(cache_ptr->slist_scan_restarts), (long long)(cache_ptr->LRU_scan_restarts),
618               (long long)(cache_ptr->index_scan_restarts));
619 
620     HDfprintf(stdout, "%s  cache image creations/reads/loads/size = %d / %d /%d / %" PRIuHSIZE "\n",
621               cache_ptr->prefix, cache_ptr->images_created, cache_ptr->images_read, cache_ptr->images_loaded,
622               cache_ptr->last_image_size);
623 
624     HDfprintf(stdout, "%s  prefetches / dirty prefetches      = %lld / %lld\n", cache_ptr->prefix,
625               (long long)(cache_ptr->prefetches), (long long)(cache_ptr->dirty_prefetches));
626 
627     HDfprintf(stdout, "%s  prefetch hits/flushes/evictions    = %lld / %lld / %lld\n", cache_ptr->prefix,
628               (long long)(cache_ptr->prefetch_hits),
629               (long long)(cache_ptr->flushes[H5AC_PREFETCHED_ENTRY_ID]),
630               (long long)(cache_ptr->evictions[H5AC_PREFETCHED_ENTRY_ID]));
631 
632     if (cache_ptr->prefetches > 0)
633         prefetch_use_rate = 100.0 * ((double)(cache_ptr->prefetch_hits)) / ((double)(cache_ptr->prefetches));
634     else
635         prefetch_use_rate = 0.0;
636 
637     HDfprintf(stdout, "%s  prefetched entry use rate          = %lf\n", cache_ptr->prefix, prefetch_use_rate);
638 
639 #if H5C_COLLECT_CACHE_ENTRY_STATS
640 
641     HDfprintf(stdout, "%s  aggregate max / min accesses       = %d / %d\n", cache_ptr->prefix,
642               (int)aggregate_max_accesses, (int)aggregate_min_accesses);
643 
644     HDfprintf(stdout, "%s  aggregate max_clears / max_flushes = %d / %d\n", cache_ptr->prefix,
645               (int)aggregate_max_clears, (int)aggregate_max_flushes);
646 
647     HDfprintf(stdout, "%s  aggregate max_size / max_pins      = %d / %d\n", cache_ptr->prefix,
648               (int)aggregate_max_size, (int)aggregate_max_pins);
649 
650 #endif /* H5C_COLLECT_CACHE_ENTRY_STATS */
651 
652     if (display_detailed_stats) {
653         for (i = 0; i <= cache_ptr->max_type_id; i++) {
654             HDfprintf(stdout, "\n");
655 
656             HDfprintf(stdout, "%s  Stats on %s:\n", cache_ptr->prefix,
657                       ((cache_ptr->class_table_ptr))[i]->name);
658 
659             if ((cache_ptr->hits[i] > 0) || (cache_ptr->misses[i] > 0))
660                 hit_rate = 100.0 * ((double)(cache_ptr->hits[i])) /
661                            ((double)(cache_ptr->hits[i] + cache_ptr->misses[i]));
662             else
663                 hit_rate = 0.0;
664 
665             HDfprintf(stdout, "%s    hits / misses / hit_rate       = %ld / %ld / %f\n", cache_ptr->prefix,
666                       (long)(cache_ptr->hits[i]), (long)(cache_ptr->misses[i]), hit_rate);
667 
668             HDfprintf(stdout, "%s    write / read (max) protects    = %ld / %ld (%d)\n", cache_ptr->prefix,
669                       (long)(cache_ptr->write_protects[i]), (long)(cache_ptr->read_protects[i]),
670                       (int)(cache_ptr->max_read_protects[i]));
671 
672             HDfprintf(stdout, "%s    clears / flushes               = %ld / %ld\n", cache_ptr->prefix,
673                       (long)(cache_ptr->clears[i]), (long)(cache_ptr->flushes[i]));
674 
675             HDfprintf(stdout, "%s    evictions / take ownerships    = %ld / %ld\n", cache_ptr->prefix,
676                       (long)(cache_ptr->evictions[i]), (long)(cache_ptr->take_ownerships[i]));
677 
678             HDfprintf(stdout, "%s    insertions(pinned) / moves     = %ld(%ld) / %ld\n", cache_ptr->prefix,
679                       (long)(cache_ptr->insertions[i]), (long)(cache_ptr->pinned_insertions[i]),
680                       (long)(cache_ptr->moves[i]));
681 
682             HDfprintf(stdout, "%s    entry / cache flush moves      = %ld / %ld\n", cache_ptr->prefix,
683                       (long)(cache_ptr->entry_flush_moves[i]), (long)(cache_ptr->cache_flush_moves[i]));
684 
685             HDfprintf(stdout, "%s    size increases / decreases     = %ld / %ld\n", cache_ptr->prefix,
686                       (long)(cache_ptr->size_increases[i]), (long)(cache_ptr->size_decreases[i]));
687 
688             HDfprintf(stdout, "%s    entry/cache flush size changes = %ld / %ld\n", cache_ptr->prefix,
689                       (long)(cache_ptr->entry_flush_size_changes[i]),
690                       (long)(cache_ptr->cache_flush_size_changes[i]));
691 
692             HDfprintf(stdout, "%s    entry pins / unpins            = %ld / %ld\n", cache_ptr->prefix,
693                       (long)(cache_ptr->pins[i]), (long)(cache_ptr->unpins[i]));
694 
695             HDfprintf(stdout, "%s    entry dirty pins/pin'd flushes = %ld / %ld\n", cache_ptr->prefix,
696                       (long)(cache_ptr->dirty_pins[i]), (long)(cache_ptr->pinned_flushes[i]));
697 
698 #if H5C_COLLECT_CACHE_ENTRY_STATS
699 
700             HDfprintf(stdout, "%s    entry max / min accesses       = %d / %d\n", cache_ptr->prefix,
701                       cache_ptr->max_accesses[i], cache_ptr->min_accesses[i]);
702 
703             HDfprintf(stdout, "%s    entry max_clears / max_flushes = %d / %d\n", cache_ptr->prefix,
704                       cache_ptr->max_clears[i], cache_ptr->max_flushes[i]);
705 
706             HDfprintf(stdout, "%s    entry max_size / max_pins      = %d / %d\n", cache_ptr->prefix,
707                       (int)(cache_ptr->max_size[i]), (int)(cache_ptr->max_pins[i]));
708 
709 #endif /* H5C_COLLECT_CACHE_ENTRY_STATS */
710 
711         } /* end for */
712     }     /* end if */
713 
714     HDfprintf(stdout, "\n");
715 
716 #endif /* H5C_COLLECT_CACHE_STATS */
717 
718 done:
719     FUNC_LEAVE_NOAPI(ret_value)
720 } /* H5C_stats() */
721 
722 /*-------------------------------------------------------------------------
723  *
724  * Function:    H5C_stats__reset
725  *
726  * Purpose:     Reset the stats fields to their initial values.
727  *
728  * Return:      void
729  *
730  * Programmer:  John Mainzer, 4/28/04
731  *
732  *-------------------------------------------------------------------------
733  */
734 void
735 #ifndef NDEBUG
H5C_stats__reset(H5C_t * cache_ptr)736 H5C_stats__reset(H5C_t *cache_ptr)
737 #else /* NDEBUG */
738 #if H5C_COLLECT_CACHE_STATS
739 H5C_stats__reset(H5C_t *cache_ptr)
740 #else  /* H5C_COLLECT_CACHE_STATS */
741 H5C_stats__reset(H5C_t H5_ATTR_UNUSED *cache_ptr)
742 #endif /* H5C_COLLECT_CACHE_STATS */
743 #endif /* NDEBUG */
744 {
745 #if H5C_COLLECT_CACHE_STATS
746     int i;
747 #endif /* H5C_COLLECT_CACHE_STATS */
748 
749     HDassert(cache_ptr);
750     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
751 
752 #if H5C_COLLECT_CACHE_STATS
753     for (i = 0; i <= cache_ptr->max_type_id; i++) {
754         cache_ptr->hits[i]                     = 0;
755         cache_ptr->misses[i]                   = 0;
756         cache_ptr->write_protects[i]           = 0;
757         cache_ptr->read_protects[i]            = 0;
758         cache_ptr->max_read_protects[i]        = 0;
759         cache_ptr->insertions[i]               = 0;
760         cache_ptr->pinned_insertions[i]        = 0;
761         cache_ptr->clears[i]                   = 0;
762         cache_ptr->flushes[i]                  = 0;
763         cache_ptr->evictions[i]                = 0;
764         cache_ptr->take_ownerships[i]          = 0;
765         cache_ptr->moves[i]                    = 0;
766         cache_ptr->entry_flush_moves[i]        = 0;
767         cache_ptr->cache_flush_moves[i]        = 0;
768         cache_ptr->pins[i]                     = 0;
769         cache_ptr->unpins[i]                   = 0;
770         cache_ptr->dirty_pins[i]               = 0;
771         cache_ptr->pinned_flushes[i]           = 0;
772         cache_ptr->pinned_clears[i]            = 0;
773         cache_ptr->size_increases[i]           = 0;
774         cache_ptr->size_decreases[i]           = 0;
775         cache_ptr->entry_flush_size_changes[i] = 0;
776         cache_ptr->cache_flush_size_changes[i] = 0;
777     } /* end for */
778 
779     cache_ptr->total_ht_insertions              = 0;
780     cache_ptr->total_ht_deletions               = 0;
781     cache_ptr->successful_ht_searches           = 0;
782     cache_ptr->total_successful_ht_search_depth = 0;
783     cache_ptr->failed_ht_searches               = 0;
784     cache_ptr->total_failed_ht_search_depth     = 0;
785 
786     cache_ptr->max_index_len        = 0;
787     cache_ptr->max_index_size       = (size_t)0;
788     cache_ptr->max_clean_index_size = (size_t)0;
789     cache_ptr->max_dirty_index_size = (size_t)0;
790 
791     cache_ptr->max_slist_len  = 0;
792     cache_ptr->max_slist_size = (size_t)0;
793 
794     cache_ptr->max_pl_len  = 0;
795     cache_ptr->max_pl_size = (size_t)0;
796 
797     cache_ptr->max_pel_len  = 0;
798     cache_ptr->max_pel_size = (size_t)0;
799 
800     cache_ptr->calls_to_msic                          = 0;
801     cache_ptr->total_entries_skipped_in_msic          = 0;
802     cache_ptr->total_dirty_pf_entries_skipped_in_msic = 0;
803     cache_ptr->total_entries_scanned_in_msic          = 0;
804     cache_ptr->max_entries_skipped_in_msic            = 0;
805     cache_ptr->max_dirty_pf_entries_skipped_in_msic   = 0;
806     cache_ptr->max_entries_scanned_in_msic            = 0;
807     cache_ptr->entries_scanned_to_make_space          = 0;
808 
809     cache_ptr->slist_scan_restarts = 0;
810     cache_ptr->LRU_scan_restarts   = 0;
811     cache_ptr->index_scan_restarts = 0;
812 
813     cache_ptr->images_created  = 0;
814     cache_ptr->images_read     = 0;
815     cache_ptr->images_loaded   = 0;
816     cache_ptr->last_image_size = (hsize_t)0;
817 
818     cache_ptr->prefetches       = 0;
819     cache_ptr->dirty_prefetches = 0;
820     cache_ptr->prefetch_hits    = 0;
821 
822 #if H5C_COLLECT_CACHE_ENTRY_STATS
823     for (i = 0; i <= cache_ptr->max_type_id; i++) {
824         cache_ptr->max_accesses[i] = 0;
825         cache_ptr->min_accesses[i] = 1000000;
826         cache_ptr->max_clears[i]   = 0;
827         cache_ptr->max_flushes[i]  = 0;
828         cache_ptr->max_size[i]     = (size_t)0;
829         cache_ptr->max_pins[i]     = 0;
830     } /* end for */
831 
832 #endif /* H5C_COLLECT_CACHE_ENTRY_STATS */
833 #endif /* H5C_COLLECT_CACHE_STATS */
834 } /* H5C_stats__reset() */
835 
836 /*-------------------------------------------------------------------------
837  * Function:    H5C_flush_dependency_exists()
838  *
839  * Purpose:	Test to see if a flush dependency relationship exists
840  *          between the supplied parent and child.  Both parties
841  *          are indicated by addresses so as to avoid the necessity
842  *          of protect / unprotect calls prior to this call.
843  *
844  *          If either the parent or the child is not in the metadata
845  *          cache, the function sets *fd_exists_ptr to FALSE.
846  *
847  *          If both are in the cache, the childs list of parents is
848  *          searched for the proposed parent.  If the proposed parent
849  *          is found in the childs parent list, the function sets
850  *          *fd_exists_ptr to TRUE.  In all other non-error cases,
851  *          the function sets *fd_exists_ptr FALSE.
852  *
853  * Return:      SUCCEED on success/FAIL on failure.  Note that
854  *              *fd_exists_ptr is undefined on failure.
855  *
856  * Programmer:  John Mainzer
857  *              9/28/16
858  *
859  *-------------------------------------------------------------------------
860  */
861 #ifndef NDEBUG
862 herr_t
H5C_flush_dependency_exists(H5C_t * cache_ptr,haddr_t parent_addr,haddr_t child_addr,hbool_t * fd_exists_ptr)863 H5C_flush_dependency_exists(H5C_t *cache_ptr, haddr_t parent_addr, haddr_t child_addr, hbool_t *fd_exists_ptr)
864 {
865     hbool_t            fd_exists = FALSE; /* whether flush dependency exists */
866     H5C_cache_entry_t *parent_ptr;        /* Ptr to parent entry */
867     H5C_cache_entry_t *child_ptr;         /* Ptr to child entry */
868     hbool_t            ret_value = FALSE; /* Return value */
869 
870     FUNC_ENTER_NOAPI(NULL)
871 
872     /* Sanity checks */
873     HDassert(cache_ptr);
874     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
875     HDassert(H5F_addr_defined(parent_addr));
876     HDassert(H5F_addr_defined(child_addr));
877     HDassert(fd_exists_ptr);
878 
879     H5C__SEARCH_INDEX(cache_ptr, parent_addr, parent_ptr, FAIL)
880     H5C__SEARCH_INDEX(cache_ptr, child_addr, child_ptr, FAIL)
881 
882     if (parent_ptr && child_ptr) {
883         HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
884         HDassert(child_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
885 
886         if (child_ptr->flush_dep_nparents > 0) {
887             unsigned u; /* Local index variable */
888 
889             HDassert(child_ptr->flush_dep_parent);
890             HDassert(child_ptr->flush_dep_parent_nalloc >= child_ptr->flush_dep_nparents);
891 
892             for (u = 0; u < child_ptr->flush_dep_nparents; u++) {
893                 if (child_ptr->flush_dep_parent[u] == parent_ptr) {
894                     fd_exists = TRUE;
895                     HDassert(parent_ptr->flush_dep_nchildren > 0);
896                     break;
897                 } /* end if */
898             }     /* end for */
899         }         /* end if */
900     }             /* end if */
901 
902     *fd_exists_ptr = fd_exists;
903 
904 done:
905     FUNC_LEAVE_NOAPI(ret_value)
906 } /* H5C_flush_dependency_exists() */
907 #endif /* NDEBUG */
908 
909 /*-------------------------------------------------------------------------
910  *
911  * Function:    H5C_validate_index_list
912  *
913  * Purpose:     Debugging function that scans the index list for errors.
914  *
915  *		If an error is detected, the function generates a
916  *		diagnostic and returns FAIL.  If no error is detected,
917  *		the function returns SUCCEED.
918  *
919  * Return:      FAIL if error is detected, SUCCEED otherwise.
920  *
921  * Programmer:  John Mainzer, 9/16/16
922  *
923  *-------------------------------------------------------------------------
924  */
925 #ifndef NDEBUG
926 herr_t
H5C_validate_index_list(H5C_t * cache_ptr)927 H5C_validate_index_list(H5C_t *cache_ptr)
928 {
929     H5C_cache_entry_t *entry_ptr = NULL;
930     uint32_t           len       = 0;
931     int32_t            index_ring_len[H5C_RING_NTYPES];
932     size_t             size       = 0;
933     size_t             clean_size = 0;
934     size_t             dirty_size = 0;
935     size_t             index_ring_size[H5C_RING_NTYPES];
936     size_t             clean_index_ring_size[H5C_RING_NTYPES];
937     size_t             dirty_index_ring_size[H5C_RING_NTYPES];
938     int                i;
939     herr_t             ret_value = SUCCEED; /* Return value */
940 
941     FUNC_ENTER_NOAPI_NOINIT
942 
943     /* Sanity checks */
944     HDassert(cache_ptr);
945     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
946 
947     for (i = 0; i < H5C_RING_NTYPES; i++) {
948         index_ring_len[i]        = 0;
949         index_ring_size[i]       = 0;
950         clean_index_ring_size[i] = 0;
951         dirty_index_ring_size[i] = 0;
952     } /* end if */
953 
954     if (((cache_ptr->il_head == NULL) || (cache_ptr->il_tail == NULL)) &&
955         (cache_ptr->il_head != cache_ptr->il_tail))
956         HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointer validation failed")
957 
958     if ((cache_ptr->index_len == 1) &&
959         ((cache_ptr->il_head != cache_ptr->il_tail) || (cache_ptr->il_head == NULL) ||
960          (cache_ptr->il_head->size != cache_ptr->index_size)))
961         HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointer sanity checks failed")
962 
963     if ((cache_ptr->index_len >= 1) &&
964         ((cache_ptr->il_head == NULL) || (cache_ptr->il_head->il_prev != NULL) ||
965          (cache_ptr->il_tail == NULL) || (cache_ptr->il_tail->il_next != NULL)))
966         HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list length sanity checks failed")
967 
968     entry_ptr = cache_ptr->il_head;
969     while (entry_ptr != NULL) {
970         if ((entry_ptr != cache_ptr->il_head) &&
971             ((entry_ptr->il_prev == NULL) || (entry_ptr->il_prev->il_next != entry_ptr)))
972             HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointers for entry are invalid")
973 
974         if ((entry_ptr != cache_ptr->il_tail) &&
975             ((entry_ptr->il_next == NULL) || (entry_ptr->il_next->il_prev != entry_ptr)))
976             HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointers for entry are invalid")
977 
978         HDassert(entry_ptr->ring > 0);
979         HDassert(entry_ptr->ring < H5C_RING_NTYPES);
980 
981         len++;
982         index_ring_len[entry_ptr->ring] += 1;
983 
984         size += entry_ptr->size;
985         index_ring_size[entry_ptr->ring] += entry_ptr->size;
986 
987         if (entry_ptr->is_dirty) {
988             dirty_size += entry_ptr->size;
989             dirty_index_ring_size[entry_ptr->ring] += entry_ptr->size;
990         } /* end if */
991         else {
992             clean_size += entry_ptr->size;
993             clean_index_ring_size[entry_ptr->ring] += entry_ptr->size;
994         } /* end else */
995 
996         entry_ptr = entry_ptr->il_next;
997     } /* end while */
998 
999     if ((cache_ptr->index_len != len) || (cache_ptr->il_len != len) || (cache_ptr->index_size != size) ||
1000         (cache_ptr->il_size != size) || (cache_ptr->clean_index_size != clean_size) ||
1001         (cache_ptr->dirty_index_size != dirty_size) || (clean_size + dirty_size != size))
1002         HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index, clean and dirty sizes for cache are invalid")
1003 
1004     size       = 0;
1005     clean_size = 0;
1006     dirty_size = 0;
1007     for (i = 0; i < H5C_RING_NTYPES; i++) {
1008         size += clean_index_ring_size[i] + dirty_index_ring_size[i];
1009         clean_size += clean_index_ring_size[i];
1010         dirty_size += dirty_index_ring_size[i];
1011     } /* end for */
1012 
1013     if ((cache_ptr->index_size != size) || (cache_ptr->clean_index_size != clean_size) ||
1014         (cache_ptr->dirty_index_size != dirty_size))
1015         HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index, clean and dirty sizes for cache are invalid")
1016 
1017 done:
1018     if (ret_value != SUCCEED)
1019         HDassert(0);
1020 
1021     FUNC_LEAVE_NOAPI(ret_value)
1022 } /* H5C_validate_index_list() */
1023 #endif /* NDEBUG */
1024 
1025 /*-------------------------------------------------------------------------
1026  *
1027  * Function:    H5C_get_entry_ptr_from_addr()
1028  *
1029  * Purpose:     Debugging function that attempts to look up an entry in the
1030  *              cache by its file address, and if found, returns a pointer
1031  *              to the entry in *entry_ptr_ptr.  If the entry is not in the
1032  *              cache, *entry_ptr_ptr is set to NULL.
1033  *
1034  *              WARNING: This call should be used only in debugging
1035  *                       routines, and it should be avoided when
1036  *                       possible.
1037  *
1038  *                       Further, if we ever multi-thread the cache,
1039  *                       this routine will have to be either discarded
1040  *                       or heavily re-worked.
1041  *
1042  *                       Finally, keep in mind that the entry whose
1043  *                       pointer is obtained in this fashion may not
1044  *                       be in a stable state.
1045  *
1046  *              Note that this function is only defined if NDEBUG
1047  *              is not defined.
1048  *
1049  *              As heavy use of this function is almost certainly a
1050  *              bad idea, the metadata cache tracks the number of
1051  *              successful calls to this function, and (if
1052  *              H5C_DO_SANITY_CHECKS is defined) displays any
1053  *              non-zero count on cache shutdown.
1054  *
1055  * Return:      FAIL if error is detected, SUCCEED otherwise.
1056  *
1057  * Programmer:  John Mainzer, 5/30/14
1058  *
1059  *-------------------------------------------------------------------------
1060  */
1061 #ifndef NDEBUG
1062 herr_t
H5C_get_entry_ptr_from_addr(H5C_t * cache_ptr,haddr_t addr,void ** entry_ptr_ptr)1063 H5C_get_entry_ptr_from_addr(H5C_t *cache_ptr, haddr_t addr, void **entry_ptr_ptr)
1064 {
1065     H5C_cache_entry_t *entry_ptr = NULL;
1066     herr_t             ret_value = SUCCEED; /* Return value */
1067 
1068     FUNC_ENTER_NOAPI(FAIL)
1069 
1070     /* Sanity checks */
1071     HDassert(cache_ptr);
1072     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
1073     HDassert(H5F_addr_defined(addr));
1074     HDassert(entry_ptr_ptr);
1075 
1076     H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
1077 
1078     if (entry_ptr == NULL)
1079         /* the entry doesn't exist in the cache -- report this
1080          * and quit.
1081          */
1082         *entry_ptr_ptr = NULL;
1083     else {
1084         *entry_ptr_ptr = entry_ptr;
1085 
1086         /* increment call counter */
1087         (cache_ptr->get_entry_ptr_from_addr_counter)++;
1088     } /* end else */
1089 
1090 done:
1091     FUNC_LEAVE_NOAPI(ret_value)
1092 } /* H5C_get_entry_ptr_from_addr() */
1093 #endif /* NDEBUG */
1094 
1095 /*-------------------------------------------------------------------------
1096  * Function:    H5C_get_serialization_in_progress
1097  *
1098  * Purpose:     Return the current value of
1099  *              cache_ptr->serialization_in_progress.
1100  *
1101  * Return:      Current value of cache_ptr->serialization_in_progress.
1102  *
1103  * Programmer:  John Mainzer
1104  *		8/24/15
1105  *
1106  *-------------------------------------------------------------------------
1107  */
1108 #ifndef NDEBUG
1109 hbool_t
H5C_get_serialization_in_progress(const H5C_t * cache_ptr)1110 H5C_get_serialization_in_progress(const H5C_t *cache_ptr)
1111 {
1112     FUNC_ENTER_NOAPI_NOINIT_NOERR
1113 
1114     /* Sanity check */
1115     HDassert(cache_ptr);
1116     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
1117 
1118     FUNC_LEAVE_NOAPI(cache_ptr->serialization_in_progress)
1119 } /* H5C_get_serialization_in_progress() */
1120 #endif /* NDEBUG */
1121 
1122 /*-------------------------------------------------------------------------
1123  *
1124  * Function:    H5C_cache_is_clean()
1125  *
1126  * Purpose:     Debugging function that verifies that all rings in the
1127  *		metadata cache are clean from the outermost ring, inwards
1128  *		to the inner ring specified.
1129  *
1130  *		Returns TRUE if all specified rings are clean, and FALSE
1131  *		if not.  Throws an assertion failure on error.
1132  *
1133  * Return:      TRUE if the indicated ring(s) are clean, and FALSE otherwise.
1134  *
1135  * Programmer:  John Mainzer, 6/18/16
1136  *
1137  *-------------------------------------------------------------------------
1138  */
1139 #ifndef NDEBUG
1140 hbool_t
H5C_cache_is_clean(const H5C_t * cache_ptr,H5C_ring_t inner_ring)1141 H5C_cache_is_clean(const H5C_t *cache_ptr, H5C_ring_t inner_ring)
1142 {
1143     H5C_ring_t ring      = H5C_RING_USER;
1144     hbool_t    ret_value = TRUE; /* Return value */
1145 
1146     FUNC_ENTER_NOAPI_NOINIT_NOERR
1147 
1148     /* Sanity checks */
1149     HDassert(cache_ptr);
1150     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
1151     HDassert(inner_ring >= H5C_RING_USER);
1152     HDassert(inner_ring <= H5C_RING_SB);
1153 
1154     while (ring <= inner_ring) {
1155         if (cache_ptr->dirty_index_ring_size[ring] > 0)
1156             HGOTO_DONE(FALSE)
1157 
1158         ring++;
1159     } /* end while */
1160 
1161 done:
1162     FUNC_LEAVE_NOAPI(ret_value)
1163 } /* H5C_cache_is_clean() */
1164 #endif /* NDEBUG */
1165 
1166 /*-------------------------------------------------------------------------
1167  *
1168  * Function:    H5C_verify_entry_type()
1169  *
1170  * Purpose:     Debugging function that attempts to look up an entry in the
1171  *		cache by its file address, and if found, test to see if its
1172  *		type field contains the expted value.
1173  *
1174  *		If the specified entry is in cache, *in_cache_ptr is set
1175  *		to TRUE, and *type_ok_ptr is set to TRUE or FALSE depending
1176  *		on whether the entries type field matches the expected_type
1177  *		parameter.
1178  *
1179  *		If the target entry is not in cache, *in_cache_ptr is
1180  *		set to FALSE, and *type_ok_ptr is undefined.
1181  *
1182  *		Note that this function is only defined if NDEBUG
1183  *		is not defined.
1184  *
1185  * Return:      FAIL if error is detected, SUCCEED otherwise.
1186  *
1187  * Programmer:  John Mainzer, 5/30/14
1188  *
1189  *-------------------------------------------------------------------------
1190  */
1191 #ifndef NDEBUG
1192 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)1193 H5C_verify_entry_type(H5C_t *cache_ptr, haddr_t addr, const H5C_class_t *expected_type, hbool_t *in_cache_ptr,
1194                       hbool_t *type_ok_ptr)
1195 {
1196     H5C_cache_entry_t *entry_ptr = NULL;
1197     herr_t             ret_value = SUCCEED; /* Return value */
1198 
1199     FUNC_ENTER_NOAPI(FAIL)
1200 
1201     /* Sanity checks */
1202     HDassert(cache_ptr);
1203     HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
1204     HDassert(H5F_addr_defined(addr));
1205     HDassert(expected_type);
1206     HDassert(in_cache_ptr);
1207     HDassert(type_ok_ptr);
1208 
1209     H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
1210 
1211     if (entry_ptr == NULL)
1212         /* the entry doesn't exist in the cache -- report this
1213          * and quit.
1214          */
1215         *in_cache_ptr = FALSE;
1216     else {
1217         *in_cache_ptr = TRUE;
1218 
1219         if (entry_ptr->prefetched)
1220             *type_ok_ptr = (expected_type->id == entry_ptr->prefetch_type_id);
1221         else
1222             *type_ok_ptr = (expected_type == entry_ptr->type);
1223     } /* end else */
1224 
1225 done:
1226     FUNC_LEAVE_NOAPI(ret_value)
1227 } /* H5C_verify_entry_type() */
1228 #endif /* NDEBUG */
1229