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