tdb2: implement tdb_chainlock_read/tdb_chainunlock_read.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 29 Mar 2011 05:23:36 +0000 (15:53 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 29 Mar 2011 05:23:36 +0000 (15:53 +1030)
ccan/tdb2/hash.c
ccan/tdb2/tdb2.h

index 8bda587df88787ebed4d195ca8c57e4f909f3ed1..2b997008f7782961b370439488a570642be452eb 100644 (file)
@@ -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);
+}
index ffbc7760b11659af9ee8f78ca211b8d5c6123520..802bcdbe10e02d7b52fc51fb90a9cec968a2f527 100644 (file)
@@ -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()