- return tdb_write_convert(tdb, off, rec, sizeof(*rec));
-}
-
-/* If we fail, others will try after us. */
-static void enlarge_hash(struct tdb_context *tdb)
-{
- tdb_off_t newoff, oldoff, i;
- tdb_len_t hlen;
- uint64_t h, num = 1ULL << tdb->header.v.hash_bits;
- struct tdb_used_record pad, *r;
-
- /* FIXME: We should do this without holding locks throughout. */
- if (tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false) == -1)
- return;
-
- /* Someone else enlarged for us? Nothing to do. */
- if ((1ULL << tdb->header.v.hash_bits) != num)
- goto unlock;
-
- /* Allocate our new array. */
- hlen = num * sizeof(tdb_off_t) * 2;
- newoff = alloc(tdb, 0, hlen, 0, false);
- if (unlikely(newoff == TDB_OFF_ERR))
- goto unlock;
- if (unlikely(newoff == 0)) {
- if (tdb_expand(tdb, 0, hlen, false) == -1)
- goto unlock;
- newoff = alloc(tdb, 0, hlen, 0, false);
- if (newoff == TDB_OFF_ERR || newoff == 0)
- goto unlock;
- }
- /* Step over record header! */
- newoff += sizeof(struct tdb_used_record);
-
- /* Starts all zero. */
- if (zero_out(tdb, newoff, hlen) == -1)
- goto unlock;
-
- /* FIXME: If the space before is empty, we know this is in its ideal
- * location. Or steal a bit from the pointer to avoid rehash. */
- for (i = tdb_find_nonzero_off(tdb, hash_off(tdb, 0), num);
- i < num;
- i += tdb_find_nonzero_off(tdb, hash_off(tdb, i), num - i)) {
- tdb_off_t off;
- off = tdb_read_off(tdb, hash_off(tdb, i));
- if (unlikely(off == TDB_OFF_ERR))
- goto unlock;
- if (unlikely(!off)) {
- tdb->ecode = TDB_ERR_CORRUPT;
- tdb->log(tdb, TDB_DEBUG_FATAL, tdb->log_priv,
- "find_bucket_and_lock: zero hash bucket!\n");
- goto unlock;
- }
- h = hash_record(tdb, off);
- /* FIXME: Encode extra hash bits! */
- if (tdb_write_off(tdb, newoff
- + (h & ((num * 2) - 1)) * sizeof(uint64_t),
- off) == -1)
- goto unlock;
- }
-
- /* Free up old hash. */
- oldoff = tdb->header.v.hash_off - sizeof(*r);
- r = tdb_get(tdb, oldoff, &pad, sizeof(*r));
- if (!r)
- goto unlock;
- add_free_record(tdb, oldoff,
- sizeof(*r)+rec_data_length(r)+rec_extra_padding(r));
-
- /* Now we write the modified header. */
- tdb->header.v.hash_bits++;
- tdb->header.v.hash_off = newoff;
- write_header(tdb);
-unlock:
- tdb_allrecord_unlock(tdb, F_WRLCK);