return false;
}
+static bool read_all(int fd, void *buf, size_t len)
+{
+ while (len) {
+ ssize_t ret;
+ ret = read(fd, buf, len);
+ if (ret < 0)
+ return false;
+ if (ret == 0) {
+ /* ETOOSHORT? */
+ errno = EWOULDBLOCK;
+ return false;
+ }
+ buf = (char *)buf + ret;
+ len -= ret;
+ }
+ return true;
+}
+
static uint64_t random_number(struct tdb_context *tdb)
{
int fd;
fd = open("/dev/urandom", O_RDONLY);
if (fd >= 0) {
- if (tdb_read_all(fd, &ret, sizeof(ret))) {
+ if (read_all(fd, &ret, sizeof(ret))) {
tdb_logerr(tdb, TDB_SUCCESS, TDB_DEBUG_TRACE,
"tdb_open: random from /dev/urandom");
close(fd);
struct new_database {
struct tdb_header hdr;
- struct tdb_freelist flist;
+ struct tdb_freetable ftable;
};
/* initialise a new database */
memset(newdb.hdr.hashtable, 0, sizeof(newdb.hdr.hashtable));
/* Free is empty. */
- newdb.hdr.free_list = offsetof(struct new_database, flist);
- memset(&newdb.flist, 0, sizeof(newdb.flist));
- set_used_header(NULL, &newdb.flist.hdr, 0,
- sizeof(newdb.flist) - sizeof(newdb.flist.hdr),
- sizeof(newdb.flist) - sizeof(newdb.flist.hdr), 1);
+ newdb.hdr.free_table = offsetof(struct new_database, ftable);
+ memset(&newdb.ftable, 0, sizeof(newdb.ftable));
+ set_header(NULL, &newdb.ftable.hdr, TDB_FTABLE_MAGIC, 0,
+ sizeof(newdb.ftable) - sizeof(newdb.ftable.hdr),
+ sizeof(newdb.ftable) - sizeof(newdb.ftable.hdr), 0);
/* Magic food */
memset(newdb.hdr.magic_food, 0, sizeof(newdb.hdr.magic_food));
int saved_errno = 0;
uint64_t hash_test;
unsigned v;
+ ssize_t rlen;
struct tdb_header hdr;
struct tdb_attribute_seed *seed = NULL;
tdb->logfn = NULL;
tdb->transaction = NULL;
tdb->stats = NULL;
+ tdb->access = NULL;
tdb_hash_init(tdb);
tdb_io_init(tdb);
tdb_lock_init(tdb);
}
tdb_convert(tdb, &hdr.hash_seed, sizeof(hdr.hash_seed));
tdb->hash_seed = hdr.hash_seed;
- tdb_flist_init(tdb);
+ tdb_ftable_init(tdb);
return tdb;
}
goto fail;
}
- if (!tdb_pread_all(tdb->fd, &hdr, sizeof(hdr), 0)
- || strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0) {
- if (!(open_flags & O_CREAT)) {
- tdb_logerr(tdb, TDB_ERR_IO, TDB_DEBUG_ERROR,
- "tdb_open: %s is not a tdb file", name);
- goto fail;
- }
+ /* If they used O_TRUNC, read will return 0. */
+ rlen = read(tdb->fd, &hdr, sizeof(hdr));
+ if (rlen == 0 && (open_flags & O_CREAT)) {
if (tdb_new_database(tdb, seed, &hdr) == -1) {
goto fail;
}
- } else if (hdr.version != TDB_VERSION) {
+ } else if (rlen < 0) {
+ tdb_logerr(tdb, TDB_ERR_IO, TDB_DEBUG_ERROR,
+ "tdb_open: error %s reading %s",
+ strerror(errno), name);
+ goto fail;
+ } else if (rlen < sizeof(hdr)
+ || strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0) {
+ tdb_logerr(tdb, TDB_ERR_IO, TDB_DEBUG_ERROR,
+ "tdb_open: %s is not a tdb file", name);
+ goto fail;
+ }
+
+ if (hdr.version != TDB_VERSION) {
if (hdr.version == bswap_64(TDB_VERSION))
tdb->flags |= TDB_CONVERT;
else {
goto fail;
}
- if (tdb_flist_init(tdb) == -1)
+ if (tdb_ftable_init(tdb) == -1)
goto fail;
tdb->next = tdbs;
return NULL;
}
-/* FIXME: modify, don't rewrite! */
static int update_rec_hdr(struct tdb_context *tdb,
tdb_off_t off,
tdb_len_t keylen,
{
uint64_t dataroom = rec_data_length(rec) + rec_extra_padding(rec);
- if (set_used_header(tdb, rec, keylen, datalen, keylen + dataroom, h))
+ if (set_header(tdb, rec, TDB_USED_MAGIC, keylen, datalen,
+ keylen + dataroom, h))
return -1;
return tdb_write_convert(tdb, off, rec, sizeof(*rec));
tdb_off_t new_off;
/* Allocate a new record. */
- new_off = alloc(tdb, key.dsize, dbuf.dsize, h->h, growing);
+ new_off = alloc(tdb, key.dsize, dbuf.dsize, h->h, TDB_USED_MAGIC,
+ growing);
if (unlikely(new_off == TDB_OFF_ERR))
return -1;
h.hlock_range, F_WRLCK);
return 0;
}
- /* FIXME: See if right record is free? */
} else {
if (flag == TDB_MODIFY) {
/* if the record doesn't exist and we
F_WRLCK);
return 0;
}
- /* FIXME: Check right record free? */
/* Slow path. */
newdata = malloc(key.dsize + old_dlen + dbuf.dsize);