@cryptotaxi247 / netdata-1 / commits / dc42e45c6

Add some logging for cloud new architecture to access.log (#11788)

* add some logging for ng arch to access.log * change arrows to IN, OG, AC * log also the params for aclk requests * check for wc->host before using wc->host->hostname * turn two messages to info * reduce alert event logs * used thread local variables

Emmanuel Vasilakis committed Nov 18, 2021 at 11:56 UTC dc42e45c6a9aa35b02ce5b88e4e688066ca1958c
5 files changed +71 -34
aclk/aclk.c
+13 -7
@@ -183,6 +183,7 @@ void aclk_mqtt_wss_log_cb(mqtt_wss_log_type_t log_type, const char* str)
183 #define RX_MSGLEN_MAX 4096
184 static void msg_callback_old_protocol(const char *topic, const void *msg, size_t msglen, int qos)
185 {
186 + UNUSED(qos);
187 char cmsg[RX_MSGLEN_MAX];
188 size_t len = (msglen < RX_MSGLEN_MAX - 1) ? msglen : (RX_MSGLEN_MAX - 1);
189 const char *cmd_topic = aclk_get_topic(ACLK_TOPICID_COMMAND);
@@ -227,6 +228,7 @@ static void msg_callback_old_protocol(const char *topic, const void *msg, size_t
228 #ifdef ENABLE_NEW_CLOUD_PROTOCOL
229 static void msg_callback_new_protocol(const char *topic, const void *msg, size_t msglen, int qos)
230 {
231 + UNUSED(qos);
232 if (msglen > RX_MSGLEN_MAX)
233 error("Incoming ACLK message was bigger than MAX of %d and got truncated.", RX_MSGLEN_MAX);
234
@@ -281,7 +283,7 @@ static void puback_callback(uint16_t packet_id)
283 #endif
284
285 if (aclk_shared_state.mqtt_shutdown_msg_id == (int)packet_id) {
284 - error("Got PUBACK for shutdown message. Can exit gracefully.");
286 + info("Shutdown message has been acknowledged by the cloud. Exiting gracefully");
287 aclk_shared_state.mqtt_shutdown_msg_rcvd = 1;
288 }
289 }
@@ -314,7 +316,7 @@ static int handle_connection(mqtt_wss_client client)
316 // timeout 1000 to check at least once a second
317 // for netdata_exit
318 if (mqtt_wss_service(client, 1000) < 0){
317 - error("Connection Error or Dropped");
319 + error_report("Connection Error or Dropped");
320 return 1;
321 }
322
@@ -450,7 +452,7 @@ static int wait_popcorning_finishes()
452
453 void aclk_graceful_disconnect(mqtt_wss_client client)
454 {
453 - error("Preparing to Gracefully Shutdown the ACLK");
455 + info("Preparing to gracefully shutdown ACLK connection");
456 aclk_queue_lock();
457 aclk_queue_flush();
458 #ifdef ENABLE_NEW_CLOUD_PROTOCOL
@@ -467,14 +469,16 @@ void aclk_graceful_disconnect(mqtt_wss_client client)
469 break;
470 }
471 if (aclk_shared_state.mqtt_shutdown_msg_rcvd) {
470 - error("MQTT App Layer `disconnect` message sent successfully");
472 + info("MQTT App Layer `disconnect` message sent successfully");
473 break;
474 }
475 }
476 + info("ACLK link is down");
477 + log_access("ACLK DISCONNECTED");
478 aclk_stats_upd_online(0);
479 aclk_connected = 0;
480
477 - error("Attempting to Gracefully Shutdown MQTT/WSS connection");
481 + info("Attempting to gracefully shutdown the MQTT/WSS connection");
482 mqtt_wss_disconnect(client, 1000);
483 }
484
@@ -720,12 +724,13 @@ static int aclk_attempt_to_connect(mqtt_wss_client client)
724 json_object_put(lwt);
725
726 if (!ret) {
723 - info("MQTTWSS connection succeeded");
727 + info("ACLK connection successfully established");
728 + log_access("ACLK CONNECTED");
729 mqtt_connected_actions(client);
730 return 0;
731 }
732
728 - error("Connect failed\n");
733 + error_report("Connect failed");
734 }
735
736 return 1;
@@ -821,6 +826,7 @@ void *aclk_main(void *ptr)
826 if (handle_connection(mqttwss_client)) {
827 aclk_stats_upd_online(0);
828 aclk_connected = 0;
829 + log_access("ACLK DISCONNECTED");
830 }
831 } while (!netdata_exit);
832
aclk/aclk_query.c
+5 -1
@@ -81,6 +81,7 @@ static int http_api_v2(struct aclk_query_thread *query_thr, aclk_query_t query)
81 int retval = 0;
82 usec_t t;
83 BUFFER *local_buffer = NULL;
84 + BUFFER *log_buffer = buffer_create(NETDATA_WEB_REQUEST_URL_SIZE);
85 RRDHOST *query_host = localhost;
86
87 #ifdef NETDATA_WITH_ZLIB
@@ -116,6 +117,8 @@ static int http_api_v2(struct aclk_query_thread *query_thr, aclk_query_t query)
117 }
118 }
119
120 + buffer_strcat(log_buffer, query->data.http_api_v2.query);
121 +
122 char *mysep = strchr(query->data.http_api_v2.query, '?');
123 if (mysep) {
124 url_decode_r(w->decoded_query_string, mysep, NETDATA_WEB_REQUEST_URL_SIZE + 1);
@@ -226,7 +229,7 @@ static int http_api_v2(struct aclk_query_thread *query_thr, aclk_query_t query)
229 , dt_usec(&tv, &w->tv_ready) / 1000.0
230 , dt_usec(&tv, &w->tv_in) / 1000.0
231 , w->response.code
229 - , strip_control_characters(query->data.http_api_v2.query)
232 + , strip_control_characters((char *)buffer_tostring(log_buffer))
233 );
234
235 cleanup:
@@ -240,6 +243,7 @@ cleanup:
243 buffer_free(w->response.header_output);
244 freez(w);
245 buffer_free(local_buffer);
246 + buffer_free(log_buffer);
247 return retval;
248 }
249
database/sqlite/sqlite_aclk_alert.c
+31 -9
@@ -125,7 +125,7 @@ void aclk_push_alert_event(struct aclk_database_worker_config *wc, struct aclk_d
125 int rc;
126
127 if (unlikely(!wc->alert_updates)) {
128 - debug(D_ACLK_SYNC,"Ignoring alert push event, updates have been turned off for node %s", wc->node_id);
128 + log_access("AC [%s (%s)]: Ignoring alert push event, updates have been turned off for this node.", wc->node_id, wc->host ? wc->host->hostname : "N/A");
129 return;
130 }
131
@@ -177,6 +177,8 @@ void aclk_push_alert_event(struct aclk_database_worker_config *wc, struct aclk_d
177 char uuid_str[GUID_LEN + 1];
178 uint64_t first_sequence_id = 0;
179 uint64_t last_sequence_id = 0;
180 + static __thread uint64_t log_first_sequence_id = 0;
181 + static __thread uint64_t log_last_sequence_id = 0;
182
183 while (sqlite3_step(res) == SQLITE_ROW) {
184 struct alarm_log_entry alarm_log;
@@ -244,7 +246,12 @@ void aclk_push_alert_event(struct aclk_database_worker_config *wc, struct aclk_d
246
247 if (first_sequence_id == 0)
248 first_sequence_id = (uint64_t) sqlite3_column_int64(res, 0);
249 +
250 + if (log_first_sequence_id == 0)
251 + log_first_sequence_id = (uint64_t) sqlite3_column_int64(res, 0);
252 +
253 last_sequence_id = (uint64_t) sqlite3_column_int64(res, 0);
254 + log_last_sequence_id = (uint64_t) sqlite3_column_int64(res, 0);
255
256 destroy_alarm_log_entry(&alarm_log);
257 freez(edit_command);
@@ -256,6 +263,11 @@ void aclk_push_alert_event(struct aclk_database_worker_config *wc, struct aclk_d
263 "WHERE date_submitted IS NULL AND sequence_id BETWEEN %" PRIu64 " AND %" PRIu64 ";",
264 wc->uuid_str, first_sequence_id, last_sequence_id);
265 db_execute(buffer_tostring(sql));
266 + } else {
267 + if (log_first_sequence_id)
268 + log_access("OG [%s (%s)]: Sent alert events, first sequence_id %"PRIu64", last sequence_id %"PRIu64, wc->node_id, wc->host ? wc->host->hostname : "N/A", log_first_sequence_id, log_last_sequence_id);
269 + log_first_sequence_id = 0;
270 + log_last_sequence_id = 0;
271 }
272
273 rc = sqlite3_finalize(res);
@@ -274,6 +286,8 @@ void aclk_send_alarm_health_log(char *node_id)
286 if (unlikely(!node_id))
287 return;
288
289 + log_access("IN [%s (N/A)]: Request to send alarm health log.", node_id);
290 +
291 struct aclk_database_worker_config *wc = NULL;
292 struct aclk_database_cmd cmd;
293 memset(&cmd, 0, sizeof(cmd));
@@ -358,6 +372,7 @@ void aclk_push_alarm_health_log(struct aclk_database_worker_config *wc, struct a
372 wc->alert_sequence_id = last_sequence;
373
374 aclk_send_alarm_log_health(&alarm_log);
375 + log_access("OG [%s (%s)]: Alarm health log sent, first sequence id %ld, last sequence id %ld.", wc->node_id, wc->host ? wc->host->hostname : "N/A", first_sequence, last_sequence);
376
377 rc = sqlite3_finalize(res);
378 if (unlikely(rc != SQLITE_OK))
@@ -381,6 +396,8 @@ void aclk_send_alarm_configuration(char *config_hash)
396 return;
397 }
398
399 + log_access("IN [%s (%s)]: Request to send alert config %s.", wc->node_id, wc->host ? wc->host->hostname : "N/A", config_hash);
400 +
401 struct aclk_database_cmd cmd;
402 memset(&cmd, 0, sizeof(cmd));
403 cmd.opcode = ACLK_DATABASE_PUSH_ALERT_CONFIG;
@@ -489,7 +506,7 @@ int aclk_push_alert_config_event(struct aclk_database_worker_config *wc, struct
506 }
507
508 if (likely(p_alarm_config.cfg_hash)) {
492 - debug(D_ACLK_SYNC, "Sending alert config for %s", config_hash);
509 + log_access("OG [%s (%s)]: Sent alert config %s.", wc->node_id, wc->host ? wc->host->hostname : "N/A", config_hash);
510 aclk_send_provide_alarm_cfg(&p_alarm_config);
511 freez((char *) cmd.data_param);
512 freez(p_alarm_config.cfg_hash);
@@ -516,6 +533,8 @@ void aclk_start_alert_streaming(char *node_id, uint64_t batch_id, uint64_t start
533 if (unlikely(!node_id))
534 return;
535
536 + log_access("IN [%s (N/A)]: Start streaming alerts with batch_id %"PRIu64" and start_seq_id %"PRIu64".", node_id, batch_id, start_seq_id);
537 +
538 uuid_t node_uuid;
539 if (uuid_parse(node_id, node_uuid))
540 return;
@@ -528,12 +547,12 @@ void aclk_start_alert_streaming(char *node_id, uint64_t batch_id, uint64_t start
547 rrd_unlock();
548
549 if (unlikely(!host->health_enabled)) {
531 - info("Ignoring request to stream alert state changes, health is disabled for %s", host->machine_guid);
550 + log_access("AC [%s (%s)]: Ignoring request to stream alert state changes, health is disabled.", node_id, wc->host ? wc->host->hostname : "N/A");
551 return;
552 }
553
554 if (likely(wc)) {
536 - info("START streaming alerts for %s enabled with batch_id %"PRIu64" and start_seq_id %"PRIu64, node_id, batch_id, start_seq_id);
555 + log_access("AC [%s (%s)]: Start streaming alerts enabled with batch_id %"PRIu64" and start_seq_id %"PRIu64".", node_id, wc->host ? wc->host->hostname : "N/A", batch_id, start_seq_id);
556 __sync_synchronize();
557 wc->alerts_batch_id = batch_id;
558 wc->alerts_start_seq_id = start_seq_id;
@@ -541,7 +560,7 @@ void aclk_start_alert_streaming(char *node_id, uint64_t batch_id, uint64_t start
560 __sync_synchronize();
561 }
562 else
544 - error("ACLK synchronization thread is not active for host %s", host->hostname);
563 + log_access("AC [%s (%s)]: ACLK synchronization thread is not active.", node_id, wc->host ? wc->host->hostname : "N/A");
564
565 #else
566 UNUSED(node_id);
@@ -609,9 +628,10 @@ void aclk_process_send_alarm_snapshot(char *node_id, char *claim_id, uint64_t sn
628 rrd_unlock();
629
630 if (likely(wc)) {
612 - info(
613 - "Send alerts snapshot requested for %s with snapshot_id %" PRIu64 " and ack sequence_id %" PRIu64,
614 - node_id,
631 + log_access(
632 + "IN [%s (%s)]: Request to send alerts snapshot, snapshot_id %" PRIu64 " and ack_sequence_id %" PRIu64,
633 + wc->node_id,
634 + wc->host ? wc->host->hostname : "N/A",
635 snapshot_id,
636 sequence_id);
637 __sync_synchronize();
@@ -725,7 +745,7 @@ void aclk_push_alert_snapshot_event(struct aclk_database_worker_config *wc, stru
745 UNUSED(cmd);
746 // we perhaps we don't need this for snapshots
747 if (unlikely(!wc->alert_updates)) {
728 - debug(D_ACLK_SYNC, "Ignoring alert push snapshot event, updates have been turned off for node %s", wc->node_id);
748 + log_access("AC [%s (%s)]: Ignoring alert snapshot event, updates have been turned off for this node.", wc->node_id, wc->host ? wc->host->hostname : "N/A");
749 return;
750 }
751
@@ -733,6 +753,8 @@ void aclk_push_alert_snapshot_event(struct aclk_database_worker_config *wc, stru
753 if (unlikely(!claim_id))
754 return;
755
756 + log_access("OG [%s (%s)]: Sending alerts snapshot, snapshot_id %" PRIu64, wc->node_id, wc->host ? wc->host->hostname : "N/A", wc->alerts_snapshot_id);
757 +
758 aclk_mark_alert_cloud_ack(wc->uuid_str, wc->alerts_ack_sequence_id);
759
760 RRDHOST *host = wc->host;
database/sqlite/sqlite_aclk_chart.c
+21 -17
@@ -302,7 +302,7 @@ void aclk_send_chart_event(struct aclk_database_worker_config *wc, struct aclk_d
302
303 wc->chart_pending = 0;
304 if (unlikely(!wc->chart_updates)) {
305 - debug(D_ACLK_SYNC,"Ignoring chart push event, updates have been turned off for node %s", wc->node_id);
305 + log_access("AC [%s (%s)]: Ignoring chart push event, updates have been turned off for this node.", wc->node_id, wc->host ? wc->host->hostname : "N/A");
306 return;
307 }
308
@@ -406,6 +406,7 @@ void aclk_send_chart_event(struct aclk_database_worker_config *wc, struct aclk_d
406 db_unlock();
407
408 aclk_chart_inst_and_dim_update(payload_list, payload_list_size, is_dim, position_list, wc->batch_id);
409 + log_access("OG [%s (%s)]: Sending charts and dimensions update, batch_id %ld, first sequence %ld, last sequence %ld", wc->node_id, wc->host ? wc->host->hostname : "N/A", wc->batch_id, first_sequence, last_sequence);
410 wc->chart_sequence_id = last_sequence;
411 wc->chart_timestamp = last_timestamp;
412 }
@@ -422,7 +423,7 @@ void aclk_send_chart_event(struct aclk_database_worker_config *wc, struct aclk_d
423 else {
424 wc->chart_payload_count = sql_get_pending_count(wc);
425 if (!wc->chart_payload_count)
425 - info("%s: sync of charts and dimensions done in %ld seconds", wc->host->hostname, now_realtime_sec() - wc->startup_time);
426 + log_access("AC [%s (%s)]: Sync of charts and dimensions done in %ld seconds.", wc->node_id, wc->host ? wc->host->hostname : "N/A", now_realtime_sec() - wc->startup_time);
427 }
428
429 for (int i = 0; i <= limit; ++i)
@@ -495,12 +496,12 @@ int aclk_send_chart_config(struct aclk_database_worker_config *wc, struct aclk_d
496 }
497
498 if (likely(chart_config.config_hash)) {
498 - debug(D_ACLK_SYNC, "Sending chart config for %s", hash_id);
499 + log_access("OG [%s (%s)]: Sending chart config for %s.", wc->node_id, wc->host ? wc->host->hostname : "N/A", hash_id);
500 aclk_chart_config_updated(&chart_config, 1);
501 destroy_chart_config_updated(&chart_config);
502 }
503 else
503 - info("Chart config for %s not found", hash_id);
504 + log_access("AC [%s (%s)]: Chart config for %s not found.", wc->node_id, wc->host ? wc->host->hostname : "N/A", hash_id);
505
506 bind_fail:
507 rc = sqlite3_finalize(res);
@@ -518,6 +519,8 @@ void aclk_receive_chart_ack(struct aclk_database_worker_config *wc, struct aclk_
519 int rc;
520 sqlite3_stmt *res = NULL;
521
522 + log_access("IN [%s (%s)]: Received ack chart sequence id %ld.", wc->node_id, wc->host ? wc->host->hostname : "N/A", cmd.param1);
523 +
524 BUFFER *sql = buffer_create(1024);
525
526 buffer_sprintf(sql, "UPDATE aclk_chart_%s SET date_updated=strftime('%%s','now') WHERE sequence_id <= @sequence_id "
@@ -555,7 +558,7 @@ void aclk_receive_chart_reset(struct aclk_database_worker_config *wc, struct acl
558 if (cmd.param1 == 1) {
559 db_lock();
560 buffer_flush(sql);
558 - info("Received full resync for %s", wc->uuid_str);
561 + log_access("IN [%s (%s)]: Received chart full resync.", wc->node_id, wc->host ? wc->host->hostname : "N/A");
562 buffer_sprintf(sql, "DELETE FROM aclk_chart_payload_%s; DELETE FROM aclk_chart_%s; " \
563 "DELETE FROM aclk_chart_latest_%s;", wc->uuid_str, wc->uuid_str, wc->uuid_str);
564
@@ -583,7 +586,7 @@ void aclk_receive_chart_reset(struct aclk_database_worker_config *wc, struct acl
586 rrdhost_unlock(host);
587 }
588 else {
586 - info("Restarting chart sync for %s from sequence=%"PRIu64, wc->uuid_str, cmd.param1);
589 + log_access("AC [%s (%s)]: Restarting chart sync from sequence %"PRIu64, wc->node_id, wc->host ? wc->host->hostname : "N/A", cmd.param1);
590 wc->chart_payload_count = sql_get_pending_count(wc);
591 sql_get_last_chart_sequence(wc);
592 }
@@ -608,7 +611,7 @@ void aclk_get_chart_config(char **hash_id)
611 cmd.opcode = ACLK_DATABASE_PUSH_CHART_CONFIG;
612 for (int i = 0; hash_id[i]; ++i) {
613 // TODO: Verify that we have a valid hash_id
611 - debug(D_ACLK_SYNC,"Request %d for chart config with hash [%s] received", i, hash_id[i]);
614 + log_access("IN [%s (%s)]: Request %d for chart config with hash %s received.", wc->node_id, wc->host ? wc->host->hostname : "N/A", i, hash_id[i]);
615 cmd.data_param = (void *)strdupz(hash_id[i]);
616 aclk_database_enq_cmd(wc, &cmd);
617 }
@@ -638,7 +641,7 @@ static void aclk_submit_param_command(char *node_id, enum aclk_database_opcode a
641 aclk_database_enq_cmd(wc, &cmd);
642 else {
643 if (aclk_worker_enq_cmd(node_id, &cmd))
641 - error_report("ACLK synchronization thread is not active for node id %s", node_id);
644 + log_access("AC [%s (%s)]: ACLK synchronization thread is not active.", node_id, host ? host->hostname : "N/A");
645 }
646 return;
647 }
@@ -648,7 +651,7 @@ void aclk_ack_chart_sequence_id(char *node_id, uint64_t last_sequence_id)
651 if (unlikely(!node_id))
652 return;
653
651 - debug(D_ACLK_SYNC, "NODE %s reports last sequence id received %"PRIu64, node_id, last_sequence_id);
654 + log_access("AC [%s (N/A)]: Node reports last sequence id received %"PRIu64, node_id, last_sequence_id);
655 aclk_submit_param_command(node_id, ACLK_DATABASE_CHART_ACK, last_sequence_id);
656 return;
657 }
@@ -660,8 +663,9 @@ void aclk_start_streaming(char *node_id, uint64_t sequence_id, time_t created_at
663 if (unlikely(!node_id))
664 return;
665
663 - debug(D_ACLK_SYNC,"START streaming charts for node %s from sequence %"PRIu64" t=%ld, batch=%"PRIu64, node_id,
666 + log_access("IN [%s (N/A)]: Start streaming charts from sequence %"PRIu64" t=%ld, batch=%"PRIu64, node_id,
667 sequence_id, created_at, batch_id);
668 +
669 uuid_t node_uuid;
670 if (uuid_parse(node_id, node_uuid))
671 return;
@@ -681,9 +685,9 @@ void aclk_start_streaming(char *node_id, uint64_t sequence_id, time_t created_at
685 __sync_synchronize();
686 wc->batch_created = now_realtime_sec();
687 if (sequence_id > wc->chart_sequence_id || wc->chart_reset_count > 10) {
684 - info("Requesting full resync from the cloud for node id %s "
688 + log_access("AC [%s (%s)]: Requesting full resync from the cloud "
689 "(reset=%d, remote_seq=%"PRIu64", local_seq=%"PRIu64")"
686 - , wc->node_id, wc->chart_reset_count, sequence_id, wc->chart_sequence_id);
690 + , wc->node_id, wc->host ? wc->host->hostname : "N/A", wc->chart_reset_count, sequence_id, wc->chart_sequence_id);
691 chart_reset_t chart_reset;
692 chart_reset.claim_id = is_agent_claimed();
693 if (chart_reset.claim_id) {
@@ -699,8 +703,8 @@ void aclk_start_streaming(char *node_id, uint64_t sequence_id, time_t created_at
703 memset(&cmd, 0, sizeof(cmd));
704 // TODO: handle timestamp
705 if (sequence_id < wc->chart_sequence_id || !sequence_id) { // || created_at != wc->chart_timestamp) {
702 - info("RESET streaming charts for %s from sequence %"PRIu64 \
703 - " t=%ld (reset count=%d)", wc->node_id, wc->chart_sequence_id,
706 + log_access("AC [%s (%s)]: Reset streaming charts from sequence %"PRIu64 \
707 + " t=%ld (reset count=%d)", wc->node_id, wc->host ? wc->host->hostname : "N/A", wc->chart_sequence_id,
708 wc->chart_timestamp, wc->chart_reset_count);
709 cmd.opcode = ACLK_DATABASE_RESET_CHART;
710 cmd.param1 = sequence_id + 1;
@@ -708,8 +712,8 @@ void aclk_start_streaming(char *node_id, uint64_t sequence_id, time_t created_at
712 aclk_database_enq_cmd(wc, &cmd);
713 }
714 else {
711 - info("START streaming charts for %s enabled -- last streamed sequence %"PRIu64 \
712 - " t=%ld (reset count=%d)", wc->node_id, wc->chart_sequence_id,
715 + log_access("AC [%s (%s)]: Start streaming charts enabled -- last streamed sequence %"PRIu64 \
716 + " t=%ld (reset count=%d)", wc->node_id, wc->host ? wc->host->hostname : "N/A", wc->chart_sequence_id,
717 wc->chart_timestamp, wc->chart_reset_count);
718 wc->chart_reset_count = 0;
719 wc->chart_updates = 1;
@@ -717,7 +721,7 @@ void aclk_start_streaming(char *node_id, uint64_t sequence_id, time_t created_at
721 }
722 }
723 else
720 - error("ACLK synchronization thread is not active for host %s", host->hostname);
724 + log_access("AC [%s (%s)]: ACLK synchronization thread is not active.", wc->node_id, wc->host ? wc->host->hostname : "N/A");
725 return;
726 }
727 host = host->next;
database/sqlite/sqlite_aclk_node.c
+1
@@ -52,6 +52,7 @@ void sql_build_node_info(struct aclk_database_worker_config *wc, struct aclk_dat
52 node_info.data.host_labels_head = labels->head;
53
54 aclk_update_node_info(&node_info);
55 + log_access("OG [%s (%s)]: Sending node info for guid [%s] (%s).", wc->node_id, wc->host ? wc->host->hostname : "N/A", wc->host_guid, wc->host == localhost ? "parent" : "child");
56
57 netdata_rwlock_unlock(&labels->labels_rwlock);
58 rrd_unlock();