Commit db0f3f25 authored by Jan Kadlec's avatar Jan Kadlec

changeset: API cleanup, doxygen

parent 6e584395
......@@ -371,7 +371,7 @@ static int solve_soa_del(const knot_rrset_t *rr, struct ixfr_proc *proc)
}
// Create new changeset.
changeset_t *change = changeset_new(proc->mm, proc->zone->name);
changeset_t *change = changeset_new(proc->zone->name);
if (change == NULL) {
return KNOT_ENOMEM;
}
......
......@@ -85,14 +85,16 @@ static int sign_update(zone_t *zone, const zone_contents_t *old_contents,
assert(ddns_ch != NULL);
changeset_t sec_ch;
changeset_init(&sec_ch, zone->name, NULL);
int ret = changeset_init(&sec_ch, zone->name);
if (ret != KNOT_EOK) {
return ret;
}
/*
* Check if the UPDATE changed DNSKEYs or NSEC3PARAM.
* If yes, signing just the changes is insufficient, we have to sign
* the whole zone.
*/
int ret = KNOT_EOK;
uint32_t refresh_at = 0;
if (zones_dnskey_changed(old_contents, new_contents) ||
zones_nsec3param_changed(old_contents, new_contents)) {
......@@ -151,7 +153,11 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata)
// Create DDNS change
changeset_t ddns_ch;
changeset_init(&ddns_ch, qdata->zone->name, NULL);
ret = changeset_init(&ddns_ch, qdata->zone->name);
if (ret != KNOT_EOK) {
*rcode = KNOT_RCODE_SERVFAIL;
return ret;
}
ret = ddns_process_update(zone, query, &ddns_ch, rcode);
if (ret != KNOT_EOK) {
......
......@@ -1146,7 +1146,7 @@ finish:
static int load_changeset(journal_t *journal, journal_node_t *n, const zone_t *zone, list_t *chgs)
{
changeset_t *ch = changeset_new(NULL, zone->name);
changeset_t *ch = changeset_new(zone->name);
if (ch == NULL) {
return KNOT_ENOMEM;
}
......
......@@ -36,41 +36,129 @@ static int add_rr_to_zone(zone_contents_t *z, const knot_rrset_t *rrset)
return ret;
}
void changeset_init(changeset_t *ch, const knot_dname_t *apex, mm_ctx_t *mm)
static void cleanup_iter_list(list_t *l)
{
memset(ch, 0, sizeof(changeset_t));
ptrnode_t *n, *nxt;
WALK_LIST_DELSAFE(n, nxt, *l) {
hattrie_iter_t *it = (hattrie_iter_t *)n->d;
hattrie_iter_free(it);
rem_node(&n->n);
free(n);
}
init_list(l);
}
static int changeset_iter_init(changeset_iter_t *ch_it,
const changeset_t *ch, bool sorted, size_t tries, ...)
{
memset(ch_it, 0, sizeof(*ch_it));
init_list(&ch_it->iters);
va_list args;
va_start(args, tries);
for (size_t i = 0; i < tries; ++i) {
hattrie_t *t = va_arg(args, hattrie_t *);
if (t) {
if (sorted) {
hattrie_build_index(t);
}
hattrie_iter_t *it = hattrie_iter_begin(t, sorted);
if (it == NULL) {
cleanup_iter_list(&ch_it->iters);
return KNOT_ENOMEM;
}
if (ptrlist_add(&ch_it->iters, it, NULL) == NULL) {
cleanup_iter_list(&ch_it->iters);
return KNOT_ENOMEM;
}
}
}
va_end(args);
return KNOT_EOK;
}
static void iter_next_node(changeset_iter_t *ch_it, hattrie_iter_t *t_it)
{
assert(!hattrie_iter_finished(t_it));
// Get next node, but not for the very first call.
if (ch_it->node) {
hattrie_iter_next(t_it);
}
if (hattrie_iter_finished(t_it)) {
ch_it->node = NULL;
return;
}
ch_it->node = (zone_node_t *)*hattrie_iter_val(t_it);
assert(ch_it->node);
while (ch_it->node && ch_it->node->rrset_count == 0) {
// Skip empty non-terminals.
hattrie_iter_next(t_it);
if (hattrie_iter_finished(t_it)) {
ch_it->node = NULL;
} else {
ch_it->node = (zone_node_t *)*hattrie_iter_val(t_it);
assert(ch_it->node);
}
}
ch_it->node_pos = 0;
}
static knot_rrset_t get_next_rr(changeset_iter_t *ch_it, hattrie_iter_t *t_it) // pun intented
{
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(hattrie_iter_finished(t_it));
knot_rrset_t rr;
knot_rrset_init_empty(&rr);
return rr;
}
}
ch->mm = mm;
return node_rrset_at(ch_it->node, ch_it->node_pos++);
}
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);
if (ch->add == NULL) {
return KNOT_ENOMEM;
}
ch->remove = zone_contents_new(apex);
if (ch->remove == NULL) {
zone_contents_free(&ch->add);
return KNOT_ENOMEM;
}
// Init change lists
init_list(&ch->new_data);
init_list(&ch->old_data);
return KNOT_EOK;
}
changeset_t *changeset_new(mm_ctx_t *mm, const knot_dname_t *apex)
changeset_t *changeset_new(const knot_dname_t *apex)
{
changeset_t *ret = mm_alloc(mm, sizeof(changeset_t));
changeset_t *ret = malloc(sizeof(changeset_t));
if (ret == NULL) {
ERR_ALLOC_FAILED;
return NULL;
}
changeset_init(ret, apex, mm);
if (changeset_init(ret, apex) == KNOT_EOK) {
return ret;
}
int changeset_add_rrset(changeset_t *ch, const knot_rrset_t *rrset)
{
return add_rr_to_zone(ch->add, rrset);
}
int changeset_rem_rrset(changeset_t *ch, const knot_rrset_t *rrset)
{
return add_rr_to_zone(ch->remove, rrset);
} else {
free(ret);
return NULL;
}
}
bool changeset_empty(const changeset_t *ch)
......@@ -112,9 +200,18 @@ size_t changeset_size(const changeset_t *ch)
return size;
}
int changeset_merge(changeset_t *ch1, changeset_t *ch2)
int changeset_add_rrset(changeset_t *ch, const knot_rrset_t *rrset)
{
return add_rr_to_zone(ch->add, rrset);
}
int changeset_rem_rrset(changeset_t *ch, const knot_rrset_t *rrset)
{
return add_rr_to_zone(ch->remove, rrset);
}
int changeset_merge(changeset_t *ch1, const changeset_t *ch2)
{
#warning slow slow slow slow
changeset_iter_t itt;
changeset_iter_add(&itt, ch2, false);
......@@ -144,37 +241,16 @@ int changeset_merge(changeset_t *ch1, changeset_t *ch2)
// Use soa_to and serial from the second changeset
// soa_to from the first changeset is redundant, delete it
knot_rrset_t *soa_copy = knot_rrset_copy(ch2->soa_to, NULL);
if (soa_copy == NULL) {
return KNOT_ENOMEM;
}
knot_rrset_free(&ch1->soa_to, NULL);
knot_rrset_free(&ch2->soa_from, NULL);
ch1->soa_to = ch2->soa_to;
ch2->soa_to = NULL;
ch1->soa_to = soa_copy;
return KNOT_EOK;
}
void changeset_clear(changeset_t *ch)
{
if (ch == NULL) {
return;
}
// Delete RRSets in lists, in case there are any left
zone_contents_deep_free(&ch->add);
zone_contents_deep_free(&ch->remove);
knot_rrset_free(&ch->soa_from, NULL);
knot_rrset_free(&ch->soa_to, NULL);
// Delete binary data
free(ch->data);
}
void changeset_free(changeset_t *ch)
{
changeset_clear(ch);
free(ch);
}
void changesets_clear(list_t *chgs)
{
if (chgs) {
......@@ -199,47 +275,27 @@ void changesets_free(list_t *chgs)
}
}
static void cleanup_iter_list(list_t *l)
void changeset_clear(changeset_t *ch)
{
ptrnode_t *n, *nxt;
WALK_LIST_DELSAFE(n, nxt, *l) {
hattrie_iter_t *it = (hattrie_iter_t *)n->d;
hattrie_iter_free(it);
rem_node(&n->n);
free(n);
if (ch == NULL) {
return;
}
init_list(l);
}
static int changeset_iter_init(changeset_iter_t *ch_it,
const changeset_t *ch, bool sorted, size_t tries, ...)
{
memset(ch_it, 0, sizeof(*ch_it));
init_list(&ch_it->iters);
// Delete RRSets in lists, in case there are any left
zone_contents_deep_free(&ch->add);
zone_contents_deep_free(&ch->remove);
va_list args;
va_start(args, tries);
for (size_t i = 0; i < tries; ++i) {
hattrie_t *t = va_arg(args, hattrie_t *);
if (t) {
if (sorted) {
hattrie_build_index(t);
}
hattrie_iter_t *it = hattrie_iter_begin(t, sorted);
if (it == NULL) {
cleanup_iter_list(&ch_it->iters);
return KNOT_ENOMEM;
}
if (ptrlist_add(&ch_it->iters, it, NULL) == NULL) {
cleanup_iter_list(&ch_it->iters);
return KNOT_ENOMEM;
}
}
}
knot_rrset_free(&ch->soa_from, NULL);
knot_rrset_free(&ch->soa_to, NULL);
va_end(args);
// Delete binary data
free(ch->data);
}
return KNOT_EOK;
void changeset_free(changeset_t *ch)
{
changeset_clear(ch);
free(ch);
}
int changeset_iter_add(changeset_iter_t *itt, const changeset_t *ch, bool sorted)
......@@ -261,49 +317,6 @@ int changeset_iter_all(changeset_iter_t *itt, const changeset_t *ch, bool sorted
ch->remove->nodes, ch->remove->nsec3_nodes);
}
static void iter_next_node(changeset_iter_t *ch_it, hattrie_iter_t *t_it)
{
assert(!hattrie_iter_finished(t_it));
// Get next node, but not for the very first call.
if (ch_it->node) {
hattrie_iter_next(t_it);
}
if (hattrie_iter_finished(t_it)) {
ch_it->node = NULL;
return;
}
ch_it->node = (zone_node_t *)*hattrie_iter_val(t_it);
assert(ch_it->node);
while (ch_it->node && ch_it->node->rrset_count == 0) {
// Skip empty non-terminals.
hattrie_iter_next(t_it);
if (hattrie_iter_finished(t_it)) {
ch_it->node = NULL;
} else {
ch_it->node = (zone_node_t *)*hattrie_iter_val(t_it);
assert(ch_it->node);
}
}
ch_it->node_pos = 0;
}
static knot_rrset_t get_next_rr(changeset_iter_t *ch_it, hattrie_iter_t *t_it) // pun intented
{
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(hattrie_iter_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++);
}
knot_rrset_t changeset_iter_next(changeset_iter_t *it)
{
assert(it);
......
......@@ -3,9 +3,9 @@
*
* \author Jan Kadlec <jan.kadlec@nic.cz>
*
* \brief Structure for representing IXFR/DDNS changeset and its API.
* \brief Structure for representing zone change and its API.
*
* \addtogroup xfr
* \addtogroup server
* @{
*/
/* Copyright (C) 2013 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
......@@ -29,54 +29,52 @@
#include "libknot/rrset.h"
#include "knot/zone/contents.h"
#include "common/lists.h"
#include "common/mempattern.h"
/*----------------------------------------------------------------------------*/
/*! \brief One zone change, from 'soa_from' to 'soa_to'. */
typedef struct changeset {
typedef struct {
node_t n; /*!< List node. */
mm_ctx_t *mm; /*!< Memory context */
knot_rrset_t *soa_from; /*!< Start SOA. */
zone_contents_t *add;
zone_contents_t *remove;
knot_rrset_t *soa_to; /*!< Destination SOA. */
uint8_t *data; /*!< Serialized changeset. */
size_t size; /*!< Size of serialized changeset. */
zone_contents_t *add; /*!< Change additions. */
zone_contents_t *remove; /*!< Change removals. */
list_t old_data; /*!< Old data, to be freed after succesfull update. */
list_t new_data; /*!< New data, to be freed after failed update. */
size_t size; /*!< Size of serialized changeset. */
uint8_t *data; /*!< Serialized changeset. */
} changeset_t;
/*! \brief Changeset iteration structure. */
typedef struct {
list_t iters;
const zone_node_t *node;
uint16_t node_pos;
list_t iters; /*!< List of pending zone iterators. */
const zone_node_t *node; /*!< Current zone node. */
uint16_t node_pos; /*!< Position in node. */
} changeset_iter_t;
/*----------------------------------------------------------------------------*/
changeset_t *changeset_new(mm_ctx_t *mm, const knot_dname_t *apex);
void changeset_init(changeset_t *ch, const knot_dname_t *apex, mm_ctx_t *mm);
/*!
* \brief Add RRSet to changeset. RRSet is either inserted to 'add' or to
* 'remove' list. Will *not* try to merge with previous RRSets.
* \brief Inits changeset structure.
*
* \param chgs Changeset to add RRSet into.
* \param rrset RRSet to be added.
* \param part Add to 'add' or 'remove'?
* \param ch Changeset to init.
* \param apex Zone apex DNAME.
*
* \retval KNOT_EOK on success.
* \retval Error code on failure.
* \return KNOT_E*
*/
int changeset_add_rrset(changeset_t *ch, const knot_rrset_t *rrset);
int changeset_rem_rrset(changeset_t *ch, const knot_rrset_t *rrset);
int changeset_init(changeset_t *ch, const knot_dname_t *apex);
/*!
* \brief Checks whether changeset is empty.
* \brief Creates new changeset structure.
*
* Changeset is considered empty if it has no RRs in REMOVE and ADD sections and
* final SOA (soa_to) is not set.
* \param apex Zone apex DNAME.
*
* \return Changeset structure on success, NULL on errors.
*/
changeset_t *changeset_new(const knot_dname_t *apex);
/*!
* \brief Checks whether changeset is empty, i.e. no change will happen after its application.
*
* \param changeset Changeset to be checked.
*
......@@ -94,16 +92,111 @@ bool changeset_empty(const changeset_t *ch);
*/
size_t changeset_size(const changeset_t *ch);
/*!
* \brief Add RRSet to 'add' part of changeset.
*
* \param ch Changeset to add RRSet into.
* \param rrset RRSet to be added.
*
* \return KNOT_E*
*/
int changeset_add_rrset(changeset_t *ch, const knot_rrset_t *rrset);
/*!
* \brief Add RRSet to 'remove' part of changeset.
*
* \param ch Changeset to add RRSet into.
* \param rrset RRSet to be added.
*
* \return KNOT_E*
*/
int changeset_rem_rrset(changeset_t *ch, const knot_rrset_t *rrset);
/*!
* \brief Merges two changesets together. Legacy, to be removed with new zone API.
*
* \param ch1 Merge into this changeset.
* \param ch2 Merge this changeset.
*
* \return KNOT_E*
*/
int changeset_merge(changeset_t *ch1, const changeset_t *ch2);
/*!
* \brief Clears changesets in list. Changesets are not free'd. Legacy.
*
* \param chgs Changeset list to clear.
*/
void changesets_clear(list_t *chgs);
/*!
* \brief Free changesets in list. Legacy.
*
* \param chgs Changeset list to free.
*/
void changesets_free(list_t *chgs);
/*!
* \brief Clear single changeset.
*
* \param ch Changeset to clear.
*/
void changeset_clear(changeset_t *ch);
/*!
* \brief Frees single changeset.
*
* \param ch Changeset to free.
*/
void changeset_free(changeset_t *ch);
int changeset_merge(changeset_t *ch1, changeset_t *ch2);
/*!
* \brief Inits changeset iteration structure with changeset additions.
*
* \param itt Iterator to init.
* \param ch Changeset to use.
* \param sorted Sort the iteration?
*
* \return KNOT_E*
*/
int changeset_iter_add(changeset_iter_t *itt, const changeset_t *ch, bool sorted);
/*!
* \brief Inits changeset iteration structure with changeset removals.
*
* \param itt Iterator to init.
* \param ch Changeset to use.
* \param sorted Sort the iteration?
*
* \return KNOT_E*
*/
int changeset_iter_rem(changeset_iter_t *itt, const changeset_t *ch, bool sorted);
/*!
* \brief Inits changeset iteration structure with changeset additions and removals.
*
* \param itt Iterator to init.
* \param ch Changeset to use.
* \param sorted Sort the iteration?
*
* \return KNOT_E*
*/
int changeset_iter_all(changeset_iter_t *itt, const changeset_t *ch, bool sorted);
/*!
* \brief Gets next RRSet from changeset iterator.
*
* \param it Changeset iterator.
*
* \return Next RRSet in iterator, empty RRSet if iteration done.
*/
knot_rrset_t changeset_iter_next(changeset_iter_t *it);
/*!
* \brief Free resources allocated by changeset iterator.
*
* \param it Iterator to clear.
*/
void changeset_iter_clear(changeset_iter_t *it);
/*! @} */
......@@ -504,18 +504,21 @@ static int event_dnssec(zone_t *zone)
{
assert(zone);
changeset_t ch;
changeset_init(&ch, zone->name, NULL);
int ret = KNOT_ERROR;
char *zname = knot_dname_to_str(zone->name);
char *msgpref = sprintf_alloc("DNSSEC: Zone %s -", zname);
free(zname);
int ret = KNOT_EOK;
if (msgpref == NULL) {
ret = KNOT_ENOMEM;
goto done;
}
changeset_t ch;
ret = changeset_init(&ch, zone->name);
if (ret != KNOT_EOK) {
goto done;
}
uint32_t refresh_at = time(NULL);
if (zone->flags & ZONE_FORCE_RESIGN) {
log_zone_info("%s Complete resign started (dropping all "
......
......@@ -130,7 +130,10 @@ int zone_load_post(zone_contents_t *contents, zone_t *zone, uint32_t *dnssec_ref
if (conf->dnssec_enable) {
assert(conf->build_diffs);
changeset_t ch;
changeset_init(&ch, zone->name, NULL);
ret = changeset_init(&ch, zone->name);
if (ret != KNOT_EOK) {
return ret;
}
ret = knot_dnssec_zone_sign(contents, conf, &ch, KNOT_SOA_SERIAL_UPDATE,
dnssec_refresh);
if (ret != KNOT_EOK) {
......@@ -152,7 +155,10 @@ int zone_load_post(zone_contents_t *contents, zone_t *zone, uint32_t *dnssec_ref
/* Calculate IXFR from differences (if configured). */
const bool contents_changed = zone->contents && (contents != zone->contents);
changeset_t diff_change;
changeset_init(&diff_change, zone->name, NULL);
ret = changeset_init(&diff_change, zone->name);
if (ret != KNOT_EOK) {
return ret;
}
if (contents_changed && conf->build_diffs) {
ret = zone_contents_create_diff(zone->contents, contents, &diff_change);
if (ret == KNOT_ENODIFF) {
......
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