dovecot-2.0: doveadm: Added log test|reopen|find commands.
dovecot at dovecot.org
dovecot at dovecot.org
Fri May 28 17:15:26 EEST 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/86fd141577c3
changeset: 11416:86fd141577c3
user: Timo Sirainen <tss at iki.fi>
date: Fri May 28 15:15:10 2010 +0100
description:
doveadm: Added log test|reopen|find commands.
diffstat:
src/doveadm/Makefile.am | 1 +
src/doveadm/doveadm-log.c | 269 ++++++++++++++++++++++++++++++++++++++++++++
src/doveadm/doveadm-master.c | 6 +-
src/doveadm/doveadm.c | 1 +
src/doveadm/doveadm.h | 3 +
5 files changed, 277 insertions(+), 3 deletions(-)
diffs (truncated from 335 to 300 lines):
diff -r 257eb30cc529 -r 86fd141577c3 src/doveadm/Makefile.am
--- a/src/doveadm/Makefile.am Fri May 28 13:11:15 2010 +0100
+++ b/src/doveadm/Makefile.am Fri May 28 15:15:10 2010 +0100
@@ -52,6 +52,7 @@
doveadm-dump-mailboxlog.c \
doveadm-dump-thread.c \
doveadm-kick.c \
+ doveadm-log.c \
doveadm-master.c \
doveadm-mail.c \
doveadm-mail-altmove.c \
diff -r 257eb30cc529 -r 86fd141577c3 src/doveadm/doveadm-log.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/doveadm-log.c Fri May 28 15:15:10 2010 +0100
@@ -0,0 +1,269 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "hash.h"
+#include "str.h"
+#include "istream.h"
+#include "master-service-private.h"
+#include "master-service-settings.h"
+#include "doveadm.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <signal.h>
+#include <sys/stat.h>
+
+#define LAST_LOG_TYPE LOG_TYPE_PANIC
+#define TEST_LOG_MSG_PREFIX "This is Dovecot's "
+
+static void cmd_log_test(int argc ATTR_UNUSED, char *argv[] ATTR_UNUSED)
+{
+ unsigned int i;
+
+ master_service->flags |= MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR;
+ master_service_init_log(master_service, "doveadm: ");
+
+ for (i = 0; i < LAST_LOG_TYPE; i++) {
+ const char *prefix = failure_log_type_prefixes[i];
+
+ i_log_type(i, TEST_LOG_MSG_PREFIX"%s log",
+ t_str_lcase(t_strcut(prefix, ':')));
+ }
+}
+
+static void cmd_log_reopen(int argc ATTR_UNUSED, char *argv[] ATTR_UNUSED)
+{
+ doveadm_master_send_signal(SIGUSR1);
+}
+
+struct log_find_file {
+ const char *path;
+ uoff_t size;
+
+ /* 1 << enum log_type */
+ unsigned int mask;
+};
+
+struct log_find_context {
+ pool_t pool;
+ struct hash_table *files;
+};
+
+static void cmd_log_find_add(struct log_find_context *ctx,
+ const char *path, enum log_type type)
+{
+ struct log_find_file *file;
+ char *key;
+
+ file = hash_table_lookup(ctx->files, path);
+ if (file == NULL) {
+ file = p_new(ctx->pool, struct log_find_file, 1);
+ file->path = key = p_strdup(ctx->pool, path);
+ hash_table_insert(ctx->files, key, file);
+ }
+
+ file->mask |= 1 << type;
+}
+
+static void
+cmd_log_find_syslog_files(struct log_find_context *ctx, const char *path)
+{
+ struct log_find_file *file;
+ DIR *dir;
+ struct dirent *d;
+ struct stat st;
+ char *key;
+ string_t *full_path;
+ unsigned int dir_len;
+
+ dir = opendir(path);
+ if (dir == NULL) {
+ i_error("opendir(%s) failed: %m", path);
+ return;
+ }
+
+ full_path = t_str_new(256);
+ str_append(full_path, path);
+ str_append_c(full_path, '/');
+ dir_len = str_len(full_path);
+
+ while ((d = readdir(dir)) != NULL) {
+ if (d->d_name[0] == '.')
+ continue;
+
+ str_truncate(full_path, dir_len);
+ str_append(full_path, d->d_name);
+ if (stat(str_c(full_path), &st) < 0)
+ continue;
+
+ if (S_ISDIR(st.st_mode)) {
+ /* recursively go through all subdirectories */
+ cmd_log_find_syslog_files(ctx, str_c(full_path));
+ } else {
+ file = p_new(ctx->pool, struct log_find_file, 1);
+ file->size = st.st_size;
+ file->path = key =
+ p_strdup(ctx->pool, str_c(full_path));
+ hash_table_insert(ctx->files, key, file);
+ }
+ }
+
+ (void)closedir(dir);
+}
+
+static bool log_type_find(const char *str, enum log_type *type_r)
+{
+ unsigned int i, len = strlen(str);
+
+ for (i = 0; i < LAST_LOG_TYPE; i++) {
+ if (strncasecmp(str, failure_log_type_prefixes[i], len) == 0 &&
+ failure_log_type_prefixes[i][len] == ':') {
+ *type_r = i;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void cmd_log_find_syslog_file_messages(struct log_find_file *file)
+{
+ struct istream *input;
+ const char *line, *p;
+ enum log_type type;
+ int fd;
+
+ fd = open(file->path, O_RDONLY);
+ if (fd == -1)
+ return;
+ input = i_stream_create_fd(fd, 1024, TRUE);
+ while ((line = i_stream_read_next_line(input)) != NULL) {
+ p = strstr(line, TEST_LOG_MSG_PREFIX);
+ if (p == NULL)
+ continue;
+ p += strlen(TEST_LOG_MSG_PREFIX);
+
+ /* <type> log */
+ T_BEGIN {
+ if (log_type_find(t_strcut(p, ' '), &type))
+ file->mask |= 1 << type;
+ } T_END;
+ }
+ i_stream_destroy(&input);
+}
+
+static void cmd_log_find_syslog_messages(struct log_find_context *ctx)
+{
+ struct hash_iterate_context *iter;
+ struct stat st;
+ void *key, *value;
+
+ iter = hash_table_iterate_init(ctx->files);
+ while (hash_table_iterate(iter, &key, &value)) {
+ struct log_find_file *file = value;
+
+ if (file->mask != 0 ||
+ stat(file->path, &st) < 0 ||
+ (uoff_t)st.st_size <= file->size)
+ continue;
+
+ cmd_log_find_syslog_file_messages(file);
+ }
+ hash_table_iterate_deinit(&iter);
+}
+
+static void
+cmd_log_find_syslog(struct log_find_context *ctx, int argc, char *argv[])
+{
+ const char *log_dir;
+ struct stat st;
+
+ if (argc > 1)
+ log_dir = argv[1];
+ else if (stat("/var/log", &st) == 0 && S_ISDIR(st.st_mode))
+ log_dir = "/var/log";
+ else if (stat("/var/adm", &st) == 0 && S_ISDIR(st.st_mode))
+ log_dir = "/var/adm";
+ else
+ return;
+
+ printf("Looking for log files from %s\n", log_dir);
+ cmd_log_find_syslog_files(ctx, log_dir);
+ cmd_log_test(0, NULL);
+ cmd_log_find_syslog_messages(ctx);
+}
+
+static void cmd_log_find(int argc, char *argv[])
+{
+ const struct master_service_settings *set;
+ const char *log_file_path;
+ struct log_find_context ctx;
+ unsigned int i;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.pool = pool_alloconly_create("log file", 1024*32);
+ ctx.files = hash_table_create(default_pool, ctx.pool, 0,
+ str_hash, (hash_cmp_callback_t *)strcmp);
+
+ /* first get the paths that we know are used */
+ set = master_service_settings_get(master_service);
+ log_file_path = set->log_path;
+ if (*log_file_path != '\0') {
+ cmd_log_find_add(&ctx, log_file_path, LOG_TYPE_WARNING);
+ cmd_log_find_add(&ctx, log_file_path, LOG_TYPE_ERROR);
+ cmd_log_find_add(&ctx, log_file_path, LOG_TYPE_FATAL);
+ }
+
+ if (*set->info_log_path != '\0')
+ log_file_path = set->info_log_path;
+ if (*log_file_path != '\0')
+ cmd_log_find_add(&ctx, log_file_path, LOG_TYPE_INFO);
+
+ if (*set->debug_log_path != '\0')
+ log_file_path = set->debug_log_path;
+ if (*log_file_path != '\0')
+ cmd_log_find_add(&ctx, log_file_path, LOG_TYPE_DEBUG);
+
+ if (*set->log_path == '\0') {
+ /* at least some logs were logged via syslog */
+ cmd_log_find_syslog(&ctx, argc, argv);
+ }
+
+ /* print them */
+ for (i = 0; i < LAST_LOG_TYPE; i++) {
+ struct hash_iterate_context *iter;
+ void *key, *value;
+ bool found = FALSE;
+
+ iter = hash_table_iterate_init(ctx.files);
+ while (hash_table_iterate(iter, &key, &value)) {
+ struct log_find_file *file = value;
+
+ if ((file->mask & (1 << i)) != 0) {
+ printf("%s%s\n", failure_log_type_prefixes[i],
+ file->path);
+ found = TRUE;
+ }
+ }
+ hash_table_iterate_deinit(&iter);
+
+ if (!found)
+ printf("%sNot found\n", failure_log_type_prefixes[i]);
+ }
+}
+
+struct doveadm_cmd doveadm_cmd_log[] = {
+ { cmd_log_test, "log test", "", NULL },
+ { cmd_log_reopen, "log reopen", "", NULL },
+ { cmd_log_find, "log find", "[<dir>]", NULL }
+};
+
+void doveadm_register_log_commands(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < N_ELEMENTS(doveadm_cmd_log); i++)
+ doveadm_register_cmd(&doveadm_cmd_log[i]);
+}
diff -r 257eb30cc529 -r 86fd141577c3 src/doveadm/doveadm-master.c
--- a/src/doveadm/doveadm-master.c Fri May 28 13:11:15 2010 +0100
+++ b/src/doveadm/doveadm-master.c Fri May 28 15:15:10 2010 +0100
@@ -45,7 +45,7 @@
return found;
}
-static void send_master_signal(int signo)
+void doveadm_master_send_signal(int signo)
{
const char *pidfile_path;
unsigned int i;
@@ -76,12 +76,12 @@
static void cmd_stop(int argc ATTR_UNUSED, char *argv[] ATTR_UNUSED)
{
More information about the dovecot-cvs
mailing list