"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/doveadm/doveadm-stats.c" between
dovecot-2.3.16.tar.gz and dovecot-2.3.17.tar.gz

About: Dovecot is an IMAP and POP3 server, written with security primarily in mind.

doveadm-stats.c  (dovecot-2.3.16):doveadm-stats.c  (dovecot-2.3.17)
skipping to change at line 12 skipping to change at line 12
#include "lib.h" #include "lib.h"
#include "net.h" #include "net.h"
#include "istream.h" #include "istream.h"
#include "str.h" #include "str.h"
#include "strescape.h" #include "strescape.h"
#include "write-full.h" #include "write-full.h"
#include "master-service.h" #include "master-service.h"
#include "doveadm.h" #include "doveadm.h"
#include "doveadm-print.h" #include "doveadm-print.h"
#include "stats-settings.h"
#include <math.h> #include <math.h>
#define DOVEADM_DUMP_DEFAULT_FIELDS \ #define DOVEADM_DUMP_DEFAULT_FIELDS \
"count sum min max avg median stddev %95" "count sum min max avg median stddev %95"
enum doveadm_dump_field_type { enum doveadm_dump_field_type {
DOVEADM_DUMP_FIELD_TYPE_PASSTHROUGH = 0, DOVEADM_DUMP_FIELD_TYPE_PASSTHROUGH = 0,
DOVEADM_DUMP_FIELD_TYPE_STDDEV, DOVEADM_DUMP_FIELD_TYPE_STDDEV,
}; };
struct stats_cmd_context {
string_t *cmd;
struct doveadm_cmd_context *cctx;
struct istream *input;
const char *path;
void *data;
};
struct dump_data {
const char **fields;
unsigned int field_count;
enum doveadm_dump_field_type *field_types;
};
struct stats_cmd_vfuncs {
int (*build_cmd)(struct stats_cmd_context *ctx, const char **error_r);
void (*process_response)(struct stats_cmd_context *ctx);
};
static int build_stats_dump_cmd(struct stats_cmd_context *ctx, const char **erro
r_r);
static int build_stats_add_cmd(struct stats_cmd_context *ctx, const char **error
_r);
static int build_stats_remove_cmd(struct stats_cmd_context *ctx, const char **er
ror_r);
static void stats_dump_process_response(struct stats_cmd_context *ctx);
static void stats_modify_process_response(struct stats_cmd_context *ctx);
static void stats_send_cmd(struct stats_cmd_context *ctx);
static struct stats_cmd_vfuncs dump_vfuncs = {
.build_cmd = build_stats_dump_cmd,
.process_response = stats_dump_process_response
};
static struct stats_cmd_vfuncs add_vfuncs = {
.build_cmd = build_stats_add_cmd,
.process_response = stats_modify_process_response
};
static struct stats_cmd_vfuncs remove_vfuncs = {
.build_cmd = build_stats_remove_cmd,
.process_response = stats_modify_process_response
};
static string_t *init_stats_cmd(void)
{
string_t *cmd = t_str_new(128);
str_append(cmd, "VERSION\tstats-reader-client\t2\t0\n");
return cmd;
}
static void stats_exec_cmd(struct doveadm_cmd_context *cctx,
struct stats_cmd_vfuncs *vfuncs)
{
struct stats_cmd_context ctx;
const char *build_cmd_error;
ctx.cctx = cctx;
if (vfuncs->build_cmd(&ctx, &build_cmd_error) < 0) {
i_error("%s", build_cmd_error);
return;
}
stats_send_cmd(&ctx);
vfuncs->process_response(&ctx);
i_stream_destroy(&ctx.input);
}
static void handle_disconnection(struct stats_cmd_context *ctx)
{
i_error("read(%s) failed: %s", ctx->path,
i_stream_get_disconnect_reason(ctx->input));
}
static void stats_send_cmd(struct stats_cmd_context *ctx)
{
int fd;
const char *line;
if (!doveadm_cmd_param_str(ctx->cctx, "socket-path", &ctx->path))
ctx->path = t_strconcat(doveadm_settings->base_dir,
"/stats-reader", NULL);
fd = doveadm_connect(ctx->path);
net_set_nonblock(fd, FALSE);
if (write_full(fd, str_data(ctx->cmd), str_len(ctx->cmd)) < 0)
i_fatal("write(%s) failed %m", ctx->path);
ctx->input = i_stream_create_fd_autoclose(&fd, SIZE_MAX);
if ((line = i_stream_read_next_line(ctx->input)) == NULL)
i_fatal("%s: Failed to read VERSION line", ctx->path);
else if (!version_string_verify(line, "stats-reader-server", 2)) {
i_fatal_status(EX_PROTOCOL,
"%s is not a compatible stats-reader socket", ctx->path);
}
}
static void dump_timing(const char *const **args, static void dump_timing(const char *const **args,
const enum doveadm_dump_field_type field_types[], const enum doveadm_dump_field_type field_types[],
unsigned int fields_count) unsigned int fields_count)
{ {
unsigned int i, args_count = str_array_length(*args); unsigned int i, args_count = str_array_length(*args);
if (args_count > fields_count) if (args_count > fields_count)
args_count = fields_count; args_count = fields_count;
for (i = 0; i < args_count; i++) { for (i = 0; i < args_count; i++) {
const char *value = (*args)[i]; const char *value = (*args)[i];
skipping to change at line 48 skipping to change at line 142
double variance = strtod(value, NULL); double variance = strtod(value, NULL);
value = t_strdup_printf("%.02f", sqrt(variance)); value = t_strdup_printf("%.02f", sqrt(variance));
break; break;
} }
} }
doveadm_print(value); doveadm_print(value);
} }
*args += args_count; *args += args_count;
} }
static void stats_dump(const char *path, const char *const *fields, bool reset) static int build_stats_dump_cmd(struct stats_cmd_context *ctx,
const char **error_r ATTR_UNUSED)
{ {
struct istream *input; bool reset;
string_t *cmd = t_str_new(128); struct dump_data *data = t_new(struct dump_data, 1);
unsigned int i, fields_count = str_array_length(fields); const char *fields_raw;
enum doveadm_dump_field_type field_types[fields_count]; const char **fields;
char *line; if (!doveadm_cmd_param_bool(ctx->cctx, "reset", &reset))
int fd; reset = FALSE;
if (!doveadm_cmd_param_str(ctx->cctx, "fields", &fields_raw))
fields_raw = DOVEADM_DUMP_DEFAULT_FIELDS;
fd = doveadm_connect(path); fields = t_strsplit_spaces(fields_raw, ", ");
net_set_nonblock(fd, FALSE); data->fields = fields;
str_append(cmd, "VERSION\tstats-reader-client\t2\t0\n"); data->field_count = str_array_length(fields);
str_append(cmd, reset ? "DUMP-RESET" : "DUMP"); data->field_types =
i_zero(&field_types); t_malloc0(sizeof(enum doveadm_dump_field_type) * data->field_coun
for (i = 0; i < fields_count; i++) { t);
str_append_c(cmd, '\t'); ctx->data = data;
ctx->cmd = init_stats_cmd();
str_append(ctx->cmd, reset ? "DUMP-RESET" : "DUMP");
unsigned int i;
for (i = 0; i < data->field_count; i++) {
str_append_c(ctx->cmd, '\t');
if (strcmp(fields[i], "stddev") == 0) { if (strcmp(fields[i], "stddev") == 0) {
field_types[i] = DOVEADM_DUMP_FIELD_TYPE_STDDEV; data->field_types[i] = DOVEADM_DUMP_FIELD_TYPE_STDDEV;
str_append(cmd, "variance"); str_append(ctx->cmd, "variance");
} else { } else {
str_append_tabescaped(cmd, fields[i]); str_append_tabescaped(ctx->cmd, fields[i]);
} }
} }
str_append_c(cmd, '\n'); str_append_c(ctx->cmd, '\n');
if (write_full(fd, str_data(cmd), str_len(cmd)) < 0) return 0;
i_fatal("write(%s) failed: %m", path); }
input = i_stream_create_fd_autoclose(&fd, SIZE_MAX); static void stats_dump_process_response(struct stats_cmd_context *ctx)
if ((line = i_stream_read_next_line(input)) == NULL) {
i_fatal("%s: Failed to read VERSION line", path); unsigned int i;
else if (!version_string_verify(line, "stats-reader-server", 2)) { char *line;
i_fatal_status(EX_PROTOCOL, struct dump_data *data = ctx->data;
"%s is not a compatible stats-reader socket", path);
}
doveadm_print_init(DOVEADM_PRINT_TYPE_TAB);
doveadm_print_header_simple("metric_name"); doveadm_print_header_simple("metric_name");
doveadm_print_header_simple("field"); doveadm_print_header_simple("field");
for (i = 0; i < fields_count; i++) for (i = 0; i < data->field_count; i++)
doveadm_print_header(fields[i], fields[i], DOVEADM_PRINT_HEADER_F doveadm_print_header(data->fields[i], data->fields[i],
LAG_NUMBER); DOVEADM_PRINT_HEADER_FLAG_NUMBER);
while ((line = i_stream_read_next_line(input)) != NULL) { while ((line = i_stream_read_next_line(ctx->input)) != NULL) {
if (line[0] == '\0') if (line[0] == '\0')
break; break;
T_BEGIN { T_BEGIN {
const char *const *args = const char *const *args =
t_strsplit_tabescaped_inplace(line); t_strsplit_tabescaped_inplace(line);
const char *metric_name = args[0]; const char *metric_name = args[0];
doveadm_print(metric_name); args++; doveadm_print(metric_name); args++;
doveadm_print("duration"); doveadm_print("duration");
dump_timing(&args, field_types, fields_count); dump_timing(&args, data->field_types, data->field_count);
while (*args != NULL) { while (*args != NULL) {
doveadm_print(metric_name); doveadm_print(metric_name);
doveadm_print(*args); args++; doveadm_print(*args); args++;
dump_timing(&args, field_types, fields_count); dump_timing(&args, data->field_types, data->field _count);
} }
} T_END; } T_END;
} }
if (line == NULL)
handle_disconnection(ctx);
}
static int build_stats_add_cmd(struct stats_cmd_context *ctx,
const char **error_r)
{
unsigned int i;
const char *parameter;
struct {
const char *name;
const char *default_val;
} params[] = {
{ "name", "" },
{ "description", "" },
{ "fields", "" },
{ "group_by", "" },
{ "filter", "" },
{ "exporter", "" },
/* Default exporter-include is to be modified
together with stats-settings */
{ "exporter-include",
STATS_METRIC_SETTINGS_DEFAULT_EXPORTER_INCLUDE },
};
ctx->cmd = init_stats_cmd();
str_append(ctx->cmd, "METRICS-ADD");
for (i = 0; i < N_ELEMENTS(params); i++) {
if (!doveadm_cmd_param_str(ctx->cctx, params[i].name, &parameter)
)
parameter = params[i].default_val;
if (parameter[0] == '\0' &&
(strcmp(params[i].name, "name") == 0 ||
strcmp(params[i].name, "filter") == 0)) {
*error_r =
t_strdup_printf("stats add: missing %s parameter"
,
params[i].name);
return -1;
}
str_append_c(ctx->cmd, '\t');
str_append_tabescaped(ctx->cmd, parameter);
}
if (input->stream_errno != 0) str_append_c(ctx->cmd, '\n');
i_fatal("read(%s) failed: %s", path, i_stream_get_error(input)); return 0;
i_stream_destroy(&input);
} }
static void static void stats_modify_process_response(struct stats_cmd_context *ctx)
doveadm_cmd_stats_dump(struct doveadm_cmd_context *cctx)
{ {
const char *path, *fields; const char *line = i_stream_read_next_line(ctx->input);
bool reset; if (line == NULL) {
handle_disconnection(ctx);
return;
}
if (line[0] == '-')
i_error("%s", ++line);
else if (line[0] != '+')
i_error("Invalid response: %s", line);
}
if (!doveadm_cmd_param_str(cctx, "socket-path", &path)) static int build_stats_remove_cmd(struct stats_cmd_context *ctx,
path = t_strconcat(doveadm_settings->base_dir, "/stats-reader", N const char **error_r)
ULL); {
if (!doveadm_cmd_param_bool(cctx, "reset", &reset)) const char *name;
reset = FALSE;
if (!doveadm_cmd_param_str(cctx, "fields", &fields)) ctx->cmd = init_stats_cmd();
fields = DOVEADM_DUMP_DEFAULT_FIELDS; str_append(ctx->cmd, "METRICS-REMOVE\t");
doveadm_print_init(DOVEADM_PRINT_TYPE_TAB); if (!doveadm_cmd_param_str(ctx->cctx, "name", &name)) {
stats_dump(path, t_strsplit_spaces(fields, ", "), reset); *error_r = "stats remove: missing name parameter";
return; return -1;
}
str_append_tabescaped(ctx->cmd, name);
str_append_c(ctx->cmd, '\n');
return 0;
}
static void doveadm_cmd_stats_dump(struct doveadm_cmd_context *cctx)
{
stats_exec_cmd(cctx, &dump_vfuncs);
}
static void doveadm_cmd_stats_add(struct doveadm_cmd_context *cctx)
{
stats_exec_cmd(cctx, &add_vfuncs);
}
static void doveadm_cmd_stats_remove(struct doveadm_cmd_context *cctx)
{
stats_exec_cmd(cctx, &remove_vfuncs);
} }
struct doveadm_cmd_ver2 doveadm_cmd_stats_dump_ver2 = { struct doveadm_cmd_ver2 doveadm_cmd_stats_dump_ver2 = {
.cmd = doveadm_cmd_stats_dump, .cmd = doveadm_cmd_stats_dump,
.name = "stats dump", .name = "stats dump",
.usage = "[-s <stats socket path>] [-r] [-f <fields>]", .usage = "[-s <stats socket path>] [-r] [-f <fields>]",
DOVEADM_CMD_PARAMS_START DOVEADM_CMD_PARAMS_START
DOVEADM_CMD_PARAM('s', "socket-path", CMD_PARAM_STR, 0) DOVEADM_CMD_PARAM('s', "socket-path", CMD_PARAM_STR, 0)
DOVEADM_CMD_PARAM('r', "reset", CMD_PARAM_BOOL, 0) DOVEADM_CMD_PARAM('r', "reset", CMD_PARAM_BOOL, 0)
DOVEADM_CMD_PARAM('f', "fields", CMD_PARAM_STR, 0) DOVEADM_CMD_PARAM('f', "fields", CMD_PARAM_STR, 0)
DOVEADM_CMD_PARAMS_END DOVEADM_CMD_PARAMS_END
}; };
struct doveadm_cmd_ver2 doveadm_cmd_stats_add_ver2 = {
.cmd = doveadm_cmd_stats_add,
.name = "stats add",
.usage = "[--description <string>] [--exporter <name> [--exporter-include
<fields>]] [--fields <fields>] [--group_by <fields>] <name> <filter>",
DOVEADM_CMD_PARAMS_START
DOVEADM_CMD_PARAM('\0', "name", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
DOVEADM_CMD_PARAM('\0', "filter", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
DOVEADM_CMD_PARAM('\0', "exporter", CMD_PARAM_STR, 0)
DOVEADM_CMD_PARAM('\0', "exporter-include", CMD_PARAM_STR, 0)
DOVEADM_CMD_PARAM('\0', "description", CMD_PARAM_STR, 0)
DOVEADM_CMD_PARAM('\0', "fields", CMD_PARAM_STR, 0)
DOVEADM_CMD_PARAM('\0', "group-by", CMD_PARAM_STR, 0)
DOVEADM_CMD_PARAMS_END
};
struct doveadm_cmd_ver2 doveadm_cmd_stats_remove_ver2 = {
.cmd = doveadm_cmd_stats_remove,
.name = "stats remove",
.usage = "<name>",
DOVEADM_CMD_PARAMS_START
DOVEADM_CMD_PARAM('\0', "name", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
DOVEADM_CMD_PARAMS_END
};
 End of changes. 21 change blocks. 
51 lines changed or deleted 223 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)