Coverage Report

Created: 2024-06-18 06:29

/src/hdf5/src/H5Cdbg.c
Line
Count
Source (jump to first uncovered line)
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the COPYING file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/*-------------------------------------------------------------------------
14
 *
15
 * Created:     H5Cdbg.c
16
 *
17
 * Purpose:     Debugging Routines for the generic cache structure or entries.
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5Cmodule.h" /* This source code file is part of the H5C module */
27
28
/***********/
29
/* Headers */
30
/***********/
31
#include "H5private.h"   /* Generic Functions            */
32
#include "H5ACprivate.h" /* Metadata Cache               */
33
#include "H5Cpkg.h"      /* Cache                        */
34
#include "H5Eprivate.h"  /* Error Handling               */
35
#include "H5SLprivate.h" /* Skip Lists                               */
36
37
/****************/
38
/* Local Macros */
39
/****************/
40
41
/******************/
42
/* Local Typedefs */
43
/******************/
44
45
/********************/
46
/* Local Prototypes */
47
/********************/
48
49
/*********************/
50
/* Package Variables */
51
/*********************/
52
53
/*****************************/
54
/* Library Private Variables */
55
/*****************************/
56
57
/*******************/
58
/* Local Variables */
59
/*******************/
60
61
#ifndef NDEBUG
62
63
/*-------------------------------------------------------------------------
64
 * Function:    H5C_dump_cache
65
 *
66
 * Purpose:     Print a summary of the contents of the metadata cache for
67
 *              debugging purposes.
68
 *
69
 * Return:      Non-negative on success/Negative on failure
70
 *
71
 *-------------------------------------------------------------------------
72
 */
73
herr_t
74
H5C_dump_cache(H5C_t *cache_ptr, const char *cache_name)
75
{
76
    H5C_cache_entry_t *entry_ptr;
77
    H5SL_t            *slist_ptr = NULL;
78
    int                i;                   /* Local index variable */
79
    herr_t             ret_value = SUCCEED; /* Return value */
80
81
    FUNC_ENTER_NOAPI(FAIL)
82
83
    /* Sanity check */
84
    assert(cache_ptr != NULL);
85
    assert(cache_name != NULL);
86
87
    /* First, create a skip list */
88
    if (NULL == (slist_ptr = H5SL_create(H5SL_TYPE_HADDR, NULL)))
89
        HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "can't create skip list");
90
91
    /* Next, scan the index, and insert all entries in the skip list.
92
     * Do this, as we want to display cache entries in increasing address
93
     * order.
94
     */
95
    for (i = 0; i < H5C__HASH_TABLE_LEN; i++) {
96
        entry_ptr = cache_ptr->index[i];
97
98
        while (entry_ptr != NULL) {
99
            if (H5SL_insert(slist_ptr, entry_ptr, &(entry_ptr->addr)) < 0)
100
                HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "can't insert entry in skip list");
101
102
            entry_ptr = entry_ptr->ht_next;
103
        } /* end while */
104
    }     /* end for */
105
106
    /* If we get this far, all entries in the cache are listed in the
107
     * skip list -- scan the skip list generating the desired output.
108
     */
109
110
    fprintf(stdout, "\n\nDump of metadata cache \"%s\"\n", cache_name);
111
112
    /* Print header */
113
    fprintf(stdout, "Entry ");
114
    fprintf(stdout, "|       Address      ");
115
    fprintf(stdout, "|         Tag        ");
116
    fprintf(stdout, "|  Size ");
117
    fprintf(stdout, "| Ring ");
118
    fprintf(stdout, "|              Type              ");
119
    fprintf(stdout, "| Prot/Pin/Dirty");
120
    fprintf(stdout, "\n");
121
122
    fprintf(stdout, "--------------------------------------------------------------------------------------"
123
                    "--------------------------\n");
124
125
    i         = 0;
126
    entry_ptr = (H5C_cache_entry_t *)H5SL_remove_first(slist_ptr);
127
    while (entry_ptr != NULL) {
128
        /* Print entry */
129
        fprintf(stdout, "%s%5d ", cache_ptr->prefix, i);
130
        fprintf(stdout, "  0x%16llx ", (long long)(entry_ptr->addr));
131
        if (NULL == entry_ptr->tag_info)
132
            fprintf(stdout, "    %16s ", "N/A");
133
        else
134
            fprintf(stdout, "  0x%16llx ", (long long)(entry_ptr->tag_info->tag));
135
        fprintf(stdout, "  %5lld ", (long long)(entry_ptr->size));
136
        fprintf(stdout, "    %d  ", (int)(entry_ptr->ring));
137
        fprintf(stdout, "  %2d %-32s ", (int)(entry_ptr->type->id), (entry_ptr->type->name));
138
        fprintf(stdout, " %d", (int)(entry_ptr->is_protected));
139
        fprintf(stdout, " %d", (int)(entry_ptr->is_pinned));
140
        fprintf(stdout, " %d", (int)(entry_ptr->is_dirty));
141
        fprintf(stdout, "\n");
142
143
        /* remove the next (first) item in the skip list */
144
        entry_ptr = (H5C_cache_entry_t *)H5SL_remove_first(slist_ptr);
145
146
        i++;
147
    } /* end while */
148
149
    fprintf(stdout, "\n\n");
150
151
    /* Verify that all the entries were removed from the skip list */
152
    assert(H5SL_count(slist_ptr) == 0);
153
154
done:
155
    /* Discard the skip list */
156
    if (slist_ptr)
157
        H5SL_close(slist_ptr);
158
159
    FUNC_LEAVE_NOAPI(ret_value)
160
} /* H5C_dump_cache() */
161
#endif /* NDEBUG */
162
163
#ifndef NDEBUG
164
165
/*-------------------------------------------------------------------------
166
 * Function:    H5C_dump_cache_LRU
167
 *
168
 * Purpose:     Print a summary of the contents of the metadata cache
169
 *              LRU for debugging purposes.
170
 *
171
 * Return:      Non-negative on success/Negative on failure
172
 *
173
 *-------------------------------------------------------------------------
174
 */
175
herr_t
176
H5C_dump_cache_LRU(H5C_t *cache_ptr, const char *cache_name)
177
{
178
    H5C_cache_entry_t *entry_ptr;
179
    int                i = 0;
180
181
    FUNC_ENTER_NOAPI_NOERR
182
183
    /* Sanity check */
184
    assert(cache_ptr != NULL);
185
    assert(cache_name != NULL);
186
187
    fprintf(stdout, "\n\nDump of metadata cache LRU \"%s\"\n", cache_name);
188
    fprintf(stdout, "LRU len = %d, LRU size = %d\n", cache_ptr->LRU_list_len,
189
            (int)(cache_ptr->LRU_list_size));
190
    fprintf(stdout, "index_size = %d, max_cache_size = %d, delta = %d\n\n", (int)(cache_ptr->index_size),
191
            (int)(cache_ptr->max_cache_size),
192
            (int)(cache_ptr->max_cache_size) - (int)(cache_ptr->index_size));
193
194
    /* Print header */
195
    fprintf(stdout, "Entry ");
196
    fprintf(stdout, "|       Address      ");
197
    fprintf(stdout, "|         Tag        ");
198
    fprintf(stdout, "|  Size ");
199
    fprintf(stdout, "| Ring ");
200
    fprintf(stdout, "|              Type              ");
201
    fprintf(stdout, "| Dirty");
202
    fprintf(stdout, "\n");
203
204
    fprintf(stdout, "--------------------------------------------------------------------------------------"
205
                    "--------------------------\n");
206
207
    entry_ptr = cache_ptr->LRU_head_ptr;
208
    while (entry_ptr != NULL) {
209
        /* Print entry */
210
        fprintf(stdout, "%s%5d ", cache_ptr->prefix, i);
211
        fprintf(stdout, "  0x%16llx ", (long long)(entry_ptr->addr));
212
213
        if (NULL == entry_ptr->tag_info)
214
            fprintf(stdout, "    %16s ", "N/A");
215
        else
216
            fprintf(stdout, "  0x%16llx ", (long long)(entry_ptr->tag_info->tag));
217
218
        fprintf(stdout, "  %5lld ", (long long)(entry_ptr->size));
219
        fprintf(stdout, "    %d  ", (int)(entry_ptr->ring));
220
        fprintf(stdout, "  %2d %-32s ", (int)(entry_ptr->type->id), (entry_ptr->type->name));
221
        fprintf(stdout, " %d", (int)(entry_ptr->is_dirty));
222
        fprintf(stdout, "\n");
223
224
        i++;
225
        entry_ptr = entry_ptr->next;
226
    } /* end while */
227
228
    fprintf(stdout, "--------------------------------------------------------------------------------------"
229
                    "--------------------------\n");
230
231
    FUNC_LEAVE_NOAPI(SUCCEED)
232
} /* H5C_dump_cache_LRU() */
233
#endif /* NDEBUG */
234
235
/*-------------------------------------------------------------------------
236
 * Function:    H5C_dump_cache_skip_list
237
 *
238
 * Purpose:     Debugging routine that prints a summary of the contents of
239
 *              the skip list used by the metadata cache metadata cache to
240
 *              maintain an address sorted list of dirty entries.
241
 *
242
 * Return:      Non-negative on success/Negative on failure
243
 *
244
 *-------------------------------------------------------------------------
245
 */
