@cryptotaxi247 / netdata-1 / commits / fe45b4961

Revert "Fix race condition in dbengine (#7533)" (#7560)

We are removing this fix for further internal testing, it will be returning after we iron out some bugs. This reverts commit 53ab093d84919c743450199a31bca9a13412e451.

Andrew Moss committed Dec 17, 2019 at 19:15 UTC fe45b4961e92b21d0de2a3e340f4563fb6b4be2b
8 files changed +72 -116
daemon/main.c
+4 -8
@@ -340,12 +340,10 @@ int help(int exitcode) {
340 " -W unittest Run internal unittests and exit.\n\n"
341 #ifdef ENABLE_DBENGINE
342 " -W createdataset=N Create a DB engine dataset of N seconds and exit.\n\n"
343 - " -W stresstest=A,B,C,D,E,F\n"
344 - " Run a DB engine stress test for A seconds,\n"
343 + " -W stresstest=A,B,C,D,E Run a DB engine stress test for A seconds,\n"
344 " with B writers and C readers, with a ramp up\n"
345 " time of D seconds for writers, a page cache\n"
347 - " size of E MiB, an optional disk space limit\n"
348 - " of F MiB and exit.\n\n"
346 + " size of E MiB, and exit.\n\n"
347 #endif
348 " -W set section option value\n"
349 " set netdata.conf option from the command line.\n\n"
@@ -958,7 +956,7 @@ int main(int argc, char **argv) {
956 else if(strncmp(optarg, stresstest_string, strlen(stresstest_string)) == 0) {
957 char *endptr;
958 unsigned test_duration_sec = 0, dset_charts = 0, query_threads = 0, ramp_up_seconds = 0,
961 - page_cache_mb = 0, disk_space_mb = 0;
959 + page_cache_mb = 0;
960
961 optarg += strlen(stresstest_string);
962 test_duration_sec = (unsigned)strtoul(optarg, &endptr, 0);
@@ -970,10 +968,8 @@ int main(int argc, char **argv) {
968 ramp_up_seconds = (unsigned)strtoul(endptr + 1, &endptr, 0);
969 if (',' == *endptr)
970 page_cache_mb = (unsigned)strtoul(endptr + 1, &endptr, 0);
973 - if (',' == *endptr)
974 - disk_space_mb = (unsigned)strtoul(endptr + 1, &endptr, 0);
971 dbengine_stress_test(test_duration_sec, dset_charts, query_threads, ramp_up_seconds,
976 - page_cache_mb, disk_space_mb);
972 + page_cache_mb);
973 return 0;
974 }
975 #endif
daemon/unit_test.c
+27 -56
@@ -1723,7 +1723,7 @@ int test_dbengine(void)
1723
1724 default_rrd_memory_mode = RRD_MEMORY_MODE_DBENGINE;
1725
1726 - fprintf(stderr, "Initializing localhost with hostname 'unittest-dbengine'\n");
1726 + debug(D_RRDHOST, "Initializing localhost with hostname 'unittest-dbengine'");
1727 host = dbengine_rrdhost_find_or_create("unittest-dbengine");
1728 if (NULL == host)
1729 return 1;
@@ -1915,9 +1915,6 @@ static void generate_dbengine_chart(void *arg)
1915 rrdset_done(st);
1916 thread_info->time_max = time_current;
1917 }
1918 - for (j = 0; j < DSET_DIMS; ++j) {
1919 - rrdeng_store_metric_finalize(rd[j]);
1920 - }
1918 }
1919
1920 void generate_dbengine_dataset(unsigned history_seconds)
@@ -1938,7 +1935,7 @@ void generate_dbengine_dataset(unsigned history_seconds)
1935 default_rrdeng_disk_quota_mb -= default_rrdeng_disk_quota_mb * EXPECTED_COMPRESSION_RATIO / 100;
1936
1937 error_log_limit_unlimited();
1941 - fprintf(stderr, "Initializing localhost with hostname 'dbengine-dataset'\n");
1938 + debug(D_RRDHOST, "Initializing localhost with hostname 'dbengine-dataset'");
1939
1940 host = dbengine_rrdhost_find_or_create("dbengine-dataset");
1941 if (NULL == host)
@@ -1989,7 +1986,6 @@ struct dbengine_query_thread {
1986 unsigned history_seconds; /* how far back in the past to go */
1987 volatile long done; /* initialize to 0, set to 1 to stop thread */
1988 unsigned long errors, queries_nr, queried_metrics_nr; /* statistics */
1992 - uint8_t delete_old_data; /* if non zero then data are deleted when disk space is exhausted */
1989
1990 struct dbengine_chart_thread *chart_threads[]; /* dset_charts elements */
1991 };
@@ -1999,7 +1995,7 @@ static void query_dbengine_chart(void *arg)
1995 struct dbengine_query_thread *thread_info = (struct dbengine_query_thread *)arg;
1996 const int DSET_CHARTS = thread_info->dset_charts;
1997 const int DSET_DIMS = thread_info->dset_dims;
2002 - time_t time_after, time_before, time_min, time_approx_min, time_max, duration;
1998 + time_t time_after, time_before, time_min, time_max, duration;
1999 int i, j, update_every = 1;
2000 RRDSET *st;
2001 RRDDIM *rd;
@@ -2019,13 +2015,6 @@ static void query_dbengine_chart(void *arg)
2015
2016 time_min = thread_info->time_present - thread_info->history_seconds + 1;
2017 time_max = thread_info->chart_threads[i]->time_max;
2022 -
2023 - if (thread_info->delete_old_data) {
2024 - /* A time window of twice the disk space is sufficient for compression space savings of up to 50% */
2025 - time_approx_min = time_max - (default_rrdeng_disk_quota_mb * 2 * 1024 * 1024) /
2026 - (((uint64_t) DSET_DIMS * DSET_CHARTS) * sizeof(storage_number));
2027 - time_min = MAX(time_min, time_approx_min);
2028 - }
2018 if (!time_max) {
2019 time_before = time_after = time_min;
2020 } else {
@@ -2041,22 +2030,18 @@ static void query_dbengine_chart(void *arg)
2030 expected = unpack_storage_number(pack_storage_number((calculated_number) generatedv, SN_EXISTS));
2031
2032 if (unlikely(rd->state->query_ops.is_finished(&handle))) {
2044 - if (!thread_info->delete_old_data) { /* data validation only when we don't delete */
2045 - fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, expecting value "
2046 - CALCULATED_NUMBER_FORMAT ", found data gap, ### E R R O R ###\n",
2047 - st->name, rd->name, (unsigned long) time_now, expected);
2048 - ++thread_info->errors;
2049 - }
2033 + fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, expecting value "
2034 + CALCULATED_NUMBER_FORMAT ", found data gap, ### E R R O R ###\n",
2035 + st->name, rd->name, (unsigned long) time_now, expected);
2036 + ++thread_info->errors;
2037 break;
2038 }
2039 n = rd->state->query_ops.next_metric(&handle, &time_retrieved);
2040 if (SN_EMPTY_SLOT == n) {
2054 - if (!thread_info->delete_old_data) { /* data validation only when we don't delete */
2055 - fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, expecting value "
2056 - CALCULATED_NUMBER_FORMAT ", found data gap, ### E R R O R ###\n",
2057 - st->name, rd->name, (unsigned long) time_now, expected);
2058 - ++thread_info->errors;
2059 - }
2041 + fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, expecting value "
2042 + CALCULATED_NUMBER_FORMAT ", found data gap, ### E R R O R ###\n",
2043 + st->name, rd->name, (unsigned long) time_now, expected);
2044 + ++thread_info->errors;
2045 break;
2046 }
2047 ++thread_info->queried_metrics_nr;
@@ -2064,21 +2049,15 @@ static void query_dbengine_chart(void *arg)
2049
2050 same = (calculated_number_round(value) == calculated_number_round(expected)) ? 1 : 0;
2051 if (!same) {
2067 - if (!thread_info->delete_old_data) { /* data validation only when we don't delete */
2068 - fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, expecting value "
2069 - CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT
2070 - ", ### E R R O R ###\n",
2071 - st->name, rd->name, (unsigned long) time_now, expected, value);
2072 - ++thread_info->errors;
2073 - }
2052 + fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, expecting value "
2053 + CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", ### E R R O R ###\n",
2054 + st->name, rd->name, (unsigned long) time_now, expected, value);
2055 + ++thread_info->errors;
2056 }
2057 if (time_retrieved != time_now) {
2076 - if (!thread_info->delete_old_data) { /* data validation only when we don't delete */
2077 - fprintf(stderr,
2078 - " DB-engine stresstest %s/%s: at %lu secs, found timestamp %lu ### E R R O R ###\n",
2079 - st->name, rd->name, (unsigned long) time_now, (unsigned long) time_retrieved);
2080 - ++thread_info->errors;
2081 - }
2058 + fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, found timestamp %lu ### E R R O R ###\n",
2059 + st->name, rd->name, (unsigned long) time_now, (unsigned long) time_retrieved);
2060 + ++thread_info->errors;
2061 }
2062 }
2063 rd->state->query_ops.finalize(&handle);
@@ -2086,19 +2065,17 @@ static void query_dbengine_chart(void *arg)
2065 }
2066
2067 void dbengine_stress_test(unsigned TEST_DURATION_SEC, unsigned DSET_CHARTS, unsigned QUERY_THREADS,
2089 - unsigned RAMP_UP_SECONDS, unsigned PAGE_CACHE_MB, unsigned DISK_SPACE_MB)
2068 + unsigned RAMP_UP_SECONDS, unsigned PAGE_CACHE_MB)
2069 {
2070 const unsigned DSET_DIMS = 128;
2071 const uint64_t EXPECTED_COMPRESSION_RATIO = 20;
2093 - const unsigned HISTORY_SECONDS = 3600 * 24 * 365 * 50; /* 50 years of history */
2072 + const unsigned HISTORY_SECONDS = 3600 * 24 * 365; /* 1 year of history */
2073 RRDHOST *host = NULL;
2074 struct dbengine_chart_thread **chart_threads;
2075 struct dbengine_query_thread **query_threads;
2076 unsigned i, j;
2077 time_t time_start, time_end;
2078
2100 - error_log_limit_unlimited();
2101 -
2079 if (!TEST_DURATION_SEC)
2080 TEST_DURATION_SEC = 10;
2081 if (!DSET_CHARTS)
@@ -2110,18 +2087,13 @@ void dbengine_stress_test(unsigned TEST_DURATION_SEC, unsigned DSET_CHARTS, unsi
2087
2088 default_rrd_memory_mode = RRD_MEMORY_MODE_DBENGINE;
2089 default_rrdeng_page_cache_mb = PAGE_CACHE_MB;
2113 - if (DISK_SPACE_MB) {
2114 - fprintf(stderr, "By setting disk space limit data are allowed to be deleted. "
2115 - "Data validation is turned off for this run.\n");
2116 - default_rrdeng_disk_quota_mb = DISK_SPACE_MB;
2117 - } else {
2118 - // Worst case for uncompressible data
2119 - default_rrdeng_disk_quota_mb =
2120 - (((uint64_t) DSET_DIMS * DSET_CHARTS) * sizeof(storage_number) * HISTORY_SECONDS) / (1024 * 1024);
2121 - default_rrdeng_disk_quota_mb -= default_rrdeng_disk_quota_mb * EXPECTED_COMPRESSION_RATIO / 100;
2122 - }
2090 + // Worst case for uncompressible data
2091 + default_rrdeng_disk_quota_mb = (((uint64_t)DSET_DIMS * DSET_CHARTS) * sizeof(storage_number) * HISTORY_SECONDS) /
2092 + (1024 * 1024);
2093 + default_rrdeng_disk_quota_mb -= default_rrdeng_disk_quota_mb * EXPECTED_COMPRESSION_RATIO / 100;
2094
2124 - fprintf(stderr, "Initializing localhost with hostname 'dbengine-stress-test'\n");
2095 + error_log_limit_unlimited();
2096 + debug(D_RRDHOST, "Initializing localhost with hostname 'dbengine-stress-test'");
2097
2098 host = dbengine_rrdhost_find_or_create("dbengine-stress-test");
2099 if (NULL == host)
@@ -2140,7 +2112,7 @@ void dbengine_stress_test(unsigned TEST_DURATION_SEC, unsigned DSET_CHARTS, unsi
2112 "%u MiB of page cache.\n",
2113 RAMP_UP_SECONDS, TEST_DURATION_SEC, DSET_CHARTS, QUERY_THREADS, PAGE_CACHE_MB);
2114
2143 - time_start = now_realtime_sec() + HISTORY_SECONDS; /* move history to the future */
2115 + time_start = now_realtime_sec();
2116 for (i = 0 ; i < DSET_CHARTS ; ++i) {
2117 chart_threads[i]->host = host;
2118 chart_threads[i]->chartname = "random";
@@ -2174,7 +2146,6 @@ void dbengine_stress_test(unsigned TEST_DURATION_SEC, unsigned DSET_CHARTS, unsi
2146 for (j = 0 ; j < DSET_CHARTS ; ++j) {
2147 query_threads[i]->chart_threads[j] = chart_threads[j];
2148 }
2177 - query_threads[i]->delete_old_data = DISK_SPACE_MB ? 1 : 0;
2149 assert(0 == uv_thread_create(&query_threads[i]->thread, query_dbengine_chart, query_threads[i]));
2150 }
2151 sleep(TEST_DURATION_SEC);
daemon/unit_test.h
+1 -1
@@ -12,7 +12,7 @@ extern int unit_test_buffer(void);
12 extern int test_dbengine(void);
13 extern void generate_dbengine_dataset(unsigned history_seconds);
14 extern void dbengine_stress_test(unsigned TEST_DURATION_SEC, unsigned DSET_CHARTS, unsigned QUERY_THREADS,
15 - unsigned RAMP_UP_SECONDS, unsigned PAGE_CACHE_MB, unsigned DISK_SPACE_MB);
15 + unsigned RAMP_UP_SECONDS, unsigned PAGE_CACHE_MB);
16
17 #endif
18
database/engine/pagecache.c
+13 -21
@@ -101,13 +101,6 @@ void pg_cache_wake_up_waiters_unsafe(struct rrdeng_page_descr *descr)
101 uv_cond_broadcast(&pg_cache_descr->cond);
102 }
103
104 -void pg_cache_wake_up_waiters(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr)
105 -{
106 - rrdeng_page_descr_mutex_lock(ctx, descr);
107 - pg_cache_wake_up_waiters_unsafe(descr);
108 - rrdeng_page_descr_mutex_unlock(ctx, descr);
109 -}
110 -
104 /*
105 * The caller must hold page descriptor lock.
106 * The lock will be released and re-acquired. The descriptor is not guaranteed
@@ -142,8 +135,10 @@ unsigned long pg_cache_wait_event(struct rrdengine_instance *ctx, struct rrdeng_
135
136 /*
137 * The caller must hold page descriptor lock.
138 + * Gets a reference to the page descriptor.
139 + * Returns 1 on success and 0 on failure.
140 */
146 -int pg_cache_can_get_unsafe(struct rrdeng_page_descr *descr, int exclusive_access)
141 +int pg_cache_try_get_unsafe(struct rrdeng_page_descr *descr, int exclusive_access)
142 {
143 struct page_cache_descr *pg_cache_descr = descr->pg_cache_descr;
144
@@ -151,25 +146,25 @@ int pg_cache_can_get_unsafe(struct rrdeng_page_descr *descr, int exclusive_acces
146 (exclusive_access && pg_cache_descr->refcnt)) {
147 return 0;
148 }
149 + if (exclusive_access)
150 + pg_cache_descr->flags |= RRD_PAGE_LOCKED;
151 + ++pg_cache_descr->refcnt;
152
153 return 1;
154 }
155
156 /*
157 * The caller must hold page descriptor lock.
160 - * Gets a reference to the page descriptor.
161 - * Returns 1 on success and 0 on failure.
158 + * Same return values as pg_cache_try_get_unsafe() without doing anything.
159 */
163 -int pg_cache_try_get_unsafe(struct rrdeng_page_descr *descr, int exclusive_access)
160 +int pg_cache_can_get_unsafe(struct rrdeng_page_descr *descr, int exclusive_access)
161 {
162 struct page_cache_descr *pg_cache_descr = descr->pg_cache_descr;
163
167 - if (!pg_cache_can_get_unsafe(descr, exclusive_access))
164 + if ((pg_cache_descr->flags & (RRD_PAGE_LOCKED | RRD_PAGE_READ_PENDING)) ||
165 + (exclusive_access && pg_cache_descr->refcnt)) {
166 return 0;
169 -
170 - if (exclusive_access)
171 - pg_cache_descr->flags |= RRD_PAGE_LOCKED;
172 - ++pg_cache_descr->refcnt;
167 + }
168
169 return 1;
170 }
@@ -434,11 +429,8 @@ void pg_cache_punch_hole(struct rrdengine_instance *ctx, struct rrdeng_page_desc
429 uv_rwlock_wrunlock(&pg_cache->pg_cache_rwlock);
430 }
431 pg_cache_put(ctx, descr);
437 - rrdeng_try_deallocate_pg_cache_descr(ctx, descr);
438 - while (descr->pg_cache_descr_state & PG_CACHE_DESCR_ALLOCATED) {
439 - rrdeng_try_deallocate_pg_cache_descr(ctx, descr); /* spin */
440 - (void)sleep_usec(1000); /* 1 msec */
441 - }
432 + if (descr->pg_cache_descr_state & PG_CACHE_DESCR_ALLOCATED)
433 + rrdeng_try_deallocate_pg_cache_descr(ctx, descr);
434 destroy:
435 freez(descr);
436 pg_cache_update_metric_times(page_index);
database/engine/pagecache.h
-1
@@ -148,7 +148,6 @@ struct page_cache { /* TODO: add statistics */
148 };
149
150 extern void pg_cache_wake_up_waiters_unsafe(struct rrdeng_page_descr *descr);
151 -extern void pg_cache_wake_up_waiters(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr);
151 extern void pg_cache_wait_event_unsafe(struct rrdeng_page_descr *descr);
152 extern unsigned long pg_cache_wait_event(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr);
153 extern void pg_cache_replaceQ_insert(struct rrdengine_instance *ctx,
database/engine/rrdengine.c
+5 -5
@@ -121,19 +121,19 @@ after_crc_check:
121 } else {
122 (void) memcpy(page, uncompressed_buf + page_offset, descr->page_length);
123 }
124 + pg_cache_replaceQ_insert(ctx, descr);
125 rrdeng_page_descr_mutex_lock(ctx, descr);
126 pg_cache_descr = descr->pg_cache_descr;
127 pg_cache_descr->page = page;
128 pg_cache_descr->flags |= RRD_PAGE_POPULATED;
129 pg_cache_descr->flags &= ~RRD_PAGE_READ_PENDING;
129 - rrdeng_page_descr_mutex_unlock(ctx, descr);
130 - pg_cache_replaceQ_insert(ctx, descr);
130 + debug(D_RRDENGINE, "%s: Waking up waiters.", __func__);
131 if (xt_io_descr->release_descr) {
132 - pg_cache_put(ctx, descr);
132 + pg_cache_put_unsafe(descr);
133 } else {
134 - debug(D_RRDENGINE, "%s: Waking up waiters.", __func__);
135 - pg_cache_wake_up_waiters(ctx, descr);
134 + pg_cache_wake_up_waiters_unsafe(descr);
135 }
136 + rrdeng_page_descr_mutex_unlock(ctx, descr);
137 }
138 if (!have_read_error && RRD_NO_COMPRESSION != header->compression_algorithm) {
139 freez(uncompressed_buf);
database/engine/rrdengineapi.c
+5 -5
@@ -473,16 +473,16 @@ storage_number rrdeng_load_metric_next(struct rrddim_query_handle *rrdimm_handle
473 /* We need to get a new page */
474 if (descr) {
475 /* Drop old page's reference */
476 -#ifdef NETDATA_INTERNAL_CHECKS
477 - rrd_stat_atomic_add(&ctx->stats.metric_API_consumers, -1);
478 -#endif
479 - pg_cache_put(ctx, descr);
480 - handle->descr = NULL;
476 handle->next_page_time = (page_end_time / USEC_PER_SEC) + 1;
477 if (unlikely(handle->next_page_time > rrdimm_handle->end_time)) {
478 goto no_more_metrics;
479 }
480 next_page_time = handle->next_page_time * USEC_PER_SEC;
481 +#ifdef NETDATA_INTERNAL_CHECKS
482 + rrd_stat_atomic_add(&ctx->stats.metric_API_consumers, -1);
483 +#endif
484 + pg_cache_put(ctx, descr);
485 + handle->descr = NULL;
486 }
487 descr = pg_cache_lookup_next(ctx, handle->page_index, &handle->page_index->id,
488 next_page_time, rrdimm_handle->end_time * USEC_PER_SEC);
database/engine/rrdenglocking.c
+17 -19
@@ -20,7 +20,12 @@ struct page_cache_descr *rrdeng_create_pg_cache_descr(struct rrdengine_instance
20
21 void rrdeng_destroy_pg_cache_descr(struct rrdengine_instance *ctx, struct page_cache_descr *pg_cache_descr)
22 {
23 + /* Flush any lock and condition variable users */
24 + uv_mutex_lock(&pg_cache_descr->mutex);
25 + uv_mutex_unlock(&pg_cache_descr->mutex);
26 +
27 uv_cond_destroy(&pg_cache_descr->cond);
28 +
29 uv_mutex_destroy(&pg_cache_descr->mutex);
30 freez(pg_cache_descr);
31 rrd_stat_atomic_add(&ctx->stats.page_cache_descriptors, -1);
@@ -95,7 +100,7 @@ void rrdeng_page_descr_mutex_lock(struct rrdengine_instance *ctx, struct rrdeng_
100 void rrdeng_page_descr_mutex_unlock(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr)
101 {
102 unsigned long old_state, new_state, ret_state, old_users;
98 - struct page_cache_descr *pg_cache_descr, *delete_pg_cache_descr = NULL;
103 + struct page_cache_descr *pg_cache_descr;
104 uint8_t we_locked;
105
106 uv_mutex_unlock(&descr->pg_cache_descr->mutex);
@@ -111,8 +116,7 @@ void rrdeng_page_descr_mutex_unlock(struct rrdengine_instance *ctx, struct rrden
116 ret_state = ulong_compare_and_swap(&descr->pg_cache_descr_state, old_state, 0);
117 if (old_state == ret_state) {
118 /* success */
114 - rrdeng_destroy_pg_cache_descr(ctx, delete_pg_cache_descr);
115 - return;
119 + break;
120 }
121 continue; /* spin */
122 }
@@ -124,15 +128,12 @@ void rrdeng_page_descr_mutex_unlock(struct rrdengine_instance *ctx, struct rrden
128 pg_cache_descr = descr->pg_cache_descr;
129 /* caller is the only page cache descriptor user and there are no pending references on the page */
130 if ((old_state & PG_CACHE_DESCR_DESTROY) && (1 == old_users) &&
127 - !pg_cache_descr->flags && !pg_cache_descr->refcnt) {
128 - assert(!pg_cache_descr->waiters);
129 -
131 + !pg_cache_descr->flags && !pg_cache_descr->refcnt && !pg_cache_descr->waiters) {
132 new_state = PG_CACHE_DESCR_LOCKED;
133 ret_state = ulong_compare_and_swap(&descr->pg_cache_descr_state, old_state, new_state);
134 if (old_state == ret_state) {
135 we_locked = 1;
134 - delete_pg_cache_descr = pg_cache_descr;
135 - descr->pg_cache_descr = NULL;
136 + rrdeng_destroy_pg_cache_descr(ctx, pg_cache_descr);
137 /* retry */
138 continue;
139 }
@@ -149,6 +150,7 @@ void rrdeng_page_descr_mutex_unlock(struct rrdengine_instance *ctx, struct rrden
150 }
151 /* spin */
152 }
153 +
154 }
155
156 /*
@@ -159,11 +161,11 @@ void rrdeng_page_descr_mutex_unlock(struct rrdengine_instance *ctx, struct rrden
161 void rrdeng_try_deallocate_pg_cache_descr(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr)
162 {
163 unsigned long old_state, new_state, ret_state, old_users;
162 - struct page_cache_descr *pg_cache_descr = NULL;
163 - uint8_t just_locked, can_free, must_unlock;
164 + struct page_cache_descr *pg_cache_descr;
165 + uint8_t just_locked, we_freed, must_unlock;
166
167 just_locked = 0;
166 - can_free = 0;
168 + we_freed = 0;
169 must_unlock = 0;
170 while (1) { /* spin */
171 old_state = descr->pg_cache_descr_state;
@@ -175,11 +177,9 @@ void rrdeng_try_deallocate_pg_cache_descr(struct rrdengine_instance *ctx, struct
177 must_unlock = 1;
178 just_locked = 0;
179 /* Try deallocate if there are no pending references on the page */
178 - if (!pg_cache_descr->flags && !pg_cache_descr->refcnt) {
179 - assert(!pg_cache_descr->waiters);
180 -
181 - descr->pg_cache_descr = NULL;
182 - can_free = 1;
180 + if (!pg_cache_descr->flags && !pg_cache_descr->refcnt && !pg_cache_descr->waiters) {
181 + rrdeng_destroy_pg_cache_descr(ctx, pg_cache_descr);
182 + we_freed = 1;
183 /* success */
184 continue;
185 }
@@ -188,7 +188,7 @@ void rrdeng_try_deallocate_pg_cache_descr(struct rrdengine_instance *ctx, struct
188 if (unlikely(must_unlock)) {
189 assert(0 == old_users);
190
191 - if (can_free) {
191 + if (we_freed) {
192 /* success */
193 new_state = 0;
194 } else {
@@ -198,8 +198,6 @@ void rrdeng_try_deallocate_pg_cache_descr(struct rrdengine_instance *ctx, struct
198 ret_state = ulong_compare_and_swap(&descr->pg_cache_descr_state, old_state, new_state);
199 if (old_state == ret_state) {
200 /* unlocked */
201 - if (can_free)
202 - rrdeng_destroy_pg_cache_descr(ctx, pg_cache_descr);
201 return;
202 }
203 continue; /* spin */