]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
file_dotlock_open/delete/replace now has lock_suffix parameter. NULL
authorTimo Sirainen <tss@iki.fi>
Mon, 3 May 2004 22:08:26 +0000 (01:08 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 3 May 2004 22:08:26 +0000 (01:08 +0300)
defaults to ".lock".

Fixed dotlocking transaction log.

--HG--
branch : HEAD

src/lib-index/mail-transaction-log-private.h
src/lib-index/mail-transaction-log.c
src/lib-storage/index/maildir/maildir-uidlist.c
src/lib-storage/subscription-file/subscription-file.c
src/lib/file-dotlock.c
src/lib/file-dotlock.h

index 256789e18d8b6325a7f0c2fd5b9b8bbdcb5cc60f..d749300bee128655e7fe3bdb09a31177e1eb2caa 100644 (file)
@@ -13,7 +13,6 @@ struct mail_transaction_log_file {
        char *filepath;
        int fd;
        int lock_type;
-       struct dotlock dotlock;
 
        ino_t st_ino;
        dev_t st_dev;
@@ -30,6 +29,9 @@ struct mail_transaction_log {
        struct mail_index *index;
         struct mail_transaction_log_view *views;
        struct mail_transaction_log_file *head, *tail;
+
+       unsigned int dotlock_count;
+       struct dotlock dotlock;
 };
 
 void
index dbb7ab0bebfa039726c49238194216a4199abdc2..b6518ee32b30a4619beb997c06dc75596ab91d6e 100644 (file)
@@ -144,13 +144,16 @@ mail_transaction_log_file_dotlock(struct mail_transaction_log_file *file,
        int ret;
 
        if (lock_type == F_UNLCK) {
-               ret = file_unlock_dotlock(file->filepath, &file->dotlock);
+               file->lock_type = F_UNLCK;
+               if (--file->log->dotlock_count > 0)
+                       return 0;
+
+               ret = file_unlock_dotlock(file->filepath, &file->log->dotlock);
                if (ret < 0) {
                        mail_index_file_set_syscall_error(file->log->index,
                                file->filepath, "file_unlock_dotlock()");
                        return -1;
                }
-               file->lock_type = F_UNLCK;
 
                if (ret == 0) {
                        mail_index_set_error(file->log->index,
@@ -161,13 +164,18 @@ mail_transaction_log_file_dotlock(struct mail_transaction_log_file *file,
                return 0;
        }
 
-       ret = file_lock_dotlock(file->filepath, NULL, FALSE,
-                               LOG_DOTLOCK_TIMEOUT,
-                               LOG_DOTLOCK_STALE_TIMEOUT,
-                               LOG_DOTLOCK_IMMEDIATE_STALE_TIMEOUT,
-                               NULL, NULL, &file->dotlock);
+       if (file->log->dotlock_count > 0)
+               ret = 1;
+       else {
+               ret = file_lock_dotlock(file->filepath, NULL, FALSE,
+                                       LOG_DOTLOCK_TIMEOUT,
+                                       LOG_DOTLOCK_STALE_TIMEOUT,
+                                       LOG_DOTLOCK_IMMEDIATE_STALE_TIMEOUT,
+                                       NULL, NULL, &file->log->dotlock);
+       }
        if (ret > 0) {
-               file->lock_type = F_WRLCK;
+               file->log->dotlock_count++;
+               file->lock_type = F_WRLCK;
                return 0;
        }
        if (ret < 0) {
@@ -311,12 +319,16 @@ static int
 mail_transaction_log_file_create(struct mail_transaction_log *log,
                                 const char *path, dev_t dev, ino_t ino)
 {
+#define LOG_NEW_DOTLOCK_SUFFIX ".newlock"
        struct mail_index *index = log->index;
        struct mail_transaction_log_header hdr;
        struct stat st;
        int fd, fd2, ret;
 
-       fd = file_dotlock_open(path, NULL, LOG_DOTLOCK_TIMEOUT,
+       /* With dotlocking we might already have path.lock created, so this
+          filename has to be different. */
+       fd = file_dotlock_open(path, NULL, LOG_NEW_DOTLOCK_SUFFIX,
+                              LOG_DOTLOCK_TIMEOUT,
                               LOG_DOTLOCK_STALE_TIMEOUT,
                               LOG_DOTLOCK_IMMEDIATE_STALE_TIMEOUT, NULL, NULL);
        if (fd == -1) {
@@ -334,7 +346,8 @@ mail_transaction_log_file_create(struct mail_transaction_log *log,
                } else if (st.st_dev == dev && st.st_ino == ino) {
                        /* same file, still broken */
                } else {
-                       (void)file_dotlock_delete(path, fd2);
+                       (void)file_dotlock_delete(path, LOG_NEW_DOTLOCK_SUFFIX,
+                                                 fd2);
                        return fd2;
                }
 
@@ -364,19 +377,20 @@ mail_transaction_log_file_create(struct mail_transaction_log *log,
        }
 
        if (write_full(fd, &hdr, sizeof(hdr)) < 0) {
-               mail_index_file_set_syscall_error(index, path, "write_full()");
-                (void)file_dotlock_delete(path, fd);
+               mail_index_file_set_syscall_error(index, path,
+                                                 "write_full()");
+                (void)file_dotlock_delete(path, LOG_NEW_DOTLOCK_SUFFIX, fd);
                return -1;
        }
 
        fd2 = dup(fd);
        if (fd2 < 0) {
                mail_index_file_set_syscall_error(index, path, "dup()");
-                (void)file_dotlock_delete(path, fd);
+                (void)file_dotlock_delete(path, LOG_NEW_DOTLOCK_SUFFIX, fd);
                return -1;
        }
 
-       if (file_dotlock_replace(path, fd, FALSE) <= 0)
+       if (file_dotlock_replace(path, LOG_NEW_DOTLOCK_SUFFIX, fd, FALSE) <= 0)
                return -1;
 
        /* success */
index e15b1f6a546e545fdd7c52948ff0a94bce1d05b6..0a58f2b52089c29f5470c992d78a9941aea81af4 100644 (file)
@@ -77,8 +77,8 @@ int maildir_uidlist_try_lock(struct maildir_uidlist *uidlist)
        path = t_strconcat(uidlist->ibox->control_dir,
                           "/" MAILDIR_UIDLIST_NAME, NULL);
         old_mask = umask(0777 & ~uidlist->ibox->mail_create_mode);
-       fd = file_dotlock_open(path, NULL, 0, 0, UIDLIST_LOCK_STALE_TIMEOUT,
-                              NULL, NULL);
+       fd = file_dotlock_open(path, NULL, NULL, 0, 0,
+                              UIDLIST_LOCK_STALE_TIMEOUT, NULL, NULL);
        umask(old_mask);
        if (fd == -1) {
                if (errno == EAGAIN)
@@ -101,7 +101,7 @@ void maildir_uidlist_unlock(struct maildir_uidlist *uidlist)
 
        path = t_strconcat(uidlist->ibox->control_dir,
                           "/" MAILDIR_UIDLIST_NAME, NULL);
-       (void)file_dotlock_delete(path, uidlist->lock_fd);
+       (void)file_dotlock_delete(path, NULL, uidlist->lock_fd);
        uidlist->lock_fd = -1;
 }
 
@@ -482,7 +482,7 @@ static int maildir_uidlist_rewrite(struct maildir_uidlist *uidlist)
                db_path = t_strconcat(ibox->control_dir,
                                      "/" MAILDIR_UIDLIST_NAME, NULL);
 
-               if (file_dotlock_replace(db_path, uidlist->lock_fd,
+               if (file_dotlock_replace(db_path, NULL, uidlist->lock_fd,
                                         FALSE) <= 0) {
                        mail_storage_set_critical(ibox->box.storage,
                                "file_dotlock_replace(%s) failed: %m", db_path);
index e819b3f8ad8ec88a26dc48e3575a2424b8999e3b..44312e9bceb48dc7b247f00eb58c2f7278d7b154 100644 (file)
@@ -79,7 +79,8 @@ int subsfile_set_subscribed(struct mail_storage *storage, const char *path,
                name = "INBOX";
 
        /* FIXME: set lock notification callback */
-       fd_out = file_dotlock_open(path, NULL, SUBSCRIPTION_FILE_LOCK_TIMEOUT,
+       fd_out = file_dotlock_open(path, NULL, NULL,
+                                  SUBSCRIPTION_FILE_LOCK_TIMEOUT,
                                   SUBSCRIPTION_FILE_CHANGE_TIMEOUT,
                                   SUBSCRIPTION_FILE_IMMEDIATE_TIMEOUT,
                                   NULL, NULL);
@@ -97,7 +98,7 @@ int subsfile_set_subscribed(struct mail_storage *storage, const char *path,
        fd_in = open(path, O_RDONLY);
        if (fd_in == -1 && errno != ENOENT) {
                subsfile_set_syscall_error(storage, "open()", path);
-               file_dotlock_delete(path, fd_out);
+               file_dotlock_delete(path, NULL, fd_out);
                return -1;
        }
 
@@ -137,13 +138,13 @@ int subsfile_set_subscribed(struct mail_storage *storage, const char *path,
        o_stream_unref(output);
 
        if (failed || (set && found) || (!set && !found)) {
-               if (file_dotlock_delete(path, fd_out) < 0) {
+               if (file_dotlock_delete(path, NULL, fd_out) < 0) {
                        subsfile_set_syscall_error(storage,
                                "file_dotlock_delete()", path);
                        failed = TRUE;
                }
        } else {
-               if (file_dotlock_replace(path, fd_out, TRUE) < 0) {
+               if (file_dotlock_replace(path, NULL, fd_out, TRUE) < 0) {
                        subsfile_set_syscall_error(storage,
                                "file_dotlock_replace()", path);
                        failed = TRUE;
index 75c3488bbae1869a1237dacc02362a4a75f6b39e..85cd177958fd0ef7c412328ad84e4345492cfdb9 100644 (file)
@@ -14,6 +14,8 @@
 #include <time.h>
 #include <sys/stat.h>
 
+#define DEFAULT_LOCK_SUFFIX ".lock"
+
 /* 0.1 .. 0.2msec */
 #define LOCK_RANDOM_USLEEP_TIME (100000 + (unsigned int)rand() % 100000)
 
@@ -244,13 +246,14 @@ static int try_create_lock(struct lock_info *lock_info, const char *temp_prefix)
        return 1;
 }
 
-static int dotlock_create(const char *path, const char *temp_prefix,
-                         int checkonly, int *fd,
-                         unsigned int timeout, unsigned int stale_timeout,
-                         unsigned int immediate_stale_timeout,
-                         int (*callback)(unsigned int secs_left, int stale,
-                                         void *context),
-                         void *context)
+static int
+dotlock_create(const char *path, const char *temp_prefix,
+              const char *lock_suffix, int checkonly, int *fd,
+              unsigned int timeout, unsigned int stale_timeout,
+              unsigned int immediate_stale_timeout,
+              int (*callback)(unsigned int secs_left, int stale,
+                              void *context),
+              void *context)
 {
        const char *lock_path;
         struct lock_info lock_info;
@@ -261,7 +264,7 @@ static int dotlock_create(const char *path, const char *temp_prefix,
 
        now = time(NULL);
 
-       lock_path = t_strconcat(path, ".lock", NULL);
+       lock_path = t_strconcat(path, lock_suffix, NULL);
        stale_notify_threshold = stale_timeout / 2;
        max_wait_time = now + timeout;
 
@@ -342,11 +345,11 @@ int file_lock_dotlock(const char *path, const char *temp_prefix, int checkonly,
        struct stat st;
        int fd, ret;
 
-       lock_path = t_strconcat(path, ".lock", NULL);
+       lock_path = t_strconcat(path, DEFAULT_LOCK_SUFFIX, NULL);
 
-       ret = dotlock_create(path, temp_prefix, checkonly, &fd,
-                            timeout, stale_timeout, immediate_stale_timeout,
-                            callback, context);
+       ret = dotlock_create(path, temp_prefix, DEFAULT_LOCK_SUFFIX,
+                            checkonly, &fd, timeout, stale_timeout,
+                            immediate_stale_timeout, callback, context);
        if (ret <= 0 || checkonly)
                return ret;
 
@@ -379,12 +382,13 @@ int file_lock_dotlock(const char *path, const char *temp_prefix, int checkonly,
        return 1;
 }
 
-static int dotlock_delete(const char *path, const struct dotlock *dotlock)
+static int dotlock_delete(const char *path, const char *lock_suffix,
+                         const struct dotlock *dotlock)
 {
        const char *lock_path;
         struct stat st;
 
-       lock_path = t_strconcat(path, ".lock", NULL);
+       lock_path = t_strconcat(path, lock_suffix, NULL);
 
        if (lstat(lock_path, &st) < 0) {
                if (errno == ENOENT) {
@@ -424,10 +428,11 @@ static int dotlock_delete(const char *path, const struct dotlock *dotlock)
 
 int file_unlock_dotlock(const char *path, const struct dotlock *dotlock)
 {
-       return dotlock_delete(path, dotlock);
+       return dotlock_delete(path, DEFAULT_LOCK_SUFFIX, dotlock);
 }
 
-int file_dotlock_open(const char *path, const char *temp_prefix,
+int file_dotlock_open(const char *path,
+                     const char *temp_prefix, const char *lock_suffix,
                      unsigned int timeout, unsigned int stale_timeout,
                      unsigned int immediate_stale_timeout,
                      int (*callback)(unsigned int secs_left, int stale,
@@ -436,7 +441,10 @@ int file_dotlock_open(const char *path, const char *temp_prefix,
 {
        int ret, fd;
 
-       ret = dotlock_create(path, temp_prefix, FALSE, &fd,
+       if (lock_suffix == NULL)
+               lock_suffix = DEFAULT_LOCK_SUFFIX;
+
+       ret = dotlock_create(path, temp_prefix, lock_suffix, FALSE, &fd,
                             timeout, stale_timeout, immediate_stale_timeout,
                             callback, context);
        if (ret <= 0)
@@ -444,13 +452,17 @@ int file_dotlock_open(const char *path, const char *temp_prefix,
        return fd;
 }
 
-int file_dotlock_replace(const char *path, int fd, int verify_owner)
+int file_dotlock_replace(const char *path, const char *lock_suffix,
+                        int fd, int verify_owner)
 {
        struct stat st, st2;
        const char *lock_path;
        int old_errno;
 
-       lock_path = t_strconcat(path, ".lock", NULL);
+       if (lock_suffix == NULL)
+               lock_suffix = DEFAULT_LOCK_SUFFIX;
+
+       lock_path = t_strconcat(path, lock_suffix, NULL);
        if (verify_owner) {
                if (fstat(fd, &st) < 0) {
                        old_errno = errno;
@@ -487,16 +499,19 @@ int file_dotlock_replace(const char *path, int fd, int verify_owner)
        return 1;
 }
 
-int file_dotlock_delete(const char *path, int fd)
+int file_dotlock_delete(const char *path, const char *lock_suffix, int fd)
 {
        struct dotlock dotlock;
        struct stat st;
        int old_errno;
 
+       if (lock_suffix == NULL)
+               lock_suffix = DEFAULT_LOCK_SUFFIX;
+
        if (fstat(fd, &st) < 0) {
                old_errno = errno;
                i_error("fstat(%s) failed: %m",
-                       t_strconcat(path, ".lock", NULL));
+                       t_strconcat(path, lock_suffix, NULL));
                (void)close(fd);
                errno = old_errno;
                return -1;
@@ -504,7 +519,7 @@ int file_dotlock_delete(const char *path, int fd)
 
        if (close(fd) < 0) {
                i_error("close(%s) failed: %m",
-                       t_strconcat(path, ".lock", NULL));
+                       t_strconcat(path, lock_suffix, NULL));
                return -1;
        }
 
@@ -512,5 +527,5 @@ int file_dotlock_delete(const char *path, int fd)
        dotlock.ino = st.st_ino;
        dotlock.mtime = st.st_mtime;
 
-       return dotlock_delete(path, &dotlock);
+       return dotlock_delete(path, lock_suffix, &dotlock);
 }
index 7c13b3ee854ea711e787204991647d149ef3e42a..454efcefcb9f7aa2b7d5d2970cbeb5d5f81e6883 100644 (file)
@@ -40,7 +40,8 @@ int file_unlock_dotlock(const char *path, const struct dotlock *dotlock);
 /* Use dotlock as the new content for file. This provides read safety without
    locks, but not very good for large files. Returns fd for lock file.
    If locking timed out, returns -1 and errno = EAGAIN. */
-int file_dotlock_open(const char *path, const char *temp_prefix,
+int file_dotlock_open(const char *path,
+                     const char *temp_prefix, const char *lock_suffix,
                      unsigned int timeout, unsigned int stale_timeout,
                      unsigned int immediate_stale_timeout,
                      int (*callback)(unsigned int secs_left, int stale,
@@ -48,8 +49,9 @@ int file_dotlock_open(const char *path, const char *temp_prefix,
                      void *context);
 /* Replaces path with path.lock file. Closes given fd. If verify_owner is TRUE,
    it checks that lock file hasn't been overwritten before renaming. */
-int file_dotlock_replace(const char *path, int fd, int verify_owner);
+int file_dotlock_replace(const char *path, const char *lock_suffix,
+                        int fd, int verify_owner);
 /* Like file_unlock_dotlock(). Closes given fd. */
-int file_dotlock_delete(const char *path, int fd);
+int file_dotlock_delete(const char *path, const char *lock_suffix, int fd);
 
 #endif