dovecot: Added mail_log_events, mail_log_group_events and mail_l...

dovecot at dovecot.org dovecot at dovecot.org
Thu Jun 21 00:51:42 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/ea050869097b
changeset: 5794:ea050869097b
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Jun 21 00:51:34 2007 +0300
description:
Added mail_log_events, mail_log_group_events and mail_log_fields settings to
mail_log plugin.

diffstat:

2 files changed, 389 insertions(+), 21 deletions(-)
dovecot-example.conf                   |    8 
src/plugins/mail-log/mail-log-plugin.c |  402 ++++++++++++++++++++++++++++++--

diffs (truncated from 493 to 300 lines):

diff -r 512f8982ae8b -r ea050869097b dovecot-example.conf
--- a/dovecot-example.conf	Wed Jun 20 23:50:38 2007 +0300
+++ b/dovecot-example.conf	Thu Jun 21 00:51:34 2007 +0300
@@ -1103,4 +1103,12 @@ plugin {
   # they're moved to a 3rd namespace. The mails won't be counted in quota,
   # and they're not deleted automatically (use a cronjob or something).
   #lazy_expunge = .EXPUNGED/ .DELETED/ .DELETED/.EXPUNGED/
+
+  # Events to log. Default is all.
+  #mail_log_events = delete undelete expunge copy mailbox_delete
+  # Group events within a transaction to one line.
+  #mail_log_group_events = 
+  # Available fields: uid, box, msgid, size, vsize
+  # size and vsize are available only for expunge and copy events.
+  #mail_log_fields = uid box msgid size
 }
diff -r 512f8982ae8b -r ea050869097b src/plugins/mail-log/mail-log-plugin.c
--- a/src/plugins/mail-log/mail-log-plugin.c	Wed Jun 20 23:50:38 2007 +0300
+++ b/src/plugins/mail-log/mail-log-plugin.c	Thu Jun 21 00:51:34 2007 +0300
@@ -2,10 +2,13 @@
 
 #include "lib.h"
 #include "array.h"
+#include "str.h"
 #include "str-sanitize.h"
 #include "mail-storage-private.h"
 #include "mailbox-list-private.h"
 #include "mail-log-plugin.h"
+
+#include <stdlib.h>
 
 #define MAILBOX_NAME_LOG_LEN 64
 #define MSGID_LOG_LEN 80
@@ -17,7 +20,73 @@
 #define MAIL_LOG_LIST_CONTEXT(obj) \
 	MODULE_CONTEXT(obj, mail_log_mailbox_list_module)
 
+enum mail_log_field {
+	MAIL_LOG_FIELD_UID	= 0x01,
+	MAIL_LOG_FIELD_BOX	= 0x02,
+	MAIL_LOG_FIELD_MSGID	= 0x04,
+	MAIL_LOG_FIELD_PSIZE	= 0x08,
+	MAIL_LOG_FIELD_VSIZE	= 0x10
+};
+#define MAIL_LOG_DEFAULT_FIELDS \
+	(MAIL_LOG_FIELD_UID | MAIL_LOG_FIELD_BOX | \
+	 MAIL_LOG_FIELD_MSGID | MAIL_LOG_FIELD_PSIZE)
+
+enum mail_log_event {
+	MAIL_LOG_EVENT_DELETE		= 0x01,
+	MAIL_LOG_EVENT_UNDELETE		= 0x02,
+	MAIL_LOG_EVENT_EXPUNGE		= 0x04,
+	MAIL_LOG_EVENT_COPY		= 0x08,
+	MAIL_LOG_EVENT_MAILBOX_DELETE	= 0x10,
+
+	MAIL_LOG_EVENT_MASK_ALL		= 0x1f
+};
+#define MAIL_LOG_DEFAULT_EVENTS MAIL_LOG_EVENT_MASK_ALL
+
+static const char *field_names[] = {
+	"uid",
+	"box",
+	"msgid",
+	"size",
+	"vsize",
+	NULL
+};
+
+static const char *event_names[] = {
+	"delete",
+	"undelete",
+	"expunge",
+	"copy",
+	"mailbox_delete",
+	NULL
+};
+
+struct mail_log_settings {
+	enum mail_log_field fields;
+	enum mail_log_event events;
+
+	unsigned int group_events:1;
+};
+
+struct mail_log_group_changes {
+	enum mail_log_event event;
+	const char *data;
+
+	ARRAY_TYPE(seq_range) uids;
+	uoff_t psize_total, vsize_total;
+};
+
+struct mail_log_transaction_context {
+	union mailbox_transaction_module_context module_ctx;
+	pool_t pool;
+
+	ARRAY_DEFINE(group_changes, struct mail_log_group_changes);
+
+	unsigned int changes;
+};
+
 const char *mail_log_plugin_version = PACKAGE_VERSION;
+
+static struct mail_log_settings mail_log_set;
 
 static void (*mail_log_next_hook_mail_storage_created)
 	(struct mail_storage *storage);
