147
stream_decompressor_start(&r->thread.compressed.decompressor, buf + start, signature_size);
148
149
if (unlikely(!compressed_message_size)) {
150
- nd_log(NDLS_DAEMON, NDLP_ERR, "multiplexed uncompressed data in compressed stream!");
150
+ nd_log(NDLS_DAEMON, NDLP_ERR,
151
+ "STREAM RECEIVE[x] '%s' [from [%s]:%s]: multiplexed uncompressed data in compressed stream!",
152
+ rrdhost_hostname(r->host), r->client_ip, r->client_port);
153
return DECOMPRESS_FAILED;
154
}
155
156
if(unlikely(compressed_message_size > COMPRESSION_MAX_MSG_SIZE)) {
157
nd_log(NDLS_DAEMON, NDLP_ERR,
156
- "received a compressed message of %zu bytes, which is bigger than the max compressed message "
158
+ "STREAM RECEIVE[x] '%s' [from [%s]:%s]: received a compressed message of %zu bytes, "
159
+ "which is bigger than the max compressed message "
160
"size supported of %zu. Ignoring message.",
161
+ rrdhost_hostname(r->host), r->client_ip, r->client_port,
162
compressed_message_size, (size_t)COMPRESSION_MAX_MSG_SIZE);
163
return DECOMPRESS_FAILED;
164
}
173
stream_decompress(&r->thread.compressed.decompressor, buf + start + signature_size, compressed_message_size);
174
175
if (unlikely(!bytes_to_parse)) {
172
- nd_log(NDLS_DAEMON, NDLP_ERR, "no bytes to parse.");
176
+ nd_log(NDLS_DAEMON, NDLP_ERR,
177
+ "STREAM RECEIVE[x] '%s' [from [%s]:%s]: no bytes to decompress.",
178
+ rrdhost_hostname(r->host), r->client_ip, r->client_port);
179
return DECOMPRESS_FAILED;
180
}
181
265
STREAM_CIRCULAR_BUFFER_STATS stats = *stream_circular_buffer_stats_unsafe(rpt->thread.send_to_child.scb);
266
spinlock_unlock(&rpt->thread.send_to_child.spinlock);
267
nd_log(NDLS_DAEMON, NDLP_ERR,
262
- "STREAM RECEIVE[%zu] %s [from %s]: send buffer is full (buffer size %u, max %u, used %u, available %u). "
268
+ "STREAM RECEIVE[%zu] '%s' [from [%s]:%s]: send buffer is full (buffer size %u, max %u, used %u, available %u). "
269
"Restarting connection.",
264
- sth->id, rrdhost_hostname(rpt->host), rpt->client_ip,
270
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rpt->client_port,
271
stats.bytes_size, stats.bytes_max_size, stats.bytes_outstanding, stats.bytes_available);
272
273
stream_receiver_remove(sth, rpt, "receiver send buffer overflow");
278
"STREAM RECEIVE[%zu]: invalid msg id %u", sth->id, (unsigned)msg->opcode);
279
}
280
275
-ssize_t send_to_child(const char *txt, void *data, STREAM_TRAFFIC_TYPE type) {
281
+static ssize_t send_to_child(const char *txt, void *data, STREAM_TRAFFIC_TYPE type) {
282
struct receiver_state *rpt = data;
283
if(!rpt || rpt->thread.meta.type != POLLFD_TYPE_RECEIVER || !rpt->thread.send_to_child.scb)
284
return 0;
292
293
size_t size = strlen(txt);
294
ssize_t rc = (ssize_t)size;
289
- if(!stream_circular_buffer_add_unsafe(scb, txt, size, size, type)) {
295
+ if(!stream_circular_buffer_add_unsafe(scb, txt, size, size, type, true)) {
296
+ // should never happen, because of autoscaling
297
msg.opcode = STREAM_OPCODE_RECEIVER_BUFFER_OVERFLOW;
298
rc = -1;
299
}
322
// put the client IP and port into the buffers used by plugins.d
323
{
324
char buf[CONFIG_MAX_NAME];
318
- snprintfz(buf, sizeof(buf), "%s:%s", rpt->client_ip, rpt->client_port);
325
+ snprintfz(buf, sizeof(buf), "[%s]:%s", rpt->client_ip, rpt->client_port);
326
string_freez(rpt->thread.cd.id);
327
rpt->thread.cd.id = string_strdupz(buf);
321
- }
328
323
- {
324
- char buf[FILENAME_MAX + 1];
325
- snprintfz(buf, sizeof(buf), "%s:%s", rpt->client_ip, rpt->client_port);
329
string_freez(rpt->thread.cd.filename);
330
rpt->thread.cd.filename = string_strdupz(buf);
331
387
388
// --------------------------------------------------------------------------------------------------------------------
389
390
+static void stream_receive_log_database_gap(struct receiver_state *rpt) {
391
+ RRDHOST *host = rpt->host;
392
+
393
+ time_t now = now_realtime_sec();
394
+ time_t last_db_entry = 0;
395
+ rrdhost_retention(host, now, false, NULL, &last_db_entry);
396
+
397
+ if(now < last_db_entry)
398
+ last_db_entry = now;
399
+
400
+ char buf[128];
401
+ duration_snprintf(buf, sizeof(buf), now - last_db_entry, "s", true);
402
+ nd_log(NDLS_DAEMON, NDLP_NOTICE,
403
+ "STREAM RECEIVE '%s' [from [%s]:%s]: node connected; last sample in the database %s ago",
404
+ rrdhost_hostname(host), rpt->client_ip, rpt->client_port, buf);
405
+}
406
+
407
void stream_receiver_move_queue_to_running_unsafe(struct stream_thread *sth) {
408
internal_fatal(sth->tid != gettid_cached(), "Function %s() should only be used by the dispatcher thread", __FUNCTION__ );
409
424
ND_LOG_STACK_PUSH(lgs);
425
426
nd_log(NDLS_DAEMON, NDLP_DEBUG,
407
- "STREAM RECEIVE[%zu] [%s]: moving host from receiver queue to receiver running...",
408
- sth->id, rrdhost_hostname(rpt->host));
427
+ "STREAM RECEIVE[%zu] '%s' [from [%s]:%s]: moving host from receiver queue to receiver running...",
428
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rpt->client_port);
429
430
rpt->host->stream.rcv.status.tid = gettid_cached();
431
rpt->thread.meta.type = POLLFD_TYPE_RECEIVER;
433
434
spinlock_lock(&rpt->thread.send_to_child.spinlock);
435
rpt->thread.send_to_child.scb = stream_circular_buffer_create();
416
-
417
- // this should be big enough to fit all the replies to the replication requests we may receive in a batch
418
- stream_circular_buffer_set_max_size_unsafe(rpt->thread.send_to_child.scb, 100 * 1024 * 1024, true);
436
rpt->thread.send_to_child.msg.thread_slot = (int32_t)sth->id;
437
rpt->thread.send_to_child.msg.session = os_random32();
438
rpt->thread.send_to_child.msg.meta = &rpt->thread.meta;
447
rrdhost_hostname(rpt->host), rpt->client_ip, rpt->client_port, rpt->sock.fd);
448
449
if(!nd_poll_add(sth->run.ndpl, rpt->sock.fd, ND_POLL_READ, &rpt->thread.meta))
433
- nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to add receiver socket to nd_poll()");
450
+ nd_log(NDLS_DAEMON, NDLP_ERR,
451
+ "STREAM RECEIVE[%zu] '%s' [from [%s]:%s]:"
452
+ "Failed to add receiver socket to nd_poll()",
453
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rpt->client_port);
454
+
455
+ stream_receive_log_database_gap(rpt);
456
457
// keep this last, since it sends commands back to the child
458
streaming_parser_init(rpt);
530
531
static ssize_t
532
stream_receive_and_process(struct stream_thread *sth, struct receiver_state *rpt, PARSER *parser, bool *removed) {
533
+ internal_fatal(sth->tid != gettid_cached(), "Function %s() should only be used by the dispatcher thread", __FUNCTION__);
534
+
535
ssize_t rc;
536
if(rpt->thread.compressed.enabled) {
537
rc = receiver_read_compressed(rpt);
613
}
614
615
// process poll() events for streaming receivers
592
-void stream_receive_process_poll_events(struct stream_thread *sth, struct receiver_state *rpt, nd_poll_event_t events, usec_t now_ut)
616
+// returns true when the receiver is still there, false if it removed it
617
+bool stream_receive_process_poll_events(struct stream_thread *sth, struct receiver_state *rpt, nd_poll_event_t events, usec_t now_ut)
618
{
594
- internal_fatal(
595
- sth->tid != gettid_cached(), "Function %s() should only be used by the dispatcher thread", __FUNCTION__);
619
+ internal_fatal(sth->tid != gettid_cached(), "Function %s() should only be used by the dispatcher thread", __FUNCTION__);
620
621
PARSER *parser = __atomic_load_n(&rpt->thread.parser, __ATOMIC_RELAXED);
622
ND_LOG_STACK lgs[] = {
636
if (receiver_should_stop(rpt)) {
637
receiver_set_exit_reason(rpt, rpt->exit.reason, false);
638
stream_receiver_remove(sth, rpt, "received stop signal");
615
- return;
639
+ return false;
640
}
641
642
if (unlikely(events & (ND_POLL_ERROR | ND_POLL_HUP | ND_POLL_INVALID))) {
655
656
worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SOCKET_ERROR);
657
634
- nd_log(
635
- NDLS_DAEMON,
636
- NDLP_ERR,
637
- "STREAM RECEIVE[%zu] %s [from %s]: %s - closing connection",
638
- sth->id,
639
- rrdhost_hostname(rpt->host),
640
- rpt->client_ip,
641
- error);
658
+ nd_log(NDLS_DAEMON, NDLP_ERR,
659
+ "STREAM RECEIVE[%zu] '%s' [from [%s]:%s]: %s - closing connection",
660
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rpt->client_port, error);
661
662
receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_SOCKET_ERROR, false);
663
stream_receiver_remove(sth, rpt, error);
645
- return;
664
+ return false;
665
}
666
667
if (events & ND_POLL_WRITE) {
668
worker_is_busy(WORKER_STREAM_JOB_SOCKET_SEND);
669
651
- if (spinlock_trylock(&rpt->thread.send_to_child.spinlock)) {
652
- const char *disconnect_reason = NULL;
653
- STREAM_HANDSHAKE reason;
654
-
655
- char *chunk;
656
- STREAM_CIRCULAR_BUFFER *scb = rpt->thread.send_to_child.scb;
657
- STREAM_CIRCULAR_BUFFER_STATS *stats = stream_circular_buffer_stats_unsafe(scb);
658
- size_t outstanding = stream_circular_buffer_get_unsafe(scb, &chunk);
659
- ssize_t rc = write_stream(rpt, chunk, outstanding);
660
- if (likely(rc > 0)) {
661
- stream_circular_buffer_del_unsafe(scb, rc);
662
- if (!stats->bytes_outstanding) {
663
- if (!nd_poll_upd(sth->run.ndpl, rpt->sock.fd, ND_POLL_READ, &rpt->thread.meta))
664
- nd_log(NDLS_DAEMON, NDLP_ERR, "STREAM RECEIVE: cannot update nd_poll()");
665
-
666
- // recreate the circular buffer if we have to
667
- stream_circular_buffer_recreate_timed_unsafe(rpt->thread.send_to_child.scb, now_ut, false);
670
+ bool stop = false;
671
+ while(!stop) {
672
+ if (spinlock_trylock(&rpt->thread.send_to_child.spinlock)) {
673
+ const char *disconnect_reason = NULL;
674
+ STREAM_HANDSHAKE reason;
675
+
676
+ char *chunk;
677
+ STREAM_CIRCULAR_BUFFER *scb = rpt->thread.send_to_child.scb;
678
+ STREAM_CIRCULAR_BUFFER_STATS *stats = stream_circular_buffer_stats_unsafe(scb);
679
+ size_t outstanding = stream_circular_buffer_get_unsafe(scb, &chunk);
680
+ ssize_t rc = write_stream(rpt, chunk, outstanding);
681
+ if (likely(rc > 0)) {
682
+ stream_circular_buffer_del_unsafe(scb, rc);
683
+ if (!stats->bytes_outstanding) {
684
+ if (!nd_poll_upd(sth->run.ndpl, rpt->sock.fd, ND_POLL_READ, &rpt->thread.meta))
685
+ nd_log(NDLS_DAEMON, NDLP_ERR,
686
+ "STREAM RECEIVE[%zu] '%s' [from [%s]:%s]: cannot update nd_poll()",
687
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rpt->client_port);
688
+
689
+ // recreate the circular buffer if we have to
690
+ stream_circular_buffer_recreate_timed_unsafe(rpt->thread.send_to_child.scb, now_ut, false);
691
+ stop = true;
692
+ }
693
+ else if(stream_thread_process_opcodes(sth, &rpt->thread.meta))
694
+ stop = true;
695
}
669
- } else if (rc == 0 || errno == ECONNRESET) {
670
- disconnect_reason = "socket reports EOF (closed by child)";
671
- reason = STREAM_HANDSHAKE_DISCONNECT_SOCKET_CLOSED_BY_REMOTE_END;
672
- } else if (rc < 0) {
673
- if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
674
- // will try later
675
- ;
676
- else {
677
- disconnect_reason = "socket reports error while writing";
678
- reason = STREAM_HANDSHAKE_DISCONNECT_SOCKET_WRITE_FAILED;
696
+ else if (rc == 0 || errno == ECONNRESET) {
697
+ disconnect_reason = "socket reports EOF (closed by child)";
698
+ reason = STREAM_HANDSHAKE_DISCONNECT_SOCKET_CLOSED_BY_REMOTE_END;
699
+ }
700
+ else if (rc < 0) {
701
+ if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
702
+ // will try later
703
+ stop = true;
704
+ else {
705
+ disconnect_reason = "socket reports error while writing";
706
+ reason = STREAM_HANDSHAKE_DISCONNECT_SOCKET_WRITE_FAILED;
707
+ }
708
+ }
709
+ spinlock_unlock(&rpt->thread.send_to_child.spinlock);
710
+
711
+ if (disconnect_reason) {
712
+ worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SEND_ERROR);
713
+ nd_log(NDLS_DAEMON, NDLP_ERR,
714
+ "STREAM RECEIVE[%zu] '%s' [from [%s]:%s]: %s (%zd, on fd %d) - closing connection - "
715
+ "we have sent %zu bytes in %zu operations.",
716
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rpt->client_port,
717
+ disconnect_reason, rc, rpt->sock.fd, stats->bytes_sent, stats->sends);
718
+
719
+ receiver_set_exit_reason(rpt, reason, false);
720
+ stream_receiver_remove(sth, rpt, disconnect_reason);
721
+ return false;
722
}
723
}
681
- spinlock_unlock(&rpt->thread.send_to_child.spinlock);
682
-
683
- if (disconnect_reason) {
684
- worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SEND_ERROR);
685
- nd_log(NDLS_DAEMON, NDLP_ERR,
686
- "STREAM RECEIVE[%zu] %s [from %s]: %s (%zd, on fd %d) - closing connection - "
687
- "we have sent %zu bytes in %zu operations.",
688
- sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, disconnect_reason, rc, rpt->sock.fd,
689
- stats->bytes_sent, stats->sends);
690
-
691
- receiver_set_exit_reason(rpt, reason, false);
692
- stream_receiver_remove(sth, rpt, disconnect_reason);
693
- return;
694
- }
724
+ else
725
+ break;
726
}
727
}
728
729
if (!(events & ND_POLL_READ))
699
- return;
730
+ return true;
731
732
// we can receive data from this socket
733
734
worker_is_busy(WORKER_STREAM_JOB_SOCKET_RECEIVE);
704
- bool removed = false;
705
- while(!removed) {
735
+ bool removed = false, stop = false;
736
+ size_t iterations = 0;
737
+ while(!removed && !stop && iterations++ < MAX_IO_ITERATIONS_PER_EVENT) {
738
ssize_t rc = stream_receive_and_process(sth, rpt, parser, &removed);
739
if (likely(rc > 0)) {
740
rpt->last_msg_t = (time_t)(now_ut / USEC_PER_SEC);
741
+
742
+ if(stream_thread_process_opcodes(sth, &rpt->thread.meta))
743
+ stop = true;
744
}
745
else if (rc == 0 || errno == ECONNRESET) {
746
worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_REMOTE_CLOSED);
747
nd_log(NDLS_DAEMON, NDLP_ERR,
713
- "STREAM RECEIVE[%zu] %s [from %s]: socket %d reports EOF (closed by child).",
714
- sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rpt->sock.fd);
748
+ "STREAM RECEIVE[%zu] '%s' [from [%s]:%s]: socket %d reports EOF (closed by child).",
749
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rpt->client_port, rpt->sock.fd);
750
receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_SOCKET_CLOSED_BY_REMOTE_END, false);
751
stream_receiver_remove(sth, rpt, "socket reports EOF (closed by child)");
717
- return;
752
+ return false;
753
}
754
else if (rc < 0) {
755
if(removed)
721
- return;
756
+ return false;
757
758
else if ((errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR))
759
// will try later
725
- break;
760
+ stop = true;
761
else {
762
worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_RECEIVE_ERROR);
763
nd_log(NDLS_DAEMON, NDLP_ERR,
729
- "STREAM RECEIVE[%zu] %s [from %s]: error during receive (%zd, on fd %d) - closing connection.",
730
- sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rc, rpt->sock.fd);
764
+ "STREAM RECEIVE[%zu] '%s' [from [%s]:%s]: error during receive (%zd, on fd %d) - closing connection.",
765
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rpt->client_port, rc, rpt->sock.fd);
766
receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_SOCKET_READ_FAILED, false);
767
stream_receiver_remove(sth, rpt, "error during receive");
733
- return;
768
+ return false;
769
}
770
}
771
}
772
+
773
+ return !removed;
774
}
775
776
void stream_receiver_cleanup(struct stream_thread *sth) {
819
if (rpt->config.health.delay > 0) {
820
host->health.delay_up_to = now_realtime_sec() + rpt->config.health.delay;
821
nd_log(NDLS_DAEMON, NDLP_DEBUG,
785
- "[%s]: Postponing health checks for %" PRId64 " seconds, because it was just connected.",
786
- rrdhost_hostname(host),
822
+ "STREAM RECEIVE '%s' [from [%s]:%s]: "
823
+ "Postponing health checks for %" PRId64 " seconds, because it was just connected.",
824
+ rrdhost_hostname(host), rpt->client_ip, rpt->client_port,
825
(int64_t) rpt->config.health.delay);
826
}
827
}
835
signal_rrdcontext = true;
836
stream_receiver_replication_reset(host);
837
800
- rrdhost_flag_clear(rpt->host, RRDHOST_FLAG_STREAM_RECEIVER_DISCONNECTED);
838
+ rrdhost_flag_set(rpt->host, RRDHOST_FLAG_COLLECTOR_ONLINE);
839
aclk_queue_node_info(rpt->host, true);
840
841
rrdhost_stream_parents_reset(host, STREAM_HANDSHAKE_PREPARING);
848
if(signal_rrdcontext)
849
rrdcontext_host_child_connected(host);
850
851
+ if(set_this)
852
+ ml_host_start(host);
853
+
854
return set_this;
855
}
856
863
// Make sure that we detach this thread and don't kill a freshly arriving receiver
864
865
if (host->receiver == rpt) {
825
- rrdhost_flag_set(host, RRDHOST_FLAG_STREAM_RECEIVER_DISCONNECTED);
866
+ rrdhost_flag_clear(host, RRDHOST_FLAG_COLLECTOR_ONLINE);
867
rrdhost_receiver_unlock(host);
868
{
869
// run all these without having the receiver lock
870
871
+ ml_host_stop(host);
872
stream_path_child_disconnected(host);
873
stream_sender_signal_to_stop_and_wait(host, STREAM_HANDSHAKE_DISCONNECT_RECEIVER_LEFT, false);
874
stream_receiver_replication_reset(host);