/* Lock all the hash buckets. */
again:
hash_size = (1ULL << tdb->header.v.hash_bits);
- if (tdb_lock_gradual(tdb, ltype, TDB_HASH_LOCK_START,
- 1ULL << tdb->header.v.hash_bits, flags)) {
+ if (tdb_lock_gradual(tdb, ltype, flags, TDB_HASH_LOCK_START,
+ hash_size)) {
if (!(flags & TDB_LOCK_PROBE)) {
tdb->log(tdb, TDB_DEBUG_ERROR, tdb->log_priv,
"tdb_lockall hashes failed (%s)\n",
int tdb_unlock_list(struct tdb_context *tdb, tdb_off_t list, int ltype)
{
+ list &= ((1ULL << tdb->header.v.hash_bits) - 1);
+
/* a allrecord lock allows us to avoid per chain locks */
if (tdb->allrecord_lock.count) {
if (tdb->allrecord_lock.ltype == F_RDLCK
+ flist, F_WRLCK);
}
-#if 0
+/* Even if the entry isn't in this hash bucket, you'd have to lock this
+ * bucket to find it. */
static int chainlock(struct tdb_context *tdb, const TDB_DATA *key,
int ltype, enum tdb_lock_flags waitflag,
const char *func)
return chainlock(tdb, &key, F_WRLCK, TDB_LOCK_WAIT, "tdb_chainlock");
}
+int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
+{
+ uint64_t h = tdb_hash(tdb, key.dptr, key.dsize);
+ tdb_trace_1rec(tdb, "tdb_chainunlock", key);
+ return tdb_unlock_list(tdb, h, F_WRLCK);
+}
+
+#if 0
/* lock/unlock one hash chain, non-blocking. This is meant to be used
to reduce contention - it cannot guarantee how many records will be
locked */
"tdb_chainlock_nonblock");
}
-int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
-{
- uint64_t h = tdb_hash(tdb, key.dptr, key.dsize);
- tdb_trace_1rec(tdb, "tdb_chainunlock", key);
- return tdb_unlock_list(tdb, h & ((1ULL << tdb->header.v.hash_bits)-1),
- F_WRLCK);
-}
-
int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
{
return chainlock(tdb, &key, F_RDLCK, TDB_LOCK_WAIT,