0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-09 20:58:44 +00:00

Trie index: storing existence of indices

This commit is contained in:
Maria Matejka 2019-04-09 16:25:29 +02:00
parent 0972274dc3
commit 04be35ecaa
3 changed files with 37 additions and 19 deletions

View File

@ -26,6 +26,7 @@ union tindex_data {
struct tindex {
union tindex_data *index_data;
u64 *exists;
pool *p;
struct idm idm;
u8 unit_size;
@ -40,6 +41,7 @@ tindex_new(pool *p)
ti->unit_size = TI_MIN_UNIT_SIZE;
ti->address_size = TI_MIN_ADDRESS_SIZE;
ti->index_data = mb_allocz(p, ti->unit_size * (1 << ti->address_size));
ti->exists = mb_allocz(p, (1 << (ti->address_size - 3)));
idm_init(&(ti->idm), p, (1 << (ti->address_size - 5)), (1 << ti->address_size));
u32 rootnode = idm_alloc(&(ti->idm));
ASSERT(rootnode == 1);
@ -234,6 +236,24 @@ static inline uint tindex_input_bits(const u64 *bits_in, const uint blen, uint *
return ilen;
}
static inline void
tindex_exists_set(const struct tindex *ti, const u64 idx)
{
ti->exists[idx / 64] |= (1ULL << (idx % 64));
}
static inline u64
tindex_exists(const struct tindex *ti, const u64 idx)
{
return (ti->exists[idx / 64] & (1ULL << (idx % 64)));
}
static inline void
tindex_exists_clear(const struct tindex *ti, const u64 idx)
{
ti->exists[idx / 64] &= ~(1ULL << (idx % 64));
}
const char dump_indent[] = " ";
#define INDENT (dump_indent + sizeof(dump_indent) - depth - 1)
@ -263,7 +283,7 @@ _tindex_dump(const struct tindex *ti, u64 idx, uint depth, uint bit)
if (depth)
dlen++;
debug("%s0x%x/%u (%lu)\n", INDENT, data, dlen, idx);
debug("%s0x%x/%u (%lu %c)\n", INDENT, data, dlen, idx, tindex_exists(ti, idx) ? '*' : ' ');
u64 left = tindex_left(ti, idx, usize, asize, addrmask);
if (left)
_tindex_dump(ti, left, depth+1, 0);
@ -325,11 +345,19 @@ tindex_find(struct tindex *ti, const u64 *bits_in, const uint blen, const int cr
ilen = tindex_input_bits(bits_in, blen, &bpos, 1, &bits);
/* No more bits, we're done */
if (!ilen)
if (!ilen) {
/* Existence bits fiddling */
if (create)
tindex_exists_set(ti, idx);
else if (!tindex_exists(ti, idx))
return 0;
return idx;
}
/* Just one bit, to be sure */
ASSERT(bits < 2);
ASSERT(ilen == 1);
/* Go left or right? */
u64 nidx = bits ? tindex_right(ti, idx, usize, asize, addrmask) : tindex_left(ti, idx, usize, asize, addrmask);
@ -410,8 +438,10 @@ tindex_find(struct tindex *ti, const u64 *bits_in, const uint blen, const int cr
/* Grow there a branch if it has to be grown, otherwise return */
if (split)
break;
else
else {
tindex_exists_set(ti, midx);
return midx;
}
}
/* Growing a new branch */
@ -426,6 +456,7 @@ tindex_find(struct tindex *ti, const u64 *bits_in, const uint blen, const int cr
/* End of input data */
if ((ilen < dsize - 1) || !tindex_input_bits(bits_in, blen, &bpos, 1, &dataright)) {
tindex_put(ti, idx, usize, asize, dsize, dshift, data, ilen, 0, 0, uidx);
tindex_exists_set(ti, idx);
return idx;
}

View File

@ -10,21 +10,7 @@
#include "nest/bird.h"
/**
* tindex_bitcheck() callback is called by tindex_find() repeatedly
* to get input bits as needed. Maximal number of bits is
* given in @len; it shall be replaced the actual number of bits
* returned. The bits shall be returned in LSB of the return value.
* If (and only if) no bits are remaining, @len shall be changed,
* otherwise the callee must always return full bit string.
*
* This is intended to be implemented as a nested function in
* a library call using this tree index.
**/
typedef u64 (*tindex_bitcheck)(u8 *len);
/**
* Allocate a new tr[ei]e index from the given pool
* Allocate a new trie index from the given pool
* @p: pool to allocate from
*
* Returns the allocated tindex structure.

View File

@ -19,6 +19,7 @@ struct test_trie {
static inline void test_trie_add(struct test_trie *tt, u64 data) {
u64 idx = tindex_find(tt->ti, &data, 64, 1);
bt_assert(idx > 0);
u64 nlen = tt->len;
while (idx > nlen)
@ -57,7 +58,7 @@ t_simple(void)
}
for (u64 i = 0; i < 20; i++)
bt_assert(test_trie_get(&tt, i) == 1);
bt_assert_msg(test_trie_get(&tt, i) == 1, "Index %lu shall be in trie", i);
return 1;
}