From 5a5b9f8d3d187b15b9e7b427c7c3b2ac5ee7c6be Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 29 Mar 2011 15:53:36 +1030 Subject: [PATCH] tdb2: implement tdb_chainlock_read/tdb_chainunlock_read. --- ccan/tdb2/hash.c | 21 +++++++++++++++++++++ ccan/tdb2/tdb2.h | 29 ++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/ccan/tdb2/hash.c b/ccan/tdb2/hash.c index 8bda587d..2b997008 100644 --- a/ccan/tdb2/hash.c +++ b/ccan/tdb2/hash.c @@ -875,3 +875,24 @@ void tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) tdb_trace_1rec(tdb, "tdb_chainunlock", key); tdb_unlock_hashes(tdb, lockstart, locksize, F_WRLCK); } + +enum TDB_ERROR tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb->last_error = chainlock(tdb, &key, F_RDLCK, TDB_LOCK_WAIT, + "tdb_chainlock_read"); +} + +void tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + uint64_t h = tdb_hash(tdb, key.dptr, key.dsize); + tdb_off_t lockstart, locksize; + unsigned int group, gbits; + + gbits = TDB_TOPLEVEL_HASH_BITS - TDB_HASH_GROUP_BITS; + group = bits_from(h, 64 - gbits, gbits); + + lockstart = hlock_range(group, &locksize); + + tdb_trace_1rec(tdb, "tdb_chainunlock_read", key); + tdb_unlock_hashes(tdb, lockstart, locksize, F_RDLCK); +} diff --git a/ccan/tdb2/tdb2.h b/ccan/tdb2/tdb2.h index ffbc7760..802bcdbe 100644 --- a/ccan/tdb2/tdb2.h +++ b/ccan/tdb2/tdb2.h @@ -395,7 +395,7 @@ enum TDB_ERROR tdb_nextkey(struct tdb_context *tdb, struct tdb_data *key); * @tdb: the tdb context returned from tdb_open() * @key: the key to lock. * - * This prevents any changes from occurring to a group of keys including @key, + * This prevents any access occurring to a group of keys including @key, * even if @key does not exist. This allows primitive atomic updates of * records without using transactions. * @@ -417,6 +417,33 @@ enum TDB_ERROR tdb_chainlock(struct tdb_context *tdb, TDB_DATA key); */ void tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key); +/** + * tdb_chainlock_read - lock a record in the TDB, for reading + * @tdb: the tdb context returned from tdb_open() + * @key: the key to lock. + * + * This prevents any changes from occurring to a group of keys including @key, + * even if @key does not exist. This allows primitive atomic updates of + * records without using transactions. + * + * You cannot begin a transaction while holding a tdb_chainlock_read(), nor can + * you do any operations on any other keys in the database. This also means + * that you cannot hold more than one tdb_chainlock()/read() at a time. + * + * See Also: + * tdb_chainlock() + */ +enum TDB_ERROR tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key); + +/** + * tdb_chainunlock_read - unlock a record in the TDB for reading + * @tdb: the tdb context returned from tdb_open() + * @key: the key to unlock. + * + * The key must have previously been locked by tdb_chainlock_read(). + */ +void tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key); + /** * tdb_lockall - lock the entire TDB * @tdb: the tdb context returned from tdb_open() -- 2.39.2