- tdb_convert(tdb, &tdb->header, sizeof(tdb->header));
- hash_test = TDB_HASH_MAGIC;
- hash_test = tdb->khash(&hash_test, sizeof(hash_test),
- tdb->header.hash_seed, tdb->hash_priv);
- if (tdb->header.hash_test != hash_test) {
- /* wrong hash variant */
- tdb->log(tdb, TDB_DEBUG_ERROR, tdb->log_priv,
- "tdb_open: %s uses a different hash function\n",
- name);
- errno = EIO;
- goto fail;
- }
-
- if (fstat(tdb->fd, &st) == -1)
- goto fail;
-
- /* Is it already in the open list? If so, fail. */
- if (tdb_already_open(st.st_dev, st.st_ino)) {
- /* FIXME */
- tdb->log(tdb, TDB_DEBUG_ERROR, tdb->log_priv,
- "tdb_open: %s (%d,%d) is already open in this process\n",
- name, (int)st.st_dev, (int)st.st_ino);
- errno = EBUSY;
- goto fail;
- }
-
- tdb->name = strdup(name);
- if (!tdb->name) {
- errno = ENOMEM;
- goto fail;
- }
-
- tdb->map_size = st.st_size;
- tdb->device = st.st_dev;
- tdb->inode = st.st_ino;
- tdb_io_init(tdb);
- tdb_mmap(tdb);
-
- internal:
- /* Internal (memory-only) databases skip all the code above to
- * do with disk files, and resume here by releasing their
- * open lock and hooking into the active list. */
- tdb_unlock_open(tdb);
- tdb->last_zone = random_free_zone(tdb);
- tdb->next = tdbs;
- tdbs = tdb;
- return tdb;
-
- fail:
- save_errno = errno;
-
- if (!tdb)
- return NULL;
-
-#ifdef TDB_TRACE
- close(tdb->tracefd);
-#endif
- if (tdb->map_ptr) {
- if (tdb->flags & TDB_INTERNAL) {
- free(tdb->map_ptr);
- } else
- tdb_munmap(tdb);
- }
- free((char *)tdb->name);
- if (tdb->fd != -1)
- if (close(tdb->fd) != 0)
- tdb->log(tdb, TDB_DEBUG_ERROR, tdb->log_priv,
- "tdb_open: failed to close tdb->fd"
- " on error!\n");
- free(tdb);
- errno = save_errno;
- return NULL;
-}
-
-static int tdb_key_compare(TDB_DATA key, TDB_DATA data, void *private_data)
-{
- return memcmp(data.dptr, key.dptr, data.dsize) == 0;
-}
-
-static void unlock_lists(struct tdb_context *tdb,
- uint64_t start, uint64_t end, int ltype)
-{
- do {
- tdb_unlock_list(tdb, start, ltype);
- start = (start + ((1ULL << tdb->header.v.hash_bits) - 1))
- & ((1ULL << tdb->header.v.hash_bits) - 1);
- } while (start != end);
+ /* If we didn't use the old record, this implies we're growing. */
+ ecode = replace_data(tdb, &h, key, dbuf, off, old_room, off);
+out:
+ tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK);
+ return tdb->last_error = ecode;