Commit 58a62df1 authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

journal on-the-fly deserialization: used in IXFR

parent 8664300f
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> /* 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 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 it under the terms of the GNU General Public License as published by
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "contrib/mempattern.h" #include "contrib/mempattern.h"
#include "contrib/sockaddr.h" #include "contrib/sockaddr.h"
#include "knot/journal/chgset_ctx.h"
#include "knot/nameserver/axfr.h" #include "knot/nameserver/axfr.h"
#include "knot/nameserver/internet.h" #include "knot/nameserver/internet.h"
#include "knot/nameserver/ixfr.h" #include "knot/nameserver/ixfr.h"
...@@ -42,30 +43,30 @@ ...@@ -42,30 +43,30 @@
/*! \brief Puts current RR into packet, stores state for retries. */ /*! \brief Puts current RR into packet, stores state for retries. */
static int ixfr_put_chg_part(knot_pkt_t *pkt, struct ixfr_proc *ixfr, static int ixfr_put_chg_part(knot_pkt_t *pkt, struct ixfr_proc *ixfr,
changeset_iter_t *itt) chgset_ctx_t *itt)
{ {
assert(pkt); assert(pkt);
assert(ixfr); assert(ixfr);
assert(itt); assert(itt);
if (knot_rrset_empty(&ixfr->cur_rr)) { if (!knot_rrset_empty(&ixfr->cur_rr)) {
ixfr->cur_rr = changeset_iter_next(itt); IXFR_SAFE_PUT(pkt, &ixfr->cur_rr);
knot_rrset_clear(&ixfr->cur_rr, NULL);
} }
while (!knot_rrset_empty(&ixfr->cur_rr)) { while (itt->phase != CHGSET_CTX_DONE) {
int r = chgset_ctx_next(itt, &ixfr->cur_rr);
if (r != KNOT_EOK) {
knot_rrset_clear(&ixfr->cur_rr, NULL);
return r;
}
IXFR_SAFE_PUT(pkt, &ixfr->cur_rr); IXFR_SAFE_PUT(pkt, &ixfr->cur_rr);
ixfr->cur_rr = changeset_iter_next(itt); knot_rrset_clear(&ixfr->cur_rr, NULL);
} }
return KNOT_EOK; return KNOT_EOK;
} }
/*! \brief Tests if iteration has started. */
static bool iter_empty(struct ixfr_proc *ixfr)
{
return EMPTY_LIST(ixfr->cur.iters) && knot_rrset_empty(&ixfr->cur_rr);
}
/*! /*!
* \brief Process single changeset. * \brief Process single changeset.
* \note Keep in mind that this function must be able to resume processing, * \note Keep in mind that this function must be able to resume processing,
...@@ -78,63 +79,22 @@ static int ixfr_process_changeset(knot_pkt_t *pkt, const void *item, ...@@ -78,63 +79,22 @@ static int ixfr_process_changeset(knot_pkt_t *pkt, const void *item,
{ {
int ret = KNOT_EOK; int ret = KNOT_EOK;
struct ixfr_proc *ixfr = (struct ixfr_proc *)xfer; struct ixfr_proc *ixfr = (struct ixfr_proc *)xfer;
changeset_t *chgset = (changeset_t *)item; chgset_ctx_t *chgset = (chgset_ctx_t *)item;
/* Put former SOA. */
if (ixfr->state == IXFR_SOA_DEL) {
IXFR_SAFE_PUT(pkt, chgset->soa_from);
ixfr->state = IXFR_DEL;
}
/* Put REMOVE RRSets. */ ret = ixfr_put_chg_part(pkt, ixfr, chgset);
if (ixfr->state == IXFR_DEL) { if (ret != KNOT_EOK) {
if (iter_empty(ixfr)) { return ret;
ret = changeset_iter_rem(&ixfr->cur, chgset);
if (ret != KNOT_EOK) {
return ret;
}
}
ret = ixfr_put_chg_part(pkt, ixfr, &ixfr->cur);
if (ret != KNOT_EOK) {
return ret;
}
changeset_iter_clear(&ixfr->cur);
ixfr->state = IXFR_SOA_ADD;
}
/* Put next SOA. */
if (ixfr->state == IXFR_SOA_ADD) {
IXFR_SAFE_PUT(pkt, chgset->soa_to);
ixfr->state = IXFR_ADD;
}
/* Put Add RRSets. */
if (ixfr->state == IXFR_ADD) {
if (iter_empty(ixfr)) {
ret = changeset_iter_add(&ixfr->cur, chgset);
if (ret != KNOT_EOK) {
return ret;
}
}
ret = ixfr_put_chg_part(pkt, ixfr, &ixfr->cur);
if (ret != KNOT_EOK) {
return ret;
}
changeset_iter_clear(&ixfr->cur);
ixfr->state = IXFR_SOA_DEL;
} }
/* Finished change set. */ /* Finished change set. */
const uint32_t serial_from = knot_soa_serial(&chgset->soa_from->rrs); IXFROUT_LOG(LOG_DEBUG, ixfr->qdata, "serial %u -> %u", chgset->serial_from, chgset->serial_to);
const uint32_t serial_to = knot_soa_serial(&chgset->soa_to->rrs);
IXFROUT_LOG(LOG_DEBUG, ixfr->qdata, "serial %u -> %u", serial_from, serial_to);
return ret; return ret;
} }
#undef IXFR_SAFE_PUT #undef IXFR_SAFE_PUT
static int ixfr_load_chsets(list_t *chgsets, zone_t *zone, static int ixfr_load_chsets(chgset_ctx_list_t *chgsets, zone_t *zone,
const knot_rrset_t *their_soa) const knot_rrset_t *their_soa)
{ {
assert(chgsets); assert(chgsets);
...@@ -147,12 +107,7 @@ static int ixfr_load_chsets(list_t *chgsets, zone_t *zone, ...@@ -147,12 +107,7 @@ static int ixfr_load_chsets(list_t *chgsets, zone_t *zone,
return KNOT_EUPTODATE; return KNOT_EUPTODATE;
} }
int ret = zone_changes_load(conf(), zone, chgsets, serial_from); return zone_chgset_ctx_load(conf(), zone, chgsets, serial_from);
if (ret != KNOT_EOK) {
changesets_free(chgsets);
}
return ret;
} }
static int ixfr_query_check(knotd_qdata_t *qdata) static int ixfr_query_check(knotd_qdata_t *qdata)
...@@ -180,8 +135,7 @@ static void ixfr_answer_cleanup(knotd_qdata_t *qdata) ...@@ -180,8 +135,7 @@ static void ixfr_answer_cleanup(knotd_qdata_t *qdata)
knot_mm_t *mm = qdata->mm; knot_mm_t *mm = qdata->mm;
ptrlist_free(&ixfr->proc.nodes, mm); ptrlist_free(&ixfr->proc.nodes, mm);
changeset_iter_clear(&ixfr->cur); chgset_ctx_list_close(&ixfr->changesets);
changesets_free(&ixfr->changesets);
mm_free(mm, qdata->extra->ext); mm_free(mm, qdata->extra->ext);
/* Allow zone changes (finished). */ /* Allow zone changes (finished). */
...@@ -204,41 +158,39 @@ static int ixfr_answer_init(knotd_qdata_t *qdata) ...@@ -204,41 +158,39 @@ static int ixfr_answer_init(knotd_qdata_t *qdata)
/* Compare serials. */ /* Compare serials. */
const knot_pktsection_t *authority = knot_pkt_section(qdata->query, KNOT_AUTHORITY); const knot_pktsection_t *authority = knot_pkt_section(qdata->query, KNOT_AUTHORITY);
const knot_rrset_t *their_soa = knot_pkt_rr(authority, 0); const knot_rrset_t *their_soa = knot_pkt_rr(authority, 0);
list_t chgsets;
init_list(&chgsets);
int ret = ixfr_load_chsets(&chgsets, (zone_t *)qdata->extra->zone, their_soa);
if (ret != KNOT_EOK) {
return ret;
}
/* Initialize transfer processing. */ /* Initialize transfer processing. */
knot_mm_t *mm = qdata->mm; knot_mm_t *mm = qdata->mm;
struct ixfr_proc *xfer = mm_alloc(mm, sizeof(struct ixfr_proc)); struct ixfr_proc *xfer = mm_alloc(mm, sizeof(struct ixfr_proc));
if (xfer == NULL) { if (xfer == NULL) {
changesets_free(&chgsets);
return KNOT_ENOMEM; return KNOT_ENOMEM;
} }
memset(xfer, 0, sizeof(struct ixfr_proc)); memset(xfer, 0, sizeof(struct ixfr_proc));
int ret = ixfr_load_chsets(&xfer->changesets, (zone_t *)qdata->extra->zone, their_soa);
if (ret != KNOT_EOK) {
mm_free(mm, xfer);
return ret;
}
xfr_stats_begin(&xfer->proc.stats); xfr_stats_begin(&xfer->proc.stats);
xfer->state = IXFR_SOA_DEL; xfer->state = IXFR_SOA_DEL;
init_list(&xfer->proc.nodes); init_list(&xfer->proc.nodes);
init_list(&xfer->changesets);
init_list(&xfer->cur.iters);
knot_rrset_init_empty(&xfer->cur_rr); knot_rrset_init_empty(&xfer->cur_rr);
add_tail_list(&xfer->changesets, &chgsets);
xfer->qdata = qdata; xfer->qdata = qdata;
/* Put all changesets to processing queue. */ /* Put all changesets to processing queue. */
changeset_t *chs = NULL; chgset_ctx_t *chs = NULL;
WALK_LIST(chs, xfer->changesets) { WALK_LIST(chs, xfer->changesets.l) {
ptrlist_add(&xfer->proc.nodes, chs, mm); ptrlist_add(&xfer->proc.nodes, chs, mm);
chgset_ctx_iterate(chs); // init already, so we don't have to decide later, no harm
} }
/* Keep first and last serial. */ /* Keep first and last serial. */
chs = HEAD(xfer->changesets); chs = HEAD(xfer->changesets.l);
xfer->soa_from = chs->soa_from; xfer->soa_from = chs->serial_from;
chs = TAIL(xfer->changesets); chs = TAIL(xfer->changesets.l);
xfer->soa_to = chs->soa_to; xfer->soa_to = chs->serial_to;
/* Set up cleanup callback. */ /* Set up cleanup callback. */
qdata->extra->ext = xfer; qdata->extra->ext = xfer;
...@@ -301,8 +253,7 @@ int ixfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) ...@@ -301,8 +253,7 @@ int ixfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
switch (ret) { switch (ret) {
case KNOT_EOK: /* OK */ case KNOT_EOK: /* OK */
IXFROUT_LOG(LOG_INFO, qdata, "started, serial %u -> %u", IXFROUT_LOG(LOG_INFO, qdata, "started, serial %u -> %u",
knot_soa_serial(&ixfr->soa_from->rrs), ixfr->soa_from, ixfr->soa_to);
knot_soa_serial(&ixfr->soa_to->rrs));
break; break;
case KNOT_EUPTODATE: /* Our zone is same age/older, send SOA. */ case KNOT_EUPTODATE: /* Our zone is same age/older, send SOA. */
IXFROUT_LOG(LOG_INFO, qdata, "zone is up-to-date"); IXFROUT_LOG(LOG_INFO, qdata, "zone is up-to-date");
......
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> /* 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 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 it under the terms of the GNU General Public License as published by
...@@ -38,13 +38,12 @@ struct ixfr_proc { ...@@ -38,13 +38,12 @@ struct ixfr_proc {
enum ixfr_state state; enum ixfr_state state;
/* Changes to be sent. */ /* Changes to be sent. */
list_t changesets; chgset_ctx_list_t changesets;
/* Currenty processed changeset. */ /* Currenty processed changeset. */
knot_rrset_t cur_rr; knot_rrset_t cur_rr;
changeset_iter_t cur; uint32_t soa_from;
const knot_rrset_t *soa_from; uint32_t soa_to;
const knot_rrset_t *soa_to;
/* Processing context. */ /* Processing context. */
knotd_qdata_t *qdata; knotd_qdata_t *qdata;
......
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