dbengine: cache bug-fix when under pressure (#17231)
when a page cannot be acquired, repeat the call until it can or does not exist
Costa Tsaousis committed
Mar 23, 2024 at 11:06 UTC
3240d07c435864a33bef93e5a1c3971c5398c6d1
1 file changed
+43
-26
src/database/engine/cache.c
+43
-26
@@ -1325,21 +1325,8 @@ static PGC_PAGE *page_add(PGC *cache, PGC_ENTRY *entry, bool *added) {
1325
return page;
1326
}
1327
1328
-static PGC_PAGE *page_find_and_acquire(PGC *cache, Word_t section, Word_t metric_id, time_t start_time_s, PGC_SEARCH method) {
1329
- __atomic_add_fetch(&cache->stats.workers_search, 1, __ATOMIC_RELAXED);
1330
-
1331
- size_t *stats_hit_ptr, *stats_miss_ptr;
1332
-
1333
- if(method == PGC_SEARCH_CLOSEST) {
1334
- __atomic_add_fetch(&cache->stats.searches_closest, 1, __ATOMIC_RELAXED);
1335
- stats_hit_ptr = &cache->stats.searches_closest_hits;
1336
- stats_miss_ptr = &cache->stats.searches_closest_misses;
1337
- }
1338
- else {
1339
- __atomic_add_fetch(&cache->stats.searches_exact, 1, __ATOMIC_RELAXED);
1340
- stats_hit_ptr = &cache->stats.searches_exact_hits;
1341
- stats_miss_ptr = &cache->stats.searches_exact_misses;
1342
- }
1328
+static PGC_PAGE *page_find_and_acquire_once(PGC *cache, Word_t section, Word_t metric_id, time_t start_time_s, PGC_SEARCH method, bool *retry) {
1329
+ *retry = false;
1330
1331
PGC_PAGE *page = NULL;
1332
size_t partition = pgc_indexing_partition(cache, metric_id);
@@ -1462,22 +1449,13 @@ static PGC_PAGE *page_find_and_acquire(PGC *cache, Word_t section, Word_t metric
1449
1450
if(!page_acquire(cache, page)) {
1451
// this page is not good to use
1452
+ *retry = true;
1453
page = NULL;
1454
}
1455
}
1456
1457
cleanup:
1458
pgc_index_read_unlock(cache, partition);
1471
-
1472
- if(page) {
1473
- __atomic_add_fetch(stats_hit_ptr, 1, __ATOMIC_RELAXED);
1474
- page_has_been_accessed(cache, page);
1475
- }
1476
- else
1477
- __atomic_add_fetch(stats_miss_ptr, 1, __ATOMIC_RELAXED);
1478
-
1479
- __atomic_sub_fetch(&cache->stats.workers_search, 1, __ATOMIC_RELAXED);
1480
-
1459
return page;
1460
}
1461
@@ -2048,7 +2026,46 @@ void pgc_page_hot_set_end_time_s(PGC *cache __maybe_unused, PGC_PAGE *page, time
2026
}
2027
2028
PGC_PAGE *pgc_page_get_and_acquire(PGC *cache, Word_t section, Word_t metric_id, time_t start_time_s, PGC_SEARCH method) {
2051
- return page_find_and_acquire(cache, section, metric_id, start_time_s, method);
2029
+ static const struct timespec ns = { .tv_sec = 0, .tv_nsec = 1 };
2030
+
2031
+ PGC_PAGE *page = NULL;
2032
+
2033
+ __atomic_add_fetch(&cache->stats.workers_search, 1, __ATOMIC_RELAXED);
2034
+
2035
+ size_t *stats_hit_ptr, *stats_miss_ptr;
2036
+
2037
+ if(method == PGC_SEARCH_CLOSEST) {
2038
+ __atomic_add_fetch(&cache->stats.searches_closest, 1, __ATOMIC_RELAXED);
2039
+ stats_hit_ptr = &cache->stats.searches_closest_hits;
2040
+ stats_miss_ptr = &cache->stats.searches_closest_misses;
2041
+ }
2042
+ else {
2043
+ __atomic_add_fetch(&cache->stats.searches_exact, 1, __ATOMIC_RELAXED);
2044
+ stats_hit_ptr = &cache->stats.searches_exact_hits;
2045
+ stats_miss_ptr = &cache->stats.searches_exact_misses;
2046
+ }
2047
+
2048
+ while(1) {
2049
+ bool retry = false;
2050
+
2051
+ page = page_find_and_acquire_once(cache, section, metric_id, start_time_s, method, &retry);
2052
+
2053
+ if(page || !retry)
2054
+ break;
2055
+
2056
+ nanosleep(&ns, NULL);
2057
+ }
2058
+
2059
+ if(page) {
2060
+ __atomic_add_fetch(stats_hit_ptr, 1, __ATOMIC_RELAXED);
2061
+ page_has_been_accessed(cache, page);
2062
+ }
2063
+ else
2064
+ __atomic_add_fetch(stats_miss_ptr, 1, __ATOMIC_RELAXED);
2065
+
2066
+ __atomic_sub_fetch(&cache->stats.workers_search, 1, __ATOMIC_RELAXED);
2067
+
2068
+ return page;
2069
}
2070
2071
struct pgc_statistics pgc_get_statistics(PGC *cache) {