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() */ |