+/* Returns -1 on error, 0 on OK, 1 on "expand and retry." */
+static int replace_data(struct tdb_context *tdb,
+ uint64_t h, struct tdb_data key, struct tdb_data dbuf,
+ tdb_off_t bucket,
+ tdb_off_t old_off, tdb_len_t old_room,
+ bool growing)
+{
+ tdb_off_t new_off;
+
+ /* Allocate a new record. */
+ new_off = alloc(tdb, key.dsize, dbuf.dsize, h, growing);
+ if (new_off == 0)
+ return 1;
+
+ /* We didn't like the existing one: remove it. */
+ if (old_off)
+ add_free_record(tdb, old_off,
+ sizeof(struct tdb_used_record)
+ + key.dsize + old_room);
+
+ /* FIXME: Encode extra hash bits! */
+ if (tdb_write_off(tdb, hash_off(tdb, bucket), new_off) == -1)
+ return -1;
+
+ new_off += sizeof(struct tdb_used_record);
+ if (tdb->methods->write(tdb, new_off, key.dptr, key.dsize) == -1)
+ return -1;
+
+ new_off += key.dsize;
+ if (tdb->methods->write(tdb, new_off, dbuf.dptr, dbuf.dsize) == -1)
+ return -1;
+
+ /* FIXME: tdb_increment_seqnum(tdb); */
+ return 0;
+}
+