246
#ifndef NDEBUG
247
herr_t
248
H5C_dump_cache_skip_list(H5C_t *cache_ptr, char *calling_fcn)
249
{
250
    herr_t             ret_value = SUCCEED; /* Return value */
251
    int                i;
252
    H5C_cache_entry_t *entry_ptr = NULL;
253
    H5SL_node_t       *node_ptr  = NULL;
254
255
    FUNC_ENTER_NOAPI_NOERR
256
257
    assert(cache_ptr != NULL);
258
    assert(calling_fcn != NULL);
259
260
    fprintf(stdout, "\n\nDumping metadata cache skip list from %s.\n", calling_fcn);
261
    fprintf(stdout, " slist %s.\n", cache_ptr->slist_enabled ? "enabled" : "disabled");
262
    fprintf(stdout, " slist len = %" PRIu32 ".\n", cache_ptr->slist_len);
263
    fprintf(stdout, " slist size = %zu.\n", cache_ptr->slist_size);
264
265
    if (cache_ptr->slist_len > 0) {
266
267
        /* If we get this far, all entries in the cache are listed in the
268
         * skip list -- scan the skip list generating the desired output.
269
         */
270
        fprintf(stdout, "Num:    Addr:               Len: Prot/Pind: Dirty: Type:\n");
271
272
        i = 0;
273
274
        node_ptr = H5SL_first(cache_ptr->slist_ptr);
275
        if (node_ptr != NULL)
276
            entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
277
        else
278
            entry_ptr = NULL;
279
280
        while (entry_ptr != NULL) {
281
            fprintf(stdout, "%s%d       0x%016llx  %4lld    %d/%d       %d    %s\n", cache_ptr->prefix, i,
282
                    (long long)(entry_ptr->addr), (long long)(entry_ptr->size),
283
                    (int)(entry_ptr->is_protected), (int)(entry_ptr->is_pinned), (int)(entry_ptr->is_dirty),
284
                    entry_ptr->type->name);
285
            fprintf(stdout, "   node_ptr = %p, item = %p\n", (void *)node_ptr, H5SL_item(node_ptr));
286
287
            /* increment node_ptr before we delete its target */
288
            node_ptr = H5SL_next(node_ptr);
289
            if (node_ptr != NULL)
290
                entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
291
            else
292
                entry_ptr = NULL;
293
294
            i++;
295
        } /* end while */
296
    }     /* end if */
297
298
    fprintf(stdout, "\n\n");
299
300
    FUNC_LEAVE_NOAPI(ret_value)
301
} /* H5C_dump_cache_skip_list() */
302
#endif /* NDEBUG */
303
304
/*-------------------------------------------------------------------------
305
 * Function:    H5C_set_prefix
306
 *
307
 * Purpose:     Set the values of the prefix field of H5C_t.  This
308
 *    filed is used to label some debugging output.
309
 *
310
 * Return:      Non-negative on success/Negative on failure
311
 *
312
 *-------------------------------------------------------------------------
313
 */
314
herr_t
315
H5C_set_prefix(H5C_t *cache_ptr, char *prefix)
316
0
{
317
0
    herr_t ret_value = SUCCEED; /* Return value */
318
319
0
    FUNC_ENTER_NOAPI(FAIL)
320
321
0
    if (cache_ptr == NULL || prefix == NULL || strlen(prefix) >= H5C__PREFIX_LEN)
322
0
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad param(s) on entry");
323
324
0
    strncpy(&(cache_ptr->prefix[0]), prefix, (size_t)(H5C__PREFIX_LEN));
325
326
0
    cache_ptr->prefix[H5C__PREFIX_LEN - 1] = '\0';
327
328
0
done:
329
0
    FUNC_LEAVE_NOAPI(ret_value)
330
0
} /* H5C_set_prefix() */
331
332
/*-------------------------------------------------------------------------
333
 * Function:    H5C_stats
334
 *
335
 * Purpose:     Prints statistics about the cache.
336
 *
337
 * Return:      Non-negative on success/Negative on failure
338
 *
339
 *-------------------------------------------------------------------------
340
 */
341
herr_t
342
H5C_stats(H5C_t *cache_ptr, const char *cache_name,
343
          bool
344
#if !H5C_COLLECT_CACHE_STATS
345
              H5_ATTR_UNUSED
346
#endif /* H5C_COLLECT_CACHE_STATS */
347
                  display_detailed_stats)
