Fix flushing error threshold (#8425)
* Fix flushing error threshold to account for inactive producers of dbengine instance * Disable page invalidation during shutdown of dbengine * Fix crash during netdata shutdown if command server has failed to initialize * Add fallback for uv_listen to retry with backlog = 1 on failure. * Adhere to the API change of libuv v1.35
Markos Fountoulakis committed
Mar 23, 2020 at 18:50 UTC
04e674fcba1d1fab1647203734f918f2cfc3904e
6 files changed
+41
-8
daemon/commands.c
+18
-2
@@ -15,6 +15,7 @@ char cmd_prefix_by_status[] = {
15
CMD_PREFIX_ERROR
16
};
17
18
+static int command_server_initialized = 0;
19
static int command_thread_error;
20
static int command_thread_shutdown;
21
static unsigned clients = 0;
@@ -496,7 +497,7 @@ static void command_thread(void *arg)
497
}
498
async.data = NULL;
499
499
- ret = uv_pipe_init(loop, &server_pipe, 1);
500
+ ret = uv_pipe_init(loop, &server_pipe, 0);
501
if (ret) {
502
error("uv_pipe_init(): %s", uv_strerror(ret));
503
command_thread_error = ret;
@@ -510,7 +511,13 @@ static void command_thread(void *arg)
511
command_thread_error = ret;
512
goto error_after_pipe_bind;
513
}
513
- if ((ret = uv_listen((uv_stream_t *)&server_pipe, SOMAXCONN, connection_cb))) {
514
+ ret = uv_listen((uv_stream_t *)&server_pipe, SOMAXCONN, connection_cb);
515
+ if (ret) {
516
+ /* Fallback to backlog of 1 */
517
+ info("uv_listen() failed with backlog = %d, falling back to backlog = 1.", SOMAXCONN);
518
+ ret = uv_listen((uv_stream_t *)&server_pipe, 1, connection_cb);
519
+ }
520
+ if (ret) {
521
error("uv_listen(): %s", uv_strerror(ret));
522
command_thread_error = ret;
523
goto error_after_uv_listen;
@@ -563,6 +570,9 @@ void commands_init(void)
570
int error;
571
572
sanity_check();
573
+ if (command_server_initialized)
574
+ return;
575
+
576
info("Initializing command server.");
577
for (i = 0 ; i < CMD_TOTAL_COMMANDS ; ++i) {
578
uv_mutex_init(&command_lock_array[i]);
@@ -587,6 +597,8 @@ void commands_init(void)
597
}
598
goto after_error;
599
}
600
+
601
+ command_server_initialized = 1;
602
return;
603
604
after_error:
@@ -597,6 +609,9 @@ void commands_exit(void)
609
{
610
cmd_t i;
611
612
+ if (!command_server_initialized)
613
+ return;
614
+
615
command_thread_shutdown = 1;
616
info("Shutting down command server.");
617
/* wake up event loop */
@@ -608,4 +623,5 @@ void commands_exit(void)
623
}
624
uv_rwlock_destroy(&exclusive_rwlock);
625
info("Command server has stopped.");
626
+ command_server_initialized = 0;
627
}
database/engine/pagecache.c
+4
-4
@@ -221,7 +221,7 @@ static void pg_cache_release_pages(struct rrdengine_instance *ctx, unsigned numb
221
unsigned long pg_cache_hard_limit(struct rrdengine_instance *ctx)
222
{
223
/* it's twice the number of producers since we pin 2 pages per producer */
224
- return ctx->max_cache_pages + 2 * (unsigned long)ctx->stats.metric_API_producers;
224
+ return ctx->max_cache_pages + 2 * (unsigned long)ctx->metric_API_max_producers;
225
}
226
227
/*
@@ -231,7 +231,7 @@ unsigned long pg_cache_hard_limit(struct rrdengine_instance *ctx)
231
unsigned long pg_cache_soft_limit(struct rrdengine_instance *ctx)
232
{
233
/* it's twice the number of producers since we pin 2 pages per producer */
234
- return ctx->cache_pages_low_watermark + 2 * (unsigned long)ctx->stats.metric_API_producers;
234
+ return ctx->cache_pages_low_watermark + 2 * (unsigned long)ctx->metric_API_max_producers;
235
}
236
237
/*
@@ -240,8 +240,8 @@ unsigned long pg_cache_soft_limit(struct rrdengine_instance *ctx)
240
*/
241
unsigned long pg_cache_committed_hard_limit(struct rrdengine_instance *ctx)
242
{
243
- /* We remove the active pages of the producers from the calculation and only allow 50% of the extra pinned pages */
244
- return ctx->cache_pages_low_watermark + (unsigned long)ctx->stats.metric_API_producers / 2;
243
+ /* We remove the active pages of the producers from the calculation and only allow the extra pinned pages */
244
+ return ctx->cache_pages_low_watermark + (unsigned long)ctx->metric_API_max_producers;
245
}
246
247
/*
database/engine/rrdengine.c
+2
-1
@@ -814,7 +814,7 @@ void timer_cb(uv_timer_t* handle)
814
uv_rwlock_rdlock(&pg_cache->committed_page_index.lock);
815
nr_committed_pages = pg_cache->committed_page_index.nr_committed_pages;
816
uv_rwlock_rdunlock(&pg_cache->committed_page_index.lock);
817
- producers = ctx->stats.metric_API_producers;
817
+ producers = ctx->metric_API_max_producers;
818
/* are flushable pages more than 25% of the maximum page cache size */
819
high_watermark = (ctx->max_cache_pages * 25LLU) / 100;
820
low_watermark = (ctx->max_cache_pages * 5LLU) / 100; /* 5%, must be smaller than high_watermark */
@@ -920,6 +920,7 @@ void rrdeng_worker(void* arg)
920
break;
921
case RRDENG_SHUTDOWN:
922
shutdown = 1;
923
+ ctx->drop_metrics_under_page_cache_pressure = 0;
924
break;
925
case RRDENG_READ_PAGE:
926
do_read_extent(wc, &cmd.read_page.page_cache_descr, 1, 0);
database/engine/rrdengine.h
+1
@@ -183,6 +183,7 @@ struct rrdengine_instance {
183
unsigned last_fileno; /* newest index of datafile and journalfile */
184
unsigned long max_cache_pages;
185
unsigned long cache_pages_low_watermark;
186
+ unsigned long metric_API_max_producers;
187
188
struct rrdengine_statistics stats;
189
};
database/engine/rrdengineapi.c
+14
-1
@@ -189,9 +189,21 @@ void rrdeng_store_metric_next(RRDDIM *rd, usec_t point_in_time, storage_number n
189
if (perfect_page_alignment)
190
rd->rrdset->rrddim_page_alignment = descr->page_length;
191
if (unlikely(INVALID_TIME == descr->start_time)) {
192
+ unsigned long new_metric_API_producers, old_metric_API_max_producers, ret_metric_API_max_producers;
193
descr->start_time = point_in_time;
194
194
- rrd_stat_atomic_add(&ctx->stats.metric_API_producers, 1);
195
+ new_metric_API_producers = rrd_atomic_add_fetch(&ctx->stats.metric_API_producers, 1);
196
+ while (unlikely(new_metric_API_producers > (old_metric_API_max_producers = ctx->metric_API_max_producers))) {
197
+ /* Increase ctx->metric_API_max_producers */
198
+ ret_metric_API_max_producers = ulong_compare_and_swap(&ctx->metric_API_max_producers,
199
+ old_metric_API_max_producers,
200
+ new_metric_API_producers);
201
+ if (old_metric_API_max_producers == ret_metric_API_max_producers) {
202
+ /* success */
203
+ break;
204
+ }
205
+ }
206
+
207
pg_cache_insert(ctx, handle->page_index, descr);
208
} else {
209
pg_cache_add_new_metric_time(handle->page_index, descr);
@@ -791,6 +803,7 @@ int rrdeng_init(struct rrdengine_instance **ctxp, char *dbfiles_path, unsigned p
803
strncpyz(ctx->dbfiles_path, dbfiles_path, sizeof(ctx->dbfiles_path) - 1);
804
ctx->dbfiles_path[sizeof(ctx->dbfiles_path) - 1] = '\0';
805
ctx->drop_metrics_under_page_cache_pressure = rrdeng_drop_metrics_under_page_cache_pressure;
806
+ ctx->metric_API_max_producers = 0;
807
808
memset(&ctx->worker_config, 0, sizeof(ctx->worker_config));
809
ctx->worker_config.ctx = ctx;
database/engine/rrdenginelib.h
+2
@@ -28,8 +28,10 @@ typedef uintptr_t rrdeng_stats_t;
28
29
#ifdef __ATOMIC_RELAXED
30
#define rrd_atomic_fetch_add(p, n) __atomic_fetch_add(p, n, __ATOMIC_RELAXED)
31
+#define rrd_atomic_add_fetch(p, n) __atomic_add_fetch(p, n, __ATOMIC_RELAXED)
32
#else
33
#define rrd_atomic_fetch_add(p, n) __sync_fetch_and_add(p, n)
34
+#define rrd_atomic_add_fetch(p, n) __sync_add_and_fetch(p, n)
35
#endif
36
37
#define rrd_stat_atomic_add(p, n) rrd_atomic_fetch_add(p, n)