- uint64_t new_num_buckets, new_num_zones, new_zone_bits;
- uint64_t i, old_num_total, old_num_zones, old_size, old_zone_bits;
- tdb_len_t add, freebucket_size, needed;
- tdb_off_t off, old_free_off;
- const tdb_off_t *oldf;
- struct tdb_used_record fhdr;
-
- /* We need room for the record header too. */
- needed = sizeof(struct tdb_used_record)
- + adjust_size(klen, dlen, growing);
-
- /* tdb_allrecord_lock will update header; did zones change? */
- old_zone_bits = tdb->header.v.zone_bits;
- old_num_zones = tdb->header.v.num_zones;
-
- /* FIXME: this is overkill. An expand lock? */
- if (tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false) == -1)
- return -1;
-
- /* Someone may have expanded for us. */
- if (old_zone_bits != tdb->header.v.zone_bits
- || old_num_zones != tdb->header.v.num_zones)
- goto success;
-
- /* They may have also expanded the underlying size (otherwise we'd
- * have expanded our mmap to look at those offsets already). */
- old_size = tdb->map_size;
- tdb->methods->oob(tdb, tdb->map_size + 1, true);
- if (tdb->map_size != old_size)
- goto success;
-
- /* Did we enlarge zones without enlarging file? */
- if (tdb->map_size < tdb->header.v.num_zones<<tdb->header.v.zone_bits) {
- add = (tdb->header.v.num_zones<<tdb->header.v.zone_bits)
- - tdb->map_size;
- /* Updates tdb->map_size. */
- if (tdb->methods->expand_file(tdb, add) == -1)
- goto fail;
- if (add_free_record(tdb, tdb->map_size - add, add) == -1)
- goto fail;
- if (add >= needed) {
- /* Allocate from this zone. */
- tdb->last_zone = zone_of(tdb, tdb->map_size - add);
- goto success;
- }
- }