348
0
{
349
#if H5C_COLLECT_CACHE_STATS
350
    int     i;
351
    int64_t total_hits                     = 0;
352
    int64_t total_misses                   = 0;
353
    int64_t total_write_protects           = 0;
354
    int64_t total_read_protects            = 0;
355
    int64_t max_read_protects              = 0;
356
    int64_t total_insertions               = 0;
357
    int64_t total_pinned_insertions        = 0;
358
    int64_t total_clears                   = 0;
359
    int64_t total_flushes                  = 0;
360
    int64_t total_evictions                = 0;
361
    int64_t total_take_ownerships          = 0;
362
    int64_t total_moves                    = 0;
363
    int64_t total_entry_flush_moves        = 0;
364
    int64_t total_cache_flush_moves        = 0;
365
    int64_t total_size_increases           = 0;
366
    int64_t total_size_decreases           = 0;
367
    int64_t total_entry_flush_size_changes = 0;
368
    int64_t total_cache_flush_size_changes = 0;
369
    int64_t total_pins                     = 0;
370
    int64_t total_unpins                   = 0;
371
    int64_t total_dirty_pins               = 0;
372
    int64_t total_pinned_flushes           = 0;
373
    int64_t total_pinned_clears            = 0;
374
    int32_t aggregate_max_accesses         = 0;
375
    int32_t aggregate_min_accesses         = 1000000;
376
    int32_t aggregate_max_clears           = 0;
377
    int32_t aggregate_max_flushes          = 0;
378
    size_t  aggregate_max_size             = 0;
379
    int32_t aggregate_max_pins             = 0;
380
    double  hit_rate;
381
    double  prefetch_use_rate;
382
    double  average_successful_search_depth                   = 0.0;
383
    double  average_failed_search_depth                       = 0.0;
384
    double  average_entries_skipped_per_calls_to_msic         = 0.0;
385
    double  average_dirty_pf_entries_skipped_per_call_to_msic = 0.0;
386
    double  average_entries_scanned_per_calls_to_msic         = 0.0;
387
#endif                          /* H5C_COLLECT_CACHE_STATS */
388
0
    herr_t ret_value = SUCCEED; /* Return value */
389
390
0
    FUNC_ENTER_NOAPI(FAIL)
391
392
0
    if (NULL == cache_ptr || NULL == cache_name)
393
0
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr or cache_name");
394
395
#if H5C_COLLECT_CACHE_STATS
396
    for (i = 0; i <= cache_ptr->max_type_id; i++) {
397
        total_hits += cache_ptr->hits[i];
398
        total_misses += cache_ptr->misses[i];
399
        total_write_protects += cache_ptr->write_protects[i];
400
        total_read_protects += cache_ptr->read_protects[i];
401
        if (max_read_protects < cache_ptr->max_read_protects[i])
402
            max_read_protects = cache_ptr->max_read_protects[i];
403
        total_insertions += cache_ptr->insertions[i];
404
        total_pinned_insertions += cache_ptr->pinned_insertions[i];
405
        total_clears += cache_ptr->clears[i];
406
        total_flushes += cache_ptr->flushes[i];
407
        total_evictions += cache_ptr->evictions[i];
408
        total_take_ownerships += cache_ptr->take_ownerships[i];
409
        total_moves += cache_ptr->moves[i];
410
        total_entry_flush_moves += cache_ptr->entry_flush_moves[i];
411
        total_cache_flush_moves += cache_ptr->cache_flush_moves[i];
412
        total_size_increases += cache_ptr->size_increases[i];
413
        total_size_decreases += cache_ptr->size_decreases[i];
414
        total_entry_flush_size_changes += cache_ptr->entry_flush_size_changes[i];
415
        total_cache_flush_size_changes += cache_ptr->cache_flush_size_changes[i];
416
        total_pins += cache_ptr->pins[i];
417
        total_unpins += cache_ptr->unpins[i];
418
        total_dirty_pins += cache_ptr->dirty_pins[i];
419
        total_pinned_flushes += cache_ptr->pinned_flushes[i];
420
        total_pinned_clears += cache_ptr->pinned_clears[i];
421
#if H5C_COLLECT_CACHE_ENTRY_STATS
422
        if (aggregate_max_accesses < cache_ptr->max_accesses[i])
423
            aggregate_max_accesses = cache_ptr->max_accesses[i];
424
        if (aggregate_min_accesses > aggregate_max_accesses)
425
            aggregate_min_accesses = aggregate_max_accesses;
426
        if (aggregate_min_accesses > cache_ptr->min_accesses[i])
427
            aggregate_min_accesses = cache_ptr->min_accesses[i];
428
        if (aggregate_max_clears < cache_ptr->max_clears[i])
429
            aggregate_max_clears = cache_ptr->max_clears[i];
430
        if (aggregate_max_flushes < cache_ptr->max_flushes[i])
431
            aggregate_max_flushes = cache_ptr->max_flushes[i];
432
        if (aggregate_max_size < cache_ptr->max_size[i])
433
            aggregate_max_size = cache_ptr->max_size[i];
434
        if (aggregate_max_pins < cache_ptr->max_pins[i])
435
            aggregate_max_pins = cache_ptr->max_pins[i];
436
#endif /* H5C_COLLECT_CACHE_ENTRY_STATS */
437
    }  /* end for */
438
439
    if ((total_hits > 0) || (total_misses > 0))
440
        hit_rate = 100.0 * ((double)(total_hits)) / ((double)(total_hits + total_misses));
441
    else
442
        hit_rate = 0.0;
443
444
    if (cache_ptr->successful_ht_searches > 0)
445
        average_successful_search_depth = ((double)(cache_ptr->total_successful_ht_search_depth)) /
446
                                          ((double)(cache_ptr->successful_ht_searches));
447
448
    if (cache_ptr->failed_ht_searches > 0)
449
        average_failed_search_depth =
450
            ((double)(cache_ptr->total_failed_ht_search_depth)) / ((double)(cache_ptr->failed_ht_searches));
451
452
    fprintf(stdout, "\n%sH5C: cache statistics for %s\n", cache_ptr->prefix, cache_name);
453
454
    fprintf(stdout, "\n");
455
456
    fprintf(stdout, "%s  hash table insertion / deletions   = %ld / %ld\n", cache_ptr->prefix,
457
            (long)(cache_ptr->total_ht_insertions), (long)(cache_ptr->total_ht_deletions));
458
459
    fprintf(stdout, "%s  HT successful / failed searches    = %ld / %ld\n", cache_ptr->prefix,
460
            (long)(cache_ptr->successful_ht_searches), (long)(cache_ptr->failed_ht_searches));
461
462
    fprintf(stdout, "%s  Av. HT suc / failed search depth   = %f / %f\n", cache_ptr->prefix,
463
            average_successful_search_depth, average_failed_search_depth);
464
465
    fprintf(stdout, "%s  current (max) index size / length  = %ld (%ld) / %lu (%lu)\n", cache_ptr->prefix,
466
            (long)(cache_ptr->index_size), (long)(cache_ptr->max_index_size),
467
            (unsigned long)(cache_ptr->index_len), (unsigned long)(cache_ptr->max_index_len));
468
469
    fprintf(stdout, "%s  current (max) clean/dirty idx size = %ld (%ld) / %ld (%ld)\n", cache_ptr->prefix,
470
            (long)(cache_ptr->clean_index_size), (long)(cache_ptr->max_clean_index_size),
471
            (long)(cache_ptr->dirty_index_size), (long)(cache_ptr->max_dirty_index_size));
472
473
    fprintf(stdout, "%s  current (max) slist size / length  = %ld (%ld) / %lu (%lu)\n", cache_ptr->prefix,
474
            (long)(cache_ptr->slist_size), (long)(cache_ptr->max_slist_size),
475
            (unsigned long)(cache_ptr->slist_len), (unsigned long)(cache_ptr->max_slist_len));
476
477
    fprintf(stdout, "%s  current (max) PL size / length     = %ld (%ld) / %lu (%lu)\n", cache_ptr->prefix,
478
            (long)(cache_ptr->pl_size), (long)(cache_ptr->max_pl_size), (unsigned long)(cache_ptr->pl_len),
479
            (unsigned long)(cache_ptr->max_pl_len));
480
481
    fprintf(stdout, "%s  current (max) PEL size / length    = %ld (%ld) / %lu (%lu)\n", cache_ptr->prefix,
482
            (long)(cache_ptr->pel_size), (long)(cache_ptr->max_pel_size), (unsigned long)(cache_ptr->pel_len),
483
            (unsigned long)(cache_ptr->max_pel_len));
484
485
    fprintf(stdout, "%s  current LRU list size / length     = %ld / %lu\n", cache_ptr->prefix,
486
            (long)(cache_ptr->LRU_list_size), (unsigned long)(cache_ptr->LRU_list_len));
487
488
#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
489
    fprintf(stdout, "%s  current clean LRU size / length    = %ld / %lu\n", cache_ptr->prefix,
490
            (long)(cache_ptr->cLRU_list_size), (unsigned long)(cache_ptr->cLRU_list_len));
491
492
    fprintf(stdout, "%s  current dirty LRU size / length    = %ld / %lu\n", cache_ptr->prefix,
493
            (long)(cache_ptr->dLRU_list_size), (unsigned long)(cache_ptr->dLRU_list_len));
494
#endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
495
496
    fprintf(stdout, "%s  Total hits / misses / hit_rate     = %ld / %ld / %f\n", cache_ptr->prefix,
497
            (long)total_hits, (long)total_misses, hit_rate);
498
499
    fprintf(stdout, "%s  Total write / read (max) protects  = %ld / %ld (%ld)\n", cache_ptr->prefix,
500
            (long)total_write_protects, (long)total_read_protects, (long)max_read_protects);
501
502
    fprintf(stdout, "%s  Total clears / flushes             = %ld / %ld\n", cache_ptr->prefix,
503
            (long)total_clears, (long)total_flushes);
504
505
    fprintf(stdout, "%s  Total evictions / take ownerships  = %ld / %ld\n", cache_ptr->prefix,
506
            (long)total_evictions, (long)total_take_ownerships);
507
508
    fprintf(stdout, "%s  Total insertions(pinned) / moves   = %ld(%ld) / %ld\n", cache_ptr->prefix,
509
            (long)total_insertions, (long)total_pinned_insertions, (long)total_moves);
510
511
    fprintf(stdout, "%s  Total entry / cache flush moves    = %ld / %ld\n", cache_ptr->prefix,
512
            (long)total_entry_flush_moves, (long)total_cache_flush_moves);
513
514
    fprintf(stdout, "%s  Total entry size incrs / decrs     = %ld / %ld\n", cache_ptr->prefix,
515
            (long)total_size_increases, (long)total_size_decreases);
516
517
    fprintf(stdout, "%s  Ttl entry/cache flush size changes = %ld / %ld\n", cache_ptr->prefix,
518
            (long)total_entry_flush_size_changes, (long)total_cache_flush_size_changes);
519
520
    fprintf(stdout, "%s  Total entry pins (dirty) / unpins  = %ld (%ld) / %ld\n", cache_ptr->prefix,
521
            (long)total_pins, (long)total_dirty_pins, (long)total_unpins);
522
523
    fprintf(stdout, "%s  Total pinned flushes / clears      = %ld / %ld\n", cache_ptr->prefix,
524
            (long)total_pinned_flushes, (long)total_pinned_clears);
525
526
    fprintf(stdout, "%s  MSIC: (make space in cache) calls  = %lld\n", cache_ptr->prefix,
527
            (long long)(cache_ptr->calls_to_msic));
528
529
    if (cache_ptr->calls_to_msic > 0)
530
        average_entries_skipped_per_calls_to_msic =
531
            (((double)(cache_ptr->total_entries_skipped_in_msic)) / ((double)(cache_ptr->calls_to_msic)));
532
533
    fprintf(stdout, "%s  MSIC: Average/max entries skipped  = %lf / %ld\n", cache_ptr->prefix,
534
            (double)average_entries_skipped_per_calls_to_msic,
535
            (long)(cache_ptr->max_entries_skipped_in_msic));
536
537
    if (cache_ptr->calls_to_msic > 0)
538
        average_dirty_pf_entries_skipped_per_call_to_msic =
539
            (((double)(cache_ptr->total_dirty_pf_entries_skipped_in_msic)) /
540
             ((double)(cache_ptr->calls_to_msic)));
541
542
    fprintf(stdout, "%s  MSIC: Average/max dirty pf entries skipped  = %lf / %ld\n", cache_ptr->prefix,
543
            average_dirty_pf_entries_skipped_per_call_to_msic,
544
            (long)(cache_ptr->max_dirty_pf_entries_skipped_in_msic));
545
546
    if (cache_ptr->calls_to_msic > 0)
547
        average_entries_scanned_per_calls_to_msic =
548
            (((double)(cache_ptr->total_entries_scanned_in_msic)) / ((double)(cache_ptr->calls_to_msic)));
549
550
    fprintf(stdout, "%s  MSIC: Average/max entries scanned  = %lf / %ld\n", cache_ptr->prefix,
551
            (double)average_entries_scanned_per_calls_to_msic,
552
            (long)(cache_ptr->max_entries_scanned_in_msic));
553
554
    fprintf(stdout, "%s  MSIC: Scanned to make space(evict) = %lld\n", cache_ptr->prefix,
555
            (long long)(cache_ptr->entries_scanned_to_make_space));
556
557
    fprintf(stdout, "%s  MSIC: Scanned to satisfy min_clean = %lld\n", cache_ptr->prefix,
558
            (long long)(cache_ptr->total_entries_scanned_in_msic - cache_ptr->entries_scanned_to_make_space));
559
560
    fprintf(stdout, "%s  slist/LRU/index scan restarts   = %lld / %lld / %lld.\n", cache_ptr->prefix,
561
            (long long)(cache_ptr->slist_scan_restarts), (long long)(cache_ptr->LRU_scan_restarts),
562
            (long long)(cache_ptr->index_scan_restarts));
563
564
    fprintf(stdout, "%s  cache image creations/reads/loads/size = %d / %d /%d / %" PRIuHSIZE "\n",
565
            cache_ptr->prefix, cache_ptr->images_created, cache_ptr->images_read, cache_ptr->images_loaded,
566
            cache_ptr->last_image_size);
567
568
    fprintf(stdout, "%s  prefetches / dirty prefetches      = %lld / %lld\n", cache_ptr->prefix,
569
            (long long)(cache_ptr->prefetches), (long long)(cache_ptr->dirty_prefetches));
570
571
    fprintf(stdout, "%s  prefetch hits/flushes/evictions    = %lld / %lld / %lld\n", cache_ptr->prefix,
572
            (long long)(cache_ptr->prefetch_hits), (long long)(cache_ptr->flushes[H5AC_PREFETCHED_ENTRY_ID]),
573
            (long long)(cache_ptr->evictions[H5AC_PREFETCHED_ENTRY_ID]));
574
575
    if (cache_ptr->prefetches > 0)
576
        prefetch_use_rate = 100.0 * ((double)(cache_ptr->prefetch_hits)) / ((double)(cache_ptr->prefetches));
577
    else
578
        prefetch_use_rate = 0.0;
579
580
    fprintf(stdout, "%s  prefetched entry use rate          = %lf\n", cache_ptr->prefix, prefetch_use_rate);
581
582
#if H5C_COLLECT_CACHE_ENTRY_STATS
583
584
    fprintf(stdout, "%s  aggregate max / min accesses       = %d / %d\n", cache_ptr->prefix,
585
            (int)aggregate_max_accesses, (int)aggregate_min_accesses);
586
587
    fprintf(stdout, "%s  aggregate max_clears / max_flushes = %d / %d\n", cache_ptr->prefix,
588
            (int)aggregate_max_clears, (int)aggregate_max_flushes);
589
590
    fprintf(stdout, "%s  aggregate max_size / max_pins      = %d / %d\n", cache_ptr->prefix,
591
            (int)aggregate_max_size, (int)aggregate_max_pins);
592
593
#endif /* H5C_COLLECT_CACHE_ENTRY_STATS */
594
595
    if (display_detailed_stats) {
596
        for (i = 0; i <= cache_ptr->max_type_id; i++) {
597
            fprintf(stdout, "\n");
598
599
            fprintf(stdout, "%s  Stats on %s:\n", cache_ptr->prefix, ((cache_ptr->class_table_ptr))[i]->name);
600
601
            if ((cache_ptr->hits[i] > 0) || (cache_ptr->misses[i] > 0))
602
                hit_rate = 100.0 * ((double)(cache_ptr->hits[i])) /
603
                           ((double)(cache_ptr->hits[i] + cache_ptr->misses[i]));
604
            else
605
                hit_rate = 0.0;
606
607
            fprintf(stdout, "%s    hits / misses / hit_rate       = %ld / %ld / %f\n", cache_ptr->prefix,
608
                    (long)(cache_ptr->hits[i]), (long)(cache_ptr->misses[i]), hit_rate);
609
610
            fprintf(stdout, "%s    write / read (max) protects    = %ld / %ld (%d)\n", cache_ptr->prefix,
611
                    (long)(cache_ptr->write_protects[i]), (long)(cache_ptr->read_protects[i]),
612
                    (int)(cache_ptr->max_read_protects[i]));
613
614
            fprintf(stdout, "%s    clears / flushes               = %ld / %ld\n", cache_ptr->prefix,
615
                    (long)(cache_ptr->clears[i]), (long)(cache_ptr->flushes[i]));
616
617
            fprintf(stdout, "%s    evictions / take ownerships    = %ld / %ld\n", cache_ptr->prefix,
618
                    (long)(cache_ptr->evictions[i]), (long)(cache_ptr->take_ownerships[i]));
619
620
            fprintf(stdout, "%s    insertions(pinned) / moves     = %ld(%ld) / %ld\n", cache_ptr->prefix,
621
                    (long)(cache_ptr->insertions[i]), (long)(cache_ptr->pinned_insertions[i]),
622
                    (long)(cache_ptr->moves[i]));
623
624
            fprintf(stdout, "%s    entry / cache flush moves      = %ld / %ld\n", cache_ptr->prefix,
625
                    (long)(cache_ptr->entry_flush_moves[i]), (long)(cache_ptr->cache_flush_moves[i]));
626
627
            fprintf(stdout, "%s    size increases / decreases     = %ld / %ld\n", cache_ptr->prefix,
628
                    (long)(cache_ptr->size_increases[i]), (long)(cache_ptr->size_decreases[i]));
629
630
            fprintf(stdout, "%s    entry/cache flush size changes = %ld / %ld\n", cache_ptr->prefix,
631
                    (long)(cache_ptr->entry_flush_size_changes[i]),
632
                    (long)(cache_ptr->cache_flush_size_changes[i]));
633
634
            fprintf(stdout, "%s    entry pins / unpins            = %ld / %ld\n", cache_ptr->prefix,
635
                    (long)(cache_ptr->pins[i]), (long)(cache_ptr->unpins[i]));
636
637
            fprintf(stdout, "%s    entry dirty pins/pin'd flushes = %ld / %ld\n", cache_ptr->prefix,
638
                    (long)(cache_ptr->dirty_pins[i]), (long)(cache_ptr->pinned_flushes[i]));
639
640
#if H5C_COLLECT_CACHE_ENTRY_STATS
641
642
            fprintf(stdout, "%s    entry max / min accesses       = %d / %d\n", cache_ptr->prefix,
643
                    cache_ptr->max_accesses[i], cache_ptr->min_accesses[i]);
644
645
            fprintf(stdout, "%s    entry max_clears / max_flushes = %d / %d\n", cache_ptr->prefix,
646
                    cache_ptr->max_clears[i], cache_ptr->max_flushes[i]);
647
648
            fprintf(stdout, "%s    entry max_size / max_pins      = %d / %d\n", cache_ptr->prefix,
649
                    (int)(cache_ptr->max_size[i]), (int)(cache_ptr->max_pins[i]));
650
651
#endif /* H5C_COLLECT_CACHE_ENTRY_STATS */
652
653
        } /* end for */
654
    }     /* end if */
655
656
    fprintf(stdout, "\n");
657
658
#endif /* H5C_COLLECT_CACHE_STATS */
659
660
0
done:
661
0
    FUNC_LEAVE_NOAPI(ret_value)
662
0
} /* H5C_stats() */
663
664
/*-------------------------------------------------------------------------
665
 * Function:    H5C_stats__reset
666
 *
667
 * Purpose:     Reset the stats fields to their initial values.
668
 *
669
 * Return:      void
670
 *
671
 *-------------------------------------------------------------------------
672
 */
