From 238812433b4f7965fd662dce0f4efccb092630a8 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 5 Apr 2013 16:37:45 +0300 Subject: [PATCH] lib-index: Add timestamps and value lengths to attribute change records in transaction log. The timestamps will be useful for dsync, and value lengths will be useful for metadata quota. --- src/doveadm/doveadm-dump-log.c | 29 +++++++++++++++++-- src/lib-index/mail-index-transaction-export.c | 5 ++++ .../mail-index-transaction-private.h | 1 + src/lib-index/mail-index-transaction-update.c | 27 +++++++++++++---- src/lib-index/mail-index.h | 5 ++-- src/lib-storage/index/index-attribute.c | 7 +++-- src/plugins/acl/acl-mailbox.c | 9 ++++-- 7 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/doveadm/doveadm-dump-log.c b/src/doveadm/doveadm-dump-log.c index eb4ffa5e4e..5cdf1bc3de 100644 --- a/src/doveadm/doveadm-dump-log.c +++ b/src/doveadm/doveadm-dump-log.c @@ -421,12 +421,37 @@ static void log_record_print(const struct mail_transaction_header *hdr, } case MAIL_TRANSACTION_ATTRIBUTE_UPDATE: { const char *keys = data; - unsigned int i; + const uint32_t *extra; + unsigned int i, extra_pos, extra_count = 0; for (i = 0; i < size && keys[i] != '\0'; ) { - printf(" - %s\n", keys+i); + if (keys[i] == '+') + extra_count++; + extra_count++; i += strlen(keys+i) + 1; } + if (i % sizeof(uint32_t) != 0) + i += sizeof(uint32_t) - i%sizeof(uint32_t); + extra = (const void *)(keys+i); + + if ((size-i) != extra_count*sizeof(uint32_t)) { + printf(" - broken entry\n"); + break; + } + + extra_pos = 0; + for (i = 0; i < size && keys[i] != '\0'; ) { + printf(" - %s: %s/%s : timestamp=%s", + keys[i] == '+' ? "add" : keys[i] == '-' ? "remove" : "?", + keys[i+1] == 'p' ? "private" : + keys[i+1] == 's' ? "shared" : "?error?", + keys+i+2, unixdate2str(extra[extra_pos++])); + if (keys[i] == '+') + printf(" value_len=%u", extra[extra_pos++]); + printf("\n"); + i += strlen(keys+i) + 1; + } + break; } default: diff --git a/src/lib-index/mail-index-transaction-export.c b/src/lib-index/mail-index-transaction-export.c index 7194836aba..beaeb4a158 100644 --- a/src/lib-index/mail-index-transaction-export.c +++ b/src/lib-index/mail-index-transaction-export.c @@ -399,6 +399,11 @@ void mail_index_transaction_export(struct mail_index_transaction *t, buffer_append_zero(t->attribute_updates, 4 - t->attribute_updates->used % 4); } + /* append the timestamp and value lengths */ + buffer_append(t->attribute_updates, + t->attribute_updates_suffix->data, + t->attribute_updates_suffix->used); + i_assert(t->attribute_updates->used % 4 == 0); log_append_buffer(&ctx, t->attribute_updates, MAIL_TRANSACTION_ATTRIBUTE_UPDATE); } diff --git a/src/lib-index/mail-index-transaction-private.h b/src/lib-index/mail-index-transaction-private.h index aef4765e6e..f4fc880515 100644 --- a/src/lib-index/mail-index-transaction-private.h +++ b/src/lib-index/mail-index-transaction-private.h @@ -71,6 +71,7 @@ struct mail_index_transaction { ARRAY(struct mail_index_transaction_keyword_update) keyword_updates; buffer_t *attribute_updates; /* [+-][ps]key\0.. */ + buffer_t *attribute_updates_suffix; /* [].. */ uint64_t min_highest_modseq; uint64_t max_modseq; diff --git a/src/lib-index/mail-index-transaction-update.c b/src/lib-index/mail-index-transaction-update.c index 75e49f09ab..f7887bf0c9 100644 --- a/src/lib-index/mail-index-transaction-update.c +++ b/src/lib-index/mail-index-transaction-update.c @@ -78,6 +78,8 @@ void mail_index_transaction_reset_v(struct mail_index_transaction *t) array_free(&t->ext_reset_atomic); if (t->attribute_updates != NULL) buffer_free(&t->attribute_updates); + if (t->attribute_updates_suffix != NULL) + buffer_free(&t->attribute_updates_suffix); t->first_new_seq = mail_index_view_get_messages_count(t->view)+1; t->last_new_seq = 0; @@ -652,26 +654,39 @@ void mail_index_update_flags(struct mail_index_transaction *t, uint32_t seq, static void mail_index_attribute_set_full(struct mail_index_transaction *t, - const char *key, bool pvt, char prefix) + const char *key, bool pvt, char prefix, + time_t timestamp, uint32_t value_len) { - if (t->attribute_updates == NULL) + uint32_t ts = timestamp; + + if (t->attribute_updates == NULL) { t->attribute_updates = buffer_create_dynamic(default_pool, 64); + t->attribute_updates_suffix = buffer_create_dynamic(default_pool, 64); + } buffer_append_c(t->attribute_updates, prefix); buffer_append_c(t->attribute_updates, pvt ? 'p' : 's'); buffer_append(t->attribute_updates, key, strlen(key)+1); + + buffer_append(t->attribute_updates_suffix, &ts, sizeof(ts)); + if (prefix == '+') { + buffer_append(t->attribute_updates_suffix, + &value_len, sizeof(value_len)); + } t->log_updates = TRUE; } void mail_index_attribute_set(struct mail_index_transaction *t, - bool pvt, const char *key) + bool pvt, const char *key, + time_t timestamp, uint32_t value_len) { - mail_index_attribute_set_full(t, key, pvt, '+'); + mail_index_attribute_set_full(t, key, pvt, '+', timestamp, value_len); } void mail_index_attribute_unset(struct mail_index_transaction *t, - bool pvt, const char *key) + bool pvt, const char *key, + time_t timestamp) { - mail_index_attribute_set_full(t, key, pvt, '-'); + mail_index_attribute_set_full(t, key, pvt, '-', timestamp, 0); } void mail_index_update_header(struct mail_index_transaction *t, diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h index 2495559026..1a108434d1 100644 --- a/src/lib-index/mail-index.h +++ b/src/lib-index/mail-index.h @@ -468,10 +468,11 @@ void mail_index_update_flags_range(struct mail_index_transaction *t, change gets assigned its own modseq and any log readers can find out about this change. */ void mail_index_attribute_set(struct mail_index_transaction *t, - bool pvt, const char *key); + bool pvt, const char *key, + time_t timestamp, uint32_t value_len); /* Attribute was deleted. */ void mail_index_attribute_unset(struct mail_index_transaction *t, - bool pvt, const char *key); + bool pvt, const char *key, time_t timestamp); /* Update message's modseq to be at least min_modseq. */ void mail_index_update_modseq(struct mail_index_transaction *t, uint32_t seq, uint64_t min_modseq); diff --git a/src/lib-storage/index/index-attribute.c b/src/lib-storage/index/index-attribute.c index 5c53c0c431..72226e5d45 100644 --- a/src/lib-storage/index/index-attribute.c +++ b/src/lib-storage/index/index-attribute.c @@ -1,6 +1,7 @@ /* Copyright (c) 2013 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "ioloop.h" #include "dict.h" #include "index-storage.h" @@ -179,6 +180,7 @@ int index_storage_attribute_set(struct mailbox_transaction_context *t, struct dict_transaction_context *dtrans; const char *mailbox_prefix; bool pvt = type == MAIL_ATTRIBUTE_TYPE_PRIVATE; + time_t ts = value->last_change != 0 ? value->last_change : ioloop_time; int ret = 0; if (strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT, @@ -202,10 +204,11 @@ int index_storage_attribute_set(struct mailbox_transaction_context *t, ret = -1; } else if (value_str != NULL) { dict_set(dtrans, prefixed_key, value_str); - mail_index_attribute_set(t->itrans, pvt, key); + mail_index_attribute_set(t->itrans, pvt, key, + ts, strlen(value_str)); } else { dict_unset(dtrans, prefixed_key); - mail_index_attribute_unset(t->itrans, pvt, key); + mail_index_attribute_unset(t->itrans, pvt, key, ts); } } T_END; return ret; diff --git a/src/plugins/acl/acl-mailbox.c b/src/plugins/acl/acl-mailbox.c index ee6c1c34e5..6ed4bc9dd9 100644 --- a/src/plugins/acl/acl-mailbox.c +++ b/src/plugins/acl/acl-mailbox.c @@ -6,6 +6,7 @@ problem actually exists when opening read-only mailboxes. */ #include "lib.h" #include "array.h" +#include "ioloop.h" #include "istream.h" #include "mailbox-list-private.h" #include "acl-api-private.h" @@ -620,6 +621,8 @@ int acl_mailbox_update_acl(struct mailbox_transaction_context *t, { struct acl_object *aclobj; const char *key; + time_t ts = update->last_change != 0 ? + update->last_change : ioloop_time; key = t_strdup_printf(MAILBOX_ATTRIBUTE_PREFIX_ACL"%s", acl_rights_get_id(&update->rights)); @@ -629,9 +632,11 @@ int acl_mailbox_update_acl(struct mailbox_transaction_context *t, return -1; } + /* FIXME: figure out some value lengths, so maybe some day + quota could apply to ACLs as well. */ if (acl_mailbox_update_removed_id(aclobj, update)) - mail_index_attribute_unset(t->itrans, FALSE, key); + mail_index_attribute_unset(t->itrans, FALSE, key, ts); else - mail_index_attribute_set(t->itrans, FALSE, key); + mail_index_attribute_set(t->itrans, FALSE, key, ts, 0); return 0; } -- 2.47.3