@@ -30,24 +99,225 @@ static MODULE_CONTEXT_DEFINE_INIT(mail_l
 static MODULE_CONTEXT_DEFINE_INIT(mail_log_mailbox_list_module,
 				  &mailbox_list_module_register);
 
-static void mail_log_action(struct mail *mail, const char *action)
-{
-	const char *msgid, *mailbox_str;
-
-	mailbox_str = mailbox_get_name(mail->box);
-	if (strcmp(mailbox_str, "INBOX") == 0) {
-		/* most operations are for INBOX, and POP3 has only INBOX,
-		   so don't add it. */
-		mailbox_str = "";
-	} else {
-		mailbox_str = str_sanitize(mailbox_str, 80);
-		mailbox_str = t_strconcat(", box=", mailbox_str, NULL);
-	}
-
-	msgid = mail_get_first_header(mail, "Message-ID");
-	i_info("%s: uid=%u, msgid=%s%s", action, mail->uid,
-	       msgid == NULL ? "(null)" : str_sanitize(msgid, MSGID_LOG_LEN),
-	       mailbox_str);
+static enum mail_log_field mail_log_field_find(const char *name)
+{
+	unsigned int i;
+
+	for (i = 0; field_names[i] != NULL; i++) {
+		if (strcmp(name, field_names[i]) == 0)
+			return 1 << i;
+	}
+	return 0;
+}
+
+static enum mail_log_event mail_log_event_find(const char *name)
+{
+	unsigned int i;
+
+	for (i = 0; event_names[i] != NULL; i++) {
+		if (strcmp(name, event_names[i]) == 0)
+			return 1 << i;
+	}
+	return 0;
+}
+
+static const char *mail_log_event_get_name(enum mail_log_event event)
+{
+	unsigned int i;
+
+	for (i = 0; event_names[i] != NULL; i++) {
+		if ((unsigned)event == (unsigned)(1 << i))
+			return event_names[i];
+	}
+	i_unreached();
+	return NULL;
+}
+
+static struct mail_log_group_changes *
+mail_log_action_get_group(struct mail_log_transaction_context *lt,
+			  enum mail_log_event event, const char *data)
+{
+	struct mail_log_group_changes *group;
+	unsigned int i, count;
+
+	if (!array_is_created(&lt->group_changes))
+		p_array_init(&lt->group_changes, lt->pool, 8);
+
+	group = array_get_modifiable(&lt->group_changes, &count);
+	for (i = 0; i < count; i++) {
+		if (group[i].event == event &&
+		    null_strcmp(data, group[i].data) == 0)
+			return &group[i];
+	}
+
+	group = array_append_space(&lt->group_changes);
+	group->event = event;
+	group->data = p_strdup(lt->pool, data);
+	return group;
+}
+
+static void
+mail_log_action_add_group(struct mail_log_transaction_context *lt,
+			  struct mail *mail, enum mail_log_event event,
+			  const char *data)
+{
+	struct mail_log_group_changes *group;
+	uoff_t size;
+
+	group = mail_log_action_get_group(lt, event, data);
+
+	if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0) {
+		if (!array_is_created(&group->uids))
+			p_array_init(&group->uids, lt->pool, 32);
+		seq_range_array_add(&group->uids, 0, mail->uid);
+	}
+
+	if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
+	    (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
+		size = mail_get_physical_size(mail);
+		if (size != (uoff_t)-1)
+			group->psize_total += size;
+	}
+
+	if ((mail_log_set.fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
+	    (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
+		size = mail_get_virtual_size(mail);
+		if (size != (uoff_t)-1)
+			group->vsize_total += size;
+	}
+}
+
+static void mail_log_append_mailbox_name(string_t *str, struct mailbox *box)
+{
+	const char *mailbox_str;
+
+	/* most operations are for INBOX, and POP3 has only INBOX,
+	   so don't add it. */
+	mailbox_str = mailbox_get_name(box);
+	if (strcmp(mailbox_str, "INBOX") != 0) {
+		str_printfa(str, "box=%s, ",
+			    str_sanitize(mailbox_str, MAILBOX_NAME_LOG_LEN));
+	}
+}
+
+static void
+mail_log_group(struct mailbox *box, const struct mail_log_group_changes *group)
+{
+	const struct seq_range *range;
+	unsigned int i, count;
+	string_t *str;
+	
+	t_push();
+
+	str = t_str_new(128);
+	str_printfa(str, "%s: ", mail_log_event_get_name(group->event));
+
+	if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0 &&
+	    array_is_created(&group->uids)) {
+		str_append(str, "uids=");
+
+		range = array_get(&group->uids, &count);
+		for (i = 0; i < count; i++) {
+			if (i != 0)
+				str_append_c(str, ',');
+
+			str_printfa(str, "%u", range[i].seq1);
+			if (range[i].seq1 != range[i].seq2)
+				str_printfa(str, "-%u", range[i].seq2);
+		}
+		str_append(str, ", ");
+	}
+
+	if ((mail_log_set.fields & MAIL_LOG_FIELD_BOX) != 0)
+		mail_log_append_mailbox_name(str, box);
+
+	if (group->event == MAIL_LOG_EVENT_COPY)
+		str_printfa(str, "dest=%s, ", group->data);
+
+	if (group->psize_total != 0)
+		str_printfa(str, "size=%"PRIuUOFF_T", ", group->psize_total);
+	if (group->vsize_total != 0)
+		str_printfa(str, "size=%"PRIuUOFF_T", ", group->vsize_total);
+	str_truncate(str, str_len(str)-2);
+
+	i_info("%s", str_c(str));
+	t_pop();
+}
+
+static void
+mail_log_group_changes(struct mailbox *box,
+		       struct mail_log_transaction_context *lt)
+{
+	const struct mail_log_group_changes *group;
+	unsigned int i, count;
+
+	group = array_get(&lt->group_changes, &count);
+	for (i = 0; i < count; i++)
+		mail_log_group(box, &group[i]);
+}
+
+static void mail_log_action(struct mail *mail, enum mail_log_event event,
+			    const char *data)
+{
+	struct mail_log_transaction_context *lt =
+		MAIL_LOG_CONTEXT(mail->transaction);
+	const char *msgid;
+	uoff_t size;
+	string_t *str;
+	pool_t pool;
+
+	if ((mail_log_set.events & event) == 0)
+		return;
+
+	if (lt == NULL) {


More information about the dovecot-cvs mailing list