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) {
} 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 {
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)) {
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)
}
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);
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 {
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;
}
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;
}
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) {
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;
}
{
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);
node_free(node, NULL);
}
- trie_it_free(it);
+ zone_tree_it_free(&it);
zone_tree_free(&nodes);
}
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
break;
}
if (node->flags & NODE_FLAGS_NONAUTH || node->flags & NODE_FLAGS_EMPTY) {
- trie_it_next(it);
+ zone_tree_it_next(&it);
continue;
}
break;
}
- trie_it_next(it);
+ zone_tree_it_next(&it);
}
- trie_it_free(it);
+ zone_tree_it_free(&it);
return result;
}
{
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;
}
struct axfr_proc {
struct xfr_proc proc;
trie_it_t *i;
+ zone_tree_it_t it;
unsigned cur_rrset;
};
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;
}
{
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);
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.
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;
}
/*! \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;
/* 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;
}
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;
}
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;
return;
}
- trie_it_free(it->tree_it);
+ zone_tree_it_free(&it->tree_it);
}
bool zone_update_no_change(zone_update_t *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;
// 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 {
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;
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;
}
* 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;
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) {
*/
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.
*
*/
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.
*