Commit c02f63e6 authored by Rusty Russell's avatar Rusty Russell

tdb2: rework hash.c functions to return enum TDB_ERROR.

This time we have to use our tri-value "tdb_bool_err" type to indicate
true, false, or error, which now allows us to correctly handle errors
in key matching (rather than treating it as a non-match).
parent 323a9473
This diff is collapsed.
......@@ -394,13 +394,13 @@ struct tdb_methods {
/* hash.c: */
void tdb_hash_init(struct tdb_context *tdb);
int first_in_hash(struct tdb_context *tdb,
struct traverse_info *tinfo,
TDB_DATA *kbuf, size_t *dlen);
tdb_bool_err first_in_hash(struct tdb_context *tdb,
struct traverse_info *tinfo,
TDB_DATA *kbuf, size_t *dlen);
int next_in_hash(struct tdb_context *tdb,
struct traverse_info *tinfo,
TDB_DATA *kbuf, size_t *dlen);
tdb_bool_err next_in_hash(struct tdb_context *tdb,
struct traverse_info *tinfo,
TDB_DATA *kbuf, size_t *dlen);
/* Hash random memory. */
uint64_t tdb_hash(struct tdb_context *tdb, const void *ptr, size_t len);
......@@ -416,14 +416,14 @@ tdb_off_t find_and_lock(struct tdb_context *tdb,
struct tdb_used_record *rec,
struct traverse_info *tinfo);
int replace_in_hash(struct tdb_context *tdb,
struct hash_info *h,
tdb_off_t new_off);
enum TDB_ERROR replace_in_hash(struct tdb_context *tdb,
struct hash_info *h,
tdb_off_t new_off);
int add_to_hash(struct tdb_context *tdb, struct hash_info *h,
tdb_off_t new_off);
enum TDB_ERROR add_to_hash(struct tdb_context *tdb, struct hash_info *h,
tdb_off_t new_off);
int delete_from_hash(struct tdb_context *tdb, struct hash_info *h);
enum TDB_ERROR delete_from_hash(struct tdb_context *tdb, struct hash_info *h);
/* For tdb_check */
bool is_subhash(tdb_off_t val);
......
......@@ -449,11 +449,13 @@ static int replace_data(struct tdb_context *tdb,
add_free_record(tdb, old_off,
sizeof(struct tdb_used_record)
+ key.dsize + old_room);
if (replace_in_hash(tdb, h, new_off) == -1)
return -1;
ecode = replace_in_hash(tdb, h, new_off);
} else {
if (add_to_hash(tdb, h, new_off) == -1)
return -1;
ecode = add_to_hash(tdb, h, new_off);
}
if (ecode != TDB_SUCCESS) {
tdb->ecode = ecode;
return -1;
}
new_off += sizeof(struct tdb_used_record);
......@@ -485,8 +487,10 @@ int tdb_store(struct tdb_context *tdb,
enum TDB_ERROR ecode;
off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
if (unlikely(off == TDB_OFF_ERR))
if (TDB_OFF_IS_ERR(off)) {
tdb->ecode = off;
return -1;
}
/* Now we have lock on this hash bucket. */
if (flag == TDB_INSERT) {
......@@ -551,8 +555,10 @@ int tdb_append(struct tdb_context *tdb,
int ret;
off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
if (unlikely(off == TDB_OFF_ERR))
if (TDB_OFF_IS_ERR(off)) {
tdb->ecode = off;
return -1;
}
if (off) {
old_dlen = rec_data_length(&rec);
......@@ -621,8 +627,10 @@ struct tdb_data tdb_fetch(struct tdb_context *tdb, struct tdb_data key)
struct tdb_data ret;
off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
if (unlikely(off == TDB_OFF_ERR))
if (TDB_OFF_IS_ERR(off)) {
tdb->ecode = off;
return tdb_null;
}
if (!off) {
tdb->ecode = TDB_ERR_NOEXIST;
......@@ -646,10 +654,13 @@ int tdb_delete(struct tdb_context *tdb, struct tdb_data key)
tdb_off_t off;
struct tdb_used_record rec;
struct hash_info h;
enum TDB_ERROR ecode;
off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
if (unlikely(off == TDB_OFF_ERR))
if (TDB_OFF_IS_ERR(off)) {
tdb->ecode = off;
return -1;
}
if (!off) {
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK);
......@@ -657,8 +668,11 @@ int tdb_delete(struct tdb_context *tdb, struct tdb_data key)
return -1;
}
if (delete_from_hash(tdb, &h) == -1)
ecode = delete_from_hash(tdb, &h);
if (ecode != TDB_SUCCESS) {
tdb->ecode = ecode;
goto unlock_err;
}
/* Free the deleted entry. */
add_stat(tdb, frees, 1);
......
......@@ -19,7 +19,7 @@ static tdb_off_t tdb_offset(struct tdb_context *tdb, struct tdb_data key)
struct hash_info h;
off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
if (unlikely(off == TDB_OFF_ERR))
if (TDB_OFF_IS_ERR(off))
return 0;
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
return off;
......
......@@ -20,15 +20,15 @@
int64_t tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *p)
{
int ret;
enum TDB_ERROR ecode;
struct traverse_info tinfo;
struct tdb_data k, d;
int64_t count = 0;
k.dptr = NULL;
for (ret = first_in_hash(tdb, &tinfo, &k, &d.dsize);
ret == 1;
ret = next_in_hash(tdb, &tinfo, &k, &d.dsize)) {
for (ecode = first_in_hash(tdb, &tinfo, &k, &d.dsize);
ecode == TDB_SUCCESS;
ecode = next_in_hash(tdb, &tinfo, &k, &d.dsize)) {
d.dptr = k.dptr + k.dsize;
count++;
......@@ -39,8 +39,10 @@ int64_t tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *p)
free(k.dptr);
}
if (ret < 0)
if (ecode != TDB_ERR_NOEXIST) {
tdb->ecode = ecode;
return -1;
}
return count;
}
......@@ -48,15 +50,16 @@ TDB_DATA tdb_firstkey(struct tdb_context *tdb)
{
struct traverse_info tinfo;
struct tdb_data k;
switch (first_in_hash(tdb, &tinfo, &k, NULL)) {
case 1:
enum TDB_ERROR ecode;
ecode = first_in_hash(tdb, &tinfo, &k, NULL);
if (ecode == TDB_SUCCESS) {
return k;
case 0:
tdb->ecode = TDB_SUCCESS;
/* Fall thru... */
default:
return tdb_null;
}
if (ecode == TDB_ERR_NOEXIST)
ecode = TDB_SUCCESS;
tdb->ecode = ecode;
return tdb_null;
}
/* We lock twice, not very efficient. We could keep last key & tinfo cached. */
......@@ -65,19 +68,21 @@ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key)
struct traverse_info tinfo;
struct hash_info h;
struct tdb_used_record rec;
enum TDB_ERROR ecode;
tinfo.prev = find_and_lock(tdb, key, F_RDLCK, &h, &rec, &tinfo);
if (unlikely(tinfo.prev == TDB_OFF_ERR))
if (TDB_OFF_IS_ERR(tinfo.prev)) {
tdb->ecode = tinfo.prev;
return tdb_null;
}
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
switch (next_in_hash(tdb, &tinfo, &key, NULL)) {
case 1:
ecode = next_in_hash(tdb, &tinfo, &key, NULL);
if (ecode == TDB_SUCCESS) {
return key;
case 0:
tdb->ecode = TDB_SUCCESS;
/* Fall thru... */
default:
return tdb_null;
}
if (ecode == TDB_ERR_NOEXIST)
ecode = TDB_SUCCESS;
tdb->ecode = ecode;
return tdb_null;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment