mbox-lock.c revision 822b71c04ddd61cb08a0104f9e58f55334725e2a
/* Copyright (C) 2002 Timo Sirainen */
#include "lib.h"
#include "mail-index-private.h"
#include "mbox-storage.h"
#include "mbox-file.h"
#include "mbox-lock.h"
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef HAVE_FLOCK
#endif
/* 0.1 .. 0.2msec */
/* lock methods to use in wanted order */
#define DEFAULT_READ_LOCK_METHODS "fcntl"
#define DEFAULT_WRITE_LOCK_METHODS "dotlock fcntl"
/* lock timeout */
/* assume stale dotlock if mbox file hasn't changed for n seconds */
enum mbox_lock_type {
};
struct mbox_lock_context {
struct mbox_mailbox *mbox;
int lock_status[MBOX_LOCK_COUNT];
int checked_file;
int lock_type;
int dotlock_last_stale;
};
struct mbox_lock_data {
enum mbox_lock_type type;
const char *name;
};
#ifdef HAVE_FLOCK
#else
# define mbox_lock_flock NULL
#endif
#ifdef HAVE_LOCKF
#else
# define mbox_lock_lockf NULL
#endif
struct mbox_lock_data lock_data[] = {
};
static int lock_settings_initialized = FALSE;
static int lock_timeout, dotlock_change_timeout;
enum mbox_lock_type *locks)
{
enum mbox_lock_type type;
const char *const *lock;
int i, dest;
break;
}
}
i_fatal("%s: Support for lock type %s "
}
for (i = 0; i < dest; i++) {
}
/* @UNSAFE */
}
}
static void mbox_init_lock_settings(void)
{
const char *str;
int r, w;
at least read_locks and possibly more. */
break;
if (read_locks[r] == write_locks[w])
r++;
}
"Lock ordering must be the same with both, "
"and write locks must contain all read locks "
"(and possibly more)");
}
}
{
return 0;
return -1;
}
}
if (mbox_file_open(mbox) < 0)
return -1;
}
return 0;
}
{
enum mbox_lock_type *lock_types;
int i;
/* get next index we wish to try locking. it's the one after
dotlocking. */
if (lock_types[i] == MBOX_LOCK_DOTLOCK)
break;
}
i++;
/* we couldn't get fd lock -
it's really locked */
return FALSE;
}
}
}
return TRUE;
}
{
struct dotlock_settings set;
int ret;
if (!mbox->mbox_dotlocked)
return 1;
ret = -1;
}
return 1;
}
if (mbox->mbox_dotlocked)
return 1;
if (ret < 0) {
return -1;
}
if (ret == 0) {
"Timeout while waiting for lock");
return 0;
}
return -1;
return 1;
}
#ifdef HAVE_FLOCK
{
return -1;
return 1;
else
last_notify = 0;
if (errno != EWOULDBLOCK) {
return -1;
}
if (now >= max_wait_time)
return 0;
if (now != last_notify) {
max_wait_time - now);
}
}
return 1;
}
#endif
#ifdef HAVE_LOCKF
{
return -1;
return 1;
else
last_notify = 0;
return -1;
}
if (now >= max_wait_time)
return 0;
if (now != last_notify) {
max_wait_time - now);
}
}
return 1;
}
#endif
{
unsigned int next_alarm;
int wait_type;
return -1;
return 1;
if (max_wait_time == 0) {
} else {
if (now >= max_wait_time)
alarm(1);
else
}
alarm(0);
return -1;
}
if (now >= max_wait_time) {
alarm(0);
return 0;
}
/* notify locks once every 5 seconds.
try to use rounded values. */
if (next_alarm == 0)
next_alarm = 5;
max_wait_time - now);
}
alarm(0);
return 1;
}
{
enum mbox_lock_type *lock_types;
enum mbox_lock_type type;
int i, ret = 0, lock_status;
type = lock_types[i];
continue;
if (ret <= 0)
break;
}
return ret;
}
{
struct mbox_lock_context ctx;
int ret, i, drop_locks;
/* read-only mbox stream. no need to lock. */
return 1;
}
/* dropping to shared lock. first drop those that we
don't remove completely. */
for (i = 0; i < MBOX_LOCK_COUNT; i++)
drop_locks = TRUE;
} else {
drop_locks = FALSE;
}
if (ret <= 0) {
if (!drop_locks)
(void)mbox_unlock_files(&ctx);
if (ret == 0) {
"Timeout while waiting for lock");
}
return ret;
}
if (drop_locks) {
/* dropping to shared lock: drop the locks that are only
in write list */
}
return 1;
}
unsigned int *lock_id_r)
{
int ret;
/* mbox must be locked before index */
if (ret <= 0)
return ret;
}
} else {
mbox->mbox_excl_locks++;
}
return 1;
}
{
int ret = 0;
ret = -1;
/* make sure we don't keep mmap() between locks */
}
return ret;
}
{
struct mbox_lock_context ctx;
int i;
if (lock_id & 1) {
/* dropping exclusive lock */
if (--mbox->mbox_excl_locks > 0)
return 0;
if (mbox->mbox_shared_locks > 0) {
/* drop to shared lock */
return -1;
return 0;
}
} else {
/* dropping shared lock */
if (--mbox->mbox_shared_locks > 0)
return 0;
if (mbox->mbox_excl_locks > 0)
return 0;
}
/* all locks gone */
for (i = 0; i < MBOX_LOCK_COUNT; i++)
return mbox_unlock_files(&ctx);
}