static void *statsd_network_thread (void *args) /* {{{ */ { statsd_config_t *conf = args; fds_poll_t fds; int status; size_t i; memset(&fds, 0, sizeof(fds_poll_t)); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); status = statsd_network_init (conf, &fds); if (status != 0) { ERROR ("statsd plugin: Unable to open listening sockets."); pthread_exit ((void *) 0); } pthread_cleanup_push(statsd_network_release, &fds); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); while (1) { status = poll (fds.fds, (nfds_t) fds.fds_num, /* timeout = */ -1); if (status < 0) { char errbuf[1024] = {0}; if (EAGAIN == errno) continue; if (EINTR == errno) { DEBUG("statsd plugin: poll(2) has been interrupted"); break; } ERROR ("statsd plugin: poll(2) failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); break; } DEBUG("statsd plugin: ohh some moving in the sockets"); for (i = 0; i < fds.fds_num; i++) { if ((fds.fds[i].revents & (POLLIN | POLLPRI)) == 0) continue; statsd_network_read(conf, fds.fds[i].fd); fds.fds[i].revents = 0; } pthread_testcancel(); } /* wait for pthread_cancel */ pthread_cleanup_pop(1); return ((void *) 0); } /* }}} void *statsd_network_thread */
static void *statsd_network_thread (void *args) /* {{{ */ { struct pollfd *fds = NULL; size_t fds_num = 0; int status; size_t i; status = statsd_network_init (&fds, &fds_num); if (status != 0) { ERROR ("statsd plugin: Unable to open listening sockets."); pthread_exit ((void *) 0); } while (!network_thread_shutdown) { status = poll (fds, (nfds_t) fds_num, /* timeout = */ -1); if (status < 0) { char errbuf[1024]; if ((errno == EINTR) || (errno == EAGAIN)) continue; ERROR ("statsd plugin: poll(2) failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); break; } for (i = 0; i < fds_num; i++) { if ((fds[i].revents & (POLLIN | POLLPRI)) == 0) continue; statsd_network_read (fds[i].fd); fds[i].revents = 0; } } /* while (!network_thread_shutdown) */ /* Clean up */ for (i = 0; i < fds_num; i++) close (fds[i].fd); sfree (fds); return ((void *) 0); } /* }}} void *statsd_network_thread */
static int statsd_network_init(struct pollfd **ret_fds, /* {{{ */ size_t *ret_fds_num) { struct pollfd *fds = NULL; size_t fds_num = 0; struct addrinfo *ai_list; int status; char const *node = (conf_node != NULL) ? conf_node : STATSD_DEFAULT_NODE; char const *service = (conf_service != NULL) ? conf_service : STATSD_DEFAULT_SERVICE; struct addrinfo ai_hints = {.ai_family = AF_UNSPEC, .ai_flags = AI_PASSIVE | AI_ADDRCONFIG, .ai_socktype = SOCK_DGRAM}; status = getaddrinfo(node, service, &ai_hints, &ai_list); if (status != 0) { ERROR("statsd plugin: getaddrinfo (\"%s\", \"%s\") failed: %s", node, service, gai_strerror(status)); return status; } for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) { int fd; struct pollfd *tmp; char dbg_node[NI_MAXHOST]; char dbg_service[NI_MAXSERV]; fd = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol); if (fd < 0) { ERROR("statsd plugin: socket(2) failed: %s", STRERRNO); continue; } getnameinfo(ai_ptr->ai_addr, ai_ptr->ai_addrlen, dbg_node, sizeof(dbg_node), dbg_service, sizeof(dbg_service), NI_DGRAM | NI_NUMERICHOST | NI_NUMERICSERV); DEBUG("statsd plugin: Trying to bind to [%s]:%s ...", dbg_node, dbg_service); status = bind(fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen); if (status != 0) { ERROR("statsd plugin: bind(2) failed: %s", STRERRNO); close(fd); continue; } tmp = realloc(fds, sizeof(*fds) * (fds_num + 1)); if (tmp == NULL) { ERROR("statsd plugin: realloc failed."); close(fd); continue; } fds = tmp; tmp = fds + fds_num; fds_num++; memset(tmp, 0, sizeof(*tmp)); tmp->fd = fd; tmp->events = POLLIN | POLLPRI; } freeaddrinfo(ai_list); if (fds_num == 0) { ERROR("statsd plugin: Unable to create listening socket for [%s]:%s.", (node != NULL) ? node : "::", service); return ENOENT; } *ret_fds = fds; *ret_fds_num = fds_num; return 0; } /* }}} int statsd_network_init */ static void *statsd_network_thread(void *args) /* {{{ */ { struct pollfd *fds = NULL; size_t fds_num = 0; int status; status = statsd_network_init(&fds, &fds_num); if (status != 0) { ERROR("statsd plugin: Unable to open listening sockets."); pthread_exit((void *)0); } while (!network_thread_shutdown) { status = poll(fds, (nfds_t)fds_num, /* timeout = */ -1); if (status < 0) { if ((errno == EINTR) || (errno == EAGAIN)) continue; ERROR("statsd plugin: poll(2) failed: %s", STRERRNO); break; } for (size_t i = 0; i < fds_num; i++) { if ((fds[i].revents & (POLLIN | POLLPRI)) == 0) continue; statsd_network_read(fds[i].fd); fds[i].revents = 0; } } /* while (!network_thread_shutdown) */ /* Clean up */ for (size_t i = 0; i < fds_num; i++) close(fds[i].fd); sfree(fds); return (void *)0; } /* }}} void *statsd_network_thread */ static int statsd_config_timer_percentile(oconfig_item_t *ci) /* {{{ */ { double percent = NAN; double *tmp; int status; status = cf_util_get_double(ci, &percent); if (status != 0) return status; if ((percent <= 0.0) || (percent >= 100)) { ERROR("statsd plugin: The value for \"%s\" must be between 0 and 100, " "exclusively.", ci->key); return ERANGE; } tmp = realloc(conf_timer_percentile, sizeof(*conf_timer_percentile) * (conf_timer_percentile_num + 1)); if (tmp == NULL) { ERROR("statsd plugin: realloc failed."); return ENOMEM; } conf_timer_percentile = tmp; conf_timer_percentile[conf_timer_percentile_num] = percent; conf_timer_percentile_num++; return 0; } /* }}} int statsd_config_timer_percentile */