71
return st;
72
}
73
74
-static inline RRDDIM_ACQUIRED *pluginsd_acquire_dimension(RRDHOST *host, RRDSET *st, const char *dimension, const char *cmd) {
74
+static inline RRDSET *pluginsd_get_chart_from_parent(void *user) {
75
+ return ((PARSER_USER_OBJECT *) user)->st;
76
+}
77
+
78
+static inline void pluginsd_lock_rrdset_data_collection(void *user) {
79
+ PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user;
80
+ if(u->st && !u->v2.locked_data_collection) {
81
+ netdata_spinlock_lock(&u->st->data_collection_lock);
82
+ u->v2.locked_data_collection = true;
83
+ }
84
+}
85
+
86
+static inline bool pluginsd_unlock_rrdset_data_collection(void *user) {
87
+ PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user;
88
+ if(u->st && u->v2.locked_data_collection) {
89
+ netdata_spinlock_unlock(&u->st->data_collection_lock);
90
+ u->v2.locked_data_collection = false;
91
+ return true;
92
+ }
93
+
94
+ return false;
95
+}
96
+
97
+void pluginsd_rrdset_cleanup(RRDSET *st) {
98
+ for(size_t i = 0; i < st->pluginsd.used ; i++) {
99
+ if (st->pluginsd.rda[i]) {
100
+ rrddim_acquired_release(st->pluginsd.rda[i]);
101
+ st->pluginsd.rda[i] = NULL;
102
+ }
103
+ }
104
+ freez(st->pluginsd.rda);
105
+ st->pluginsd.rda = NULL;
106
+ st->pluginsd.size = 0;
107
+ st->pluginsd.used = 0;
108
+ st->pluginsd.pos = 0;
109
+}
110
+
111
+static inline void pluginsd_set_chart_from_parent(void *user, RRDSET *st, const char *keyword) {
112
+ PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user;
113
+
114
+ if(unlikely(pluginsd_unlock_rrdset_data_collection(user))) {
115
+ error("PLUGINSD: 'host:%s/chart:%s/' stale data collection lock found during %s; it has been unlocked",
116
+ rrdhost_hostname(u->st->rrdhost), rrdset_id(u->st), keyword);
117
+ }
118
+
119
+ if(unlikely(u->v2.ml_locked)) {
120
+ ml_chart_update_end(u->st);
121
+ u->v2.ml_locked = false;
122
+
123
+ error("PLUGINSD: 'host:%s/chart:%s/' stale ML lock found during %s, it has been unlocked",
124
+ rrdhost_hostname(u->st->rrdhost), rrdset_id(u->st), keyword);
125
+ }
126
+
127
+ if(st) {
128
+ size_t dims = dictionary_entries(st->rrddim_root_index);
129
+ if(unlikely(st->pluginsd.size < dims)) {
130
+ st->pluginsd.rda = reallocz(st->pluginsd.rda, dims * sizeof(RRDDIM_ACQUIRED *));
131
+ st->pluginsd.size = dims;
132
+ }
133
+
134
+ if(st->pluginsd.pos > st->pluginsd.used && st->pluginsd.pos <= st->pluginsd.size)
135
+ st->pluginsd.used = st->pluginsd.pos;
136
+
137
+ st->pluginsd.pos = 0;
138
+ }
139
+
140
+ u->st = st;
141
+}
142
+
143
+static inline RRDDIM *pluginsd_acquire_dimension(RRDHOST *host, RRDSET *st, const char *dimension, const char *cmd) {
144
if (unlikely(!dimension || !*dimension)) {
145
error("PLUGINSD: 'host:%s/chart:%s' got a %s, without a dimension.",
146
rrdhost_hostname(host), rrdset_id(st), cmd);
147
return NULL;
148
}
149
81
- RRDDIM_ACQUIRED *rda = rrddim_find_and_acquire(st, dimension);
150
+ RRDDIM_ACQUIRED *rda;
151
83
- if (unlikely(!rda))
152
+ if(likely(st->pluginsd.pos < st->pluginsd.used)) {
153
+ rda = st->pluginsd.rda[st->pluginsd.pos];
154
+ RRDDIM *rd = rrddim_acquired_to_rrddim(rda);
155
+ if (likely(rd && strcmp(rrddim_id(rd), dimension) == 0)) {
156
+ st->pluginsd.pos++;
157
+ return rd;
158
+ }
159
+ else {
160
+ rrddim_acquired_release(rda);
161
+ st->pluginsd.rda[st->pluginsd.pos] = NULL;
162
+ }
163
+ }
164
+
165
+ rda = rrddim_find_and_acquire(st, dimension);
166
+ if (unlikely(!rda)) {
167
error("PLUGINSD: 'host:%s/chart:%s/dim:%s' got a %s but dimension does not exist.",
168
rrdhost_hostname(host), rrdset_id(st), dimension, cmd);
169
87
- return rda;
170
+ return NULL;
171
+ }
172
+
173
+ if(likely(st->pluginsd.pos < st->pluginsd.size))
174
+ st->pluginsd.rda[st->pluginsd.pos++] = rda;
175
+
176
+ return rrddim_acquired_to_rrddim(rda);
177
}
178
179
static inline RRDSET *pluginsd_find_chart(RRDHOST *host, const char *chart, const char *cmd) {
191
return st;
192
}
193
105
-static inline PARSER_RC PLUGINSD_DISABLE_PLUGIN(void *user) {
194
+static inline PARSER_RC PLUGINSD_DISABLE_PLUGIN(void *user, const char *keyword, const char *msg) {
195
((PARSER_USER_OBJECT *) user)->enabled = 0;
196
+
197
+ if(keyword && msg) {
198
+ error_limit_static_global_var(erl, 1, 0);
199
+ error_limit(&erl, "PLUGINSD: keyword %s: %s", keyword, msg);
200
+ }
201
+
202
return PARSER_RC_ERROR;
203
}
204
208
char *value = get_word(words, num_words, 2);
209
210
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_SET);
116
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
211
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
212
213
RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_SET, PLUGINSD_KEYWORD_CHART);
119
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
214
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
215
121
- RRDDIM_ACQUIRED *rda = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_SET);
122
- if(!rda) return PLUGINSD_DISABLE_PLUGIN(user);
123
-
124
- RRDDIM *rd = rrddim_acquired_to_rrddim(rda);
216
+ RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_SET);
217
+ if(!rd) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
218
219
if (unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
220
debug(D_PLUGINSD, "PLUGINSD: 'host:%s/chart:%s/dim:%s' SET is setting value to '%s'",
221
rrdhost_hostname(host), rrdset_id(st), dimension, value && *value ? value : "UNSET");
222
223
if (value && *value)
131
- rrddim_set_by_pointer(st, rd, strtoll(value, NULL, 0));
224
+ rrddim_set_by_pointer(st, rd, str2ll_hex_or_dec(value));
225
133
- rrddim_acquired_release(rda);
226
return PARSER_RC_OK;
227
}
228
232
char *microseconds_txt = get_word(words, num_words, 2);
233
234
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_BEGIN);
143
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
235
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
236
237
RRDSET *st = pluginsd_find_chart(host, id, PLUGINSD_KEYWORD_BEGIN);
146
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
238
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
239
148
- ((PARSER_USER_OBJECT *)user)->st = st;
240
+ pluginsd_set_chart_from_parent(user, st, PLUGINSD_KEYWORD_BEGIN);
241
242
usec_t microseconds = 0;
243
if (microseconds_txt && *microseconds_txt) {
279
UNUSED(num_words);
280
281
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_END);
190
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
282
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
283
284
RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_END, PLUGINSD_KEYWORD_BEGIN);
193
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
285
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
286
287
if (unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
288
debug(D_PLUGINSD, "requested an END on chart '%s'", rrdset_id(st));
289
198
- ((PARSER_USER_OBJECT *) user)->st = NULL;
199
- ((PARSER_USER_OBJECT *) user)->count++;
290
+ pluginsd_set_chart_from_parent(user, NULL, PLUGINSD_KEYWORD_END);
291
+ ((PARSER_USER_OBJECT *) user)->data_collections_count++;
292
293
struct timeval now;
294
now_realtime_timeval(&now);
300
PARSER_RC pluginsd_chart(char **words, size_t num_words, void *user)
301
{
302
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_CHART);
211
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
303
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
304
305
char *type = get_word(words, num_words, 1);
306
char *name = get_word(words, num_words, 2);
323
}
324
325
// make sure we have the required variables
234
- if (unlikely((!type || !*type || !id || !*id))) {
235
- error("PLUGINSD: 'host:%s' requested a CHART, without a type.id. Disabling it.",
236
- rrdhost_hostname(host));
237
-
238
- ((PARSER_USER_OBJECT *) user)->enabled = 0;
239
- return PARSER_RC_ERROR;
240
- }
326
+ if (unlikely((!type || !*type || !id || !*id)))
327
+ return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_CHART, "missing parameters");
328
329
// parse the name, and make sure it does not include 'type.'
330
if (unlikely(name && *name)) {
331
// when data are streamed from child nodes
332
// name will be type.name
246
- // so we have to remove 'type.' from name too
333
+ // so, we have to remove 'type.' from name too
334
size_t len = strlen(type);
335
if (strncmp(type, name, len) == 0 && name[len] == '.')
336
name = &name[len + 1];
407
rrdset_flag_clear(st, RRDSET_FLAG_STORE_FIRST);
408
}
409
}
323
- ((PARSER_USER_OBJECT *)user)->st = st;
410
+ pluginsd_set_chart_from_parent(user, st, PLUGINSD_KEYWORD_CHART);
411
412
return PARSER_RC_OK;
413
}
419
const char *wall_clock_time_txt = get_word(words, num_words, 3);
420
421
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_CHART_DEFINITION_END);
335
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
422
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
423
424
RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_CHART_DEFINITION_END, PLUGINSD_KEYWORD_CHART);
338
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
425
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
426
427
time_t first_entry_child = (first_entry_txt && *first_entry_txt) ? (time_t)str2ul(first_entry_txt) : 0;
428
time_t last_entry_child = (last_entry_txt && *last_entry_txt) ? (time_t)str2ul(last_entry_txt) : 0;
466
char *options = get_word(words, num_words, 6);
467
468
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_DIMENSION);
382
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
469
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
470
471
RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_DIMENSION, PLUGINSD_KEYWORD_CHART);
385
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
472
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
473
387
- if (unlikely(!id)) {
388
- error("PLUGINSD: 'host:%s/chart:%s' got a DIMENSION, without an id. Disabling it.",
389
- rrdhost_hostname(host), st ? rrdset_id(st) : "UNSET");
390
- return PLUGINSD_DISABLE_PLUGIN(user);
391
- }
392
-
393
- if (unlikely(!st && !((PARSER_USER_OBJECT *) user)->st_exists)) {
394
- error("PLUGINSD: 'host:%s' got a DIMENSION, without a CHART. Disabling it.",
395
- rrdhost_hostname(host));
396
- return PLUGINSD_DISABLE_PLUGIN(user);
397
- }
474
+ if (unlikely(!id))
475
+ return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_DIMENSION, "missing dimension id");
476
477
long multiplier = 1;
478
if (multiplier_s && *multiplier_s) {
401
- multiplier = strtol(multiplier_s, NULL, 0);
479
+ multiplier = str2ll_hex_or_dec(multiplier_s);
480
if (unlikely(!multiplier))
481
multiplier = 1;
482
}
483
484
long divisor = 1;
485
if (likely(divisor_s && *divisor_s)) {
408
- divisor = strtol(divisor_s, NULL, 0);
486
+ divisor = str2ll_hex_or_dec(divisor_s);
487
if (unlikely(!divisor))
488
divisor = 1;
489
}
790
NETDATA_DOUBLE v;
791
792
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_VARIABLE);
715
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
793
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
794
717
- RRDSET *st = ((PARSER_USER_OBJECT *) user)->st;
795
+ RRDSET *st = pluginsd_get_chart_from_parent(user);
796
797
int global = (st) ? 0 : 1;
798
808
}
809
}
810
733
- if (unlikely(!name || !*name)) {
734
- error("PLUGINSD: 'host:%s/chart:%s' got a VARIABLE without a variable name. Disabling it.",
735
- rrdhost_hostname(host), st ? rrdset_id(st):"UNSET");
736
-
737
- ((PARSER_USER_OBJECT *)user)->enabled = 0;
738
- return PLUGINSD_DISABLE_PLUGIN(user);
739
- }
811
+ if (unlikely(!name || !*name))
812
+ return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_VARIABLE, "missing variable name");
813
814
if (unlikely(!value || !*value))
815
value = NULL;
823
return PARSER_RC_OK;
824
}
825
753
- if (!global && !st) {
754
- error("PLUGINSD: 'host:%s/chart:%s' cannot update CHART VARIABLE '%s' without a chart",
755
- rrdhost_hostname(host),
756
- st ? rrdset_id(st):"UNSET",
757
- name
758
- );
759
- return PLUGINSD_DISABLE_PLUGIN(user);
760
- }
826
+ if (!global && !st)
827
+ return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_VARIABLE, "no chart is defined and no GLOBAL is given");
828
829
char *endptr = NULL;
830
v = (NETDATA_DOUBLE)str2ndd(value, &endptr);
870
871
PARSER_RC pluginsd_flush(char **words __maybe_unused, size_t num_words __maybe_unused, void *user)
872
{
806
- debug(D_PLUGINSD, "requested a FLUSH");
807
- ((PARSER_USER_OBJECT *) user)->st = NULL;
873
+ debug(D_PLUGINSD, "requested a " PLUGINSD_KEYWORD_FLUSH);
874
+ pluginsd_set_chart_from_parent(user, NULL, PLUGINSD_KEYWORD_FLUSH);
875
((PARSER_USER_OBJECT *) user)->replay.start_time = 0;
876
((PARSER_USER_OBJECT *) user)->replay.end_time = 0;
877
((PARSER_USER_OBJECT *) user)->replay.start_time_ut = 0;
892
const char *label_source = get_word(words, num_words, 2);
893
const char *value = get_word(words, num_words, 3);
894
828
- if (!name || !label_source || !value) {
829
- error("PLUGINSD: ignoring malformed or empty LABEL command.");
830
- return PLUGINSD_DISABLE_PLUGIN(user);
831
- }
895
+ if (!name || !label_source || !value)
896
+ return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_LABEL, "missing parameters");
897
898
char *store = (char *)value;
899
bool allocated_store = false;
939
PARSER_RC pluginsd_overwrite(char **words __maybe_unused, size_t num_words __maybe_unused, void *user)
940
{
941
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_OVERWRITE);
877
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
942
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
943
944
debug(D_PLUGINSD, "requested to OVERWRITE host labels");
945
963
964
if (!name || !value || !*label_source) {
965
error("Ignoring malformed or empty CHART LABEL command.");
901
- return PLUGINSD_DISABLE_PLUGIN(user);
966
+ return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
967
}
968
969
if(unlikely(!((PARSER_USER_OBJECT *) user)->chart_rrdlabels_linked_temporarily)) {
905
- ((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily = ((PARSER_USER_OBJECT *)user)->st->rrdlabels;
970
+ RRDSET *st = pluginsd_get_chart_from_parent(user);
971
+ ((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily = st->rrdlabels;
972
rrdlabels_unmark_all(((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily);
973
}
974
981
PARSER_RC pluginsd_clabel_commit(char **words __maybe_unused, size_t num_words __maybe_unused, void *user)
982
{
983
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_CLABEL_COMMIT);
918
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
984
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
985
986
RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_CLABEL_COMMIT, PLUGINSD_KEYWORD_BEGIN);
921
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
987
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
988
989
debug(D_PLUGINSD, "requested to commit chart labels");
990
991
if(!((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily) {
992
error("PLUGINSD: 'host:%s' got CLABEL_COMMIT, without a CHART or BEGIN. Ignoring it.",
993
rrdhost_hostname(host));
928
- return PLUGINSD_DISABLE_PLUGIN(user);
994
+ return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
995
}
996
997
rrdlabels_remove_all_unmarked(((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily);
1003
return PARSER_RC_OK;
1004
}
1005
940
-PARSER_RC pluginsd_replay_rrdset_begin(char **words, size_t num_words, void *user)
941
-{
1006
+PARSER_RC pluginsd_replay_begin(char **words, size_t num_words, void *user) {
1007
char *id = get_word(words, num_words, 1);
1008
char *start_time_str = get_word(words, num_words, 2);
1009
char *end_time_str = get_word(words, num_words, 3);
1010
char *child_now_str = get_word(words, num_words, 4);
1011
1012
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_BEGIN);
948
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
1013
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1014
1015
RRDSET *st;
1016
if (likely(!id || !*id))
1018
else
1019
st = pluginsd_find_chart(host, id, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1020
956
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
957
- ((PARSER_USER_OBJECT *) user)->st = st;
1021
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1022
+ pluginsd_set_chart_from_parent(user, st, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1023
1024
if(start_time_str && end_time_str) {
1025
time_t start_time = (time_t)str2ul(start_time_str);
1081
return PARSER_RC_OK;
1082
}
1083
1019
- error("PLUGINSD REPLAY ERROR: 'host:%s/chart:%s' got a " PLUGINSD_KEYWORD_REPLAY_BEGIN " from %ld to %ld, but timestamps are invalid (now is %ld [%s], tolerance %ld). Ignoring " PLUGINSD_KEYWORD_REPLAY_SET,
1084
+ error("PLUGINSD REPLAY ERROR: 'host:%s/chart:%s' got a " PLUGINSD_KEYWORD_REPLAY_BEGIN
1085
+ " from %ld to %ld, but timestamps are invalid "
1086
+ "(now is %ld [%s], tolerance %ld). Ignoring " PLUGINSD_KEYWORD_REPLAY_SET,
1087
rrdhost_hostname(st->rrdhost), rrdset_id(st), start_time, end_time,
1088
wall_clock_time, wall_clock_comes_from_child ? "child wall clock" : "parent wall clock", tolerance);
1089
}
1100
return PARSER_RC_OK;
1101
}
1102
1103
+static inline SN_FLAGS pluginsd_parse_storage_number_flags(const char *flags_str) {
1104
+ SN_FLAGS flags = SN_FLAG_NONE;
1105
+
1106
+ char c;
1107
+ while ((c = *flags_str++)) {
1108
+ switch (c) {
1109
+ case 'A':
1110
+ flags |= SN_FLAG_NOT_ANOMALOUS;
1111
+ break;
1112
+
1113
+ case 'R':
1114
+ flags |= SN_FLAG_RESET;
1115
+ break;
1116
+
1117
+ case 'E':
1118
+ flags = SN_EMPTY_SLOT;
1119
+ return flags;
1120
+
1121
+ default:
1122
+ internal_error(true, "Unknown SN_FLAGS flag '%c'", c);
1123
+ break;
1124
+ }
1125
+ }
1126
+
1127
+ return flags;
1128
+}
1129
+
1130
PARSER_RC pluginsd_replay_set(char **words, size_t num_words, void *user)
1131
{
1132
char *dimension = get_word(words, num_words, 1);
1134
char *flags_str = get_word(words, num_words, 3);
1135
1136
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_SET);
1043
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
1137
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1138
1139
RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_SET, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1046
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
1140
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1141
1048
- if(!((PARSER_USER_OBJECT *) user)->replay.rset_enabled) {
1142
+ PARSER_USER_OBJECT *u = user;
1143
+ if(!u->replay.rset_enabled) {
1144
error_limit_static_thread_var(erl, 1, 0);
1050
- error_limit(&erl, "PLUGINSD: 'host:%s/chart:%s' got a " PLUGINSD_KEYWORD_REPLAY_SET " but it is disabled by " PLUGINSD_KEYWORD_REPLAY_BEGIN " errors",
1051
- rrdhost_hostname(host), rrdset_id(st));
1145
+ error_limit(&erl, "PLUGINSD: 'host:%s/chart:%s' got a %s but it is disabled by %s errors",
1146
+ rrdhost_hostname(host), rrdset_id(st), PLUGINSD_KEYWORD_REPLAY_SET, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1147
1148
// we have to return OK here
1149
return PARSER_RC_OK;
1150
}
1151
1057
- RRDDIM_ACQUIRED *rda = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_REPLAY_SET);
1058
- if(!rda) return PLUGINSD_DISABLE_PLUGIN(user);
1152
+ RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_REPLAY_SET);
1153
+ if(!rd) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1154
1060
- if (unlikely(!((PARSER_USER_OBJECT *) user)->replay.start_time || !((PARSER_USER_OBJECT *) user)->replay.end_time)) {
1061
- error("PLUGINSD: 'host:%s/chart:%s/dim:%s' got a " PLUGINSD_KEYWORD_REPLAY_SET " with invalid timestamps %ld to %ld from a " PLUGINSD_KEYWORD_REPLAY_BEGIN ". Disabling it.",
1155
+ if (unlikely(!u->replay.start_time || !u->replay.end_time)) {
1156
+ error("PLUGINSD: 'host:%s/chart:%s/dim:%s' got a %s with invalid timestamps %ld to %ld from a %s. Disabling it.",
1157
rrdhost_hostname(host),
1158
rrdset_id(st),
1159
dimension,
1065
- ((PARSER_USER_OBJECT *) user)->replay.start_time,
1066
- ((PARSER_USER_OBJECT *) user)->replay.end_time);
1067
- return PLUGINSD_DISABLE_PLUGIN(user);
1160
+ PLUGINSD_KEYWORD_REPLAY_SET,
1161
+ u->replay.start_time,
1162
+ u->replay.end_time,
1163
+ PLUGINSD_KEYWORD_REPLAY_BEGIN);
1164
+ return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1165
}
1166
1167
if (unlikely(!value_str || !*value_str))
1171
flags_str = "";
1172
1173
if (likely(value_str)) {
1077
- RRDDIM *rd = rrddim_acquired_to_rrddim(rda);
1078
-
1174
RRDDIM_FLAGS rd_flags = rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE | RRDDIM_FLAG_ARCHIVED);
1175
1176
if(!(rd_flags & RRDDIM_FLAG_ARCHIVED)) {
1177
NETDATA_DOUBLE value = strtondd(value_str, NULL);
1083
- SN_FLAGS flags = SN_FLAG_NONE;
1084
-
1085
- char c;
1086
- while ((c = *flags_str++)) {
1087
- switch (c) {
1088
- case 'R':
1089
- flags |= SN_FLAG_RESET;
1090
- break;
1091
-
1092
- case 'E':
1093
- flags |= SN_EMPTY_SLOT;
1094
- value = NAN;
1095
- break;
1096
-
1097
- default:
1098
- error("unknown flag '%c'", c);
1099
- break;
1100
- }
1101
- }
1178
+ SN_FLAGS flags = pluginsd_parse_storage_number_flags(flags_str);
1179
1103
- if (!netdata_double_isnumber(value)) {
1180
+ if (!netdata_double_isnumber(value) || (flags == SN_EMPTY_SLOT)) {
1181
value = NAN;
1182
flags = SN_EMPTY_SLOT;
1183
}
1184
1108
- rrddim_store_metric(rd, ((PARSER_USER_OBJECT *) user)->replay.end_time_ut, value, flags);
1109
- rd->last_collected_time.tv_sec = ((PARSER_USER_OBJECT *) user)->replay.end_time;
1185
+ rrddim_store_metric(rd, u->replay.end_time_ut, value, flags);
1186
+ rd->last_collected_time.tv_sec = u->replay.end_time;
1187
rd->last_collected_time.tv_usec = 0;
1188
rd->collections_counter++;
1189
}
1194
}
1195
}
1196
1120
- rrddim_acquired_release(rda);
1197
return PARSER_RC_OK;
1198
}
1199
1209
char *last_stored_value_str = get_word(words, num_words, 5);
1210
1211
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE);
1136
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
1212
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1213
1214
RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1139
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
1215
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1216
1141
- RRDDIM_ACQUIRED *rda = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE);
1142
- if(!rda) return PLUGINSD_DISABLE_PLUGIN(user);
1217
+ RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE);
1218
+ if(!rd) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1219
1144
- RRDDIM *rd = rrddim_acquired_to_rrddim(rda);
1220
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;
1221
usec_t last_collected_ut = last_collected_ut_str ? str2ull(last_collected_ut_str) : 0;
1222
if(last_collected_ut > dim_last_collected_ut) {
1148
- rd->last_collected_time.tv_sec = last_collected_ut / USEC_PER_SEC;
1149
- rd->last_collected_time.tv_usec = last_collected_ut % USEC_PER_SEC;
1223
+ rd->last_collected_time.tv_sec = (time_t)(last_collected_ut / USEC_PER_SEC);
1224
+ rd->last_collected_time.tv_usec = (last_collected_ut % USEC_PER_SEC);
1225
}
1226
1227
rd->last_collected_value = last_collected_value_str ? str2ll(last_collected_value_str, NULL) : 0;
1228
rd->last_calculated_value = last_calculated_value_str ? str2ndd(last_calculated_value_str, NULL) : 0;
1229
rd->last_stored_value = last_stored_value_str ? str2ndd(last_stored_value_str, NULL) : 0.0;
1155
- rrddim_acquired_release(rda);
1230
+
1231
return PARSER_RC_OK;
1232
}
1233
1240
char *last_updated_ut_str = get_word(words, num_words, 2);
1241
1242
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_RRDSET_STATE);
1168
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
1243
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1244
1245
RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_RRDSET_STATE, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1171
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
1246
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1247
1248
usec_t chart_last_collected_ut = (usec_t)st->last_collected_time.tv_sec * USEC_PER_SEC + (usec_t)st->last_collected_time.tv_usec;
1249
usec_t last_collected_ut = last_collected_ut_str ? str2ull(last_collected_ut_str) : 0;
1250
if(last_collected_ut > chart_last_collected_ut) {
1176
- st->last_collected_time.tv_sec = last_collected_ut / USEC_PER_SEC;
1177
- st->last_collected_time.tv_usec = last_collected_ut % USEC_PER_SEC;
1251
+ st->last_collected_time.tv_sec = (time_t)(last_collected_ut / USEC_PER_SEC);
1252
+ st->last_collected_time.tv_usec = (last_collected_ut % USEC_PER_SEC);
1253
}
1254
1255
usec_t chart_last_updated_ut = (usec_t)st->last_updated.tv_sec * USEC_PER_SEC + (usec_t)st->last_updated.tv_usec;
1256
usec_t last_updated_ut = last_updated_ut_str ? str2ull(last_updated_ut_str) : 0;
1257
if(last_updated_ut > chart_last_updated_ut) {
1183
- st->last_updated.tv_sec = last_updated_ut / USEC_PER_SEC;
1184
- st->last_updated.tv_usec = last_updated_ut % USEC_PER_SEC;
1258
+ st->last_updated.tv_sec = (time_t)(last_updated_ut / USEC_PER_SEC);
1259
+ st->last_updated.tv_usec = (last_updated_ut % USEC_PER_SEC);
1260
}
1261
1262
st->counter++;
1294
PARSER_USER_OBJECT *user_object = user;
1295
1296
RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_END);
1222
- if(!host) return PLUGINSD_DISABLE_PLUGIN(user);
1297
+ if(!host) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1298
1299
RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_END, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1225
- if(!st) return PLUGINSD_DISABLE_PLUGIN(user);
1300
+ if(!st) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1301
1302
#ifdef NETDATA_LOG_REPLICATION_REQUESTS
1303
internal_error(true,
1310
);
1311
#endif
1312
1238
- ((PARSER_USER_OBJECT *) user)->st = NULL;
1239
- ((PARSER_USER_OBJECT *) user)->count++;
1313
+ ((PARSER_USER_OBJECT *) user)->data_collections_count++;
1314
1315
if(((PARSER_USER_OBJECT *) user)->replay.rset_enabled && st->rrdhost->receiver) {
1316
time_t now = now_realtime_sec();
1356
internal_error(true, "REPLAY ERROR: 'host:%s/chart:%s' got a " PLUGINSD_KEYWORD_REPLAY_END " with enable_streaming = true, but there is no replication in progress for this chart.",
1357
rrdhost_hostname(host), rrdset_id(st));
1358
#endif
1359
+
1360
+ pluginsd_set_chart_from_parent(user, NULL, PLUGINSD_KEYWORD_REPLAY_END);
1361
+
1362
worker_set_metric(WORKER_RECEIVER_JOB_REPLICATION_COMPLETION, 100.0);
1363
1364
return PARSER_RC_OK;
1365
}
1366
1367
+ pluginsd_set_chart_from_parent(user, NULL, PLUGINSD_KEYWORD_REPLAY_END);
1368
+
1369
rrdcontext_updated_retention_rrdset(st);
1370
1371
bool ok = replicate_chart_request(send_to_plugin, user_object->parser, host, st,
1374
return ok ? PARSER_RC_OK : PARSER_RC_ERROR;
1375
}
1376
1377
+PARSER_RC pluginsd_begin_v2(char **words, size_t num_words, void *user) {
1378
+ timing_init();
1379
+
1380
+ char *id = get_word(words, num_words, 1);
1381
+ char *update_every_str = get_word(words, num_words, 2);
1382
+ char *end_time_str = get_word(words, num_words, 3);
1383
+ char *wall_clock_time_str = get_word(words, num_words, 4);
1384
+
1385
+ if(unlikely(!id || !update_every_str || !end_time_str || !wall_clock_time_str))
1386
+ return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_BEGIN_V2, "missing parameters");
1387
+
1388
+ RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_BEGIN_V2);
1389
+ if(unlikely(!host)) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1390
+
1391
+ timing_step(TIMING_STEP_BEGIN2_PREPARE);
1392
+
1393
+ RRDSET *st = pluginsd_find_chart(host, id, PLUGINSD_KEYWORD_BEGIN_V2);
1394
+ if(unlikely(!st)) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1395
+
1396
+ pluginsd_set_chart_from_parent(user, st, PLUGINSD_KEYWORD_BEGIN_V2);
1397
+
1398
+ if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE | RRDSET_FLAG_ARCHIVED)))
1399
+ rrdset_isnot_obsolete(st);
1400
+
1401
+ timing_step(TIMING_STEP_BEGIN2_FIND_CHART);
1402
+
1403
+ // ------------------------------------------------------------------------
1404
+ // parse the parameters
1405
+
1406
+ time_t update_every = (time_t)str2ull_hex_or_dec(update_every_str);
1407
+ time_t end_time = (time_t)str2ull_hex_or_dec(end_time_str);
1408
+
1409
+ time_t wall_clock_time;
1410
+ if(likely(*wall_clock_time_str == '#'))
1411
+ wall_clock_time = end_time;
1412
+ else
1413
+ wall_clock_time = (time_t)str2ull_hex_or_dec(wall_clock_time_str);
1414
+
1415
+ if (unlikely(update_every != st->update_every))
1416
+ rrdset_set_update_every_s(st, update_every);
1417
+
1418
+ timing_step(TIMING_STEP_BEGIN2_PARSE);
1419
+
1420
+ // ------------------------------------------------------------------------
1421
+ // prepare our state
1422
+
1423
+ pluginsd_lock_rrdset_data_collection(user);
1424
+
1425
+ PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user;
1426
+ u->v2.update_every = update_every;
1427
+ u->v2.end_time = end_time;
1428
+ u->v2.wall_clock_time = wall_clock_time;
1429
+ u->v2.ml_locked = ml_chart_update_begin(st);
1430
+
1431
+ timing_step(TIMING_STEP_BEGIN2_ML);
1432
+
1433
+ // ------------------------------------------------------------------------
1434
+ // propagate it forward in v2
1435
+
1436
+ if(!u->v2.stream_buffer.wb && rrdhost_has_rrdpush_sender_enabled(st->rrdhost))
1437
+ u->v2.stream_buffer = rrdset_push_metric_initialize(u->st, wall_clock_time);
1438
+
1439
+ if(u->v2.stream_buffer.v2 && u->v2.stream_buffer.wb) {
1440
+ BUFFER *wb = u->v2.stream_buffer.wb;
1441
+
1442
+ buffer_need_bytes(wb, 1024);
1443
+
1444
+ if(unlikely(u->v2.stream_buffer.begin_v2_added))
1445
+ buffer_fast_strcat(wb, PLUGINSD_KEYWORD_END_V2 "\n", sizeof(PLUGINSD_KEYWORD_END_V2) - 1 + 1);
1446
+
1447
+ buffer_fast_strcat(wb, PLUGINSD_KEYWORD_BEGIN_V2 " '", sizeof(PLUGINSD_KEYWORD_BEGIN_V2) - 1 + 2);
1448
+ buffer_fast_strcat(wb, rrdset_id(st), string_strlen(st->id));
1449
+ buffer_fast_strcat(wb, "' ", 2);
1450
+ buffer_strcat(wb, update_every_str);
1451
+ buffer_fast_strcat(wb, " ", 1);
1452
+ buffer_strcat(wb, end_time_str);
1453
+ buffer_fast_strcat(wb, " ", 1);
1454
+ buffer_strcat(wb, wall_clock_time_str);
1455
+ buffer_fast_strcat(wb, "\n", 1);
1456
+
1457
+ u->v2.stream_buffer.last_point_end_time_s = end_time;
1458
+ u->v2.stream_buffer.begin_v2_added = true;
1459
+ }
1460
+
1461
+ timing_step(TIMING_STEP_BEGIN2_PROPAGATE);
1462
+
1463
+ // ------------------------------------------------------------------------
1464
+ // store it
1465
+
1466
+ st->last_collected_time.tv_sec = end_time;
1467
+ st->last_collected_time.tv_usec = 0;
1468
+ st->last_updated.tv_sec = end_time;
1469
+ st->last_updated.tv_usec = 0;
1470
+ st->counter++;
1471
+ st->counter_done++;
1472
+
1473
+ // these are only needed for db mode RAM, SAVE, MAP, ALLOC
1474
+ st->current_entry++;
1475
+ if(st->current_entry >= st->entries)
1476
+ st->current_entry -= st->entries;
1477
+
1478
+ timing_step(TIMING_STEP_BEGIN2_STORE);
1479
+
1480
+ return PARSER_RC_OK;
1481
+}
1482
+
1483
+PARSER_RC pluginsd_set_v2(char **words, size_t num_words, void *user) {
1484
+ timing_init();
1485
+
1486
+ char *dimension = get_word(words, num_words, 1);
1487
+ char *collected_str = get_word(words, num_words, 2);
1488
+ char *value_str = get_word(words, num_words, 3);
1489
+ char *flags_str = get_word(words, num_words, 4);
1490
+
1491
+ if(unlikely(!dimension || !collected_str || !value_str || !flags_str))
1492
+ return PLUGINSD_DISABLE_PLUGIN(user, PLUGINSD_KEYWORD_SET_V2, "missing parameters");
1493
+
1494
+ PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user;
1495
+
1496
+ RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_SET_V2);
1497
+ if(unlikely(!host)) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1498
+
1499
+ RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_SET_V2, PLUGINSD_KEYWORD_BEGIN_V2);
1500
+ if(unlikely(!st)) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1501
+
1502
+ timing_step(TIMING_STEP_SET2_PREPARE);
1503
+
1504
+ RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_SET_V2);
1505
+ if(unlikely(!rd)) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1506
+
1507
+ if(unlikely(rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE | RRDDIM_FLAG_ARCHIVED)))
1508
+ rrddim_isnot_obsolete(st, rd);
1509
+
1510
+ timing_step(TIMING_STEP_SET2_LOOKUP_DIMENSION);
1511
+
1512
+ // ------------------------------------------------------------------------
1513
+ // parse the parameters
1514
+
1515
+ collected_number collected_value = (collected_number)str2ll_hex_or_dec(collected_str);
1516
+
1517
+ NETDATA_DOUBLE value;
1518
+ if(*value_str == '#')
1519
+ value = (NETDATA_DOUBLE)collected_value;
1520
+ else
1521
+ value = strtondd(value_str, NULL);
1522
+
1523
+ SN_FLAGS flags = pluginsd_parse_storage_number_flags(flags_str);
1524
+
1525
+ timing_step(TIMING_STEP_SET2_PARSE);
1526
+
1527
+ // ------------------------------------------------------------------------
1528
+ // check value and ML
1529
+
1530
+ if (unlikely(!netdata_double_isnumber(value) || (flags == SN_EMPTY_SLOT))) {
1531
+ value = NAN;
1532
+ flags = SN_EMPTY_SLOT;
1533
+
1534
+ if(u->v2.ml_locked)
1535
+ ml_is_anomalous(rd, u->v2.end_time, 0, false);
1536
+ }
1537
+ else if(u->v2.ml_locked) {
1538
+ if (ml_is_anomalous(rd, u->v2.end_time, value, true)) {
1539
+ // clear anomaly bit: 0 -> is anomalous, 1 -> not anomalous
1540
+ flags &= ~((storage_number) SN_FLAG_NOT_ANOMALOUS);
1541
+ }
1542
+ else
1543
+ flags |= SN_FLAG_NOT_ANOMALOUS;
1544
+ }
1545
+
1546
+ timing_step(TIMING_STEP_SET2_ML);
1547
+
1548
+ // ------------------------------------------------------------------------
1549
+ // propagate it forward in v2
1550
+
1551
+ if(u->v2.stream_buffer.v2 && u->v2.stream_buffer.begin_v2_added && u->v2.stream_buffer.wb) {
1552
+ BUFFER *wb = u->v2.stream_buffer.wb;
1553
+ buffer_need_bytes(wb, 1024);
1554
+ buffer_fast_strcat(wb, PLUGINSD_KEYWORD_SET_V2 " '", sizeof(PLUGINSD_KEYWORD_SET_V2) - 1 + 2);
1555
+ buffer_fast_strcat(wb, rrddim_id(rd), string_strlen(rd->id));
1556
+ buffer_fast_strcat(wb, "' ", 2);
1557
+ buffer_strcat(wb, collected_str);
1558
+ buffer_fast_strcat(wb, " ", 1);
1559
+ buffer_strcat(wb, value_str);
1560
+ buffer_fast_strcat(wb, " ", 1);
1561
+ buffer_print_sn_flags(wb, flags, true);
1562
+ buffer_fast_strcat(wb, "\n", 1);
1563
+ }
1564
+
1565
+ timing_step(TIMING_STEP_SET2_PROPAGATE);
1566
+
1567
+ // ------------------------------------------------------------------------
1568
+ // store it
1569
+
1570
+ rrddim_store_metric(rd, u->v2.end_time * USEC_PER_SEC, value, flags);
1571
+ rd->last_collected_time.tv_sec = u->v2.end_time;
1572
+ rd->last_collected_time.tv_usec = 0;
1573
+ rd->last_collected_value = collected_value;
1574
+ rd->last_stored_value = value;
1575
+ rd->last_calculated_value = value;
1576
+ rd->collections_counter++;
1577
+ rd->updated = true;
1578
+
1579
+ timing_step(TIMING_STEP_SET2_STORE);
1580
+
1581
+ return PARSER_RC_OK;
1582
+}
1583
+
1584
+void pluginsd_cleanup_v2(void *user) {
1585
+ // this is called when the thread is stopped while processing
1586
+ pluginsd_set_chart_from_parent(user, NULL, "THREAD CLEANUP");
1587
+}
1588
+
1589
+PARSER_RC pluginsd_end_v2(char **words __maybe_unused, size_t num_words __maybe_unused, void *user) {
1590
+ timing_init();
1591
+
1592
+ RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_END_V2);
1593
+ if(unlikely(!host)) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1594
+
1595
+ RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_END_V2, PLUGINSD_KEYWORD_BEGIN_V2);
1596
+ if(unlikely(!st)) return PLUGINSD_DISABLE_PLUGIN(user, NULL, NULL);
1597
+
1598
+ PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user;
1599
+ u->data_collections_count++;
1600
+
1601
+ timing_step(TIMING_STEP_END2_PREPARE);
1602
+
1603
+ // ------------------------------------------------------------------------
1604
+ // propagate the whole chart update in v1
1605
+
1606
+ if(unlikely(!u->v2.stream_buffer.v2 && !u->v2.stream_buffer.begin_v2_added && u->v2.stream_buffer.wb))
1607
+ rrdset_push_metrics_v1(&u->v2.stream_buffer, st);
1608
+
1609
+ timing_step(TIMING_STEP_END2_PUSH_V1);
1610
+
1611
+ // ------------------------------------------------------------------------
1612
+ // unblock data collection
1613
+
1614
+ ml_chart_update_end(st);
1615
+ u->v2.ml_locked = false;
1616
+
1617
+ timing_step(TIMING_STEP_END2_ML);
1618
+
1619
+ pluginsd_unlock_rrdset_data_collection(user);
1620
+ rrdcontext_collected_rrdset(st);
1621
+ store_metric_collection_completed();
1622
+
1623
+ timing_step(TIMING_STEP_END2_RRDSET);
1624
+
1625
+ // ------------------------------------------------------------------------
1626
+ // propagate it forward
1627
+
1628
+ rrdset_push_metrics_finished(&u->v2.stream_buffer, st);
1629
+
1630
+ timing_step(TIMING_STEP_END2_PROPAGATE);
1631
+
1632
+ // ------------------------------------------------------------------------
1633
+ // cleanup RRDSET / RRDDIM
1634
+
1635
+ RRDDIM *rd;
1636
+ rrddim_foreach_read(rd, st) {
1637
+ rd->calculated_value = 0;
1638
+ rd->collected_value = 0;
1639
+ rd->updated = false;
1640
+ }
1641
+ rrddim_foreach_done(rd);
1642
+
1643
+ // ------------------------------------------------------------------------
1644
+ // reset state
1645
+
1646
+ u->v2 = (struct parser_user_object_v2){ 0 };
1647
+
1648
+ timing_step(TIMING_STEP_END2_STORE);
1649
+ timing_report();
1650
+
1651
+ return PARSER_RC_OK;
1652
+}
1653
+
1654
static void pluginsd_process_thread_cleanup(void *ptr) {
1655
PARSER *parser = (PARSER *)ptr;
1656
+
1657
+ if(parser->user_cleanup_cb)
1658
+ parser->user_cleanup_cb(parser->user);
1659
+
1660
rrd_collector_finished();
1661
parser_destroy(parser);
1662
}
1695
};
1696
1697
// fp_plugin_output = our input; fp_plugin_input = our output
1338
- PARSER *parser = parser_init(host, &user, fp_plugin_output, fp_plugin_input, -1, PARSER_INPUT_SPLIT, NULL);
1698
+ PARSER *parser = parser_init(host, &user, NULL, fp_plugin_output, fp_plugin_input, -1, PARSER_INPUT_SPLIT, NULL);
1699
1700
rrd_collector_started();
1701
1714
netdata_thread_cleanup_pop(1);
1715
1716
cd->unsafe.enabled = user.enabled;
1357
- size_t count = user.count;
1717
+ size_t count = user.data_collections_count;
1718
1719
if (likely(count)) {
1720
cd->successful_collections += count;