673
void
674
#ifndef NDEBUG
675
H5C_stats__reset(H5C_t *cache_ptr)
676
#else /* NDEBUG */
677
#if H5C_COLLECT_CACHE_STATS
678
H5C_stats__reset(H5C_t                            *cache_ptr)
679
#else  /* H5C_COLLECT_CACHE_STATS */
680
H5C_stats__reset(H5C_t H5_ATTR_UNUSED *cache_ptr)
681
#endif /* H5C_COLLECT_CACHE_STATS */
682
#endif /* NDEBUG */
683
10
{
684
#if H5C_COLLECT_CACHE_STATS
685
    int i;
686
#endif /* H5C_COLLECT_CACHE_STATS */
687
688
10
    assert(cache_ptr);
689
690
#if H5C_COLLECT_CACHE_STATS
691
    for (i = 0; i <= cache_ptr->max_type_id; i++) {
692
        cache_ptr->hits[i]                     = 0;
693
        cache_ptr->misses[i]                   = 0;
694
        cache_ptr->write_protects[i]           = 0;
695
        cache_ptr->read_protects[i]            = 0;
696
        cache_ptr->max_read_protects[i]        = 0;
697
        cache_ptr->insertions[i]               = 0;
698
        cache_ptr->pinned_insertions[i]        = 0;
699
        cache_ptr->clears[i]                   = 0;
700
        cache_ptr->flushes[i]                  = 0;
701
        cache_ptr->evictions[i]                = 0;
702
        cache_ptr->take_ownerships[i]          = 0;
703
        cache_ptr->moves[i]                    = 0;
704
        cache_ptr->entry_flush_moves[i]        = 0;
705
        cache_ptr->cache_flush_moves[i]        = 0;
706
        cache_ptr->pins[i]                     = 0;
707
        cache_ptr->unpins[i]                   = 0;
708
        cache_ptr->dirty_pins[i]               = 0;
709
        cache_ptr->pinned_flushes[i]           = 0;
710
        cache_ptr->pinned_clears[i]            = 0;
711
        cache_ptr->size_increases[i]           = 0;
712
        cache_ptr->size_decreases[i]           = 0;
713
        cache_ptr->entry_flush_size_changes[i] = 0;
714
        cache_ptr->cache_flush_size_changes[i] = 0;
715
    } /* end for */
716
717
    cache_ptr->total_ht_insertions              = 0;
718
    cache_ptr->total_ht_deletions               = 0;
719
    cache_ptr->successful_ht_searches           = 0;
720
    cache_ptr->total_successful_ht_search_depth = 0;
721
    cache_ptr->failed_ht_searches               = 0;
722
    cache_ptr->total_failed_ht_search_depth     = 0;
723
724
    cache_ptr->max_index_len        = 0;
725
    cache_ptr->max_index_size       = (size_t)0;
726
    cache_ptr->max_clean_index_size = (size_t)0;
727
    cache_ptr->max_dirty_index_size = (size_t)0;
728
729
    cache_ptr->max_slist_len  = 0;
730
    cache_ptr->max_slist_size = (size_t)0;
731
732
    cache_ptr->max_pl_len  = 0;
733
    cache_ptr->max_pl_size = (size_t)0;
734
735
    cache_ptr->max_pel_len  = 0;
736
    cache_ptr->max_pel_size = (size_t)0;
737
738
    cache_ptr->calls_to_msic                          = 0;
739
    cache_ptr->total_entries_skipped_in_msic          = 0;
740
    cache_ptr->total_dirty_pf_entries_skipped_in_msic = 0;
741
    cache_ptr->total_entries_scanned_in_msic          = 0;
742
    cache_ptr->max_entries_skipped_in_msic            = 0;
743
    cache_ptr->max_dirty_pf_entries_skipped_in_msic   = 0;
744
    cache_ptr->max_entries_scanned_in_msic            = 0;
745
    cache_ptr->entries_scanned_to_make_space          = 0;
746
747
    cache_ptr->slist_scan_restarts = 0;
748
    cache_ptr->LRU_scan_restarts   = 0;
749
    cache_ptr->index_scan_restarts = 0;
750
751
    cache_ptr->images_created  = 0;
752
    cache_ptr->images_read     = 0;
753
    cache_ptr->images_loaded   = 0;
754
    cache_ptr->last_image_size = (hsize_t)0;
755
756
    cache_ptr->prefetches       = 0;
757
    cache_ptr->dirty_prefetches = 0;
758
    cache_ptr->prefetch_hits    = 0;
759
760
#if H5C_COLLECT_CACHE_ENTRY_STATS
761
    for (i = 0; i <= cache_ptr->max_type_id; i++) {
762
        cache_ptr->max_accesses[i] = 0;
763
        cache_ptr->min_accesses[i] = 1000000;
764
        cache_ptr->max_clears[i]   = 0;
765
        cache_ptr->max_flushes[i]  = 0;
766
        cache_ptr->max_size[i]     = (size_t)0;
767
        cache_ptr->max_pins[i]     = 0;
768
    } /* end for */
769
770
#endif /* H5C_COLLECT_CACHE_ENTRY_STATS */
771
#endif /* H5C_COLLECT_CACHE_STATS */
772
10
} /* H5C_stats__reset() */
773
774
/*-------------------------------------------------------------------------
775
 * Function:    H5C_flush_dependency_exists()
776
 *
777
 * Purpose: Test to see if a flush dependency relationship exists
778
 *          between the supplied parent and child.  Both parties
779
 *          are indicated by addresses so as to avoid the necessity
780
 *          of protect / unprotect calls prior to this call.
781
 *
782
 *          If either the parent or the child is not in the metadata
783
 *          cache, the function sets *fd_exists_ptr to false.
784
 *
785
 *          If both are in the cache, the child's list of parents is
786
 *          searched for the proposed parent.  If the proposed parent
787
 *          is found in the child's parent list, the function sets
788
 *          *fd_exists_ptr to true.  In all other non-error cases,
789
 *          the function sets *fd_exists_ptr false.
790
 *
791
 * Return:      SUCCEED on success/FAIL on failure.  Note that
792
 *              *fd_exists_ptr is undefined on failure.
793
 *
794
 *-------------------------------------------------------------------------
795
 */
