r22832: merged the latest tdb changes from ctdb to Samba4
authorAndrew Tridgell <tridge@samba.org>
Mon, 14 May 2007 01:00:06 +0000 (01:00 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:52:22 +0000 (14:52 -0500)
(This used to be commit a88ab4fa3a07c31bc45c612043f9e096f384eda4)

source4/lib/tdb/common/lock.c
source4/lib/tdb/common/tdb.c
source4/lib/tdb/include/tdb.h

index 14ccbe39765d53f046f3d1db12e8558981a18ba3..72892febbd3261692e29ea0a1d2d6d3df648389a 100644 (file)
@@ -28,6 +28,8 @@
 
 #include "tdb_private.h"
 
+#define TDB_MARK_LOCK 0x80000000
+
 /* a byte range locking function - return 0 on success
    this functions locks/unlocks 1 byte at the specified offset.
 
@@ -109,6 +111,9 @@ static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op)
 {
        struct tdb_lock_type *new_lck;
        int i;
+       bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
+
+       ltype &= ~TDB_MARK_LOCK;
 
        /* a global lock allows us to avoid per chain locks */
        if (tdb->global_lock.count && 
@@ -158,7 +163,8 @@ static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op)
 
        /* Since fcntl locks don't nest, we do a lock for the first one,
           and simply bump the count for future ones */
-       if (tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list,ltype, op,
+       if (!mark_lock &&
+           tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op,
                                     0, 1)) {
                return -1;
        }
@@ -200,6 +206,9 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
        int ret = -1;
        int i;
        struct tdb_lock_type *lck = NULL;
+       bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
+
+       ltype &= ~TDB_MARK_LOCK;
 
        /* a global lock allows us to avoid per chain locks */
        if (tdb->global_lock.count && 
@@ -244,8 +253,12 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
         * anyway.
         */
 
-       ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK,
-                                      F_SETLKW, 0, 1);
+       if (mark_lock) {
+               ret = 0;
+       } else {
+               ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK,
+                                              F_SETLKW, 0, 1);
+       }
        tdb->num_locks--;
 
        /*
@@ -275,8 +288,12 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
 
 
 /* lock/unlock entire database */
-static int _tdb_lockall(struct tdb_context *tdb, int ltype)
+static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op)
 {
+       bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
+
+       ltype &= ~TDB_MARK_LOCK;
+
        /* There are no locks on read-only dbs */
        if (tdb->read_only || tdb->traverse_read)
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
@@ -296,9 +313,12 @@ static int _tdb_lockall(struct tdb_context *tdb, int ltype)
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
        }
 
-       if (tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, F_SETLKW, 
+       if (!mark_lock &&
+           tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op,
                                     0, 4*tdb->header.hash_size)) {
-               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno)));
+               if (op == F_SETLKW) {
+                       TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno)));
+               }
                return -1;
        }
 
@@ -308,9 +328,15 @@ static int _tdb_lockall(struct tdb_context *tdb, int ltype)
        return 0;
 }
 
+
+
 /* unlock entire db */
 static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
 {
+       bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
+
+       ltype &= ~TDB_MARK_LOCK;
+
        /* There are no locks on read-only dbs */
        if (tdb->read_only || tdb->traverse_read) {
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
@@ -325,7 +351,8 @@ static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
                return 0;
        }
 
-       if (tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 
+       if (!mark_lock &&
+           tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 
                                     0, 4*tdb->header.hash_size)) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno)));
                return -1;
@@ -340,7 +367,25 @@ static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
 /* lock entire database with write lock */
 int tdb_lockall(struct tdb_context *tdb)
 {
-       return _tdb_lockall(tdb, F_WRLCK);
+       return _tdb_lockall(tdb, F_WRLCK, F_SETLKW);
+}
+
+/* lock entire database with write lock - mark only */
+int tdb_lockall_mark(struct tdb_context *tdb)
+{
+       return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW);
+}
+
+/* unlock entire database with write lock - unmark only */
+int tdb_lockall_unmark(struct tdb_context *tdb)
+{
+       return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK);
+}
+
+/* lock entire database with write lock - nonblocking varient */
+int tdb_lockall_nonblock(struct tdb_context *tdb)
+{
+       return _tdb_lockall(tdb, F_WRLCK, F_SETLK);
 }
 
 /* unlock entire database with write lock */
