]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
zone tree: api for tree iteration, avoid iterating trie
authorLibor Peltan <libor.peltan@nic.cz>
Mon, 11 Feb 2019 11:33:57 +0000 (12:33 +0100)
committerDaniel Salzman <daniel.salzman@nic.cz>
Fri, 26 Apr 2019 12:39:58 +0000 (14:39 +0200)
src/knot/dnssec/nsec-chain.c
src/knot/dnssec/nsec3-chain.c
src/knot/nameserver/axfr.c
src/knot/updates/changesets.c
src/knot/updates/changesets.h
src/knot/updates/zone-update.c
src/knot/updates/zone-update.h
src/knot/zone/contents.c
src/knot/zone/zone-tree.c
src/knot/zone/zone-tree.h

index 4bcb6bcb1d5737e12d3d316d987d709048ebc7e4..952b7d28fa9523005a50e374e811f0e9b2961eb8 100644 (file)
@@ -157,25 +157,25 @@ int knot_nsec_chain_iterate_create(zone_tree_t *nodes,
        assert(nodes);
        assert(callback);
 
-       trie_it_t *it = trie_it_begin(nodes);
-       if (!it) {
-               return KNOT_ENOMEM;
+       zone_tree_it_t it = { 0 };
+       int result = zone_tree_it_begin(nodes, &it);
+       if (result != KNOT_EOK) {
+               return result;
        }
 
-       if (trie_it_finished(it)) {
-               trie_it_free(it);
+       if (zone_tree_it_finished(&it)) {
+               zone_tree_it_free(&it);
                return KNOT_EINVAL;
        }
 
-       zone_node_t *first = (zone_node_t *)*trie_it_val(it);
+       zone_node_t *first = zone_tree_it_val(&it);
        zone_node_t *previous = first;
        zone_node_t *current = first;
 
-       trie_it_next(it);
+       zone_tree_it_next(&it);
 
-       int result = KNOT_EOK;
-       while (!trie_it_finished(it)) {
-               current = (zone_node_t *)*trie_it_val(it);
+       while (!zone_tree_it_finished(&it)) {
+               current = zone_tree_it_val(&it);
 
                result = callback(previous, current, data);
                if (result == NSEC_NODE_SKIP) {
@@ -184,30 +184,25 @@ int knot_nsec_chain_iterate_create(zone_tree_t *nodes,
                } else if (result == KNOT_EOK) {
                        previous = current;
                } else {
-                       trie_it_free(it);
+                       zone_tree_it_free(&it);
                        return result;
                }
-               trie_it_next(it);
+               zone_tree_it_next(&it);
        }
 
-       trie_it_free(it);
+       zone_tree_it_free(&it);
 
        return result == NSEC_NODE_SKIP ? callback(previous, first, data) :
                         callback(current, first, data);
 }
 
-inline static zone_node_t *it_val(trie_it_t *it)
-{
-       return (zone_node_t *)*trie_it_val(it);
-}
-
-inline static zone_node_t *it_next0(trie_it_t *it, zone_node_t *first)
+inline static zone_node_t *it_next0(zone_tree_it_t *it, zone_node_t *first)
 {
-       trie_it_next(it);
-       return (trie_it_finished(it) ? first : it_val(it));
+       zone_tree_it_next(it);
+       return (zone_tree_it_finished(it) ? first : zone_tree_it_val(it));
 }
 
-static zone_node_t *it_next1(trie_it_t *it, zone_node_t *first)
+static zone_node_t *it_next1(zone_tree_it_t *it, zone_node_t *first)
 {
        zone_node_t *res;
        do {
@@ -216,7 +211,7 @@ static zone_node_t *it_next1(trie_it_t *it, zone_node_t *first)
        return res;
 }
 
-static zone_node_t *it_next2(trie_it_t *it, zone_node_t *first, changeset_t *ch)
+static zone_node_t *it_next2(zone_tree_it_t *it, zone_node_t *first, changeset_t *ch)
 {
        zone_node_t *res = it_next0(it, first);
        while (knot_nsec_empty_nsec_and_rrsigs_in_node(res) || (res->flags & NODE_FLAGS_NONAUTH)) {
@@ -245,24 +240,25 @@ int knot_nsec_chain_iterate_fix(zone_tree_t *old_nodes, zone_tree_t *new_nodes,
        assert(new_nodes);
        assert(callback);
 
-       int ret = KNOT_EOK;
-
-       trie_it_t *old_it = trie_it_begin(old_nodes), *new_it = trie_it_begin(new_nodes);
-       if (old_it == NULL || new_it == NULL) {
-               ret = KNOT_ENOMEM;
+       zone_tree_it_t old_it = { 0 }, new_it = { 0 };
+       int ret = zone_tree_it_begin(old_nodes, &old_it);
+       if (ret == KNOT_EOK) {
+               ret = zone_tree_it_begin(new_nodes, &new_it);
+       }
+       if (ret != KNOT_EOK) {
                goto cleanup;
        }
 
-       if (trie_it_finished(new_it)) {
+       if (zone_tree_it_finished(&new_it)) {
                ret = KNOT_ENORECORD;
                goto cleanup;
        }
-       if (trie_it_finished(old_it)) {
+       if (zone_tree_it_finished(&old_it)) {
                ret = KNOT_ENORECORD;
                goto cleanup;
        }
 
-       zone_node_t *old_first = it_val(old_it), *new_first = it_val(new_it);
+       zone_node_t *old_first = zone_tree_it_val(&old_it), *new_first = zone_tree_it_val(&new_it);
 
        if (!knot_dname_is_equal(old_first->owner, new_first->owner)) {
                // this may happen with NSEC3 (on NSEC, it will be apex)
@@ -280,8 +276,8 @@ int knot_nsec_chain_iterate_fix(zone_tree_t *old_nodes, zone_tree_t *new_nodes,
        }
 
        zone_node_t *old_prev = old_first, *new_prev = new_first;
-       zone_node_t *old_curr = it_next1(old_it, old_first);
-       zone_node_t *new_curr = it_next2(new_it, new_first, data->changeset);
+       zone_node_t *old_curr = it_next1(&old_it, old_first);
+       zone_node_t *new_curr = it_next2(&new_it, new_first, data->changeset);
 
        while (1) {
                bool bitmap_change = !node_bitmap_equal(old_prev, new_prev);
@@ -305,7 +301,7 @@ int knot_nsec_chain_iterate_fix(zone_tree_t *old_nodes, zone_tree_t *new_nodes,
                                ret = knot_nsec_changeset_remove(old_curr, data->changeset);
                                CHECK_RET;
                                old_prev = old_curr;
-                               old_curr = it_next1(old_it, old_first);
+                               old_curr = it_next1(&old_it, old_first);
                                ret = callback(new_prev, new_curr, data);
                                CHECK_RET;
                        } else {
@@ -315,7 +311,7 @@ int knot_nsec_chain_iterate_fix(zone_tree_t *old_nodes, zone_tree_t *new_nodes,
                                ret = callback(new_prev, new_curr, data);
                                CHECK_RET;
                                new_prev = new_curr;
-                               new_curr = it_next2(new_it, new_first, data->changeset);
+                               new_curr = it_next2(&new_it, new_first, data->changeset);
                                ret = callback(new_prev, new_curr, data);
                                CHECK_RET;
                        }
@@ -328,13 +324,13 @@ int knot_nsec_chain_iterate_fix(zone_tree_t *old_nodes, zone_tree_t *new_nodes,
 
                old_prev = old_curr;
                new_prev = new_curr;
-               old_curr = it_next1(old_it, old_first);
-               new_curr = it_next2(new_it, new_first, data->changeset);
+               old_curr = it_next1(&old_it, old_first);
+               new_curr = it_next2(&new_it, new_first, data->changeset);
        }
 
 cleanup:
-       trie_it_free(old_it);
-       trie_it_free(new_it);
+       zone_tree_it_free(&old_it);
+       zone_tree_it_free(&new_it);
        return ret;
 }
 
index b70a8faf21e28a541f661751d90ac7a482cb4170..fe706af0c3b7ed61036fd148f1822ec61358041a 100644 (file)
@@ -126,10 +126,9 @@ static int copy_signatures(zone_tree_t *from, zone_tree_t *to)
 
        assert(to);
 
-       trie_it_t *it = trie_it_begin(from);
-
-       for (/* NOP */; !trie_it_finished(it); trie_it_next(it)) {
-               zone_node_t *node_from = (zone_node_t *)*trie_it_val(it);
+       zone_tree_it_t it = { 0 };
+       for ((void)zone_tree_it_begin(from, &it); !zone_tree_it_finished(&it); zone_tree_it_next(&it)) {
+               zone_node_t *node_from = zone_tree_it_val(&it);
 
                zone_node_t *node_to = zone_tree_get(to, node_from->owner);
                if (node_to == NULL) {
@@ -142,12 +141,12 @@ static int copy_signatures(zone_tree_t *from, zone_tree_t *to)
 
                int ret = shallow_copy_signature(node_from, node_to);
                if (ret != KNOT_EOK) {
-                       trie_it_free(it);
+                       zone_tree_it_free(&it);
                        return ret;
                }
        }
 
-       trie_it_free(it);
+       zone_tree_it_free(&it);
        return KNOT_EOK;
 }
 
@@ -159,9 +158,9 @@ static void free_nsec3_tree(zone_tree_t *nodes)
 {
        assert(nodes);
 
-       trie_it_t *it = trie_it_begin(nodes);
-       for (/* NOP */; !trie_it_finished(it); trie_it_next(it)) {
-               zone_node_t *node = (zone_node_t *)*trie_it_val(it);
+       zone_tree_it_t it = { 0 };
+       for ((void)zone_tree_it_begin(nodes, &it); !zone_tree_it_finished(&it); zone_tree_it_next(&it)) {
+               zone_node_t *node = zone_tree_it_val(&it);
                // newly allocated NSEC3 nodes
                knot_rdataset_t *nsec3 = node_rdataset(node, KNOT_RRTYPE_NSEC3);
                knot_rdataset_t *rrsig = node_rdataset(node, KNOT_RRTYPE_RRSIG);
@@ -170,7 +169,7 @@ static void free_nsec3_tree(zone_tree_t *nodes)
                node_free(node, NULL);
        }
 
-       trie_it_free(it);
+       zone_tree_it_free(&it);
        zone_tree_free(&nodes);
 }
 
@@ -495,11 +494,11 @@ static int create_nsec3_nodes(const zone_contents_t *zone,
        assert(nsec3_nodes);
        assert(chgset);
 
-       int result = KNOT_EOK;
+       zone_tree_it_t it = { 0 };
+       int result = zone_tree_it_begin(zone->nodes, &it);
 
-       trie_it_t *it = trie_it_begin(zone->nodes);
-       while (!trie_it_finished(it)) {
-               zone_node_t *node = (zone_node_t *)*trie_it_val(it);
+       while (!zone_tree_it_finished(&it)) {
+               zone_node_t *node = zone_tree_it_val(&it);
 
                /*!
                 * Remove possible NSEC from the node. (Do not allow both NSEC
@@ -510,7 +509,7 @@ static int create_nsec3_nodes(const zone_contents_t *zone,
                        break;
                }
                if (node->flags & NODE_FLAGS_NONAUTH || node->flags & NODE_FLAGS_EMPTY) {
-                       trie_it_next(it);
+                       zone_tree_it_next(&it);
                        continue;
                }
 
@@ -527,10 +526,10 @@ static int create_nsec3_nodes(const zone_contents_t *zone,
                        break;
                }
 
-               trie_it_next(it);
+               zone_tree_it_next(&it);
        }
 
-       trie_it_free(it);
+       zone_tree_it_free(&it);
 
        return result;
 }
@@ -644,23 +643,26 @@ static int fix_nsec3_nodes(zone_update_t *update, const dnssec_nsec3_params_t *p
 {
        assert(update);
 
-       int ret = KNOT_EOK;
+       zone_tree_it_t it = { 0 };
+       int ret = zone_tree_it_begin(update->change.remove->nodes, &it);
 
-       trie_it_t *rem_it = trie_it_begin(update->change.remove->nodes);
-       while (!trie_it_finished(rem_it) && ret == KNOT_EOK) {
-               zone_node_t *n = (zone_node_t *)*trie_it_val(rem_it);
+       while (!zone_tree_it_finished(&it) && ret == KNOT_EOK) {
+               zone_node_t *n = zone_tree_it_val(&it);
                ret = fix_nsec3_for_node(update, params, ttl, opt_out, chgset, n->owner);
-               trie_it_next(rem_it);
+               zone_tree_it_next(&it);
+       }
+
+       if (ret == KNOT_EOK) {
+               zone_tree_it_free(&it);
+               ret = zone_tree_it_begin(update->change.add->nodes, &it);
        }
-       trie_it_free(rem_it);
 
-       trie_it_t *add_it = trie_it_begin(update->change.add->nodes);
-       while (!trie_it_finished(add_it) && ret == KNOT_EOK) {
-               zone_node_t *n = (zone_node_t *)*trie_it_val(add_it);
+       while (!zone_tree_it_finished(&it) && ret == KNOT_EOK) {
+               zone_node_t *n = zone_tree_it_val(&it);
                ret = fix_nsec3_for_node(update, params, ttl, opt_out, chgset, n->owner);
-               trie_it_next(add_it);
+               zone_tree_it_next(&it);
        }
-       trie_it_free(add_it);
+       zone_tree_it_free(&it);
 
        return ret;
 }
index 0bd9611e3adbb4b268fbfa48cca359841d3658a3..4b55f8b95663291b7d1380559bd1eaa6ab321228 100644 (file)
@@ -35,6 +35,7 @@
 struct axfr_proc {
        struct xfr_proc proc;
        trie_it_t *i;
+       zone_tree_it_t it;
        unsigned cur_rrset;
 };
 
@@ -70,25 +71,20 @@ static int axfr_process_node_tree(knot_pkt_t *pkt, const void *item,
 
        struct axfr_proc *axfr = (struct axfr_proc*)state;
 
-       if (axfr->i == NULL) {
-               axfr->i = trie_it_begin((trie_t *)item);
-       }
+       int ret = zone_tree_it_begin((zone_tree_t *)item, &axfr->it); // does nothing if already itearating
 
        /* Put responses. */
-       int ret = KNOT_EOK;
-       while (!trie_it_finished(axfr->i)) {
-               zone_node_t *node = (zone_node_t *)*trie_it_val(axfr->i);
+       while (ret == KNOT_EOK && !zone_tree_it_finished(&axfr->it)) {
+               zone_node_t *node = zone_tree_it_val(&axfr->it);
                ret = axfr_put_rrsets(pkt, node, axfr);
-               if (ret != KNOT_EOK) {
-                       break;
+               if (ret == KNOT_EOK) {
+                       zone_tree_it_next(&axfr->it);
                }
-               trie_it_next(axfr->i);
        }
 
        /* Finished all nodes. */
        if (ret == KNOT_EOK) {
-               trie_it_free(axfr->i);
-               axfr->i = NULL;
+               zone_tree_it_free(&axfr->it);
        }
        return ret;
 }
@@ -97,7 +93,7 @@ static void axfr_query_cleanup(knotd_qdata_t *qdata)
 {
        struct axfr_proc *axfr = (struct axfr_proc *)qdata->extra->ext;
 
-       trie_it_free(axfr->i);
+       zone_tree_it_free(&axfr->it);
        ptrlist_free(&axfr->proc.nodes, qdata->mm);
        mm_free(qdata->mm, axfr);
 
index 79c341128d88a45bd493e7fcf5a36c14e281b8ea..ff393578a876416da7e3c3021883475ee3d6233e 100644 (file)
@@ -53,96 +53,28 @@ static int add_rr_to_contents(zone_contents_t *z, const knot_rrset_t *rrset)
        return ret == KNOT_ETTL ? KNOT_EOK : ret;
 }
 
-/*! \brief Cleans up trie iterations. */
-static void cleanup_iter_list(list_t *l)
-{
-       ptrnode_t *n, *nxt;
-       WALK_LIST_DELSAFE(n, nxt, *l) {
-               trie_it_t *it = (trie_it_t *)n->d;
-               trie_it_free(it);
-               rem_node(&n->n);
-               free(n);
-       }
-       init_list(l);
-}
-
 /*! \brief Inits changeset iterator with given tries. */
 static int changeset_iter_init(changeset_iter_t *ch_it, size_t tries, ...)
 {
        memset(ch_it, 0, sizeof(*ch_it));
-       init_list(&ch_it->iters);
 
        va_list args;
        va_start(args, tries);
 
+       assert(tries <= sizeof(ch_it->trees) / sizeof(*ch_it->trees));
        for (size_t i = 0; i < tries; ++i) {
-               trie_t *t = va_arg(args, trie_t *);
+               zone_tree_t *t = va_arg(args, zone_tree_t *);
                if (t == NULL) {
                        continue;
                }
 
-               trie_it_t *it = trie_it_begin(t);
-               if (it == NULL) {
-                       cleanup_iter_list(&ch_it->iters);
-                       va_end(args);
-                       return KNOT_ENOMEM;
-               }
-
-               if (ptrlist_add(&ch_it->iters, it, NULL) == NULL) {
-                       cleanup_iter_list(&ch_it->iters);
-                       va_end(args);
-                       return KNOT_ENOMEM;
-               }
+               ch_it->trees[ch_it->n_trees++] = t;
        }
 
        va_end(args);
 
-       return KNOT_EOK;
-}
-
-/*! \brief Gets next node from trie iterators. */
-static void iter_next_node(changeset_iter_t *ch_it, trie_it_t *t_it)
-{
-       assert(!trie_it_finished(t_it));
-       // Get next node, but not for the very first call.
-       if (ch_it->node) {
-               trie_it_next(t_it);
-       }
-       if (trie_it_finished(t_it)) {
-               ch_it->node = NULL;
-               return;
-       }
-
-       ch_it->node = (zone_node_t *)*trie_it_val(t_it);
-       assert(ch_it->node);
-       while (ch_it->node && ch_it->node->rrset_count == 0) {
-               // Skip empty non-terminals.
-               trie_it_next(t_it);
-               if (trie_it_finished(t_it)) {
-                       ch_it->node = NULL;
-               } else {
-                       ch_it->node = (zone_node_t *)*trie_it_val(t_it);
-                       assert(ch_it->node);
-               }
-       }
-
-       ch_it->node_pos = 0;
-}
-
-/*! \brief Gets next RRSet from trie iterators. */
-static knot_rrset_t get_next_rr(changeset_iter_t *ch_it, trie_it_t *t_it)
-{
-       if (ch_it->node == NULL || ch_it->node_pos == ch_it->node->rrset_count) {
-               iter_next_node(ch_it, t_it);
-               if (ch_it->node == NULL) {
-                       assert(trie_it_finished(t_it));
-                       knot_rrset_t rr;
-                       knot_rrset_init_empty(&rr);
-                       return rr;
-               }
-       }
-
-       return node_rrset_at(ch_it->node, ch_it->node_pos++);
+       assert(ch_it->n_trees);
+       return zone_tree_it_begin(ch_it->trees[0], &ch_it->it);
 }
 
 // removes from counterpart what is in rr.
@@ -737,29 +669,36 @@ int changeset_iter_all(changeset_iter_t *itt, const changeset_t *ch)
 knot_rrset_t changeset_iter_next(changeset_iter_t *it)
 {
        assert(it);
-       ptrnode_t *n = NULL;
+
        knot_rrset_t rr;
-       knot_rrset_init_empty(&rr);
-       WALK_LIST(n, it->iters) {
-               trie_it_t *t_it = (trie_it_t *)n->d;
-               if (trie_it_finished(t_it)) {
-                       continue;
+       while (it->node == NULL || it->node_pos >= it->node->rrset_count) {
+               if (it->node != NULL) {
+                       zone_tree_it_next(&it->it);
                }
-
-               rr = get_next_rr(it, t_it);
-               if (!knot_rrset_empty(&rr)) {
-                       // Got valid RRSet.
-                       return rr;
+               while (zone_tree_it_finished(&it->it)) {
+                       zone_tree_it_free(&it->it);
+                       if (--it->n_trees > 0) {
+                               for (size_t i = 0; i < it->n_trees; i++) {
+                                       it->trees[i] = it->trees[i + 1];
+                               }
+                               (void)zone_tree_it_begin(it->trees[0], &it->it);
+                       } else {
+                               knot_rrset_init_empty(&rr);
+                               return rr;
+                       }
                }
+               it->node = zone_tree_it_val(&it->it);
+               it->node_pos = 0;
        }
-
+       rr = node_rrset_at(it->node, it->node_pos++);
+       assert(!knot_rrset_empty(&rr));
        return rr;
 }
 
 void changeset_iter_clear(changeset_iter_t *it)
 {
        if (it) {
-               cleanup_iter_list(&it->iters);
+               zone_tree_it_free(&it->it);
                it->node = NULL;
                it->node_pos = 0;
        }
index 2cbd1bb9c1ee82f402d543c69bbf62dcf747928f..f64264d2ed28bb36e623714f8bd4b754da5d2c69 100644 (file)
@@ -43,6 +43,9 @@ typedef struct {
 /*! \brief Changeset iteration structure. */
 typedef struct {
        list_t iters;             /*!< List of pending zone iterators. */
+       zone_tree_t *trees[4];    /*!< Poiters to zone trees to iterate over. */
+       size_t n_trees;           /*!< Their count. */
+       zone_tree_it_t it;        /*!< Zone tree iterator. */
        const zone_node_t *node;  /*!< Current zone node. */
        uint16_t node_pos;        /*!< Position in node. */
 } changeset_iter_t;
index f55a1b023fbb4dd00e9cb2ae9c97f481586ab376..b9564d89543c2c7d8b174901cd0846586f5f9d32 100644 (file)
@@ -799,27 +799,25 @@ static int iter_init_tree_iters(zone_update_iter_t *it, zone_update_t *update,
 
        /* Begin iteration. We can safely assume _contents is a valid pointer. */
        zone_tree_t *tree = nsec3 ? _contents->nsec3_nodes : _contents->nodes;
-       it->tree_it = trie_it_begin(tree);
-       if (it->tree_it == NULL) {
+       if (zone_tree_it_begin(tree, &it->tree_it) != KNOT_EOK) {
                return KNOT_ENOMEM;
        }
 
-       it->cur_node = (zone_node_t *)(*trie_it_val(it->tree_it));
+       it->cur_node = zone_tree_it_val(&it->tree_it);
 
        return KNOT_EOK;
 }
 
 static int iter_get_next_node(zone_update_iter_t *it)
 {
-       trie_it_next(it->tree_it);
-       if (trie_it_finished(it->tree_it)) {
-               trie_it_free(it->tree_it);
-               it->tree_it = NULL;
+       zone_tree_it_next(&it->tree_it);
+       if (zone_tree_it_finished(&it->tree_it)) {
+               zone_tree_it_free(&it->tree_it);
                it->cur_node = NULL;
                return KNOT_ENOENT;
        }
 
-       it->cur_node = (zone_node_t *)(*trie_it_val(it->tree_it));
+       it->cur_node = zone_tree_it_val(&it->tree_it);
 
        return KNOT_EOK;
 }
@@ -835,7 +833,7 @@ static int iter_init(zone_update_iter_t *it, zone_update_t *update, const bool n
                return ret;
        }
 
-       it->cur_node = (zone_node_t *)(*trie_it_val(it->tree_it));
+       it->cur_node = zone_tree_it_val(&it->tree_it);
 
        return KNOT_EOK;
 }
@@ -877,7 +875,7 @@ int zone_update_iter_next(zone_update_iter_t *it)
                return KNOT_EINVAL;
        }
 
-       if (it->tree_it != NULL) {
+       if (it->tree_it.it != NULL) {
                int ret = iter_get_next_node(it);
                if (ret != KNOT_EOK && ret != KNOT_ENOENT) {
                        return ret;
@@ -902,7 +900,7 @@ void zone_update_iter_finish(zone_update_iter_t *it)
                return;
        }
 
-       trie_it_free(it->tree_it);
+       zone_tree_it_free(&it->tree_it);
 }
 
 bool zone_update_no_change(zone_update_t *update)
index 59eb3b9f119f1562ecc4e833350aa04baea4bcbc..27dd83a0223370f084d95209b67a85228ec42268 100644 (file)
@@ -36,7 +36,7 @@ typedef struct zone_update {
 
 typedef struct {
        zone_update_t *update;          /*!< The update we're iterating over. */
-       trie_it_t *tree_it;             /*!< Iterator for the new zone. */
+       zone_tree_it_t tree_it;         /*!< Iterator for the new zone. */
        const zone_node_t *cur_node;    /*!< Current node in the new zone. */
        bool nsec3;                     /*!< Set when we're using the NSEC3 node tree. */
 } zone_update_iter_t;
index 2bf6b47f66bcce3940093ece4d593eeed4b9e172..48eea2f3878e7e1170b6ba797123a8bbc356e491 100644 (file)
@@ -375,12 +375,12 @@ static int recreate_normal_tree(const zone_contents_t *z, zone_contents_t *out)
 
        // everything done, now just update "parent" and "apex" pointers
        out->apex = NULL;
-       trie_it_t *itt = trie_it_begin(out->nodes);
-       if (itt == NULL) {
+       zone_tree_it_t it = { 0 };
+       if (zone_tree_it_begin(out->nodes, &it) != KNOT_EOK) {
                return KNOT_ENOMEM;
        }
-       while (!trie_it_finished(itt)) {
-               zone_node_t *to_fix = (zone_node_t *)*trie_it_val(itt);
+       while (!zone_tree_it_finished(&it)) {
+               zone_node_t *to_fix = zone_tree_it_val(&it);
                if (out->apex == NULL && knot_dname_cmp(to_fix->owner, z->apex->owner) == 0) {
                        out->apex = to_fix;
                } else {
@@ -389,9 +389,9 @@ static int recreate_normal_tree(const zone_contents_t *z, zone_contents_t *out)
                        assert(parent != NULL);
                        node_set_parent(to_fix, parent);
                }
-               trie_it_next(itt);
+               zone_tree_it_next(&it);
        }
-       trie_it_free(itt);
+       zone_tree_it_free(&it);
        assert(out->apex != NULL);
 
        return KNOT_EOK;
@@ -404,16 +404,16 @@ static int recreate_nsec3_tree(const zone_contents_t *z, zone_contents_t *out)
                return KNOT_ENOMEM;
        }
 
-       trie_it_t *itt = trie_it_begin(z->nsec3_nodes);
-       if (itt == NULL) {
+       zone_tree_it_t it = { 0 };
+       if (zone_tree_it_begin(z->nsec3_nodes, &it) != KNOT_EOK) {
                return KNOT_ENOMEM;
        }
-       while (!trie_it_finished(itt)) {
-               zone_node_t *to_fix = (zone_node_t *)*trie_it_val(itt);
+       while (!zone_tree_it_finished(&it)) {
+               zone_node_t *to_fix = zone_tree_it_val(&it);
                to_fix->parent = out->apex;
-               trie_it_next(itt);
+               zone_tree_it_next(&it);
        }
-       trie_it_free(itt);
+       zone_tree_it_free(&it);
        return KNOT_EOK;
 }
 
index 0cfed7f0b212177aeffcf1c24987af3e551ccda4..486853bfb41ca01fa1052a4833818312b33f568b 100644 (file)
@@ -103,11 +103,15 @@ int zone_tree_get_less_or_equal(zone_tree_t *tree,
                 * cases like NSEC3, there is no such sort of thing (name wise).
                 */
                /*! \todo We could store rightmost node in zonetree probably. */
-               trie_it_t *i = trie_it_begin(tree);
-               *previous = *(zone_node_t **)trie_it_val(i); /* leftmost */
+               zone_tree_it_t it = { 0 };
+               ret = zone_tree_it_begin(tree, &it);
+               if (ret != KNOT_EOK) {
+                       return ret;
+               }
+               *previous = zone_tree_it_val(&it); /* leftmost */
                *previous = (*previous)->prev; /* rightmost */
                *found = NULL;
-               trie_it_free(i);
+               zone_tree_it_free(&it);
        }
 
        return exact_match;
@@ -175,6 +179,39 @@ int zone_tree_apply(zone_tree_t *tree, zone_tree_apply_cb_t function, void *data
        return trie_apply(tree, (int (*)(trie_val_t *, void *))function, data);
 }
 
+int zone_tree_it_begin(zone_tree_t *tree, zone_tree_it_t *it)
+{
+       if (it->tree == NULL) {
+               it->it = trie_it_begin((trie_t *)tree);
+               if (it->it == NULL) {
+                       return KNOT_ENOMEM;
+               }
+               it->tree = tree;
+       }
+       return KNOT_EOK;
+}
+
+bool zone_tree_it_finished(zone_tree_it_t *it)
+{
+       return it->it == NULL || trie_it_finished(it->it);
+}
+
+zone_node_t *zone_tree_it_val(zone_tree_it_t *it)
+{
+       return (zone_node_t *)*trie_it_val(it->it);
+}
+
+void zone_tree_it_next(zone_tree_it_t *it)
+{
+       trie_it_next(it->it);
+}
+
+void zone_tree_it_free(zone_tree_it_t *it)
+{
+       trie_it_free(it->it);
+       memset(it, 0, sizeof(*it));
+}
+
 void zone_tree_free(zone_tree_t **tree)
 {
        if (tree == NULL || *tree == NULL) {
index e31ae2c22df4439304eb957c91c4d550de586252..62091a7046185b5a4107a409d2251d016452f511 100644 (file)
@@ -26,6 +26,14 @@ typedef trie_t zone_tree_t;
  */
 typedef int (*zone_tree_apply_cb_t)(zone_node_t **node, void *data);
 
+/*!
+ * \brief Zone tree iteration context.
+ */
+typedef struct {
+       zone_tree_t *tree;
+       trie_it_t *it;
+} zone_tree_it_t;
+
 /*!
  * \brief Creates the zone tree.
  *
@@ -135,6 +143,40 @@ void zone_tree_delete_empty(zone_tree_t *tree, zone_node_t *node);
  */
 int zone_tree_apply(zone_tree_t *tree, zone_tree_apply_cb_t function, void *data);
 
+/*!
+ * \brief Start zone tree iteration.
+ *
+ * \param tree   Zone tree to iterate over.
+ * \param it     Out: iteration context. It shall be zeroed before.
+ *
+ * \return KNOT_OK, KNOT_ENOMEM
+ */
+int zone_tree_it_begin(zone_tree_t *tree, zone_tree_it_t *it);
+
+/*!
+ * \brief Return true iff iteration is finished.
+ *
+ * \note The iteration context needs to be freed afterwards nevertheless.
+ */
+bool zone_tree_it_finished(zone_tree_it_t *it);
+
+/*!
+ * \brief Return the node, zone iteration is currently pointing at.
+ *
+ * \note Don't call this when zone_tree_it_finished.
+ */
+zone_node_t *zone_tree_it_val(zone_tree_it_t *it);
+
+/*!
+ * \brief Move the iteration to next node.
+ */
+void zone_tree_it_next(zone_tree_it_t *it);
+
+/*!
+ * \brief Free zone iteration context.
+ */
+void zone_tree_it_free(zone_tree_it_t *it);
+
 /*!
  * \brief Destroys the zone tree, not touching the saved data.
  *