Commit 475a2e80 authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

bi-nodes implemented, used for zone, updates, apply

parent 7b9cc47f
......@@ -291,7 +291,7 @@ static zone_node_t *create_nsec3_node(const knot_dname_t *owner,
assert(apex_node);
assert(rr_types);
zone_node_t *new_node = node_new(owner, NULL);
zone_node_t *new_node = node_new(owner, false, false, NULL);
if (!new_node) {
return NULL;
}
......@@ -508,7 +508,7 @@ static int create_nsec3_nodes(const zone_contents_t *zone,
if (result != KNOT_EOK) {
break;
}
if (node->flags & NODE_FLAGS_NONAUTH || node->flags & NODE_FLAGS_EMPTY) {
if (node->flags & NODE_FLAGS_NONAUTH || node->flags & NODE_FLAGS_EMPTY || node->flags & NODE_FLAGS_DELETED) {
zone_tree_it_next(&it);
continue;
}
......@@ -521,7 +521,7 @@ static int create_nsec3_nodes(const zone_contents_t *zone,
break;
}
result = zone_tree_insert(nsec3_nodes, nsec3_node);
result = zone_tree_insert(nsec3_nodes, &nsec3_node);
if (result != KNOT_EOK) {
break;
}
......@@ -631,6 +631,7 @@ static int fix_nsec3_for_node(zone_update_t *update, const dnssec_nsec3_params_t
ret = changeset_add_addition(chgset, &nsec3, CHANGESET_CHECK | CHANGESET_CHECK_CANCELOUT);
}
}
binode_unify(new_nsec3_n, false, NULL);
node_free_rrsets(new_nsec3_n, NULL);
node_free(new_nsec3_n, NULL);
}
......@@ -749,7 +750,7 @@ int knot_nsec3_create_chain(const zone_contents_t *zone,
int result;
zone_tree_t *nsec3_nodes = zone_tree_create();
zone_tree_t *nsec3_nodes = zone_tree_create(false);
if (!nsec3_nodes) {
return KNOT_ENOMEM;
}
......
......@@ -46,7 +46,7 @@ static int delete_nsec3_chain(const zone_contents_t *zone, changeset_t *changese
return KNOT_EOK;
}
zone_tree_t *empty_tree = zone_tree_create();
zone_tree_t *empty_tree = zone_tree_create(false);
if (!empty_tree) {
return KNOT_ENOMEM;
}
......
......@@ -193,7 +193,7 @@ static void xfr_log_publish(const struct refresh_data *data,
static int axfr_init(struct refresh_data *data)
{
zone_contents_t *new_zone = zone_contents_new(data->zone->name);
zone_contents_t *new_zone = zone_contents_new(data->zone->name, true);
if (new_zone == NULL) {
return KNOT_ENOMEM;
}
......
......@@ -183,7 +183,7 @@ static int add_rr_to_contents(zone_contents_t *z, const knot_rrset_t *rrset)
bool journal_read_changeset(journal_read_t *ctx, changeset_t *ch)
{
zone_contents_t *tree = zone_contents_new(ctx->zone);
zone_contents_t *tree = zone_contents_new(ctx->zone, false);
knot_rrset_t *soa = calloc(1, sizeof(*soa)), rr = { 0 };
if (tree == NULL || soa == NULL) {
ctx->txn.ret = KNOT_ENOMEM;
......@@ -203,7 +203,7 @@ bool journal_read_changeset(journal_read_t *ctx, changeset_t *ch)
ch->soa_from = soa;
ch->remove = tree;
soa = malloc(sizeof(*soa));
tree = zone_contents_new(ctx->zone);
tree = zone_contents_new(ctx->zone, false);
if (tree == NULL || soa == NULL) {
ctx->txn.ret = KNOT_ENOMEM;
goto fail;
......
This diff is collapsed.
......@@ -26,8 +26,6 @@ enum {
struct apply_ctx {
zone_contents_t *contents;
list_t old_data; /*!< Old data, to be freed after successful update. */
list_t new_data; /*!< New data, to be freed after failed update. */
zone_tree_t *node_ptrs; /*!< Just pointers to the affected nodes in contents. */
zone_tree_t *nsec3_ptrs; /*!< The same for NSEC3 nodes. */
uint32_t flags;
......
......@@ -122,7 +122,7 @@ static void check_redundancy(zone_contents_t *counterpart, const knot_rrset_t *r
// Remove empty node.
zone_tree_t *t = knot_rrset_is_nsec3rel(rr) ?
counterpart->nsec3_nodes : counterpart->nodes;
zone_tree_delete_empty(t, node);
zone_tree_del_node(t, node, (zone_tree_del_node_cb_t)node_free, NULL);
}
}
......@@ -134,11 +134,11 @@ int changeset_init(changeset_t *ch, const knot_dname_t *apex)
memset(ch, 0, sizeof(changeset_t));
// Init local changes
ch->add = zone_contents_new(apex);
ch->add = zone_contents_new(apex, false);
if (ch->add == NULL) {
return KNOT_ENOMEM;
}
ch->remove = zone_contents_new(apex);
ch->remove = zone_contents_new(apex, false);
if (ch->remove == NULL) {
zone_contents_free(ch->add);
return KNOT_ENOMEM;
......
......@@ -71,7 +71,7 @@ static int init_incremental(zone_update_t *update, zone_t *zone, zone_contents_t
static int init_full(zone_update_t *update, zone_t *zone)
{
update->new_cont = zone_contents_new(zone->name);
update->new_cont = zone_contents_new(zone->name, true);
if (update->new_cont == NULL) {
return KNOT_ENOMEM;
}
......@@ -681,6 +681,16 @@ static int commit_full(conf_t *conf, zone_update_t *update)
return ret;
}
static int check_unified(zone_node_t *node, void *data)
{
(void)data;
zone_node_t *counter = binode_counterpart(node);
assert((node->flags ^ counter->flags) == NODE_FLAGS_SECOND);
assert(node->rrset_count == counter->rrset_count);
assert(node->rrs == counter->rrs);
return KNOT_EOK;
}
int zone_update_commit(conf_t *conf, zone_update_t *update)
{
if (conf == NULL || update == NULL) {
......@@ -748,6 +758,9 @@ int zone_update_commit(conf_t *conf, zone_update_t *update)
update->a_ctx = NULL;
update->new_cont = NULL;
zone_contents_apply(update->zone->contents, check_unified, NULL);
zone_contents_nsec3_apply(update->zone->contents, check_unified, NULL);
/* Sync zonefile immediately if configured. */
val = conf_zone_get(conf, C_ZONEFILE_SYNC, update->zone->name);
if (conf_int(&val) == 0) {
......
......@@ -25,10 +25,7 @@ int adjust_cb_flags(zone_node_t *node, const zone_contents_t *zone)
{
zone_node_t *parent = node_parent(node);
// check if this node is not a wildcard child of its parent
if (knot_dname_is_wildcard(node->owner)) {
parent->flags |= NODE_FLAGS_WILDCARD_CHILD;
}
assert(!(node->flags & NODE_FLAGS_DELETED));
// set flags (delegation point, non-authoritative)
if (parent && (parent->flags & NODE_FLAGS_DELEG || parent->flags & NODE_FLAGS_NONAUTH)) {
......@@ -37,7 +34,7 @@ int adjust_cb_flags(zone_node_t *node, const zone_contents_t *zone)
node->flags |= NODE_FLAGS_DELEG;
} else {
// Default.
node->flags = NODE_FLAGS_AUTH | (node->flags & NODE_FLAGS_APEX);
node->flags &= ~(NODE_FLAGS_DELEG | NODE_FLAGS_NONAUTH);
}
return KNOT_EOK; // always returns this value :)
......@@ -75,7 +72,13 @@ int unadjust_cb_point_to_nsec3(zone_node_t *node, const zone_contents_t *zone)
int adjust_cb_wildcard_nsec3(zone_node_t *node, const zone_contents_t *zone)
{
free(node->nsec3_wildcard_name);
zone_node_t *counter = binode_counterpart(node);
assert(counter != NULL);
if (counter->nsec3_wildcard_name != node->nsec3_wildcard_name) {
// FIXME this should never happen, but it does
free(node->nsec3_wildcard_name);
}
node->nsec3_wildcard_name = NULL;
if (!knot_is_nsec3_enabled(zone)) {
return KNOT_EOK;
......@@ -118,6 +121,7 @@ static bool nsec3_params_match(const knot_rdataset_t *rrs,
int adjust_cb_nsec3_flags(zone_node_t *node, const zone_contents_t *zone)
{
// check if this node belongs to correct chain
node->flags &= ~NODE_FLAGS_IN_NSEC3_CHAIN;
const knot_rdataset_t *nsec3_rrs = node_rdataset(node, KNOT_RRTYPE_NSEC3);
for (uint16_t i = 0; nsec3_rrs != NULL && i < nsec3_rrs->count; i++) {
if (nsec3_params_match(nsec3_rrs, &zone->nsec3_params, i)) {
......@@ -128,15 +132,12 @@ int adjust_cb_nsec3_flags(zone_node_t *node, const zone_contents_t *zone)
}
/*! \brief Link pointers to additional nodes for this RRSet. */
static int discover_additionals(const knot_dname_t *owner, struct rr_data *rr_data,
static int discover_additionals(zone_node_t *adjn, uint16_t rr_at,
const zone_contents_t *zone)
{
struct rr_data *rr_data = &adjn->rrs[rr_at];
assert(rr_data != NULL);
/* Drop possible previous additional nodes. */
additional_clear(rr_data->additional);
rr_data->additional = NULL;
const knot_rdataset_t *rrs = &rr_data->rrs;
uint16_t rdcount = rrs->count;
......@@ -158,7 +159,7 @@ static int discover_additionals(const knot_dname_t *owner, struct rr_data *rr_da
glue_t *glue;
if ((node->flags & (NODE_FLAGS_DELEG | NODE_FLAGS_NONAUTH)) &&
rr_data->type == KNOT_RRTYPE_NS &&
knot_dname_in_bailiwick(node->owner, owner) >= 0) {
knot_dname_in_bailiwick(node->owner, adjn->owner) >= 0) {
glue = &mandatory[mandatory_count++];
glue->optional = false;
} else {
......@@ -171,26 +172,45 @@ static int discover_additionals(const knot_dname_t *owner, struct rr_data *rr_da
/* Store sorted additionals by the type, mandatory first. */
size_t total_count = mandatory_count + others_count;
additional_t *new_addit = NULL;
if (total_count > 0) {
rr_data->additional = malloc(sizeof(additional_t));
if (rr_data->additional == NULL) {
new_addit = malloc(sizeof(additional_t));
if (new_addit == NULL) {
return KNOT_ENOMEM;
}
rr_data->additional->count = total_count;
new_addit->count = total_count;
size_t size = total_count * sizeof(glue_t);
rr_data->additional->glues = malloc(size);
if (rr_data->additional->glues == NULL) {
free(rr_data->additional);
new_addit->glues = malloc(size);
if (new_addit->glues == NULL) {
free(new_addit);
return KNOT_ENOMEM;
}
size_t mandatory_size = mandatory_count * sizeof(glue_t);
memcpy(rr_data->additional->glues, mandatory, mandatory_size);
memcpy(rr_data->additional->glues + mandatory_count, others,
memcpy(new_addit->glues, mandatory, mandatory_size);
memcpy(new_addit->glues + mandatory_count, others,
size - mandatory_size);
}
/* If the result differs, shallow copy node and store additionals. */
if (!additional_equal(rr_data->additional, new_addit)) {
if (!binode_additional_shared(adjn, adjn->rrs[rr_at].type)) {
// FIXME this should never happen, but it does
additional_clear(adjn->rrs[rr_at].additional);
}
int ret = binode_prepare_change(adjn, NULL);
if (ret != KNOT_EOK) {
return ret;
}
rr_data = &adjn->rrs[rr_at];
rr_data->additional = new_addit;
} else {
additional_clear(new_addit);
}
return KNOT_EOK;
}
......@@ -200,7 +220,7 @@ int adjust_cb_additionals(zone_node_t *node, const zone_contents_t *zone)
for(uint16_t i = 0; i < node->rrset_count; ++i) {
struct rr_data *rr_data = &node->rrs[i];
if (knot_rrtype_additional_needed(rr_data->type)) {
int ret = discover_additionals(node->owner, rr_data, zone);
int ret = discover_additionals(node, i, zone);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -271,6 +291,10 @@ static int adjust_single(zone_node_t *node, void *data)
assert(node != NULL);
assert(data != NULL);
if ((node->flags & NODE_FLAGS_DELETED)) {
return KNOT_EOK;
}
zone_adjust_arg_t *args = (zone_adjust_arg_t *)data;
// remember first node
......
......@@ -25,38 +25,9 @@
#include "contrib/qp-trie/trie.h"
#include "contrib/macros.h"
/*!
* \brief Checks if the given node can be inserted into the given zone.
*
* Checks if both the arguments are non-NULL and if the owner of the node
* belongs to the zone (i.e. is a subdomain of the zone apex).
*
* \param zone Zone to which the node is going to be inserted.
* \param node Node to check.
*
* \retval KNOT_EOK if both arguments are non-NULL and the node belongs to the
* zone.
* \retval KNOT_EINVAL if either of the arguments is NULL.
* \retval KNOT_EOUTOFZONE if the node does not belong to the zone.
*/
static int check_node(const zone_contents_t *contents, const zone_node_t *node)
{
assert(contents);
assert(contents->apex != NULL);
assert(node);
if (knot_dname_in_bailiwick(node->owner, contents->apex->owner) <= 0) {
return KNOT_EOUTOFZONE;
}
return KNOT_EOK;
}
/*!
* \brief Destroys all RRSets in a node.
*
* This function is designed to be used in the tree-iterating functions.
*
* \param node Node to destroy RRSets from.
* \param data Unused parameter.
*/
......@@ -65,6 +36,7 @@ static int destroy_node_rrsets_from_tree(zone_node_t *node, void *data)
UNUSED(data);
if (node != NULL) {
binode_unify(node, false, NULL);
node_free_rrsets(node, NULL);
node_free(node, NULL);
}
......@@ -122,7 +94,7 @@ static bool find_in_tree(zone_tree_t *tree, const knot_dname_t *name,
return match > 0;
}
zone_contents_t *zone_contents_new(const knot_dname_t *apex_name)
zone_contents_t *zone_contents_new(const knot_dname_t *apex_name, bool use_binodes)
{
if (apex_name == NULL) {
return NULL;
......@@ -133,17 +105,17 @@ zone_contents_t *zone_contents_new(const knot_dname_t *apex_name)
return NULL;
}
contents->apex = node_new(apex_name, NULL);
if (contents->apex == NULL) {
contents->nodes = zone_tree_create(use_binodes);
if (contents->nodes == NULL) {
goto cleanup;
}
contents->nodes = zone_tree_create();
if (contents->nodes == NULL) {
contents->apex = node_new_for_contents(apex_name, contents);
if (contents->apex == NULL) {
goto cleanup;
}
if (zone_tree_insert(contents->nodes, contents->apex) != KNOT_EOK) {
if (zone_tree_insert(contents->nodes, &contents->apex) != KNOT_EOK) {
goto cleanup;
}
contents->apex->flags |= NODE_FLAGS_APEX;
......@@ -157,115 +129,34 @@ cleanup:
return NULL;
}
static zone_node_t *get_node(const zone_contents_t *zone, const knot_dname_t *name)
zone_node_t *node_new_for_contents(const knot_dname_t *owner, const zone_contents_t *contents)
{
assert(zone);
assert(name);
return zone_tree_get(zone->nodes, name);
return node_new(owner, (contents->nodes->flags & ZONE_TREE_USE_BINODES),
(contents->nodes->flags & ZONE_TREE_USE_BINODES) &&
(contents->nodes->flags & ZONE_TREE_BINO_SECOND), NULL);
}
static int add_node(zone_contents_t *zone, zone_node_t *node, bool create_parents)
zone_tree_t *zone_contents_tree_for_rr(zone_contents_t *contents, const knot_rrset_t *rr)
{
if (zone == NULL || node == NULL) {
return KNOT_EINVAL;
}
int ret = check_node(zone, node);
if (ret != KNOT_EOK) {
return ret;
}
ret = zone_tree_insert(zone->nodes, node);
if (ret != KNOT_EOK) {
return ret;
}
if (!create_parents) {
return KNOT_EOK;
}
bool nsec3rel = knot_rrset_is_nsec3rel(rr);
/* No parents for root domain. */
if (*node->owner == '\0') {
return KNOT_EOK;
}
zone_node_t *next_node = NULL;
const uint8_t *parent = knot_wire_next_label(node->owner, NULL);
if (knot_dname_is_equal(zone->apex->owner, parent)) {
node_set_parent(node, zone->apex);
// check if the node is not wildcard child of the parent
if (knot_dname_is_wildcard(node->owner)) {
zone->apex->flags |= NODE_FLAGS_WILDCARD_CHILD;
}
} else {
while (parent != NULL && !(next_node = get_node(zone, parent))) {
/* Create a new node. */
next_node = node_new(parent, NULL);
if (next_node == NULL) {
return KNOT_ENOMEM;
}
/* Insert node to a tree. */
ret = zone_tree_insert(zone->nodes, next_node);
if (ret != KNOT_EOK) {
node_free(next_node, NULL);
return ret;
}
/* Update node pointers. */
node_set_parent(node, next_node);
if (knot_dname_is_wildcard(node->owner)) {
next_node->flags |= NODE_FLAGS_WILDCARD_CHILD;
}
node = next_node;
parent = knot_wire_next_label(parent, NULL);
if (nsec3rel && contents->nsec3_nodes == NULL) {
contents->nsec3_nodes = zone_tree_create((contents->nodes->flags & ZONE_TREE_USE_BINODES));
if (contents->nsec3_nodes == NULL) {
return NULL;
}
// set the found parent (in the zone) as the parent of the last
// inserted node
node_set_parent(node, next_node);
contents->nsec3_nodes->flags = contents->nodes->flags;
}
return KNOT_EOK;
return nsec3rel ? contents->nsec3_nodes : contents->nodes;
}
static int add_nsec3_node(zone_contents_t *zone, zone_node_t *node)
static zone_node_t *get_node(const zone_contents_t *zone, const knot_dname_t *name)
{
if (zone == NULL || node == NULL) {
return KNOT_EINVAL;
}
int ret = check_node(zone, node);
if (ret != KNOT_EOK) {
return ret;
}
/* Create NSEC3 tree if not exists. */
if (zone->nsec3_nodes == NULL) {
zone->nsec3_nodes = zone_tree_create();
if (zone->nsec3_nodes == NULL) {
return KNOT_ENOMEM;
}
}
// how to know if this is successful??
ret = zone_tree_insert(zone->nsec3_nodes, node);
if (ret != KNOT_EOK) {
return ret;
}
// no parents to be created, the only parent is the zone apex
// set the apex as the parent of the node
node_set_parent(node, zone->apex);
// cannot be wildcard child, so nothing to be done
assert(zone);
assert(name);
return KNOT_EOK;
return zone_tree_get(zone->nodes, name);
}
static zone_node_t *get_nsec3_node(const zone_contents_t *zone,
......@@ -290,18 +181,10 @@ static int insert_rr(zone_contents_t *z, const knot_rrset_t *rr,
}
if (*n == NULL) {
*n = nsec3 ? get_nsec3_node(z, rr->owner) : get_node(z, rr->owner);
if (*n == NULL) {
// Create new, insert
*n = node_new(rr->owner, NULL);
if (*n == NULL) {
return KNOT_ENOMEM;
}
int ret = nsec3 ? add_nsec3_node(z, *n) : add_node(z, *n, true);
if (ret != KNOT_EOK) {
node_free(*n, NULL);
*n = NULL;
}
int ret = zone_tree_add_node(zone_contents_tree_for_rr(z, rr), z->apex, rr->owner,
(zone_tree_new_node_cb_t)node_new_for_contents, z, n);
if (ret != KNOT_EOK) {
return ret;
}
}
......@@ -342,7 +225,7 @@ static int remove_rr(zone_contents_t *z, const knot_rrset_t *rr,
node_remove_rdataset(node, rr->type);
// If node is empty now, delete it from zone tree.
if (node->rrset_count == 0 && node != z->apex) {
zone_tree_delete_empty(nsec3 ? z->nsec3_nodes : z->nodes, node);
zone_tree_del_node(nsec3 ? z->nsec3_nodes : z->nodes, node, (zone_tree_del_node_cb_t)node_free, NULL);
}
}
......@@ -352,53 +235,18 @@ static int remove_rr(zone_contents_t *z, const knot_rrset_t *rr,
static int recreate_normal_tree(const zone_contents_t *z, zone_contents_t *out)
{
out->nodes = trie_dup(z->nodes, (trie_dup_cb)node_shallow_copy, NULL);
out->nodes = zone_tree_dup(z->nodes);
if (out->nodes == NULL) {
return KNOT_ENOMEM;
}
// everything done, now just update "parent" and "apex" pointers
out->apex = NULL;
zone_tree_it_t it = { 0 };
if (zone_tree_it_begin(out->nodes, &it) != KNOT_EOK) {
return KNOT_ENOMEM;
}
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 {
const knot_dname_t *parname = knot_wire_next_label(to_fix->owner, NULL);
zone_node_t *parent = get_node(out, parname);
assert(parent != NULL);
node_set_parent(to_fix, parent);
}
zone_tree_it_next(&it);
}
zone_tree_it_free(&it);
assert(out->apex != NULL);
out->apex = binode_node(z->apex, (out->nodes->flags & ZONE_TREE_BINO_SECOND));
return KNOT_EOK;
}
static int recreate_nsec3_tree(const zone_contents_t *z, zone_contents_t *out)
{
out->nsec3_nodes = trie_dup(z->nsec3_nodes, (trie_dup_cb)node_shallow_copy, NULL);
if (out->nsec3_nodes == NULL) {
return KNOT_ENOMEM;
}
zone_tree_it_t it = { 0 };
if (zone_tree_it_begin(z->nsec3_nodes, &it) != KNOT_EOK) {
return KNOT_ENOMEM;
}
while (!zone_tree_it_finished(&it)) {
zone_node_t *to_fix = zone_tree_it_val(&it);
to_fix->parent = out->apex;
zone_tree_it_next(&it);
}
zone_tree_it_free(&it);
return KNOT_EOK;
out->nsec3_nodes = zone_tree_dup(z->nsec3_nodes);
return out->nsec3_nodes == NULL ? KNOT_ENOMEM : KNOT_EOK;
}
// Public API
......@@ -423,29 +271,6 @@ int zone_contents_remove_rr(zone_contents_t *z, const knot_rrset_t *rr,
return remove_rr(z, rr, n, knot_rrset_is_nsec3rel(rr));
}
zone_node_t *zone_contents_get_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset)
{
if (zone == NULL || rrset == NULL) {
return NULL;
}
const bool nsec3 = knot_rrset_is_nsec3rel(rrset);
zone_node_t *node = nsec3 ? get_nsec3_node(zone, rrset->owner) :
get_node(zone, rrset->owner);
if (node == NULL) {
node = node_new(rrset->owner, NULL);
int ret = nsec3 ? add_nsec3_node(zone, node) : add_node(zone, node, true);
if (ret != KNOT_EOK) {
node_free(node, NULL);
return NULL;
}
return node;
} else {
return node;
}
}
const zone_node_t *zone_contents_find_node(const zone_contents_t *zone, const knot_dname_t *name)
{
if (zone == NULL || name == NULL) {
......
......@@ -41,11 +41,22 @@ typedef struct zone_contents {
/*!
* \brief Allocate and create new zone contents.
*
* \param apex_name Name of the root node.
* \param apex_name Name of the root node.
* \param use_binodes Zone trees shall consist of bi-nodes to enable zone updates.
*
* \return New contents or NULL on error.
*/
zone_contents_t *zone_contents_new(const knot_dname_t *apex_name);
zone_contents_t *zone_contents_new(const knot_dname_t *apex_name, bool use_binodes);
/*!
* \brief Create a node suitable for inserting into this contents.
*/
zone_node_t *node_new_for_contents(const knot_dname_t *owner, const zone_contents_t *contents);
/*!
* \brief Returns zone tree for inserting given RR.
*/
zone_tree_t *zone_contents_tree_for_rr(zone_contents_t *contents, const knot_rrset_t *rr);
/*!
* \brief Add an RR to contents.
......@@ -69,16 +80,6 @@ int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t
*/
int zone_contents_remove_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t **n);
/*!
* \brief Get the node with this RR (the RR's owner).
*
* \param zone Contents to add to.
* \param rrset The RR to add.
*
* \return The searched node if it exists, a new added empty node or NULL on error.
*/
zone_node_t *zone_contents_get_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset);
/*!
* \brief Tries to find a node with the specified name in the zone.
*
......
......@@ -17,7 +17,6 @@
#include "knot/zone/node.h"
#include "libknot/libknot.h"
#include "contrib/macros.h"
#include "contrib/mempattern.h"
void additional_clear(additional_t *additional)
{
......@@ -29,11 +28,28 @@ void additional_clear(additional_t *additional)
free(additional);
}
bool additional_equal(additional_t *a, additional_t *b)
{
if (a == NULL || b == NULL || a->count != b->count) {
return false;
}
for (int i = 0; i < a->count; i++) {
glue_t *ag = &a->glues[i], *bg = &b->glues[i];
if (ag->ns_pos != bg->ns_pos ||
ag->optional != bg->optional ||
binode_node((zone_node_t *)ag->node, false) !=
binode_node((zone_node_t *)bg->node, false)) {
return false;
}
}
return true;
}
/*! \brief Clears allocated data in RRSet entry. */
static void rr_data_clear(struct rr_data *data, knot_mm_t *mm)
{
knot_rdataset_clear(&data->rrs, mm);
additional_clear(data->additional);
memset(data, 0, sizeof(*data));
}
/*! \brief Clears allocated data in RRSet entry. */
......@@ -84,9 +100,9 @@ static bool ttl_changed(struct rr_data *node_data, const knot_rrset_t *rrset)
return rrset->ttl != node_data->ttl;
}
zone_node_t *node_new(const knot_dname_t *owner, knot_mm_t *mm)
zone_node_t *node_new(const knot_dname_t *owner, bool binode, bool second, knot_mm_t *mm)
{
zone_node_t *ret = mm_alloc(mm, sizeof(zone_node_t));
zone_node_t *ret = mm_alloc(mm, (binode ? 2 : 1) * sizeof(zone_node_t));
if (ret == NULL) {
return NULL;
}
......@@ -102,10 +118,128 @@ zone_node_t *node_new(const knot_dname_t *owner, knot_mm_t *mm)
// Node is authoritative by default.
ret->flags = NODE_FLAGS_AUTH;
if (second) {
ret->flags |= NODE_FLAGS_DELETED;
}
if (binode) {
ret->flags |= NODE_FLAGS_BINODE;