Commit 32df9283 authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

zone tree: api for tree iteration, avoid iterating trie

parent cad0c3da
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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)
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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) {
......
......@@ -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);
/*!