Mercurial > dovecot > core-2.2
view src/plugins/stats/mail-stats-fill.c @ 19552:0f22db71df7a
global: freshen copyright
git ls-files | xargs perl -p -i -e 's/(\d+)-201[0-5]/$1-2016/g;s/ (201[0-5]) Dovecot/ $1-2016 Dovecot/'
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Wed, 13 Jan 2016 12:24:03 +0200 |
parents | a9952ceeac61 |
children | f935beaa6af5 |
line wrap: on
line source
/* Copyright (c) 2011-2016 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "stats-plugin.h" #include "mail-stats.h" #include <sys/resource.h> #define PROC_IO_PATH "/proc/self/io" static bool proc_io_disabled = FALSE; static int proc_io_fd = -1; static int process_io_buffer_parse(const char *buf, struct mail_stats *stats) { const char *const *tmp; tmp = t_strsplit(buf, "\n"); for (; *tmp != NULL; tmp++) { if (strncmp(*tmp, "rchar: ", 7) == 0) { if (str_to_uint64(*tmp + 7, &stats->read_bytes) < 0) return -1; } else if (strncmp(*tmp, "wchar: ", 7) == 0) { if (str_to_uint64(*tmp + 7, &stats->write_bytes) < 0) return -1; } else if (strncmp(*tmp, "syscr: ", 7) == 0) { if (str_to_uint32(*tmp + 7, &stats->read_count) < 0) return -1; } else if (strncmp(*tmp, "syscw: ", 7) == 0) { if (str_to_uint32(*tmp + 7, &stats->write_count) < 0) return -1; } } return 0; } static int process_io_open(void) { uid_t uid; if (proc_io_fd != -1) return proc_io_fd; if (proc_io_disabled) return -1; proc_io_fd = open(PROC_IO_PATH, O_RDONLY); if (proc_io_fd == -1 && errno == EACCES) { /* kludge: if we're running with permissions temporarily dropped, get them temporarily back so we can open /proc/self/io. */ uid = geteuid(); if (seteuid(0) == 0) { proc_io_fd = open(PROC_IO_PATH, O_RDONLY); if (seteuid(uid) < 0) { /* oops, this is bad */ i_fatal("stats: seteuid(%s) failed", dec2str(uid)); } } errno = EACCES; } if (proc_io_fd == -1) { if (errno != ENOENT) i_error("open(%s) failed: %m", PROC_IO_PATH); proc_io_disabled = TRUE; return -1; } return proc_io_fd; } static void process_read_io_stats(struct mail_stats *stats) { char buf[1024]; int fd, ret; if ((fd = process_io_open()) == -1) return; ret = pread(fd, buf, sizeof(buf), 0); if (ret <= 0) { if (ret == -1) i_error("read(%s) failed: %m", PROC_IO_PATH); else i_error("read(%s) returned EOF", PROC_IO_PATH); } else if (ret == sizeof(buf)) { /* just shouldn't happen.. */ i_error("%s is larger than expected", PROC_IO_PATH); proc_io_disabled = TRUE; } else { buf[ret] = '\0'; T_BEGIN { if (process_io_buffer_parse(buf, stats) < 0) { i_error("Invalid input in file %s", PROC_IO_PATH); proc_io_disabled = TRUE; } } T_END; } } static void user_trans_stats_get(struct stats_user *suser, struct mail_stats *dest_r) { struct stats_transaction_context *strans; mail_stats_add_transaction(dest_r, &suser->finished_transaction_stats); for (strans = suser->transactions; strans != NULL; strans = strans->next) mail_stats_add_transaction(dest_r, &strans->trans->stats); } void mail_stats_fill(struct stats_user *suser, struct mail_stats *stats_r) { struct rusage usage; memset(stats_r, 0, sizeof(*stats_r)); /* cputime */ if (getrusage(RUSAGE_SELF, &usage) < 0) memset(&usage, 0, sizeof(usage)); stats_r->user_cpu = usage.ru_utime; stats_r->sys_cpu = usage.ru_stime; stats_r->min_faults = usage.ru_minflt; stats_r->maj_faults = usage.ru_majflt; stats_r->vol_cs = usage.ru_nvcsw; stats_r->invol_cs = usage.ru_nivcsw; stats_r->disk_input = (unsigned long long)usage.ru_inblock * 512ULL; stats_r->disk_output = (unsigned long long)usage.ru_oublock * 512ULL; (void)gettimeofday(&stats_r->clock_time, NULL); process_read_io_stats(stats_r); user_trans_stats_get(suser, stats_r); }