@@ -352,7 +397,13 @@ int tdb_unlockall(struct tdb_context *tdb)
 /* lock entire database with read lock */
 int tdb_lockall_read(struct tdb_context *tdb)
 {
-       return _tdb_lockall(tdb, F_RDLCK);
+       return _tdb_lockall(tdb, F_RDLCK, F_SETLKW);
+}
+
+/* lock entire database with read lock - nonblock varient */
+int tdb_lockall_read_nonblock(struct tdb_context *tdb)
+{
+       return _tdb_lockall(tdb, F_RDLCK, F_SETLK);
 }
 
 /* unlock entire database with read lock */
@@ -376,6 +427,18 @@ int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)
        return tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
 }
 
+/* mark a chain as locked without actually locking it. Warning! use with great caution! */
+int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key)
+{
+       return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
+}
+
+/* unmark a chain as locked without actually locking it. Warning! use with great caution! */
+int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key)
+{
+       return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
+}
+
 int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
 {
        return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
index 25103d826e5f0e9398e76f371ac9ef437b87a993..70d050e7e6d633ece2add684c894bdbb9d69ac1d 100644 (file)
 TDB_DATA tdb_null;
 
 /*
-  increment the tdb sequence number if the tdb has been opened using
+  non-blocking increment of the tdb sequence number if the tdb has been opened using
   the TDB_SEQNUM flag
 */
-static void tdb_increment_seqnum(struct tdb_context *tdb)
+void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
 {
        tdb_off_t seqnum=0;
        
@@ -42,16 +42,29 @@ static void tdb_increment_seqnum(struct tdb_context *tdb)
                return;
        }
 
-       if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) {
-               return;
-       }
-
        /* we ignore errors from this, as we have no sane way of
           dealing with them.
        */
        tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
        seqnum++;
        tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum);
+}
+
+/*
+  increment the tdb sequence number if the tdb has been opened using
+  the TDB_SEQNUM flag
+*/
+static void tdb_increment_seqnum(struct tdb_context *tdb)
+{
+       if (!(tdb->flags & TDB_SEQNUM)) {
+               return;
+       }
+
+       if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) {
+               return;
+       }
+
+       tdb_increment_seqnum_nonblock(tdb);
 
        tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1);
 }
@@ -649,3 +662,11 @@ int tdb_get_flags(struct tdb_context *tdb)
        return tdb->flags;
 }
 
+
+/*
+  enable sequence number handling on an open tdb
+*/
+void tdb_enable_seqnum(struct tdb_context *tdb)
+{
+       tdb->flags |= TDB_SEQNUM;
+}
index e77b78f7ed0258cd26e39990405ee7e1931b99f0..9a9a4b489afc156e14abf01695225d880a3df6b1 100644 (file)
@@ -116,9 +116,13 @@ int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *);
 int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *);
 int tdb_exists(struct tdb_context *tdb, TDB_DATA key);
 int tdb_lockall(struct tdb_context *tdb);
+int tdb_lockall_nonblock(struct tdb_context *tdb);
 int tdb_unlockall(struct tdb_context *tdb);
 int tdb_lockall_read(struct tdb_context *tdb);
+int tdb_lockall_read_nonblock(struct tdb_context *tdb);
 int tdb_unlockall_read(struct tdb_context *tdb);
+int tdb_lockall_mark(struct tdb_context *tdb);
+int tdb_lockall_unmark(struct tdb_context *tdb);
 const char *tdb_name(struct tdb_context *tdb);
 int tdb_fd(struct tdb_context *tdb);
 tdb_log_func tdb_log_fn(struct tdb_context *tdb);
@@ -131,6 +135,8 @@ int tdb_get_seqnum(struct tdb_context *tdb);
 int tdb_hash_size(struct tdb_context *tdb);
 size_t tdb_map_size(struct tdb_context *tdb);
 int tdb_get_flags(struct tdb_context *tdb);
+void tdb_enable_seqnum(struct tdb_context *tdb);
+void tdb_increment_seqnum_nonblock(struct tdb_context *tdb);
 
 /* Low level locking functions: use with care */
 int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key);
@@ -138,6 +144,8 @@ int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key);
 int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key);
 int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key);
 int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key);
 
 /* Debug functions. Not used in production. */
 void tdb_dump_all(struct tdb_context *tdb);