5
#include "stream-receiver-internals.h"
6
#include "web/server/h2o/http_server.h"
7
8
+static void stream_receiver_remove(struct stream_thread *sth, struct receiver_state *rpt, const char *why);
9
+
10
// When a child disconnects this is the maximum we will wait
11
// before we update the cloud that the child is offline
12
#define MAX_CHILD_DISC_DELAY (30000)
30
31
// --------------------------------------------------------------------------------------------------------------------
32
31
-static inline ssize_t read_stream(struct receiver_state *r, char* buffer, size_t size) {
33
+static bool stream_receiver_log_capabilities(BUFFER *wb, void *ptr) {
34
+ struct receiver_state *rpt = ptr;
35
+ if(!rpt)
36
+ return false;
37
+
38
+ stream_capabilities_to_string(wb, rpt->capabilities);
39
+ return true;
40
+}
41
+
42
+static bool stream_receiver_log_transport(BUFFER *wb, void *ptr) {
43
+ struct receiver_state *rpt = ptr;
44
+ if(!rpt)
45
+ return false;
46
+
47
+ buffer_strcat(wb, nd_sock_is_ssl(&rpt->sock) ? "https" : "http");
48
+ return true;
49
+}
50
+
51
+// --------------------------------------------------------------------------------------------------------------------
52
+
53
+static inline ssize_t write_stream(struct receiver_state *r, char* buffer, size_t size) {
54
if(unlikely(!size)) {
55
internal_error(true, "%s() asked to read zero bytes", __FUNCTION__);
56
+ errno_clear();
57
return -2;
58
}
59
60
#ifdef ENABLE_H2O
61
if (is_h2o_rrdpush(r)) {
39
- if(nd_thread_signaled_to_cancel())
62
+ if(nd_thread_signaled_to_cancel()) {
63
+ errno_clear();
64
return -3;
65
+ }
66
42
- return (ssize_t)h2o_stream_read(r->h2o_ctx, buffer, size);
67
+ return (ssize_t)h2o_stream_write(r->h2o_ctx, buffer, size);
68
}
69
#endif
70
46
- ssize_t bytes_read = nd_sock_read(&r->sock, buffer, size, 0);
47
- if(bytes_read <= 0) {
48
- if (bytes_read == 0)
49
- netdata_log_error("STREAM: %s(): EOF while reading data from socket!", __FUNCTION__);
50
- else {
51
- netdata_log_error("STREAM: %s() failed to read from socket!", __FUNCTION__);
52
- bytes_read = -1;
53
- }
54
- }
55
-
56
- return bytes_read;
71
+ ssize_t bytes_written = nd_sock_send_nowait(&r->sock, buffer, size);
72
+ return bytes_written;
73
}
74
59
-static inline STREAM_HANDSHAKE read_stream_error_to_reason(ssize_t code) {
60
- if(code > 0)
61
- return 0;
62
-
63
- switch(code) {
64
- case 0:
65
- // EOF
66
- return STREAM_HANDSHAKE_DISCONNECT_SOCKET_EOF;
67
-
68
- case -1:
69
- // failed to read
70
- return STREAM_HANDSHAKE_DISCONNECT_SOCKET_READ_FAILED;
71
-
72
- case -2:
73
- // asked to read zero bytes
74
- return STREAM_HANDSHAKE_DISCONNECT_NOT_SUFFICIENT_RECEIVER_READ_BUFFER;
75
+static inline ssize_t read_stream(struct receiver_state *r, char* buffer, size_t size) {
76
+ if(unlikely(!size)) {
77
+ internal_error(true, "%s() asked to read zero bytes", __FUNCTION__);
78
+ errno_clear();
79
+ return -2;
80
+ }
81
76
- case -3:
77
- // the thread is cancelled
78
- return STREAM_HANDSHAKE_DISCONNECT_SHUTDOWN;
82
+#ifdef ENABLE_H2O
83
+ if (is_h2o_rrdpush(r)) {
84
+ if(nd_thread_signaled_to_cancel()) {
85
+ errno_clear();
86
+ return -3;
87
+ }
88
80
- default:
81
- // anything else
82
- return STREAM_HANDSHAKE_DISCONNECT_UNKNOWN_SOCKET_READ_ERROR;
89
+ return (ssize_t)h2o_stream_read(r->h2o_ctx, buffer, size);
90
}
91
+#endif
92
+
93
+ ssize_t bytes_read = nd_sock_revc_nowait(&r->sock, buffer, size);
94
+ return bytes_read;
95
}
96
97
// --------------------------------------------------------------------------------------------------------------------
211
"%s: read_buffer does not start with zero #2", __FUNCTION__ );
212
213
ssize_t bytes_read = read_stream(r, r->thread.compressed.buf + r->thread.compressed.used,
203
- sizeof(r->thread.compressed.buf) - r->thread.compressed.used);
214
+ r->thread.compressed.size - r->thread.compressed.used);
215
216
if(bytes_read > 0) {
217
r->thread.compressed.used += bytes_read;
239
240
// --------------------------------------------------------------------------------------------------------------------
241
242
+void stream_receiver_handle_op(struct stream_thread *sth, struct receiver_state *rpt, struct stream_opcode *msg) {
243
+ ND_LOG_STACK lgs[] = {
244
+ ND_LOG_FIELD_STR(NDF_NIDL_NODE, rpt->host->hostname),
245
+ ND_LOG_FIELD_TXT(NDF_SRC_IP, rpt->client_ip),
246
+ ND_LOG_FIELD_TXT(NDF_SRC_PORT, rpt->client_port),
247
+ ND_LOG_FIELD_CB(NDF_SRC_TRANSPORT, stream_receiver_log_transport, rpt),
248
+ ND_LOG_FIELD_CB(NDF_SRC_CAPABILITIES, stream_receiver_log_capabilities, rpt),
249
+ ND_LOG_FIELD_UUID(NDF_MESSAGE_ID, &streaming_to_parent_msgid),
250
+ ND_LOG_FIELD_END(),
251
+ };
252
+ ND_LOG_STACK_PUSH(lgs);
253
+
254
+ if(msg->opcode & STREAM_OPCODE_RECEIVER_BUFFER_OVERFLOW) {
255
+ worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_OVERFLOW);
256
+ errno_clear();
257
+ spinlock_lock(&rpt->thread.send_to_child.spinlock);
258
+ // copy the statistics
259
+ STREAM_CIRCULAR_BUFFER_STATS stats = *stream_circular_buffer_stats_unsafe(rpt->thread.send_to_child.scb);
260
+ spinlock_unlock(&rpt->thread.send_to_child.spinlock);
261
+ 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). "
263
+ "Restarting connection.",
264
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip,
265
+ stats.bytes_size, stats.bytes_max_size, stats.bytes_outstanding, stats.bytes_available);
266
+
267
+ stream_receiver_remove(sth, rpt, "receiver send buffer overflow");
268
+ return;
269
+ }
270
+
271
+ nd_log(NDLS_DAEMON, NDLP_ERR,
272
+ "STREAM RECEIVE[%zu]: invalid msg id %u", sth->id, (unsigned)msg->opcode);
273
+}
274
+
275
+ssize_t send_to_child(const char *txt, void *data, STREAM_TRAFFIC_TYPE type) {
276
+ struct receiver_state *rpt = data;
277
+ if(!rpt || rpt->thread.meta.type != POLLFD_TYPE_RECEIVER || !rpt->thread.send_to_child.scb)
278
+ return 0;
279
+
280
+ spinlock_lock(&rpt->thread.send_to_child.spinlock);
281
+ STREAM_CIRCULAR_BUFFER *scb = rpt->thread.send_to_child.scb;
282
+ STREAM_CIRCULAR_BUFFER_STATS *stats = stream_circular_buffer_stats_unsafe(scb);
283
+ bool was_empty = stats->bytes_outstanding == 0;
284
+ struct stream_opcode msg = rpt->thread.send_to_child.msg;
285
+ msg.opcode = STREAM_OPCODE_NONE;
286
+
287
+ size_t size = strlen(txt);
288
+ ssize_t rc = (ssize_t)size;
289
+ if(!stream_circular_buffer_add_unsafe(scb, txt, size, size, type)) {
290
+ msg.opcode = STREAM_OPCODE_RECEIVER_BUFFER_OVERFLOW;
291
+ rc = -1;
292
+ }
293
+ else if(was_empty)
294
+ msg.opcode = STREAM_OPCODE_RECEIVER_POLLOUT;
295
+
296
+ spinlock_unlock(&rpt->thread.send_to_child.spinlock);
297
+
298
+ if(msg.opcode != STREAM_OPCODE_NONE)
299
+ stream_receiver_send_opcode(rpt, msg);
300
+
301
+ return rc;
302
+}
303
+
304
static void streaming_parser_init(struct receiver_state *rpt) {
305
rpt->thread.cd = (struct plugind){
306
.update_every = default_rrd_update_every,
307
.unsafe = {
235
- .spinlock = NETDATA_SPINLOCK_INITIALIZER,
308
+ .spinlock = SPINLOCK_INITIALIZER,
309
.running = true,
310
.enabled = true,
311
},
313
};
314
315
// put the client IP and port into the buffers used by plugins.d
243
- snprintfz(rpt->thread.cd.id, CONFIG_MAX_NAME, "%s:%s", rpt->client_ip, rpt->client_port);
244
- snprintfz(rpt->thread.cd.filename, FILENAME_MAX, "%s:%s", rpt->client_ip, rpt->client_port);
245
- snprintfz(rpt->thread.cd.fullfilename, FILENAME_MAX, "%s:%s", rpt->client_ip, rpt->client_port);
246
- snprintfz(rpt->thread.cd.cmd, PLUGINSD_CMD_MAX, "%s:%s", rpt->client_ip, rpt->client_port);
316
+ {
317
+ char buf[CONFIG_MAX_NAME];
318
+ snprintfz(buf, sizeof(buf), "%s:%s", rpt->client_ip, rpt->client_port);
319
+ string_freez(rpt->thread.cd.id);
320
+ rpt->thread.cd.id = string_strdupz(buf);
321
+ }
322
+
323
+ {
324
+ char buf[FILENAME_MAX + 1];
325
+ snprintfz(buf, sizeof(buf), "%s:%s", rpt->client_ip, rpt->client_port);
326
+ string_freez(rpt->thread.cd.filename);
327
+ rpt->thread.cd.filename = string_strdupz(buf);
328
+
329
+ string_freez(rpt->thread.cd.fullfilename);
330
+ rpt->thread.cd.fullfilename = string_strdupz(buf);
331
+
332
+ string_freez(rpt->thread.cd.cmd);
333
+ rpt->thread.cd.cmd = string_strdupz(buf);
334
+ }
335
336
PARSER *parser = NULL;
337
{
345
};
346
347
parser = parser_init(&user, -1, -1, PARSER_INPUT_SPLIT, &rpt->sock);
348
+ parser->send_to_plugin_data = rpt;
349
+ parser->send_to_plugin_cb = send_to_child;
350
}
351
352
#ifdef ENABLE_H2O
384
385
// --------------------------------------------------------------------------------------------------------------------
386
297
-static bool stream_receiver_log_capabilities(BUFFER *wb, void *ptr) {
298
- struct receiver_state *rpt = ptr;
299
- if(!rpt)
300
- return false;
301
-
302
- stream_capabilities_to_string(wb, rpt->capabilities);
303
- return true;
304
-}
305
-
306
-static bool stream_receiver_log_transport(BUFFER *wb, void *ptr) {
307
- struct receiver_state *rpt = ptr;
308
- if(!rpt)
309
- return false;
310
-
311
- buffer_strcat(wb, nd_sock_is_ssl(&rpt->sock) ? "https" : "http");
312
- return true;
313
-}
314
-
315
-// --------------------------------------------------------------------------------------------------------------------
316
-
387
void stream_receiver_move_queue_to_running_unsafe(struct stream_thread *sth) {
388
internal_fatal(sth->tid != gettid_cached(), "Function %s() should only be used by the dispatcher thread", __FUNCTION__ );
389
407
"STREAM RECEIVE[%zu] [%s]: moving host from receiver queue to receiver running...",
408
sth->id, rrdhost_hostname(rpt->host));
409
340
- internal_fatal(RECEIVERS_GET(&sth->rcv.receivers, (Word_t)rpt) != NULL, "Receiver to be added is already in the list of receivers");
341
- RECEIVERS_SET(&sth->rcv.receivers, (Word_t)rpt, rpt);
342
-
343
- streaming_parser_init(rpt);
344
-
410
rpt->host->stream.rcv.status.tid = gettid_cached();
411
rpt->thread.meta.type = POLLFD_TYPE_RECEIVER;
412
rpt->thread.meta.rpt = rpt;
413
+
414
+ spinlock_lock(&rpt->thread.send_to_child.spinlock);
415
+ 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);
419
+ rpt->thread.send_to_child.msg.thread_slot = (int32_t)sth->id;
420
+ rpt->thread.send_to_child.msg.session = os_random32();
421
+ rpt->thread.send_to_child.msg.meta = &rpt->thread.meta;
422
+ spinlock_unlock(&rpt->thread.send_to_child.spinlock);
423
+
424
+ internal_fatal(META_GET(&sth->run.meta, (Word_t)&rpt->thread.meta) != NULL, "Receiver to be added is already in the list of receivers");
425
+ META_SET(&sth->run.meta, (Word_t)&rpt->thread.meta, &rpt->thread.meta);
426
+
427
+ if(sock_setnonblock(rpt->sock.fd) < 0)
428
+ nd_log(NDLS_DAEMON, NDLP_ERR,
429
+ "STREAM RECEIVE '%s' [from [%s]:%s]: cannot set the non-blocking flag from socket %d",
430
+ rrdhost_hostname(rpt->host), rpt->client_ip, rpt->client_port, rpt->sock.fd);
431
+
432
if(!nd_poll_add(sth->run.ndpl, rpt->sock.fd, ND_POLL_READ, &rpt->thread.meta))
349
- internal_fatal(true, "Failed to add receiver socket to nd_poll()");
433
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to add receiver socket to nd_poll()");
434
+
435
+ // keep this last, since it sends commands back to the child
436
+ streaming_parser_init(rpt);
437
}
438
}
439
353
-static void stream_receiver_on_disconnect(struct stream_thread *sth __maybe_unused, struct receiver_state *rpt) {
440
+static void stream_receiver_remove(struct stream_thread *sth, struct receiver_state *rpt, const char *why) {
441
internal_fatal(sth->tid != gettid_cached(), "Function %s() should only be used by the dispatcher thread", __FUNCTION__ );
355
- if(!rpt) return;
442
+
443
+ nd_log(NDLS_DAEMON, NDLP_ERR,
444
+ "STREAM RECEIVE[%zu] '%s' [from [%s]:%s]: "
445
+ "receiver disconnected: %s"
446
+ , sth->id
447
+ , rpt->hostname ? rpt->hostname : "-"
448
+ , rpt->client_ip ? rpt->client_ip : "-"
449
+ , rpt->client_port ? rpt->client_port : "-"
450
+ , why ? why : "");
451
+
452
+ internal_fatal(META_GET(&sth->run.meta, (Word_t)&rpt->thread.meta) == NULL, "Receiver to be removed is not found in the list of receivers");
453
+ META_DEL(&sth->run.meta, (Word_t)&rpt->thread.meta);
454
+
455
+ if(!nd_poll_del(sth->run.ndpl, rpt->sock.fd))
456
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to delete receiver socket from nd_poll()");
457
+
458
+ rpt->host->stream.rcv.status.tid = 0;
459
+
460
+ spinlock_lock(&rpt->thread.send_to_child.spinlock);
461
+ rpt->thread.send_to_child.msg.session = 0;
462
+ rpt->thread.send_to_child.msg.meta = NULL;
463
+ stream_circular_buffer_destroy(rpt->thread.send_to_child.scb);
464
+ rpt->thread.send_to_child.scb = NULL;
465
+ spinlock_unlock(&rpt->thread.send_to_child.spinlock);
466
+
467
+ stream_thread_node_removed(rpt->host);
468
469
buffer_free(rpt->thread.buffer);
470
rpt->thread.buffer = NULL;
500
501
rrdhost_clear_receiver(rpt);
502
rrdhost_set_is_parent_label();
503
+
504
stream_receiver_free(rpt);
505
+ // DO NOT USE rpt after this point
506
}
507
394
-static void stream_receiver_remove(struct stream_thread *sth, struct receiver_state *rpt, const char *why) {
395
- internal_fatal(sth->tid != gettid_cached(), "Function %s() should only be used by the dispatcher thread", __FUNCTION__ );
396
-
397
- nd_log(NDLS_DAEMON, NDLP_ERR,
398
- "STREAM RECEIVE[%zu] '%s' [from [%s]:%s]: "
399
- "receiver disconnected: %s"
400
- , sth->id
401
- , rpt->hostname ? rpt->hostname : "-"
402
- , rpt->client_ip ? rpt->client_ip : "-"
403
- , rpt->client_port ? rpt->client_port : "-"
404
- , why ? why : "");
508
+static ssize_t
509
+stream_receive_and_process(struct stream_thread *sth, struct receiver_state *rpt, PARSER *parser, bool *removed) {
510
+ ssize_t rc;
511
+ if(rpt->thread.compressed.enabled) {
512
+ rc = receiver_read_compressed(rpt);
513
+ if(unlikely(rc <= 0))
514
+ return rc;
515
+
516
+ while(!nd_thread_signaled_to_cancel() && service_running(SERVICE_STREAMING) && !receiver_should_stop(rpt)) {
517
+ worker_is_busy(WORKER_STREAM_JOB_DECOMPRESS);
518
+
519
+ // feed the decompressor with the new data we just read
520
+ decompressor_status_t feed_rc = receiver_feed_decompressor(rpt);
521
+
522
+ if(likely(feed_rc == DECOMPRESS_OK)) {
523
+ while (true) {
524
+ // feed our uncompressed data buffer with new data
525
+ decompressor_status_t decompress_rc = receiver_get_decompressed(rpt);
526
+
527
+ if (likely(decompress_rc == DECOMPRESS_OK)) {
528
+ // loop through all the complete lines found in the uncompressed buffer
529
+
530
+ while (buffered_reader_next_line(&rpt->reader, rpt->thread.buffer)) {
531
+ if (unlikely(parser_action(parser, rpt->thread.buffer->buffer))) {
532
+ receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_PARSER_FAILED, false);
533
+ stream_receiver_remove(sth, rpt, "parser action failed");
534
+ *removed = true;
535
+ return -1;
536
+ }
537
406
- internal_fatal(RECEIVERS_GET(&sth->rcv.receivers, (Word_t)rpt) == NULL, "Receiver to be removed is not found in the list of receivers");
407
- RECEIVERS_DEL(&sth->rcv.receivers, (Word_t)rpt);
408
- if(!nd_poll_del(sth->run.ndpl, rpt->sock.fd))
409
- internal_fatal(true, "Failed to remove receiver socket from nd_poll()");
538
+ rpt->thread.buffer->len = 0;
539
+ rpt->thread.buffer->buffer[0] = '\0';
540
+ }
541
+ }
542
+ else if (decompress_rc == DECOMPRESS_NEED_MORE_DATA)
543
+ break;
544
+
545
+ else {
546
+ receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_PARSER_FAILED, false);
547
+ stream_receiver_remove(sth, rpt, "receiver decompressor failed");
548
+ *removed = true;
549
+ return -1;
550
+ }
551
+ }
552
+ }
553
+ else if (feed_rc == DECOMPRESS_NEED_MORE_DATA)
554
+ break;
555
+ else {
556
+ receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_PARSER_FAILED, false);
557
+ stream_receiver_remove(sth, rpt, "receiver compressed data invalid");
558
+ *removed = true;
559
+ return -1;
560
+ }
561
+ }
562
411
- rpt->host->stream.rcv.status.tid = 0;
563
+ if(receiver_should_stop(rpt)) {
564
+ receiver_set_exit_reason(rpt, rpt->exit.reason, false);
565
+ stream_receiver_remove(sth, rpt, "received stop signal");
566
+ *removed = true;
567
+ return -1;
568
+ }
569
+ }
570
+ else {
571
+ rc = receiver_read_uncompressed(rpt);
572
+ if(rc <= 0) return rc;
573
+
574
+ while(buffered_reader_next_line(&rpt->reader, rpt->thread.buffer)) {
575
+ if(unlikely(parser_action(parser, rpt->thread.buffer->buffer))) {
576
+ receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_PARSER_FAILED, false);
577
+ stream_receiver_remove(sth, rpt, "parser action failed");
578
+ *removed = true;
579
+ return -1;
580
+ }
581
413
- stream_thread_node_removed(rpt->host);
582
+ rpt->thread.buffer->len = 0;
583
+ rpt->thread.buffer->buffer[0] = '\0';
584
+ }
585
+ }
586
415
- stream_receiver_on_disconnect(sth, rpt);
416
- // DO NOT USE rpt after this point
587
+ return rc;
588
}
589
590
// process poll() events for streaming receivers
420
-void stream_receive_process_poll_events(struct stream_thread *sth, struct receiver_state *rpt, nd_poll_event_t events __maybe_unused, usec_t now_ut) {
421
- PARSER *parser = __atomic_load_n(&rpt->thread.parser, __ATOMIC_RELAXED);
422
- ND_LOG_STACK lgs[] = {
423
- ND_LOG_FIELD_TXT(NDF_SRC_IP, rpt->client_ip),
424
- ND_LOG_FIELD_TXT(NDF_SRC_PORT, rpt->client_port),
425
- ND_LOG_FIELD_TXT(NDF_NIDL_NODE, rpt->hostname),
426
- ND_LOG_FIELD_CB(NDF_SRC_TRANSPORT, stream_receiver_log_transport, rpt),
427
- ND_LOG_FIELD_CB(NDF_SRC_CAPABILITIES, stream_receiver_log_capabilities, rpt),
428
- ND_LOG_FIELD_CB(NDF_REQUEST, line_splitter_reconstruct_line, &parser->line),
429
- ND_LOG_FIELD_CB(NDF_NIDL_NODE, parser_reconstruct_node, parser),
430
- ND_LOG_FIELD_CB(NDF_NIDL_INSTANCE, parser_reconstruct_instance, parser),
431
- ND_LOG_FIELD_CB(NDF_NIDL_CONTEXT, parser_reconstruct_context, parser),
432
- ND_LOG_FIELD_END(),
433
- };
434
- ND_LOG_STACK_PUSH(lgs);
591
+void stream_receive_process_poll_events(struct stream_thread *sth, struct receiver_state *rpt, nd_poll_event_t events, usec_t now_ut)
592
+{
593
+ internal_fatal(
594
+ sth->tid != gettid_cached(), "Function %s() should only be used by the dispatcher thread", __FUNCTION__);
595
436
- if(receiver_should_stop(rpt)) {
437
- receiver_set_exit_reason(rpt, rpt->exit.reason, false);
438
- stream_receiver_remove(sth, rpt, "received stop signal");
439
- return;
440
- }
441
-
442
- rpt->last_msg_t = (time_t)(now_ut / USEC_PER_SEC);
596
+ PARSER *parser = __atomic_load_n(&rpt->thread.parser, __ATOMIC_RELAXED);
597
+ ND_LOG_STACK lgs[] = {
598
+ ND_LOG_FIELD_TXT(NDF_SRC_IP, rpt->client_ip),
599
+ ND_LOG_FIELD_TXT(NDF_SRC_PORT, rpt->client_port),
600
+ ND_LOG_FIELD_TXT(NDF_NIDL_NODE, rpt->hostname),
601
+ ND_LOG_FIELD_CB(NDF_SRC_TRANSPORT, stream_receiver_log_transport, rpt),
602
+ ND_LOG_FIELD_CB(NDF_SRC_CAPABILITIES, stream_receiver_log_capabilities, rpt),
603
+ ND_LOG_FIELD_CB(NDF_REQUEST, line_splitter_reconstruct_line, &parser->line),
604
+ ND_LOG_FIELD_CB(NDF_NIDL_NODE, parser_reconstruct_node, parser),
605
+ ND_LOG_FIELD_CB(NDF_NIDL_INSTANCE, parser_reconstruct_instance, parser),
606
+ ND_LOG_FIELD_CB(NDF_NIDL_CONTEXT, parser_reconstruct_context, parser),
607
+ ND_LOG_FIELD_END(),
608
+ };
609
+ ND_LOG_STACK_PUSH(lgs);
610
444
- if(rpt->thread.compressed.enabled) {
445
- worker_is_busy(WORKER_STREAM_JOB_SOCKET_RECEIVE);
611
+ if (receiver_should_stop(rpt)) {
612
+ receiver_set_exit_reason(rpt, rpt->exit.reason, false);
613
+ stream_receiver_remove(sth, rpt, "received stop signal");
614
+ return;
615
+ }
616
447
- ssize_t bytes = receiver_read_compressed(rpt);
448
- if(unlikely(bytes <= 0)) {
449
- if(bytes < 0 && (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR))
450
- return;
617
+ if (unlikely(events & (ND_POLL_ERROR | ND_POLL_HUP | ND_POLL_INVALID))) {
618
+ // we have errors on this socket
619
452
- worker_is_busy(WORKER_STREAM_JOB_SOCKET_ERROR);
453
- receiver_set_exit_reason(rpt, read_stream_error_to_reason(bytes), false);
454
- stream_receiver_remove(sth, rpt, "receiver socket read error");
455
- return;
456
- }
620
+ worker_is_busy(WORKER_STREAM_JOB_SOCKET_ERROR);
621
458
- bool node_removed = false;
459
- while(!node_removed && !nd_thread_signaled_to_cancel() && service_running(SERVICE_STREAMING) && !receiver_should_stop(rpt)) {
460
- worker_is_busy(WORKER_STREAM_JOB_DECOMPRESS);
622
+ char *error = "unknown error";
623
462
- // feed the decompressor with the new data we just read
463
- decompressor_status_t feed = receiver_feed_decompressor(rpt);
624
+ if (events & ND_POLL_ERROR)
625
+ error = "socket reports errors";
626
+ else if (events & ND_POLL_HUP)
627
+ error = "connection closed by remote end (HUP)";
628
+ else if (events & ND_POLL_INVALID)
629
+ error = "connection is invalid";
630
465
- if(likely(feed == DECOMPRESS_OK)) {
466
- while (!node_removed) {
467
- // feed our uncompressed data buffer with new data
468
- decompressor_status_t rc = receiver_get_decompressed(rpt);
631
+ worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SOCKET_ERROR);
632
470
- if (likely(rc == DECOMPRESS_OK)) {
471
- // loop through all the complete lines found in the uncompressed buffer
633
+ nd_log(
634
+ NDLS_DAEMON,
635
+ NDLP_ERR,
636
+ "STREAM RECEIVE[%zu] %s [from %s]: %s - closing connection",
637
+ sth->id,
638
+ rrdhost_hostname(rpt->host),
639
+ rpt->client_ip,
640
+ error);
641
473
- while (buffered_reader_next_line(&rpt->reader, rpt->thread.buffer)) {
474
- if (unlikely(parser_action(parser, rpt->thread.buffer->buffer))) {
475
- receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_PARSER_FAILED, false);
476
- stream_receiver_remove(sth, rpt, "parser action failed");
477
- node_removed = true;
478
- break;
479
- }
642
+ receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_SOCKET_ERROR, false);
643
+ stream_receiver_remove(sth, rpt, error);
644
+ return;
645
+ }
646
481
- rpt->thread.buffer->len = 0;
482
- rpt->thread.buffer->buffer[0] = '\0';
483
- }
484
- }
485
- else if (rc == DECOMPRESS_NEED_MORE_DATA)
486
- break;
487
-
488
- else {
489
- receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_PARSER_FAILED, false);
490
- stream_receiver_remove(sth, rpt, "receiver decompressor failed");
491
- node_removed = true;
492
- break;
493
- }
494
- }
647
+ if (events & ND_POLL_WRITE) {
648
+ worker_is_busy(WORKER_STREAM_JOB_SOCKET_SEND);
649
+
650
+ if (spinlock_trylock(&rpt->thread.send_to_child.spinlock)) {
651
+ const char *disconnect_reason = NULL;
652
+ STREAM_HANDSHAKE reason;
653
+
654
+ char *chunk;
655
+ STREAM_CIRCULAR_BUFFER *scb = rpt->thread.send_to_child.scb;
656
+ STREAM_CIRCULAR_BUFFER_STATS *stats = stream_circular_buffer_stats_unsafe(scb);
657
+ size_t outstanding = stream_circular_buffer_get_unsafe(scb, &chunk);
658
+ ssize_t rc = write_stream(rpt, chunk, outstanding);
659
+ if (likely(rc > 0)) {
660
+ stream_circular_buffer_del_unsafe(scb, rc);
661
+ if (!stats->bytes_outstanding) {
662
+ if (!nd_poll_upd(sth->run.ndpl, rpt->sock.fd, ND_POLL_READ, &rpt->thread.meta))
663
+ nd_log(NDLS_DAEMON, NDLP_ERR, "STREAM RECEIVE: cannot update nd_poll()");
664
+
665
+ // recreate the circular buffer if we have to
666
+ stream_circular_buffer_recreate_timed_unsafe(rpt->thread.send_to_child.scb, now_ut, false);
667
}
496
- else if (feed == DECOMPRESS_NEED_MORE_DATA)
497
- break;
668
+ } else if (rc == 0 || errno == ECONNRESET) {
669
+ disconnect_reason = "socket reports EOF (closed by child)";
670
+ reason = STREAM_HANDSHAKE_DISCONNECT_SOCKET_CLOSED_BY_REMOTE_END;
671
+ } else if (rc < 0) {
672
+ if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
673
+ // will try later
674
+ ;
675
else {
499
- receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_PARSER_FAILED, false);
500
- stream_receiver_remove(sth, rpt, "receiver compressed data invalid");
501
- node_removed = true;
502
- break;
676
+ disconnect_reason = "socket reports error while writing";
677
+ reason = STREAM_HANDSHAKE_DISCONNECT_SOCKET_WRITE_FAILED;
678
}
679
}
505
-
506
- if(!node_removed && receiver_should_stop(rpt)) {
507
- receiver_set_exit_reason(rpt, rpt->exit.reason, false);
508
- stream_receiver_remove(sth, rpt, "received stop signal");
680
+ spinlock_unlock(&rpt->thread.send_to_child.spinlock);
681
+
682
+ if (disconnect_reason) {
683
+ worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SEND_ERROR);
684
+ nd_log(NDLS_DAEMON, NDLP_ERR,
685
+ "STREAM RECEIVE[%zu] %s [from %s]: %s (%zd, on fd %d) - closing connection - "
686
+ "we have sent %zu bytes in %zu operations.",
687
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, disconnect_reason, rc, rpt->sock.fd,
688
+ stats->bytes_sent, stats->sends);
689
+
690
+ receiver_set_exit_reason(rpt, reason, false);
691
+ stream_receiver_remove(sth, rpt, disconnect_reason);
692
return;
693
}
694
}
512
- else {
513
- worker_is_busy(WORKER_STREAM_JOB_SOCKET_RECEIVE);
695
+ }
696
515
- ssize_t bytes = receiver_read_uncompressed(rpt);
516
- if(unlikely(bytes <= 0)) {
517
- if(bytes < 0 && (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR))
518
- return;
697
+ if (!(events & ND_POLL_READ))
698
+ return;
699
520
- worker_is_busy(WORKER_STREAM_JOB_SOCKET_ERROR);
521
- receiver_set_exit_reason(rpt, read_stream_error_to_reason(bytes), false);
522
- stream_receiver_remove(sth, rpt, "socker read error");
523
- return;
524
- }
700
+ // we can receive data from this socket
701
526
- while(buffered_reader_next_line(&rpt->reader, rpt->thread.buffer)) {
527
- if(unlikely(parser_action(parser, rpt->thread.buffer->buffer))) {
528
- receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_PARSER_FAILED, false);
529
- stream_receiver_remove(sth, rpt, "parser action failed");
530
- break;
531
- }
702
+ worker_is_busy(WORKER_STREAM_JOB_SOCKET_RECEIVE);
703
+ while(true) {
704
+ bool removed = false;
705
+ ssize_t rc = stream_receive_and_process(sth, rpt, parser, &removed);
706
+ if (likely(rc > 0)) {
707
+ rpt->last_msg_t = (time_t)(now_ut / USEC_PER_SEC);
708
+ }
709
+ else if (rc == 0 || errno == ECONNRESET) {
710
+ worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_REMOTE_CLOSED);
711
+ nd_log(NDLS_DAEMON, NDLP_ERR,
712
+ "STREAM RECEIVE[%zu] %s [from %s]: socket %d reports EOF (closed by child).",
713
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rpt->sock.fd);
714
+ receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_SOCKET_CLOSED_BY_REMOTE_END, false);
715
+ stream_receiver_remove(sth, rpt, "socket reports EOF (closed by child)");
716
+ return;
717
+ }
718
+ else if (rc < 0) {
719
+ if(removed)
720
+ return;
721
533
- rpt->thread.buffer->len = 0;
534
- rpt->thread.buffer->buffer[0] = '\0';
722
+ else if ((errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR))
723
+ // will try later
724
+ break;
725
+ else {
726
+ worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_RECEIVE_ERROR);
727
+ nd_log(NDLS_DAEMON, NDLP_ERR,
728
+ "STREAM RECEIVE[%zu] %s [from %s]: error during receive (%zd, on fd %d) - closing connection.",
729
+ sth->id, rrdhost_hostname(rpt->host), rpt->client_ip, rc, rpt->sock.fd);
730
+ receiver_set_exit_reason(rpt, STREAM_HANDSHAKE_DISCONNECT_SOCKET_READ_FAILED, false);
731
+ stream_receiver_remove(sth, rpt, "error during receive");
732
+ return;
733
}
734
}
735
+ }
736
}
737
738
void stream_receiver_cleanup(struct stream_thread *sth) {
739
Word_t idx = 0;
541
- for(struct receiver_state *rpt = RECEIVERS_FIRST(&sth->rcv.receivers, &idx);
542
- rpt;
543
- rpt = RECEIVERS_NEXT(&sth->rcv.receivers, &idx))
740
+ for(struct pollfd_meta *m = META_FIRST(&sth->run.meta, &idx);
741
+ m;
742
+ m = META_NEXT(&sth->run.meta, &idx)) {
743
+ if (m->type != POLLFD_TYPE_RECEIVER) continue;
744
+ struct receiver_state *rpt = m->rpt;
745
stream_receiver_remove(sth, rpt, "shutdown");
545
-
546
- RECEIVERS_FREE(&sth->rcv.receivers, NULL);
746
+ }
747
}
748
749
static void stream_receiver_replication_reset(RRDHOST *host) {