]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-index: mail_index_attribute_[un]set() adds changed attributes' keys to transactio...
authorTimo Sirainen <tss@iki.fi>
Thu, 14 Mar 2013 13:29:18 +0000 (15:29 +0200)
committerTimo Sirainen <tss@iki.fi>
Thu, 14 Mar 2013 13:29:18 +0000 (15:29 +0200)
This provides them both a modseq (so their changes become visible) as well
as an efficient way to see what attributes have changed by reading the
transaction log. The values themselves aren't written to the log, because
they could be large.

src/doveadm/doveadm-dump-log.c
src/lib-index/mail-index-modseq.c
src/lib-index/mail-index-sync-update.c
src/lib-index/mail-index-transaction-export.c
src/lib-index/mail-index-transaction-private.h
src/lib-index/mail-index-transaction-update.c
src/lib-index/mail-index.h
src/lib-index/mail-transaction-log-file.c
src/lib-index/mail-transaction-log-view.c
src/lib-index/mail-transaction-log.h

index 429b9acc386f86a42c19314d23b4270ca5ed8146..eb4ffa5e4e7e3ff7e1b18f78e556a9b8e957add1 100644 (file)
@@ -52,6 +52,7 @@ mail_transaction_header_has_modseq(const struct mail_transaction_header *hdr)
        case MAIL_TRANSACTION_FLAG_UPDATE:
        case MAIL_TRANSACTION_KEYWORD_UPDATE:
        case MAIL_TRANSACTION_KEYWORD_RESET:
+       case MAIL_TRANSACTION_ATTRIBUTE_UPDATE:
                /* these changes increase modseq */
                return TRUE;
        }
@@ -114,6 +115,9 @@ static const char *log_record_type(unsigned int type)
        case MAIL_TRANSACTION_BOUNDARY:
                name = "boundary";
                break;
+       case MAIL_TRANSACTION_ATTRIBUTE_UPDATE:
+               name = "attribute-update";
+               break;
        default:
                name = t_strdup_printf("unknown: %x", type);
                break;
@@ -415,6 +419,16 @@ static void log_record_print(const struct mail_transaction_header *hdr,
                printf(" - size=%u\n", rec->size);
                break;
        }
+       case MAIL_TRANSACTION_ATTRIBUTE_UPDATE: {
+               const char *keys = data;
+               unsigned int i;
+
+               for (i = 0; i < size && keys[i] != '\0'; ) {
+                       printf(" - %s\n", keys+i);
+                       i += strlen(keys+i) + 1;
+               }
+               break;
+       }
        default:
                break;
        }
index 2114f04561417acf18352bd3b8ee7dfdff832eb4..75aecf32558feb1625dff6dc4d2c24bb62d12236 100644 (file)
@@ -335,6 +335,7 @@ mail_index_modseq_update_old_rec(struct mail_index_modseq_sync *ctx,
        buffer_t uid_buf;
        unsigned int i, count;
        uint32_t seq1, seq2;
+       uint64_t modseq;
 
        switch (thdr->type & MAIL_TRANSACTION_TYPE_MASK) {
        case MAIL_TRANSACTION_APPEND: {
@@ -374,12 +375,19 @@ mail_index_modseq_update_old_rec(struct mail_index_modseq_sync *ctx,
                array_create_from_buffer(&uids, &uid_buf,
                        sizeof(struct mail_transaction_keyword_reset));
                break;
+       case MAIL_TRANSACTION_ATTRIBUTE_UPDATE:
+               break;
        default:
                return;
        }
 
+       /* update highestmodseq regardless of whether any mails were updated */
+       modseq = mail_transaction_log_view_get_prev_modseq(ctx->log_view);
+       if (modseq > ctx->highest_modseq)
+               ctx->highest_modseq = modseq;
+
        /* update modseqs */
-       count = array_count(&uids);
+       count = array_is_created(&uids) ? array_count(&uids) : 0;
        for (i = 0; i < count; i++) {
                rec = array_idx(&uids, i);
                if (mail_index_lookup_seq_range(ctx->view, rec->seq1, rec->seq2,
index b206b58080fc78315ac1e1e9d7fdef9260ed082d..986d3a1b221b7cbd176a505e6fd3cd60b6e3b4a3 100644 (file)
@@ -495,6 +495,7 @@ mail_index_sync_record_real(struct mail_index_sync_map_ctx *ctx,
                            const struct mail_transaction_header *hdr,
                            const void *data)
 {
+       uint64_t modseq;
        int ret = 0;
 
        switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
@@ -767,6 +768,10 @@ mail_index_sync_record_real(struct mail_index_sync_map_ctx *ctx,
                break;
        case MAIL_TRANSACTION_BOUNDARY:
                break;
+       case MAIL_TRANSACTION_ATTRIBUTE_UPDATE:
+               modseq = mail_transaction_log_view_get_prev_modseq(ctx->view->log_view);
+               mail_index_modseq_update_highest(ctx->modseq_ctx, modseq);
+               break;
        default:
                mail_index_sync_set_corrupted(ctx,
                        "Unknown transaction record type 0x%x",
index 2a8801c0d0c8091a33a955f97bfeb924196d8022..7194836abaaeffd8d1556d6dcbff240a82ec85a3 100644 (file)
@@ -393,6 +393,15 @@ void mail_index_transaction_export(struct mail_index_transaction *t,
                log_append_buffer(&ctx, log_get_hdr_update_buffer(t, TRUE),
                                  MAIL_TRANSACTION_HEADER_UPDATE);
        }
+       if (t->attribute_updates != NULL) {
+               /* need to have 32bit alignment */
+               if (t->attribute_updates->used % 4 != 0) {
+                       buffer_append_zero(t->attribute_updates,
+                                          4 - t->attribute_updates->used % 4);
+               }
+               log_append_buffer(&ctx, t->attribute_updates,
+                                 MAIL_TRANSACTION_ATTRIBUTE_UPDATE);
+       }
        if (array_is_created(&t->appends)) {
                change_mask |= MAIL_INDEX_FSYNC_MASK_APPENDS;
                log_append_buffer(&ctx, t->appends.arr.buffer,
index 9816a33e3e603740d39b5d97e28ec15ea7d69786..aef4765e6ef3116980377768087f719d69aa48ff 100644 (file)
@@ -70,6 +70,7 @@ struct mail_index_transaction {
        ARRAY(uint32_t) ext_reset_atomic;
 
        ARRAY(struct mail_index_transaction_keyword_update) keyword_updates;
+       buffer_t *attribute_updates; /* [+-][ps]key\0.. */
 
        uint64_t min_highest_modseq;
        uint64_t max_modseq;
index 03ebed55af2e35af8e9f38474bab18ccc782ba4b..e5a4c318b98e257b9e5db89539772cff544c94a7 100644 (file)
@@ -76,6 +76,8 @@ void mail_index_transaction_reset_v(struct mail_index_transaction *t)
                array_free(&t->ext_reset_ids);
        if (array_is_created(&t->ext_reset_atomic))
                array_free(&t->ext_reset_atomic);
+       if (t->attribute_updates != NULL)
+               buffer_free(&t->attribute_updates);
 
        t->first_new_seq = mail_index_view_get_messages_count(t->view)+1;
        t->last_new_seq = 0;
@@ -106,6 +108,7 @@ void mail_index_transaction_set_log_updates(struct mail_index_transaction *t)
                array_is_created(&t->modseq_updates) ||
                array_is_created(&t->expunges) ||
                array_is_created(&t->keyword_updates) ||
+               t->attribute_updates != NULL ||
                t->pre_hdr_changed || t->post_hdr_changed ||
                t->min_highest_modseq != 0;
 }
@@ -647,6 +650,30 @@ void mail_index_update_flags(struct mail_index_transaction *t, uint32_t seq,
        mail_index_update_flags_range(t, seq, seq, modify_type, flags);
 }
 
+static void
+mail_index_attribute_set_full(struct mail_index_transaction *t,
+                             const char *key, bool pvt, char prefix)
+{
+       if (t->attribute_updates == NULL)
+               t->attribute_updates = 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);
+       t->log_updates = TRUE;
+}
+
+void mail_index_attribute_set(struct mail_index_transaction *t,
+                             bool pvt, const char *key)
+{
+       mail_index_attribute_set_full(t, key, pvt, '+');
+}
+
+void mail_index_attribute_unset(struct mail_index_transaction *t,
+                               bool pvt, const char *key)
+{
+       mail_index_attribute_set_full(t, key, pvt, '-');
+}
+
 void mail_index_update_header(struct mail_index_transaction *t,
                              size_t offset, const void *data, size_t size,
                              bool prepend)
index 570bdc25c55569973e6b5462bb01e4ac14318c86..2495559026c918a23e8bad6849559c9728db8dd4 100644 (file)
@@ -464,6 +464,14 @@ void mail_index_update_flags_range(struct mail_index_transaction *t,
                                   uint32_t seq1, uint32_t seq2,
                                   enum modify_type modify_type,
                                   enum mail_flags flags);
+/* Specified attribute's value was changed. This is just a notification so the
+   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);
+/* Attribute was deleted. */
+void mail_index_attribute_unset(struct mail_index_transaction *t,
+                               bool pvt, const char *key);
 /* 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);
index 9de8a5c04bc7974e1eae23cceecd4026b6a2fd81..4e0bcfa4d73128e76dc214a86a68911e7b929a79 100644 (file)
@@ -1022,6 +1022,7 @@ void mail_transaction_update_modseq(const struct mail_transaction_header *hdr,
        case MAIL_TRANSACTION_FLAG_UPDATE:
        case MAIL_TRANSACTION_KEYWORD_UPDATE:
        case MAIL_TRANSACTION_KEYWORD_RESET:
+       case MAIL_TRANSACTION_ATTRIBUTE_UPDATE:
                /* these changes increase modseq */
                *cur_modseq += 1;
                break;
index 78b7673922dee10bb61606eb5aab4f33cf4084a8..60f594e4d864f5143e0b21646125a544bb5668a1 100644 (file)
@@ -608,6 +608,40 @@ log_view_is_record_valid(struct mail_transaction_log_file *file,
                        if ((i % 4) != 0)
                                i += 4 - (i % 4);
                }
+               break;
+       }
+       case MAIL_TRANSACTION_ATTRIBUTE_UPDATE: {
+               const char *attr_changes = data;
+               unsigned int i;
+
+               for (i = 0; i+2 < rec_size && attr_changes[i] != '\0'; ) {
+                       if (attr_changes[i] != '+' && attr_changes[i] != '-') {
+                               mail_transaction_log_file_set_corrupted(file,
+                                       "attribute update: Invalid prefix 0x%02x",
+                                       attr_changes[i]);
+                               return FALSE;
+                       }
+                       i++;
+                       if (attr_changes[i] != 'p' && attr_changes[i] != 's') {
+                               mail_transaction_log_file_set_corrupted(file,
+                                       "attribute update: Invalid type 0x%02x",
+                                       attr_changes[i]);
+                               return FALSE;
+                       }
+                       i++;
+                       if (attr_changes[i] == '\0') {
+                               mail_transaction_log_file_set_corrupted(file,
+                                       "attribute update: Empty key");
+                               return FALSE;
+                       }
+                       i += strlen(attr_changes+i) + 1;
+               }
+               if (i == 0 || (i < rec_size && attr_changes[i] != '\0')) {
+                       mail_transaction_log_file_set_corrupted(file,
+                               "attribute update doesn't end with NUL");
+                       return FALSE;
+               }
+               break;
        }
        default:
                break;
index ee43222b786693f3ad6ed9302f2e07de075c06b6..69e9b7139d46221569b8789de933d0bda59e6df6 100644 (file)
@@ -44,8 +44,9 @@ enum mail_transaction_type {
        MAIL_TRANSACTION_INDEX_DELETED          = 0x00020000,
        MAIL_TRANSACTION_INDEX_UNDELETED        = 0x00040000,
        MAIL_TRANSACTION_BOUNDARY               = 0x00080000,
+       MAIL_TRANSACTION_ATTRIBUTE_UPDATE       = 0x00100000,
 
-       MAIL_TRANSACTION_TYPE_MASK              = 0x000fffff,
+       MAIL_TRANSACTION_TYPE_MASK              = 0x0fffffff,
 
 #define MAIL_TRANSACTION_EXT_MASK \
        (MAIL_TRANSACTION_EXT_INTRO | MAIL_TRANSACTION_EXT_RESET | \