From: Florian Forster Date: Wed, 27 Sep 2017 09:37:57 +0000 (+0200) Subject: Merge remote-tracking branch 'github/pr/2034' X-Git-Tag: collectd-5.8.0~75 X-Git-Url: https://git.octo.it/?p=collectd.git;a=commitdiff_plain;h=2ec16cfeb86629a81a6942deb9b7e3c1b1711e02;hp=4943510c1db22b5cf6342411271eb10255680211 Merge remote-tracking branch 'github/pr/2034' --- diff --git a/Makefile.am b/Makefile.am index 24c5b8c0..04636b3f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1680,7 +1680,9 @@ endif if BUILD_PLUGIN_TURBOSTAT pkglib_LTLIBRARIES += turbostat.la -turbostat_la_SOURCES = src/turbostat.c +turbostat_la_SOURCES = \ + src/turbostat.c \ + src/msr-index.h turbostat_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif diff --git a/configure.ac b/configure.ac index 8f2a9ab3..55f78d8a 100644 --- a/configure.ac +++ b/configure.ac @@ -521,32 +521,6 @@ if test "x$ac_system" = "xLinux"; then ]] ) # For the turbostat plugin - AC_CHECK_HEADERS([asm/msr-index.h], - [have_asm_msrindex_h="yes"], - [have_asm_msrindex_h="no"] - ) - - if test "x$have_asm_msrindex_h" = "xyes"; then - AC_CACHE_CHECK([whether asm/msr-index.h has MSR_PKG_C10_RESIDENCY], - [c_cv_have_usable_asm_msrindex_h], - [ - AC_COMPILE_IFELSE( - [ - AC_LANG_PROGRAM( - [[#include]], - [[ - int y = MSR_PKG_C10_RESIDENCY; - return(y); - ]] - ) - ], - [c_cv_have_usable_asm_msrindex_h="yes"], - [c_cv_have_usable_asm_msrindex_h="no"], - ) - ] - ) - fi - AC_CHECK_HEADERS([cpuid.h], [have_cpuid_h="yes"], [have_cpuid_h="no (cpuid.h not found)"] @@ -6227,7 +6201,7 @@ if test "x$ac_system" = "xLinux"; then plugin_ipvs="yes" fi - if test "x$c_cv_have_usable_asm_msrindex_h" = "xyes" && test "x$have_cpuid_h" = "xyes"; then + if test "x$have_cpuid_h" = "xyes"; then plugin_turbostat="yes" fi diff --git a/src/collectd.conf.in b/src/collectd.conf.in index a0e342ea..460e93c3 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -591,12 +591,16 @@ # # +# #Plugin "foo" # Instance "foodir" # Name "*.conf" # MTime "-5m" # Size "+10k" # Recursive true # IncludeHidden false +# #FilesSizeType "bytes" +# #FilesCountType "files" +# #TypeInstance "instance" # # diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 3be5d4b8..11602b2a 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -2743,12 +2743,16 @@ blocks, the following options are recognized: =over 4 +=item B I + +Use I as the plugin name when submitting values. +Defaults to B. + =item B I -Sets the plugin instance to I. That instance name must be unique, but -it's your responsibility, the plugin doesn't check for that. If not given, the -instance is set to the directory name with all slashes replaced by underscores -and all leading underscores removed. +Sets the plugin instance to I. If not given, the instance is set to +the directory name with all slashes replaced by underscores and all leading +underscores removed. Empty value is allowed. =item B I @@ -2794,6 +2798,21 @@ Controls whether or not to include "hidden" files and directories in the count. "Hidden" files and directories are those, whose name begins with a dot. Defaults to I, i.e. by default hidden files and directories are ignored. +=item B I + +Sets the type used to dispatch files combined size. Empty value ("") disables +reporting. Defaults to B. + +=item B I + +Sets the type used to dispatch number of files. Empty value ("") disables +reporting. Defaults to B. + +=item B I + +Sets the I used to dispatch values. Defaults to an empty string +(no plugin instance). + =back =head2 Plugin C @@ -8223,9 +8242,9 @@ collections. The different bits of this bit mask accepted by this plugin are: Boolean enabling the use of logical core numbering for per core statistics. When enabled, CnE> is used as plugin instance, where I is a -sequential number assigned by the kernel. Otherwise, CnE> is used -where I is the n-th core of the socket, causing name conflicts when there is -more than one socket. +dynamic number assigned by the kernel. Otherwise, CnE> is used +if there is only one package and CnE-coreEmE> if there is +more than one, where I is the n-th core of package I. =back diff --git a/src/daemon/common.c b/src/daemon/common.c index 3ae61d85..6c856a6b 100644 --- a/src/daemon/common.c +++ b/src/daemon/common.c @@ -269,7 +269,8 @@ ssize_t swrite(int fd, const void *buf, size_t count) { if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) { /* if recv returns zero (even though poll() said there is data to be * read), that means the connection has been closed */ - return errno ? errno : -1; + errno = ECONNRESET; + return -1; } } diff --git a/src/filecount.c b/src/filecount.c index a2ec8e82..5b812b88 100644 --- a/src/filecount.c +++ b/src/filecount.c @@ -37,7 +37,11 @@ struct fc_directory_conf_s { char *path; + char *plugin_name; char *instance; + char *files_size_type; + char *files_num_type; + char *type_instance; int options; @@ -58,31 +62,56 @@ typedef struct fc_directory_conf_s fc_directory_conf_t; static fc_directory_conf_t **directories = NULL; static size_t directories_num = 0; +void fc_free_dir(fc_directory_conf_t *dir) { + sfree(dir->path); + sfree(dir->plugin_name); + sfree(dir->instance); + sfree(dir->files_size_type); + sfree(dir->files_num_type); + sfree(dir->type_instance); + sfree(dir->name); + + sfree(dir); +} /* void fc_free_dir */ + static void fc_submit_dir(const fc_directory_conf_t *dir) { value_list_t vl = VALUE_LIST_INIT; - vl.values = &(value_t){.gauge = (gauge_t)dir->files_num}; - vl.values_len = 1; - sstrncpy(vl.plugin, "filecount", sizeof(vl.plugin)); - sstrncpy(vl.plugin_instance, dir->instance, sizeof(vl.plugin_instance)); - sstrncpy(vl.type, "files", sizeof(vl.type)); + sstrncpy(vl.plugin, dir->plugin_name, sizeof(vl.plugin)); + if (dir->instance != NULL) + sstrncpy(vl.plugin_instance, dir->instance, sizeof(vl.plugin_instance)); + if (dir->type_instance != NULL) + sstrncpy(vl.type_instance, dir->type_instance, sizeof(vl.type_instance)); - plugin_dispatch_values(&vl); + vl.values_len = 1; - vl.values = &(value_t){.gauge = (gauge_t)dir->files_size}; - sstrncpy(vl.type, "bytes", sizeof(vl.type)); + if (dir->files_num_type != NULL) { + vl.values = &(value_t){.gauge = (gauge_t)dir->files_num}; + sstrncpy(vl.type, dir->files_num_type, sizeof(vl.type)); + plugin_dispatch_values(&vl); + } - plugin_dispatch_values(&vl); + if (dir->files_size_type != NULL) { + vl.values = &(value_t){.gauge = (gauge_t)dir->files_size}; + sstrncpy(vl.type, dir->files_size_type, sizeof(vl.type)); + plugin_dispatch_values(&vl); + } } /* void fc_submit_dir */ /* * Config: * * + * Plugin "foo" * Instance "foobar" * Name "*.conf" * MTime -3600 * Size "+10M" + * Recursive true + * IncludeHidden false + * FilesSizeType "bytes" + * FilesCountType "files" + * TypeInstance "instance" * * * @@ -94,7 +123,6 @@ static void fc_submit_dir(const fc_directory_conf_t *dir) { static int fc_config_set_instance(fc_directory_conf_t *dir, const char *str) { char buffer[1024]; char *ptr; - char *copy; sstrncpy(buffer, str, sizeof(buffer)); for (ptr = buffer; *ptr != 0; ptr++) @@ -104,10 +132,7 @@ static int fc_config_set_instance(fc_directory_conf_t *dir, const char *str) { for (ptr = buffer; *ptr == '_'; ptr++) /* do nothing */; - if (*ptr == 0) - return -1; - - copy = strdup(ptr); + char *copy = strdup(ptr); if (copy == NULL) return -1; @@ -130,15 +155,13 @@ static int fc_config_add_dir_instance(fc_directory_conf_t *dir, static int fc_config_add_dir_name(fc_directory_conf_t *dir, oconfig_item_t *ci) { - char *temp; - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { WARNING("filecount plugin: The `Name' config option needs exactly one " "string argument."); return -1; } - temp = strdup(ci->values[0].value.string); + char *temp = strdup(ci->values[0].value.string); if (temp == NULL) { ERROR("filecount plugin: strdup failed."); return -1; @@ -152,9 +175,6 @@ static int fc_config_add_dir_name(fc_directory_conf_t *dir, static int fc_config_add_dir_mtime(fc_directory_conf_t *dir, oconfig_item_t *ci) { - char *endptr; - double temp; - if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) && (ci->values[0].type != OCONFIG_TYPE_NUMBER))) { WARNING("filecount plugin: The `MTime' config option needs exactly one " @@ -168,8 +188,8 @@ static int fc_config_add_dir_mtime(fc_directory_conf_t *dir, } errno = 0; - endptr = NULL; - temp = strtod(ci->values[0].value.string, &endptr); + char *endptr = NULL; + double temp = strtod(ci->values[0].value.string, &endptr); if ((errno != 0) || (endptr == NULL) || (endptr == ci->values[0].value.string)) { WARNING("filecount plugin: Converting `%s' to a number failed.", @@ -220,9 +240,6 @@ static int fc_config_add_dir_mtime(fc_directory_conf_t *dir, static int fc_config_add_dir_size(fc_directory_conf_t *dir, oconfig_item_t *ci) { - char *endptr; - double temp; - if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) && (ci->values[0].type != OCONFIG_TYPE_NUMBER))) { WARNING("filecount plugin: The `Size' config option needs exactly one " @@ -236,8 +253,8 @@ static int fc_config_add_dir_size(fc_directory_conf_t *dir, } errno = 0; - endptr = NULL; - temp = strtod(ci->values[0].value.string, &endptr); + char *endptr = NULL; + double temp = strtod(ci->values[0].value.string, &endptr); if ((errno != 0) || (endptr == NULL) || (endptr == ci->values[0].value.string)) { WARNING("filecount plugin: Converting `%s' to a number failed.", @@ -303,9 +320,6 @@ static int fc_config_add_dir_option(fc_directory_conf_t *dir, } /* int fc_config_add_dir_option */ static int fc_config_add_dir(oconfig_item_t *ci) { - fc_directory_conf_t *dir; - int status; - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { WARNING("filecount plugin: `Directory' needs exactly one string " "argument."); @@ -313,7 +327,7 @@ static int fc_config_add_dir(oconfig_item_t *ci) { } /* Initialize `dir' */ - dir = calloc(1, sizeof(*dir)); + fc_directory_conf_t *dir = calloc(1, sizeof(*dir)); if (dir == NULL) { ERROR("filecount plugin: calloc failed."); return -1; @@ -322,23 +336,36 @@ static int fc_config_add_dir(oconfig_item_t *ci) { dir->path = strdup(ci->values[0].value.string); if (dir->path == NULL) { ERROR("filecount plugin: strdup failed."); - sfree(dir); + fc_free_dir(dir); return -1; } - fc_config_set_instance(dir, dir->path); - dir->options = FC_RECURSIVE; dir->name = NULL; + dir->plugin_name = strdup("filecount"); + dir->instance = NULL; + dir->type_instance = NULL; dir->mtime = 0; dir->size = 0; - status = 0; + dir->files_size_type = strdup("bytes"); + dir->files_num_type = strdup("files"); + + if (dir->plugin_name == NULL || dir->files_size_type == NULL || + dir->files_num_type == NULL) { + ERROR("filecount plugin: strdup failed."); + fc_free_dir(dir); + return -1; + } + + int status = 0; for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; - if (strcasecmp("Instance", option->key) == 0) + if (strcasecmp("Plugin", option->key) == 0) + status = cf_util_get_string(option, &dir->plugin_name); + else if (strcasecmp("Instance", option->key) == 0) status = fc_config_add_dir_instance(dir, option); else if (strcasecmp("Name", option->key) == 0) status = fc_config_add_dir_name(dir, option); @@ -350,6 +377,12 @@ static int fc_config_add_dir(oconfig_item_t *ci) { status = fc_config_add_dir_option(dir, option, FC_RECURSIVE); else if (strcasecmp("IncludeHidden", option->key) == 0) status = fc_config_add_dir_option(dir, option, FC_HIDDEN); + else if (strcasecmp("FilesSizeType", option->key) == 0) + status = cf_util_get_string(option, &dir->files_size_type); + else if (strcasecmp("FilesCountType", option->key) == 0) + status = cf_util_get_string(option, &dir->files_num_type); + else if (strcasecmp("TypeInstance", option->key) == 0) + status = cf_util_get_string(option, &dir->type_instance); else { WARNING("filecount plugin: fc_config_add_dir: " "Option `%s' not allowed here.", @@ -361,28 +394,52 @@ static int fc_config_add_dir(oconfig_item_t *ci) { break; } /* for (ci->children) */ - if (status == 0) { - fc_directory_conf_t **temp; + if (status != 0) { + fc_free_dir(dir); + return -1; + } - temp = realloc(directories, sizeof(*directories) * (directories_num + 1)); - if (temp == NULL) { - ERROR("filecount plugin: realloc failed."); - status = -1; - } else { - directories = temp; - directories[directories_num] = dir; - directories_num++; + /* Set default plugin instance */ + if (dir->instance == NULL) { + fc_config_set_instance(dir, dir->path); + if (dir->instance == NULL || strlen(dir->instance) == 0) { + ERROR("filecount plugin: failed to build plugin instance name."); + fc_free_dir(dir); + return -1; } } - if (status != 0) { - sfree(dir->name); + /* Handle disabled types */ + if (strlen(dir->instance) == 0) sfree(dir->instance); - sfree(dir->path); - sfree(dir); + + if (strlen(dir->files_size_type) == 0) + sfree(dir->files_size_type); + + if (strlen(dir->files_num_type) == 0) + sfree(dir->files_num_type); + + if (dir->files_size_type == NULL && dir->files_num_type == NULL) { + WARNING("filecount plugin: Both `FilesSizeType' and `FilesCountType ' " + "are disabled for '%s'. There's no types to report.", + dir->path); + fc_free_dir(dir); + return -1; + } + + /* Ready to add it to list */ + fc_directory_conf_t **temp = + realloc(directories, sizeof(*directories) * (directories_num + 1)); + if (temp == NULL) { + ERROR("filecount plugin: realloc failed."); + fc_free_dir(dir); return -1; } + directories = temp; + directories[directories_num] = dir; + directories_num++; + return 0; } /* int fc_config_add_dir */ @@ -414,14 +471,13 @@ static int fc_read_dir_callback(const char *dirname, const char *filename, fc_directory_conf_t *dir = user_data; char abs_path[PATH_MAX]; struct stat statbuf; - int status; if (dir == NULL) return -1; snprintf(abs_path, sizeof(abs_path), "%s/%s", dirname, filename); - status = lstat(abs_path, &statbuf); + int status = lstat(abs_path, &statbuf); if (status != 0) { ERROR("filecount plugin: stat (%s) failed.", abs_path); return -1; @@ -478,15 +534,13 @@ static int fc_read_dir_callback(const char *dirname, const char *filename, } /* int fc_read_dir_callback */ static int fc_read_dir(fc_directory_conf_t *dir) { - int status; - dir->files_num = 0; dir->files_size = 0; if (dir->mtime != 0) dir->now = time(NULL); - status = + int status = walk_directory(dir->path, fc_read_dir_callback, dir, /* include hidden */ (dir->options & FC_HIDDEN) ? 1 : 0); if (status != 0) { diff --git a/src/memcached.c b/src/memcached.c index 3502e355..90f323f8 100644 --- a/src/memcached.c +++ b/src/memcached.c @@ -5,6 +5,7 @@ * Copyright (C) 2009 Doug MacEachern * Copyright (C) 2009 Franck Lombardi * Copyright (C) 2012 Nicolas Szalay + * Copyright (C) 2017 Pavel Rochnyak * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -26,6 +27,7 @@ * Doug MacEachern * Franck Lombardi * Nicolas Szalay + * Pavel Rochnyak **/ #include "collectd.h" @@ -38,8 +40,12 @@ #include #include +#include + #define MEMCACHED_DEF_HOST "127.0.0.1" #define MEMCACHED_DEF_PORT "11211" +#define MEMCACHED_CONNECT_TIMEOUT 10000 +#define MEMCACHED_IO_TIMEOUT 5000 struct memcached_s { char *name; @@ -47,6 +53,7 @@ struct memcached_s { char *socket; char *connhost; char *connport; + int fd; }; typedef struct memcached_s memcached_t; @@ -57,6 +64,12 @@ static void memcached_free(void *arg) { if (st == NULL) return; + if (st->fd >= 0) { + shutdown(st->fd, SHUT_RDWR); + close(st->fd); + st->fd = -1; + } + sfree(st->name); sfree(st->host); sfree(st->socket); @@ -86,7 +99,15 @@ static int memcached_connect_unix(memcached_t *st) { if (status != 0) { shutdown(fd, SHUT_RDWR); close(fd); - fd = -1; + return -1; + } + + /* switch to non-blocking mode */ + int flags = fcntl(fd, F_GETFL); + status = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if (status != 0) { + close(fd); + return -1; } return fd; @@ -124,16 +145,47 @@ static int memcached_connect_inet(memcached_t *st) { continue; } + /* switch socket to non-blocking mode */ + int flags = fcntl(fd, F_GETFL); + status = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if (status != 0) { + close(fd); + fd = -1; + continue; + } + /* connect to the memcached daemon */ status = (int)connect(fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen); - if (status != 0) { + if (status != 0 && errno != EINPROGRESS) { shutdown(fd, SHUT_RDWR); close(fd); fd = -1; continue; } - /* A socket could be opened and connecting succeeded. We're done. */ + /* Wait until connection establishes */ + struct pollfd pollfd = { + .fd = fd, .events = POLLOUT, + }; + do + status = poll(&pollfd, 1, MEMCACHED_CONNECT_TIMEOUT); + while (status < 0 && errno == EINTR); + if (status <= 0) { + close(fd); + fd = -1; + continue; + } + + /* Check if all is good */ + int socket_error; + status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&socket_error, + &(socklen_t){sizeof(socket_error)}); + if (status != 0 || socket_error != 0) { + close(fd); + fd = -1; + continue; + } + /* A socket is opened and connection succeeded. We're done. */ break; } @@ -141,32 +193,55 @@ static int memcached_connect_inet(memcached_t *st) { return fd; } /* int memcached_connect_inet */ -static int memcached_connect(memcached_t *st) { +static void memcached_connect(memcached_t *st) { + if (st->fd >= 0) + return; + if (st->socket != NULL) - return memcached_connect_unix(st); + st->fd = memcached_connect_unix(st); else - return memcached_connect_inet(st); + st->fd = memcached_connect_inet(st); + + if (st->fd >= 0) + INFO("memcached plugin: Instance \"%s\": connection established.", + st->name); } static int memcached_query_daemon(char *buffer, size_t buffer_size, memcached_t *st) { - int fd, status; + int status; size_t buffer_fill; - fd = memcached_connect(st); - if (fd < 0) { + memcached_connect(st); + if (st->fd < 0) { ERROR("memcached plugin: Instance \"%s\" could not connect to daemon.", st->name); return -1; } - status = (int)swrite(fd, "stats\r\n", strlen("stats\r\n")); + struct pollfd pollfd = { + .fd = st->fd, .events = POLLOUT, + }; + + do + status = poll(&pollfd, 1, MEMCACHED_IO_TIMEOUT); + while (status < 0 && errno == EINTR); + + if (status <= 0) { + ERROR("memcached plugin: poll() failed for write() call."); + close(st->fd); + st->fd = -1; + return -1; + } + + status = (int)swrite(st->fd, "stats\r\n", strlen("stats\r\n")); if (status != 0) { char errbuf[1024]; - ERROR("memcached plugin: write(2) failed: %s", + ERROR("memcached plugin: Instance \"%s\": write(2) failed: %s", st->name, sstrerror(errno, errbuf, sizeof(errbuf))); - shutdown(fd, SHUT_RDWR); - close(fd); + shutdown(st->fd, SHUT_RDWR); + close(st->fd); + st->fd = -1; return -1; } @@ -174,27 +249,48 @@ static int memcached_query_daemon(char *buffer, size_t buffer_size, memset(buffer, 0, buffer_size); buffer_fill = 0; - while ((status = (int)recv(fd, buffer + buffer_fill, - buffer_size - buffer_fill, /* flags = */ 0)) != - 0) { + pollfd.events = POLLIN; + while (1) { + do + status = poll(&pollfd, 1, MEMCACHED_IO_TIMEOUT); + while (status < 0 && errno == EINTR); + + if (status <= 0) { + ERROR("memcached plugin: Instance \"%s\": Timeout reading from socket", + st->name); + close(st->fd); + st->fd = -1; + return -1; + } + + do + status = (int)recv(st->fd, buffer + buffer_fill, + buffer_size - buffer_fill, /* flags = */ 0); + while (status < 0 && errno == EINTR); + char const end_token[5] = {'E', 'N', 'D', '\r', '\n'}; if (status < 0) { char errbuf[1024]; - if ((errno == EAGAIN) || (errno == EINTR)) + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) continue; - ERROR("memcached: Error reading from socket: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - shutdown(fd, SHUT_RDWR); - close(fd); + ERROR("memcached plugin: Instance \"%s\": Error reading from socket: %s", + st->name, sstrerror(errno, errbuf, sizeof(errbuf))); + shutdown(st->fd, SHUT_RDWR); + close(st->fd); + st->fd = -1; return -1; } buffer_fill += (size_t)status; if (buffer_fill > buffer_size) { buffer_fill = buffer_size; - WARNING("memcached plugin: Message was truncated."); + WARNING("memcached plugin: Instance \"%s\": Message was truncated.", + st->name); + shutdown(st->fd, SHUT_RDWR); + close(st->fd); + st->fd = -1; break; } @@ -206,12 +302,11 @@ static int memcached_query_daemon(char *buffer, size_t buffer_size, status = 0; if (buffer_fill == 0) { - WARNING("memcached plugin: No data returned by memcached."); + WARNING("memcached plugin: Instance \"%s\": No data returned by memcached.", + st->name); status = -1; } - shutdown(fd, SHUT_RDWR); - close(fd); return status; } /* int memcached_query_daemon */ @@ -377,6 +472,13 @@ static int memcached_read(user_data_t *user_data) { } else if (FIELD_IS("listen_disabled_num")) { submit_derive("connections", "listen_disabled", atof(fields[2]), st); } + /* + * Total number of connections opened since the server started running + * Report this as connection rate. + */ + else if (FIELD_IS("total_connections")) { + submit_derive("connections", "opened", atof(fields[2]), st); + } /* * Commands @@ -562,6 +664,8 @@ static int config_add_instance(oconfig_item_t *ci) { st->connhost = NULL; st->connport = NULL; + st->fd = -1; + if (strcasecmp(ci->key, "Instance") == 0) status = cf_util_get_string(ci, &st->name); @@ -639,6 +743,8 @@ static int memcached_init(void) { st->connhost = NULL; st->connport = NULL; + st->fd = -1; + status = memcached_add_read_callback(st); if (status == 0) memcached_have_instances = 1; diff --git a/src/msr-index.h b/src/msr-index.h new file mode 100644 index 00000000..2adca577 --- /dev/null +++ b/src/msr-index.h @@ -0,0 +1,88 @@ +/* + * Partial header file imported from the linux kernel + * (arch/x86/include/asm/msr-index.h) + * as it is not provided by the kernel sources anymore + * + * Only the minimal blocks of macro have been included + * ---- + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * ---- + */ + +#ifndef _ASM_X86_MSR_INDEX_H +#define _ASM_X86_MSR_INDEX_H + +/* + * CPU model specific register (MSR) numbers. + * + * Do not add new entries to this file unless the definitions are shared + * between multiple compilation units. + */ + +/* Intel MSRs. Some also available on other CPUs */ + +/* C-state Residency Counters */ +#define MSR_PKG_C3_RESIDENCY 0x000003f8 +#define MSR_PKG_C6_RESIDENCY 0x000003f9 +#define MSR_ATOM_PKG_C6_RESIDENCY 0x000003fa +#define MSR_PKG_C7_RESIDENCY 0x000003fa +#define MSR_CORE_C3_RESIDENCY 0x000003fc +#define MSR_CORE_C6_RESIDENCY 0x000003fd +#define MSR_CORE_C7_RESIDENCY 0x000003fe +#define MSR_KNL_CORE_C6_RESIDENCY 0x000003ff +#define MSR_PKG_C2_RESIDENCY 0x0000060d +#define MSR_PKG_C8_RESIDENCY 0x00000630 +#define MSR_PKG_C9_RESIDENCY 0x00000631 +#define MSR_PKG_C10_RESIDENCY 0x00000632 + +/* Run Time Average Power Limiting (RAPL) Interface */ + +#define MSR_RAPL_POWER_UNIT 0x00000606 + +#define MSR_PKG_POWER_LIMIT 0x00000610 +#define MSR_PKG_ENERGY_STATUS 0x00000611 +#define MSR_PKG_PERF_STATUS 0x00000613 +#define MSR_PKG_POWER_INFO 0x00000614 + +#define MSR_DRAM_POWER_LIMIT 0x00000618 +#define MSR_DRAM_ENERGY_STATUS 0x00000619 +#define MSR_DRAM_PERF_STATUS 0x0000061b +#define MSR_DRAM_POWER_INFO 0x0000061c + +#define MSR_PP0_POWER_LIMIT 0x00000638 +#define MSR_PP0_ENERGY_STATUS 0x00000639 +#define MSR_PP0_POLICY 0x0000063a +#define MSR_PP0_PERF_STATUS 0x0000063b + +#define MSR_PP1_POWER_LIMIT 0x00000640 +#define MSR_PP1_ENERGY_STATUS 0x00000641 +#define MSR_PP1_POLICY 0x00000642 + + + +/* Intel defined MSRs. */ +#define MSR_IA32_TSC 0x00000010 +#define MSR_SMI_COUNT 0x00000034 + +#define MSR_IA32_MPERF 0x000000e7 +#define MSR_IA32_APERF 0x000000e8 + +#define MSR_IA32_THERM_STATUS 0x0000019c + +#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2 + +#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1 + + +#endif /* _ASM_X86_MSR_INDEX_H */ diff --git a/src/turbostat.c b/src/turbostat.c index 1049fb2a..e4419b85 100644 --- a/src/turbostat.c +++ b/src/turbostat.c @@ -41,7 +41,7 @@ #include "plugin.h" #include "utils_time.h" -#include +#include "msr-index.h" #include #ifdef HAVE_SYS_CAPABILITY_H #include @@ -585,7 +585,10 @@ static int submit_counters(struct thread_data *t, struct core_data *c, /* If not using logical core numbering, set core id */ if (!config_lcn) { - snprintf(name, sizeof(name), "core%02d", c->core_id); + if (topology.num_packages > 1) + snprintf(name, sizeof(name), "pkg%02d-core%02d", p->package_id, c->core_id); + else + snprintf(name, sizeof(name), "core%02d", c->core_id); } if (do_core_cstate & (1 << 3)) diff --git a/src/write_redis.c b/src/write_redis.c index 5a029de2..7dd5029c 100644 --- a/src/write_redis.c +++ b/src/write_redis.c @@ -45,6 +45,7 @@ struct wr_node_s { char *prefix; int database; int max_set_size; + int max_set_duration; _Bool store_rates; redisContext *conn; @@ -125,6 +126,20 @@ static int wr_write(const data_set_t *ds, /* {{{ */ freeReplyObject(rr); } + if (node->max_set_duration > 0) { + /* + * remove element, scored less than 'current-max_set_duration' + * '(%d' indicates 'less than' in redis CLI. + */ + rr = redisCommand(node->conn, "ZREMRANGEBYSCORE %s -1 (%d", key, + (time - node->max_set_duration) + 1); + if (rr == NULL) + WARNING("ZREMRANGEBYSCORE command error. key:%s message:%s", key, + node->conn->errstr); + else + freeReplyObject(rr); + } + /* TODO(octo): This is more overhead than necessary. Use the cache and * metadata to determine if it is a new metric and call SADD only once for * each metric. */ @@ -175,6 +190,7 @@ static int wr_config_node(oconfig_item_t *ci) /* {{{ */ node->prefix = NULL; node->database = 0; node->max_set_size = -1; + node->max_set_duration = -1; node->store_rates = 1; pthread_mutex_init(&node->lock, /* attr = */ NULL); @@ -205,6 +221,8 @@ static int wr_config_node(oconfig_item_t *ci) /* {{{ */ status = cf_util_get_int(child, &node->database); } else if (strcasecmp("MaxSetSize", child->key) == 0) { status = cf_util_get_int(child, &node->max_set_size); + } else if (strcasecmp("MaxSetDuration", child->key) == 0) { + status = cf_util_get_int(child, &node->max_set_duration); } else if (strcasecmp("StoreRates", child->key) == 0) { status = cf_util_get_boolean(child, &node->store_rates); } else