]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb/lock.c
Make TDB 32 bit clean (not just 31 bit) for systems with 64 bit file offsets.
[ccan] / ccan / tdb / lock.c
index 2bb6ddb88385a56de4ca48d57ea4c5f07eb6317f..07545b345ba0c6d80af5ed541376eca195afb87b 100644 (file)
@@ -84,7 +84,7 @@ int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,
                        TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n", 
                                 tdb->fd, offset, rw_type, lck_type, (int)len));
                }
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+               return -1;
        }
        return 0;
 }
@@ -133,10 +133,12 @@ static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op)
        }
 
        if (tdb->global_lock.count) {
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
        }
 
        if (list < -1 || list >= (int)tdb->header.hash_size) {
+               tdb->ecode = TDB_ERR_LOCK;
                TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n", 
                           list, ltype));
                return -1;
@@ -228,7 +230,8 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
        }
 
        if (tdb->global_lock.count) {
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
        }
 
        if (tdb->flags & TDB_NOLOCK)
@@ -301,16 +304,21 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
  */
 int tdb_transaction_lock(struct tdb_context *tdb, int ltype)
 {
-       if (tdb->have_transaction_lock || tdb->global_lock.count) {
+       if (tdb->global_lock.count) {
+               return 0;
+       }
+       if (tdb->transaction_lock_count > 0) {
+               tdb->transaction_lock_count++;
                return 0;
        }
+
        if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype, 
                                     F_SETLKW, 0, 1) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n"));
                tdb->ecode = TDB_ERR_LOCK;
                return -1;
        }
-       tdb->have_transaction_lock = 1;
+       tdb->transaction_lock_count++;
        return 0;
 }
 
@@ -320,12 +328,16 @@ int tdb_transaction_lock(struct tdb_context *tdb, int ltype)
 int tdb_transaction_unlock(struct tdb_context *tdb)
 {
        int ret;
-       if (!tdb->have_transaction_lock) {
+       if (tdb->global_lock.count) {
+               return 0;
+       }
+       if (tdb->transaction_lock_count > 1) {
+               tdb->transaction_lock_count--;
                return 0;
        }
        ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
        if (ret == 0) {
-               tdb->have_transaction_lock = 0;
+               tdb->transaction_lock_count = 0;
        }
        return ret;
 }
@@ -341,8 +353,10 @@ static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op)
        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);
