Commit 3db928d9 authored by Lubos Slovak's avatar Lubos Slovak

changesets: Reviewed and fixed.

- Unified parameter names.
- Added some missing allocation checks.
- Fixed changesets_empty() (was giving wrong answer if there were
  more changesets and the last one was empty).
- add_soa() now returns error code. Neede for parameter checking.
- changeset_merge() should not change the second changeset.
- Removed unused changesets_clear().
- Removed unused flags from changesets_t.
- Fixed doxygen comments.
parent 89c6290c
......@@ -119,6 +119,8 @@ static int sign_update(zone_t *zone, const zone_contents_t *old_contents,
return ret;
}
// Free the DNSSEC changeset's SOA from (not used anymore)
knot_rrset_free(&sec_ch->soa_from, NULL);
// Shallow free DNSSEC changesets
free(sec_chs);
......
......@@ -984,7 +984,10 @@ static int changesets_unpack(changeset_t *chs)
*/
assert(rrset->type == KNOT_RRTYPE_SOA);
assert(chs->serial_from == knot_soa_serial(&rrset->rrs));
changeset_add_soa(chs, rrset, CHANGESET_REMOVE);
ret = changeset_add_soa(chs, rrset, CHANGESET_REMOVE);
if (ret != KNOT_EOK) {
return ret;
}
/* Read remaining RRSets */
int in_remove_section = 1;
......@@ -1003,8 +1006,8 @@ static int changesets_unpack(changeset_t *chs)
/* Move to ADD section if in REMOVE. */
if (in_remove_section) {
changeset_add_soa(chs, rrset,
CHANGESET_ADD);
ret = changeset_add_soa(chs, rrset,
CHANGESET_ADD);
in_remove_section = 0;
} else {
/* Final SOA. */
......
......@@ -27,29 +27,32 @@
#include "libknot/rrtype/soa.h"
#include "common/debug.h"
static int knot_changesets_init(changesets_t *changesets)
static int knot_changesets_init(changesets_t *chs)
{
if (changesets == NULL) {
return KNOT_EINVAL;
}
assert(chs != NULL);
// Create new changesets structure
memset(changesets, 0, sizeof(changesets_t));
memset(chs, 0, sizeof(changesets_t));
// Initialize memory context for changesets (xmalloc'd)
struct mempool *chs_pool = mp_new(sizeof(changeset_t));
changesets->mmc_chs.ctx = chs_pool;
changesets->mmc_chs.alloc = (mm_alloc_t)mp_alloc;
changesets->mmc_chs.free = NULL;
chs->mmc_chs.ctx = chs_pool;
chs->mmc_chs.alloc = (mm_alloc_t)mp_alloc;
chs->mmc_chs.free = NULL;
// Initialize memory context for RRs in changesets (xmalloc'd)
struct mempool *rr_pool = mp_new(sizeof(knot_rr_ln_t));
changesets->mmc_rr.ctx = rr_pool;
changesets->mmc_rr.alloc = (mm_alloc_t)mp_alloc;
changesets->mmc_rr.free = NULL;
chs->mmc_rr.ctx = rr_pool;
chs->mmc_rr.alloc = (mm_alloc_t)mp_alloc;
chs->mmc_rr.free = NULL;
if (chs_pool == NULL || rr_pool == NULL) {
ERR_ALLOC_FAILED;
return KNOT_ENOMEM;
}
// Init list with changesets
init_list(&changesets->sets);
init_list(&chs->sets);
return KNOT_EOK;
}
......@@ -57,6 +60,11 @@ static int knot_changesets_init(changesets_t *changesets)
changesets_t *changesets_create(unsigned count)
{
changesets_t *ch = malloc(sizeof(changesets_t));
if (ch == NULL) {
ERR_ALLOC_FAILED;
return NULL;
}
int ret = knot_changesets_init(ch);
if (ret != KNOT_EOK) {
return NULL;
......@@ -73,22 +81,23 @@ changesets_t *changesets_create(unsigned count)
return ch;
}
changeset_t *changesets_create_changeset(changesets_t *ch)
changeset_t *changesets_create_changeset(changesets_t *chs)
{
if (ch == NULL) {
if (chs == NULL) {
return NULL;
}
// Create set changesets' memory allocator
changeset_t *set = ch->mmc_chs.alloc(ch->mmc_chs.ctx,
sizeof(changeset_t));
changeset_t *set = chs->mmc_chs.alloc(chs->mmc_chs.ctx,
sizeof(changeset_t));
if (set == NULL) {
ERR_ALLOC_FAILED;
return NULL;
}
memset(set, 0, sizeof(changeset_t));
// Init set's memory context (Allocator from changests structure is used)
set->mem_ctx = ch->mmc_rr;
set->mem_ctx = chs->mmc_rr;
// Init local lists
init_list(&set->add);
......@@ -99,9 +108,9 @@ changeset_t *changesets_create_changeset(changesets_t *ch)
init_list(&set->old_data);
// Insert into list of sets
add_tail(&ch->sets, (node_t *)set);
add_tail(&chs->sets, (node_t *)set);
++ch->count;
++chs->count;
return set;
}
......@@ -117,20 +126,26 @@ changeset_t *changesets_get_last(const changesets_t *chs)
bool changesets_empty(const changesets_t *chs)
{
changeset_t *last = changesets_get_last(chs);
if (last == NULL) {
if (chs == NULL || EMPTY_LIST(chs->sets)) {
return true;
}
return changeset_is_empty(last);
changeset_t *ch = NULL;
WALK_LIST(ch, chs->sets) {
if (!changeset_is_empty(ch)) {
return false;
}
}
return true;
}
int changeset_add_rrset(changeset_t *chgs, knot_rrset_t *rrset,
changeset_part_t part)
int changeset_add_rrset(changeset_t *ch, knot_rrset_t *rrset,
changeset_part_t part)
{
// Create wrapper node for list
knot_rr_ln_t *rr_node =
chgs->mem_ctx.alloc(chgs->mem_ctx.ctx, sizeof(knot_rr_ln_t));
ch->mem_ctx.alloc(ch->mem_ctx.ctx, sizeof(knot_rr_ln_t));
if (rr_node == NULL) {
// This will not happen with mp_alloc, but allocator can change
ERR_ALLOC_FAILED;
......@@ -139,9 +154,9 @@ int changeset_add_rrset(changeset_t *chgs, knot_rrset_t *rrset,
rr_node->rr = rrset;
if (part == CHANGESET_ADD) {
add_tail(&chgs->add, (node_t *)rr_node);
add_tail(&ch->add, (node_t *)rr_node);
} else {
add_tail(&chgs->remove, (node_t *)rr_node);
add_tail(&ch->remove, (node_t *)rr_node);
}
return KNOT_EOK;
......@@ -154,60 +169,63 @@ static void knot_changeset_store_soa(knot_rrset_t **chg_soa,
*chg_serial = knot_soa_serial(&soa->rrs);
}
void changeset_add_soa(changeset_t *changeset, knot_rrset_t *soa,
changeset_part_t part)
int changeset_add_soa(changeset_t *ch, knot_rrset_t *soa,
changeset_part_t part)
{
if (ch == NULL || soa == NULL) {
return KNOT_EINVAL;
}
switch (part) {
case CHANGESET_ADD:
knot_changeset_store_soa(&changeset->soa_to,
&changeset->serial_to, soa);
knot_changeset_store_soa(&ch->soa_to, &ch->serial_to, soa);
break;
case CHANGESET_REMOVE:
knot_changeset_store_soa(&changeset->soa_from,
&changeset->serial_from, soa);
knot_changeset_store_soa(&ch->soa_from, &ch->serial_from, soa);
break;
default:
assert(0);
return KNOT_EINVAL;
}
return KNOT_EOK;
}
bool changeset_is_empty(const changeset_t *changeset)
bool changeset_is_empty(const changeset_t *ch)
{
if (changeset == NULL) {
if (ch == NULL) {
return true;
}
return (changeset->soa_to == NULL &&
EMPTY_LIST(changeset->add) && EMPTY_LIST(changeset->remove));
return (ch->soa_to == NULL &&
EMPTY_LIST(ch->add) && EMPTY_LIST(ch->remove));
}
size_t changeset_size(const changeset_t *changeset)
size_t changeset_size(const changeset_t *ch)
{
if (!changeset || changeset_is_empty(changeset)) {
if (!ch || changeset_is_empty(ch)) {
return 0;
}
return list_size(&changeset->add) + list_size(&changeset->remove);
return list_size(&ch->add) + list_size(&ch->remove);
}
int changeset_apply(changeset_t *changeset,
changeset_part_t part,
int (*func)(knot_rrset_t *, void *), void *data)
int changeset_apply(changeset_t *ch, changeset_part_t part,
int (*func)(knot_rrset_t *, void *), void *data)
{
if (changeset == NULL || func == NULL) {
if (ch == NULL || func == NULL) {
return KNOT_EINVAL;
}
knot_rr_ln_t *rr_node = NULL;
if (part == CHANGESET_ADD) {
WALK_LIST(rr_node, changeset->add) {
WALK_LIST(rr_node, ch->add) {
int res = func(rr_node->rr, data);
if (res != KNOT_EOK) {
return res;
}
}
} else if (part == CHANGESET_REMOVE) {
WALK_LIST(rr_node, changeset->remove) {
WALK_LIST(rr_node, ch->remove) {
int res = func(rr_node->rr, data);
if (res != KNOT_EOK) {
return res;
......@@ -220,7 +238,8 @@ int changeset_apply(changeset_t *changeset,
int changeset_merge(changeset_t *ch1, changeset_t *ch2)
{
if (ch1 == NULL || ch2 == NULL || ch1->data != NULL || ch2->data != NULL) {
if (ch1 == NULL || ch2 == NULL || ch1->data != NULL
|| ch2->data != NULL) {
return KNOT_EINVAL;
}
......@@ -231,71 +250,60 @@ 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_free(&ch1->soa_to, NULL);
knot_rrset_free(&ch2->soa_from, NULL);
ch1->soa_to = ch2->soa_to;
ch1->serial_to = ch2->serial_to;
return KNOT_EOK;
}
static void knot_free_changeset(changeset_t *changeset, mm_ctx_t *rr_mm)
static void knot_free_changeset(changeset_t *ch, mm_ctx_t *rr_mm)
{
if (changeset == NULL) {
if (ch == NULL) {
return;
}
// Delete RRSets in lists, in case there are any left
knot_rr_ln_t *rr_node;
WALK_LIST(rr_node, changeset->add) {
WALK_LIST(rr_node, ch->add) {
knot_rrset_free(&rr_node->rr, rr_mm);
}
WALK_LIST(rr_node, changeset->remove) {
WALK_LIST(rr_node, ch->remove) {
knot_rrset_free(&rr_node->rr, rr_mm);
}
knot_rrset_free(&changeset->soa_from, rr_mm);
knot_rrset_free(&changeset->soa_to, rr_mm);
knot_rrset_free(&ch->soa_from, rr_mm);
knot_rrset_free(&ch->soa_to, rr_mm);
// Delete binary data
free(changeset->data);
free(ch->data);
}
static void knot_changesets_deinit(changesets_t *changesets, mm_ctx_t *rr_mm)
static void knot_changesets_deinit(changesets_t *ch, mm_ctx_t *rr_mm)
{
if (!EMPTY_LIST(changesets->sets)) {
if (!EMPTY_LIST(ch->sets)) {
changeset_t *chg = NULL;
WALK_LIST(chg, changesets->sets) {
WALK_LIST(chg, ch->sets) {
knot_free_changeset(chg, rr_mm);
}
}
// Free pool with sets themselves
mp_delete(changesets->mmc_chs.ctx);
mp_delete(ch->mmc_chs.ctx);
// Free pool with RRs in sets / changes
mp_delete(changesets->mmc_rr.ctx);
mp_delete(ch->mmc_rr.ctx);
knot_rrset_free(&changesets->first_soa, rr_mm);
knot_rrset_free(&ch->first_soa, rr_mm);
}
void changesets_free(changesets_t **changesets, mm_ctx_t *rr_mm)
void changesets_free(changesets_t **chs, mm_ctx_t *rr_mm)
{
if (changesets == NULL || *changesets == NULL) {
if (chs == NULL || *chs == NULL) {
return;
}
knot_changesets_deinit(*changesets, rr_mm);
free(*changesets);
*changesets = NULL;
}
int changesets_clear(changesets_t *changesets, mm_ctx_t *rr_mm)
{
if (changesets == NULL) {
return KNOT_EINVAL;
}
knot_changesets_deinit(*chs, rr_mm);
knot_changesets_deinit(changesets, rr_mm);
return knot_changesets_init(changesets);
free(*chs);
*chs = NULL;
}
......@@ -70,7 +70,6 @@ typedef struct {
list_t sets; /*!< List of changesets. */
size_t count; /*!< Changeset count. */
knot_rrset_t *first_soa; /*!< First received SOA. */
uint32_t flags; /*!< DDNS / IXFR flags. */
} changesets_t;
/*----------------------------------------------------------------------------*/
......@@ -93,9 +92,6 @@ typedef enum {
*/
changesets_t *changesets_create(unsigned count);
/*! \brief Reinitialize changesets structure. */
int changesets_clear(changesets_t *changesets, mm_ctx_t *rr_mm);
/*!
* \brief Creates new changeset structure and returns it to caller.
* The structure is also connected to a list of changesets.
......@@ -105,7 +101,7 @@ int changesets_clear(changesets_t *changesets, mm_ctx_t *rr_mm);
* \retval Created structure on success.
* \retval NULL on failure.
*/
changeset_t *changesets_create_changeset(changesets_t *ch);
changeset_t *changesets_create_changeset(changesets_t *chs);
/*!
* \brief Gets last changesets from from structure's list.
......@@ -115,9 +111,18 @@ changeset_t *changesets_create_changeset(changesets_t *ch);
* \retval Last changeset on success.
* \retval NULL on failure.
*/
changeset_t *changesets_get_last(const changesets_t *ch);
changeset_t *changesets_get_last(const changesets_t *chs);
/*! \brief Return true if changesets are empty. */
/*!
* \brief Checks whether the changesets are empty.
*
* Changesets are considered empty if there is no changeset or all changesets
* are empty.
*
* \param chs Changesets to check.
*
* \return True If there is at least one non-empty changeset. False otherwise.
*/
bool changesets_empty(const changesets_t *chs);
/*!
......@@ -131,8 +136,8 @@ bool changesets_empty(const changesets_t *chs);
* \retval KNOT_EOK on success.
* \retval Error code on failure.
*/
int changeset_add_rrset(changeset_t *chgs,
knot_rrset_t *rrset, changeset_part_t part);
int changeset_add_rrset(changeset_t *ch, knot_rrset_t *rrset,
changeset_part_t part);
/*!
* \brief Adds a source/destination SOA RRSet to changeset.
......@@ -141,21 +146,21 @@ int changeset_add_rrset(changeset_t *chgs,
* \param soa SOA RRSet to be stored to changeset.
* \param part To which part we store SOA (from = REMOVE, add = TO)
*/
void changeset_add_soa(changeset_t *changeset, knot_rrset_t *soa,
changeset_part_t part);
int changeset_add_soa(changeset_t *ch, knot_rrset_t *soa,
changeset_part_t part);
/*!
* \brief Checks whether changeset is empty.
*
* \param changeset Changeset to be checked.
*
* Changeset is considered empty if it has no RRs in REMOVE and ADD sections and
* final SOA (soa_to) is not set.
*
* \param changeset Changeset to be checked.
*
* \retval true if changeset is empty.
* \retval false if changeset is not empty.
*/
bool changeset_is_empty(const changeset_t *changeset);
bool changeset_is_empty(const changeset_t *ch);
/*!
* \brief Get number of changes (additions and removals) in the changeset.
......@@ -164,26 +169,25 @@ bool changeset_is_empty(const changeset_t *changeset);
*
* \return Number of changes in the changeset.
*/
size_t changeset_size(const changeset_t *changeset);
size_t changeset_size(const changeset_t *ch);
/*!
* \brief Apply given function to all RRSets in one part of the changeset.
*
* If the applied function fails, the application aborts and this function
* returns the return value of the applied function.
*
* \param changeset Changeset to apply the function to.
* \param part Part of changeset to apply the function to.
* \param func Function to apply to RRSets in the changeset. It is required that
* the function returns KNOT_EOK on success.
* \param data Data to pass to the applied function.
*
* If the applied function fails, the application aborts and this function
* returns the return value of the applied function.
*
* \retval KNOT_EOK if OK
* \retval KNOT_EINVAL if \a changeset or \a func is NULL.
* \retval Other error code if the applied function failed.
*/
int changeset_apply(changeset_t *changeset,
changeset_part_t part,
int changeset_apply(changeset_t *ch, changeset_part_t part,
int (*func)(knot_rrset_t *, void *), void *data);
/*!
......@@ -192,18 +196,18 @@ int changeset_apply(changeset_t *changeset,
* \param changesets Double pointer to changesets structure to be freed.
* \param mm Memory context used to allocate RRSets.
*/
void changesets_free(changesets_t **changesets, mm_ctx_t *rr_mm);
void changesets_free(changesets_t **chs, mm_ctx_t *rr_mm);
/*!
* \brief Merges two changesets together, second changeset's lists are kept.
*
* \param ch1 Changeset to merge into
* \param ch2 Changeset to merge
*
* Beginning SOA is used from the first changeset, ending SOA from the second.
* Ending SOA from first changeset is deleted. SOAs in the second changeset are
* left untouched.
*
* \param ch1 Changeset to merge into
* \param ch2 Changeset to merge
*
* \retval KNOT_EOK on success.
* \retval Error code on failure.
*/
......
......@@ -657,8 +657,7 @@ static int process_add_soa(const zone_node_t *node,
return KNOT_ENOMEM;
}
changeset_add_soa(changeset, soa_cpy, CHANGESET_ADD);
return KNOT_EOK;
return changeset_add_soa(changeset, soa_cpy, CHANGESET_ADD);
}
/*!< \brief Adds normal RR, ignores when CNAME exists in node. */
......@@ -985,7 +984,11 @@ int ddns_process_update(const zone_t *zone, const knot_pkt_t *query,
return KNOT_ENOMEM;
}
changeset_add_soa(changeset, soa_begin, CHANGESET_REMOVE);
int ret = changeset_add_soa(changeset, soa_begin, CHANGESET_REMOVE);
if (ret != KNOT_EOK) {
*rcode = ret_to_rcode(ret);
return ret;
}
int64_t sn_old = zone_contents_serial(zone->contents);
......@@ -997,7 +1000,7 @@ int ddns_process_update(const zone_t *zone, const knot_pkt_t *query,
const knot_rrset_t *rr = &authority->rr[i];
/* Check if the entry is correct. */
int ret = check_update(rr, query, rcode);
ret = check_update(rr, query, rcode);
if (ret != KNOT_EOK) {
assert(*rcode != KNOT_RCODE_NOERROR);
return ret;
......@@ -1032,7 +1035,11 @@ int ddns_process_update(const zone_t *zone, const knot_pkt_t *query,
zone_contents_next_serial(zone->contents,
zone->conf->serial_policy);
knot_soa_serial_set(&soa_cpy->rrs, new_serial);
changeset_add_soa(changeset, soa_cpy, CHANGESET_ADD);
ret = changeset_add_soa(changeset, soa_cpy, CHANGESET_ADD);
if (ret != KNOT_EOK) {
*rcode = ret_to_rcode(ret);
return ret;
}
}
*rcode = KNOT_RCODE_NOERROR;
......
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