6
#ifdef ENABLE_NEW_CLOUD_PROTOCOL
7
#include "../../aclk/aclk_charts_api.h"
8
#include "../../aclk/aclk.h"
9
-#endif
9
11
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
10
static inline int sql_queue_chart_payload(struct aclk_database_worker_config *wc,
11
void *data, enum aclk_database_opcode opcode)
12
{
13
+ int rc;
14
if (unlikely(!wc))
15
return 1;
16
18
memset(&cmd, 0, sizeof(cmd));
19
cmd.opcode = opcode;
20
cmd.data = data;
22
- aclk_database_enq_cmd(wc, &cmd);
23
- return 0;
21
+ rc = aclk_database_enq_cmd_noblock(wc, &cmd);
22
+ return rc;
23
}
24
25
static int payload_sent(char *uuid_str, uuid_t *uuid, void *payload, size_t payload_size)
59
return send_status;
60
}
61
63
-static int aclk_add_chart_payload(char *uuid_str, uuid_t *uuid, char *claim_id, ACLK_PAYLOAD_TYPE payload_type,
64
- void *payload, size_t payload_size)
62
+static int aclk_add_chart_payload(struct aclk_database_worker_config *wc, uuid_t *uuid, char *claim_id,
63
+ ACLK_PAYLOAD_TYPE payload_type, void *payload, size_t payload_size)
64
{
65
static __thread sqlite3_stmt *res_chart = NULL;
66
int rc;
67
69
- rc = payload_sent(uuid_str, uuid, payload, payload_size);
68
+ rc = payload_sent(wc->uuid_str, uuid, payload, payload_size);
69
if (rc == 1)
70
return 0;
71
73
BUFFER *sql = buffer_create(1024);
74
75
buffer_sprintf(sql,"INSERT INTO aclk_chart_payload_%s (unique_id, uuid, claim_id, date_created, type, payload) " \
77
- "VALUES (@unique_id, @uuid, @claim_id, strftime('%%s','now'), @type, @payload);", uuid_str);
76
+ "VALUES (@unique_id, @uuid, @claim_id, strftime('%%s','now'), @type, @payload);", wc->uuid_str);
77
78
rc = prepare_statement(db_meta, (char *) buffer_tostring(sql), &res_chart);
79
buffer_free(sql);
114
rc = execute_insert(res_chart);
115
if (unlikely(rc != SQLITE_DONE))
116
error_report("Failed store chart payload event, rc = %d", rc);
117
+ else {
118
+ wc->chart_payload_count++;
119
+ time_t now = now_realtime_sec();
120
+ if (wc->rotation_after > now && wc->rotation_after < now + ACLK_DATABASE_ROTATION_DELAY)
121
+ wc->rotation_after = now + ACLK_DATABASE_ROTATION_DELAY;
122
+ }
123
124
bind_fail:
125
if (unlikely(sqlite3_reset(res_chart) != SQLITE_OK))
126
error_report("Failed to reset statement in store chart payload, rc = %d", rc);
127
return (rc != SQLITE_DONE);
128
}
124
-#endif
129
+
130
131
int aclk_add_chart_event(struct aclk_database_worker_config *wc, struct aclk_database_cmd cmd)
132
{
133
int rc = 0;
134
CHECK_SQLITE_CONNECTION(db_meta);
135
131
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
136
char *claim_id = is_agent_claimed();
137
138
RRDSET *st = cmd.data;
162
size_t size;
163
char *payload = generate_chart_instance_updated(&size, &chart_payload);
164
if (likely(payload))
161
- rc = aclk_add_chart_payload(wc->uuid_str, st->chart_uuid, claim_id, ACLK_PAYLOAD_CHART, (void *) payload, size);
165
+ rc = aclk_add_chart_payload(wc, st->chart_uuid, claim_id, ACLK_PAYLOAD_CHART, (void *) payload, size);
166
freez(payload);
167
chart_instance_updated_destroy(&chart_payload);
168
}
165
-#else
166
- UNUSED(wc);
167
- UNUSED(cmd);
168
-#endif
169
+ return rc;
170
+}
171
+
172
+static inline int aclk_upd_dimension_event(struct aclk_database_worker_config *wc, char *claim_id, uuid_t *dim_uuid,
173
+ const char *dim_id, const char *dim_name, const char *chart_name, time_t first_time, time_t last_time)
174
+{
175
+ int rc = 0;
176
+ size_t size;
177
+
178
+ if (unlikely(!dim_uuid || !dim_id || !dim_name || !chart_name))
179
+ return 0;
180
+
181
+ struct chart_dimension_updated dim_payload;
182
+ memset(&dim_payload, 0, sizeof(dim_payload));
183
+
184
+ if (!first_time)
185
+ info("DEBUG: Deleting dimension [%s] [%s] [%s] [%s] [%s]", wc->node_id, claim_id, dim_id, dim_name, chart_name);
186
+ dim_payload.node_id = wc->node_id;
187
+ dim_payload.claim_id = claim_id;
188
+ dim_payload.name = dim_name;
189
+ dim_payload.id = dim_id;
190
+ dim_payload.chart_id = chart_name;
191
+ dim_payload.created_at.tv_sec = first_time;
192
+ dim_payload.last_timestamp.tv_sec = last_time;
193
+ char *payload = generate_chart_dimension_updated(&size, &dim_payload);
194
+ if (likely(payload))
195
+ rc = aclk_add_chart_payload(wc, dim_uuid, claim_id, ACLK_PAYLOAD_DIMENSION, (void *)payload, size);
196
+ freez(payload);
197
return rc;
198
}
199
202
int rc = 0;
203
CHECK_SQLITE_CONNECTION(db_meta);
204
177
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
205
char *claim_id = is_agent_claimed();
206
207
RRDDIM *rd = cmd.data;
214
215
int live = ((now - last_t) < (RRDSET_MINIMUM_LIVE_COUNT * rd->update_every));
216
190
- struct chart_dimension_updated dim_payload;
191
- size_t size;
192
-
193
- memset(&dim_payload, 0, sizeof(dim_payload));
194
- dim_payload.node_id = wc->node_id;
195
- dim_payload.claim_id = claim_id;
196
- dim_payload.name = rd->name;
197
- dim_payload.id = rd->id;
217
+ rc = aclk_upd_dimension_event(
218
+ wc,
219
+ claim_id,
220
+ &rd->state->metric_uuid,
221
+ rd->id,
222
+ rd->name,
223
+ rd->rrdset->id,
224
+ first_t,
225
+ live ? 0 : last_t);
226
199
- dim_payload.chart_id = rd->rrdset->name;
200
- dim_payload.created_at.tv_sec = first_t;
201
- if (unlikely(!live))
202
- dim_payload.last_timestamp.tv_sec = last_t;
203
-
204
- char *payload = generate_chart_dimension_updated(&size, &dim_payload);
205
- if (likely(payload))
206
- rc = aclk_add_chart_payload(wc->uuid_str, &rd->state->metric_uuid, claim_id, ACLK_PAYLOAD_DIMENSION, (void *)payload, size);
207
- freez(payload);
227
freez(claim_id);
228
}
229
rrddim_flag_clear(rd, RRDDIM_FLAG_ACLK);
211
-#else
212
- UNUSED(wc);
213
- UNUSED(cmd);
214
-#endif
230
return rc;
231
}
232
233
+
234
void aclk_send_chart_event(struct aclk_database_worker_config *wc, struct aclk_database_cmd cmd)
235
{
220
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
236
int rc;
237
238
wc->chart_pending = 0;
284
285
int loop = cmd.param1;
286
287
+ uint64_t start_sequence_id = wc->chart_sequence_id;
288
+
289
while (loop > 0) {
290
uint64_t previous_sequence_id = wc->chart_sequence_id;
291
int count = 0;
311
previous_sequence_id = last_sequence;
312
is_dim[count] = sqlite3_column_int(res, 3) > 0;
313
count++;
314
+ if (wc->chart_payload_count)
315
+ wc->chart_payload_count--;
316
}
317
freez(payload_list[count]);
318
payload_list_max_size[count] = 0;
344
wc->chart_sequence_id = last_sequence;
345
wc->chart_timestamp = last_timestamp;
346
}
347
+ else
348
+ break;
349
--loop;
350
}
351
352
+ if (start_sequence_id != wc->chart_sequence_id) {
353
+ time_t now = now_realtime_sec();
354
+ if (wc->rotation_after > now && wc->rotation_after < now + ACLK_DATABASE_ROTATION_DELAY)
355
+ wc->rotation_after = now + ACLK_DATABASE_ROTATION_DELAY;
356
+ }
357
+ else {
358
+ wc->chart_payload_count = sql_get_pending_count(wc);
359
+ if (!wc->chart_payload_count)
360
+ info("%s: sync of charts and dimensions done in %ld seconds", wc->host->hostname, now_realtime_sec() - wc->startup_time);
361
+ }
362
+
363
for (int i = 0; i <= limit; ++i)
364
freez(payload_list[i]);
365
376
377
buffer_free(sql);
378
freez(claim_id);
347
-#else
348
- UNUSED(wc);
349
- UNUSED(cmd);
350
-#endif
379
return;
380
}
381
354
-
382
// Push one chart config to the cloud
383
int aclk_send_chart_config(struct aclk_database_worker_config *wc, struct aclk_database_cmd cmd)
384
{
385
UNUSED(wc);
359
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
386
387
CHECK_SQLITE_CONNECTION(db_meta);
388
445
freez((char *) cmd.data_param);
446
buffer_free(sql);
447
return rc;
422
-#else
423
- UNUSED(cmd);
424
- return 0;
425
-#endif
448
}
449
450
+
451
void aclk_receive_chart_ack(struct aclk_database_worker_config *wc, struct aclk_database_cmd cmd)
452
{
453
int rc;
483
484
void aclk_receive_chart_reset(struct aclk_database_worker_config *wc, struct aclk_database_cmd cmd)
485
{
463
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
486
BUFFER *sql = buffer_create(1024);
487
buffer_sprintf(sql, "UPDATE aclk_chart_%s SET status = NULL, date_submitted = NULL WHERE sequence_id >= %"PRIu64";",
488
wc->uuid_str, cmd.param1);
501
db_unlock();
502
wc->chart_sequence_id = 0;
503
wc->chart_timestamp = 0;
504
+ wc->chart_payload_count = 0;
505
506
RRDHOST *host = wc->host;
507
rrdhost_rdlock(host);
508
RRDSET *st;
509
rrdset_foreach_read(st, host) {
510
rrdset_rdlock(st);
511
+ rrdset_flag_clear(st, RRDSET_FLAG_ACLK);
512
RRDDIM *rd;
513
rrddim_foreach_read(rd, st) {
514
rd->state->aclk_live_status = (rd->state->aclk_live_status == 0);
515
}
492
- rrdset_flag_clear(st, RRDSET_FLAG_ACLK);
516
rrdset_unlock(st);
517
}
518
rrdhost_unlock(host);
519
}
520
else {
498
- //sql_chart_deduplicate(wc, cmd);
499
- sql_get_last_chart_sequence(wc, cmd);
521
+ info("Restarting chart sync for %s from sequence=%"PRIu64, wc->uuid_str, cmd.param1);
522
+ wc->chart_payload_count = sql_get_pending_count(wc);
523
+ sql_get_last_chart_sequence(wc);
524
}
525
buffer_free(sql);
526
wc->chart_updates = 1;
503
-#else
504
- UNUSED(wc);
505
- UNUSED(cmd);
506
-#endif
507
-
527
return;
528
}
529
530
+
531
//
532
// Functions called directly from ACLK threads and will queue commands
533
//
588
return;
589
}
590
571
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
572
-void aclk_reset_chart_event(char *node_id, uint64_t last_sequence_id)
591
+// Start streaming charts / dimensions for node_id
592
+void aclk_start_streaming(char *node_id, uint64_t sequence_id, time_t created_at, uint64_t batch_id)
593
{
594
+ UNUSED(created_at);
595
if (unlikely(!node_id))
596
return;
597
577
- debug(D_ACLK_SYNC, "NODE %s wants to resync from %"PRIu64, node_id, last_sequence_id);
578
- aclk_submit_param_command(node_id, ACLK_DATABASE_RESET_CHART, last_sequence_id);
598
+ debug(D_ACLK_SYNC,"START streaming charts for node %s from sequence %"PRIu64" t=%ld, batch=%"PRIu64, node_id,
599
+ sequence_id, created_at, batch_id);
600
+ uuid_t node_uuid;
601
+ if (uuid_parse(node_id, node_uuid))
602
+ return;
603
+
604
+ struct aclk_database_worker_config *wc = NULL;
605
+ rrd_wrlock();
606
+ RRDHOST *host = localhost;
607
+ while(host) {
608
+ if (host->node_id && !(uuid_compare(*host->node_id, node_uuid))) {
609
+ rrd_unlock();
610
+ wc = (struct aclk_database_worker_config *)host->dbsync_worker;
611
+ if (likely(wc)) {
612
+ wc->chart_reset_count++;
613
+ __sync_synchronize();
614
+ wc->chart_updates = 0;
615
+ wc->batch_id = batch_id;
616
+ __sync_synchronize();
617
+ wc->batch_created = now_realtime_sec();
618
+ if (sequence_id > wc->chart_sequence_id || wc->chart_reset_count > 10) {
619
+ info("Requesting full resync from the cloud for node id %s "
620
+ "(reset=%d, remote_seq=%"PRIu64", local_seq=%"PRIu64")"
621
+ , wc->node_id, wc->chart_reset_count, sequence_id, wc->chart_sequence_id);
622
+ chart_reset_t chart_reset;
623
+ chart_reset.claim_id = is_agent_claimed();
624
+ if (chart_reset.claim_id) {
625
+ chart_reset.node_id = node_id;
626
+ chart_reset.reason = SEQ_ID_NOT_EXISTS;
627
+ aclk_chart_reset(chart_reset);
628
+ freez(chart_reset.claim_id);
629
+ wc->chart_reset_count = -1;
630
+ }
631
+ return;
632
+ } else {
633
+ struct aclk_database_cmd cmd;
634
+ memset(&cmd, 0, sizeof(cmd));
635
+ // TODO: handle timestamp
636
+ if (sequence_id < wc->chart_sequence_id || !sequence_id) { // || created_at != wc->chart_timestamp) {
637
+ info("RESET streaming charts for %s from sequence %"PRIu64 \
638
+ " t=%ld (reset count=%d)", wc->node_id, wc->chart_sequence_id,
639
+ wc->chart_timestamp, wc->chart_reset_count);
640
+ cmd.opcode = ACLK_DATABASE_RESET_CHART;
641
+ cmd.param1 = sequence_id + 1;
642
+ cmd.completion = NULL;
643
+ aclk_database_enq_cmd(wc, &cmd);
644
+ }
645
+ else {
646
+ info("START streaming charts for %s enabled -- last streamed sequence %"PRIu64 \
647
+ " t=%ld (reset count=%d)", wc->node_id, wc->chart_sequence_id,
648
+ wc->chart_timestamp, wc->chart_reset_count);
649
+ wc->chart_reset_count = 0;
650
+ wc->chart_updates = 1;
651
+ }
652
+ }
653
+ }
654
+ else
655
+ error("ACLK synchronization thread is not active for host %s", host->hostname);
656
+ return;
657
+ }
658
+ host = host->next;
659
+ }
660
+ rrd_unlock();
661
return;
662
}
581
-#endif
663
583
-// ST is read locked
584
-int sql_queue_chart_to_aclk(RRDSET *st)
664
+#define SQL_SELECT_HOST_MEMORY_MODE "SELECT memory_mode FROM chart WHERE host_id = @host_id LIMIT 1;"
665
+
666
+static RRD_MEMORY_MODE sql_get_host_memory_mode(uuid_t *host_id)
667
{
586
-#ifdef ENABLE_ACLK
587
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
588
- if (!aclk_use_new_cloud_arch)
589
-#endif
590
- {
591
- rrdset_flag_clear(st, RRDSET_FLAG_ACLK);
592
- aclk_update_chart(st->rrdhost, st->id, 1);
593
- return 0;
668
+ int rc;
669
+
670
+ RRD_MEMORY_MODE memory_mode = RRD_MEMORY_MODE_RAM;
671
+ sqlite3_stmt *res = NULL;
672
+
673
+ rc = sqlite3_prepare_v2(db_meta, SQL_SELECT_HOST_MEMORY_MODE, -1, &res, 0);
674
+
675
+ if (unlikely(rc != SQLITE_OK)) {
676
+ error_report("Failed to prepare statement to read host memory mode");
677
+ return memory_mode;
678
}
595
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
596
- return sql_queue_chart_payload((struct aclk_database_worker_config *) st->rrdhost->dbsync_worker,
597
- st, ACLK_DATABASE_ADD_CHART);
598
-#else
599
- return 0;
600
-#endif
601
-#else
602
- UNUSED(st);
603
- return 0;
604
-#endif
605
-}
679
607
-int sql_queue_dimension_to_aclk(RRDDIM *rd)
608
-{
609
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
610
- if (!aclk_use_new_cloud_arch)
611
- return 0;
680
+ rc = sqlite3_bind_blob(res, 1, host_id, sizeof(*host_id), SQLITE_STATIC);
681
+ if (unlikely(rc != SQLITE_OK)) {
682
+ error_report("Failed to bind host parameter to fetch host memory mode");
683
+ goto failed;
684
+ }
685
613
- int rc = sql_queue_chart_payload((struct aclk_database_worker_config *) rd->rrdset->rrdhost->dbsync_worker,
614
- rd, ACLK_DATABASE_ADD_DIMENSION);
615
- if (likely(!rc))
616
- rrddim_flag_set(rd, RRDDIM_FLAG_ACLK);
617
- return rc;
618
-#else
619
- UNUSED(rd);
620
- return 0;
621
-#endif
686
+ while (sqlite3_step(res) == SQLITE_ROW) {
687
+ memory_mode = (RRD_MEMORY_MODE) sqlite3_column_int(res, 0);
688
+ }
689
+
690
+failed:
691
+ rc = sqlite3_finalize(res);
692
+ if (unlikely(rc != SQLITE_OK))
693
+ error_report("Failed to finalize the prepared statement when reading host memory mode");
694
+ return memory_mode;
695
}
696
624
-void sql_chart_deduplicate(struct aclk_database_worker_config *wc, struct aclk_database_cmd cmd)
697
+#define SELECT_HOST_DIMENSION_LIST "SELECT d.dim_id, c.update_every, c.type||'.'||c.id, d.id, d.name FROM chart c, dimension d " \
698
+ "WHERE d.chart_id = c.chart_id AND c.host_id = @host_id ORDER BY c.update_every ASC;"
699
+
700
+#define SELECT_HOST_CHART_LIST "SELECT distinct h.host_id, c.update_every, c.type||'.'||c.id FROM chart c, host h " \
701
+ "WHERE c.host_id = h.host_id AND c.host_id = @host_id ORDER BY c.update_every ASC;"
702
+
703
+void aclk_update_retention(struct aclk_database_worker_config *wc, struct aclk_database_cmd cmd)
704
{
705
UNUSED(cmd);
706
+ int rc;
707
628
- BUFFER *sql = buffer_create(1024);
708
+ if (!aclk_use_new_cloud_arch || !aclk_connected)
709
+ return;
710
630
- db_lock();
631
- buffer_sprintf(sql, "DROP TABLE IF EXISTS t_%s;", wc->uuid_str);
632
- db_execute(buffer_tostring(sql));
711
+ char *claim_id = is_agent_claimed();
712
+ if (unlikely(!claim_id))
713
+ return;
714
634
- buffer_flush(sql);
635
- buffer_sprintf(sql, "CREATE TABLE t_%s AS SELECT * FROM aclk_chart_payload_%s WHERE unique_id IN "
636
- "(SELECT unique_id from aclk_chart_%s WHERE date_submitted IS NULL AND update_count > 0);",
637
- wc->uuid_str, wc->uuid_str, wc->uuid_str);
638
- db_execute(buffer_tostring(sql));
715
+ sqlite3_stmt *res = NULL;
716
+ RRD_MEMORY_MODE memory_mode;
717
640
- buffer_flush(sql);
641
- buffer_sprintf(sql, "DELETE FROM aclk_chart_payload_%s WHERE unique_id IN (SELECT unique_id FROM t_%s); " ,
642
- wc->uuid_str, wc->uuid_str);
643
- db_execute(buffer_tostring(sql));
718
+ uuid_t host_uuid;
719
+ rc = uuid_parse(wc->host_guid, host_uuid);
720
+ if (unlikely(rc)) {
721
+ freez(claim_id);
722
+ return;
723
+ }
724
645
- buffer_flush(sql);
646
- buffer_sprintf(sql, "DELETE FROM aclk_chart_%s WHERE unique_id IN (SELECT unique_id FROM t_%s);",
647
- wc->uuid_str, wc->uuid_str);
648
- db_execute(buffer_tostring(sql));
725
+ if (wc->host)
726
+ memory_mode = wc->host->rrd_memory_mode;
727
+ else
728
+ memory_mode = sql_get_host_memory_mode(&host_uuid);
729
650
- buffer_flush(sql);
651
- buffer_sprintf(sql, "DELETE FROM aclk_chart_latest_%s WHERE unique_id IN (SELECT unique_id FROM t_%s);",
652
- wc->uuid_str, wc->uuid_str);
653
- db_execute(buffer_tostring(sql));
730
+ if (memory_mode == RRD_MEMORY_MODE_DBENGINE)
731
+ rc = sqlite3_prepare_v2(db_meta, SELECT_HOST_DIMENSION_LIST, -1, &res, 0);
732
+ else
733
+ rc = sqlite3_prepare_v2(db_meta, SELECT_HOST_CHART_LIST, -1, &res, 0);
734
655
- buffer_flush(sql);
656
- buffer_sprintf(sql, "INSERT INTO aclk_chart_payload_%s SELECT * FROM t_%s ORDER BY DATE_CREATED ASC;",
657
- wc->uuid_str, wc->uuid_str);
658
- db_execute(buffer_tostring(sql));
735
+ if (unlikely(rc != SQLITE_OK)) {
736
+ error_report("Failed to prepare statement to fetch host dimensions");
737
+ freez(claim_id);
738
+ return;
739
+ }
740
660
- buffer_flush(sql);
661
- buffer_sprintf(sql, "INSERT OR REPLACE INTO aclk_chart_latest_%s (uuid, unique_id, date_submitted) "
662
- "SELECT uuid, unique_id, date_submitted FROM aclk_chart_%s where sequence_id IN "
663
- "(SELECT sequence_id FROM aclk_chart_%s WHERE date_submitted IS NOT NULL "
664
- "GROUP BY uuid HAVING sequence_id = MAX(sequence_id));"
665
- , wc->uuid_str, wc->uuid_str, wc->uuid_str);
666
- db_execute(buffer_tostring(sql));
741
+ rc = sqlite3_bind_blob(res, 1, &host_uuid, sizeof(host_uuid), SQLITE_STATIC);
742
+ if (unlikely(rc != SQLITE_OK)) {
743
+ error_report("Failed to bind host parameter to fetch host dimensions");
744
+ goto failed;
745
+ }
746
668
- buffer_flush(sql);
669
- buffer_sprintf(sql, "DROP TABLE IF EXISTS t_%s;", wc->uuid_str);
670
- db_execute(buffer_tostring(sql));
671
- db_unlock();
747
+ time_t start_time = LONG_MAX;
748
+ time_t first_entry_t;
749
+ time_t last_entry_t;
750
+ uint32_t update_every = 0;
751
673
- sql_get_last_chart_sequence(wc, cmd);
752
+ struct retention_updated rotate_data;
753
675
- buffer_free(sql);
754
+ memset(&rotate_data, 0, sizeof(rotate_data));
755
+
756
+ int max_intervals = 32;
757
+
758
+ rotate_data.interval_duration_count = 0;
759
+ rotate_data.interval_durations = callocz(max_intervals, sizeof(*rotate_data.interval_durations));
760
+
761
+ now_realtime_timeval(&rotate_data.rotation_timestamp);
762
+ rotate_data.memory_mode = memory_mode;
763
+ rotate_data.claim_id = claim_id;
764
+ rotate_data.node_id = strdupz(wc->node_id);
765
+
766
+ // time_t now = now_realtime_sec();
767
+ while (sqlite3_step(res) == SQLITE_ROW) {
768
+ if (!update_every || update_every != (uint32_t) sqlite3_column_int(res, 1)) {
769
+ if (update_every) {
770
+ debug(D_ACLK_SYNC,"Update %s for %u oldest time = %ld", wc->host_guid, update_every, start_time);
771
+ rotate_data.interval_durations[rotate_data.interval_duration_count].retention = rotate_data.rotation_timestamp.tv_sec - start_time;
772
+ rotate_data.interval_duration_count++;
773
+ }
774
+ update_every = (uint32_t) sqlite3_column_int(res, 1);
775
+ rotate_data.interval_durations[rotate_data.interval_duration_count].update_every = update_every;
776
+ start_time = LONG_MAX;
777
+ }
778
+#ifdef ENABLE_DBENGINE
779
+ if (memory_mode == RRD_MEMORY_MODE_DBENGINE)
780
+ rc = rrdeng_metric_latest_time_by_uuid((uuid_t *)sqlite3_column_blob(res, 0), &first_entry_t, &last_entry_t);
781
+ else
782
+#endif
783
+ {
784
+ if (wc->host) {
785
+ RRDSET *st = NULL;
786
+ rc = (st = rrdset_find(wc->host, (const char *)sqlite3_column_text(res, 2))) ? 0 : 1;
787
+ if (!rc) {
788
+ first_entry_t = rrdset_first_entry_t(st);
789
+ last_entry_t = rrdset_last_entry_t(st);
790
+ }
791
+ }
792
+ else {
793
+ rc = 0;
794
+ first_entry_t = rotate_data.rotation_timestamp.tv_sec;
795
+ }
796
+ }
797
+
798
+ if (likely(!rc && first_entry_t))
799
+ start_time = MIN(start_time, first_entry_t);
800
+
801
+ // if (memory_mode == RRD_MEMORY_MODE_DBENGINE) {
802
+ // int live = ((now - last_entry_t) < (RRDSET_MINIMUM_LIVE_COUNT * update_every));
803
+ // (void) aclk_upd_dimension_event(
804
+ // wc->uuid_str,
805
+ // claim_id,
806
+ // (uuid_t *)sqlite3_column_blob(res, 0),
807
+ // (const char *)(const char *)sqlite3_column_text(res, 3),
808
+ // (const char *)(const char *)sqlite3_column_text(res, 4),
809
+ // (const char *)(const char *)sqlite3_column_text(res, 2),
810
+ // first_entry_t,
811
+ // live ? 0 : last_entry_t);
812
+ // }
813
+ }
814
+ if (update_every) {
815
+ debug(D_ACLK_SYNC, "Update %s for %u oldest time = %ld", wc->host_guid, update_every, start_time);
816
+ rotate_data.interval_durations[rotate_data.interval_duration_count].retention = rotate_data.rotation_timestamp.tv_sec - start_time;
817
+ rotate_data.interval_duration_count++;
818
+ }
819
+
820
+ for (int i = 0; i < rotate_data.interval_duration_count; ++i) {
821
+#ifdef NETDATA_INTERNAL_CHECKS
822
+ info("%d --> Update %s for %u Retention = %u", i, wc->host_guid,
823
+ rotate_data.interval_durations[i].update_every, rotate_data.interval_durations[i].retention);
824
+#endif
825
+ };
826
+ aclk_retention_updated(&rotate_data);
827
+ freez(rotate_data.node_id);
828
+ freez(rotate_data.interval_durations);
829
+
830
+failed:
831
+ freez(claim_id);
832
+ rc = sqlite3_finalize(res);
833
+ if (unlikely(rc != SQLITE_OK))
834
+ error_report("Failed to finalize the prepared statement when reading host dimensions");
835
return;
836
}
837
679
-void sql_get_last_chart_sequence(struct aclk_database_worker_config *wc, struct aclk_database_cmd cmd)
838
+
839
+uint32_t sql_get_pending_count(struct aclk_database_worker_config *wc)
840
{
681
- UNUSED(cmd);
841
+ BUFFER *sql = buffer_create(1024);
842
+ sqlite3_stmt *res = NULL;
843
+
844
+ buffer_sprintf(sql,"SELECT count(1) FROM aclk_chart_%s ac WHERE ac.date_submitted IS NULL;", wc->uuid_str);
845
+
846
+ int rc;
847
+ uint32_t chart_payload_count = 0;
848
+ rc = sqlite3_prepare_v2(db_meta, buffer_tostring(sql), -1, &res, 0);
849
+ if (rc != SQLITE_OK) {
850
+ error_report("Failed to prepare statement to count pending messages");
851
+ goto fail;
852
+ }
853
+ while (sqlite3_step(res) == SQLITE_ROW)
854
+ chart_payload_count = (uint32_t) sqlite3_column_int(res, 0);
855
856
+ rc = sqlite3_finalize(res);
857
+ if (unlikely(rc != SQLITE_OK))
858
+ error_report("Failed to reset statement when fetching pending messages, rc = %d", rc);
859
+
860
+fail:
861
+ buffer_free(sql);
862
+ return chart_payload_count;
863
+}
864
+
865
+void sql_get_last_chart_sequence(struct aclk_database_worker_config *wc)
866
+{
867
BUFFER *sql = buffer_create(1024);
868
869
buffer_sprintf(sql,"SELECT ac.sequence_id, ac.date_created FROM aclk_chart_%s ac " \
895
return;
896
}
897
714
-// Start streaming charts / dimensions for node_id
715
-void aclk_start_streaming(char *node_id, uint64_t sequence_id, time_t created_at, uint64_t batch_id)
898
+int queue_dimension_to_aclk(RRDDIM *rd)
899
{
717
- UNUSED(created_at);
718
-#ifdef ENABLE_NEW_CLOUD_PROTOCOL
719
- if (unlikely(!node_id))
720
- return;
900
+ int rc = sql_queue_chart_payload((struct aclk_database_worker_config *) rd->rrdset->rrdhost->dbsync_worker,
901
+ rd, ACLK_DATABASE_ADD_DIMENSION);
902
+ return rc;
903
+}
904
722
- debug(D_ACLK_SYNC,"START streaming charts for node %s from sequence %"PRIu64" t=%ld, batch=%"PRIu64, node_id,
723
- sequence_id, created_at, batch_id);
724
- uuid_t node_uuid;
725
- if (uuid_parse(node_id, node_uuid))
726
- return;
905
+#endif //ENABLE_NEW_CLOUD_PROTOCOL
906
728
- struct aclk_database_worker_config *wc = NULL;
729
- rrd_wrlock();
730
- RRDHOST *host = localhost;
731
- while(host) {
732
- if (host->node_id && !(uuid_compare(*host->node_id, node_uuid))) {
733
- rrd_unlock();
734
- wc = (struct aclk_database_worker_config *)host->dbsync_worker;
735
- if (likely(wc)) {
736
- wc->chart_reset_count++;
737
- __sync_synchronize();
738
- wc->chart_updates = 0;
739
- wc->batch_id = batch_id;
740
- __sync_synchronize();
741
- wc->batch_created = now_realtime_sec();
742
- if (sequence_id > wc->chart_sequence_id || wc->chart_reset_count > 10) {
743
- debug(D_ACLK_SYNC,"Requesting full resync from the cloud -- reset_count=%d", wc->chart_reset_count);
744
- chart_reset_t chart_reset;
745
- chart_reset.claim_id = is_agent_claimed();
746
- if (chart_reset.claim_id) {
747
- chart_reset.node_id = node_id;
748
- chart_reset.reason = SEQ_ID_NOT_EXISTS;
749
- aclk_chart_reset(chart_reset);
750
- freez(chart_reset.claim_id);
751
- wc->chart_reset_count = -1;
752
- }
753
- return;
754
- } else {
755
- struct aclk_database_cmd cmd;
756
- memset(&cmd, 0, sizeof(cmd));
757
- // TODO: handle timestamp
758
- if (sequence_id < wc->chart_sequence_id) { // || created_at != wc->chart_timestamp) {
759
- cmd.opcode = ACLK_DATABASE_RESET_CHART;
760
- cmd.param1 = sequence_id + 1;
761
- cmd.completion = NULL;
762
- aclk_database_enq_cmd(wc, &cmd);
763
- }
764
- else {
765
- debug(D_ACLK_SYNC,"START streaming charts for %s enabled -- last streamed sequence %"PRIu64 \
766
- " t=%ld (reset count=%d)", wc->host_guid, wc->chart_sequence_id,
767
- wc->chart_timestamp, wc->chart_reset_count);
768
- wc->chart_reset_count = 0;
769
- wc->chart_updates = 1;
770
- }
771
- }
772
- }
773
- else
774
- error("ACLK synchronization thread is not active for host %s", host->hostname);
775
- return;
776
- }
777
- host = host->next;
778
- }
779
- rrd_unlock();
907
+// ST is read locked
908
+int queue_chart_to_aclk(RRDSET *st)
909
+{
910
+#ifndef ENABLE_NEW_CLOUD_PROTOCOL
911
+#ifdef ENABLE_ACLK
912
+ aclk_update_chart(st->rrdhost, st->id, 1);
913
+#endif
914
+ return 0;
915
#else
781
- UNUSED(node_id);
782
- UNUSED(sequence_id);
783
- UNUSED(batch_id);
916
+ if (!aclk_use_new_cloud_arch && aclk_connected) {
917
+ aclk_update_chart(st->rrdhost, st->id, 1);
918
+ return 0;
919
+ }
920
+ return sql_queue_chart_payload((struct aclk_database_worker_config *) st->rrdhost->dbsync_worker,
921
+ st, ACLK_DATABASE_ADD_CHART);
922
#endif
785
- return;
923
}
924
+