From 0d61c11b5f4772a4762ede1d8204290b94bb08e7 Mon Sep 17 00:00:00 2001 From: Costa Tsaousis Date: Mon, 26 Jun 2023 14:00:59 +0300 Subject: use gperf for the pluginsd/streaming parser hashtable (#15251) * use gperf for the pluginsd parser * simplify pluginsd_parser by removing void pointers to user * pluginsd_split_words() with inlined pluginsd_space() * quoted_string_splitter() now uses a map instead of a function for determining spaces * add stress test for pluginsd parser * optimized BITMAP256 * optimized rrdpush receiver reception * optimized rrdpush sender compression * renames and cleanup * remove wrong negation * unify handshake and disconnection reasons * use parser_find_keyword * register job names only for the current repertoire --- CMakeLists.txt | 2 - Makefile.am | 3 +- collectors/apps.plugin/apps_plugin.c | 4 +- collectors/plugins.d/Makefile.am | 1 + collectors/plugins.d/gperf-config.txt | 43 ++ collectors/plugins.d/gperf-hashtable.h | 164 ++++++ collectors/plugins.d/plugins_d.c | 2 +- collectors/plugins.d/pluginsd_parser.c | 921 +++++++++++++++++---------------- collectors/plugins.d/pluginsd_parser.h | 165 +++++- collectors/statsd.plugin/statsd.c | 2 +- configure.ac | 1 - daemon/main.c | 8 +- database/contexts/api_v2.c | 11 +- database/rrd.h | 2 +- database/rrdfunctions.c | 10 +- database/rrdhost.c | 23 +- libnetdata/Makefile.am | 1 - libnetdata/libnetdata.c | 108 +--- libnetdata/libnetdata.h | 119 ++++- libnetdata/parser/Makefile.am | 9 - libnetdata/parser/README.md | 28 - libnetdata/parser/parser.c | 277 ---------- libnetdata/parser/parser.h | 105 ---- streaming/compression.c | 299 +++-------- streaming/receiver.c | 231 ++++----- streaming/rrdpush.c | 24 +- streaming/rrdpush.h | 131 ++++- streaming/sender.c | 66 ++- web/api/queries/query.c | 11 +- 29 files changed, 1321 insertions(+), 1450 deletions(-) create mode 100644 collectors/plugins.d/gperf-config.txt create mode 100644 collectors/plugins.d/gperf-hashtable.h delete mode 100644 libnetdata/parser/Makefile.am delete mode 100644 libnetdata/parser/README.md delete mode 100644 libnetdata/parser/parser.c delete mode 100644 libnetdata/parser/parser.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 34c381619a..dffd58875d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -491,8 +491,6 @@ set(LIBNETDATA_FILES libnetdata/string/utf8.h libnetdata/worker_utilization/worker_utilization.c libnetdata/worker_utilization/worker_utilization.h - libnetdata/parser/parser.h - libnetdata/parser/parser.c libnetdata/http/http_defs.h ) diff --git a/Makefile.am b/Makefile.am index 510fbb3e55..2a656eb420 100644 --- a/Makefile.am +++ b/Makefile.am @@ -168,8 +168,6 @@ LIBNETDATA_FILES = \ libnetdata/log/log.h \ libnetdata/onewayalloc/onewayalloc.c \ libnetdata/onewayalloc/onewayalloc.h \ - libnetdata/parser/parser.c \ - libnetdata/parser/parser.h \ libnetdata/popen/popen.c \ libnetdata/popen/popen.h \ libnetdata/procfile/procfile.c \ @@ -425,6 +423,7 @@ PLUGINSD_PLUGIN_FILES = \ collectors/plugins.d/plugins_d.h \ collectors/plugins.d/pluginsd_parser.c \ collectors/plugins.d/pluginsd_parser.h \ + collectors/plugins.d/gperf-hashtable.h \ $(NULL) RRD_PLUGIN_FILES = \ diff --git a/collectors/apps.plugin/apps_plugin.c b/collectors/apps.plugin/apps_plugin.c index 47c5ee53be..39023c2286 100644 --- a/collectors/apps.plugin/apps_plugin.c +++ b/collectors/apps.plugin/apps_plugin.c @@ -4372,7 +4372,7 @@ static void apps_plugin_function_processes(const char *transaction, char *functi struct pid_stat *p; char *words[PLUGINSD_MAX_WORDS] = { NULL }; - size_t num_words = pluginsd_split_words(function, words, PLUGINSD_MAX_WORDS); + size_t num_words = quoted_strings_splitter_pluginsd(function, words, PLUGINSD_MAX_WORDS); struct target *category = NULL, *user = NULL, *group = NULL; const char *process_name = NULL; @@ -5219,7 +5219,7 @@ void *reader_main(void *arg __maybe_unused) { while(!apps_plugin_exit && (s = fgets(buffer, PLUGINSD_LINE_MAX, stdin))) { char *words[PLUGINSD_MAX_WORDS] = { NULL }; - size_t num_words = pluginsd_split_words(buffer, words, PLUGINSD_MAX_WORDS); + size_t num_words = quoted_strings_splitter_pluginsd(buffer, words, PLUGINSD_MAX_WORDS); const char *keyword = get_word(words, num_words, 0); diff --git a/collectors/plugins.d/Makefile.am b/collectors/plugins.d/Makefile.am index 59250a997e..67fed309d5 100644 --- a/collectors/plugins.d/Makefile.am +++ b/collectors/plugins.d/Makefile.am @@ -7,5 +7,6 @@ SUBDIRS = \ $(NULL) dist_noinst_DATA = \ + gperf-config.txt \ README.md \ $(NULL) diff --git a/collectors/plugins.d/gperf-config.txt b/collectors/plugins.d/gperf-config.txt new file mode 100644 index 0000000000..490a20fc1c --- /dev/null +++ b/collectors/plugins.d/gperf-config.txt @@ -0,0 +1,43 @@ +PARSER_KEYWORD; +%% +# +# Plugins Only Keywords +# +FLUSH, pluginsd_flush, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 1 +DISABLE, pluginsd_disable, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 2 +EXIT, pluginsd_exit, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 3 +HOST, pluginsd_host, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 4 +HOST_DEFINE, pluginsd_host_define, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 5 +HOST_DEFINE_END, pluginsd_host_define_end, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 6 +HOST_LABEL, pluginsd_host_labels, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 7 +# +# Common keywords +# +BEGIN, pluginsd_begin, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 8 +CHART, pluginsd_chart, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 9 +CLABEL, pluginsd_clabel, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 10 +CLABEL_COMMIT, pluginsd_clabel_commit, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 11 +DIMENSION, pluginsd_dimension, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 12 +END, pluginsd_end, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 13 +FUNCTION, pluginsd_function, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 14 +FUNCTION_RESULT_BEGIN, pluginsd_function_result_begin, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 15 +LABEL, pluginsd_label, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 16 +OVERWRITE, pluginsd_overwrite, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 17 +SET, pluginsd_set, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 18 +VARIABLE, pluginsd_variable, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 19 +# +# Streaming only keywords +# +CLAIMED_ID, streaming_claimed_id, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 20 +BEGIN2, pluginsd_begin_v2, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 21 +SET2, pluginsd_set_v2, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 22 +END2, pluginsd_end_v2, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 23 +# +# Streaming Replication keywords +# +CHART_DEFINITION_END, pluginsd_chart_definition_end, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 24 +RBEGIN, pluginsd_replay_begin, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 25 +RDSTATE, pluginsd_replay_rrddim_collection_state, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 26 +REND, pluginsd_replay_end, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 27 +RSET, pluginsd_replay_set, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 28 +RSSTATE, pluginsd_replay_rrdset_collection_state, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 29 diff --git a/collectors/plugins.d/gperf-hashtable.h b/collectors/plugins.d/gperf-hashtable.h new file mode 100644 index 0000000000..1c4550ee89 --- /dev/null +++ b/collectors/plugins.d/gperf-hashtable.h @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: gperf --multiple-iterations=1000 --hash-function-name=gperf_keyword_hash_function --lookup-function-name=gperf_lookup_keyword --word-array-name=gperf_keywords --constants-prefix=GPERF_PARSER_ --struct-type --slot-name=keyword --global-table --null-strings --omit-struct-type --output-file=gperf-hashtable.h gperf-config.txt */ +/* Computed positions: -k'1-2' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + + +#define GPERF_PARSER_TOTAL_KEYWORDS 29 +#define GPERF_PARSER_MIN_WORD_LENGTH 3 +#define GPERF_PARSER_MAX_WORD_LENGTH 21 +#define GPERF_PARSER_MIN_HASH_VALUE 4 +#define GPERF_PARSER_MAX_HASH_VALUE 36 +/* maximum key range = 33, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +gperf_keyword_hash_function (register const char *str, register size_t len) +{ + static unsigned char asso_values[] = + { + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 15, 10, 1, 1, 9, + 4, 37, 0, 20, 37, 37, 9, 37, 14, 0, + 37, 37, 1, 0, 37, 7, 13, 37, 18, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37 + }; + return len + asso_values[(unsigned char)str[1]] + asso_values[(unsigned char)str[0]]; +} + +static PARSER_KEYWORD gperf_keywords[] = + { + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 9 "gperf-config.txt" + {"HOST", pluginsd_host, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 4}, +#line 42 "gperf-config.txt" + {"RSET", pluginsd_replay_set, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 28}, +#line 17 "gperf-config.txt" + {"CHART", pluginsd_chart, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 9}, + {(char*)0}, +#line 43 "gperf-config.txt" + {"RSSTATE", pluginsd_replay_rrdset_collection_state, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 29}, +#line 40 "gperf-config.txt" + {"RDSTATE", pluginsd_replay_rrddim_collection_state, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 26}, +#line 12 "gperf-config.txt" + {"HOST_LABEL", pluginsd_host_labels, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 7}, +#line 10 "gperf-config.txt" + {"HOST_DEFINE", pluginsd_host_define, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 5}, +#line 26 "gperf-config.txt" + {"SET", pluginsd_set, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 18}, +#line 33 "gperf-config.txt" + {"SET2", pluginsd_set_v2, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 22}, +#line 41 "gperf-config.txt" + {"REND", pluginsd_replay_end, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 27}, +#line 11 "gperf-config.txt" + {"HOST_DEFINE_END", pluginsd_host_define_end, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 6}, +#line 18 "gperf-config.txt" + {"CLABEL", pluginsd_clabel, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 10}, +#line 39 "gperf-config.txt" + {"RBEGIN", pluginsd_replay_begin, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 25}, +#line 6 "gperf-config.txt" + {"FLUSH", pluginsd_flush, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 1}, +#line 22 "gperf-config.txt" + {"FUNCTION", pluginsd_function, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 14}, +#line 31 "gperf-config.txt" + {"CLAIMED_ID", streaming_claimed_id, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 20}, +#line 38 "gperf-config.txt" + {"CHART_DEFINITION_END", pluginsd_chart_definition_end, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 24}, +#line 25 "gperf-config.txt" + {"OVERWRITE", pluginsd_overwrite, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 17}, +#line 19 "gperf-config.txt" + {"CLABEL_COMMIT", pluginsd_clabel_commit, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 11}, +#line 16 "gperf-config.txt" + {"BEGIN", pluginsd_begin, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 8}, +#line 32 "gperf-config.txt" + {"BEGIN2", pluginsd_begin_v2, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 21}, +#line 21 "gperf-config.txt" + {"END", pluginsd_end, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 13}, +#line 34 "gperf-config.txt" + {"END2", pluginsd_end_v2, PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 23}, +#line 7 "gperf-config.txt" + {"DISABLE", pluginsd_disable, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 2}, +#line 24 "gperf-config.txt" + {"LABEL", pluginsd_label, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 16}, +#line 20 "gperf-config.txt" + {"DIMENSION", pluginsd_dimension, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 12}, +#line 8 "gperf-config.txt" + {"EXIT", pluginsd_exit, PARSER_INIT_PLUGINSD, WORKER_PARSER_FIRST_JOB + 3}, +#line 23 "gperf-config.txt" + {"FUNCTION_RESULT_BEGIN", pluginsd_function_result_begin, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 15}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 27 "gperf-config.txt" + {"VARIABLE", pluginsd_variable, PARSER_INIT_PLUGINSD|PARSER_INIT_STREAMING, WORKER_PARSER_FIRST_JOB + 19} + }; + +PARSER_KEYWORD * +gperf_lookup_keyword (register const char *str, register size_t len) +{ + if (len <= GPERF_PARSER_MAX_WORD_LENGTH && len >= GPERF_PARSER_MIN_WORD_LENGTH) + { + register unsigned int key = gperf_keyword_hash_function (str, len); + + if (key <= GPERF_PARSER_MAX_HASH_VALUE) + { + register const char *s = gperf_keywords[key].keyword; + + if (s && *str == *s && !strcmp (str + 1, s + 1)) + return &gperf_keywords[key]; + } + } + return 0; +} diff --git a/collectors/plugins.d/plugins_d.c b/collectors/plugins.d/plugins_d.c index d6605602f4..f3e9ff6315 100644 --- a/collectors/plugins.d/plugins_d.c +++ b/collectors/plugins.d/plugins_d.c @@ -18,7 +18,7 @@ inline size_t pluginsd_initialize_plugin_directories() } // Parse it and store it to plugin directories - return quoted_strings_splitter(plugins_dir_list, plugin_directories, PLUGINSD_MAX_DIRECTORIES, config_isspace); + return quoted_strings_splitter_config(plugins_dir_list, plugin_directories, PLUGINSD_MAX_DIRECTORIES); } static inline void plugin_set_disabled(struct plugind *cd) { diff --git a/collectors/plugins.d/pluginsd_parser.c b/collectors/plugins.d/pluginsd_parser.c index b5356b33dc..ab7b949102 100644 --- a/collectors/plugins.d/pluginsd_parser.c +++ b/collectors/plugins.d/pluginsd_parser.c @@ -68,8 +68,8 @@ static ssize_t send_to_plugin(const char *txt, void *data) { return -4; } -static inline RRDHOST *pluginsd_require_host_from_parent(void *user, const char *cmd) { - RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host; +static inline RRDHOST *pluginsd_require_host_from_parent(PARSER *parser, const char *cmd) { + RRDHOST *host = parser->user.host; if(unlikely(!host)) error("PLUGINSD: command %s requires a host, but is not set.", cmd); @@ -77,8 +77,8 @@ static inline RRDHOST *pluginsd_require_host_from_parent(void *user, const char return host; } -static inline RRDSET *pluginsd_require_chart_from_parent(void *user, const char *cmd, const char *parent_cmd) { - RRDSET *st = ((PARSER_USER_OBJECT *) user)->st; +static inline RRDSET *pluginsd_require_chart_from_parent(PARSER *parser, const char *cmd, const char *parent_cmd) { + RRDSET *st = parser->user.st; if(unlikely(!st)) error("PLUGINSD: command %s requires a chart defined via command %s, but is not set.", cmd, parent_cmd); @@ -86,23 +86,21 @@ static inline RRDSET *pluginsd_require_chart_from_parent(void *user, const char return st; } -static inline RRDSET *pluginsd_get_chart_from_parent(void *user) { - return ((PARSER_USER_OBJECT *) user)->st; +static inline RRDSET *pluginsd_get_chart_from_parent(PARSER *parser) { + return parser->user.st; } -static inline void pluginsd_lock_rrdset_data_collection(void *user) { - PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user; - if(u->st && !u->v2.locked_data_collection) { - spinlock_lock(&u->st->data_collection_lock); - u->v2.locked_data_collection = true; +static inline void pluginsd_lock_rrdset_data_collection(PARSER *parser) { + if(parser->user.st && !parser->user.v2.locked_data_collection) { + spinlock_lock(&parser->user.st->data_collection_lock); + parser->user.v2.locked_data_collection = true; } } -static inline bool pluginsd_unlock_rrdset_data_collection(void *user) { - PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user; - if(u->st && u->v2.locked_data_collection) { - spinlock_unlock(&u->st->data_collection_lock); - u->v2.locked_data_collection = false; +static inline bool pluginsd_unlock_rrdset_data_collection(PARSER *parser) { + if(parser->user.st && parser->user.v2.locked_data_collection) { + spinlock_unlock(&parser->user.st->data_collection_lock); + parser->user.v2.locked_data_collection = false; return true; } @@ -123,29 +121,25 @@ void pluginsd_rrdset_cleanup(RRDSET *st) { st->pluginsd.pos = 0; } -static inline void pluginsd_unlock_previous_chart(void *user, const char *keyword, bool stale) { - PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user; - - if(unlikely(pluginsd_unlock_rrdset_data_collection(user))) { +static inline void pluginsd_unlock_previous_chart(PARSER *parser, const char *keyword, bool stale) { + if(unlikely(pluginsd_unlock_rrdset_data_collection(parser))) { if(stale) error("PLUGINSD: 'host:%s/chart:%s/' stale data collection lock found during %s; it has been unlocked", - rrdhost_hostname(u->st->rrdhost), rrdset_id(u->st), keyword); + rrdhost_hostname(parser->user.st->rrdhost), rrdset_id(parser->user.st), keyword); } - if(unlikely(u->v2.ml_locked)) { - ml_chart_update_end(u->st); - u->v2.ml_locked = false; + if(unlikely(parser->user.v2.ml_locked)) { + ml_chart_update_end(parser->user.st); + parser->user.v2.ml_locked = false; if(stale) error("PLUGINSD: 'host:%s/chart:%s/' stale ML lock found during %s, it has been unlocked", - rrdhost_hostname(u->st->rrdhost), rrdset_id(u->st), keyword); + rrdhost_hostname(parser->user.st->rrdhost), rrdset_id(parser->user.st), keyword); } } -static inline void pluginsd_set_chart_from_parent(void *user, RRDSET *st, const char *keyword) { - PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user; - - pluginsd_unlock_previous_chart(user, keyword, true); +static inline void pluginsd_set_chart_from_parent(PARSER *parser, RRDSET *st, const char *keyword) { + pluginsd_unlock_previous_chart(parser, keyword, true); if(st) { size_t dims = dictionary_entries(st->rrddim_root_index); @@ -160,7 +154,7 @@ static inline void pluginsd_set_chart_from_parent(void *user, RRDSET *st, const st->pluginsd.pos = 0; } - u->st = st; + parser->user.st = st; } static inline RRDDIM *pluginsd_acquire_dimension(RRDHOST *host, RRDSET *st, const char *dimension, const char *cmd) { @@ -214,8 +208,8 @@ static inline RRDSET *pluginsd_find_chart(RRDHOST *host, const char *chart, cons return st; } -static inline PARSER_RC PLUGINSD_DISABLE_PLUGIN(void *user, const char *keyword, const char *msg) { - ((PARSER_USER_OBJECT *) user)->enabled = 0; +static inline PARSER_RC PLUGINSD_DISABLE_PLUGIN(PARSER *parser, const char *keyword, const char *msg) { + parser->user.enabled = 0; if(keyword && msg) { error_limit_static_global_var(erl, 1, 0); @@ -225,19 +219,18 @@ static inline PARSER_RC PLUGINSD_DISABLE_PLUGIN(void *user, const char *keyword, return PARSER_RC_ERROR; } -PARSER_RC pluginsd_set(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_set(char **words, size_t num_words, PARSER *parser) { char *dimension = get_word(words, num_words, 1); char *value = get_word(words, num_words, 2); - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_SET); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_SET); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_SET, PLUGINSD_KEYWORD_CHART); - if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDSET *st = pluginsd_require_chart_from_parent(parser, PLUGINSD_KEYWORD_SET, PLUGINSD_KEYWORD_CHART); + if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_SET); - if(!rd) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + if(!rd) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); if (unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) debug(D_PLUGINSD, "PLUGINSD: 'host:%s/chart:%s/dim:%s' SET is setting value to '%s'", @@ -249,18 +242,17 @@ PARSER_RC pluginsd_set(char **words, size_t num_words, void *user) return PARSER_RC_OK; } -PARSER_RC pluginsd_begin(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_begin(char **words, size_t num_words, PARSER *parser) { char *id = get_word(words, num_words, 1); char *microseconds_txt = get_word(words, num_words, 2); - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_BEGIN); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_BEGIN); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); RRDSET *st = pluginsd_find_chart(host, id, PLUGINSD_KEYWORD_BEGIN); - if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - pluginsd_set_chart_from_parent(user, st, PLUGINSD_KEYWORD_BEGIN); + pluginsd_set_chart_from_parent(parser, st, PLUGINSD_KEYWORD_BEGIN); usec_t microseconds = 0; if (microseconds_txt && *microseconds_txt) { @@ -285,7 +277,7 @@ PARSER_RC pluginsd_begin(char **words, size_t num_words, void *user) if (likely(st->counter_done)) { if (likely(microseconds)) { - if (((PARSER_USER_OBJECT *)user)->trust_durations) + if (parser->user.trust_durations) rrdset_next_usec_unfiltered(st, microseconds); else rrdset_next_usec(st, microseconds); @@ -296,22 +288,21 @@ PARSER_RC pluginsd_begin(char **words, size_t num_words, void *user) return PARSER_RC_OK; } -PARSER_RC pluginsd_end(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_end(char **words, size_t num_words, PARSER *parser) { UNUSED(words); UNUSED(num_words); - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_END); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_END); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_END, PLUGINSD_KEYWORD_BEGIN); - if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDSET *st = pluginsd_require_chart_from_parent(parser, PLUGINSD_KEYWORD_END, PLUGINSD_KEYWORD_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); if (unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) debug(D_PLUGINSD, "requested an END on chart '%s'", rrdset_id(st)); - pluginsd_set_chart_from_parent(user, NULL, PLUGINSD_KEYWORD_END); - ((PARSER_USER_OBJECT *) user)->data_collections_count++; + pluginsd_set_chart_from_parent(parser, NULL, PLUGINSD_KEYWORD_END); + parser->user.data_collections_count++; struct timeval now; now_realtime_timeval(&now); @@ -320,15 +311,13 @@ PARSER_RC pluginsd_end(char **words, size_t num_words, void *user) return PARSER_RC_OK; } -static void pluginsd_host_define_cleanup(void *user) { - PARSER_USER_OBJECT *u = user; - - string_freez(u->host_define.hostname); - dictionary_destroy(u->host_define.rrdlabels); +static void pluginsd_host_define_cleanup(PARSER *parser) { + string_freez(parser->user.host_define.hostname); + dictionary_destroy(parser->user.host_define.rrdlabels); - u->host_define.hostname = NULL; - u->host_define.rrdlabels = NULL; - u->host_define.parsing_host = false; + parser->user.host_define.hostname = NULL; + parser->user.host_define.rrdlabels = NULL; + parser->user.host_define.parsing_host = false; } static inline bool pluginsd_validate_machine_guid(const char *guid, uuid_t *uuid, char *output) { @@ -340,61 +329,56 @@ static inline bool pluginsd_validate_machine_guid(const char *guid, uuid_t *uuid return true; } -static PARSER_RC pluginsd_host_define(char **words, size_t num_words, void *user) { - PARSER_USER_OBJECT *u = user; - +static inline PARSER_RC pluginsd_host_define(char **words, size_t num_words, PARSER *parser) { char *guid = get_word(words, num_words, 1); char *hostname = get_word(words, num_words, 2); if(unlikely(!guid || !*guid || !hostname || !*hostname)) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_HOST_DEFINE, "missing parameters"); + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_HOST_DEFINE, "missing parameters"); - if(unlikely(u->host_define.parsing_host)) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_HOST_DEFINE, + if(unlikely(parser->user.host_define.parsing_host)) + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_HOST_DEFINE, "another host definition is already open - did you send " PLUGINSD_KEYWORD_HOST_DEFINE_END "?"); - if(!pluginsd_validate_machine_guid(guid, &u->host_define.machine_guid, u->host_define.machine_guid_str)) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_HOST_DEFINE, "cannot parse MACHINE_GUID - is it a valid UUID?"); + if(!pluginsd_validate_machine_guid(guid, &parser->user.host_define.machine_guid, parser->user.host_define.machine_guid_str)) + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_HOST_DEFINE, "cannot parse MACHINE_GUID - is it a valid UUID?"); - u->host_define.hostname = string_strdupz(hostname); - u->host_define.rrdlabels = rrdlabels_create(); - u->host_define.parsing_host = true; + parser->user.host_define.hostname = string_strdupz(hostname); + parser->user.host_define.rrdlabels = rrdlabels_create(); + parser->user.host_define.parsing_host = true; return PARSER_RC_OK; } -static inline PARSER_RC pluginsd_host_dictionary(char **words, size_t num_words, void *user, DICTIONARY *dict, const char *keyword) { - PARSER_USER_OBJECT *u = user; - +static inline PARSER_RC pluginsd_host_dictionary(char **words, size_t num_words, PARSER *parser, DICTIONARY *dict, const char *keyword) { char *name = get_word(words, num_words, 1); char *value = get_word(words, num_words, 2); if(!name || !*name || !value) - return PLUGINSD_DISABLE_PLUGIN(user, keyword, "missing parameters"); + return PLUGINSD_DISABLE_PLUGIN(parser, keyword, "missing parameters"); - if(!u->host_define.parsing_host || !dict) - return PLUGINSD_DISABLE_PLUGIN(user, keyword, "host is not defined, send " PLUGINSD_KEYWORD_HOST_DEFINE " before this"); + if(!parser->user.host_define.parsing_host || !dict) + return PLUGINSD_DISABLE_PLUGIN(parser, keyword, "host is not defined, send " PLUGINSD_KEYWORD_HOST_DEFINE " before this"); rrdlabels_add(dict, name, value, RRDLABEL_SRC_CONFIG); return PARSER_RC_OK; } -static PARSER_RC pluginsd_host_labels(char **words, size_t num_words, void *user) { - PARSER_USER_OBJECT *u = user; - return pluginsd_host_dictionary(words, num_words, user, u->host_define.rrdlabels, PLUGINSD_KEYWORD_HOST_LABEL); +static inline PARSER_RC pluginsd_host_labels(char **words, size_t num_words, PARSER *parser) { + return pluginsd_host_dictionary(words, num_words, parser, + parser->user.host_define.rrdlabels, + PLUGINSD_KEYWORD_HOST_LABEL); } -static PARSER_RC pluginsd_host_define_end(char **words __maybe_unused, size_t num_words __maybe_unused, void *user) { - PARSER_USER_OBJECT *u = user; - - if(!u->host_define.parsing_host) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_HOST_DEFINE_END, "missing initialization, send " PLUGINSD_KEYWORD_HOST_DEFINE " before this"); +static inline PARSER_RC pluginsd_host_define_end(char **words __maybe_unused, size_t num_words __maybe_unused, PARSER *parser) { + if(!parser->user.host_define.parsing_host) + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_HOST_DEFINE_END, "missing initialization, send " PLUGINSD_KEYWORD_HOST_DEFINE " before this"); RRDHOST *host = rrdhost_find_or_create( - string2str(u->host_define.hostname), - string2str(u->host_define.hostname), - u->host_define.machine_guid_str, + string2str(parser->user.host_define.hostname), + string2str(parser->user.host_define.hostname), + parser->user.host_define.machine_guid_str, "Netdata Virtual Host 1.0", netdata_configured_timezone, netdata_configured_abbrev_timezone, @@ -413,24 +397,24 @@ static PARSER_RC pluginsd_host_define_end(char **words __maybe_unused, size_t nu default_rrdpush_enable_replication, default_rrdpush_seconds_to_replicate, default_rrdpush_replication_step, - rrdhost_labels_to_system_info(u->host_define.rrdlabels), + rrdhost_labels_to_system_info(parser->user.host_define.rrdlabels), false ); rrdhost_option_set(host, RRDHOST_OPTION_VIRTUAL_HOST); if(host->rrdlabels) { - rrdlabels_migrate_to_these(host->rrdlabels, u->host_define.rrdlabels); + rrdlabels_migrate_to_these(host->rrdlabels, parser->user.host_define.rrdlabels); } else { - host->rrdlabels = u->host_define.rrdlabels; - u->host_define.rrdlabels = NULL; + host->rrdlabels = parser->user.host_define.rrdlabels; + parser->user.host_define.rrdlabels = NULL; } - pluginsd_host_define_cleanup(user); + pluginsd_host_define_cleanup(parser); - u->host = host; - pluginsd_set_chart_from_parent(user, NULL, PLUGINSD_KEYWORD_HOST_DEFINE_END); + parser->user.host = host; + pluginsd_set_chart_from_parent(parser, NULL, PLUGINSD_KEYWORD_HOST_DEFINE_END); rrdhost_flag_clear(host, RRDHOST_FLAG_ORPHAN); rrdcontext_host_child_connected(host); @@ -439,34 +423,31 @@ static PARSER_RC pluginsd_host_define_end(char **words __maybe_unused, size_t nu return PARSER_RC_OK; } -static PARSER_RC pluginsd_host(char **words, size_t num_words, void *user) { - PARSER_USER_OBJECT *u = user; - +static inline PARSER_RC pluginsd_host(char **words, size_t num_words, PARSER *parser) { char *guid = get_word(words, num_words, 1); if(!guid || !*guid || strcmp(guid, "localhost") == 0) { - u->host = localhost; + parser->user.host = localhost; return PARSER_RC_OK; } uuid_t uuid; char uuid_str[UUID_STR_LEN]; if(!pluginsd_validate_machine_guid(guid, &uuid, uuid_str)) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_HOST, "cannot parse MACHINE_GUID - is it a valid UUID?"); + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_HOST, "cannot parse MACHINE_GUID - is it a valid UUID?"); RRDHOST *host = rrdhost_find_by_guid(uuid_str); if(unlikely(!host)) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_HOST, "cannot find a host with this machine guid - have you created it?"); + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_HOST, "cannot find a host with this machine guid - have you created it?"); - u->host = host; + parser->user.host = host; return PARSER_RC_OK; } -PARSER_RC pluginsd_chart(char **words, size_t num_words, void *user) -{ - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_CHART); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); +static inline PARSER_RC pluginsd_chart(char **words, size_t num_words, PARSER *parser) { + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_CHART); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); char *type = get_word(words, num_words, 1); char *name = get_word(words, num_words, 2); @@ -490,7 +471,7 @@ PARSER_RC pluginsd_chart(char **words, size_t num_words, void *user) // make sure we have the required variables if (unlikely((!type || !*type || !id || !*id))) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_CHART, "missing parameters"); + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_CHART, "missing parameters"); // parse the name, and make sure it does not include 'type.' if (unlikely(name && *name)) { @@ -511,11 +492,11 @@ PARSER_RC pluginsd_chart(char **words, size_t num_words, void *user) if (likely(priority_s && *priority_s)) priority = str2i(priority_s); - int update_every = ((PARSER_USER_OBJECT *) user)->cd->update_every; + int update_every = parser->user.cd->update_every; if (likely(update_every_s && *update_every_s)) update_every = str2i(update_every_s); if (unlikely(!update_every)) - update_every = ((PARSER_USER_OBJECT *) user)->cd->update_every; + update_every = parser->user.cd->update_every; RRDSET_TYPE chart_type = RRDSET_TYPE_LINE; if (unlikely(chart)) @@ -542,7 +523,7 @@ PARSER_RC pluginsd_chart(char **words, size_t num_words, void *user) st = rrdset_create( host, type, id, name, family, context, title, units, - (plugin && *plugin) ? plugin : ((PARSER_USER_OBJECT *)user)->cd->filename, + (plugin && *plugin) ? plugin : parser->user.cd->filename, module, priority, update_every, chart_type); @@ -573,22 +554,21 @@ PARSER_RC pluginsd_chart(char **words, size_t num_words, void *user) rrdset_flag_clear(st, RRDSET_FLAG_STORE_FIRST); } } - pluginsd_set_chart_from_parent(user, st, PLUGINSD_KEYWORD_CHART); + pluginsd_set_chart_from_parent(parser, st, PLUGINSD_KEYWORD_CHART); return PARSER_RC_OK; } -PARSER_RC pluginsd_chart_definition_end(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_chart_definition_end(char **words, size_t num_words, PARSER *parser) { const char *first_entry_txt = get_word(words, num_words, 1); const char *last_entry_txt = get_word(words, num_words, 2); const char *wall_clock_time_txt = get_word(words, num_words, 3); - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_CHART_DEFINITION_END); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_CHART_DEFINITION_END); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_CHART_DEFINITION_END, PLUGINSD_KEYWORD_CHART); - if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDSET *st = pluginsd_require_chart_from_parent(parser, PLUGINSD_KEYWORD_CHART_DEFINITION_END, PLUGINSD_KEYWORD_CHART); + if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); time_t first_entry_child = (first_entry_txt && *first_entry_txt) ? (time_t)str2ul(first_entry_txt) : 0; time_t last_entry_child = (last_entry_txt && *last_entry_txt) ? (time_t)str2ul(last_entry_txt) : 0; @@ -607,7 +587,6 @@ PARSER_RC pluginsd_chart_definition_end(char **words, size_t num_words, void *us rrdset_flag_clear(st, RRDSET_FLAG_RECEIVER_REPLICATION_FINISHED); rrdhost_receiver_replicating_charts_plus_one(st->rrdhost); - PARSER *parser = ((PARSER_USER_OBJECT *)user)->parser; ok = replicate_chart_request(send_to_plugin, parser, host, st, first_entry_child, last_entry_child, child_wall_clock_time, 0, 0); @@ -622,8 +601,7 @@ PARSER_RC pluginsd_chart_definition_end(char **words, size_t num_words, void *us return ok ? PARSER_RC_OK : PARSER_RC_ERROR; } -PARSER_RC pluginsd_dimension(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_dimension(char **words, size_t num_words, PARSER *parser) { char *id = get_word(words, num_words, 1); char *name = get_word(words, num_words, 2); char *algorithm = get_word(words, num_words, 3); @@ -631,14 +609,14 @@ PARSER_RC pluginsd_dimension(char **words, size_t num_words, void *user) char *divisor_s = get_word(words, num_words, 5); char *options = get_word(words, num_words, 6); - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_DIMENSION); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_DIMENSION); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_DIMENSION, PLUGINSD_KEYWORD_CHART); - if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDSET *st = pluginsd_require_chart_from_parent(parser, PLUGINSD_KEYWORD_DIMENSION, PLUGINSD_KEYWORD_CHART); + if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); if (unlikely(!id)) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_DIMENSION, "missing dimension id"); + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_DIMENSION, "missing dimension id"); long multiplier = 1; if (multiplier_s && *multiplier_s) { @@ -842,8 +820,7 @@ static int pluginsd_execute_function_callback(BUFFER *destination_wb, int timeou return HTTP_RESP_OK; } -PARSER_RC pluginsd_function(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_function(char **words, size_t num_words, PARSER *parser) { bool global = false; size_t i = 1; if(num_words >= 2 && strcmp(get_word(words, num_words, 1), "GLOBAL") == 0) { @@ -855,10 +832,10 @@ PARSER_RC pluginsd_function(char **words, size_t num_words, void *user) char *timeout_s = get_word(words, num_words, i++); char *help = get_word(words, num_words, i++); - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_FUNCTION); + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_FUNCTION); if(!host) return PARSER_RC_ERROR; - RRDSET *st = (global)?NULL:pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_FUNCTION, PLUGINSD_KEYWORD_CHART); + RRDSET *st = (global)?NULL:pluginsd_require_chart_from_parent(parser, PLUGINSD_KEYWORD_FUNCTION, PLUGINSD_KEYWORD_CHART); if(!st) global = true; if (unlikely(!timeout_s || !name || !help || (!global && !st))) { @@ -880,7 +857,6 @@ PARSER_RC pluginsd_function(char **words, size_t num_words, void *user) timeout = PLUGINS_FUNCTIONS_TIMEOUT_DEFAULT; } - PARSER *parser = ((PARSER_USER_OBJECT *) user)->parser; rrd_collector_add_function(host, st, name, timeout, help, false, pluginsd_execute_function_callback, parser); return PARSER_RC_OK; @@ -893,8 +869,7 @@ static void pluginsd_function_result_end(struct parser *parser, void *action_dat string_freez(key); } -PARSER_RC pluginsd_function_result_begin(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_function_result_begin(char **words, size_t num_words, PARSER *parser) { char *key = get_word(words, num_words, 1); char *status = get_word(words, num_words, 2); char *format = get_word(words, num_words, 3); @@ -915,8 +890,6 @@ PARSER_RC pluginsd_function_result_begin(char **words, size_t num_words, void *u time_t expiration = (expires && *expires) ? str2l(expires) : 0; - PARSER *parser = ((PARSER_USER_OBJECT *) user)->parser; - struct inflight_function *pf = NULL; if(key && *key) @@ -949,16 +922,15 @@ PARSER_RC pluginsd_function_result_begin(char **words, size_t num_words, void *u // ---------------------------------------------------------------------------- -PARSER_RC pluginsd_variable(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_variable(char **words, size_t num_words, PARSER *parser) { char *name = get_word(words, num_words, 1); char *value = get_word(words, num_words, 2); NETDATA_DOUBLE v; - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_VARIABLE); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_VARIABLE); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - RRDSET *st = pluginsd_get_chart_from_parent(user); + RRDSET *st = pluginsd_get_chart_from_parent(parser); int global = (st) ? 0 : 1; @@ -975,7 +947,7 @@ PARSER_RC pluginsd_variable(char **words, size_t num_words, void *user) } if (unlikely(!name || !*name)) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_VARIABLE, "missing variable name"); + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_VARIABLE, "missing variable name"); if (unlikely(!value || !*value)) value = NULL; @@ -990,7 +962,7 @@ PARSER_RC pluginsd_variable(char **words, size_t num_words, void *user) } if (!global && !st) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_VARIABLE, "no chart is defined and no GLOBAL is given"); + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_VARIABLE, "no chart is defined and no GLOBAL is given"); char *endptr = NULL; v = (NETDATA_DOUBLE) str2ndd_encoded(value, &endptr); @@ -1034,32 +1006,29 @@ PARSER_RC pluginsd_variable(char **words, size_t num_words, void *user) return PARSER_RC_OK; } -PARSER_RC pluginsd_flush(char **words __maybe_unused, size_t num_words __maybe_unused, void *user) -{ +static inline PARSER_RC pluginsd_flush(char **words __maybe_unused, size_t num_words __maybe_unused, PARSER *parser) { debug(D_PLUGINSD, "requested a " PLUGINSD_KEYWORD_FLUSH); - pluginsd_set_chart_from_parent(user, NULL, PLUGINSD_KEYWORD_FLUSH); - ((PARSER_USER_OBJECT *) user)->replay.start_time = 0; - ((PARSER_USER_OBJECT *) user)->replay.end_time = 0; - ((PARSER_USER_OBJECT *) user)->replay.start_time_ut = 0; - ((PARSER_USER_OBJECT *) user)->replay.end_time_ut = 0; + pluginsd_set_chart_from_parent(parser, NULL, PLUGINSD_KEYWORD_FLUSH); + parser->user.replay.start_time = 0; + parser->user.replay.end_time = 0; + parser->user.replay.start_time_ut = 0; + parser->user.replay.end_time_ut = 0; return PARSER_RC_OK; } -PARSER_RC pluginsd_disable(char **words __maybe_unused, size_t num_words __maybe_unused, void *user __maybe_unused) -{ +static inline PARSER_RC pluginsd_disable(char **words __maybe_unused, size_t num_words __maybe_unused, PARSER *parser) { info("PLUGINSD: plugin called DISABLE. Disabling it."); - ((PARSER_USER_OBJECT *) user)->enabled = 0; + parser->user.enabled = 0; return PARSER_RC_STOP; } -PARSER_RC pluginsd_label(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_label(char **words, size_t num_words, PARSER *parser) { const char *name = get_word(words, num_words, 1); const char *label_source = get_word(words, num_words, 2); const char *value = get_word(words, num_words, 3); if (!name || !label_source || !value) - return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_LABEL, "missing parameters"); + return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_LABEL, "missing parameters"); char *store = (char *)value; bool allocated_store = false; @@ -1088,13 +1057,10 @@ PARSER_RC pluginsd_label(char **words, size_t num_words, void *user) } } - if(unlikely(!((PARSER_USER_OBJECT *) user)->new_host_labels)) - ((PARSER_USER_OBJECT *) user)->new_host_labels = rrdlabels_create(); + if(unlikely(!(parser->user.new_host_labels))) + parser->user.new_host_labels = rrdlabels_create(); - rrdlabels_add(((PARSER_USER_OBJECT *)user)->new_host_labels, - name, - store, - str2l(label_source)); + rrdlabels_add(parser->user.new_host_labels, name, store, str2l(label_source)); if (allocated_store) freez(store); @@ -1102,90 +1068,84 @@ PARSER_RC pluginsd_label(char **words, size_t num_words, void *user) return PARSER_RC_OK; } -PARSER_RC pluginsd_overwrite(char **words __maybe_unused, size_t num_words __maybe_unused, void *user) -{ - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_OVERWRITE); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); +static inline PARSER_RC pluginsd_overwrite(char **words __maybe_unused, size_t num_words __maybe_unused, PARSER *parser) { + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_OVERWRITE); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); debug(D_PLUGINSD, "requested to OVERWRITE host labels"); if(unlikely(!host->rrdlabels)) host->rrdlabels = rrdlabels_create(); - rrdlabels_migrate_to_these(host->rrdlabels, (DICTIONARY *) (((PARSER_USER_OBJECT *)user)->new_host_labels)); + rrdlabels_migrate_to_these(host->rrdlabels, parser->user.new_host_labels); rrdhost_flag_set(host, RRDHOST_FLAG_METADATA_LABELS | RRDHOST_FLAG_METADATA_UPDATE); - rrdlabels_destroy(((PARSER_USER_OBJECT *)user)->new_host_labels); - ((PARSER_USER_OBJECT *)user)->new_host_labels = NULL; + rrdlabels_destroy(parser->user.new_host_labels); + parser->user.new_host_labels = NULL; return PARSER_RC_OK; } - -PARSER_RC pluginsd_clabel(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_clabel(char **words, size_t num_words, PARSER *parser) { const char *name = get_word(words, num_words, 1); const char *value = get_word(words, num_words, 2); const char *label_source = get_word(words, num_words, 3); if (!name || !value || !*label_source) { error("Ignoring malformed or empty CHART LABEL command."); - return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); } - if(unlikely(!((PARSER_USER_OBJECT *) user)->chart_rrdlabels_linked_temporarily)) { - RRDSET *st = pluginsd_get_chart_from_parent(user); - ((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily = st->rrdlabels; - rrdlabels_unmark_all(((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily); + if(unlikely(!parser->user.chart_rrdlabels_linked_temporarily)) { + RRDSET *st = pluginsd_get_chart_from_parent(parser); + parser->user.chart_rrdlabels_linked_temporarily = st->rrdlabels; + rrdlabels_unmark_all(parser->user.chart_rrdlabels_linked_temporarily); } - rrdlabels_add(((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily, - name, value, str2l(label_source)); + rrdlabels_add(parser->user.chart_rrdlabels_linked_temporarily, name, value, str2l(label_source)); return PARSER_RC_OK; } -PARSER_RC pluginsd_clabel_commit(char **words __maybe_unused, size_t num_words __maybe_unused, void *user) -{ - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_CLABEL_COMMIT); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); +static inline PARSER_RC pluginsd_clabel_commit(char **words __maybe_unused, size_t num_words __maybe_unused, PARSER *parser) { + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_CLABEL_COMMIT); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_CLABEL_COMMIT, PLUGINSD_KEYWORD_BEGIN); - if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDSET *st = pluginsd_require_chart_from_parent(parser, PLUGINSD_KEYWORD_CLABEL_COMMIT, PLUGINSD_KEYWORD_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); debug(D_PLUGINSD, "requested to commit chart labels"); - if(!((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily) { - error("PLUGINSD: 'host:%s' got CLABEL_COMMIT, without a CHART or BEGIN. Ignoring it.", - rrdhost_hostname(host)); - return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + if(!parser->user.chart_rrdlabels_linked_temporarily) { + error("PLUGINSD: 'host:%s' got CLABEL_COMMIT, without a CHART or BEGIN. Ignoring it.", rrdhost_hostname(host)); + return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); } - rrdlabels_remove_all_unmarked(((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily); + rrdlabels_remove_all_unmarked(parser->user.chart_rrdlabels_linked_temporarily); rrdset_flag_set(st, RRDSET_FLAG_METADATA_UPDATE); rrdhost_flag_set(st->rrdhost, RRDHOST_FLAG_METADATA_UPDATE); - ((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily = NULL; + parser->user.chart_rrdlabels_linked_temporarily = NULL; return PARSER_RC_OK; } -PARSER_RC pluginsd_replay_begin(char **words, size_t num_words, void *user) { +static inline PARSER_RC pluginsd_replay_begin(char **words, size_t num_words, PARSER *parser) { char *id = get_word(words, num_words, 1); char *start_time_str = get_word(words, num_words, 2); char *end_time_str = get_word(words, num_words, 3); char *child_now_str = get_word(words, num_words, 4); - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_BEGIN); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_REPLAY_BEGIN); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); RRDSET *st; if (likely(!id || !*id)) - st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_BEGIN, PLUGINSD_KEYWORD_REPLAY_BEGIN); + st = pluginsd_require_chart_from_parent(parser, PLUGINSD_KEYWORD_REPLAY_BEGIN, PLUGINSD_KEYWORD_REPLAY_BEGIN); else st = pluginsd_find_chart(host, id, PLUGINSD_KEYWORD_REPLAY_BEGIN); - if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); - pluginsd_set_chart_from_parent(user, st, PLUGINSD_KEYWORD_REPLAY_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); + pluginsd_set_chart_from_parent(parser, st, PLUGINSD_KEYWORD_REPLAY_BEGIN); if(start_time_str && end_time_str) { time_t start_time = (time_t) str2ull_encoded(start_time_str); @@ -1237,12 +1197,12 @@ PARSER_RC pluginsd_replay_begin(char **words, size_t num_words, void *user) { if(st->db.current_entry >= st->db.entries) st->db.current_entry -= st->db.entries; - ((PARSER_USER_OBJECT *) user)->replay.start_time = start_time; - ((PARSER_USER_OBJECT *) user)->replay.end_time = end_time; - ((PARSER_USER_OBJECT *) user)->replay.start_time_ut = (usec_t) start_time * USEC_PER_SEC; - ((PARSER_USER_OBJECT *) user)->replay.end_time_ut = (usec_t) end_time * USEC_PER_SEC; - ((PARSER_USER_OBJECT *) user)->replay.wall_clock_time = wall_clock_time; - ((PARSER_USER_OBJECT *) user)->replay.rset_enabled = true; + parser->user.replay.start_time = start_time; + parser->user.replay.end_time = end_time; + parser->user.replay.start_time_ut = (usec_t) start_time * USEC_PER_SEC; + parser->user.replay.end_time_ut = (usec_t) end_time * USEC_PER_SEC; + parser->user.replay.wall_clock_time = wall_clock_time; + parser->user.replay.rset_enabled = true; return PARSER_RC_OK; } @@ -1257,12 +1217,12 @@ PARSER_RC pluginsd_replay_begin(char **words, size_t num_words, void *user) { // the child sends an RBEGIN without any parameters initially // setting rset_enabled to false, means the RSET should not store any metrics // to store metrics, the RBEGIN needs to have timestamps - ((PARSER_USER_OBJECT *) user)->replay.start_time = 0; - ((PARSER_USER_OBJECT *) user)->replay.end_time = 0; - ((PARSER_USER_OBJECT *) user)->replay.start_time_ut = 0; - ((PARSER_USER_OBJECT *) user)->replay.end_time_ut = 0; - ((PARSER_USER_OBJECT *) user)->replay.wall_clock_time = 0; - ((PARSER_USER_OBJECT *) user)->replay.rset_enabled = false; + parser->user.replay.start_time = 0; + parser->user.replay.end_time = 0; + parser->user.replay.start_time_ut = 0; + parser->user.replay.end_time_ut = 0; + parser->user.replay.wall_clock_time = 0; + parser->user.replay.rset_enabled = false; return PARSER_RC_OK; } @@ -1293,20 +1253,18 @@ static inline SN_FLAGS pluginsd_parse_storage_number_flags(const char *flags_str return flags; } -PARSER_RC pluginsd_replay_set(char **words, size_t num_words, void *user) -{ +static inline PARSER_RC pluginsd_replay_set(char **words, size_t num_words, PARSER *parser) { char *dimension = get_word(words, num_words, 1); char *value_str = get_word(words, num_words, 2); char *flags_str = get_word(words, num_words, 3); - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_SET); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_REPLAY_SET); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_SET, PLUGINSD_KEYWORD_REPLAY_BEGIN); - if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDSET *st = pluginsd_require_chart_from_parent(parser, PLUGINSD_KEYWORD_REPLAY_SET, PLUGINSD_KEYWORD_REPLAY_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - PARSER_USER_OBJECT *u = user; - if(!u->replay.rset_enabled) { + if(!parser->user.replay.rset_enabled) { error_limit_static_thread_var(erl, 1, 0); error_limit(&erl, "PLUGINSD: 'host:%s/chart:%s' got a %s but it is disabled by %s errors", rrdhost_hostname(host), rrdset_id(st), PLUGINSD_KEYWORD_REPLAY_SET, PLUGINSD_KEYWORD_REPLAY_BEGIN); @@ -1316,18 +1274,18 @@ PARSER_RC pluginsd_replay_set(char **words, size_t num_words, void *user) } RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_REPLAY_SET); - if(!rd) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + if(!rd) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - if (unlikely(!u->replay.start_time || !u->replay.end_time)) { + if (unlikely(!parser->user.replay.start_time || !parser->user.replay.end_time)) { error("PLUGINSD: 'host:%s/chart:%s/dim:%s' got a %s with invalid timestamps %ld to %ld from a %s. Disabling it.", rrdhost_hostname(host), rrdset_id(st), dimension, PLUGINSD_KEYWORD_REPLAY_SET, - u->replay.start_time, - u->replay.end_time, + parser->user.replay.start_time, + parser->user.replay.end_time, PLUGINSD_KEYWORD_REPLAY_BEGIN); - return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); } if (unlikely(!value_str || !*value_str)) @@ -1348,8 +1306,8 @@ PARSER_RC pluginsd_replay_set(char **words, size_t num_words, void *user) flags = SN_EMPTY_SLOT; } - rrddim_store_metric(rd, u->replay.end_time_ut, value, flags); - rd->last_collected_time.tv_sec = u->replay.end_time; + rrddim_store_metric(rd, parser->user.replay.end_time_ut, value, flags); + rd->last_collected_time.tv_sec = parser->user.replay.end_time; rd->last_collected_time.tv_usec = 0; rd->collections_counter++; } @@ -1363,9 +1321,8 @@ PARSER_RC pluginsd_replay_set(char **words, size_t num_words, void *user) return PARSER_RC_OK; } -PARSER_RC pluginsd_replay_rrddim_collection_state(char **words, size_t num_words, void *user) -{ - if(((PARSER_USER_OBJECT *) user)->replay.rset_enabled == false) +static inline PARSER_RC pluginsd_replay_rrddim_collection_state(char **words, size_t num_words, PARSER *parser) { + if(parser->user.replay.rset_enabled == false) return PARSER_RC_OK; char *dimension = get_word(words, num_words, 1); @@ -1374,14 +1331,14 @@ PARSER_RC pluginsd_replay_rrddim_collection_state(char **words, size_t num_words char *last_calculated_value_str = get_word(words, num_words, 4); char *last_stored_value_str = get_word(words, num_words, 5); - RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE); - if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDHOST *host = pluginsd_require_host_from_parent(parser, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE); + if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); - RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE, PLUGINSD_KEYWORD_REPLAY_BEGIN); - if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + RRDSET *st = pluginsd_require_chart_from_parent(parser, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE, PLUGINSD_KEYWORD_REPLAY_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE); - if(!rd) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL); + if(!rd) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL); usec_t dim_last_collected_ut = (usec_t)rd->last_collected_time.tv_sec * USEC_PER_SEC + (usec_t)rd->last_collected_time.tv_usec; usec_t last_collected_ut = last_collected_ut_str ? str2ull_encoded(last_collected_ut_str) : 0; @@ -1397,19 +1354,18 @@ PARSER_RC pluginsd_replay_rrddim_collection_state(char **words, size_t num_words return PARSER_RC_OK; } -PARSER_RC p