796
#ifndef NDEBUG
797
herr_t
798
H5C_flush_dependency_exists(H5C_t *cache_ptr, haddr_t parent_addr, haddr_t child_addr, bool *fd_exists_ptr)
799
{
800
    bool               fd_exists = false; /* whether flush dependency exists */
801
    H5C_cache_entry_t *parent_ptr;        /* Ptr to parent entry */
802
    H5C_cache_entry_t *child_ptr;         /* Ptr to child entry */
803
    bool               ret_value = false; /* Return value */
804
805
    FUNC_ENTER_NOAPI(NULL)
806
807
    /* Sanity checks */
808
    assert(cache_ptr);
809
    assert(H5_addr_defined(parent_addr));
810
    assert(H5_addr_defined(child_addr));
811
    assert(fd_exists_ptr);
812
813
    H5C__SEARCH_INDEX(cache_ptr, parent_addr, parent_ptr, FAIL);
814
    H5C__SEARCH_INDEX(cache_ptr, child_addr, child_ptr, FAIL);
815
816
    if (parent_ptr && child_ptr) {
817
        if (child_ptr->flush_dep_nparents > 0) {
818
            unsigned u; /* Local index variable */
819
820
            assert(child_ptr->flush_dep_parent);
821
            assert(child_ptr->flush_dep_parent_nalloc >= child_ptr->flush_dep_nparents);
822
823
            for (u = 0; u < child_ptr->flush_dep_nparents; u++) {
824
                if (child_ptr->flush_dep_parent[u] == parent_ptr) {
825
                    fd_exists = true;
826
                    assert(parent_ptr->flush_dep_nchildren > 0);
827
                    break;
828
                } /* end if */
829
            }     /* end for */
830
        }         /* end if */
831
    }             /* end if */
832
833
    *fd_exists_ptr = fd_exists;
834
835
done:
836
    FUNC_LEAVE_NOAPI(ret_value)
837
} /* H5C_flush_dependency_exists() */
838
#endif /* NDEBUG */
839
840
/*-------------------------------------------------------------------------
841
 * Function:    H5C_validate_index_list
842
 *
843
 * Purpose:     Debugging function that scans the index list for errors.
844
 *
845
 *    If an error is detected, the function generates a
846
 *    diagnostic and returns FAIL.  If no error is detected,
847
 *    the function returns SUCCEED.
848
 *
849
 * Return:      FAIL if error is detected, SUCCEED otherwise.
850
 *
851
 *-------------------------------------------------------------------------
852
 */
853
#ifndef NDEBUG
854
herr_t
855
H5C_validate_index_list(H5C_t *cache_ptr)
856
{
857
    H5C_cache_entry_t *entry_ptr = NULL;
858
    uint32_t           len       = 0;
859
    int32_t            index_ring_len[H5C_RING_NTYPES];
860
    size_t             size       = 0;
861
    size_t             clean_size = 0;
862
    size_t             dirty_size = 0;
863
    size_t             index_ring_size[H5C_RING_NTYPES];
864
    size_t             clean_index_ring_size[H5C_RING_NTYPES];
865
    size_t             dirty_index_ring_size[H5C_RING_NTYPES];
866
    int                i;
867
    herr_t             ret_value = SUCCEED; /* Return value */
868
869
    FUNC_ENTER_NOAPI_NOINIT
870
871
    /* Sanity checks */
872
    assert(cache_ptr);
873
874
    for (i = 0; i < H5C_RING_NTYPES; i++) {
875
        index_ring_len[i]        = 0;
876
        index_ring_size[i]       = 0;
877
        clean_index_ring_size[i] = 0;
878
        dirty_index_ring_size[i] = 0;
879
    } /* end if */
880
881
    if (((cache_ptr->il_head == NULL) || (cache_ptr->il_tail == NULL)) &&
882
        (cache_ptr->il_head != cache_ptr->il_tail))
883
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointer validation failed");
884
885
    if ((cache_ptr->index_len == 1) &&
886
        ((cache_ptr->il_head != cache_ptr->il_tail) || (cache_ptr->il_head == NULL) ||
887
         (cache_ptr->il_head->size != cache_ptr->index_size)))
888
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointer sanity checks failed");
889
890
    if ((cache_ptr->index_len >= 1) &&
891
        ((cache_ptr->il_head == NULL) || (cache_ptr->il_head->il_prev != NULL) ||
892
         (cache_ptr->il_tail == NULL) || (cache_ptr->il_tail->il_next != NULL)))
893
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list length sanity checks failed");
894
895
    entry_ptr = cache_ptr->il_head;
896
    while (entry_ptr != NULL) {
897
        if ((entry_ptr != cache_ptr->il_head) &&
898
            ((entry_ptr->il_prev == NULL) || (entry_ptr->il_prev->il_next != entry_ptr)))
899
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointers for entry are invalid");
900
901
        if ((entry_ptr != cache_ptr->il_tail) &&
902
            ((entry_ptr->il_next == NULL) || (entry_ptr->il_next->il_prev != entry_ptr)))
903
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index list pointers for entry are invalid");
904
905
        assert(entry_ptr->ring > 0);
906
        assert(entry_ptr->ring < H5C_RING_NTYPES);
907
908
        len++;
909
        index_ring_len[entry_ptr->ring] += 1;
910
911
        size += entry_ptr->size;
912
        index_ring_size[entry_ptr->ring] += entry_ptr->size;
913
914
        if (entry_ptr->is_dirty) {
915
            dirty_size += entry_ptr->size;
916
            dirty_index_ring_size[entry_ptr->ring] += entry_ptr->size;
917
        } /* end if */
918
        else {
919
            clean_size += entry_ptr->size;
920
            clean_index_ring_size[entry_ptr->ring] += entry_ptr->size;
921
        } /* end else */
922
923
        entry_ptr = entry_ptr->il_next;
924
    } /* end while */
925
926
    if ((cache_ptr->index_len != len) || (cache_ptr->il_len != len) || (cache_ptr->index_size != size) ||
927
        (cache_ptr->il_size != size) || (cache_ptr->clean_index_size != clean_size) ||
928
        (cache_ptr->dirty_index_size != dirty_size) || (clean_size + dirty_size != size))
929
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index, clean and dirty sizes for cache are invalid");
930
931
    size       = 0;
932
    clean_size = 0;
933
    dirty_size = 0;
934
    for (i = 0; i < H5C_RING_NTYPES; i++) {
935
        size += clean_index_ring_size[i] + dirty_index_ring_size[i];
936
        clean_size += clean_index_ring_size[i];
937
        dirty_size += dirty_index_ring_size[i];
938
    } /* end for */
939
940
    if ((cache_ptr->index_size != size) || (cache_ptr->clean_index_size != clean_size) ||
941
        (cache_ptr->dirty_index_size != dirty_size))
942
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Index, clean and dirty sizes for cache are invalid");
943
944
done:
945
    if (ret_value != SUCCEED)
946
        assert(0);
947
948
    FUNC_LEAVE_NOAPI(ret_value)
949
} /* H5C_validate_index_list() */
950
#endif /* NDEBUG */
951
952
/*-------------------------------------------------------------------------
953
 * Function:    H5C_get_entry_ptr_from_addr()
954
 *
955
 * Purpose:     Debugging function that attempts to look up an entry in the
956
 *              cache by its file address, and if found, returns a pointer
957
 *              to the entry in *entry_ptr_ptr.  If the entry is not in the
958
 *              cache, *entry_ptr_ptr is set to NULL.
959
 *
960
 *              WARNING: This call should be used only in debugging
961
 *                       routines, and it should be avoided when
962
 *                       possible.
963
 *
964
 *                       Further, if we ever multi-thread the cache,
965
 *                       this routine will have to be either discarded
966
 *                       or heavily re-worked.
967
 *
968
 *                       Finally, keep in mind that the entry whose
969
 *                       pointer is obtained in this fashion may not
970
 *                       be in a stable state.
971
 *
972
 *              Note that this function is only defined if NDEBUG
973
 *              is not defined.
974
 *
975
 *              As heavy use of this function is almost certainly a
976
 *              bad idea, the metadata cache tracks the number of
977
 *              successful calls to this function, and (if
978
 *              H5C_DO_SANITY_CHECKS is defined) displays any
979
 *              non-zero count on cache shutdown.
980
 *
981
 * Return:      FAIL if error is detected, SUCCEED otherwise.
982
 *
983
 *-------------------------------------------------------------------------
984
 */
