result_t radix_tree_insert_subnet(radix_tree_t *tree, const char *subnet, void* info) { uint32_t key; int mask = trim_binary_subnet(subnet, &key); if (mask < 0) return FORMAT_ERROR; return radix_tree_insert_node(tree, key, mask, info); }
static void test2(const char *title, bool dense) { struct radix_tree s; struct radix_tree *t = &s; struct testnode *n; unsigned int i; unsigned int nnodes = 100000; unsigned int removed; radix_tree_tagid_t tag; unsigned int ntagged[RADIX_TREE_TAG_ID_MAX]; struct testnode *nodes; struct timeval stv; struct timeval etv; nodes = malloc(nnodes * sizeof(*nodes)); for (tag = 0; tag < RADIX_TREE_TAG_ID_MAX; tag++) { ntagged[tag] = 0; } radix_tree_init_tree(t); for (i = 0; i < nnodes; i++) { n = &nodes[i]; n->idx = random(); if (sizeof(long) == 4) { n->idx <<= 32; n->idx |= (uint32_t)random(); } if (dense) { n->idx %= nnodes * 2; } while (radix_tree_lookup_node(t, n->idx) != NULL) { n->idx++; } radix_tree_insert_node(t, n->idx, n); for (tag = 0; tag < RADIX_TREE_TAG_ID_MAX; tag++) { n->tagged[tag] = test2_should_tag(i, tag); if (n->tagged[tag]) { radix_tree_set_tag(t, n->idx, tag); ntagged[tag]++; } assert(n->tagged[tag] == radix_tree_get_tag(t, n->idx, tag)); } } gettimeofday(&stv, NULL); for (i = 0; i < nnodes; i++) { n = &nodes[i]; assert(radix_tree_lookup_node(t, n->idx) == n); } gettimeofday(&etv, NULL); printops(title, "lookup", 0, nnodes, &stv, &etv); for (tag = 0; tag < RADIX_TREE_TAG_ID_MAX; tag++) { unsigned int count = 0; gettimeofday(&stv, NULL); for (i = 0; i < nnodes; i++) { bool tagged; n = &nodes[i]; tagged = radix_tree_get_tag(t, n->idx, tag); assert(n->tagged[tag] == tagged); if (tagged) { count++; } } gettimeofday(&etv, NULL); assert(ntagged[tag] == count); printops(title, "get_tag", tag, nnodes, &stv, &etv); } gettimeofday(&stv, NULL); for (i = 0; i < nnodes; i++) { n = &nodes[i]; radix_tree_remove_node(t, n->idx); } gettimeofday(&etv, NULL); printops(title, "remove", 0, nnodes, &stv, &etv); gettimeofday(&stv, NULL); for (i = 0; i < nnodes; i++) { n = &nodes[i]; radix_tree_insert_node(t, n->idx, n); } gettimeofday(&etv, NULL); printops(title, "insert", 0, nnodes, &stv, &etv); for (tag = 0; tag < RADIX_TREE_TAG_ID_MAX; tag++) { ntagged[tag] = 0; gettimeofday(&stv, NULL); for (i = 0; i < nnodes; i++) { n = &nodes[i]; if (n->tagged[tag]) { radix_tree_set_tag(t, n->idx, tag); ntagged[tag]++; } } gettimeofday(&etv, NULL); printops(title, "set_tag", tag, ntagged[tag], &stv, &etv); } gettimeofday(&stv, NULL); { struct testnode *results[TEST2_GANG_LOOKUP_NODES]; uint64_t nextidx; unsigned int nfound; unsigned int total; nextidx = 0; total = 0; while ((nfound = radix_tree_gang_lookup_node(t, nextidx, (void *)results, __arraycount(results))) > 0) { nextidx = results[nfound - 1]->idx + 1; total += nfound; if (nextidx == 0) { break; } } assert(total == nnodes); } gettimeofday(&etv, NULL); printops(title, "ganglookup", 0, nnodes, &stv, &etv); gettimeofday(&stv, NULL); { struct testnode *results[TEST2_GANG_LOOKUP_NODES]; uint64_t nextidx; unsigned int nfound; unsigned int total; nextidx = UINT64_MAX; total = 0; while ((nfound = radix_tree_gang_lookup_node_reverse(t, nextidx, (void *)results, __arraycount(results))) > 0) { nextidx = results[nfound - 1]->idx - 1; total += nfound; if (nextidx == UINT64_MAX) { break; } } assert(total == nnodes); } gettimeofday(&etv, NULL); printops(title, "ganglookup_reverse", 0, nnodes, &stv, &etv); for (tag = 0; tag < RADIX_TREE_TAG_ID_MAX; tag++) { gettimeofday(&stv, NULL); { struct testnode *results[TEST2_GANG_LOOKUP_NODES]; uint64_t nextidx; unsigned int nfound; unsigned int total; nextidx = 0; total = 0; while ((nfound = radix_tree_gang_lookup_tagged_node(t, nextidx, (void *)results, __arraycount(results), tag)) > 0) { nextidx = results[nfound - 1]->idx + 1; total += nfound; } assert(total == ntagged[tag]); } gettimeofday(&etv, NULL); printops(title, "ganglookup_tag", tag, ntagged[tag], &stv, &etv); } for (tag = 0; tag < RADIX_TREE_TAG_ID_MAX; tag++) { gettimeofday(&stv, NULL); { struct testnode *results[TEST2_GANG_LOOKUP_NODES]; uint64_t nextidx; unsigned int nfound; unsigned int total; nextidx = UINT64_MAX; total = 0; while ((nfound = radix_tree_gang_lookup_tagged_node_reverse(t, nextidx, (void *)results, __arraycount(results), tag)) > 0) { nextidx = results[nfound - 1]->idx - 1; total += nfound; if (nextidx == UINT64_MAX) { break; } } assert(total == ntagged[tag]); } gettimeofday(&etv, NULL); printops(title, "ganglookup_tag_reverse", tag, ntagged[tag], &stv, &etv); } removed = 0; for (tag = 0; tag < RADIX_TREE_TAG_ID_MAX; tag++) { unsigned int total; total = 0; gettimeofday(&stv, NULL); { struct testnode *results[TEST2_GANG_LOOKUP_NODES]; uint64_t nextidx; unsigned int nfound; nextidx = 0; while ((nfound = radix_tree_gang_lookup_tagged_node(t, nextidx, (void *)results, __arraycount(results), tag)) > 0) { for (i = 0; i < nfound; i++) { radix_tree_remove_node(t, results[i]->idx); } nextidx = results[nfound - 1]->idx + 1; total += nfound; if (nextidx == 0) { break; } } assert(tag != 0 || total == ntagged[tag]); assert(total <= ntagged[tag]); } gettimeofday(&etv, NULL); printops(title, "ganglookup_tag+remove", tag, total, &stv, &etv); removed += total; } gettimeofday(&stv, NULL); { struct testnode *results[TEST2_GANG_LOOKUP_NODES]; uint64_t nextidx; unsigned int nfound; unsigned int total; nextidx = 0; total = 0; while ((nfound = radix_tree_gang_lookup_node(t, nextidx, (void *)results, __arraycount(results))) > 0) { for (i = 0; i < nfound; i++) { assert(results[i] == radix_tree_remove_node(t, results[i]->idx)); } nextidx = results[nfound - 1]->idx + 1; total += nfound; if (nextidx == 0) { break; } } assert(total == nnodes - removed); } gettimeofday(&etv, NULL); printops(title, "ganglookup+remove", 0, nnodes - removed, &stv, &etv); assert(radix_tree_empty_tree_p(t)); assert(radix_tree_empty_tagged_tree_p(t, 0)); assert(radix_tree_empty_tagged_tree_p(t, 1)); radix_tree_fini_tree(t); free(nodes); }
static void test1(void) { struct radix_tree s; struct radix_tree *t = &s; void *results[3]; radix_tree_init_tree(t); radix_tree_dump(t); assert(radix_tree_lookup_node(t, 0) == NULL); assert(radix_tree_lookup_node(t, 1000) == NULL); assert(radix_tree_gang_lookup_node(t, 0, results, 3) == 0); assert(radix_tree_gang_lookup_node(t, 1000, results, 3) == 0); assert(radix_tree_gang_lookup_node_reverse(t, 0, results, 3) == 0); assert(radix_tree_gang_lookup_node_reverse(t, 1000, results, 3) == 0); assert(radix_tree_gang_lookup_tagged_node(t, 0, results, 3, 0) == 0); assert(radix_tree_gang_lookup_tagged_node(t, 1000, results, 3, 0) == 0); assert(radix_tree_gang_lookup_tagged_node_reverse(t, 0, results, 3, 0) == 0); assert(radix_tree_gang_lookup_tagged_node_reverse(t, 1000, results, 3, 0) == 0); assert(radix_tree_empty_tree_p(t)); assert(radix_tree_empty_tagged_tree_p(t, 0)); assert(radix_tree_empty_tagged_tree_p(t, 1)); assert(radix_tree_insert_node(t, 0, (void *)0xdeadbea0) == 0); assert(!radix_tree_empty_tree_p(t)); assert(radix_tree_empty_tagged_tree_p(t, 0)); assert(radix_tree_empty_tagged_tree_p(t, 1)); assert(radix_tree_lookup_node(t, 0) == (void *)0xdeadbea0); assert(radix_tree_lookup_node(t, 1000) == NULL); memset(results, 0, sizeof(results)); assert(radix_tree_gang_lookup_node(t, 0, results, 3) == 1); assert(results[0] == (void *)0xdeadbea0); assert(radix_tree_gang_lookup_node(t, 1000, results, 3) == 0); memset(results, 0, sizeof(results)); assert(radix_tree_gang_lookup_node_reverse(t, 0, results, 3) == 1); assert(results[0] == (void *)0xdeadbea0); memset(results, 0, sizeof(results)); assert(radix_tree_gang_lookup_node_reverse(t, 1000, results, 3) == 1); assert(results[0] == (void *)0xdeadbea0); assert(radix_tree_gang_lookup_tagged_node(t, 0, results, 3, 0) == 0); assert(radix_tree_gang_lookup_tagged_node_reverse(t, 0, results, 3, 0) == 0); assert(radix_tree_insert_node(t, 1000, (void *)0xdeadbea0) == 0); assert(radix_tree_remove_node(t, 0) == (void *)0xdeadbea0); assert(!radix_tree_empty_tree_p(t)); radix_tree_dump(t); assert(radix_tree_lookup_node(t, 0) == NULL); assert(radix_tree_lookup_node(t, 1000) == (void *)0xdeadbea0); memset(results, 0, sizeof(results)); assert(radix_tree_gang_lookup_node(t, 0, results, 3) == 1); assert(results[0] == (void *)0xdeadbea0); memset(results, 0, sizeof(results)); assert(radix_tree_gang_lookup_node(t, 1000, results, 3) == 1); assert(results[0] == (void *)0xdeadbea0); assert(radix_tree_gang_lookup_node_reverse(t, 0, results, 3) == 0); memset(results, 0, sizeof(results)); assert(radix_tree_gang_lookup_node_reverse(t, 1000, results, 3) == 1); assert(results[0] == (void *)0xdeadbea0); assert(radix_tree_gang_lookup_tagged_node(t, 0, results, 3, 0) == 0); assert(radix_tree_gang_lookup_tagged_node_reverse(t, 0, results, 3, 0) == 0); assert(!radix_tree_get_tag(t, 1000, 0)); assert(!radix_tree_get_tag(t, 1000, 1)); assert(radix_tree_empty_tagged_tree_p(t, 0)); assert(radix_tree_empty_tagged_tree_p(t, 1)); radix_tree_set_tag(t, 1000, 1); assert(!radix_tree_get_tag(t, 1000, 0)); assert(radix_tree_get_tag(t, 1000, 1)); assert(radix_tree_empty_tagged_tree_p(t, 0)); assert(!radix_tree_empty_tagged_tree_p(t, 1)); radix_tree_dump(t); assert(radix_tree_lookup_node(t, 1000) == (void *)0xdeadbea0); assert(radix_tree_insert_node(t, 0, (void *)0xbea0) == 0); radix_tree_dump(t); assert(radix_tree_lookup_node(t, 0) == (void *)0xbea0); assert(radix_tree_lookup_node(t, 1000) == (void *)0xdeadbea0); assert(radix_tree_insert_node(t, UINT64_C(10000000000), (void *)0xdea0) == 0); radix_tree_dump(t); assert(radix_tree_lookup_node(t, 0) == (void *)0xbea0); assert(radix_tree_lookup_node(t, 1000) == (void *)0xdeadbea0); assert(radix_tree_lookup_node(t, UINT64_C(10000000000)) == (void *)0xdea0); radix_tree_dump(t); assert(!radix_tree_get_tag(t, 0, 1)); assert(radix_tree_get_tag(t, 1000, 1)); assert(!radix_tree_get_tag(t, UINT64_C(10000000000), 1)); radix_tree_set_tag(t, 0, 1);; radix_tree_set_tag(t, UINT64_C(10000000000), 1); radix_tree_dump(t); assert(radix_tree_get_tag(t, 0, 1)); assert(radix_tree_get_tag(t, 1000, 1)); assert(radix_tree_get_tag(t, UINT64_C(10000000000), 1)); radix_tree_clear_tag(t, 0, 1);; radix_tree_clear_tag(t, UINT64_C(10000000000), 1); radix_tree_dump(t); assert(!radix_tree_get_tag(t, 0, 1)); assert(radix_tree_get_tag(t, 1000, 1)); assert(!radix_tree_get_tag(t, UINT64_C(10000000000), 1)); radix_tree_dump(t); assert(radix_tree_replace_node(t, 1000, (void *)0x12345678) == (void *)0xdeadbea0); assert(!radix_tree_get_tag(t, 1000, 0)); assert(radix_tree_get_tag(t, 1000, 1)); assert(radix_tree_gang_lookup_node(t, 0, results, 3) == 3); assert(results[0] == (void *)0xbea0); assert(results[1] == (void *)0x12345678); assert(results[2] == (void *)0xdea0); assert(radix_tree_gang_lookup_node(t, 1, results, 3) == 2); assert(results[0] == (void *)0x12345678); assert(results[1] == (void *)0xdea0); assert(radix_tree_gang_lookup_node(t, 1001, results, 3) == 1); assert(results[0] == (void *)0xdea0); assert(radix_tree_gang_lookup_node(t, UINT64_C(10000000001), results, 3) == 0); assert(radix_tree_gang_lookup_node(t, UINT64_C(1000000000000), results, 3) == 0); assert(radix_tree_gang_lookup_tagged_node(t, 0, results, 100, 1) == 1); assert(results[0] == (void *)0x12345678); assert(entry_tagmask(t->t_root) != 0); assert(radix_tree_remove_node(t, 1000) == (void *)0x12345678); assert(entry_tagmask(t->t_root) == 0); radix_tree_dump(t); assert(radix_tree_remove_node(t, UINT64_C(10000000000)) == (void *)0xdea0); radix_tree_dump(t); assert(radix_tree_remove_node(t, 0) == (void *)0xbea0); radix_tree_dump(t); radix_tree_fini_tree(t); }