X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftdb2%2Ftdb.c;h=e3b579d0f259ad94498fe740f84bef7dc52d9d2b;hp=a4dbc53d6f237050fc8e9ae5310138a3e8e87913;hb=6dbbfabca414018b4c5acb3e6e597d84e2b19caf;hpb=4e185ad8ab5a7e01edbbe12d11eb2f1577de7e8b diff --git a/ccan/tdb2/tdb.c b/ccan/tdb2/tdb.c index a4dbc53d..e3b579d0 100644 --- a/ccan/tdb2/tdb.c +++ b/ccan/tdb2/tdb.c @@ -22,6 +22,24 @@ static bool tdb_already_open(dev_t device, ino_t ino) 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; @@ -30,7 +48,7 @@ static uint64_t random_number(struct tdb_context *tdb) 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); @@ -72,7 +90,7 @@ static uint64_t random_number(struct tdb_context *tdb) struct new_database { struct tdb_header hdr; - struct tdb_freelist flist; + struct tdb_freetable ftable; }; /* initialise a new database */ @@ -101,11 +119,11 @@ static int tdb_new_database(struct tdb_context *tdb, 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)); @@ -153,6 +171,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, int saved_errno = 0; uint64_t hash_test; unsigned v; + ssize_t rlen; struct tdb_header hdr; struct tdb_attribute_seed *seed = NULL; @@ -172,6 +191,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, tdb->logfn = NULL; tdb->transaction = NULL; tdb->stats = NULL; + tdb->access = NULL; tdb_hash_init(tdb); tdb_io_init(tdb); tdb_lock_init(tdb); @@ -228,7 +248,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, } 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; } @@ -252,17 +272,25 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, 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 { @@ -323,7 +351,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, goto fail; } - if (tdb_flist_init(tdb) == -1) + if (tdb_ftable_init(tdb) == -1) goto fail; tdb->next = tdbs; @@ -376,7 +404,6 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, return NULL; } -/* FIXME: modify, don't rewrite! */ static int update_rec_hdr(struct tdb_context *tdb, tdb_off_t off, tdb_len_t keylen, @@ -386,7 +413,8 @@ static int update_rec_hdr(struct tdb_context *tdb, { 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)); @@ -402,7 +430,8 @@ static int replace_data(struct tdb_context *tdb, 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; @@ -468,7 +497,6 @@ int tdb_store(struct tdb_context *tdb, 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 @@ -525,7 +553,6 @@ int tdb_append(struct tdb_context *tdb, F_WRLCK); return 0; } - /* FIXME: Check right record free? */ /* Slow path. */ newdata = malloc(key.dsize + old_dlen + dbuf.dsize);