985
#ifndef NDEBUG
986
herr_t
987
H5C_get_entry_ptr_from_addr(H5C_t *cache_ptr, haddr_t addr, void **entry_ptr_ptr)
988
{
989
    H5C_cache_entry_t *entry_ptr = NULL;
990
    herr_t             ret_value = SUCCEED; /* Return value */
991
992
    FUNC_ENTER_NOAPI(FAIL)
993
994
    /* Sanity checks */
995
    assert(cache_ptr);
996
    assert(H5_addr_defined(addr));
997
    assert(entry_ptr_ptr);
998
999
    H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL);
1000
1001
    if (entry_ptr == NULL)
1002
        /* the entry doesn't exist in the cache -- report this
1003
         * and quit.
1004
         */
1005
        *entry_ptr_ptr = NULL;
1006
    else {
1007
        *entry_ptr_ptr = entry_ptr;
1008
1009
        /* increment call counter */
1010
        (cache_ptr->get_entry_ptr_from_addr_counter)++;
1011
    } /* end else */
1012
1013
done:
1014
    FUNC_LEAVE_NOAPI(ret_value)
1015
} /* H5C_get_entry_ptr_from_addr() */
1016
#endif /* NDEBUG */
1017
1018
/*-------------------------------------------------------------------------
1019
 * Function:    H5C_get_serialization_in_progress
1020
 *
1021
 * Purpose:     Return the current value of
1022
 *              cache_ptr->serialization_in_progress.
1023
 *
1024
 * Return:      Current value of cache_ptr->serialization_in_progress.
1025
 *
1026
 *-------------------------------------------------------------------------
1027
 */
1028
#ifndef NDEBUG
1029
bool
1030
H5C_get_serialization_in_progress(const H5C_t *cache_ptr)
1031
{
1032
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1033
1034
    /* Sanity check */
1035
    assert(cache_ptr);
1036
1037
    FUNC_LEAVE_NOAPI(cache_ptr->serialization_in_progress)
1038
} /* H5C_get_serialization_in_progress() */
1039
#endif /* NDEBUG */
1040
1041
/*-------------------------------------------------------------------------
1042
 * Function:    H5C_cache_is_clean()
1043
 *
1044
 * Purpose:     Debugging function that verifies that all rings in the
1045
 *    metadata cache are clean from the outermost ring, inwards
1046
 *    to the inner ring specified.
1047
 *
1048
 *    Returns true if all specified rings are clean, and false
1049
 *    if not.  Throws an assertion failure on error.
1050
 *
1051
 * Return:      true if the indicated ring(s) are clean, and false otherwise.
1052
 *
1053
 *-------------------------------------------------------------------------
1054
 */
1055
#ifndef NDEBUG
1056
bool
1057
H5C_cache_is_clean(const H5C_t *cache_ptr, H5C_ring_t inner_ring)
1058
{
1059
    H5C_ring_t ring      = H5C_RING_USER;
1060
    bool       ret_value = true; /* Return value */
1061
1062
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1063
1064
    /* Sanity checks */
1065
    assert(cache_ptr);
1066
    assert(inner_ring >= H5C_RING_USER);
1067
    assert(inner_ring <= H5C_RING_SB);
1068
1069
    while (ring <= inner_ring) {
1070
        if (cache_ptr->dirty_index_ring_size[ring] > 0)
1071
            HGOTO_DONE(false);
1072
1073
        ring++;
1074
    } /* end while */
1075
1076
done:
1077
    FUNC_LEAVE_NOAPI(ret_value)
1078
} /* H5C_cache_is_clean() */
1079
#endif /* NDEBUG */
1080
1081
/*-------------------------------------------------------------------------
1082
 * Function:    H5C_verify_entry_type()
1083
 *
1084
 * Purpose:     Debugging function that attempts to look up an entry in the
1085
 *    cache by its file address, and if found, test to see if its
1086
 *    type field contains the expted value.
1087
 *
1088
 *    If the specified entry is in cache, *in_cache_ptr is set
1089
 *    to true, and *type_ok_ptr is set to true or false depending
1090
 *    on whether the entries type field matches the expected_type
1091
 *    parameter.
1092
 *
1093
 *    If the target entry is not in cache, *in_cache_ptr is
1094
 *    set to false, and *type_ok_ptr is undefined.
1095
 *
1096
 *    Note that this function is only defined if NDEBUG
1097
 *    is not defined.
1098
 *
1099
 * Return:      FAIL if error is detected, SUCCEED otherwise.
1100
 *
1101
 *-------------------------------------------------------------------------
1102
 */
1103
#ifndef NDEBUG
1104
herr_t
1105
H5C_verify_entry_type(H5C_t *cache_ptr, haddr_t addr, const H5C_class_t *expected_type, bool *in_cache_ptr,
1106
                      bool *type_ok_ptr)
1107
{
1108
    H5C_cache_entry_t *entry_ptr = NULL;
1109
    herr_t             ret_value = SUCCEED; /* Return value */
1110
1111
    FUNC_ENTER_NOAPI(FAIL)
1112
1113
    /* Sanity checks */
1114
    assert(cache_ptr);
1115
    assert(H5_addr_defined(addr));
1116
    assert(expected_type);
1117
    assert(in_cache_ptr);
1118
    assert(type_ok_ptr);
1119
1120
    H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL);
1121
1122
    if (entry_ptr == NULL)
1123
        /* the entry doesn't exist in the cache -- report this
1124
         * and quit.
1125
         */
1126
        *in_cache_ptr = false;
1127
    else {
1128
        *in_cache_ptr = true;
1129
1130
        if (entry_ptr->prefetched)
1131
            *type_ok_ptr = (expected_type->id == entry_ptr->prefetch_type_id);
1132
        else
1133
            *type_ok_ptr = (expected_type == entry_ptr->type);
1134
    } /* end else */
1135
1136
done:
1137
    FUNC_LEAVE_NOAPI(ret_value)
1138
} /* H5C_verify_entry_type() */
1139
#endif /* NDEBUG */
1140
1141
/*-------------------------------------------------------------------------
1142
 * Function:    H5C_def_auto_resize_rpt_fcn
1143
 *
1144
 * Purpose:     Print results of a automatic cache resize.
1145
 *
1146
 *        This function should only be used where printf() behaves
1147
 *        well -- i.e. not on Windows.
1148
 *
1149
 * Return:      void
1150
 *
1151
 *-------------------------------------------------------------------------
1152
 */
1153
void
1154
H5C_def_auto_resize_rpt_fcn(H5C_t *cache_ptr,
1155
#ifndef NDEBUG
1156
                            int32_t version,
1157
#else
1158
                            int32_t H5_ATTR_UNUSED version,
1159
#endif
1160
                            double hit_rate, enum H5C_resize_status status, size_t old_max_cache_size,
1161
                            size_t new_max_cache_size, size_t old_min_clean_size, size_t new_min_clean_size)
