4
5
#define LOG_FUNCTIONS false
6
7
-#define SERVING_STREAMING(parser) (parser->repertoire == PARSER_INIT_STREAMING)
8
-#define SERVING_PLUGINSD(parser) (parser->repertoire == PARSER_INIT_PLUGINSD)
7
+#define SERVING_STREAMING(parser) ((parser)->repertoire == PARSER_INIT_STREAMING)
8
+#define SERVING_PLUGINSD(parser) ((parser)->repertoire == PARSER_INIT_PLUGINSD)
9
10
static ssize_t send_to_plugin(const char *txt, void *data) {
11
PARSER *parser = data;
110
return false;
111
}
112
113
-void pluginsd_rrdset_cleanup(RRDSET *st) {
114
- spinlock_lock(&st->pluginsd.spinlock);
115
-
116
- for(size_t i = 0; i < st->pluginsd.size ; i++) {
117
- rrddim_acquired_release(st->pluginsd.rda[i]); // can be NULL
118
- st->pluginsd.rda[i] = NULL;
119
- }
120
-
121
- freez(st->pluginsd.rda);
122
- st->pluginsd.collector_tid = 0;
123
- st->pluginsd.rda = NULL;
124
- st->pluginsd.size = 0;
125
- st->pluginsd.pos = 0;
126
-
127
- spinlock_unlock(&st->pluginsd.spinlock);
128
-}
129
-
113
static inline void pluginsd_unlock_previous_scope_chart(PARSER *parser, const char *keyword, bool stale) {
114
if(unlikely(pluginsd_unlock_rrdset_data_collection(parser))) {
115
if(stale)
133
134
static inline void pluginsd_clear_scope_chart(PARSER *parser, const char *keyword) {
135
pluginsd_unlock_previous_scope_chart(parser, keyword, true);
136
+
137
+ if(parser->user.cleanup_slots && parser->user.st)
138
+ rrdset_pluginsd_receive_unslot(parser->user.st);
139
+
140
parser->user.st = NULL;
141
+ parser->user.cleanup_slots = false;
142
}
143
144
static inline bool pluginsd_set_scope_chart(PARSER *parser, RRDSET *st, const char *keyword) {
164
165
pluginsd_clear_scope_chart(parser, keyword);
166
179
- size_t dims = dictionary_entries(st->rrddim_root_index);
180
- if(unlikely(st->pluginsd.size < dims)) {
181
- st->pluginsd.rda = reallocz(st->pluginsd.rda, dims * sizeof(RRDDIM_ACQUIRED *));
167
+ st->pluginsd.pos = 0;
168
+ parser->user.st = st;
169
+ parser->user.cleanup_slots = false;
170
+
171
+ return true;
172
+}
173
+
174
+static inline void pluginsd_rrddim_put_to_slot(PARSER *parser, RRDSET *st, RRDDIM *rd, ssize_t slot, bool obsolete) {
175
+ size_t wanted_size = st->pluginsd.size;
176
+
177
+ if(slot >= 1) {
178
+ st->pluginsd.with_slots = true;
179
+ wanted_size = slot;
180
+ }
181
+ else
182
+ wanted_size = dictionary_entries(st->rrddim_root_index);
183
+
184
+ if(wanted_size > st->pluginsd.size) {
185
+ st->pluginsd.prd_array = reallocz(st->pluginsd.prd_array, wanted_size * sizeof(struct pluginsd_rrddim));
186
187
// initialize the empty slots
184
- for(ssize_t i = (ssize_t)dims - 1; i >= (ssize_t)st->pluginsd.size ;i--)
185
- st->pluginsd.rda[i] = NULL;
188
+ for(ssize_t i = (ssize_t) wanted_size - 1; i >= (ssize_t) st->pluginsd.size; i--) {
189
+ st->pluginsd.prd_array[i].rda = NULL;
190
+ st->pluginsd.prd_array[i].rd = NULL;
191
+ st->pluginsd.prd_array[i].id = NULL;
192
+ }
193
187
- st->pluginsd.size = dims;
194
+ st->pluginsd.size = wanted_size;
195
}
196
190
- st->pluginsd.pos = 0;
191
- parser->user.st = st;
197
+ if(st->pluginsd.with_slots) {
198
+ struct pluginsd_rrddim *prd = &st->pluginsd.prd_array[slot - 1];
199
193
- return true;
200
+ if(prd->rd != rd) {
201
+ prd->rda = rrddim_find_and_acquire(st, string2str(rd->id));
202
+ prd->rd = rrddim_acquired_to_rrddim(prd->rda);
203
+ prd->id = string2str(prd->rd->id);
204
+ }
205
+
206
+ if(obsolete)
207
+ parser->user.cleanup_slots = true;
208
+ }
209
}
210
196
-static inline RRDDIM *pluginsd_acquire_dimension(RRDHOST *host, RRDSET *st, const char *dimension, const char *cmd) {
211
+static inline RRDDIM *pluginsd_acquire_dimension(RRDHOST *host, RRDSET *st, const char *dimension, ssize_t slot, const char *cmd) {
212
if (unlikely(!dimension || !*dimension)) {
213
netdata_log_error("PLUGINSD: 'host:%s/chart:%s' got a %s, without a dimension.",
214
rrdhost_hostname(host), rrdset_id(st), cmd);
215
return NULL;
216
}
217
203
- if(unlikely(st->pluginsd.pos >= st->pluginsd.size))
204
- st->pluginsd.pos = 0;
218
+ if (unlikely(!st->pluginsd.size)) {
219
+ netdata_log_error("PLUGINSD: 'host:%s/chart:%s' got a %s, but the chart has no dimensions.",
220
+ rrdhost_hostname(host), rrdset_id(st), cmd);
221
+ return NULL;
222
+ }
223
+
224
+ struct pluginsd_rrddim *prd;
225
+ RRDDIM *rd;
226
206
- RRDDIM_ACQUIRED *rda = st->pluginsd.rda[st->pluginsd.pos];
227
+ if(likely(st->pluginsd.with_slots)) {
228
+ // caching with slots
229
208
- if(likely(rda)) {
209
- RRDDIM *rd = rrddim_acquired_to_rrddim(rda);
210
- if (likely(rd && string_strcmp(rd->id, dimension) == 0)) {
211
- // we found a cached RDA
212
- st->pluginsd.pos++;
230
+ if(unlikely(slot < 1 || slot > st->pluginsd.size)) {
231
+ netdata_log_error("PLUGINSD: 'host:%s/chart:%s' got a %s with slot %zd, but slots in the range [1 - %u] are expected.",
232
+ rrdhost_hostname(host), rrdset_id(st), cmd, slot, st->pluginsd.size);
233
+ return NULL;
234
+ }
235
+
236
+ prd = &st->pluginsd.prd_array[slot - 1];
237
+
238
+ rd = prd->rd;
239
+ if(likely(rd)) {
240
+#ifdef NETDATA_INTERNAL_CHECKS
241
+ if(strcmp(prd->id, dimension) != 0) {
242
+ ssize_t t;
243
+ for(t = 0; t < st->pluginsd.size ;t++) {
244
+ if (strcmp(st->pluginsd.prd_array[t].id, dimension) == 0)
245
+ break;
246
+ }
247
+ if(t >= st->pluginsd.size)
248
+ t = -1;
249
+
250
+ internal_fatal(true,
251
+ "PLUGINSD: expected to find dimension '%s' on slot %zd, but found '%s', "
252
+ "the right slot is %zd",
253
+ dimension, slot, prd->id, t);
254
+ }
255
+#endif
256
return rd;
257
}
215
- else {
216
- // the collector is sending dimensions in a different order
217
- // release the previous one, to reuse this slot
218
- rrddim_acquired_release(rda);
219
- st->pluginsd.rda[st->pluginsd.pos] = NULL;
258
+ }
259
+ else {
260
+ // caching without slots
261
+
262
+ if(unlikely(st->pluginsd.pos >= st->pluginsd.size))
263
+ st->pluginsd.pos = 0;
264
+
265
+ prd = &st->pluginsd.prd_array[st->pluginsd.pos++];
266
+
267
+ rd = prd->rd;
268
+ if(likely(rd)) {
269
+ const char *id = prd->id;
270
+
271
+ if(strcmp(id, dimension) == 0) {
272
+ // we found it cached
273
+ return rd;
274
+ }
275
+ else {
276
+ // the cached one is not good for us
277
+ rrddim_acquired_release(prd->rda);
278
+ prd->rda = NULL;
279
+ prd->rd = rd = NULL;
280
+ prd->id = NULL;
281
+ }
282
}
283
}
284
223
- rda = rrddim_find_and_acquire(st, dimension);
285
+ // we need to find the dimension and set it to prd
286
+
287
+ RRDDIM_ACQUIRED *rda = rrddim_find_and_acquire(st, dimension);
288
if (unlikely(!rda)) {
289
netdata_log_error("PLUGINSD: 'host:%s/chart:%s/dim:%s' got a %s but dimension does not exist.",
226
- rrdhost_hostname(host), rrdset_id(st), dimension, cmd);
290
+ rrdhost_hostname(host), rrdset_id(st), dimension, cmd);
291
292
return NULL;
293
}
294
231
- st->pluginsd.rda[st->pluginsd.pos++] = rda;
295
+ prd->rda = rda;
296
+ prd->rd = rd = rrddim_acquired_to_rrddim(rda);
297
+ prd->id = string2str(rd->id);
298
233
- return rrddim_acquired_to_rrddim(rda);
299
+ return rd;
300
}
301
302
static inline RRDSET *pluginsd_find_chart(RRDHOST *host, const char *chart, const char *cmd) {
314
return st;
315
}
316
317
+static inline ssize_t pluginsd_parse_rrd_slot(char **words, size_t num_words) {
318
+ ssize_t slot = -1;
319
+ char *id = get_word(words, num_words, 1);
320
+ if(id && id[0] == PLUGINSD_KEYWORD_SLOT[0] && id[1] == PLUGINSD_KEYWORD_SLOT[1] &&
321
+ id[2] == PLUGINSD_KEYWORD_SLOT[2] && id[3] == PLUGINSD_KEYWORD_SLOT[3] && id[4] == ':') {
322
+ slot = (ssize_t) str2ull_encoded(&id[5]);
323
+ if(slot < 0) slot = 0; // to make the caller increment its idx of the words
324
+ }
325
+
326
+ return slot;
327
+}
328
+
329
+static inline void pluginsd_rrdset_cache_put_to_slot(PARSER *parser, RRDSET *st, ssize_t slot, bool obsolete) {
330
+ // clean possible old cached data
331
+ rrdset_pluginsd_receive_unslot(st);
332
+
333
+ if(unlikely(slot < 1 || slot >= INT32_MAX))
334
+ return;
335
+
336
+ RRDHOST *host = st->rrdhost;
337
+
338
+ if(unlikely((size_t)slot > host->rrdpush.receive.pluginsd_chart_slots.size)) {
339
+ spinlock_lock(&host->rrdpush.receive.pluginsd_chart_slots.spinlock);
340
+ size_t old_slots = host->rrdpush.receive.pluginsd_chart_slots.size;
341
+ size_t new_slots = (old_slots < PLUGINSD_MIN_RRDSET_POINTERS_CACHE) ? PLUGINSD_MIN_RRDSET_POINTERS_CACHE : old_slots * 2;
342
+
343
+ if(new_slots < (size_t)slot)
344
+ new_slots = slot;
345
+
346
+ host->rrdpush.receive.pluginsd_chart_slots.array =
347
+ reallocz(host->rrdpush.receive.pluginsd_chart_slots.array, new_slots * sizeof(RRDSET *));
348
+
349
+ for(size_t i = old_slots; i < new_slots ;i++)
350
+ host->rrdpush.receive.pluginsd_chart_slots.array[i] = NULL;
351
+
352
+ host->rrdpush.receive.pluginsd_chart_slots.size = new_slots;
353
+ spinlock_unlock(&host->rrdpush.receive.pluginsd_chart_slots.spinlock);
354
+ }
355
+
356
+ host->rrdpush.receive.pluginsd_chart_slots.array[slot - 1] = st;
357
+ st->pluginsd.last_slot = (int32_t)slot - 1;
358
+ parser->user.cleanup_slots = obsolete;
359
+}
360
+
361
+static inline RRDSET *pluginsd_rrdset_cache_get_from_slot(PARSER *parser, RRDHOST *host, const char *id, ssize_t slot, const char *keyword) {
362
+ if(unlikely(slot < 1 || (size_t)slot > host->rrdpush.receive.pluginsd_chart_slots.size))
363
+ return pluginsd_find_chart(host, id, keyword);
364
+
365
+ RRDSET *st = host->rrdpush.receive.pluginsd_chart_slots.array[slot - 1];
366
+
367
+ if(!st) {
368
+ st = pluginsd_find_chart(host, id, keyword);
369
+ if(st)
370
+ pluginsd_rrdset_cache_put_to_slot(parser, st, slot, rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE));
371
+ }
372
+ else {
373
+ internal_fatal(string_strcmp(st->id, id) != 0,
374
+ "PLUGINSD: wrong chart in slot %zd, expected '%s', found '%s'",
375
+ slot - 1, id, string2str(st->id));
376
+ }
377
+
378
+ return st;
379
+}
380
+
381
static inline PARSER_RC PLUGINSD_DISABLE_PLUGIN(PARSER *parser, const char *keyword, const char *msg) {
382
parser->user.enabled = 0;
383
390
}
391
392
static inline PARSER_RC pluginsd_set(char **words, size_t num_words, PARSER *parser) {
263
- char *dimension = get_word(words, num_words, 1);
264
- char *value = get_word(words, num_words, 2);
393
+ int idx = 1;
394
+ ssize_t slot = pluginsd_parse_rrd_slot(words, num_words);
395
+ if(slot >= 0) idx++;
396
+
397
+ char *dimension = get_word(words, num_words, idx++);
398
+ char *value = get_word(words, num_words, idx++);
399
400
RRDHOST *host = pluginsd_require_scope_host(parser, PLUGINSD_KEYWORD_SET);
401
if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
403
RRDSET *st = pluginsd_require_scope_chart(parser, PLUGINSD_KEYWORD_SET, PLUGINSD_KEYWORD_CHART);
404
if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
405
272
- RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_SET);
406
+ RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, slot, PLUGINSD_KEYWORD_SET);
407
if(!rd) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
408
409
st->pluginsd.set = true;
419
}
420
421
static inline PARSER_RC pluginsd_begin(char **words, size_t num_words, PARSER *parser) {
288
- char *id = get_word(words, num_words, 1);
289
- char *microseconds_txt = get_word(words, num_words, 2);
422
+ int idx = 1;
423
+ ssize_t slot = pluginsd_parse_rrd_slot(words, num_words);
424
+ if(slot >= 0) idx++;
425
+
426
+ char *id = get_word(words, num_words, idx++);
427
+ char *microseconds_txt = get_word(words, num_words, idx++);
428
429
RRDHOST *host = pluginsd_require_scope_host(parser, PLUGINSD_KEYWORD_BEGIN);
430
if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
431
294
- RRDSET *st = pluginsd_find_chart(host, id, PLUGINSD_KEYWORD_BEGIN);
432
+ RRDSET *st = pluginsd_rrdset_cache_get_from_slot(parser, host, id, slot, PLUGINSD_KEYWORD_BEGIN);
433
if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
434
435
if(!pluginsd_set_scope_chart(parser, st, PLUGINSD_KEYWORD_BEGIN))
630
RRDHOST *host = pluginsd_require_scope_host(parser, PLUGINSD_KEYWORD_CHART);
631
if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
632
495
- char *type = get_word(words, num_words, 1);
496
- char *name = get_word(words, num_words, 2);
497
- char *title = get_word(words, num_words, 3);
498
- char *units = get_word(words, num_words, 4);
499
- char *family = get_word(words, num_words, 5);
500
- char *context = get_word(words, num_words, 6);
501
- char *chart = get_word(words, num_words, 7);
502
- char *priority_s = get_word(words, num_words, 8);
503
- char *update_every_s = get_word(words, num_words, 9);
504
- char *options = get_word(words, num_words, 10);
505
- char *plugin = get_word(words, num_words, 11);
506
- char *module = get_word(words, num_words, 12);
633
+ int idx = 1;
634
+ ssize_t slot = pluginsd_parse_rrd_slot(words, num_words);
635
+ if(slot >= 0) idx++;
636
+
637
+ char *type = get_word(words, num_words, idx++);
638
+ char *name = get_word(words, num_words, idx++);
639
+ char *title = get_word(words, num_words, idx++);
640
+ char *units = get_word(words, num_words, idx++);
641
+ char *family = get_word(words, num_words, idx++);
642
+ char *context = get_word(words, num_words, idx++);
643
+ char *chart = get_word(words, num_words, idx++);
644
+ char *priority_s = get_word(words, num_words, idx++);
645
+ char *update_every_s = get_word(words, num_words, idx++);
646
+ char *options = get_word(words, num_words, idx++);
647
+ char *plugin = get_word(words, num_words, idx++);
648
+ char *module = get_word(words, num_words, idx++);
649
650
// parse the id from type
651
char *id = NULL;
712
module, priority, update_every,
713
chart_type);
714
715
+ bool obsolete = false;
716
if (likely(st)) {
717
if (options && *options) {
718
if (strstr(options, "obsolete")) {
576
- pluginsd_rrdset_cleanup(st);
577
- rrdset_is_obsolete(st);
719
+ rrdset_is_obsolete___safe_from_collector_thread(st);
720
+ obsolete = true;
721
}
722
else
580
- rrdset_isnot_obsolete(st);
723
+ rrdset_isnot_obsolete___safe_from_collector_thread(st);
724
725
if (strstr(options, "detail"))
726
rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
738
rrdset_flag_clear(st, RRDSET_FLAG_STORE_FIRST);
739
}
740
else {
598
- rrdset_isnot_obsolete(st);
741
+ rrdset_isnot_obsolete___safe_from_collector_thread(st);
742
rrdset_flag_clear(st, RRDSET_FLAG_DETAIL);
743
rrdset_flag_clear(st, RRDSET_FLAG_STORE_FIRST);
744
}
745
746
if(!pluginsd_set_scope_chart(parser, st, PLUGINSD_KEYWORD_CHART))
747
return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
748
+
749
+ pluginsd_rrdset_cache_put_to_slot(parser, st, slot, obsolete);
750
}
751
else
752
pluginsd_clear_scope_chart(parser, PLUGINSD_KEYWORD_CHART);
797
}
798
799
static inline PARSER_RC pluginsd_dimension(char **words, size_t num_words, PARSER *parser) {
655
- char *id = get_word(words, num_words, 1);
656
- char *name = get_word(words, num_words, 2);
657
- char *algorithm = get_word(words, num_words, 3);
658
- char *multiplier_s = get_word(words, num_words, 4);
659
- char *divisor_s = get_word(words, num_words, 5);
660
- char *options = get_word(words, num_words, 6);
800
+ int idx = 1;
801
+ ssize_t slot = pluginsd_parse_rrd_slot(words, num_words);
802
+ if(slot >= 0) idx++;
803
+
804
+ char *id = get_word(words, num_words, idx++);
805
+ char *name = get_word(words, num_words, idx++);
806
+ char *algorithm = get_word(words, num_words, idx++);
807
+ char *multiplier_s = get_word(words, num_words, idx++);
808
+ char *divisor_s = get_word(words, num_words, idx++);
809
+ char *options = get_word(words, num_words, idx++);
810
811
RRDHOST *host = pluginsd_require_scope_host(parser, PLUGINSD_KEYWORD_DIMENSION);
812
if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
845
int unhide_dimension = 1;
846
847
rrddim_option_clear(rd, RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS);
848
+ bool obsolete = false;
849
if (options && *options) {
700
- if (strstr(options, "obsolete") != NULL)
701
- rrddim_is_obsolete(st, rd);
850
+ if (strstr(options, "obsolete") != NULL) {
851
+ obsolete = true;
852
+ rrddim_is_obsolete___safe_from_collector_thread(st, rd);
853
+ }
854
else
703
- rrddim_isnot_obsolete(st, rd);
855
+ rrddim_isnot_obsolete___safe_from_collector_thread(st, rd);
856
857
unhide_dimension = !strstr(options, "hidden");
858
860
rrddim_option_set(rd, RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS);
861
if (strstr(options, "nooverflow") != NULL)
862
rrddim_option_set(rd, RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS);
711
- } else
712
- rrddim_isnot_obsolete(st, rd);
863
+ }
864
+ else
865
+ rrddim_isnot_obsolete___safe_from_collector_thread(st, rd);
866
867
bool should_update_dimension = false;
868
880
rrdhost_flag_set(rd->rrdset->rrdhost, RRDHOST_FLAG_METADATA_UPDATE);
881
}
882
883
+ pluginsd_rrddim_put_to_slot(parser, st, rd, slot, obsolete);
884
+
885
return PARSER_RC_OK;
886
}
887
1472
}
1473
1474
static inline PARSER_RC pluginsd_replay_begin(char **words, size_t num_words, PARSER *parser) {
1320
- char *id = get_word(words, num_words, 1);
1321
- char *start_time_str = get_word(words, num_words, 2);
1322
- char *end_time_str = get_word(words, num_words, 3);
1323
- char *child_now_str = get_word(words, num_words, 4);
1475
+ int idx = 1;
1476
+ ssize_t slot = pluginsd_parse_rrd_slot(words, num_words);
1477
+ if(slot >= 0) idx++;
1478
+
1479
+ char *id = get_word(words, num_words, idx++);
1480
+ char *start_time_str = get_word(words, num_words, idx++);
1481
+ char *end_time_str = get_word(words, num_words, idx++);
1482
+ char *child_now_str = get_word(words, num_words, idx++);
1483
1484
RRDHOST *host = pluginsd_require_scope_host(parser, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1485
if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
1488
if (likely(!id || !*id))
1489
st = pluginsd_require_scope_chart(parser, PLUGINSD_KEYWORD_REPLAY_BEGIN, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1490
else
1332
- st = pluginsd_find_chart(host, id, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1491
+ st = pluginsd_rrdset_cache_get_from_slot(parser, host, id, slot, PLUGINSD_KEYWORD_REPLAY_BEGIN);
1492
1493
if(!st) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
1494
1603
}
1604
1605
static inline PARSER_RC pluginsd_replay_set(char **words, size_t num_words, PARSER *parser) {
1447
- char *dimension = get_word(words, num_words, 1);
1448
- char *value_str = get_word(words, num_words, 2);
1449
- char *flags_str = get_word(words, num_words, 3);
1606
+ int idx = 1;
1607
+ ssize_t slot = pluginsd_parse_rrd_slot(words, num_words);
1608
+ if(slot >= 0) idx++;
1609
+
1610
+ char *dimension = get_word(words, num_words, idx++);
1611
+ char *value_str = get_word(words, num_words, idx++);
1612
+ char *flags_str = get_word(words, num_words, idx++);
1613
1614
RRDHOST *host = pluginsd_require_scope_host(parser, PLUGINSD_KEYWORD_REPLAY_SET);
1615
if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
1626
return PARSER_RC_OK;
1627
}
1628
1466
- RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_REPLAY_SET);
1629
+ RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, slot, PLUGINSD_KEYWORD_REPLAY_SET);
1630
if(!rd) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
1631
1632
st->pluginsd.set = true;
1680
if(parser->user.replay.rset_enabled == false)
1681
return PARSER_RC_OK;
1682
1520
- char *dimension = get_word(words, num_words, 1);
1521
- char *last_collected_ut_str = get_word(words, num_words, 2);
1522
- char *last_collected_value_str = get_word(words, num_words, 3);
1523
- char *last_calculated_value_str = get_word(words, num_words, 4);
1524
- char *last_stored_value_str = get_word(words, num_words, 5);
1683
+ int idx = 1;
1684
+ ssize_t slot = pluginsd_parse_rrd_slot(words, num_words);
1685
+ if(slot >= 0) idx++;
1686
+
1687
+ char *dimension = get_word(words, num_words, idx++);
1688
+ char *last_collected_ut_str = get_word(words, num_words, idx++);
1689
+ char *last_collected_value_str = get_word(words, num_words, idx++);
1690
+ char *last_calculated_value_str = get_word(words, num_words, idx++);
1691
+ char *last_stored_value_str = get_word(words, num_words, idx++);
1692
1693
RRDHOST *host = pluginsd_require_scope_host(parser, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE);
1694
if(!host) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
1702
st->pluginsd.set = false;
1703
}
1704
1538
- RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE);
1705
+ RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, slot, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE);
1706
if(!rd) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
1707
1708
usec_t dim_last_collected_ut = (usec_t)rd->collector.last_collected_time.tv_sec * USEC_PER_SEC + (usec_t)rd->collector.last_collected_time.tv_usec;
1866
static inline PARSER_RC pluginsd_begin_v2(char **words, size_t num_words, PARSER *parser) {
1867
timing_init();
1868
1702
- char *id = get_word(words, num_words, 1);
1703
- char *update_every_str = get_word(words, num_words, 2);
1704
- char *end_time_str = get_word(words, num_words, 3);
1705
- char *wall_clock_time_str = get_word(words, num_words, 4);
1869
+ int idx = 1;
1870
+ ssize_t slot = pluginsd_parse_rrd_slot(words, num_words);
1871
+ if(slot >= 0) idx++;
1872
+
1873
+ char *id = get_word(words, num_words, idx++);
1874
+ char *update_every_str = get_word(words, num_words, idx++);
1875
+ char *end_time_str = get_word(words, num_words, idx++);
1876
+ char *wall_clock_time_str = get_word(words, num_words, idx++);
1877
1878
if(unlikely(!id || !update_every_str || !end_time_str || !wall_clock_time_str))
1879
return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_BEGIN_V2, "missing parameters");
1883
1884
timing_step(TIMING_STEP_BEGIN2_PREPARE);
1885
1715
- RRDSET *st = pluginsd_find_chart(host, id, PLUGINSD_KEYWORD_BEGIN_V2);
1886
+ RRDSET *st = pluginsd_rrdset_cache_get_from_slot(parser, host, id, slot, PLUGINSD_KEYWORD_BEGIN_V2);
1887
+
1888
if(unlikely(!st)) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
1889
1890
if(!pluginsd_set_scope_chart(parser, st, PLUGINSD_KEYWORD_BEGIN_V2))
1891
return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
1892
1893
if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)))
1722
- rrdset_isnot_obsolete(st);
1894
+ rrdset_isnot_obsolete___safe_from_collector_thread(st);
1895
1896
timing_step(TIMING_STEP_BEGIN2_FIND_CHART);
1897
1931
parser->user.v2.stream_buffer = rrdset_push_metric_initialize(parser->user.st, wall_clock_time);
1932
1933
if(parser->user.v2.stream_buffer.v2 && parser->user.v2.stream_buffer.wb) {
1762
- // check if receiver and sender have the same number parsing capabilities
1934
+ // check receiver capabilities
1935
bool can_copy = stream_has_capability(&parser->user, STREAM_CAP_IEEE754) == stream_has_capability(&parser->user.v2.stream_buffer, STREAM_CAP_IEEE754);
1764
- NUMBER_ENCODING encoding = stream_has_capability(&parser->user.v2.stream_buffer, STREAM_CAP_IEEE754) ? NUMBER_ENCODING_BASE64 : NUMBER_ENCODING_HEX;
1936
+
1937
+ // check sender capabilities
1938
+ bool with_slots = stream_has_capability(&parser->user.v2.stream_buffer, STREAM_CAP_SLOTS) ? true : false;
1939
+ NUMBER_ENCODING integer_encoding = stream_has_capability(&parser->user.v2.stream_buffer, STREAM_CAP_IEEE754) ? NUMBER_ENCODING_BASE64 : NUMBER_ENCODING_HEX;
1940
1941
BUFFER *wb = parser->user.v2.stream_buffer.wb;
1942
1945
if(unlikely(parser->user.v2.stream_buffer.begin_v2_added))
1946
buffer_fast_strcat(wb, PLUGINSD_KEYWORD_END_V2 "\n", sizeof(PLUGINSD_KEYWORD_END_V2) - 1 + 1);
1947
1773
- buffer_fast_strcat(wb, PLUGINSD_KEYWORD_BEGIN_V2 " '", sizeof(PLUGINSD_KEYWORD_BEGIN_V2) - 1 + 2);
1948
+ buffer_fast_strcat(wb, PLUGINSD_KEYWORD_BEGIN_V2, sizeof(PLUGINSD_KEYWORD_BEGIN_V2) - 1);
1949
+
1950
+ if(with_slots) {
1951
+ buffer_fast_strcat(wb, " "PLUGINSD_KEYWORD_SLOT":", sizeof(PLUGINSD_KEYWORD_SLOT) - 1 + 2);
1952
+ buffer_print_uint64_encoded(wb, integer_encoding, st->rrdpush.sender.chart_slot);
1953
+ }
1954
+
1955
+ buffer_fast_strcat(wb, " '", 2);
1956
buffer_fast_strcat(wb, rrdset_id(st), string_strlen(st->id));
1957
buffer_fast_strcat(wb, "' ", 2);
1958
1959
if(can_copy)
1960
buffer_strcat(wb, update_every_str);
1961
else
1780
- buffer_print_uint64_encoded(wb, encoding, update_every);
1962
+ buffer_print_uint64_encoded(wb, integer_encoding, update_every);
1963
1964
buffer_fast_strcat(wb, " ", 1);
1965
1966
if(can_copy)
1967
buffer_strcat(wb, end_time_str);
1968
else
1787
- buffer_print_uint64_encoded(wb, encoding, end_time);
1969
+ buffer_print_uint64_encoded(wb, integer_encoding, end_time);
1970
1971
buffer_fast_strcat(wb, " ", 1);
1972
1973
if(can_copy)
1974
buffer_strcat(wb, wall_clock_time_str);
1975
else
1794
- buffer_print_uint64_encoded(wb, encoding, wall_clock_time);
1976
+ buffer_print_uint64_encoded(wb, integer_encoding, wall_clock_time);
1977
1978
buffer_fast_strcat(wb, "\n", 1);
1979
2006
static inline PARSER_RC pluginsd_set_v2(char **words, size_t num_words, PARSER *parser) {
2007
timing_init();
2008
1827
- char *dimension = get_word(words, num_words, 1);
1828
- char *collected_str = get_word(words, num_words, 2);
1829
- char *value_str = get_word(words, num_words, 3);
1830
- char *flags_str = get_word(words, num_words, 4);
2009
+ int idx = 1;
2010
+ ssize_t slot = pluginsd_parse_rrd_slot(words, num_words);
2011
+ if(slot >= 0) idx++;
2012
+
2013
+ char *dimension = get_word(words, num_words, idx++);
2014
+ char *collected_str = get_word(words, num_words, idx++);
2015
+ char *value_str = get_word(words, num_words, idx++);
2016
+ char *flags_str = get_word(words, num_words, idx++);
2017
2018
if(unlikely(!dimension || !collected_str || !value_str || !flags_str))
2019
return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_SET_V2, "missing parameters");
2026
2027
timing_step(TIMING_STEP_SET2_PREPARE);
2028
1843
- RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_SET_V2);
2029
+ RRDDIM *rd = pluginsd_acquire_dimension(host, st, dimension, slot, PLUGINSD_KEYWORD_SET_V2);
2030
if(unlikely(!rd)) return PLUGINSD_DISABLE_PLUGIN(parser, NULL, NULL);
2031
2032
st->pluginsd.set = true;
2033
2034
if(unlikely(rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE | RRDDIM_FLAG_ARCHIVED)))
1849
- rrddim_isnot_obsolete(st, rd);
2035
+ rrddim_isnot_obsolete___safe_from_collector_thread(st, rd);
2036
2037
timing_step(TIMING_STEP_SET2_LOOKUP_DIMENSION);
2038
2078
if(parser->user.v2.stream_buffer.v2 && parser->user.v2.stream_buffer.begin_v2_added && parser->user.v2.stream_buffer.wb) {
2079
// check if receiver and sender have the same number parsing capabilities
2080
bool can_copy = stream_has_capability(&parser->user, STREAM_CAP_IEEE754) == stream_has_capability(&parser->user.v2.stream_buffer, STREAM_CAP_IEEE754);
2081
+
2082
+ // check the sender capabilities
2083
+ bool with_slots = stream_has_capability(&parser->user.v2.stream_buffer, STREAM_CAP_SLOTS) ? true : false;
2084
NUMBER_ENCODING integer_encoding = stream_has_capability(&parser->user.v2.stream_buffer, STREAM_CAP_IEEE754) ? NUMBER_ENCODING_BASE64 : NUMBER_ENCODING_HEX;
2085
NUMBER_ENCODING doubles_encoding = stream_has_capability(&parser->user.v2.stream_buffer, STREAM_CAP_IEEE754) ? NUMBER_ENCODING_BASE64 : NUMBER_ENCODING_DECIMAL;
2086
2087
BUFFER *wb = parser->user.v2.stream_buffer.wb;
2088
buffer_need_bytes(wb, 1024);
1900
- buffer_fast_strcat(wb, PLUGINSD_KEYWORD_SET_V2 " '", sizeof(PLUGINSD_KEYWORD_SET_V2) - 1 + 2);
2089
+ buffer_fast_strcat(wb, PLUGINSD_KEYWORD_SET_V2, sizeof(PLUGINSD_KEYWORD_SET_V2) - 1);
2090
+
2091
+ if(with_slots) {
2092
+ buffer_fast_strcat(wb, " "PLUGINSD_KEYWORD_SLOT":", sizeof(PLUGINSD_KEYWORD_SLOT) - 1 + 2);
2093
+ buffer_print_uint64_encoded(wb, integer_encoding, rd->rrdpush.sender.dim_slot);
2094
+ }
2095
+
2096
+ buffer_fast_strcat(wb, " '", 2);
2097
buffer_fast_strcat(wb, rrddim_id(rd), string_strlen(rd->id));
2098
buffer_fast_strcat(wb, "' ", 2);
2099
if(can_copy)
2174
// ------------------------------------------------------------------------
2175
// cleanup RRDSET / RRDDIM
2176
1981
- RRDDIM *rd;
1982
- rrddim_foreach_read(rd, st) {
1983
- rd->collector.calculated_value = 0;
1984
- rd->collector.collected_value = 0;
1985
- rrddim_clear_updated(rd);
2177
+ if(likely(st->pluginsd.with_slots)) {
2178
+ for(size_t i = 0; i < st->pluginsd.size ;i++) {
2179
+ RRDDIM *rd = st->pluginsd.prd_array[i].rd;
2180
+
2181
+ if(!rd)
2182
+ continue;
2183
+
2184
+ rd->collector.calculated_value = 0;
2185
+ rd->collector.collected_value = 0;
2186
+ rrddim_clear_updated(rd);
2187
+ }
2188
+ }
2189
+ else {
2190
+ RRDDIM *rd;
2191
+ rrddim_foreach_read(rd, st){
2192
+ rd->collector.calculated_value = 0;
2193
+ rd->collector.collected_value = 0;
2194
+ rrddim_clear_updated(rd);
2195
+ }
2196
+ rrddim_foreach_done(rd);
2197
}
1987
- rrddim_foreach_done(rd);
2198
2199
// ------------------------------------------------------------------------
2200
// reset state