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