1162
0
{
1163
0
    assert(cache_ptr != NULL);
1164
0
    assert(version == H5C__CURR_AUTO_RESIZE_RPT_FCN_VER);
1165
1166
0
    switch (status) {
1167
0
        case in_spec:
1168
0
            fprintf(stdout, "%sAuto cache resize -- no change. (hit rate = %lf)\n", cache_ptr->prefix,
1169
0
                    hit_rate);
1170
0
            break;
1171
1172
0
        case increase:
1173
0
            assert(hit_rate < cache_ptr->resize_ctl.lower_hr_threshold);
1174
0
            assert(old_max_cache_size < new_max_cache_size);
1175
1176
0
            fprintf(stdout, "%sAuto cache resize -- hit rate (%lf) out of bounds low (%6.5lf).\n",
1177
0
                    cache_ptr->prefix, hit_rate, cache_ptr->resize_ctl.lower_hr_threshold);
1178
0
            fprintf(stdout, "%scache size increased from (%zu/%zu) to (%zu/%zu).\n", cache_ptr->prefix,
1179
0
                    old_max_cache_size, old_min_clean_size, new_max_cache_size, new_min_clean_size);
1180
0
            break;
1181
1182
0
        case flash_increase:
1183
0
            assert(old_max_cache_size < new_max_cache_size);
1184
1185
0
            fprintf(stdout, "%sflash cache resize(%d) -- size threshold = %zu.\n", cache_ptr->prefix,
1186
0
                    (int)(cache_ptr->resize_ctl.flash_incr_mode), cache_ptr->flash_size_increase_threshold);
1187
0
            fprintf(stdout, "%s cache size increased from (%zu/%zu) to (%zu/%zu).\n", cache_ptr->prefix,
1188
0
                    old_max_cache_size, old_min_clean_size, new_max_cache_size, new_min_clean_size);
1189
0
            break;
1190
1191
0
        case decrease:
1192
0
            assert(old_max_cache_size > new_max_cache_size);
1193
1194
0
            switch (cache_ptr->resize_ctl.decr_mode) {
1195
0
                case H5C_decr__off:
1196
0
                    fprintf(stdout, "%sAuto cache resize -- decrease off.  HR = %lf\n", cache_ptr->prefix,
1197
0
                            hit_rate);
1198
0
                    break;
1199
1200
0
                case H5C_decr__threshold:
1201
0
                    assert(hit_rate > cache_ptr->resize_ctl.upper_hr_threshold);
1202
1203
0
                    fprintf(stdout, "%sAuto cache resize -- decrease by threshold.  HR = %lf > %6.5lf\n",
1204
0
                            cache_ptr->prefix, hit_rate, cache_ptr->resize_ctl.upper_hr_threshold);
1205
0
                    fprintf(stdout, "%sout of bounds high (%6.5lf).\n", cache_ptr->prefix,
1206
0
                            cache_ptr->resize_ctl.upper_hr_threshold);
1207
0
                    break;
1208
1209
0
                case H5C_decr__age_out:
1210
0
                    fprintf(stdout, "%sAuto cache resize -- decrease by ageout.  HR = %lf\n",
1211
0
                            cache_ptr->prefix, hit_rate);
1212
0
                    break;
1213
1214
0
                case H5C_decr__age_out_with_threshold:
1215
0
                    assert(hit_rate > cache_ptr->resize_ctl.upper_hr_threshold);
1216
1217
0
                    fprintf(stdout,
1218
0
                            "%sAuto cache resize -- decrease by ageout with threshold. HR = %lf > %6.5lf\n",
1219
0
                            cache_ptr->prefix, hit_rate, cache_ptr->resize_ctl.upper_hr_threshold);
1220
0
                    break;
1221
1222
0
                default:
1223
0
                    fprintf(stdout, "%sAuto cache resize -- decrease by unknown mode.  HR = %lf\n",
1224
0
                            cache_ptr->prefix, hit_rate);
1225
0
            }
1226
1227
0
            fprintf(stdout, "%s    cache size decreased from (%zu/%zu) to (%zu/%zu).\n", cache_ptr->prefix,
1228
0
                    old_max_cache_size, old_min_clean_size, new_max_cache_size, new_min_clean_size);
1229
0
            break;
1230
1231
0
        case at_max_size:
1232
0
            fprintf(stdout, "%sAuto cache resize -- hit rate (%lf) out of bounds low (%6.5lf).\n",
1233
0
                    cache_ptr->prefix, hit_rate, cache_ptr->resize_ctl.lower_hr_threshold);
1234
0
            fprintf(stdout, "%s    cache already at maximum size so no change.\n", cache_ptr->prefix);
1235
0
            break;
1236
1237
0
        case at_min_size:
1238
0
            fprintf(stdout, "%sAuto cache resize -- hit rate (%lf) -- can't decrease.\n", cache_ptr->prefix,
1239
0
                    hit_rate);
1240
0
            fprintf(stdout, "%s    cache already at minimum size.\n", cache_ptr->prefix);
1241
0
            break;
1242
1243
0
        case increase_disabled:
1244
0
            fprintf(stdout, "%sAuto cache resize -- increase disabled -- HR = %lf.", cache_ptr->prefix,
1245
0
                    hit_rate);
1246
0
            break;
1247
1248
0
        case decrease_disabled:
1249
0
            fprintf(stdout, "%sAuto cache resize -- decrease disabled -- HR = %lf.\n", cache_ptr->prefix,
1250
0
                    hit_rate);
1251
0
            break;
1252
1253
0
        case not_full:
1254
0
            assert(hit_rate < cache_ptr->resize_ctl.lower_hr_threshold);
1255
1256
0
            fprintf(stdout, "%sAuto cache resize -- hit rate (%lf) out of bounds low (%6.5lf).\n",
1257
0
                    cache_ptr->prefix, hit_rate, cache_ptr->resize_ctl.lower_hr_threshold);
1258
0
            fprintf(stdout, "%s    cache not full so no increase in size.\n", cache_ptr->prefix);
1259
0
            break;
1260
1261
0
        default:
1262
0
            fprintf(stdout, "%sAuto cache resize -- unknown status code.\n", cache_ptr->prefix);
1263
0
            break;
1264
0
    }
1265
0
} /* H5C_def_auto_resize_rpt_fcn() */
1266
1267
/*-------------------------------------------------------------------------
1268
 * Function:    H5C__validate_lru_list
1269
 *
1270
 * Purpose:     Debugging function that scans the LRU list for errors.
1271
 *
1272
 *        If an error is detected, the function generates a
1273
 *        diagnostic and returns FAIL.  If no error is detected,
1274
 *        the function returns SUCCEED.
1275
 *
1276
 * Return:      FAIL if error is detected, SUCCEED otherwise.
1277
 *
1278
 *-------------------------------------------------------------------------
1279
 */
1280
#ifdef H5C_DO_EXTREME_SANITY_CHECKS
1281
herr_t
1282
H5C__validate_lru_list(H5C_t *cache_ptr)
1283
{
1284
    int32_t            len       = 0;
1285
    size_t             size      = 0;
1286
    H5C_cache_entry_t *entry_ptr = NULL;
1287
    herr_t             ret_value = SUCCEED; /* Return value */
1288
1289
    FUNC_ENTER_PACKAGE
1290
1291
    assert(cache_ptr);
1292
1293
    if (((cache_ptr->LRU_head_ptr == NULL) || (cache_ptr->LRU_tail_ptr == NULL)) &&
1294
        (cache_ptr->LRU_head_ptr != cache_ptr->LRU_tail_ptr))
1295
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "LRU list head/tail check failed");
1296
1297
    if ((cache_ptr->LRU_list_len == 1) &&
1298
        ((cache_ptr->LRU_head_ptr != cache_ptr->LRU_tail_ptr) || (cache_ptr->LRU_head_ptr == NULL) ||
1299
         (cache_ptr->LRU_head_ptr->size != cache_ptr->LRU_list_size)))
1300
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "LRU list sanity check failed");
1301
1302
    if ((cache_ptr->LRU_list_len >= 1) &&
1303
        ((cache_ptr->LRU_head_ptr == NULL) || (cache_ptr->LRU_head_ptr->prev != NULL) ||
1304
         (cache_ptr->LRU_tail_ptr == NULL) || (cache_ptr->LRU_tail_ptr->next != NULL)))
1305
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "LRU list sanity check failed");
1306
1307
    entry_ptr = cache_ptr->LRU_head_ptr;
1308
    while (entry_ptr != NULL) {
1309
        if ((entry_ptr != cache_ptr->LRU_head_ptr) &&
1310
            ((entry_ptr->prev == NULL) || (entry_ptr->prev->next != entry_ptr)))
1311
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry has bad prev/next pointers");
1312
1313
        if ((entry_ptr != cache_ptr->LRU_tail_ptr) &&
1314
            ((entry_ptr->next == NULL) || (entry_ptr->next->prev != entry_ptr)))
1315
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry has bad prev/next pointers");
1316
1317
        if (entry_ptr->is_pinned || entry_ptr->pinned_from_client || entry_ptr->pinned_from_cache)
1318
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "invalid entry 'pin origin' fields");
1319
1320
        len++;
1321
        size += entry_ptr->size;
1322
        entry_ptr = entry_ptr->next;
1323
    }
1324
1325
    if ((cache_ptr->LRU_list_len != (uint32_t)len) || (cache_ptr->LRU_list_size != size))
1326
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "LRU list length/size check failed");
1327
1328
done:
1329
    if (ret_value != SUCCEED)
1330
        assert(0);
1331
1332
    FUNC_LEAVE_NOAPI(ret_value)
1333
} /* H5C__validate_lru_list() */
1334
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
1335
1336
/*-------------------------------------------------------------------------
1337
 * Function:    H5C__validate_pinned_entry_list
1338
 *
1339
 * Purpose:     Debugging function that scans the pinned entry list for
1340
 *              errors.
1341
 *
1342
 *        If an error is detected, the function generates a
1343
 *        diagnostic and returns FAIL.  If no error is detected,
1344
 *        the function returns SUCCEED.
1345
 *
1346
 * Return:      FAIL if error is detected, SUCCEED otherwise.
1347
 *
1348
 *-------------------------------------------------------------------------
1349
 */
1350
#ifdef H5C_DO_EXTREME_SANITY_CHECKS
1351
herr_t
1352
H5C__validate_pinned_entry_list(H5C_t *cache_ptr)
1353
{
1354
    int32_t            len       = 0;
1355
    size_t             size      = 0;
1356
    H5C_cache_entry_t *entry_ptr = NULL;
1357
    herr_t             ret_value = SUCCEED; /* Return value */
1358
1359
    FUNC_ENTER_PACKAGE
1360
1361
    assert(cache_ptr);
1362
1363
    if (((cache_ptr->pel_head_ptr == NULL) || (cache_ptr->pel_tail_ptr == NULL)) &&
1364
        (cache_ptr->pel_head_ptr != cache_ptr->pel_tail_ptr))
1365
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "pinned list head/tail check failed");
1366
1367
    if ((cache_ptr->pel_len == 1) &&
1368
        ((cache_ptr->pel_head_ptr != cache_ptr->pel_tail_ptr) || (cache_ptr->pel_head_ptr == NULL) ||
1369
         (cache_ptr->pel_head_ptr->size != cache_ptr->pel_size)))
1370
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "pinned list sanity check failed");
1371
1372
    if ((cache_ptr->pel_len >= 1) &&
1373
        ((cache_ptr->pel_head_ptr == NULL) || (cache_ptr->pel_head_ptr->prev != NULL) ||
1374
         (cache_ptr->pel_tail_ptr == NULL) || (cache_ptr->pel_tail_ptr->next != NULL)))
1375
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "pinned list sanity check failed");
1376
1377
    entry_ptr = cache_ptr->pel_head_ptr;
