-/* $Id: flock.c,v 1.10 2006-06-30 11:10:17 adam Exp $
+/* $Id: flock.c,v 1.15 2006-07-03 12:23:17 adam Exp $
Copyright (C) 1995-2006
Index Data ApS
#include <yaz/xmalloc.h>
#include <yaz/log.h>
+/** whether this module should debug */
#define DEBUG_FLOCK 1
-#define ALWAYS_FLOCK 1
-
/** have this module (mutex) been initialized? */
static int initialized = 0;
+/** whether fcntl locks are shared for all threads in a process (POSIX) */
+static int posix_locks = 1;
+
/** mutex for lock_list below */
Zebra_mutex lock_list_mutex;
assert(initialized);
zebra_mutex_lock(&lock_list_mutex);
-#ifndef WIN32
- for (p = lock_list; p ; p = p->next)
- if (!strcmp(p->fname, fname))
- break;
+ /* see if we have the same filename in a global list of "lock files" */
+#ifndef WIN32
+ if (posix_locks)
+ {
+ for (p = lock_list; p ; p = p->next)
+ if (!strcmp(p->fname, fname))
+ break;
+ }
#endif
if (!p)
- {
+ { /* didn't match (or we didn't want it to match! */
p = (struct zebra_lock_info *) xmalloc(sizeof(*p));
p->ref_count = 0;
p->fname = fname;
fname = 0; /* fname buffer now owned by p->fname */
#ifndef WIN32
- zebra_lock_rdwr_init(&p->rdwr_lock);
+ if (posix_locks)
+ zebra_lock_rdwr_init(&p->rdwr_lock);
+
zebra_mutex_init(&p->file_mutex);
p->no_file_write_lock = 0;
p->no_file_read_lock = 0;
}
if (p)
{
+ /* we have lock info so we can make a handle pointing to that */
p->ref_count++;
h = (ZebraLockHandle) xmalloc(sizeof(*h));
h->p = p;
--(h->p->ref_count);
if (h->p->ref_count == 0)
{
+ /* must remove shared info from lock_list */
struct zebra_lock_info **hp = &lock_list;
- yaz_log(log_level, "zebra_lock_destroy fd=%d p=%p fname=%s remove",
- h->p->fd, h, h->p->fname);
while (*hp)
{
if (*hp == h->p)
else
hp = &(*hp)->next;
}
+
+ yaz_log(log_level, "zebra_lock_destroy fd=%d p=%p fname=%s remove",
+ h->p->fd, h, h->p->fname);
+
#ifndef WIN32
- zebra_lock_rdwr_destroy(&h->p->rdwr_lock);
+ if (posix_locks)
+ zebra_lock_rdwr_destroy(&h->p->rdwr_lock);
zebra_mutex_destroy(&h->p->file_mutex);
#endif
if (h->p->fd != -1)
int zebra_lock_w(ZebraLockHandle h)
{
int r;
- int do_lock = ALWAYS_FLOCK;
+ int do_lock = 0;
yaz_log(log_level, "zebra_lock_w fd=%d p=%p fname=%s begin",
h->p->fd, h, h->p->fname);
-
+
#ifdef WIN32
while ((r = _locking(h->p->fd, _LK_LOCK, 1)))
;
#else
+ if (posix_locks)
+ zebra_lock_rdwr_wlock(&h->p->rdwr_lock);
+
zebra_mutex_lock(&h->p->file_mutex);
if (h->p->no_file_write_lock == 0)
do_lock = 1;
h->p->no_file_write_lock++;
- zebra_mutex_unlock(&h->p->file_mutex);
if (do_lock)
{
- yaz_log(log_level, "zebra_lock_w fd=%d p=%p fname=%s 2",
- h->p->fd, h, h->p->fname);
/* if there is already a read lock.. upgrade to write lock */
r = unixLock(h->p->fd, F_WRLCK, F_SETLKW);
}
- yaz_log(log_level, "zebra_lock_w fd=%d p=%p fname=%s 3",
- h->p->fd, h, h->p->fname);
+ else
+ {
+ assert(posix_locks);
+ }
+ zebra_mutex_unlock(&h->p->file_mutex);
- zebra_lock_rdwr_wlock(&h->p->rdwr_lock);
h->write_flag = 1;
+#endif
yaz_log(log_level, "zebra_lock_w fd=%d p=%p fname=%s end",
h->p->fd, h, h->p->fname);
-#endif
return r;
}
int zebra_lock_r(ZebraLockHandle h)
{
int r;
- int do_lock = ALWAYS_FLOCK;
+ int do_lock = 0;
- yaz_log(log_level, "zebra_lock_r fd=%d p=%p fname=%s",
+ yaz_log(log_level, "zebra_lock_r fd=%d p=%p fname=%s begin",
h->p->fd, h, h->p->fname);
#ifdef WIN32
while ((r = _locking(h->p->fd, _LK_LOCK, 1)))
;
#else
+ if (posix_locks)
+ zebra_lock_rdwr_rlock(&h->p->rdwr_lock);
+
zebra_mutex_lock(&h->p->file_mutex);
if (h->p->no_file_read_lock == 0 && h->p->no_file_write_lock == 0)
do_lock = 1;
h->p->no_file_read_lock++;
- zebra_mutex_unlock(&h->p->file_mutex);
-
if (do_lock)
{
/* only read lock if no write locks already */
r = unixLock(h->p->fd, F_RDLCK, F_SETLKW);
}
-
- zebra_lock_rdwr_rlock(&h->p->rdwr_lock);
+ else
+ {
+ assert(posix_locks);
+ }
+ zebra_mutex_unlock(&h->p->file_mutex);
+
h->write_flag = 0;
#endif
+ yaz_log(log_level, "zebra_lock_r fd=%d p=%p fname=%s end",
+ h->p->fd, h, h->p->fname);
return r;
}
int zebra_unlock(ZebraLockHandle h)
{
int r = 0;
- int do_unlock = ALWAYS_FLOCK;
+ int do_unlock = 0;
yaz_log(log_level, "zebra_unlock fd=%d p=%p fname=%s begin",
h->p->fd, h, h->p->fname);
#ifdef WIN32
r = _locking(h->p->fd, _LK_UNLCK, 1);
#else
- if (h->write_flag)
- zebra_lock_rdwr_wunlock(&h->p->rdwr_lock);
- else
- zebra_lock_rdwr_runlock(&h->p->rdwr_lock);
-
zebra_mutex_lock(&h->p->file_mutex);
if (h->write_flag)
h->p->no_file_write_lock--;
else
h->p->no_file_read_lock--;
if (h->p->no_file_read_lock == 0 && h->p->no_file_write_lock == 0)
- {
do_unlock = 1;
- yaz_log(log_level, "zebra_unlock fd=%d p=%p fname=%s 2",
- h->p->fd, h, h->p->fname);
+ if (do_unlock)
+ r = unixLock(h->p->fd, F_UNLCK, F_SETLKW);
+ else
+ {
+ assert(posix_locks);
}
zebra_mutex_unlock(&h->p->file_mutex);
- if (do_unlock)
- r = unixLock(h->p->fd, F_UNLCK, F_SETLKW);
+ if (posix_locks)
+ {
+ if (h->write_flag)
+ zebra_lock_rdwr_wunlock(&h->p->rdwr_lock);
+ else
+ zebra_lock_rdwr_runlock(&h->p->rdwr_lock);
+ }
+#endif
yaz_log(log_level, "zebra_unlock fd=%d p=%p fname=%s end",
h->p->fd, h, h->p->fname);
-#endif
return r;
}
+/** \brief see if the fcntl locking is not POSIX
+ *
+ * The default posix_locks=1 is assumed.. This function sets posix_locks
+ * to zero if linuxthreads is in use.
+ */
+static int check_for_linuxthreads()
+{
+#if __linux
+#ifdef _CS_GNU_LIBPTHREAD_VERSION
+ char conf_buf[512];
+ size_t r = confstr(_CS_GNU_LIBPTHREAD_VERSION, conf_buf, sizeof(conf_buf));
+ if (r == 0)
+ {
+ yaz_log(YLOG_WARN|YLOG_ERRNO, "confstr failed");
+ return -1;
+ }
+ if (strncmp(conf_buf, "linuxthreads", 12) == 0)
+ posix_locks = 0; /* Using linuxthreads.. */
+#else
+ posix_locks = 0; /* Old GLIBC on Linux. Assume linuxthreads */
+#endif
+#endif
+ return 0;
+}
+
void zebra_flock_init()
{
if (!initialized)
{
+ initialized = 1;
log_level = yaz_log_module_level("flock");
#if DEBUG_FLOCK
log_level = YLOG_LOG|YLOG_FLUSH;
#endif
- initialized = 1;
+ check_for_linuxthreads();
zebra_mutex_init(&lock_list_mutex);
+ yaz_log(log_level, "posix_locks: %d", posix_locks);
}
yaz_log(log_level, "zebra_flock_init");
}