Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-index/mbox/mbox-lock.c @ 73:2841fc79578f HEAD
Notify if waiting for release of mbox dotlock failed.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 28 Aug 2002 22:02:03 +0300 |
parents | 3b1985cbc908 |
children | ef6ae9e1b585 |
line wrap: on
line source
/* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" #include "mbox-index.h" #include "mbox-lock.h" #include "mail-index-util.h" #include <time.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #ifdef HAVE_FLOCK # include <sys/file.h> #endif #ifdef HAVE_FLOCK # define USE_FLOCK #endif /* 0.1 .. 0.2msec */ #define LOCK_RANDOM_USLEEP_TIME (100000 + (unsigned int)rand() % 100000) /* abort trying to get lock after 30 seconds */ #define MAX_LOCK_WAIT_SECONDS 30 /* remove lock after 10 mins */ #define STALE_LOCK_TIMEOUT (60*10) #ifdef USE_FLOCK static int mbox_lock_flock(MailIndex *index, const char *path, int fd, int set) { if (flock(fd, set ? LOCK_EX : LOCK_UN) == -1) { index_set_error(index, "flock() mbox lock failed for file " "%s: %m", path); return FALSE; } return TRUE; } #else static int mbox_lock_fcntl(MailIndex *index, const char *path, int fd, int set) { struct flock fl; fl.l_type = set ? F_WRLCK : F_UNLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; while (fcntl(fd, F_SETLKW, &fl) == -1) { if (errno != EINTR) { index_set_error(index, "fcntl() mbox lock " "failed for file %s: %m", path); return FALSE; } } return TRUE; } #endif static int mbox_lock_dotlock(MailIndex *index, const char *path, int set) { struct stat st; time_t now, max_wait_time; int fd; path = t_strconcat(path, ".lock", NULL); if (!set) { if (unlink(path) == 0 || errno == ENOENT) return TRUE; index_set_error(index, "unlink() failed for dotlock file " "%s: %m", path); return FALSE; } /* don't bother with the temp files as we'd just leave them lying around. besides, postfix also relies on O_EXCL working so we might as well. */ max_wait_time = time(NULL) + MAX_LOCK_WAIT_SECONDS; do { now = time(NULL); if (stat(path, &st) == 0) { /* lock exists, see if it's too old */ if (now > st.st_ctime + STALE_LOCK_TIMEOUT) { if (unlink(path) == -1 && errno != ENOENT) { index_set_error(index, "unlink() failed" " for dotlock file " "%s: %m", path); break; } } usleep(LOCK_RANDOM_USLEEP_TIME); continue; } fd = open(path, O_WRONLY | O_EXCL | O_CREAT, 0); if (fd >= 0) { /* got it */ (void)close(fd); return TRUE; } if (errno != EEXIST) { index_set_error(index, "Can't create dotlock file " "%s: %m", path); return FALSE; } } while (now < max_wait_time); index_set_error(index, "Timeout while waiting for release of mbox " "dotlock %s", path); return FALSE; } int mbox_lock(MailIndex *index, const char *path, int fd) { i_assert(fd >= 0); if (++index->mbox_locks > 1) return TRUE; #ifdef USE_FLOCK if (!mbox_lock_flock(index, path, fd, TRUE)) return FALSE; #else if (!mbox_lock_fcntl(index, path, fd, TRUE)) return FALSE; #endif if (!mbox_lock_dotlock(index, path, TRUE)) return FALSE; return TRUE; } int mbox_unlock(MailIndex *index, const char *path, int fd) { i_assert(fd >= 0); if (--index->mbox_locks > 0) return TRUE; #ifdef USE_FLOCK if (!mbox_lock_flock(index, path, fd, FALSE)) return FALSE; #else if (!mbox_lock_fcntl(index, path, fd, FALSE)) return FALSE; #endif if (!mbox_lock_dotlock(index, path, FALSE)) return FALSE; return TRUE; }