1378
    while (entry_ptr != NULL) {
1379
        if ((entry_ptr != cache_ptr->pel_head_ptr) &&
1380
            ((entry_ptr->prev == NULL) || (entry_ptr->prev->next != entry_ptr)))
1381
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry has bad prev/next pointers");
1382
1383
        if ((entry_ptr != cache_ptr->pel_tail_ptr) &&
1384
            ((entry_ptr->next == NULL) || (entry_ptr->next->prev != entry_ptr)))
1385
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry has bad prev/next pointers");
1386
1387
        if (!entry_ptr->is_pinned)
1388
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "pinned list contains unpinned entry");
1389
1390
        if (!(entry_ptr->pinned_from_client || entry_ptr->pinned_from_cache))
1391
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "invalid entry 'pin origin' fields");
1392
1393
        len++;
1394
        size += entry_ptr->size;
1395
        entry_ptr = entry_ptr->next;
1396
    }
1397
1398
    if ((cache_ptr->pel_len != (uint32_t)len) || (cache_ptr->pel_size != size))
1399
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "pinned list length/size check failed");
1400
1401
done:
1402
    if (ret_value != SUCCEED)
1403
        assert(0);
1404
1405
    FUNC_LEAVE_NOAPI(ret_value)
1406
} /* H5C__validate_pinned_entry_list() */
1407
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
1408
1409
/*-------------------------------------------------------------------------
1410
 * Function:    H5C__validate_protected_entry_list
1411
 *
1412
 * Purpose:     Debugging function that scans the protected entry list for
1413
 *              errors.
1414
 *
1415
 *        If an error is detected, the function generates a
1416
 *        diagnostic and returns FAIL.  If no error is detected,
1417
 *        the function returns SUCCEED.
1418
 *
1419
 * Return:      FAIL if error is detected, SUCCEED otherwise.
1420
 *
1421
 *-------------------------------------------------------------------------
1422
 */
1423
#ifdef H5C_DO_EXTREME_SANITY_CHECKS
1424
herr_t
1425
H5C__validate_protected_entry_list(H5C_t *cache_ptr)
1426
{
1427
    int32_t            len       = 0;
1428
    size_t             size      = 0;
1429
    H5C_cache_entry_t *entry_ptr = NULL;
1430
    herr_t             ret_value = SUCCEED; /* Return value */
1431
1432
    FUNC_ENTER_PACKAGE
1433
1434
    assert(cache_ptr);
1435
1436
    if (((cache_ptr->pl_head_ptr == NULL) || (cache_ptr->pl_tail_ptr == NULL)) &&
1437
        (cache_ptr->pl_head_ptr != cache_ptr->pl_tail_ptr))
1438
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "protected list head/tail check failed");
1439
1440
    if ((cache_ptr->pl_len == 1) &&
1441
        ((cache_ptr->pl_head_ptr != cache_ptr->pl_tail_ptr) || (cache_ptr->pl_head_ptr == NULL) ||
1442
         (cache_ptr->pl_head_ptr->size != cache_ptr->pl_size)))
1443
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "protected list sanity check failed");
1444
1445
    if ((cache_ptr->pl_len >= 1) &&
1446
        ((cache_ptr->pl_head_ptr == NULL) || (cache_ptr->pl_head_ptr->prev != NULL) ||
1447
         (cache_ptr->pl_tail_ptr == NULL) || (cache_ptr->pl_tail_ptr->next != NULL)))
1448
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "protected list sanity check failed");
1449
1450
    entry_ptr = cache_ptr->pl_head_ptr;
1451
    while (entry_ptr != NULL) {
1452
        if ((entry_ptr != cache_ptr->pl_head_ptr) &&
1453
            ((entry_ptr->prev == NULL) || (entry_ptr->prev->next != entry_ptr)))
1454
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry has bad prev/next pointers");
1455
1456
        if ((entry_ptr != cache_ptr->pl_tail_ptr) &&
1457
            ((entry_ptr->next == NULL) || (entry_ptr->next->prev != entry_ptr)))
1458
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry has bad prev/next pointers");
1459
1460
        if (!entry_ptr->is_protected)
1461
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "protected list contains unprotected entry");
1462
1463
        if (entry_ptr->is_read_only && (entry_ptr->ro_ref_count <= 0))
1464
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "read-only entry has non-positive ref count");
1465
1466
        len++;
1467
        size += entry_ptr->size;
1468
        entry_ptr = entry_ptr->next;
1469
    }
1470
1471
    if ((cache_ptr->pl_len != (uint32_t)len) || (cache_ptr->pl_size != size))
1472
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "protected list length/size check failed");
1473
1474
done:
1475
    if (ret_value != SUCCEED)
1476
        assert(0);
1477
1478
    FUNC_LEAVE_NOAPI(ret_value)
1479
} /* H5C__validate_protected_entry_list() */
1480
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
1481
1482
/*-------------------------------------------------------------------------
1483
 * Function:    H5C__entry_in_skip_list
1484
 *
1485
 * Purpose:     Debugging function that scans skip list to see if it
1486
 *        is in present.  We need this, as it is possible for
1487
 *        an entry to be in the skip list twice.
1488
 *
1489
 * Return:      false if the entry is not in the skip list, and true
1490
 *        if it is.
1491
 *
1492
 *-------------------------------------------------------------------------
1493
 */
1494
#ifdef H5C_DO_SLIST_SANITY_CHECKS
1495
bool
1496
H5C__entry_in_skip_list(H5C_t *cache_ptr, H5C_cache_entry_t *target_ptr)
1497
{
1498
    H5SL_node_t *node_ptr;
1499
    bool         in_slist;
1500
    bool         ret_value;
1501
1502
    FUNC_ENTER_PACKAGE
1503
1504
    /* Assertions */
1505
    assert(cache_ptr);
1506
    assert(cache_ptr->slist_ptr);
1507
1508
    node_ptr = H5SL_first(cache_ptr->slist_ptr);
1509
    in_slist = false;
1510
    while ((node_ptr != NULL) && (!in_slist)) {
1511
        H5C_cache_entry_t *entry_ptr;
1512
1513
        entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
1514
1515
        assert(entry_ptr);
1516
        assert(entry_ptr->is_dirty);
1517
        assert(entry_ptr->in_slist);
1518
1519
        if (entry_ptr == target_ptr)
1520
            in_slist = true;
1521
        else
1522
            node_ptr = H5SL_next(node_ptr);
1523
    }
1524
1525
    /* Set return value */
1526
    ret_value = in_slist;
1527
1528
done:
1529
    FUNC_LEAVE_NOAPI(ret_value)
1530
} /* H5C__entry_in_skip_list() */
1531
#endif /* H5C_DO_SLIST_SANITY_CHECKS */
1532
1533
/*-------------------------------------------------------------------------
1534
 * Function:    H5C__image_stats
1535
 *
1536
 * Purpose:     Prints statistics specific to the cache image.
1537
 *
1538
 * Return:      Non-negative on success/Negative on failure
1539
 *
1540
 *-------------------------------------------------------------------------
1541
 */
1542
herr_t
1543
#if H5C_COLLECT_CACHE_STATS
1544
H5C__image_stats(H5C_t *cache_ptr, bool print_header)
1545
#else  /* H5C_COLLECT_CACHE_STATS */
1546
H5C__image_stats(H5C_t *cache_ptr, bool H5_ATTR_UNUSED print_header)
1547
#endif /* H5C_COLLECT_CACHE_STATS */
1548
0
{
1549
#if H5C_COLLECT_CACHE_STATS
1550
    int     i;
1551
    int64_t total_hits   = 0;
1552
    int64_t total_misses = 0;
1553
    double  hit_rate;
1554
    double  prefetch_use_rate;
1555
#endif                          /* H5C_COLLECT_CACHE_STATS */
1556
0
    herr_t ret_value = SUCCEED; /* Return value */
1557
1558
0
    FUNC_ENTER_NOAPI(FAIL)
1559
1560
0
    if (NULL == cache_ptr)
1561
0
        HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr");
1562
1563
#if H5C_COLLECT_CACHE_STATS
1564
    for (i = 0; i <= cache_ptr->max_type_id; i++) {
1565
        total_hits += cache_ptr->hits[i];
1566
        total_misses += cache_ptr->misses[i];
1567
    } /* end for */
1568
1569
    if ((total_hits > 0) || (total_misses > 0))
1570
        hit_rate = 100.0 * ((double)(total_hits)) / ((double)(total_hits + total_misses));
1571
    else
1572
        hit_rate = 0.0;
1573
1574
    if (cache_ptr->prefetches > 0)
1575
        prefetch_use_rate = 100.0 * ((double)(cache_ptr->prefetch_hits)) / ((double)(cache_ptr->prefetches));
1576
    else
1577
        prefetch_use_rate = 0.0;
1578
1579
    if (print_header) {
1580
        fprintf(stdout, "\nhit     prefetches      prefetch              image  pf hit\n");
1581
        fprintf(stdout, "rate:   total:  dirty:  hits:  flshs:  evct:  size:  rate:\n");
1582
    } /* end if */
1583
1584
    fprintf(stdout, "%3.1lf    %5lld   %5lld   %5lld  %5lld   %5lld   %5lld   %3.1lf\n", hit_rate,
1585
            (long long)(cache_ptr->prefetches), (long long)(cache_ptr->dirty_prefetches),
1586
            (long long)(cache_ptr->prefetch_hits), (long long)(cache_ptr->flushes[H5AC_PREFETCHED_ENTRY_ID]),
1587
            (long long)(cache_ptr->evictions[H5AC_PREFETCHED_ENTRY_ID]),
1588
            (long long)(cache_ptr->last_image_size), prefetch_use_rate);
1589
#endif /* H5C_COLLECT_CACHE_STATS */
1590
1591
0
done:
1592
0
    FUNC_LEAVE_NOAPI(ret_value)
1593
0
} /* H5C__image_stats() */