]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Trie index: Finding the node relative from other node; storing the path. mq-trie-index
authorMaria Matejka <mq@ucw.cz>
Wed, 17 Apr 2019 13:34:39 +0000 (15:34 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 17 Apr 2019 13:34:39 +0000 (15:34 +0200)
Will be useful for filter trie conversion

lib/tindex.c
lib/tindex.h
lib/tindex_test.c

index 7d09f83d19a51f5c3798518e776faf67153c6a51..e68da7520d672bcc3ab7e7398a68dc192fae60a3 100644 (file)
@@ -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);
index 7da4b90ef88f55c3f14b958656d22252d3066d4f..c4bb5dd4850a933998b240c8848e76d45ef0128a 100644 (file)
@@ -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.
index 7a3a6521544d3ab2f68b776cbefdba9893821ee0..9f4f74ffcd767a36cb7a318c806bede5c8484304 100644 (file)
@@ -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);
 }
 
 /*