}
/* Return 1 if we find something, 0 if not, -1 on error. */
-int next_in_hash(struct tdb_context *tdb, int ltype,
+int next_in_hash(struct tdb_context *tdb,
struct traverse_info *tinfo,
TDB_DATA *kbuf, size_t *dlen)
{
hl_start = (tdb_off_t)tinfo->toplevel_group
<< (64 - group_bits);
hl_range = 1ULL << group_bits;
- if (tdb_lock_hashes(tdb, hl_start, hl_range, ltype,
+ if (tdb_lock_hashes(tdb, hl_start, hl_range, F_RDLCK,
TDB_LOCK_WAIT) != 0)
return -1;
if (tdb_read_convert(tdb, off, &rec, sizeof(rec))) {
tdb_unlock_hashes(tdb,
- hl_start, hl_range, ltype);
+ hl_start, hl_range, F_RDLCK);
return -1;
}
if (rec_magic(&rec) != TDB_USED_MAGIC) {
off + sizeof(rec),
kbuf->dsize);
}
- tdb_unlock_hashes(tdb, hl_start, hl_range, ltype);
+ tdb_unlock_hashes(tdb, hl_start, hl_range, F_RDLCK);
return kbuf->dptr ? 1 : -1;
}
- tdb_unlock_hashes(tdb, hl_start, hl_range, ltype);
+ tdb_unlock_hashes(tdb, hl_start, hl_range, F_RDLCK);
tinfo->toplevel_group++;
tinfo->levels[0].hashtable
}
/* Return 1 if we find something, 0 if not, -1 on error. */
-int first_in_hash(struct tdb_context *tdb, int ltype,
+int first_in_hash(struct tdb_context *tdb,
struct traverse_info *tinfo,
TDB_DATA *kbuf, size_t *dlen)
{
tinfo->levels[0].entry = 0;
tinfo->levels[0].total_buckets = (1 << TDB_HASH_GROUP_BITS);
- return next_in_hash(tdb, ltype, tinfo, kbuf, dlen);
+ return next_in_hash(tdb, tinfo, kbuf, dlen);
}
/* Even if the entry isn't in this hash bucket, you'd have to lock this
/* 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);
+
+int 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);
/* If it needs recovery, grab all the locks and do it. */
int tdb_lock_and_recover(struct tdb_context *tdb);
-/* traverse.c: */
-int first_in_hash(struct tdb_context *tdb, int ltype,
- struct traverse_info *tinfo,
- TDB_DATA *kbuf, size_t *dlen);
-int next_in_hash(struct tdb_context *tdb, int ltype,
- struct traverse_info *tinfo,
- TDB_DATA *kbuf, size_t *dlen);
-
/* transaction.c: */
int tdb_transaction_recover(struct tdb_context *tdb);
bool tdb_needs_recovery(struct tdb_context *tdb);
-int64_t tdb_traverse_read(struct tdb_context *tdb,
- tdb_traverse_func fn, void *p);
-
-
/**
* enum tdb_attribute_type - descriminator for union tdb_attribute.
*/
ok1(store_records(tdb));
td.calls = 0;
- num = tdb_traverse_read(tdb, trav, &td);
+ num = tdb_traverse(tdb, trav, &td);
ok1(num == NUM_RECORDS);
ok1(td.calls == NUM_RECORDS);
- /* Simple loop should match tdb_traverse_read */
+ /* Simple loop should match tdb_traverse */
for (j = 0, k = tdb_firstkey(tdb); j < td.calls; j++) {
int val;
ok1(external_agent_operation(agent, OPEN, filename) == SUCCESS);
i = add_records_to_grow(agent, tdb->fd, tdb->map_size);
- /* Do a read traverse. */
- ok1(tdb_traverse_read(tdb, NULL, NULL) == i);
+ /* Do a traverse. */
+ ok1(tdb_traverse(tdb, NULL, NULL) == i);
/* Now store something! */
ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0);
hattr.base.next = &tap_log_attr;
- plan_tests(sizeof(flags) / sizeof(flags[0]) * 53 + 1);
+ plan_tests(sizeof(flags) / sizeof(flags[0]) * 32 + 1);
for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
tdb = tdb_open("run-traverse.tdb", flags[i],
O_RDWR|O_CREAT|O_TRUNC, 0600, &hattr);
if (!tdb)
continue;
- ok1(tdb_traverse_read(tdb, NULL, NULL) == 0);
ok1(tdb_traverse(tdb, NULL, NULL) == 0);
ok1(store_records(tdb));
- num = tdb_traverse_read(tdb, NULL, NULL);
- ok1(num == NUM_RECORDS);
num = tdb_traverse(tdb, NULL, NULL);
ok1(num == NUM_RECORDS);
- /* Full traverse (read-only). */
- td.calls = 0;
- td.call_limit = UINT_MAX;
- td.low = INT_MAX;
- td.high = INT_MIN;
- td.mismatch = false;
- td.delete = false;
-
- num = tdb_traverse_read(tdb, trav, &td);
- ok1(num == NUM_RECORDS);
- ok1(!td.mismatch);
- ok1(td.calls == NUM_RECORDS);
- ok1(td.low == 0);
- ok1(td.high == NUM_RECORDS-1);
-
/* Full traverse. */
td.calls = 0;
td.call_limit = UINT_MAX;
ok1(tdb_check(tdb, NULL, NULL) == 0);
ok1(tap_log_messages == 0);
- /* Growing traverse. Expect failure on r/o traverse. */
- tgd.calls = 0;
- tgd.num_large = 0;
- tgd.mismatch = false;
- tgd.error = TDB_SUCCESS;
- num = tdb_traverse_read(tdb, trav_grow, &tgd);
- ok1(num == 1);
- ok1(tgd.error == TDB_ERR_RDONLY);
- ok1(tgd.calls == 1);
- ok1(!tgd.mismatch);
- ok1(tap_log_messages == 1);
- tap_log_messages = 0;
- ok1(tdb_check(tdb, NULL, NULL) == 0);
-
- /* Deleting traverse. Expect failure on r/o traverse. */
- td.calls = 0;
- td.call_limit = UINT_MAX;
- td.low = INT_MAX;
- td.high = INT_MIN;
- td.mismatch = false;
- td.delete = true;
- td.delete_error = TDB_SUCCESS;
- num = tdb_traverse_read(tdb, trav, &td);
- ok1(num == 1);
- ok1(td.delete_error == TDB_ERR_RDONLY);
- ok1(!td.mismatch);
- ok1(td.calls == 1);
- ok1(td.low == td.high);
- ok1(tap_log_messages == 1);
- tap_log_messages = 0;
- ok1(tdb_check(tdb, NULL, NULL) == 0);
-
/* Deleting traverse (delete everything). */
td.calls = 0;
td.call_limit = UINT_MAX;
ok1(tdb_check(tdb, NULL, NULL) == 0);
/* Now it's empty! */
- ok1(tdb_traverse_read(tdb, NULL, NULL) == 0);
ok1(tdb_traverse(tdb, NULL, NULL) == 0);
/* Re-add. */
ok1(store_records(tdb));
- ok1(tdb_traverse_read(tdb, NULL, NULL) == NUM_RECORDS);
+ ok1(tdb_traverse(tdb, NULL, NULL) == NUM_RECORDS);
ok1(tdb_check(tdb, NULL, NULL) == 0);
/* Grow. This will cause us to be reshuffled. */
#include "private.h"
#include <ccan/likely/likely.h>
-static int64_t traverse(struct tdb_context *tdb, int ltype,
- tdb_traverse_func fn, void *p)
+int64_t tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *p)
{
int ret;
struct traverse_info tinfo;
int64_t count = 0;
k.dptr = NULL;
- for (ret = first_in_hash(tdb, ltype, &tinfo, &k, &d.dsize);
+ for (ret = first_in_hash(tdb, &tinfo, &k, &d.dsize);
ret == 1;
- ret = next_in_hash(tdb, ltype, &tinfo, &k, &d.dsize)) {
+ ret = next_in_hash(tdb, &tinfo, &k, &d.dsize)) {
d.dptr = k.dptr + k.dsize;
count++;
return -1;
return count;
}
-
-int64_t tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *p)
-{
- return traverse(tdb, F_WRLCK, fn, p);
-}
-int64_t tdb_traverse_read(struct tdb_context *tdb,
- tdb_traverse_func fn, void *p)
-{
- int64_t ret;
- bool was_ro = tdb->read_only;
- tdb->read_only = true;
- ret = traverse(tdb, F_RDLCK, fn, p);
- tdb->read_only = was_ro;
- return ret;
-}
-
TDB_DATA tdb_firstkey(struct tdb_context *tdb)
{
struct traverse_info tinfo;
struct tdb_data k;
- switch (first_in_hash(tdb, F_RDLCK, &tinfo, &k, NULL)) {
+ switch (first_in_hash(tdb, &tinfo, &k, NULL)) {
case 1:
return k;
case 0:
return tdb_null;
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
- switch (next_in_hash(tdb, F_RDLCK, &tinfo, &key, NULL)) {
+ switch (next_in_hash(tdb, &tinfo, &key, NULL)) {
case 1:
return key;
case 0: