int heartbeat_container_init_context(heartbeat_container* hc, uint64_t window_size, int log_fd, heartbeat_window_complete* hwc_callback) { if (heartbeat_container_init(hc, window_size)) { return -1; } heartbeat_init(&hc->hb, window_size, hc->window_buffer, log_fd, hwc_callback); return 0; }
static void load_xcode(void) { FILE *fp; int xcode_version; int filemode; initialize_colorize(); fprintf(stderr, "LOADING: %s\n", mudconf.hcode_db); fp = my_open_file(mudconf.hcode_db, "rb", &filemode); if (!fp) { fprintf(stderr, "ERROR: %s not found.\n", mudconf.hcode_db); return; } fread(&xcode_version, sizeof(xcode_version), 1, fp); if (xcode_version != XCODE_MAGIC) { fprintf(stderr, "LOADING: %s (skipped xcodetree - version difference: 0x%08X vs 0x%08X)\n", mudconf.hcode_db, xcode_version, XCODE_MAGIC); return; } if (!load_btdb()) { /* TODO: We could be more graceful about this... */ exit(EXIT_FAILURE); } rb_walk(xcode_tree, WALK_INORDER, load_update1, fp); rb_walk(xcode_tree, WALK_INORDER, load_update2, NULL); rb_walk(xcode_tree, WALK_INORDER, load_update3, NULL); rb_walk(xcode_tree, WALK_INORDER, load_update4, NULL); /* Read in autopilot data */ rb_walk(xcode_tree, WALK_INORDER, load_autopilot_data, NULL); if (!feof(fp)) loadrepairs(fp); my_close_file(fp, &filemode); fprintf(stderr, "LOADING: %s (done)\n", mudconf.hcode_db); #ifdef BT_ADVANCED_ECON load_econdb(); #endif heartbeat_init(); }
void gears_init(void) { int i; for(i = 0; i < 7; i++) motorPD[i] = 15; /* Set Mystro MOTOR to outputs */ DDRD |= 0xfc; //Port D pins 2 - 7 /* Set Mystro DIGITAL to inputs */ DDRB &= 0xc0; //Port B pins 0 - 5 PORTB |= 0x3f; //Enable pull-ups on pins 0 - 5 /* Initialize Mystro ANALOG inputs */ adc_init(ADC_AVCC, ADC_8BIT); /* Set interval for 10us */ heartbeat_init(100); /* Turn on universal interrupts */ sei(); }
int main(int argc, char *argv[]) { mmatic *mm = mmatic_create(); mmatic *mmtmp = mmatic_create(); struct mg *mg; int i; /* * initialize and parse config */ mg = mmatic_zalloc(mm, sizeof(struct mg)); mg->mm = mm; mg->mmtmp = mmtmp; apply_defaults(mg); /* get my id number from hostname */ fetch_myid(mg); /* parse command line options */ if (parse_argv(mg, argc, argv)) return 1; /* parse configuration file options */ if (mg->options.conf_file) { if (parse_config(mg)) return 4; } /* * config syntax looks OK, see if it is feasible */ /* initialize random number generator */ srand48(mg->options.myid); /* init libevent */ mg->evb = event_init(); event_set_log_callback(libevent_log); /* init stats structures so mgstats_aggregator_add() used somewhere below works */ mgstats_init(mg); /* attach to raw interfaces */ if (mgi_init(mg, handle_packet) <= 0) { dbg(0, "no available interfaces found\n"); return 2; } /* parse traffic file */ if (parse_traffic(mg)) return 3; /* * all OK, prepare to start */ /* synchronize time reference point on all nodes */ mgc_sync(mg); /* schedule stats writing */ mgstats_start(mg); /* attach global stats */ _stats_init(mg); /* schedule heartbeat and disk sync signals */ heartbeat_init(mg); sync_init(mg); /* schedule the real work of this node: line generators */ for (i = 1; i < TRAFFIC_LINE_MAX; i++) { if (!(mg->lines[i] && mg->lines[i]->my)) continue; /* this will schedule first execution */ mgs_sleep(mg->lines[i], NULL); mg->running++; } /* suppose last frame was received now */ gettimeofday(&mg->last, NULL); /* * start! */ dbg(0, "Starting\n"); event_base_dispatch(mg->evb); /*******************************/ /* * cleanup after end of libevent loop */ event_base_free(mg->evb); mmatic_free(mg->mm); mmatic_free(mg->mmtmp); fflush(NULL); sync(); return 0; }
void *proc_diskspace_main(void *ptr) { struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; info("DISKSPACE thread created with task id %d", gettid()); if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) error("DISKSPACE: Cannot set pthread cancel type to DEFERRED."); if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("DISKSPACE: Cannot set pthread cancel state to ENABLE."); int vdo_cpu_netdata = config_get_boolean("plugin:proc", "netdata server resources", 1); int update_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "update every", localhost->rrd_update_every); if(update_every < localhost->rrd_update_every) update_every = localhost->rrd_update_every; check_for_new_mountpoints_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "check for new mount points every", check_for_new_mountpoints_every); if(check_for_new_mountpoints_every < update_every) check_for_new_mountpoints_every = update_every; struct rusage thread; usec_t duration = 0; usec_t step = update_every * USEC_PER_SEC; heartbeat_t hb; heartbeat_init(&hb); for(;;) { duration = heartbeat_dt_usec(&hb); /* usec_t hb_dt = */ heartbeat_next(&hb, step); if(unlikely(netdata_exit)) break; // -------------------------------------------------------------------------- // this is smart enough not to reload it every time mountinfo_reload(0); // -------------------------------------------------------------------------- // disk space metrics struct mountinfo *mi; for(mi = disk_mountinfo_root; mi; mi = mi->next) { if(unlikely(mi->flags & (MOUNTINFO_IS_DUMMY | MOUNTINFO_IS_BIND))) continue; do_disk_space_stats(mi, update_every); if(unlikely(netdata_exit)) break; } if(unlikely(netdata_exit)) break; dictionary_get_all(dict_mountpoints, mount_point_cleanup, NULL); if(vdo_cpu_netdata) { static RRDSET *stcpu_thread = NULL, *st_duration = NULL; static RRDDIM *rd_user = NULL, *rd_system = NULL, *rd_duration = NULL; // ---------------------------------------------------------------- getrusage(RUSAGE_THREAD, &thread); if(!stcpu_thread) { stcpu_thread = rrdset_find_localhost("netdata.plugin_diskspace"); if(!stcpu_thread) stcpu_thread = rrdset_create_localhost( "netdata" , "plugin_diskspace" , NULL , "diskspace" , NULL , "NetData Disk Space Plugin CPU usage" , "milliseconds/s" , 132020 , update_every , RRDSET_TYPE_STACKED ); rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stcpu_thread); rrddim_set_by_pointer(stcpu_thread, rd_user, thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec); rrddim_set_by_pointer(stcpu_thread, rd_system, thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec); rrdset_done(stcpu_thread); // ---------------------------------------------------------------- if(!st_duration) { st_duration = rrdset_find_localhost("netdata.plugin_diskspace_dt"); if(!st_duration) st_duration = rrdset_create_localhost( "netdata" , "plugin_diskspace_dt" , NULL , "diskspace" , NULL , "NetData Disk Space Plugin Duration" , "milliseconds/run" , 132021 , update_every , RRDSET_TYPE_AREA ); rd_duration = rrddim_add(st_duration, "duration", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st_duration); rrddim_set_by_pointer(st_duration, rd_duration, duration); rrdset_done(st_duration); // ---------------------------------------------------------------- if(unlikely(netdata_exit)) break; } } info("DISKSPACE thread exiting"); static_thread->enabled = 0; pthread_exit(NULL); return NULL; }
void *proc_diskspace_main(void *ptr) { netdata_thread_cleanup_push(diskspace_main_cleanup, ptr); int vdo_cpu_netdata = config_get_boolean("plugin:proc", "netdata server resources", 1); cleanup_mount_points = config_get_boolean(CONFIG_SECTION_DISKSPACE, "remove charts of unmounted disks" , cleanup_mount_points); int update_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "update every", localhost->rrd_update_every); if(update_every < localhost->rrd_update_every) update_every = localhost->rrd_update_every; check_for_new_mountpoints_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "check for new mount points every", check_for_new_mountpoints_every); if(check_for_new_mountpoints_every < update_every) check_for_new_mountpoints_every = update_every; struct rusage thread; usec_t duration = 0; usec_t step = update_every * USEC_PER_SEC; heartbeat_t hb; heartbeat_init(&hb); while(!netdata_exit) { duration = heartbeat_dt_usec(&hb); /* usec_t hb_dt = */ heartbeat_next(&hb, step); if(unlikely(netdata_exit)) break; // -------------------------------------------------------------------------- // this is smart enough not to reload it every time mountinfo_reload(0); // -------------------------------------------------------------------------- // disk space metrics struct mountinfo *mi; for(mi = disk_mountinfo_root; mi; mi = mi->next) { if(unlikely(mi->flags & (MOUNTINFO_IS_DUMMY | MOUNTINFO_IS_BIND))) continue; do_disk_space_stats(mi, update_every); if(unlikely(netdata_exit)) break; } if(unlikely(netdata_exit)) break; if(dict_mountpoints) dictionary_get_all(dict_mountpoints, mount_point_cleanup, NULL); if(vdo_cpu_netdata) { static RRDSET *stcpu_thread = NULL, *st_duration = NULL; static RRDDIM *rd_user = NULL, *rd_system = NULL, *rd_duration = NULL; // ---------------------------------------------------------------- getrusage(RUSAGE_THREAD, &thread); if(unlikely(!stcpu_thread)) { stcpu_thread = rrdset_create_localhost( "netdata" , "plugin_diskspace" , NULL , "diskspace" , NULL , "NetData Disk Space Plugin CPU usage" , "milliseconds/s" , "diskspace" , NULL , 132020 , update_every , RRDSET_TYPE_STACKED ); rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stcpu_thread); rrddim_set_by_pointer(stcpu_thread, rd_user, thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec); rrddim_set_by_pointer(stcpu_thread, rd_system, thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec); rrdset_done(stcpu_thread); // ---------------------------------------------------------------- if(unlikely(!st_duration)) { st_duration = rrdset_create_localhost( "netdata" , "plugin_diskspace_dt" , NULL , "diskspace" , NULL , "NetData Disk Space Plugin Duration" , "milliseconds/run" , "diskspace" , NULL , 132021 , update_every , RRDSET_TYPE_AREA ); rd_duration = rrddim_add(st_duration, "duration", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st_duration); rrddim_set_by_pointer(st_duration, rd_duration, duration); rrdset_done(st_duration); // ---------------------------------------------------------------- if(unlikely(netdata_exit)) break; } } netdata_thread_cleanup_pop(1); return NULL; }
void *backends_main(void *ptr) { netdata_thread_cleanup_push(backends_main_cleanup, ptr); int default_port = 0; int sock = -1; BUFFER *b = buffer_create(1), *response = buffer_create(1); int (*backend_request_formatter)(BUFFER *, const char *, RRDHOST *, const char *, RRDSET *, RRDDIM *, time_t, time_t, uint32_t) = NULL; int (*backend_response_checker)(BUFFER *) = NULL; // ------------------------------------------------------------------------ // collect configuration options struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; int enabled = config_get_boolean(CONFIG_SECTION_BACKEND, "enabled", 0); const char *source = config_get(CONFIG_SECTION_BACKEND, "data source", "average"); const char *type = config_get(CONFIG_SECTION_BACKEND, "type", "graphite"); const char *destination = config_get(CONFIG_SECTION_BACKEND, "destination", "localhost"); backend_prefix = config_get(CONFIG_SECTION_BACKEND, "prefix", "netdata"); const char *hostname = config_get(CONFIG_SECTION_BACKEND, "hostname", localhost->hostname); backend_update_every = (int)config_get_number(CONFIG_SECTION_BACKEND, "update every", backend_update_every); int buffer_on_failures = (int)config_get_number(CONFIG_SECTION_BACKEND, "buffer on failures", 10); long timeoutms = config_get_number(CONFIG_SECTION_BACKEND, "timeout ms", backend_update_every * 2 * 1000); backend_send_names = config_get_boolean(CONFIG_SECTION_BACKEND, "send names instead of ids", backend_send_names); charts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send charts matching", "*"), NULL, SIMPLE_PATTERN_EXACT); hosts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send hosts matching", "localhost *"), NULL, SIMPLE_PATTERN_EXACT); // ------------------------------------------------------------------------ // validate configuration options // and prepare for sending data to our backend backend_options = backend_parse_data_source(source, backend_options); if(timeoutms < 1) { error("BACKEND: invalid timeout %ld ms given. Assuming %d ms.", timeoutms, backend_update_every * 2 * 1000); timeoutms = backend_update_every * 2 * 1000; } timeout.tv_sec = (timeoutms * 1000) / 1000000; timeout.tv_usec = (timeoutms * 1000) % 1000000; if(!enabled || backend_update_every < 1) goto cleanup; // ------------------------------------------------------------------------ // select the backend type if(!strcmp(type, "graphite") || !strcmp(type, "graphite:plaintext")) { default_port = 2003; backend_response_checker = process_graphite_response; if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED) backend_request_formatter = format_dimension_collected_graphite_plaintext; else backend_request_formatter = format_dimension_stored_graphite_plaintext; } else if(!strcmp(type, "opentsdb") || !strcmp(type, "opentsdb:telnet")) { default_port = 4242; backend_response_checker = process_opentsdb_response; if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED) backend_request_formatter = format_dimension_collected_opentsdb_telnet; else backend_request_formatter = format_dimension_stored_opentsdb_telnet; } else if (!strcmp(type, "json") || !strcmp(type, "json:plaintext")) { default_port = 5448; backend_response_checker = process_json_response; if ((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED) backend_request_formatter = format_dimension_collected_json_plaintext; else backend_request_formatter = format_dimension_stored_json_plaintext; } else { error("BACKEND: Unknown backend type '%s'", type); goto cleanup; } if(backend_request_formatter == NULL || backend_response_checker == NULL) { error("BACKEND: backend is misconfigured - disabling it."); goto cleanup; } // ------------------------------------------------------------------------ // prepare the charts for monitoring the backend operation struct rusage thread; collected_number chart_buffered_metrics = 0, chart_lost_metrics = 0, chart_sent_metrics = 0, chart_buffered_bytes = 0, chart_received_bytes = 0, chart_sent_bytes = 0, chart_receptions = 0, chart_transmission_successes = 0, chart_transmission_failures = 0, chart_data_lost_events = 0, chart_lost_bytes = 0, chart_backend_reconnects = 0, chart_backend_latency = 0; RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", "backends", NULL, 130600, backend_update_every, RRDSET_TYPE_LINE); rrddim_add(chart_metrics, "buffered", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_metrics, "lost", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_metrics, "sent", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", "backends", NULL, 130610, backend_update_every, RRDSET_TYPE_AREA); rrddim_add(chart_bytes, "buffered", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_bytes, "lost", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_bytes, "sent", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_bytes, "received", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_LINE); rrddim_add(chart_ops, "write", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_ops, "discard", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_ops, "reconnect", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_ops, "failure", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_ops, "read", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); /* * this is misleading - we can only measure the time we need to send data * this time is not related to the time required for the data to travel to * the backend database and the time that server needed to process them * * issue #1432 and https://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html * RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", "backends", NULL, 130620, backend_update_every, RRDSET_TYPE_AREA); rrddim_add(chart_latency, "latency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); */ RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_STACKED); rrddim_add(chart_rusage, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); rrddim_add(chart_rusage, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); // ------------------------------------------------------------------------ // prepare the backend main loop info("BACKEND: configured ('%s' on '%s' sending '%s' data, every %d seconds, as host '%s', with prefix '%s')", type, destination, source, backend_update_every, hostname, backend_prefix); usec_t step_ut = backend_update_every * USEC_PER_SEC; time_t after = now_realtime_sec(); int failures = 0; heartbeat_t hb; heartbeat_init(&hb); while(!netdata_exit) { // ------------------------------------------------------------------------ // Wait for the next iteration point. heartbeat_next(&hb, step_ut); time_t before = now_realtime_sec(); debug(D_BACKEND, "BACKEND: preparing buffer for timeframe %lu to %lu", (unsigned long)after, (unsigned long)before); // ------------------------------------------------------------------------ // add to the buffer the data we need to send to the backend netdata_thread_disable_cancelability(); size_t count_hosts = 0; size_t count_charts_total = 0; size_t count_dims_total = 0; rrd_rdlock(); RRDHOST *host; rrdhost_foreach_read(host) { if(unlikely(!rrdhost_flag_check(host, RRDHOST_FLAG_BACKEND_SEND|RRDHOST_FLAG_BACKEND_DONT_SEND))) { char *name = (host == localhost)?"localhost":host->hostname; if (!hosts_pattern || simple_pattern_matches(hosts_pattern, name)) { rrdhost_flag_set(host, RRDHOST_FLAG_BACKEND_SEND); info("enabled backend for host '%s'", name); } else { rrdhost_flag_set(host, RRDHOST_FLAG_BACKEND_DONT_SEND); info("disabled backend for host '%s'", name); } } if(unlikely(!rrdhost_flag_check(host, RRDHOST_FLAG_BACKEND_SEND))) continue; rrdhost_rdlock(host); count_hosts++; size_t count_charts = 0; size_t count_dims = 0; size_t count_dims_skipped = 0; const char *__hostname = (host == localhost)?hostname:host->hostname; RRDSET *st; rrdset_foreach_read(st, host) { if(likely(backends_can_send_rrdset(backend_options, st))) { rrdset_rdlock(st); count_charts++; RRDDIM *rd; rrddim_foreach_read(rd, st) { if (likely(rd->last_collected_time.tv_sec >= after)) { chart_buffered_metrics += backend_request_formatter(b, backend_prefix, host, __hostname, st, rd, after, before, backend_options); count_dims++; } else { debug(D_BACKEND, "BACKEND: not sending dimension '%s' of chart '%s' from host '%s', its last data collection (%lu) is not within our timeframe (%lu to %lu)", rd->id, st->id, __hostname, (unsigned long)rd->last_collected_time.tv_sec, (unsigned long)after, (unsigned long)before); count_dims_skipped++; } } rrdset_unlock(st); } } debug(D_BACKEND, "BACKEND: sending host '%s', metrics of %zu dimensions, of %zu charts. Skipped %zu dimensions.", __hostname, count_dims, count_charts, count_dims_skipped); count_charts_total += count_charts; count_dims_total += count_dims; rrdhost_unlock(host); } rrd_unlock(); netdata_thread_enable_cancelability(); debug(D_BACKEND, "BACKEND: buffer has %zu bytes, added metrics for %zu dimensions, of %zu charts, from %zu hosts", buffer_strlen(b), count_dims_total, count_charts_total, count_hosts); // ------------------------------------------------------------------------ chart_buffered_bytes = (collected_number)buffer_strlen(b); // reset the monitoring chart counters chart_received_bytes = chart_sent_bytes = chart_sent_metrics = chart_lost_metrics = chart_transmission_successes = chart_transmission_failures = chart_data_lost_events = chart_lost_bytes = chart_backend_reconnects = chart_backend_latency = 0; if(unlikely(netdata_exit)) break; //fprintf(stderr, "\nBACKEND BEGIN:\n%s\nBACKEND END\n", buffer_tostring(b)); // FIXME //fprintf(stderr, "after = %lu, before = %lu\n", after, before); // prepare for the next iteration // to add incrementally data to buffer after = before; // ------------------------------------------------------------------------ // if we are connected, receive a response, without blocking if(likely(sock != -1)) { errno = 0; // loop through to collect all data while(sock != -1 && errno != EWOULDBLOCK) { buffer_need_bytes(response, 4096); ssize_t r = recv(sock, &response->buffer[response->len], response->size - response->len, MSG_DONTWAIT); if(likely(r > 0)) { // we received some data response->len += r; chart_received_bytes += r; chart_receptions++; } else if(r == 0) { error("BACKEND: '%s' closed the socket", destination); close(sock); sock = -1; } else { // failed to receive data if(errno != EAGAIN && errno != EWOULDBLOCK) { error("BACKEND: cannot receive data from backend '%s'.", destination); } } } // if we received data, process them if(buffer_strlen(response)) backend_response_checker(response); } // ------------------------------------------------------------------------ // if we are not connected, connect to a backend server if(unlikely(sock == -1)) { usec_t start_ut = now_monotonic_usec(); size_t reconnects = 0; sock = connect_to_one_of(destination, default_port, &timeout, &reconnects, NULL, 0); chart_backend_reconnects += reconnects; chart_backend_latency += now_monotonic_usec() - start_ut; } if(unlikely(netdata_exit)) break; // ------------------------------------------------------------------------ // if we are connected, send our buffer to the backend server if(likely(sock != -1)) { size_t len = buffer_strlen(b); usec_t start_ut = now_monotonic_usec(); int flags = 0; #ifdef MSG_NOSIGNAL flags += MSG_NOSIGNAL; #endif ssize_t written = send(sock, buffer_tostring(b), len, flags); chart_backend_latency += now_monotonic_usec() - start_ut; if(written != -1 && (size_t)written == len) { // we sent the data successfully chart_transmission_successes++; chart_sent_bytes += written; chart_sent_metrics = chart_buffered_metrics; // reset the failures count failures = 0; // empty the buffer buffer_flush(b); } else { // oops! we couldn't send (all or some of the) data error("BACKEND: failed to write data to database backend '%s'. Willing to write %zu bytes, wrote %zd bytes. Will re-connect.", destination, len, written); chart_transmission_failures++; if(written != -1) chart_sent_bytes += written; // increment the counter we check for data loss failures++; // close the socket - we will re-open it next time close(sock); sock = -1; } } else { error("BACKEND: failed to update database backend '%s'", destination); chart_transmission_failures++; // increment the counter we check for data loss failures++; } if(failures > buffer_on_failures) { // too bad! we are going to lose data chart_lost_bytes += buffer_strlen(b); error("BACKEND: reached %d backend failures. Flushing buffers to protect this host - this results in data loss on back-end server '%s'", failures, destination); buffer_flush(b); failures = 0; chart_data_lost_events++; chart_lost_metrics = chart_buffered_metrics; } if(unlikely(netdata_exit)) break; // ------------------------------------------------------------------------ // update the monitoring charts if(likely(chart_ops->counter_done)) rrdset_next(chart_ops); rrddim_set(chart_ops, "read", chart_receptions); rrddim_set(chart_ops, "write", chart_transmission_successes); rrddim_set(chart_ops, "discard", chart_data_lost_events); rrddim_set(chart_ops, "failure", chart_transmission_failures); rrddim_set(chart_ops, "reconnect", chart_backend_reconnects); rrdset_done(chart_ops); if(likely(chart_metrics->counter_done)) rrdset_next(chart_metrics); rrddim_set(chart_metrics, "buffered", chart_buffered_metrics); rrddim_set(chart_metrics, "lost", chart_lost_metrics); rrddim_set(chart_metrics, "sent", chart_sent_metrics); rrdset_done(chart_metrics); if(likely(chart_bytes->counter_done)) rrdset_next(chart_bytes); rrddim_set(chart_bytes, "buffered", chart_buffered_bytes); rrddim_set(chart_bytes, "lost", chart_lost_bytes); rrddim_set(chart_bytes, "sent", chart_sent_bytes); rrddim_set(chart_bytes, "received", chart_received_bytes); rrdset_done(chart_bytes); /* if(likely(chart_latency->counter_done)) rrdset_next(chart_latency); rrddim_set(chart_latency, "latency", chart_backend_latency); rrdset_done(chart_latency); */ getrusage(RUSAGE_THREAD, &thread); if(likely(chart_rusage->counter_done)) rrdset_next(chart_rusage); rrddim_set(chart_rusage, "user", thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec); rrddim_set(chart_rusage, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec); rrdset_done(chart_rusage); if(likely(buffer_strlen(b) == 0)) chart_buffered_metrics = 0; if(unlikely(netdata_exit)) break; } cleanup: if(sock != -1) close(sock); buffer_free(b); buffer_free(response); netdata_thread_cleanup_pop(1); return NULL; }
int main (void) { // Configure pins to the default states. config_pin_defaults(); // Initialize the watchdog module. watchdog_init(); // First, initialize registers that control servo operation. registers_init(); #if PWM_STD_ENABLED || PWM_ENH_ENABLED // Initialize the PWM module. pwm_init(); #endif #if STEP_ENABLED // Initialise the stepper motor step_init(); #endif // Initialize the ADC module. adc_init(); // Initialise the Heartbeart heartbeat_init(); // Initialize the PID algorithm module. pid_init(); #if CURVE_MOTION_ENABLED // Initialize curve motion module. motion_init(); #endif // Initialize the power module. power_init(); #if PULSE_CONTROL_ENABLED pulse_control_init(); #endif #if BACKEMF_ENABLED // Initialise the back emf module backemf_init(); #endif #if ALERT_ENABLED //initialise the alert registers alert_init(); #endif // Initialize the TWI slave module. twi_slave_init(banks_read_byte(POS_PID_BANK, REG_TWI_ADDRESS)); // Finally initialize the timer. timer_set(0); // Enable interrupts. sei(); // Trigger the adc sampling hardware adc_start(ADC_CHANNEL_POSITION); // Wait until initial position value is ready. while (!adc_position_value_is_ready()); #if CURVE_MOTION_ENABLED // Reset the curve motion with the current position of the servo. motion_reset(adc_get_position_value()); #endif // Set the initial seek position and velocity. registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, adc_get_position_value()); registers_write_word(REG_SEEK_VELOCITY_HI, REG_SEEK_VELOCITY_LO, 0); // XXX Enable PWM and writing. I do this for now to make development and // XXX tuning a bit easier. Constantly manually setting these values to // XXX turn the servo on and write the gain values get's to be a pain. #if PWM_STD_ENABLED || PWM_ENH_ENABLED pwm_enable(); #endif #if STEP_ENABLED step_enable(); #endif registers_write_enable(); // This is the main processing loop for the servo. It basically looks // for new position, power or TWI commands to be processed. for (;;) { static uint8_t emf_motor_is_coasting = 0; // Is the system heartbeat ready? if (heartbeat_is_ready()) { static int16_t last_seek_position; static int16_t wait_seek_position; static int16_t new_seek_position; // Clear the heartbeat flag heartbeat_value_clear_ready(); #if PULSE_CONTROL_ENABLED // Give pulse control a chance to update the seek position. pulse_control_update(); #endif #if CURVE_MOTION_ENABLED // Give the motion curve a chance to update the seek position and velocity. motion_next(10); #endif // General call support // Check to see if we have the wait flag enabled. If so save the new position, and write in the // old position until we get the move command if (general_call_enabled()) { //we need to wait for the go command before moving if (general_call_wait()) { // store the new position, but let the servo lock to the last seek position wait_seek_position = (int16_t) registers_read_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO); if (wait_seek_position != last_seek_position) // do we have a new position? { new_seek_position = wait_seek_position; registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, last_seek_position); } } last_seek_position = registers_read_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO); //check to make sure that we can start the move. if (general_call_start() || ( registers_read_byte(REG_GENERAL_CALL_GROUP_START) == banks_read_byte(CONFIG_BANK, REG_GENERAL_CALL_GROUP))) { // write the new position with the previously saved position registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, new_seek_position); general_call_start_wait_reset(); // reset the wait flag general_call_start_reset(); // reset the start flag } } #if BACKEMF_ENABLED // Quick and dirty check to see if pwm is active. This is done to make sure the motor doesn't // whine in the audible range while idling. uint8_t pwm_a = registers_read_byte(REG_PWM_DIRA); uint8_t pwm_b = registers_read_byte(REG_PWM_DIRB); if (pwm_a || pwm_b) { // Disable PWM backemf_coast_motor(); emf_motor_is_coasting = 1; } else { // reset the back EMF value to 0 banks_write_word(INFORMATION_BANK, REG_BACKEMF_HI, REG_BACKEMF_LO, 0); emf_motor_is_coasting = 0; } #endif #if ADC_ENABLED // Trigger the adc sampling hardware. This triggers the position and temperature sample adc_start(ADC_FIRST_CHANNEL); #endif } // Wait for the samples to complete #if TEMPERATURE_ENABLED if (adc_temperature_value_is_ready()) { // Save temperature value to registers registers_write_word(REG_TEMPERATURE_HI, REG_TEMPERATURE_LO, (uint16_t)adc_get_temperature_value()); } #endif #if CURRENT_ENABLED if (adc_power_value_is_ready()) { // Get the new power value. uint16_t power = adc_get_power_value(); // Update the power value for reporting. power_update(power); } #endif #if ADC_POSITION_ENABLED if (adc_position_value_is_ready()) { int16_t position; // Get the new position value from the ADC module. position = (int16_t) adc_get_position_value(); #else if (position_value_is_ready()) { int16_t position; // Get the position value from an external module. position = (int16_t) get_position_value(); #endif int16_t pwm; #if BACKEMF_ENABLED if (emf_motor_is_coasting == 1) { uint8_t pwm_a = registers_read_byte(REG_PWM_DIRA); uint8_t pwm_b = registers_read_byte(REG_PWM_DIRB); // Quick and dirty check to see if pwm is active if (pwm_a || pwm_b) { // Get the backemf sample. backemf_get_sample(); // Turn the motor back on backemf_restore_motor(); emf_motor_is_coasting = 0; } } #endif // Call the PID algorithm module to get a new PWM value. pwm = pid_position_to_pwm(position); #if ALERT_ENABLED // Update the alert status registers and do any throttling alert_check(); #endif // Allow any alerts to modify the PWM value. pwm = alert_pwm_throttle(pwm); #if PWM_STD_ENABLED || PWM_ENH_ENABLED // Update the servo movement as indicated by the PWM value. // Sanity checks are performed against the position value. pwm_update(position, pwm); #endif #if STEP_ENABLED // Update the stepper motor as indicated by the PWM value. // Sanity checks are performed against the position value. step_update(position, pwm); #endif } // Was a command recieved? if (twi_data_in_receive_buffer()) { // Handle any TWI command. handle_twi_command(); } // Update the bank register operations banks_update_registers(); #if MAIN_MOTION_TEST_ENABLED // This code is in place for having the servo drive itself between // two positions to aid in the servo tuning process. This code // should normally be disabled in config.h. #if CURVE_MOTION_ENABLED if (motion_time_left() == 0) { registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100); motion_append(); } #else { // Get the timer. uint16_t timer = timer_get(); // Reset the timer if greater than 800. if (timer > 800) timer_set(0); // Look for specific events. if (timer == 0) { registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, 0x0100); } else if (timer == 400) { registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, 0x0300); } } #endif #endif } return 0; }