Commit 5f0b9863 authored by Dominik Taborsky's avatar Dominik Taborsky
Browse files

zone_update: apply changes right away

parent 3945b506
......@@ -145,7 +145,7 @@ static int connect_nsec_nodes(zone_node_t *a, zone_node_t *b,
}
// Add new NSEC to the changeset (no matter if old was removed)
ret = changeset_add_rrset(data->changeset, &new_nsec, 0);
ret = changeset_add_addition(data->changeset, &new_nsec, 0);
knot_rdataset_clear(&new_nsec.rrs, NULL);
return ret;
}
......@@ -223,7 +223,7 @@ int knot_nsec_changeset_remove(const zone_node_t *n,
}
if (!knot_rrset_empty(&nsec)) {
// update changeset
result = changeset_rem_rrset(changeset, &nsec, 0);
result = changeset_add_removal(changeset, &nsec, 0);
if (result != KNOT_EOK) {
return result;
}
......@@ -251,7 +251,7 @@ int knot_nsec_changeset_remove(const zone_node_t *n,
}
// store RRSIG
result = changeset_rem_rrset(changeset, &synth_rrsigs, 0);
result = changeset_add_removal(changeset, &synth_rrsigs, 0);
knot_rdataset_clear(&synth_rrsigs.rrs, NULL);
}
......
......@@ -239,7 +239,7 @@ static int remove_nsec3param(const zone_contents_t *zone, changeset_t *changeset
assert(changeset);
knot_rrset_t rrset = node_rrset(zone->apex, KNOT_RRTYPE_NSEC3PARAM);
int ret = changeset_rem_rrset(changeset, &rrset, 0);
int ret = changeset_add_removal(changeset, &rrset, 0);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -253,7 +253,7 @@ static int remove_nsec3param(const zone_contents_t *zone, changeset_t *changeset
return ret;
}
ret = changeset_rem_rrset(changeset, &rrsig, 0);
ret = changeset_add_removal(changeset, &rrsig, 0);
knot_rdataset_clear(&rrsig.rrs, NULL);
if (ret != KNOT_EOK) {
return ret;
......@@ -307,7 +307,7 @@ static int add_nsec3param(const zone_contents_t *zone, changeset_t *changeset,
return r;
}
r = changeset_add_rrset(changeset, rrset, 0);
r = changeset_add_addition(changeset, rrset, 0);
knot_rrset_free(&rrset, NULL);
return r;
}
......
......@@ -286,7 +286,7 @@ static int remove_expired_rrsigs(const knot_rrset_t *covered,
}
if (!knot_rrset_empty(&to_remove) && result == KNOT_EOK) {
result = changeset_rem_rrset(changeset, &to_remove, 0);
result = changeset_add_removal(changeset, &to_remove, 0);
}
knot_rdataset_clear(&synth_rrsig.rrs, NULL);
......@@ -341,7 +341,7 @@ static int add_missing_rrsigs(const knot_rrset_t *covered,
}
if (!knot_rrset_empty(&to_add) && result == KNOT_EOK) {
result = changeset_add_rrset(changeset, &to_add, 0);
result = changeset_add_addition(changeset, &to_add, 0);
}
knot_rdataset_clear(&to_add.rrs, NULL);
......@@ -374,7 +374,7 @@ static int remove_rrset_rrsigs(const knot_dname_t *owner, uint16_t type,
return KNOT_EOK;
}
ret = changeset_rem_rrset(changeset, &synth_rrsig, 0);
ret = changeset_add_removal(changeset, &synth_rrsig, 0);
knot_rdataset_clear(&synth_rrsig.rrs, NULL);
return ret;
......@@ -460,7 +460,7 @@ static int remove_standalone_rrsigs(const zone_node_t *node,
if (ret != KNOT_EOK) {
return ret;
}
ret = changeset_rem_rrset(changeset, &to_remove, 0);
ret = changeset_add_removal(changeset, &to_remove, 0);
knot_rdataset_clear(&to_remove.rrs, NULL);
if (ret != KNOT_EOK) {
return ret;
......@@ -742,7 +742,7 @@ static int remove_invalid_dnskeys(const knot_rrset_t *soa,
}
if (!knot_rrset_empty(&to_remove) && result == KNOT_EOK) {
result = changeset_rem_rrset(changeset, &to_remove, 0);
result = changeset_add_removal(changeset, &to_remove, 0);
}
knot_rdataset_clear(&to_remove.rrs, NULL);
......@@ -798,7 +798,7 @@ static int add_missing_dnskeys(const knot_rrset_t *soa,
}
if (!knot_rrset_empty(&to_add) && result == KNOT_EOK) {
result = changeset_add_rrset(changeset, &to_add, 0);
result = changeset_add_addition(changeset, &to_add, 0);
}
knot_rdataset_clear(&to_add.rrs, NULL);
......
......@@ -495,13 +495,13 @@ static int solve_soa_add(const knot_rrset_t *rr, changeset_t *change, knot_mm_t
/*! \brief Adds single RR into remove section of changeset. */
static int solve_del(const knot_rrset_t *rr, changeset_t *change, knot_mm_t *mm)
{
return changeset_rem_rrset(change, rr, 0);
return changeset_add_removal(change, rr, 0);
}
/*! \brief Adds single RR into add section of changeset. */
static int solve_add(const knot_rrset_t *rr, changeset_t *change, knot_mm_t *mm)
{
return changeset_add_rrset(change, rr, 0);
return changeset_add_addition(change, rr, 0);
}
/*! \brief Decides what the next IXFR-in state should be. */
......
......@@ -742,10 +742,10 @@ static int changesets_unpack(changeset_t *chs)
} else {
/* Remove RRSets. */
if (in_remove_section) {
ret = changeset_rem_rrset(chs, &rrset, 0);
ret = changeset_add_removal(chs, &rrset, 0);
} else {
/* Add RRSets. */
ret = changeset_add_rrset(chs, &rrset, 0);
ret = changeset_add_addition(chs, &rrset, 0);
}
}
knot_rrset_clear(&rrset, NULL);
......
......@@ -146,9 +146,23 @@ static bool can_remove(const zone_node_t *node, const knot_rrset_t *rr)
}
/*! \brief Removes single RR from zone contents. */
static int remove_rr(apply_ctx_t *ctx, zone_tree_t *tree, zone_node_t *node,
const knot_rrset_t *rr, changeset_t *chset)
int apply_remove_rr(apply_ctx_t *ctx, zone_contents_t *contents,
const knot_rrset_t *rr)
{
// Find node for this owner
zone_node_t *node = zone_contents_find_node_for_rr(contents, rr);
if (!can_remove(node, rr)) {
// Cannot be removed, either no node or nonexistent RR
if (ctx->flags & APPLY_STRICT) {
// Don't ignore missing RR if strict. Required for IXFR.
return KNOT_ENORECORD;
}
return KNOT_EOK;
}
zone_tree_t *tree = knot_rrset_is_nsec3rel(rr) ?
contents->nsec3_nodes : contents->nodes;
knot_rrset_t removed_rrset = node_rrset(node, rr->type);
knot_rdata_t *old_data = removed_rrset.rrs.data;
int ret = replace_rdataset_with_copy(node, rr->type);
......@@ -198,23 +212,7 @@ static int apply_remove(apply_ctx_t *ctx, zone_contents_t *contents, changeset_t
knot_rrset_t rr = changeset_iter_next(&itt);
while (!knot_rrset_empty(&rr)) {
// Find node for this owner
zone_node_t *node = zone_contents_find_node_for_rr(contents, &rr);
if (!can_remove(node, &rr)) {
// Cannot be removed, either no node or nonexistent RR
if (ctx->flags & APPLY_STRICT) {
// Don't ignore missing RR if strict. Required for IXFR.
changeset_iter_clear(&itt);
return KNOT_ENORECORD;
}
rr = changeset_iter_next(&itt);
continue;
}
zone_tree_t *tree = knot_rrset_is_nsec3rel(&rr) ?
contents->nsec3_nodes : contents->nodes;
int ret = remove_rr(ctx, tree, node, &rr, chset);
int ret = apply_remove_rr(ctx, contents, &rr);
if (ret != KNOT_EOK) {
changeset_iter_clear(&itt);
return ret;
......@@ -228,9 +226,15 @@ static int apply_remove(apply_ctx_t *ctx, zone_contents_t *contents, changeset_t
}
/*! \brief Adds a single RR into zone contents. */
static int add_rr(apply_ctx_t *ctx, const zone_contents_t *zone, zone_node_t *node,
const knot_rrset_t *rr, changeset_t *chset)
int apply_add_rr(apply_ctx_t *ctx, zone_contents_t *zone,
const knot_rrset_t *rr)
{
// Get or create node with this owner
zone_node_t *node = zone_contents_get_node_for_rr(zone, rr);
if (node == NULL) {
return KNOT_ENOMEM;
}
knot_rrset_t changed_rrset = node_rrset(node, rr->type);
if (!knot_rrset_empty(&changed_rrset)) {
// Modifying existing RRSet.
......@@ -278,14 +282,7 @@ static int apply_add(apply_ctx_t *ctx, zone_contents_t *contents, changeset_t *c
knot_rrset_t rr = changeset_iter_next(&itt);
while(!knot_rrset_empty(&rr)) {
// Get or create node with this owner
zone_node_t *node = zone_contents_get_node_for_rr(contents, &rr);
if (node == NULL) {
changeset_iter_clear(&itt);
return KNOT_ENOMEM;
}
int ret = add_rr(ctx, contents, node, &rr, chset);
int ret = apply_add_rr(ctx, contents, &rr);
if (ret != KNOT_EOK) {
changeset_iter_clear(&itt);
return ret;
......@@ -298,10 +295,10 @@ static int apply_add(apply_ctx_t *ctx, zone_contents_t *contents, changeset_t *c
}
/*! \brief Replace old SOA with a new one. */
static int apply_replace_soa(apply_ctx_t *ctx, zone_contents_t *contents, changeset_t *chset)
int apply_replace_soa(apply_ctx_t *ctx, zone_contents_t *contents, changeset_t *chset)
{
assert(chset->soa_from && chset->soa_to);
int ret = remove_rr(ctx, contents->nodes, contents->apex, chset->soa_from, chset);
int ret = apply_remove_rr(ctx, contents, chset->soa_from);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -311,7 +308,7 @@ static int apply_replace_soa(apply_ctx_t *ctx, zone_contents_t *contents, change
return KNOT_EINVAL;
}
return add_rr(ctx, contents, contents->apex, chset->soa_to, chset);
return apply_add_rr(ctx, contents, chset->soa_to);
}
/*! \brief Apply single change to zone contents structure. */
......@@ -347,7 +344,7 @@ static int apply_single(apply_ctx_t *ctx, zone_contents_t *contents, changeset_t
/* --------------------- Zone copy and finalization ------------------------- */
/*! \brief Creates a shallow zone contents copy. */
static int prepare_zone_copy(zone_contents_t *old_contents,
int apply_prepare_zone_copy(zone_contents_t *old_contents,
zone_contents_t **new_contents)
{
if (old_contents == NULL || new_contents == NULL) {
......@@ -397,7 +394,7 @@ int apply_changesets(apply_ctx_t *ctx, zone_t *zone, list_t *chsets, zone_conten
}
zone_contents_t *contents_copy = NULL;
int ret = prepare_zone_copy(old_contents, &contents_copy);
int ret = apply_prepare_zone_copy(old_contents, &contents_copy);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -441,7 +438,7 @@ int apply_changeset(apply_ctx_t *ctx, zone_t *zone, changeset_t *change, zone_co
}
zone_contents_t *contents_copy = NULL;
int ret = prepare_zone_copy(old_contents, &contents_copy);
int ret = apply_prepare_zone_copy(old_contents, &contents_copy);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -535,12 +532,14 @@ void update_rollback(apply_ctx_t *ctx)
void update_free_zone(zone_contents_t **contents)
{
zone_tree_apply((*contents)->nodes, free_additional, NULL);
zone_tree_deep_free(&(*contents)->nodes);
zone_tree_deep_free(&(*contents)->nsec3_nodes);
if (contents && *contents) {
zone_tree_apply((*contents)->nodes, free_additional, NULL);
zone_tree_deep_free(&(*contents)->nodes);
zone_tree_deep_free(&(*contents)->nsec3_nodes);
dnssec_nsec3_params_free(&(*contents)->nsec3_params);
dnssec_nsec3_params_free(&(*contents)->nsec3_params);
free(*contents);
*contents = NULL;
free(*contents);
*contents = NULL;
}
}
......@@ -48,6 +48,20 @@ typedef struct apply_ctx apply_ctx_t;
*/
void apply_init_ctx(apply_ctx_t *ctx, uint32_t flags);
/*! \brief Removes single RR from zone contents. */
int apply_remove_rr(apply_ctx_t *ctx, zone_contents_t *contents,
const knot_rrset_t *rr);
/*! \brief Adds a single RR into zone contents. */
int apply_add_rr(apply_ctx_t *ctx, zone_contents_t *contents,
const knot_rrset_t *rr);
int apply_replace_soa(apply_ctx_t *ctx, zone_contents_t *contents, changeset_t *chset);
/*! \brief Creates a shallow zone contents copy. */
int apply_prepare_zone_copy(zone_contents_t *old_contents,
zone_contents_t **new_contents);
/*!
* \brief Applies changesets *with* zone shallow copy.
*
......
......@@ -256,7 +256,7 @@ size_t changeset_size(const changeset_t *ch)
return size;
}
int changeset_add_rrset(changeset_t *ch, const knot_rrset_t *rrset, unsigned flags)
int changeset_add_addition(changeset_t *ch, const knot_rrset_t *rrset, unsigned flags)
{
if (!ch || !rrset) {
return KNOT_EINVAL;
......@@ -288,7 +288,7 @@ int changeset_add_rrset(changeset_t *ch, const knot_rrset_t *rrset, unsigned fla
return ret;
}
int changeset_rem_rrset(changeset_t *ch, const knot_rrset_t *rrset, unsigned flags)
int changeset_add_removal(changeset_t *ch, const knot_rrset_t *rrset, unsigned flags)
{
if (!ch || !rrset) {
return KNOT_EINVAL;
......@@ -320,6 +320,36 @@ int changeset_rem_rrset(changeset_t *ch, const knot_rrset_t *rrset, unsigned fla
return ret;
}
int changeset_remove_addition(changeset_t *ch, const knot_rrset_t *rrset)
{
if (rrset->type == KNOT_RRTYPE_SOA) {
/* Do not add SOAs into actual contents. */
if (ch->soa_to != NULL) {
knot_rrset_free(&ch->soa_to, NULL);
ch->soa_to = NULL;
}
return KNOT_EOK;
}
zone_node_t *n = NULL;
return zone_contents_remove_rr(ch->add, rrset, &n);
}
int changeset_remove_removal(changeset_t *ch, const knot_rrset_t *rrset)
{
if (rrset->type == KNOT_RRTYPE_SOA) {
/* Do not add SOAs into actual contents. */
if (ch->soa_from != NULL) {
knot_rrset_free(&ch->soa_from, NULL);
ch->soa_from = NULL;
}
return KNOT_EOK;
}
zone_node_t *n = NULL;
return zone_contents_remove_rr(ch->remove, rrset, &n);
}
int changeset_merge(changeset_t *ch1, const changeset_t *ch2)
{
changeset_iter_t itt;
......@@ -327,7 +357,7 @@ int changeset_merge(changeset_t *ch1, const changeset_t *ch2)
knot_rrset_t rrset = changeset_iter_next(&itt);
while (!knot_rrset_empty(&rrset)) {
int ret = changeset_add_rrset(ch1, &rrset, CHANGESET_CHECK);
int ret = changeset_add_addition(ch1, &rrset, CHANGESET_CHECK);
if (ret != KNOT_EOK) {
changeset_iter_clear(&itt);
return ret;
......@@ -340,7 +370,7 @@ int changeset_merge(changeset_t *ch1, const changeset_t *ch2)
rrset = changeset_iter_next(&itt);
while (!knot_rrset_empty(&rrset)) {
int ret = changeset_rem_rrset(ch1, &rrset, CHANGESET_CHECK);
int ret = changeset_add_removal(ch1, &rrset, CHANGESET_CHECK);
if (ret != KNOT_EOK) {
changeset_iter_clear(&itt);
return ret;
......
......@@ -99,7 +99,7 @@ size_t changeset_size(const changeset_t *ch);
*
* \return KNOT_E*
*/
int changeset_add_rrset(changeset_t *ch, const knot_rrset_t *rrset, unsigned flags);
int changeset_add_addition(changeset_t *ch, const knot_rrset_t *rrset, unsigned flags);
/*!
* \brief Add RRSet to 'remove' part of changeset.
......@@ -110,7 +110,28 @@ int changeset_add_rrset(changeset_t *ch, const knot_rrset_t *rrset, unsigned fla
*
* \return KNOT_E*
*/
int changeset_rem_rrset(changeset_t *ch, const knot_rrset_t *rrset, unsigned flags);
int changeset_add_removal(changeset_t *ch, const knot_rrset_t *rrset, unsigned flags);
/*!
* \brief Remove an RRSet from the 'add' part of changeset.
*
* \param ch Changeset to add RRSet into.
* \param rrset RRSet to be added.
*
* \return KNOT_E*
*/
int changeset_remove_addition(changeset_t *ch, const knot_rrset_t *rrset);
/*!
* \brief Remove an RRSet from the 'remove' part of changeset.
*
* \param ch Changeset to add RRSet into.
* \param rrset RRSet to be added.
*
* \return KNOT_E*
*/
int changeset_remove_removal(changeset_t *ch, const knot_rrset_t *rrset);
/*!
* \brief Merges two changesets together. Legacy, to be removed with new zone API.
......
......@@ -538,15 +538,20 @@ static int process_rem_node(const knot_rrset_t *rr,
return KNOT_EOK;
}
zone_node_t *node_copy = node_shallow_copy(node, NULL);
// Remove all RRSets from node
for (int i = 0; i < node->rrset_count; ++i) {
knot_rrset_t rrset = node_rrset_at(node, i);
int ret = process_rem_rrset(&rrset, node, update);
size_t rrset_count = node_copy->rrset_count;
for (int i = 0; i < rrset_count; ++i) {
knot_rrset_t rrset = node_rrset_at(node_copy, rrset_count - i - 1);
int ret = process_rem_rrset(&rrset, node_copy, update);
if (ret != KNOT_EOK) {
return ret;
}
}
node_free(&node_copy, NULL);
return KNOT_EOK;
}
......
......@@ -24,109 +24,6 @@
#include <urcu.h>
static int add_to_node(zone_node_t *node, const zone_node_t *add_node,
knot_mm_t *mm)
{
for (uint16_t i = 0; i < add_node->rrset_count; ++i) {
knot_rrset_t rr = node_rrset_at(add_node, i);
if (!knot_rrset_empty(&rr)) {
int ret = node_add_rrset(node, &rr, mm);
if (ret != KNOT_EOK) {
return ret;
}
}
}
return KNOT_EOK;
}
static int rem_from_node(zone_node_t *node, const zone_node_t *rem_node,
knot_mm_t *mm)
{
for (uint16_t i = 0; i < rem_node->rrset_count; ++i) {
/* Remove each found RR from 'node'. */
knot_rrset_t rem_rrset = node_rrset_at(rem_node, i);
knot_rdataset_t *to_change = node_rdataset(node, rem_rrset.type);
if (to_change) {
/* Remove data from synthesized node */
int ret = knot_rdataset_subtract(to_change,
&rem_rrset.rrs,
mm);
if (ret != KNOT_EOK) {
return ret;
}
/* Remove whole rdataset if empty */
if (to_change->rr_count == 0) {
node_remove_rdataset(node, rem_rrset.type);
}
}
}
return KNOT_EOK;
}
static int apply_changes_to_node(zone_node_t *synth_node, const zone_node_t *add_node,
const zone_node_t *rem_node, knot_mm_t *mm)
{
/* Add changes to node */
if (!node_empty(add_node)) {
int ret = add_to_node(synth_node, add_node, mm);
if (ret != KNOT_EOK) {
return ret;
}
}
/* Remove changes from node */
if (!node_empty(rem_node)) {
int ret = rem_from_node(synth_node, rem_node, mm);
if (ret != KNOT_EOK) {
return ret;
}
}
return KNOT_EOK;
}
static int deep_copy_node_data(zone_node_t *node_copy, const zone_node_t *node,
knot_mm_t *mm)
{
/* Clear space for RRs */
node_copy->rrs = NULL;
node_copy->rrset_count = 0;
for (uint16_t i = 0; i < node->rrset_count; ++i) {
knot_rrset_t rr = node_rrset_at(node, i);
int ret = node_add_rrset(node_copy, &rr, mm);
if (ret != KNOT_EOK) {
return ret;
}
}
return KNOT_EOK;
}
static zone_node_t *node_deep_copy(const zone_node_t *node, knot_mm_t *mm)
{
if (node == NULL) {
return NULL;
}
/* Shallow copy old node */
zone_node_t *synth_node = node_shallow_copy(node, mm);
if (synth_node == NULL) {
return NULL;
}
/* Deep copy data inside node copy. */
int ret = deep_copy_node_data(synth_node, node, mm);
if (ret != KNOT_EOK) {
node_free(&synth_node, mm);
return NULL;
}
return synth_node;
}
static int init_incremental(zone_update_t *update, zone_t *zone)
{
if (zone->contents == NULL) {
......@@ -138,10 +35,21 @@ static int init_incremental(zone_update_t *update, zone_t *zone)
return ret;
}
ret = apply_prepare_zone_copy(zone->contents, &update->new_cont);
if (ret != KNOT_EOK) {
changeset_clear(&update->change);
return ret;
}
//! \todo is there a better way?
update->a_ctx.apex = update->new_cont->apex;
/* Copy base SOA RR. */
update->change.soa_from =
node_create_rrset(update->zone->contents->apex, KNOT_RRTYPE_SOA);
if (update->change.soa_from == NULL) {
changeset_clear(&update->change);
zone_contents_free(&update->new_cont);
return KNOT_ENOMEM;
}
......@@ -158,79 +66,6 @@ static int init_full(zone_update_t *update, zone_t *zone)
return KNOT_EOK;
}
static const zone_node_t *get_synth_node(zone_update_t *update, const knot_dname_t *dname)
{
const zone_node_t *old_node =
zone_contents_find_node(update->zone->contents, dname);
if (old_node == update->zone->contents->apex && update->change.soa_to != NULL) {
/* We have an apex and a SOA change, make a copy and apply the change. */
zone_node_t *synth_node = node_deep_copy(old_node, &update->mm);
if (synth_node == NULL) {
return NULL;
}
/* Remove the old SOA */
knot_rdataset_t *from = node_rdataset(synth_node, KNOT_RRTYPE_SOA);
knot_rdataset_t *what = node_rdataset(old_node, KNOT_RRTYPE_SOA);
int ret = knot_rdataset_subtract(from, what, &update->mm);
if (ret != KNOT_EOK) {
node_free_rrsets(synth_node, &update->mm);
node_free(&synth_node, &update->mm);
return NULL;
}
/* Add the new SOA */
ret = node_add_rrset(synth_node, update->change.soa_to, &update->mm);
if (ret != KNOT_EOK) {
node_free_rrsets(synth_node, &update->mm);
node_free(&synth_node, &update->mm);
return NULL;
}