25
26
size_t flushes_running;
27
size_t evictions_running;
28
+ size_t cleanup_running;
29
} rrdeng_main = {
30
.thread = 0,
31
.loop = {},
33
.timer = {},
34
.flushes_running = 0,
35
.evictions_running = 0,
36
+ .cleanup_running = 0,
37
};
38
39
static void sanity_check(void)
66
// ----------------------------------------------------------------------------
67
// work request cache
68
67
-typedef void (*work_cb)(struct rrdengine_instance *ctx, void *data, struct completion *completion, uv_work_t* req);
69
+typedef void *(*work_cb)(struct rrdengine_instance *ctx, void *data, struct completion *completion, uv_work_t* req);
70
typedef void (*after_work_cb)(struct rrdengine_instance *ctx, void *data, struct completion *completion, uv_work_t* req, int status);
71
72
struct rrdeng_work {
142
netdata_spinlock_unlock(&work_request_globals.protected.spinlock);
143
}
144
143
-void work_standard_worker(uv_work_t *req) {
145
+static void work_standard_worker(uv_work_t *req) {
146
__atomic_add_fetch(&work_request_globals.atomics.executing, 1, __ATOMIC_RELAXED);
147
148
register_libuv_worker_jobs();
149
worker_is_busy(UV_EVENT_WORKER_INIT);
150
151
struct rrdeng_work *work_request = req->data;
150
- work_request->work_cb(work_request->ctx, work_request->data, work_request->completion, req);
152
+ work_request->data = work_request->work_cb(work_request->ctx, work_request->data, work_request->completion, req);
153
worker_is_idle();
154
155
__atomic_sub_fetch(&work_request_globals.atomics.dispatched, 1, __ATOMIC_RELAXED);
160
fatal_assert(0 == uv_async_send(&rrdeng_main.async));
161
}
162
161
-void after_work_standard_callback(uv_work_t* req, int status) {
163
+static void after_work_standard_callback(uv_work_t* req, int status) {
164
struct rrdeng_work *work_request = req->data;
165
166
worker_is_busy(RRDENG_OPCODE_MAX + work_request->opcode);
612
priority = STORAGE_PRIORITY_BEST_EFFORT;
613
614
switch(opcode) {
613
- case RRDENG_OPCODE_PREP_QUERY:
615
+ case RRDENG_OPCODE_QUERY:
616
priority = STORAGE_PRIORITY_INTERNAL_QUERY_PREP;
617
break;
618
772
freez(extent);
773
}
774
773
-static void commit_data_extent(struct rrdengine_instance *ctx, struct extent_io_descriptor *xt_io_descr) {
775
+static void journalfile_extent_build(struct rrdengine_instance *ctx, struct extent_io_descriptor *xt_io_descr) {
776
unsigned count, payload_length, descr_size, size_bytes;
777
void *buf;
778
/* persistent structures */
817
rrdeng_enq_cmd(ctx, RRDENG_OPCODE_DATABASE_ROTATE, NULL, NULL, STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL, NULL);
818
}
819
818
-static void extent_flushed_to_open_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
820
+static void *extent_flushed_to_open_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
821
worker_is_busy(UV_EVENT_FLUSHED_TO_OPEN);
822
823
uv_fs_t *uv_fs_request = data;
827
unsigned i;
828
829
if (uv_fs_request->result < 0) {
828
- __atomic_add_fetch(&ctx->stats.io_errors, 1, __ATOMIC_RELAXED);
829
- rrd_stat_atomic_add(&global_io_errors, 1);
830
+ ctx_io_error(ctx);
831
error("DBENGINE: %s: uv_fs_write: %s", __func__, uv_strerror((int)uv_fs_request->result));
832
}
833
datafile = xt_io_descr->datafile;
859
860
if(datafile->fileno != ctx_last_fileno_get(ctx) && still_running)
861
// we just finished a flushing on a datafile that is not the active one
861
- rrdeng_enq_cmd(ctx, RRDENG_OPCODE_JOURNAL_FILE_INDEX, datafile, NULL, STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL, NULL);
862
+ rrdeng_enq_cmd(ctx, RRDENG_OPCODE_JOURNAL_INDEX, datafile, NULL, STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL, NULL);
863
+
864
+ return data;
865
}
866
867
// Main event loop callback
865
-static void extent_flush_io_callback(uv_fs_t *uv_fs_request) {
866
- worker_is_busy(RRDENG_OPCODE_MAX + RRDENG_OPCODE_FLUSH_PAGES);
868
+static void after_extent_write_datafile_io(uv_fs_t *uv_fs_request) {
869
+ worker_is_busy(RRDENG_OPCODE_MAX + RRDENG_OPCODE_EXTENT_WRITE);
870
+
871
struct extent_io_descriptor *xt_io_descr = uv_fs_request->data;
872
struct rrdengine_datafile *datafile = xt_io_descr->datafile;
873
struct rrdengine_instance *ctx = datafile->ctx;
874
871
- wal_flush_transaction_buffer(ctx, xt_io_descr->datafile, xt_io_descr->wal, &rrdeng_main.loop);
875
+ journalfile_v1_extent_write(ctx, xt_io_descr->datafile, xt_io_descr->wal, &rrdeng_main.loop);
876
877
netdata_spinlock_lock(&datafile->writers.spinlock);
878
datafile->writers.running--;
875
-
879
datafile->writers.flushed_to_open_running++;
877
- rrdeng_enq_cmd(xt_io_descr->ctx, RRDENG_OPCODE_FLUSHED_TO_OPEN, uv_fs_request, xt_io_descr->completion,
878
- STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL, NULL);
879
-
880
netdata_spinlock_unlock(&datafile->writers.spinlock);
881
882
+ rrdeng_enq_cmd(xt_io_descr->ctx,
883
+ RRDENG_OPCODE_FLUSHED_TO_OPEN,
884
+ uv_fs_request,
885
+ xt_io_descr->completion,
886
+ STORAGE_PRIORITY_INTERNAL_DBENGINE,
887
+ NULL,
888
+ NULL);
889
+
890
worker_is_idle();
891
}
892
893
+static bool datafile_is_full(struct rrdengine_instance *ctx, struct rrdengine_datafile *datafile) {
894
+ bool ret = false;
895
+ netdata_spinlock_lock(&datafile->writers.spinlock);
896
+
897
+ if(ctx_is_available_for_queries(ctx) && datafile->pos > rrdeng_target_data_file_size(ctx))
898
+ ret = true;
899
+
900
+ netdata_spinlock_unlock(&datafile->writers.spinlock);
901
+
902
+ return ret;
903
+}
904
+
905
+static struct rrdengine_datafile *get_datafile_to_write_extent(struct rrdengine_instance *ctx) {
906
+ struct rrdengine_datafile *datafile;
907
+
908
+ // get the latest datafile
909
+ uv_rwlock_rdlock(&ctx->datafiles.rwlock);
910
+ datafile = ctx->datafiles.first->prev;
911
+ // become a writer on this datafile, to prevent it from vanishing
912
+ netdata_spinlock_lock(&datafile->writers.spinlock);
913
+ datafile->writers.running++;
914
+ netdata_spinlock_unlock(&datafile->writers.spinlock);
915
+ uv_rwlock_rdunlock(&ctx->datafiles.rwlock);
916
+
917
+ if(datafile_is_full(ctx, datafile)) {
918
+ // remember the datafile we have become writers to
919
+ struct rrdengine_datafile *old_datafile = datafile;
920
+
921
+ // only 1 datafile creation at a time
922
+ static netdata_mutex_t mutex = NETDATA_MUTEX_INITIALIZER;
923
+ netdata_mutex_lock(&mutex);
924
+
925
+ // take the latest datafile again - without this, multiple threads may create multiple files
926
+ uv_rwlock_rdlock(&ctx->datafiles.rwlock);
927
+ datafile = ctx->datafiles.first->prev;
928
+ uv_rwlock_rdunlock(&ctx->datafiles.rwlock);
929
+
930
+ if(datafile_is_full(ctx, datafile) && create_new_datafile_pair(ctx) == 0)
931
+ rrdeng_enq_cmd(ctx, RRDENG_OPCODE_JOURNAL_INDEX, datafile, NULL, STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL,
932
+ NULL);
933
+
934
+ netdata_mutex_unlock(&mutex);
935
+
936
+ // get the new latest datafile again, like above
937
+ uv_rwlock_rdlock(&ctx->datafiles.rwlock);
938
+ datafile = ctx->datafiles.first->prev;
939
+ // become a writer on this datafile, to prevent it from vanishing
940
+ netdata_spinlock_lock(&datafile->writers.spinlock);
941
+ datafile->writers.running++;
942
+ netdata_spinlock_unlock(&datafile->writers.spinlock);
943
+ uv_rwlock_rdunlock(&ctx->datafiles.rwlock);
944
+
945
+ // release the writers on the old datafile
946
+ netdata_spinlock_lock(&old_datafile->writers.spinlock);
947
+ old_datafile->writers.running--;
948
+ netdata_spinlock_unlock(&old_datafile->writers.spinlock);
949
+ }
950
+
951
+ return datafile;
952
+}
953
+
954
/*
955
* Take a page list in a judy array and write them
956
*/
888
-static unsigned do_flush_extent(struct rrdengine_instance *ctx, struct page_descr_with_data *base, struct completion *completion) {
957
+static struct extent_io_descriptor *datafile_extent_build(struct rrdengine_instance *ctx, struct page_descr_with_data *base, struct completion *completion) {
958
int ret;
959
int compressed_size, max_compressed_size = 0;
960
unsigned i, count, size_bytes, pos, real_io_size;
985
completion_mark_complete(completion);
986
987
__atomic_sub_fetch(&ctx->atomic.extents_currently_being_flushed, 1, __ATOMIC_RELAXED);
919
- return 0;
988
+ return NULL;
989
}
990
991
xt_io_descr = extent_io_descriptor_get();
1035
pos += descr->page_length;
1036
}
1037
969
- switch (compression_algorithm) {
970
- case RRD_NO_COMPRESSION:
971
- header->payload_length = uncompressed_payload_length;
972
- break;
973
- default: /* Compress */
974
- compressed_size = LZ4_compress_default(xt_io_descr->buf + payload_offset, compressed_buf,
975
- uncompressed_payload_length, max_compressed_size);
976
- ctx->stats.before_compress_bytes += uncompressed_payload_length;
977
- ctx->stats.after_compress_bytes += compressed_size;
978
- debug(D_RRDENGINE, "LZ4 compressed %"PRIu32" bytes to %d bytes.", uncompressed_payload_length, compressed_size);
979
- (void) memcpy(xt_io_descr->buf + payload_offset, compressed_buf, compressed_size);
980
- extent_buffer_release(eb);
981
- size_bytes = payload_offset + compressed_size + sizeof(*trailer);
982
- header->payload_length = compressed_size;
983
- break;
984
- }
1038
+ if(likely(compression_algorithm == RRD_LZ4)) {
1039
+ compressed_size = LZ4_compress_default(
1040
+ xt_io_descr->buf + payload_offset,
1041
+ compressed_buf,
1042
+ (int)uncompressed_payload_length,
1043
+ max_compressed_size);
1044
986
- // get the latest datafile
987
- uv_rwlock_rdlock(&ctx->datafiles.rwlock);
988
- datafile = ctx->datafiles.first->prev;
989
- netdata_spinlock_lock(&datafile->writers.spinlock);
990
- uv_rwlock_rdunlock(&ctx->datafiles.rwlock);
991
-
992
- if(ctx_is_available_for_queries(ctx) && datafile->pos > rrdeng_target_data_file_size(ctx)) {
993
- static SPINLOCK sp = NETDATA_SPINLOCK_INITIALIZER;
994
- netdata_spinlock_lock(&sp);
995
- if(create_new_datafile_pair(ctx) == 0)
996
- rrdeng_enq_cmd(ctx, RRDENG_OPCODE_JOURNAL_FILE_INDEX, datafile, NULL, STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL,
997
- NULL);
998
- netdata_spinlock_unlock(&sp);
1045
+ __atomic_add_fetch(&ctx->stats.before_compress_bytes, uncompressed_payload_length, __ATOMIC_RELAXED);
1046
+ __atomic_add_fetch(&ctx->stats.after_compress_bytes, compressed_size, __ATOMIC_RELAXED);
1047
1000
- // unlock the old datafile
1001
- netdata_spinlock_unlock(&datafile->writers.spinlock);
1002
-
1003
- // get the new datafile
1004
- uv_rwlock_rdlock(&ctx->datafiles.rwlock);
1005
- datafile = ctx->datafiles.first->prev;
1006
- netdata_spinlock_lock(&datafile->writers.spinlock);
1007
- uv_rwlock_rdunlock(&ctx->datafiles.rwlock);
1048
+ (void) memcpy(xt_io_descr->buf + payload_offset, compressed_buf, compressed_size);
1049
+ extent_buffer_release(eb);
1050
+ size_bytes = payload_offset + compressed_size + sizeof(*trailer);
1051
+ header->payload_length = compressed_size;
1052
+ }
1053
+ else { // RRD_NO_COMPRESSION
1054
+ header->payload_length = uncompressed_payload_length;
1055
}
1056
1010
- datafile->writers.running++;
1057
+ real_io_size = ALIGN_BYTES_CEILING(size_bytes);
1058
1059
+ datafile = get_datafile_to_write_extent(ctx);
1060
+ netdata_spinlock_lock(&datafile->writers.spinlock);
1061
xt_io_descr->datafile = datafile;
1013
- xt_io_descr->bytes = size_bytes;
1062
xt_io_descr->pos = datafile->pos;
1063
+ datafile->pos += real_io_size;
1064
+ netdata_spinlock_unlock(&datafile->writers.spinlock);
1065
+
1066
+ xt_io_descr->bytes = size_bytes;
1067
xt_io_descr->uv_fs_request.data = xt_io_descr;
1068
xt_io_descr->completion = completion;
1069
1072
crc = crc32(crc, xt_io_descr->buf, size_bytes - sizeof(*trailer));
1073
crc32set(trailer->checksum, crc);
1074
1023
- real_io_size = ALIGN_BYTES_CEILING(size_bytes);
1075
xt_io_descr->iov = uv_buf_init((void *)xt_io_descr->buf, real_io_size);
1076
+ journalfile_extent_build(ctx, xt_io_descr);
1077
1026
- ctx->stats.io_write_bytes += real_io_size;
1027
- ++ctx->stats.io_write_requests;
1028
- ctx->stats.io_write_extent_bytes += real_io_size;
1029
- ++ctx->stats.io_write_extents;
1030
- commit_data_extent(ctx, xt_io_descr);
1031
- datafile->pos += real_io_size;
1032
- ctx_current_disk_space_increase(ctx, real_io_size);
1078
ctx_last_flush_fileno_set(ctx, datafile->fileno);
1079
+ ctx_current_disk_space_increase(ctx, real_io_size);
1080
+ ctx_io_write_op_bytes(ctx, real_io_size);
1081
1035
- ret = uv_fs_write(&rrdeng_main.loop, &xt_io_descr->uv_fs_request, datafile->file, &xt_io_descr->iov,
1036
- 1, xt_io_descr->pos, extent_flush_io_callback);
1082
+ return xt_io_descr;
1083
+}
1084
1038
- fatal_assert(-1 != ret);
1085
+static void after_extent_write(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t* uv_work_req __maybe_unused, int status __maybe_unused) {
1086
+ struct extent_io_descriptor *xt_io_descr = data;
1087
1040
- netdata_spinlock_unlock(&datafile->writers.spinlock);
1088
+ if(xt_io_descr) {
1089
+ int ret = uv_fs_write(&rrdeng_main.loop,
1090
+ &xt_io_descr->uv_fs_request,
1091
+ xt_io_descr->datafile->file,
1092
+ &xt_io_descr->iov,
1093
+ 1,
1094
+ (int64_t) xt_io_descr->pos,
1095
+ after_extent_write_datafile_io);
1096
1042
- return real_io_size;
1097
+ fatal_assert(-1 != ret);
1098
+ }
1099
+}
1100
+
1101
+static void *extent_write_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1102
+ worker_is_busy(UV_EVENT_FLUSH_PAGES);
1103
+ struct page_descr_with_data *base = data;
1104
+ struct extent_io_descriptor *xt_io_descr = datafile_extent_build(ctx, base, completion);
1105
+ return xt_io_descr;
1106
}
1107
1108
static void after_database_rotate(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t* req __maybe_unused, int status __maybe_unused) {
1318
1319
journal_file = datafile->journalfile;
1320
datafile_bytes = datafile->pos;
1258
- journal_file_bytes = journal_file->pos;
1321
+ journal_file_bytes = journalfile_current_size(journal_file);
1322
deleted_bytes = journalfile_v2_data_size_get(journal_file);
1323
1324
info("DBENGINE: deleting data and journal files to maintain disk quota");
1348
rrdcontext_db_rotation();
1349
}
1350
1288
-static void database_rotate_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1351
+static void *database_rotate_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1352
datafile_delete(ctx, ctx->datafiles.first, true);
1353
+ return data;
1354
}
1355
1356
static void after_flush_all_hot_and_dirty_pages_of_section(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t* req __maybe_unused, int status __maybe_unused) {
1357
;
1358
}
1359
1296
-static void flush_all_hot_and_dirty_pages_of_section_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1360
+static void *flush_all_hot_and_dirty_pages_of_section_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1361
+ worker_is_busy(UV_EVENT_QUIESCE);
1362
pgc_flush_all_hot_and_dirty_pages(main_cache, (Word_t)ctx);
1363
completion_mark_complete(&ctx->quiesce.completion);
1364
+ return data;
1365
}
1366
1367
static void after_populate_mrg(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t* req __maybe_unused, int status __maybe_unused) {
1368
;
1369
}
1370
1305
-static void populate_mrg_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1371
+static void *populate_mrg_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1372
+ worker_is_busy(UV_EVENT_POPULATE_MRG);
1373
+
1374
do {
1375
struct rrdengine_datafile *datafile = NULL;
1376
1400
} while(1);
1401
1402
completion_mark_complete(completion);
1403
+
1404
+ return data;
1405
}
1406
1407
static void after_ctx_shutdown(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t* req __maybe_unused, int status __maybe_unused) {
1408
;
1409
}
1410
1341
-static void ctx_shutdown_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1411
+static void *ctx_shutdown_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1412
+ worker_is_busy(UV_EVENT_SHUTDOWN);
1413
+
1414
completion_wait_for(&ctx->quiesce.completion);
1415
completion_destroy(&ctx->quiesce.completion);
1416
1419
sleep_usec(1 * USEC_PER_MS);
1420
1421
completion_mark_complete(completion);
1422
+
1423
+ return data;
1424
}
1425
1352
-static void cache_flush_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1426
+static void *cache_flush_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1427
if (!main_cache)
1354
- return;
1428
+ return data;
1429
1430
worker_is_busy(UV_EVENT_FLUSH_MAIN);
1431
pgc_flush_pages(main_cache, 0);
1432
+
1433
+ return data;
1434
}
1435
1360
-static void cache_evict_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *req __maybe_unused) {
1436
+static void *cache_evict_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *req __maybe_unused) {
1437
if (!main_cache)
1362
- return;
1438
+ return data;
1439
1440
worker_is_busy(UV_EVENT_EVICT_MAIN);
1441
pgc_evict_pages(main_cache, 0, 0);
1442
+
1443
+ return data;
1444
}
1445
1446
static void after_prep_query(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t* req __maybe_unused, int status __maybe_unused) {
1447
;
1448
}
1449
1372
-static void query_prep_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *req __maybe_unused) {
1450
+static void *query_prep_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *req __maybe_unused) {
1451
worker_is_busy(UV_EVENT_PREP_QUERY);
1452
PDC *pdc = data;
1453
rrdeng_prep_query(pdc);
1454
+ return data;
1455
}
1456
1457
unsigned rrdeng_target_data_file_size(struct rrdengine_instance *ctx) {
1490
#define TIMER_PERIOD_MS (1000)
1491
1492
1414
-static void extent_read_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1493
+static void *extent_read_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1494
EPDL *epdl = data;
1495
epdl_find_extent_and_populate_pages(ctx, epdl, true);
1496
+ return data;
1497
}
1498
1499
static void epdl_populate_pages_asynchronously(struct rrdengine_instance *ctx, EPDL *epdl, STORAGE_PRIORITY priority) {
1514
}
1515
1516
#define MAX_RETRIES_TO_START_INDEX (100)
1437
-static void journal_v2_indexing_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1517
+static void *journal_v2_indexing_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1518
unsigned count = 0;
1519
worker_is_busy(UV_EVENT_JOURNAL_INDEX_WAIT);
1520
1523
1524
if (count == MAX_RETRIES_TO_START_INDEX) {
1525
worker_is_idle();
1446
- return;
1526
+ return data;
1527
}
1528
1529
struct rrdengine_datafile *datafile = ctx->datafiles.first;
1555
internal_error(count, "DBENGINE: journal indexing done; %u files processed", count);
1556
1557
worker_is_idle();
1558
+
1559
+ return data;
1560
}
1561
1562
static void after_do_cache_flush(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t* req __maybe_unused, int status __maybe_unused) {
1595
};
1596
}
1597
1516
-void timer_cb(uv_timer_t* handle) {
1517
- worker_is_busy(RRDENG_TIMER_CB);
1518
- uv_stop(handle->loop);
1519
- uv_update_time(handle->loop);
1520
-
1521
- worker_set_metric(RRDENG_OPCODES_WAITING, (NETDATA_DOUBLE)rrdeng_cmd_globals.queue.waiting);
1522
- worker_set_metric(RRDENG_WORKS_DISPATCHED, (NETDATA_DOUBLE)__atomic_load_n(&work_request_globals.atomics.dispatched, __ATOMIC_RELAXED));
1523
- worker_set_metric(RRDENG_WORKS_EXECUTING, (NETDATA_DOUBLE)__atomic_load_n(&work_request_globals.atomics.executing, __ATOMIC_RELAXED));
1598
+static void after_cleanup(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t* req __maybe_unused, int status __maybe_unused) {
1599
+ rrdeng_main.cleanup_running--;
1600
+}
1601
1525
- rrdeng_enq_cmd(NULL, RRDENG_OPCODE_FLUSH_INIT, NULL, NULL, STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL, NULL);
1526
- rrdeng_enq_cmd(NULL, RRDENG_OPCODE_EVICT_INIT, NULL, NULL, STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL, NULL);
1602
+static void *cleanup_tp_worker(struct rrdengine_instance *ctx __maybe_unused, void *data __maybe_unused, struct completion *completion __maybe_unused, uv_work_t *uv_work_req __maybe_unused) {
1603
+ worker_is_busy(UV_EVENT_BUFFERS_CLEANUP);
1604
1605
rrdeng_cmd_cleanup1();
1606
work_request_cleanup1();
1627
julyl_cleanup1();
1628
#endif
1629
1630
+ return data;
1631
+}
1632
+
1633
+void timer_cb(uv_timer_t* handle) {
1634
+ worker_is_busy(RRDENG_TIMER_CB);
1635
+ uv_stop(handle->loop);
1636
+ uv_update_time(handle->loop);
1637
+
1638
+ worker_set_metric(RRDENG_OPCODES_WAITING, (NETDATA_DOUBLE)rrdeng_cmd_globals.queue.waiting);
1639
+ worker_set_metric(RRDENG_WORKS_DISPATCHED, (NETDATA_DOUBLE)__atomic_load_n(&work_request_globals.atomics.dispatched, __ATOMIC_RELAXED));
1640
+ worker_set_metric(RRDENG_WORKS_EXECUTING, (NETDATA_DOUBLE)__atomic_load_n(&work_request_globals.atomics.executing, __ATOMIC_RELAXED));
1641
+
1642
+ rrdeng_enq_cmd(NULL, RRDENG_OPCODE_FLUSH_INIT, NULL, NULL, STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL, NULL);
1643
+ rrdeng_enq_cmd(NULL, RRDENG_OPCODE_EVICT_INIT, NULL, NULL, STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL, NULL);
1644
+ rrdeng_enq_cmd(NULL, RRDENG_OPCODE_CLEANUP, NULL, NULL, STORAGE_PRIORITY_INTERNAL_DBENGINE, NULL, NULL);
1645
+
1646
worker_is_idle();
1647
}
1648
1686
void dbengine_event_loop(void* arg) {
1687
sanity_check();
1688
uv_thread_set_name_np(pthread_self(), "DBENGINE");
1689
+ service_register(SERVICE_THREAD_TYPE_EVENT_LOOP, NULL, NULL, NULL, true);
1690
1691
worker_register("DBENGINE");
1692
1693
// opcode jobs
1694
worker_register_job_name(RRDENG_OPCODE_NOOP, "noop");
1695
1696
+ worker_register_job_name(RRDENG_OPCODE_QUERY, "query");
1697
+ worker_register_job_name(RRDENG_OPCODE_EXTENT_WRITE, "extent write");
1698
worker_register_job_name(RRDENG_OPCODE_EXTENT_READ, "extent read");
1603
- worker_register_job_name(RRDENG_OPCODE_PREP_QUERY, "prep query");
1604
- worker_register_job_name(RRDENG_OPCODE_FLUSH_PAGES, "flush pages");
1699
worker_register_job_name(RRDENG_OPCODE_FLUSHED_TO_OPEN, "flushed to open");
1700
+ worker_register_job_name(RRDENG_OPCODE_DATABASE_ROTATE, "db rotate");
1701
+ worker_register_job_name(RRDENG_OPCODE_JOURNAL_INDEX, "journal index");
1702
worker_register_job_name(RRDENG_OPCODE_FLUSH_INIT, "flush init");
1703
worker_register_job_name(RRDENG_OPCODE_EVICT_INIT, "evict init");
1608
- //worker_register_job_name(RRDENG_OPCODE_DATAFILE_CREATE, "datafile create");
1609
- worker_register_job_name(RRDENG_OPCODE_JOURNAL_FILE_INDEX, "journal file index");
1610
- worker_register_job_name(RRDENG_OPCODE_DATABASE_ROTATE, "db rotate");
1704
worker_register_job_name(RRDENG_OPCODE_CTX_SHUTDOWN, "ctx shutdown");
1705
worker_register_job_name(RRDENG_OPCODE_CTX_QUIESCE, "ctx quiesce");
1706
1707
worker_register_job_name(RRDENG_OPCODE_MAX, "get opcode");
1708
1709
+ worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_QUERY, "query cb");
1710
+ worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_EXTENT_WRITE, "extent write cb");
1711
worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_EXTENT_READ, "extent read cb");
1617
- worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_PREP_QUERY, "prep query cb");
1618
- worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_FLUSH_PAGES, "flush pages cb");
1712
worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_FLUSHED_TO_OPEN, "flushed to open cb");
1713
+ worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_DATABASE_ROTATE, "db rotate cb");
1714
+ worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_JOURNAL_INDEX, "journal index cb");
1715
worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_FLUSH_INIT, "flush init cb");
1716
worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_EVICT_INIT, "evict init cb");
1622
- //worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_DATAFILE_CREATE, "datafile create cb");
1623
- worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_JOURNAL_FILE_INDEX, "journal file index cb");
1624
- worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_DATABASE_ROTATE, "db rotate cb");
1717
worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_CTX_SHUTDOWN, "ctx shutdown cb");
1718
worker_register_job_name(RRDENG_OPCODE_MAX + RRDENG_OPCODE_CTX_QUIESCE, "ctx quiesce cb");
1719
1755
break;
1756
}
1757
1666
- case RRDENG_OPCODE_PREP_QUERY: {
1758
+ case RRDENG_OPCODE_QUERY: {
1759
struct rrdengine_instance *ctx = cmd.ctx;
1760
PDC *pdc = cmd.data;
1761
work_dispatch(ctx, pdc, NULL, opcode, query_prep_tp_worker, after_prep_query);
1762
break;
1763
}
1764
1673
- case RRDENG_OPCODE_FLUSH_PAGES: {
1765
+ case RRDENG_OPCODE_EXTENT_WRITE: {
1766
struct rrdengine_instance *ctx = cmd.ctx;
1767
struct page_descr_with_data *base = cmd.data;
1768
struct completion *completion = cmd.completion; // optional
1677
- // for the datafile and the journalfile
1678
- do_flush_extent(ctx, base, completion);
1769
+ work_dispatch(ctx, base, completion, opcode, extent_write_tp_worker, after_extent_write);
1770
break;
1771
}
1772
1795
break;
1796
}
1797
1707
-// case RRDENG_OPCODE_DATAFILE_CREATE: {
1708
-// struct rrdengine_instance *ctx = cmd.ctx;
1709
-// struct rrdengine_datafile *datafile = ctx->datafiles.first->prev;
1710
-// if(datafile->pos > rrdeng_target_data_file_size(ctx) &&
1711
-// create_new_datafile_pair(ctx, 1, ctx->last_fileno + 1) == 0) {
1712
-// ++ctx->last_fileno;
1713
-// rrdeng_enq_cmd(ctx, RRDENG_OPCODE_JOURNAL_FILE_INDEX, datafile, NULL, STORAGE_PRIORITY_CRITICAL);
1714
-// }
1715
-// break;
1716
-// }
1717
-
1718
- case RRDENG_OPCODE_JOURNAL_FILE_INDEX: {
1798
+ case RRDENG_OPCODE_CLEANUP: {
1799
+ if(!rrdeng_main.cleanup_running) {
1800
+ rrdeng_main.cleanup_running++;
1801
+ work_dispatch(NULL, NULL, NULL, opcode, cleanup_tp_worker, after_cleanup);
1802
+ }
1803
+ break;
1804
+ }
1805
+
1806
+ case RRDENG_OPCODE_JOURNAL_INDEX: {
1807
struct rrdengine_instance *ctx = cmd.ctx;
1808
struct rrdengine_datafile *datafile = cmd.data;
1809
if(!__atomic_load_n(&ctx->atomic.migration_to_v2_running, __ATOMIC_RELAXED)) {