From 02c58f3fb92c18ffb31c77a397163c44d70e3c93 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 9 Nov 2002 03:37:01 +0000 Subject: Add chainlock_read functions to get a read lock. Used in *massively* contended tdb's (and I've got one :-). Jeremy. (This used to be commit 064fa201ab73f476a168c40c2b227507e7342ec4) --- source3/tdb/tdb.c | 12 +++++++++++- source3/tdb/tdbutil.c | 43 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index 2a6dca16a8..e539376ac7 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -186,7 +186,7 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, if (tdb->flags & TDB_NOLOCK) return 0; - if (tdb->read_only) { + if ((rw_type == F_WRLCK) && (tdb->read_only)) { errno = EACCES; return -1; } @@ -1802,6 +1802,16 @@ int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key) return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK); } +int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK); +} + +int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK); +} + /* register a loging function */ void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...)) diff --git a/source3/tdb/tdbutil.c b/source3/tdb/tdbutil.c index ad97f45044..5498872f8a 100644 --- a/source3/tdb/tdbutil.c +++ b/source3/tdb/tdbutil.c @@ -39,7 +39,7 @@ static void gotalarm_sig(void) Lock a chain with timeout (in seconds). ****************************************************************************/ -int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout) +static int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type) { /* Allow tdb_chainlock to be interrupted by an alarm. */ int ret; @@ -51,13 +51,19 @@ int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int tim alarm(timeout); } - ret = tdb_chainlock(tdb, key); + if (rw_type == F_RDLCK) + ret = tdb_chainlock_read(tdb, key); + else + ret = tdb_chainlock(tdb, key); if (timeout) { alarm(0); CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); - if (gotalarm) + if (gotalarm) { + DEBUG(0,("tdb_chainlock_with_timeout: alarm (%u) timed out for key %s in tdb %s\n", + timeout, key.dptr, tdb->name )); return -1; + } } return ret; @@ -74,7 +80,7 @@ int tdb_lock_bystring(TDB_CONTEXT *tdb, char *keyval, unsigned int timeout) key.dptr = keyval; key.dsize = strlen(keyval)+1; - return tdb_chainlock_with_timeout(tdb, key, timeout); + return tdb_chainlock_with_timeout(tdb, key, timeout, F_WRLCK); } /**************************************************************************** @@ -91,6 +97,35 @@ void tdb_unlock_bystring(TDB_CONTEXT *tdb, char *keyval) tdb_chainunlock(tdb, key); } +/**************************************************************************** + Read lock a chain by string. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_read_lock_bystring(TDB_CONTEXT *tdb, char *keyval, unsigned int timeout) +{ + TDB_DATA key; + + key.dptr = keyval; + key.dsize = strlen(keyval)+1; + + return tdb_chainlock_with_timeout(tdb, key, timeout, F_RDLCK); +} + +/**************************************************************************** + Read unlock a chain by string. +****************************************************************************/ + +void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, char *keyval) +{ + TDB_DATA key; + + key.dptr = keyval; + key.dsize = strlen(keyval)+1; + + tdb_chainunlock_read(tdb, key); +} + + /**************************************************************************** Fetch a int32 value by a arbitrary blob key, return -1 if not found. Output is int32 in native byte order. -- cgit