+       if (tdb->read_only || tdb->traverse_read) {
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
+       }
 
        if (tdb->global_lock.count && tdb->global_lock.ltype == ltype) {
                tdb->global_lock.count++;
@@ -351,12 +365,14 @@ static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op)
 
        if (tdb->global_lock.count) {
                /* a global lock of a different type exists */
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
        }
        
        if (tdb->num_locks != 0) {
                /* can't combine global and chain locks */
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
        }
 
        if (!mark_lock &&
@@ -385,11 +401,13 @@ static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
 
        /* There are no locks on read-only dbs */
        if (tdb->read_only || tdb->traverse_read) {
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
        }
 
        if (tdb->global_lock.ltype != ltype || tdb->global_lock.count == 0) {
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
        }
 
        if (tdb->global_lock.count > 1) {
@@ -413,21 +431,21 @@ static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
 /* lock entire database with write lock */
 int tdb_lockall(struct tdb_context *tdb)
 {
-       tdb_trace(tdb, "tdb_lockall\n");
+       tdb_trace(tdb, "tdb_lockall");
        return _tdb_lockall(tdb, F_WRLCK, F_SETLKW);
 }
 
 /* lock entire database with write lock - mark only */
 int tdb_lockall_mark(struct tdb_context *tdb)
 {
-       tdb_trace(tdb, "tdb_lockall_mark\n");
+       tdb_trace(tdb, "tdb_lockall_mark");
        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)
 {
-       tdb_trace(tdb, "tdb_lockall_unmark\n");
+       tdb_trace(tdb, "tdb_lockall_unmark");
        return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK);
 }
 
@@ -435,21 +453,21 @@ int tdb_lockall_unmark(struct tdb_context *tdb)
 int tdb_lockall_nonblock(struct tdb_context *tdb)
 {
        int ret = _tdb_lockall(tdb, F_WRLCK, F_SETLK);
-       tdb_trace(tdb, "tdb_lockall_nonblock = %i\n", ret);
+       tdb_trace_ret(tdb, "tdb_lockall_nonblock", ret);
        return ret;
 }
 
 /* unlock entire database with write lock */
 int tdb_unlockall(struct tdb_context *tdb)
 {
-       tdb_trace(tdb, "tdb_unlockall\n");
+       tdb_trace(tdb, "tdb_unlockall");
        return _tdb_unlockall(tdb, F_WRLCK);
 }
 
 /* lock entire database with read lock */
 int tdb_lockall_read(struct tdb_context *tdb)
 {
-       tdb_trace(tdb, "tdb_lockall_read\n");
+       tdb_trace(tdb, "tdb_lockall_read");
        return _tdb_lockall(tdb, F_RDLCK, F_SETLKW);
 }
 
@@ -457,14 +475,14 @@ int tdb_lockall_read(struct tdb_context *tdb)
 int tdb_lockall_read_nonblock(struct tdb_context *tdb)
 {
        int ret = _tdb_lockall(tdb, F_RDLCK, F_SETLK);
-       tdb_trace(tdb, "tdb_lockall_read_nonblock = %i\n", ret);
+       tdb_trace_ret(tdb, "tdb_lockall_read_nonblock", ret);
        return ret;
 }
 
 /* unlock entire database with read lock */
 int tdb_unlockall_read(struct tdb_context *tdb)
 {
-       tdb_trace(tdb, "tdb_unlockall_read\n");
+       tdb_trace(tdb, "tdb_unlockall_read");
        return _tdb_unlockall(tdb, F_RDLCK);
 }
 
@@ -472,10 +490,9 @@ int tdb_unlockall_read(struct tdb_context *tdb)
    contention - it cannot guarantee how many records will be locked */
 int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
 {
-       tdb_trace(tdb, "tdb_chainlock ");
-       tdb_trace_record(tdb, key);
-       tdb_trace(tdb, "\n");
-       return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
+       int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
+       tdb_trace_1rec(tdb, "tdb_chainlock", key);
+       return ret;
 }
 
 /* lock/unlock one hash chain, non-blocking. This is meant to be used
@@ -484,56 +501,45 @@ int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
 int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)
 {
        int ret = tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
-       tdb_trace(tdb, "tdb_chainlock_nonblock ");
-       tdb_trace_record(tdb, key);
-       tdb_trace(tdb, "= %i\n", ret);
+       tdb_trace_1rec_ret(tdb, "tdb_chainlock_nonblock", key, ret);
        return ret;
 }
 
 /* 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)
 {
-       tdb_trace(tdb, "tdb_chainlock_mark ");
-       tdb_trace_record(tdb, key);
-       tdb_trace(tdb, "\n");
-       return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
+       int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
+       tdb_trace_1rec(tdb, "tdb_chainlock_mark", key);
+       return ret;
 }
 
 /* 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)
 {
-       tdb_trace(tdb, "tdb_chainlock_unmark ");
-       tdb_trace_record(tdb, key);
-       tdb_trace(tdb, "\n");
+       tdb_trace_1rec(tdb, "tdb_chainlock_unmark", 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)
 {
-       tdb_trace(tdb, "tdb_chainunlock ");
-       tdb_trace_record(tdb, key);
-       tdb_trace(tdb, "\n");
+       tdb_trace_1rec(tdb, "tdb_chainunlock", key);
        return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
 }
 
 int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
 {
-       tdb_trace(tdb, "tdb_chainlock_read ");
-       tdb_trace_record(tdb, key);
-       tdb_trace(tdb, "\n");
-       return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
+       int ret;
+       ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
+       tdb_trace_1rec(tdb, "tdb_chainlock_read", key);
+       return ret;
 }
 
 int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
 {
-       tdb_trace(tdb, "tdb_chainunlock_read ");
-       tdb_trace_record(tdb, key);
-       tdb_trace(tdb, "\n");
+       tdb_trace_1rec(tdb, "tdb_chainunlock_read", key);
        return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
 }
 
-
-
 /* record lock stops delete underneath */
 int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
 {