Commit 9ec432e9 authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

Adjust refactor

parent 42951122
......@@ -212,6 +212,8 @@ src/knot/worker/pool.c
src/knot/worker/pool.h
src/knot/worker/queue.c
src/knot/worker/queue.h
src/knot/zone/adjust.c
src/knot/zone/adjust.h
src/knot/zone/contents.c
src/knot/zone/contents.h
src/knot/zone/node.c
......
......@@ -147,6 +147,8 @@ libknotd_la_SOURCES = \
knot/worker/pool.h \
knot/worker/queue.c \
knot/worker/queue.h \
knot/zone/adjust.c \
knot/zone/adjust.h \
knot/zone/contents.c \
knot/zone/contents.h \
knot/zone/node.c \
......
......@@ -50,11 +50,6 @@ static int sign_init(zone_contents_t *zone, zone_sign_flags_t flags, zone_sign_r
}
}
r = zone_contents_adjust_full(zone);
if (r != KNOT_EOK) {
return r;
}
// update policy based on the zone content
update_policy_from_zone(ctx->policy, zone);
......
......@@ -26,6 +26,7 @@
#include "knot/dnssec/key_records.h"
#include "knot/dnssec/rrset-sign.h"
#include "knot/dnssec/zone-sign.h"
#include "knot/zone/adjust.h"
#include "libknot/libknot.h"
#include "contrib/dynarray.h"
#include "contrib/macros.h"
......@@ -1197,8 +1198,7 @@ int knot_zone_sign_update(zone_update_t *update,
int ret = KNOT_EOK;
ret = apply_prepare_to_sign(update->a_ctx);
ret = zone_adjust_update(update, adjust_cb_flags_and_additionals, adjust_cb_nsec3_flags);
if (ret != KNOT_EOK) {
return ret;
}
......
......@@ -212,12 +212,7 @@ static int axfr_finalize(struct refresh_data *data)
{
zone_contents_t *new_zone = data->axfr.zone;
int ret = zone_contents_adjust_full(new_zone);
if (ret != KNOT_EOK) {
return ret;
}
ret = xfr_validate(new_zone, data);
int ret = xfr_validate(new_zone, data);
if (ret != KNOT_EOK) {
return ret;
}
......
......@@ -218,16 +218,30 @@ static int apply_single(apply_ctx_t *ctx, const changeset_t *chset)
/* ------------------------------- API -------------------------------------- */
void apply_init_ctx(apply_ctx_t *ctx, zone_contents_t *contents, uint32_t flags)
int apply_init_ctx(apply_ctx_t *ctx, zone_contents_t *contents, uint32_t flags)
{
assert(ctx);
if (ctx == NULL) {
return KNOT_EINVAL;
}
ctx->contents = contents;
init_list(&ctx->old_data);
init_list(&ctx->new_data);
ctx->node_ptrs = zone_tree_create();
if (ctx->node_ptrs == NULL) {
return KNOT_ENOMEM;
}
ctx->nsec3_ptrs = zone_tree_create();
if (ctx->nsec3_ptrs == NULL) {
zone_tree_free(&ctx->node_ptrs);
return KNOT_ENOMEM;
}
ctx->flags = flags;
return KNOT_EOK;
}
int apply_prepare_zone_copy(zone_contents_t *old_contents,
......@@ -265,6 +279,8 @@ int apply_add_rr(apply_ctx_t *ctx, const knot_rrset_t *rr)
if (node == NULL) {
return KNOT_ENOMEM;
}
zone_tree_insert(knot_rrset_is_nsec3rel(rr) ? ctx->nsec3_ptrs : ctx->node_ptrs, node);
// re-inserting makes no harm
knot_rrset_t changed_rrset = node_rrset(node, rr->type);
if (!knot_rrset_empty(&changed_rrset)) {
......@@ -327,8 +343,9 @@ int apply_remove_rr(apply_ctx_t *ctx, const knot_rrset_t *rr)
return KNOT_EOK;
}
zone_tree_t *tree = knot_rrset_is_nsec3rel(rr) ?
contents->nsec3_nodes : contents->nodes;
bool nsec3 = knot_rrset_is_nsec3rel(rr);
zone_tree_insert(nsec3 ? ctx->nsec3_ptrs : ctx->node_ptrs, node);
zone_tree_t *tree = nsec3 ? contents->nsec3_nodes : contents->nodes;
knot_rrset_t removed_rrset = node_rrset(node, rr->type);
knot_rdata_t *old_data = removed_rrset.rrs.rdata;
......@@ -364,6 +381,7 @@ int apply_remove_rr(apply_ctx_t *ctx, 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 != contents->apex) {
zone_tree_remove_node(nsec3 ? ctx->nsec3_ptrs: ctx->node_ptrs, node->owner);
zone_tree_delete_empty(tree, node);
}
}
......@@ -393,11 +411,6 @@ int apply_replace_soa(apply_ctx_t *ctx, const changeset_t *chset)
return apply_add_rr(ctx, chset->soa_to);
}
int apply_prepare_to_sign(apply_ctx_t *ctx)
{
return zone_contents_adjust_pointers(ctx->contents);
}
int apply_changesets_directly(apply_ctx_t *ctx, list_t *chsets)
{
if (ctx == NULL || ctx->contents == NULL || chsets == NULL) {
......@@ -412,7 +425,7 @@ int apply_changesets_directly(apply_ctx_t *ctx, list_t *chsets)
}
}
return zone_contents_adjust_full(ctx->contents);
return KNOT_EOK;
}
int apply_changeset_directly(apply_ctx_t *ctx, const changeset_t *ch)
......@@ -427,26 +440,18 @@ int apply_changeset_directly(apply_ctx_t *ctx, const changeset_t *ch)
return ret;
}
ret = zone_contents_adjust_full(ctx->contents);
if (ret != KNOT_EOK) {
update_rollback(ctx);
return ret;
}
return KNOT_EOK;
}
int apply_finalize(apply_ctx_t *ctx)
{
return zone_contents_adjust_full(ctx->contents);
}
void update_cleanup(apply_ctx_t *ctx)
{
if (ctx == NULL) {
return;
}
zone_tree_free(&ctx->node_ptrs);
zone_tree_free(&ctx->nsec3_ptrs);
// Delete old RR data
rrs_list_clear(&ctx->old_data, NULL);
init_list(&ctx->old_data);
......@@ -461,6 +466,9 @@ void update_rollback(apply_ctx_t *ctx)
return;
}
zone_tree_free(&ctx->node_ptrs);
zone_tree_free(&ctx->nsec3_ptrs);
// Delete new RR data
rrs_list_clear(&ctx->new_data, NULL);
init_list(&ctx->new_data);
......
......@@ -28,6 +28,8 @@ 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;
};
......@@ -39,8 +41,10 @@ typedef struct apply_ctx apply_ctx_t;
* \param ctx Context to be initialized.
* \param contents Zone contents to apply changes onto.
* \param flags Flags to control the application process.
*
* \return KNOT_E*
*/
void apply_init_ctx(apply_ctx_t *ctx, zone_contents_t *contents, uint32_t flags);
int apply_init_ctx(apply_ctx_t *ctx, zone_contents_t *contents, uint32_t flags);
/*!
* \brief Creates a shallow zone contents copy.
......@@ -83,17 +87,6 @@ int apply_remove_rr(apply_ctx_t *ctx, const knot_rrset_t *rr);
*/
int apply_replace_soa(apply_ctx_t *ctx, const changeset_t *ch);
/*!
* \brief Prepares the new zone contents for signing.
*
* Adjusted pointers are required for DNSSEC.
*
* \param ctx Apply context.
*
* \return KNOT_E*
*/
int apply_prepare_to_sign(apply_ctx_t *ctx);
/*!
* \brief Applies changesets directly to the zone, without copying it.
*
......@@ -116,17 +109,6 @@ int apply_changesets_directly(apply_ctx_t *ctx, list_t *chsets);
*/
int apply_changeset_directly(apply_ctx_t *ctx, const changeset_t *ch);
/*!
* \brief Finalizes the zone contents for publishing.
*
* Fully adjusts the zone.
*
* \param ctx Apply context.
*
* \return KNOT_E*
*/
int apply_finalize(apply_ctx_t *ctx);
/*!
* \brief Cleanups successful zone update.
*
......
......@@ -17,6 +17,7 @@
#include "knot/common/log.h"
#include "knot/dnssec/zone-events.h"
#include "knot/updates/zone-update.h"
#include "knot/zone/adjust.h"
#include "knot/zone/serial.h"
#include "knot/zone/zone-diff.h"
#include "contrib/mempattern.h"
......@@ -50,7 +51,11 @@ static int init_incremental(zone_update_t *update, zone_t *zone, zone_contents_t
}
uint32_t apply_flags = update->flags & UPDATE_STRICT ? APPLY_STRICT : 0;
apply_init_ctx(update->a_ctx, update->new_cont, apply_flags);
ret = apply_init_ctx(update->a_ctx, update->new_cont, apply_flags);
if (ret != KNOT_EOK) {
changeset_clear(&update->change);
return ret;
}
/* Copy base SOA RR. */
update->change.soa_from =
......@@ -73,7 +78,11 @@ static int init_full(zone_update_t *update, zone_t *zone)
update->new_cont_deep_copy = true;
apply_init_ctx(update->a_ctx, update->new_cont, 0);
int ret = apply_init_ctx(update->a_ctx, update->new_cont, 0);
if (ret != KNOT_EOK) {
zone_contents_free(update->new_cont);
return ret;
}
return KNOT_EOK;
}
......@@ -224,7 +233,12 @@ int zone_update_from_contents(zone_update_t *update, zone_t *zone_without_conten
}
uint32_t apply_flags = update->flags & UPDATE_STRICT ? APPLY_STRICT : 0;
apply_init_ctx(update->a_ctx, update->new_cont, apply_flags);
int ret = apply_init_ctx(update->a_ctx, update->new_cont, apply_flags);
if (ret != KNOT_EOK) {
changeset_clear(&update->change);
free(update->a_ctx);
return ret;
}
return KNOT_EOK;
}
......@@ -584,23 +598,13 @@ int zone_update_increment_soa(zone_update_t *update, conf_t *conf)
return set_new_soa(update, conf_opt(&val));
}
static int commit_incremental(conf_t *conf, zone_update_t *update,
zone_contents_t **contents_out)
static int commit_incremental(conf_t *conf, zone_update_t *update)
{
assert(update);
assert(contents_out);
if (changeset_empty(&update->change)) {
changeset_clear(&update->change);
if (update->zone->contents == NULL || update->new_cont_deep_copy) {
*contents_out = update->new_cont;
}
return KNOT_EOK;
}
zone_contents_t *new_contents = update->new_cont;
int ret = KNOT_EOK;
if (zone_update_to(update) == NULL) {
if (zone_update_to(update) == NULL && !changeset_empty(&update->change)) {
/* No SOA in the update, create one according to the current policy */
ret = zone_update_increment_soa(update, conf);
if (ret != KNOT_EOK) {
......@@ -609,7 +613,7 @@ static int commit_incremental(conf_t *conf, zone_update_t *update,
}
}
ret = apply_finalize(update->a_ctx);
ret = zone_adjust_full(new_contents);
if (ret != KNOT_EOK) {
zone_update_clear(update);
return ret;
......@@ -617,22 +621,19 @@ static int commit_incremental(conf_t *conf, zone_update_t *update,
/* Write changes to journal if all went well. */
conf_val_t val = conf_zone_get(conf, C_JOURNAL_CONTENT, update->zone->name);
if (conf_opt(&val) != JOURNAL_CONTENT_NONE) {
if (conf_opt(&val) != JOURNAL_CONTENT_NONE && !changeset_empty(&update->change)) {
ret = zone_change_store(conf, update->zone, &update->change);
if (ret != KNOT_EOK) {
return ret;
}
}
*contents_out = new_contents;
return KNOT_EOK;
}
static int commit_full(conf_t *conf, zone_update_t *update, zone_contents_t **contents_out)
static int commit_full(conf_t *conf, zone_update_t *update)
{
assert(update);
assert(contents_out);
/* Check if we have SOA. We might consider adding full semantic check here.
* But if we wanted full sem-check I'd consider being it controlled by a flag
......@@ -641,7 +642,7 @@ static int commit_full(conf_t *conf, zone_update_t *update, zone_contents_t **co
return KNOT_ESEMCHECK;
}
int ret = zone_contents_adjust_full(update->new_cont);
int ret = zone_adjust_full(update->new_cont);
if (ret != KNOT_EOK) {
zone_update_clear(update);
return ret;
......@@ -655,8 +656,6 @@ static int commit_full(conf_t *conf, zone_update_t *update, zone_contents_t **co
ret = zone_changes_clear(conf, update->zone);
}
*contents_out = update->new_cont;
return ret;
}
......@@ -703,26 +702,25 @@ int zone_update_commit(conf_t *conf, zone_update_t *update)
}
int ret = KNOT_EOK;
zone_contents_t *new_contents = NULL;
if (update->flags & UPDATE_INCREMENTAL) {
ret = commit_incremental(conf, update, &new_contents);
if (changeset_empty(&update->change) &&
update->zone->contents != NULL && !update->new_cont_deep_copy) {
changeset_clear(&update->change);
return KNOT_EOK;
}
ret = commit_incremental(conf, update);
} else {
ret = commit_full(conf, update, &new_contents);
ret = commit_full(conf, update);
}
if (ret != KNOT_EOK) {
return ret;
}
/* If there is anything to change. */
if (new_contents == NULL) {
return KNOT_EOK;
}
/* Check the zone size. */
conf_val_t val = conf_zone_get(conf, C_MAX_ZONE_SIZE, update->zone->name);
size_t size_limit = conf_int(&val);
if (new_contents->size > size_limit) {
if (update->new_cont->size > size_limit) {
/* Recoverable error. */
return KNOT_EZONESIZE;
}
......@@ -737,7 +735,7 @@ int zone_update_commit(conf_t *conf, zone_update_t *update)
/* Switch zone contents. */
zone_contents_t *old_contents;
old_contents = zone_switch_contents(update->zone, new_contents);
old_contents = zone_switch_contents(update->zone, update->new_cont);
/* Sync RCU. */
if (update->flags & UPDATE_FULL) {
......
This diff is collapsed.
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "knot/zone/contents.h"
#include "knot/updates/zone-update.h"
typedef int (*adjust_cb_t)(zone_node_t *, const zone_contents_t *);
/*
* \brief Varoius callbacks for adjusting zone node's params and pointers.
*
* \param node Node to be adjusted. Must be already inside the zone contents!
* \param zone Zone being adjusted.
*
* \return KNOT_E*
*/
// fix NORMAL node flags, like NODE_FLAGS_NONAUTH, NODE_FLAGS_DELEG etc.
int adjust_cb_flags(zone_node_t *node, const zone_contents_t *zone);
// fix NORMAL node pointer to corresponding NSEC3 node
int adjust_cb_point_to_nsec3(zone_node_t *node, const zone_contents_t *zone);
// fix NORMAL node pointer to NSEC3 node proving nonexistence of wildcard
int adjust_cb_wildcard_nsec3(zone_node_t *node, const zone_contents_t *zone);
// fix NSEC3 node flags: NODE_FLAGS_IN_NSEC3_CHAIN
int adjust_cb_nsec3_flags(zone_node_t *node, const zone_contents_t *zone);
// fix NORMAL node flags to additionals, like NS records and glue...
int adjust_cb_additionals(zone_node_t *node, const zone_contents_t *zone);
// adjust_cb_flags and adjust_cb_additionals at once
int adjust_cb_flags_and_additionals(zone_node_t *node, const zone_contents_t *zone);
// adjust_cb_flags and adjust_cb_flags at once
int adjust_cb_flags_and_nsec3(zone_node_t *node, const zone_contents_t *zone);
// adjust_cb_point_to_nsec3, adjust_cb_wildcard_nsec3 and adjust_cb_additionals at once
int adjust_cb_nsec3_and_additionals(zone_node_t *node, const zone_contents_t *zone);
// dummy callback, just make prev pointers adjusting and zone size measuring work
int adjust_cb_void(zone_node_t *node, const zone_contents_t *zone);
/*!
* \brief Apply callback to NSEC3 and NORMAL nodes. Fix PREV pointers and measure zone size.
*
* \param zone Zone to be adjusted.
* \param nodes_cb Callback for NORMAL nodes.
* \param nsec3_cb Callback for NSEC3 nodes.
*
* \return KNOT_E*
*/
int zone_adjust_contents(zone_contents_t *zone, adjust_cb_t nodes_cb, adjust_cb_t nsec3_cb);
/*!
* \brief Apply callback to nodes affected by the zone update.
*
* \note Fixing PREV pointers and zone measurement does not make sense since we are not
* iterating over whole zone. The same applies for callback that reference other
* (unchanged, but indirecty affected) zone nodes.
*
* \param update Zone update being finalized.
* \param nodes_cb Callback for NORMAL nodes.
* \param nsec3_cb Callback for NSEC3 nodes.
*
* \return KNOT_E*
*/
int zone_adjust_update(zone_update_t *update, adjust_cb_t nodes_cb, adjust_cb_t nsec3_cb);
/*!
* \brief Do a general-purpose full update.
*
* This operates in two phases, first fix basic node flags and prev pointers,
* than nsec3-related pointers and additionals.
*
* \param zone Zone to be adjusted.
*
* \return KNOT_E*
*/
int zone_adjust_full(zone_contents_t *zone);
This diff is collapsed.
......@@ -173,22 +173,6 @@ int zone_contents_find_nsec3_for_name(const zone_contents_t *contents,
const zone_node_t *zone_contents_find_wildcard_child(const zone_contents_t *contents,
const zone_node_t *parent);
/*!
* \brief Sets parent and previous pointers and node flags. (cheap operation)
* For both normal and NSEC3 tree
*
* \param contents Zone contents to be adjusted.
*/
int zone_contents_adjust_pointers(zone_contents_t *contents);
/*!
* \brief Sets parent and previous pointers, sets node flags and NSEC3 links.
* This has to be called before the zone can be served.
*
* \param contents Zone contents to be adjusted.
*/
int zone_contents_adjust_full(zone_contents_t *contents);
/*!
* \brief Applies the given function to each regular node in the zone.
*
......
......@@ -16,6 +16,7 @@
#include "knot/zone/node.h"
#include "libknot/libknot.h"
#include "contrib/macros.h"
#include "contrib/mempattern.h"
void additional_clear(additional_t *additional)
......@@ -310,3 +311,20 @@ bool node_bitmap_equal(const zone_node_t *a, const zone_node_t *b)
}
return true;
}
void node_size(const zone_node_t *node, size_t *size)
{
int rrset_count = node->rrset_count;
for (int i = 0; i < rrset_count; i++) {
knot_rrset_t rrset = node_rrset_at(node, i);
*size += knot_rrset_size(&rrset);
}
}
void node_max_ttl(const zone_node_t *node, uint32_t *max)
{
int rrset_count = node->rrset_count;
for (int i = 0; i < rrset_count; i++) {
*max = MAX(*max, node->rrs[i].ttl);
}
}
......@@ -276,3 +276,19 @@ static inline knot_rrset_t node_rrset_at(const zone_node_t *node, size_t pos)
rrset.additional = rr_data->additional;
return rrset;
}
/*!
* \brief Compute node size.
*
* \param node Node in question.
* \param size In/out: node size will be added to this value.
*/
void node_size(const zone_node_t *node, size_t *size);
/*!
* \brief Compute node maximum TTL.
*
* \param node Node in question.
* \param size In/out: this value will be maximalized with max TTL of node rrsets.
*/
void node_max_ttl(const zone_node_t *node, uint32_t *max);
......@@ -85,7 +85,11 @@ int zone_load_journal(conf_t *conf, zone_t *zone, zone_contents_t *contents)
/* Apply changesets. */
apply_ctx_t a_ctx = { 0 };
apply_init_ctx(&a_ctx, contents, 0);
ret = apply_init_ctx(&a_ctx, contents, 0);
if (ret != KNOT_EOK) {
changesets_free(&chgs);
return ret;
}
ret = apply_changesets_directly(&a_ctx, &chgs);
if (ret == KNOT_EOK) {
......@@ -126,7 +130,12 @@ int zone_load_from_journal(conf_t *conf, zone_t *zone, zone_contents_t **content
}
apply_ctx_t a_ctx = { 0 };
apply_init_ctx(&a_ctx, *contents, 0);
ret = apply_init_ctx(&a_ctx, *contents, 0);
if (ret != KNOT_EOK) {
changesets_free(&chgs);
return ret;
}
ret = apply_changesets_directly(&a_ctx, &chgs);
if (ret == KNOT_EOK) {
log_zone_info(zone->name, "zone loaded from journal, serial %u",
......
......@@ -114,11 +114,9 @@ int zone_tree_get_less_or_equal(zone_tree_t *tree,
}
/*! \brief Removes node with the given owner from the zone tree. */
static void remove_node(zone_tree_t *tree, const knot_dname_t *owner)
void zone_tree_remove_node(zone_tree_t *tree, const knot_dname_t *owner)
{
assert(owner);
if (zone_tree_is_empty(tree)) {
if (zone_tree_is_empty(tree) || owner == NULL) {
return;
}
......@@ -159,7 +157,7 @@ void zone_tree_delete_empty(zone_tree_t *tree, zone_node_t *node)
}
// Delete node
remove_node(tree, node->owner);
zone_tree_remove_node(tree, node->owner);
node_free(node, NULL);
}
}
......
......@@ -107,6 +107,14 @@ int zone_tree_get_less_or_equal(zone_tree_t *tree,
zone_node_t **found,
zone_node_t **previous);
/*!
* \brief Remove a node from a tree with no checks.
*
* \param tree The tree to remove from.
* \param owner The node to remove.
*/
void zone_tree_remove_node(zone_tree_t *tree, const knot_dname_t *owner);
/*!
* \brief Delete a node that has no RRSets and no children.
*
......
......@@ -30,6 +30,7 @@
#include "knot/common/log.h"
#include "knot/dnssec/zone-nsec.h"
#include "knot/zone/semantic-check.h"
#include "knot/zone/adjust.h"
#include "knot/zone/contents.h"
#include "knot/zone/zonefile.h"
#include "knot/zone/zone-dump.h"
......@@ -225,7 +226,7 @@ zone_contents_t *zonefile_load(zloader_t *loader)
goto fail;
}
ret = zone_contents_adjust_full(zc->z);
ret = zone_adjust_contents(zc->z, adjust_cb_flags_and_nsec3, adjust_cb_nsec3_flags);
if (ret != KNOT_EOK) {
ERROR(zname, "failed to finalize zone contents (%s)",
knot_strerror(ret));
......
......@@ -18,6 +18,7 @@
#include "test_conf.h"
#include "knot/server/server.h"
#include "knot/zone/adjust.h"
#include "contrib/mempattern.h"
/* Some domain names. */
......@@ -52,7 +53,7 @@ static inline void create_root_zone(server_t *server, knot_mm_t *mm)
knot_rrset_free(soa, mm);
/* Bake the zone. */
zone_contents_adjust_full(root->contents);
(void)zone_adjust_full(root->contents);
/* Switch zone db. */
knot_zonedb_free(&server->zone_db);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment