]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-lda: Fixed duplicate database to work with multiple users per process.
authorTimo Sirainen <tss@iki.fi>
Fri, 23 Oct 2009 02:01:43 +0000 (22:01 -0400)
committerTimo Sirainen <tss@iki.fi>
Fri, 23 Oct 2009 02:01:43 +0000 (22:01 -0400)
--HG--
branch : HEAD

src/lda/main.c
src/lib-lda/duplicate.c
src/lib-lda/duplicate.h
src/lib-lda/mail-deliver.c
src/lib-lda/mail-deliver.h

index 435be379186ac3197b0e5692a0c9a58689783935..e2d095d0e4c5560d142686783f9727e827754b48 100644 (file)
@@ -24,7 +24,6 @@
 #include "raw-storage.h"
 #include "mail-deliver.h"
 #include "mail-send.h"
-#include "duplicate.h"
 #include "mbox-from.h"
 #include "lda-settings.h"
 
@@ -393,7 +392,6 @@ int main(int argc, char *argv[])
         lib_signals_ignore(SIGXFSZ, TRUE);
 #endif
        ctx.set = mail_storage_service_user_get_set(service_user)[1];
-        duplicate_init(mail_user_set_get_storage_set(ctx.dest_user));
 
        /* create a separate mail user for the internal namespace */
        if (master_service_set(master_service,
@@ -491,7 +489,6 @@ int main(int argc, char *argv[])
 
        mail_user_unref(&ctx.dest_user);
        mail_user_unref(&raw_mail_user);
-       duplicate_deinit();
        pool_unref(&ctx.pool);
 
        mail_storage_service_user_free(&service_user);
index fd88c68ba83cf297e1272da80b45b537b7ef2ba4..0ab52f12cac1c01c9fc016a20bf2a1e9baec609d 100644 (file)
@@ -7,6 +7,7 @@
 #include "home-expand.h"
 #include "file-dotlock.h"
 #include "hash.h"
+#include "mail-user.h"
 #include "mail-storage-settings.h"
 #include "duplicate.h"
 
@@ -14,7 +15,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-#define DUPLICATE_PATH "~/.dovecot.lda-dupes"
+#define DUPLICATE_FNAME ".dovecot.lda-dupes"
 #define COMPRESS_PERCENTAGE 10
 #define DUPLICATE_BUFSIZE 4096
 #define DUPLICATE_VERSION 2
@@ -47,7 +48,13 @@ struct duplicate_file {
        unsigned int changed:1;
 };
 
-static struct dotlock_settings duplicate_dotlock_set = {
+struct duplicate_context {
+       char *path;
+       struct dotlock_settings dotlock_set;
+       struct duplicate_file *file;
+};
+
+static const struct dotlock_settings default_duplicate_dotlock_set = {
        MEMBER(temp_prefix) NULL,
        MEMBER(lock_suffix) NULL,
 
@@ -59,7 +66,6 @@ static struct dotlock_settings duplicate_dotlock_set = {
 
        MEMBER(use_excl_lock) FALSE
 };
-static struct duplicate_file *duplicate_file = NULL;
 
 static int duplicate_cmp(const void *p1, const void *p2)
 {
@@ -200,7 +206,7 @@ static int duplicate_read(struct duplicate_file *file)
        return 0;
 }
 
-static struct duplicate_file *duplicate_new(const char *path)
+static struct duplicate_file *duplicate_file_new(struct duplicate_context *ctx)
 {
        struct duplicate_file *file;
        pool_t pool;
@@ -209,18 +215,18 @@ static struct duplicate_file *duplicate_new(const char *path)
 
        file = p_new(pool, struct duplicate_file, 1);
        file->pool = pool;
-       file->path = p_strdup(pool, path);
-       file->new_fd = file_dotlock_open(&duplicate_dotlock_set, path, 0,
+       file->path = p_strdup(pool, ctx->path);
+       file->new_fd = file_dotlock_open(&ctx->dotlock_set, file->path, 0,
                                         &file->dotlock);
        if (file->new_fd == -1)
-               i_error("file_dotlock_create(%s) failed: %m", path);
+               i_error("file_dotlock_create(%s) failed: %m", file->path);
        file->hash = hash_table_create(default_pool, pool, 0,
                                       duplicate_hash, duplicate_cmp);
        (void)duplicate_read(file);
        return file;
 }
 
-static void duplicate_free(struct duplicate_file **_file)
+static void duplicate_file_free(struct duplicate_file **_file)
 {
        struct duplicate_file *file = *_file;
 
@@ -232,52 +238,54 @@ static void duplicate_free(struct duplicate_file **_file)
        pool_unref(&file->pool);
 }
 
-int duplicate_check(const void *id, size_t id_size, const char *user)
+int duplicate_check(struct duplicate_context *ctx,
+                   const void *id, size_t id_size, const char *user)
 {
        struct duplicate d;
 
-       if (duplicate_file == NULL)
-               duplicate_file = duplicate_new(home_expand(DUPLICATE_PATH));
+       if (ctx->file == NULL)
+               ctx->file = duplicate_file_new(ctx);
 
        d.id = id;
        d.id_size = id_size;
        d.user = user;
 
-       return hash_table_lookup(duplicate_file->hash, &d) != NULL;
+       return hash_table_lookup(ctx->file->hash, &d) != NULL;
 }
 
-void duplicate_mark(const void *id, size_t id_size,
+void duplicate_mark(struct duplicate_context *ctx,
+                   const void *id, size_t id_size,
                     const char *user, time_t timestamp)
 {
        struct duplicate *d;
        void *new_id;
 
-       if (duplicate_file == NULL)
-               duplicate_file = duplicate_new(home_expand(DUPLICATE_PATH));
+       if (ctx->file == NULL)
+               ctx->file = duplicate_file_new(ctx);
 
-       new_id = p_malloc(duplicate_file->pool, id_size);
+       new_id = p_malloc(ctx->file->pool, id_size);
        memcpy(new_id, id, id_size);
 
-       d = p_new(duplicate_file->pool, struct duplicate, 1);
+       d = p_new(ctx->file->pool, struct duplicate, 1);
        d->id = new_id;
        d->id_size = id_size;
-       d->user = p_strdup(duplicate_file->pool, user);
+       d->user = p_strdup(ctx->file->pool, user);
        d->time = timestamp;
 
-       duplicate_file->changed = TRUE;
-       hash_table_insert(duplicate_file->hash, d, d);
+       ctx->file->changed = TRUE;
+       hash_table_insert(ctx->file->hash, d, d);
 }
 
-void duplicate_flush(void)
+void duplicate_flush(struct duplicate_context *ctx)
 {
-       struct duplicate_file *file = duplicate_file;
+       struct duplicate_file *file = ctx->file;
        struct duplicate_file_header hdr;
        struct duplicate_record_header rec;
        struct ostream *output;
         struct hash_iterate_context *iter;
        void *key, *value;
 
-       if (duplicate_file == NULL || !file->changed || file->new_fd == -1)
+       if (file == NULL || !file->changed || file->new_fd == -1)
                return;
 
        memset(&hdr, 0, sizeof(hdr));
@@ -308,16 +316,34 @@ void duplicate_flush(void)
        file->new_fd = -1;
 }
 
-void duplicate_init(const struct mail_storage_settings *set)
+struct duplicate_context *duplicate_init(struct mail_user *user)
 {
-       duplicate_dotlock_set.use_excl_lock = set->dotlock_use_excl;
-       duplicate_dotlock_set.nfs_flush = set->mail_nfs_storage;
+       struct duplicate_context *ctx;
+       const struct mail_storage_settings *mail_set;
+       const char *home;
+
+       if (mail_user_get_home(user, &home) < 0)
+               i_fatal("User %s doesn't have home dir set", user->username);
+
+       ctx = i_new(struct duplicate_context, 1);
+       ctx->path = i_strconcat(home, "/"DUPLICATE_FNAME, NULL);
+       ctx->dotlock_set = default_duplicate_dotlock_set;
+
+       mail_set = mail_user_set_get_storage_set(user);
+       ctx->dotlock_set.use_excl_lock = mail_set->dotlock_use_excl;
+       ctx->dotlock_set.nfs_flush = mail_set->mail_nfs_storage;
+       return ctx;
 }
 
-void duplicate_deinit(void)
+void duplicate_deinit(struct duplicate_context **_ctx)
 {
-       if (duplicate_file != NULL) {
-               duplicate_flush();
-               duplicate_free(&duplicate_file);
+       struct duplicate_context *ctx = *_ctx;
+
+       *_ctx = NULL;
+       if (ctx->file != NULL) {
+               duplicate_flush(ctx);
+               duplicate_file_free(&ctx->file);
        }
+       i_free(ctx->path);
+       i_free(ctx);
 }
index 5e8745376c3e9b0abadddfd7339ec65cbae5993f..b9551ad6cdb5f1d62f2d61f315992fa5f3f76248 100644 (file)
@@ -1,17 +1,20 @@
 #ifndef DUPLICATE_H
 #define DUPLICATE_H
 
+struct duplicate_context;
 struct mail_storage_settings;
 
 #define DUPLICATE_DEFAULT_KEEP (3600 * 24)
 
-int duplicate_check(const void *id, size_t id_size, const char *user);
-void duplicate_mark(const void *id, size_t id_size,
+int duplicate_check(struct duplicate_context *ctx,
+                   const void *id, size_t id_size, const char *user);
+void duplicate_mark(struct duplicate_context *ctx,
+                   const void *id, size_t id_size,
                     const char *user, time_t timestamp);
 
-void duplicate_flush(void);
+void duplicate_flush(struct duplicate_context *ctx);
 
-void duplicate_init(const struct mail_storage_settings *set);
-void duplicate_deinit(void);
+struct duplicate_context *duplicate_init(struct mail_user *user);
+void duplicate_deinit(struct duplicate_context **ctx);
 
 #endif
index 58d427a68b07da173031311ad5e348b5942c80a3..2a55c131d8bfbf6795bdd159f2fbfea4fba685a1 100644 (file)
@@ -10,6 +10,7 @@
 #include "lda-settings.h"
 #include "mail-storage.h"
 #include "mail-namespace.h"
+#include "duplicate.h"
 #include "mail-deliver.h"
 
 deliver_mail_func_t *deliver_mail = NULL;
@@ -247,6 +248,7 @@ int mail_deliver(struct mail_deliver_context *ctx,
        if (deliver_mail == NULL)
                ret = -1;
        else {
+               ctx->dup_ctx = duplicate_init(ctx->dest_user);
                if (deliver_mail(ctx, storage_r) <= 0) {
                        /* if message was saved, don't bounce it even though
                           the script failed later. */
@@ -255,6 +257,7 @@ int mail_deliver(struct mail_deliver_context *ctx,
                        /* success. message may or may not have been saved. */
                        ret = 0;
                }
+               duplicate_deinit(&ctx->dup_ctx);
        }
 
        if (ret < 0 && !ctx->tried_default_save) {
index 64df09a2e0c0715a696cd586c66d62e0f5137aba..7da440b4c95e16aad9020178dcbe61f5115da316 100644 (file)
@@ -8,6 +8,8 @@ struct mail_deliver_context {
        pool_t pool;
        const struct lda_settings *set;
 
+       struct duplicate_context *dup_ctx;
+
        /* Mail to save */
        struct mail *src_mail;
        /* Envelope sender, if known. */