diff --git a/lib/tindex.c b/lib/tindex.c index 7d09f83d..e68da752 100644 --- a/lib/tindex.c +++ b/lib/tindex.c @@ -648,7 +648,7 @@ tindex_renumber(union tindex_data *idata, const struct tindex_info *tinfo, u64 o #define TINDEX_ALLOC_IDX ({ u64 out = idm_alloc(&(ti->idm)); if (!out) goto noidx; out; }) u64 -tindex_find(struct tindex *ti, const uTDB *bits_in, const uint blen, const u64 create) +tindex_find_rel_path(struct tindex *ti, const u64 sidx, const uTDB *bits_in, const uint blen, uint bpos, u64 *path, const u64 create) { if (blen > ti->bdepth) if (create) @@ -659,6 +659,8 @@ tindex_find(struct tindex *ti, const uTDB *bits_in, const uint blen, const u64 c union tindex_data *idata = ti->index_data; const struct tindex_info stinfo = tindex_get_info(ti), *tinfo = &stinfo; + ASSERT(sidx > 0); + ASSERT(sidx <= tinfo->addrmask); /* Validate unit size */ switch (tinfo->usize) { @@ -669,10 +671,16 @@ tindex_find(struct tindex *ti, const uTDB *bits_in, const uint blen, const u64 c default: bug("This shall never happen"); } - u64 idx = 1; /* The root node is always 1 */ - u64 uidx = 0; /* Parent node is 0 on beginning */ + /* Here we begin */ + u64 idx = sidx; + u64 uidx = tindex_up(idata, tinfo, idx); - uint bpos = 0; + if (path) + memset(&(path[bpos]), 0, (blen - bpos) * sizeof(u64)); + + /* Shortcut for zero-length query */ + if (blen == bpos) + return tindex_exists(ti->exists, idx) ? idx : 0; while (1) { /* Get data from trie */ @@ -713,6 +721,10 @@ tindex_find(struct tindex *ti, const uTDB *bits_in, const uint blen, const u64 c return 0; } + /* This is not final for sure, store the path node */ + if (path && tindex_exists(ti->exists, idx)) + path[bpos] = idx; + /* Just one bit, to be sure */ ASSERT(bits < 2); ASSERT(ilen == 1); diff --git a/lib/tindex.h b/lib/tindex.h index 7da4b90e..c4bb5dd4 100644 --- a/lib/tindex.h +++ b/lib/tindex.h @@ -20,6 +20,41 @@ struct tindex* tindex_new(pool *p); #define TINDEX_CREATE (~(0ULL)) #define TINDEX_FIND 0 +/** + * Get the whole path to the indexed node at once + * @ti: the index to look into + * @sidx: index where to start + * @bits_in: data + * @blen: number of bits to extract from @bits_in. + * If @blen is not multiple of 64, the LSB's of the last u64 are ignored. + * @bpos: number of bits to ignore from @bits_in. + * @path: preallocated array of @blen of u64's to store the path. + * @create: TINDEX_FIND to find existing, TINDEX_CREATE to create new records, + * every other value is for internal use + * + * Return value: 0 for not found; nonzero = the index + */ + +u64 tindex_find_rel_path(struct tindex *ti, const u64 sidx, const u32 *bits_in, const uint blen, const uint bpos, u64 *path, const u64 create); + + +/** + * Find an index beginning somewhere else + * @ti: the index to look into + * @sidx: index where to start + * @bits_in: data + * @blen: number of bits to extract from @bits_in. + * If @blen is not multiple of 64, the LSB's of the last u64 are ignored. + * @bpos: number of bits to ignore from @bits_in. + * @create: TINDEX_FIND to find existing, TINDEX_CREATE to create new records, + * every other value is for internal use + * + * Return value: 0 for not found; nonzero = the index + */ + +static inline u64 tindex_find_rel(struct tindex *ti, const u64 sidx, const u32 *bits_in, const uint blen, uint bpos, const u64 create) +{ return tindex_find_rel_path(ti, sidx, bits_in, blen, bpos, NULL, create); } + /** * Find an index * @ti: the tindex to look into @@ -32,7 +67,8 @@ struct tindex* tindex_new(pool *p); * Return value: 0 for not found; nonzero = the index */ -u64 tindex_find(struct tindex *ti, const u32 *bits_in, const uint blen, const u64 create); +static inline u64 tindex_find(struct tindex *ti, const u32 *bits_in, const uint blen, const u64 create) +{ return tindex_find_rel(ti, 1, bits_in, blen, 0, create); } /** * Delete an index. diff --git a/lib/tindex_test.c b/lib/tindex_test.c index 7a3a6521..9f4f74ff 100644 --- a/lib/tindex_test.c +++ b/lib/tindex_test.c @@ -38,9 +38,12 @@ static inline void test_trie_add(struct test_trie *tt, u64 data) { static inline void test_trie_get(struct test_trie *tt, u64 data, u64 cnt) { u64 out = 0; u32 dtb[2] = { data >> 32, data }; - u64 idx = tindex_find(tt->ti, dtb, 64, TINDEX_FIND); + u64 path[64] = {}; + u64 idx = tindex_find_rel_path(tt->ti, 1, dtb, 64, 0, path, TINDEX_FIND); if (idx) out = tt->data[idx]; bt_assert_msg(out == cnt, "Index %lu shall be in trie %lu times, is %lu times.", data, cnt, out); + for (int i=0; i<64; i++) + bt_assert(path[i] == 0); } /*