Disable debug mode
[idzebra-moved-to-github.git] / util / flock.c
index 4953741..42dd067 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: flock.c,v 1.8 2006-06-27 11:56:29 adam Exp $
+/* $Id: flock.c,v 1.13 2006-06-30 15:10:20 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -40,6 +40,18 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <yaz/xmalloc.h>
 #include <yaz/log.h>
 
+/** whether lock file desciptors are shared within one process' threads */
+#define ZEBRA_FLOCK_SHARE_FD_IN_THREADS 1
+
+/** whether we always lock on the file - even if rd/wr locks should do */
+#define ZEBRA_FLOCK_FILE_LOCK_ALWAYS 1
+
+/** whether we should also use pthreads locking to do "extra" rd/wr locks */
+#define ZEBRA_FLOCK_EXTRA_RDWR_LOCKS 1
+
+/** whether this module should debug */
+#define DEBUG_FLOCK 0
+
 /** have this module (mutex) been initialized? */
 static int initialized = 0;
 
@@ -69,7 +81,9 @@ struct zebra_lock_info {
     /** number of file write locks/read locks */
     int no_file_write_lock;
     int no_file_read_lock;
+#if ZEBRA_FLOCK_EXTRA_RDWR_LOCKS
     Zebra_lock_rdwr rdwr_lock;
+#endif
     Zebra_mutex file_mutex;
 #endif
     /** next in lock list */
@@ -114,17 +128,22 @@ char *zebra_mk_fname(const char *dir, const char *name)
 ZebraLockHandle zebra_lock_create(const char *dir, const char *name)
 {
     char *fname = zebra_mk_fname(dir, name);
-    struct zebra_lock_info *p;
+    struct zebra_lock_info *p = 0;
     ZebraLockHandle h = 0;
 
     assert(initialized);
 
     zebra_mutex_lock(&lock_list_mutex);
+    /* see if we have the same filename in a global list of "lock files" */
+#ifndef WIN32
+#if ZEBRA_FLOCK_SHARE_FD_IN_THREADS
     for (p = lock_list; p ; p = p->next)
         if (!strcmp(p->fname, fname))
             break;
+#endif
+#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;
@@ -146,10 +165,10 @@ ZebraLockHandle zebra_lock_create(const char *dir, const char *name)
         {
             p->fname = fname;
             fname = 0;  /* fname buffer now owned by p->fname */
-            yaz_log(log_level, "zebra_lock_create fd=%d p=%p fname=%s",
-                    p->fd, p, p->fname);
 #ifndef WIN32
+#if ZEBRA_FLOCK_EXTRA_RDWR_LOCKS
             zebra_lock_rdwr_init(&p->rdwr_lock);
+#endif
             zebra_mutex_init(&p->file_mutex);
             p->no_file_write_lock = 0;
             p->no_file_read_lock = 0;
@@ -160,10 +179,15 @@ ZebraLockHandle zebra_lock_create(const char *dir, const char *name)
     }
     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;
+#ifndef WIN32
         h->write_flag = 0;
+#endif
+        yaz_log(log_level, "zebra_lock_create fd=%d p=%p fname=%s",
+                h->p->fd, h, p->fname);
     }
     zebra_mutex_unlock(&lock_list_mutex);
     xfree(fname); /* free it - if it's still there */
@@ -178,12 +202,13 @@ void zebra_lock_destroy(ZebraLockHandle h)
     yaz_log(log_level, "zebra_lock_destroy fd=%d p=%p fname=%s",
             h->p->fd, h, h->p->fname);
     zebra_mutex_lock(&lock_list_mutex);
-    yaz_log(log_level, "zebra_lock_destroy fd=%d p=%p fname=%s 1",
-            h->p->fd, h, h->p->fname);
+    yaz_log(log_level, "zebra_lock_destroy fd=%d p=%p fname=%s refcount=%d",
+            h->p->fd, h, h->p->fname, h->p->ref_count);
     assert(h->p->ref_count > 0);
     --(h->p->ref_count);
     if (h->p->ref_count == 0)
     {
+        /* must remove shared info from lock_list */
         struct zebra_lock_info **hp = &lock_list;
         while (*hp)
         {
@@ -195,8 +220,14 @@ void zebra_lock_destroy(ZebraLockHandle h)
             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
+#if ZEBRA_FLOCK_EXTRA_RDWR_LOCKS
         zebra_lock_rdwr_destroy(&h->p->rdwr_lock);
+#endif
         zebra_mutex_destroy(&h->p->file_mutex);
 #endif
         if (h->p->fd != -1)
@@ -212,57 +243,82 @@ void zebra_lock_destroy(ZebraLockHandle h)
 static int unixLock(int fd, int type, int cmd)
 {
     struct flock area;
+    int r;
     area.l_type = type;
     area.l_whence = SEEK_SET;
     area.l_len = area.l_start = 0L;
-    return fcntl(fd, cmd, &area);
+
+    yaz_log(log_level, "fcntl begin type=%d fd=%d", type, fd);
+    r = fcntl(fd, cmd, &area);
+    if (r == -1)
+        yaz_log(YLOG_WARN|YLOG_ERRNO, "fcntl FAIL type=%d fd=%d", type, fd);
+    else
+        yaz_log(log_level, "fcntl type=%d OK fd=%d", type, fd);
+    
+    return r;
 }
 #endif
 
 int zebra_lock_w(ZebraLockHandle h)
 {
     int r;
-    yaz_log(log_level, "zebra_lock_w fd=%d p=%p fname=%s", 
+    int do_lock = ZEBRA_FLOCK_FILE_LOCK_ALWAYS;
+    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 ZEBRA_FLOCK_EXTRA_RDWR_LOCKS
+    zebra_lock_rdwr_wlock(&h->p->rdwr_lock);
+#endif
+
     zebra_mutex_lock(&h->p->file_mutex);
     if (h->p->no_file_write_lock == 0)
+        do_lock = 1;
+    h->p->no_file_write_lock++;
+    if (do_lock)
     {
         /* if there is already a read lock.. upgrade to write lock */
         r = unixLock(h->p->fd, F_WRLCK, F_SETLKW);
     }
-    h->p->no_file_write_lock++;
     zebra_mutex_unlock(&h->p->file_mutex);
 
-    zebra_lock_rdwr_wlock(&h->p->rdwr_lock);
-#endif
     h->write_flag = 1;
+    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 = ZEBRA_FLOCK_FILE_LOCK_ALWAYS;
+
     yaz_log(log_level, "zebra_lock_r fd=%d p=%p fname=%s", 
             h->p->fd, h, h->p->fname);
 #ifdef WIN32
     while ((r = _locking(h->p->fd, _LK_LOCK, 1)))
         ;
 #else
+#if ZEBRA_FLOCK_EXTRA_RDWR_LOCKS
+    zebra_lock_rdwr_rlock(&h->p->rdwr_lock);
+#endif
+
     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++;
+    if (do_lock)
     {
         /* only read lock if no write locks already */
         r = unixLock(h->p->fd, F_RDLCK, F_SETLKW);
     }
-    h->p->no_file_read_lock++;
     zebra_mutex_unlock(&h->p->file_mutex);
-
-    zebra_lock_rdwr_rlock(&h->p->rdwr_lock);
+    
     h->write_flag = 0;
 #endif
     return r;
@@ -271,26 +327,32 @@ int zebra_lock_r(ZebraLockHandle h)
 int zebra_unlock(ZebraLockHandle h)
 {
     int r = 0;
-    yaz_log(log_level, "zebra_unlock fd=%d p=%p fname=%s",
+    int do_unlock = ZEBRA_FLOCK_FILE_LOCK_ALWAYS;
+    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;
+    if (do_unlock)
         r = unixLock(h->p->fd, F_UNLCK, F_SETLKW);
-    }
     zebra_mutex_unlock(&h->p->file_mutex);
+
+#if ZEBRA_FLOCK_EXTRA_RDWR_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;
 }
@@ -300,9 +362,13 @@ void zebra_flock_init()
     if (!initialized)
     {
         log_level = yaz_log_module_level("flock");
+#if DEBUG_FLOCK
+        log_level = YLOG_LOG|YLOG_FLUSH;
+#endif
         initialized = 1;
         zebra_mutex_init(&lock_list_mutex);
     }
+    yaz_log(log_level, "zebra_flock_init");
 }
 
 /*