Browse Source

tdb2: implement tdb_chainlock_read/tdb_chainunlock_read.

Rusty Russell 15 years ago
parent
commit
5a5b9f8d3d
2 changed files with 49 additions and 1 deletions
  1. 21 0
      ccan/tdb2/hash.c
  2. 28 1
      ccan/tdb2/tdb2.h

+ 21 - 0
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);
+}

+ 28 - 1
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()