]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Trie index: storing existence of indices
authorMaria Matejka <mq@ucw.cz>
Tue, 9 Apr 2019 14:25:29 +0000 (16:25 +0200)
committerMaria Matejka <mq@ucw.cz>
Tue, 9 Apr 2019 14:33:39 +0000 (16:33 +0200)
lib/tindex.c
lib/tindex.h
lib/tindex_test.c

index e49d3ce1f4f3b5b0edc07e65cfc95d8778297f72..fedbe95ae4163715201f0302e68f0ad944f79521 100644 (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;
     }
 
index acd65c42d75a4152b05485dba8e66822874767c3..bdc31ba52a340ea3454f93d6e65fb1b06300e2c3 100644 (file)
 #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.
index e11af414fc2bea5610c8230d83027b6b78cdecb4..4698b8a37421f174b59aea84432a97024aa1b81d 100644 (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;
 }