Commit 25b571de authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

zone-in-journal: serialize zone contents directly

parent c9fe6850
......@@ -38,9 +38,9 @@ MDB_val journal_changeset_to_chunk_key(const changeset_t *ch, uint32_t chunk_id)
}
}
void journal_make_header(void *chunk, const changeset_t *ch)
void journal_make_header(void *chunk, uint32_t ch_serial_to)
{
knot_lmdb_make_key_part(chunk, JOURNAL_HEADER_SIZE, "IILLL", changeset_to(ch),
knot_lmdb_make_key_part(chunk, JOURNAL_HEADER_SIZE, "IILLL", ch_serial_to,
(uint32_t)0 /* we no longer care for # of chunks */,
(uint64_t)0, (uint64_t)0, (uint64_t)0);
}
......
......@@ -60,9 +60,9 @@ MDB_val journal_changeset_to_chunk_key(const changeset_t *ch, uint32_t chunk_id)
* \brief Initialise chunk header.
*
* \param chunk Pointer to the changeset chunk. It must be at least JOURNAL_HEADER_SIZE, perhaps more.
* \param ch Changeset to be serialized into the chunk.
* \param ch Serial-to of the changeset being serialized.
*/
void journal_make_header(void *chunk, const changeset_t *ch);
void journal_make_header(void *chunk, uint32_t ch_serial_to);
/*!
* \brief Obtain serial-to of the serialized changeset.
......
......@@ -22,14 +22,9 @@
#include "knot/journal/serialization.h"
#include "libknot/error.h"
void journal_write_changeset(knot_lmdb_txn_t *txn, const changeset_t *ch)
static void journal_write_serialize(knot_lmdb_txn_t *txn, serialize_ctx_t *ser, const changeset_t *ch, uint32_t ch_serial_to)
{
MDB_val chunk;
serialize_ctx_t *ser = serialize_init(ch);
if (ser == NULL) {
txn->ret = KNOT_ENOMEM;
return;
}
uint32_t i = 0;
while (serialize_unfinished(ser) && txn->ret == KNOT_EOK) {
serialize_prepare(ser, JOURNAL_CHUNK_MAX - JOURNAL_HEADER_SIZE, &chunk.mv_size);
......@@ -40,7 +35,7 @@ void journal_write_changeset(knot_lmdb_txn_t *txn, const changeset_t *ch)
chunk.mv_data = NULL;
MDB_val key = journal_changeset_to_chunk_key(ch, i);
if (knot_lmdb_insert(txn, &key, &chunk)) {
journal_make_header(chunk.mv_data, ch);
journal_make_header(chunk.mv_data, ch_serial_to);
serialize_chunk(ser, chunk.mv_data + JOURNAL_HEADER_SIZE, chunk.mv_size - JOURNAL_HEADER_SIZE);
}
free(key.mv_data);
......@@ -50,6 +45,29 @@ void journal_write_changeset(knot_lmdb_txn_t *txn, const changeset_t *ch)
// return value is in the txn
}
void journal_write_changeset(knot_lmdb_txn_t *txn, const changeset_t *ch)
{
serialize_ctx_t *ser = serialize_init(ch);
if (ser == NULL) {
txn->ret = KNOT_ENOMEM;
return;
}
journal_write_serialize(txn, ser, ch, changeset_to(ch));
}
void journal_write_zone(knot_lmdb_txn_t *txn, const zone_contents_t *z)
{
serialize_ctx_t *ser = serialize_zone_init(z);
if (ser == NULL) {
txn->ret = KNOT_ENOMEM;
return;
}
changeset_t fake_ch;
fake_ch.soa_from = NULL;
fake_ch.add = (zone_contents_t *)z;
journal_write_serialize(txn, ser, &fake_ch, zone_contents_serial(z));
}
static int merge_cb(bool remove, const knot_rrset_t *rr, void *ctx)
{
changeset_t *ch = ctx;
......@@ -171,11 +189,8 @@ void journal_fix_occupation(zone_journal_t j, knot_lmdb_txn_t *txn, journal_meta
}
}
int journal_insert_zone(zone_journal_t j, const changeset_t *ch)
int journal_insert_zone(zone_journal_t j, const zone_contents_t *z)
{
if (ch->remove != NULL) {
return KNOT_EINVAL;
}
int ret = knot_lmdb_open(j.db);
if (ret != KNOT_EOK) {
return ret;
......@@ -187,11 +202,11 @@ int journal_insert_zone(zone_journal_t j, const changeset_t *ch)
MDB_val prefix = { knot_dname_size(j.zone), (void *)j.zone };
knot_lmdb_del_prefix(&txn, &prefix);
journal_write_changeset(&txn, ch);
journal_write_zone(&txn, z);
journal_metadata_t md = { 0 };
md.flags = JOURNAL_SERIAL_TO_VALID;
md.serial_to = changeset_to(ch);
md.serial_to = zone_contents_serial(z);
md.first_serial = md.serial_to;
journal_store_metadata(&txn, j.zone, &md);
......
......@@ -27,6 +27,14 @@
*/
void journal_write_changeset(knot_lmdb_txn_t *txn, const changeset_t *ch);
/*!
* \brief Serialize zone contents aka "bootstrap" changeset into journal, no checks.
*
* \param txn Journal DB transaction.
* \param z Zone contents to be written.
*/
void journal_write_zone(knot_lmdb_txn_t *txn, const zone_contents_t *z);
/*!
* \brief Merge all following changeset into one of journal changeset.
*
......@@ -87,11 +95,11 @@ void journal_fix_occupation(zone_journal_t j, knot_lmdb_txn_t *txn, journal_meta
* \brief Store zone-in-journal into the journal, update metadata.
*
* \param j Zone journal.
* \param ch Changeset containing zone-in-journal.
* \param z Zone contents to be stored.
*
* \return KNOT_E*
*/
int journal_insert_zone(zone_journal_t j, const changeset_t *ch);
int journal_insert_zone(zone_journal_t j, const zone_contents_t *z);
/*!
* \brief Store changeset into journal, fulfilling quotas and updating metadata.
......
......@@ -17,12 +17,16 @@
#include <assert.h>
#include "knot/journal/serialization.h"
#include "knot/zone/zone-tree.h"
#include "libknot/libknot.h"
#define SERIALIZE_RRSET_INIT (-1)
#define SERIALIZE_RRSET_DONE ((1L<<16)+1)
typedef enum {
PHASE_ZONE_SOA,
PHASE_ZONE_NODES,
PHASE_ZONE_NSEC3,
PHASE_SOA_1,
PHASE_REM,
PHASE_SOA_2,
......@@ -33,6 +37,11 @@ typedef enum {
#define RRSET_BUF_MAXSIZE 256
struct serialize_ctx {
const zone_contents_t *z;
zone_tree_it_t zit;
zone_node_t *n;
uint16_t node_pos;
const changeset_t *ch;
changeset_iter_t it;
serialize_phase_t changeset_phase;
......@@ -56,11 +65,52 @@ serialize_ctx_t *serialize_init(const changeset_t *ch)
return ctx;
}
serialize_ctx_t *serialize_zone_init(const zone_contents_t *z)
{
serialize_ctx_t *ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
return NULL;
}
ctx->z = z;
ctx->changeset_phase = PHASE_ZONE_SOA;
ctx->rrset_phase = SERIALIZE_RRSET_INIT;
ctx->rrset_buf_size = 0;
return ctx;
}
static knot_rrset_t get_next_rrset(serialize_ctx_t *ctx)
{
knot_rrset_t res;
knot_rrset_init_empty(&res);
switch (ctx->changeset_phase) {
case PHASE_ZONE_SOA:
zone_tree_it_begin(ctx->z->nodes, &ctx->zit);
ctx->changeset_phase = PHASE_ZONE_NODES;
return node_rrset(ctx->z->apex, KNOT_RRTYPE_SOA);
case PHASE_ZONE_NODES:
case PHASE_ZONE_NSEC3:
while (ctx->n == NULL || ctx->node_pos >= ctx->n->rrset_count) {
if (zone_tree_it_finished(&ctx->zit)) {
zone_tree_it_free(&ctx->zit);
if (ctx->changeset_phase == PHASE_ZONE_NSEC3 || zone_tree_is_empty(ctx->z->nsec3_nodes)) {
ctx->changeset_phase = PHASE_END;
return res;
} else {
zone_tree_it_begin(ctx->z->nsec3_nodes, &ctx->zit);
ctx->changeset_phase = PHASE_ZONE_NSEC3;
}
}
ctx->n = zone_tree_it_val(&ctx->zit);
zone_tree_it_next(&ctx->zit);
ctx->node_pos = 0;
}
res = node_rrset_at(ctx->n, ctx->node_pos++);
if (ctx->n == ctx->z->apex && res.type == KNOT_RRTYPE_SOA) {
return get_next_rrset(ctx);
}
return res;
case PHASE_SOA_1:
changeset_iter_rem(&ctx->it, ctx->ch);
ctx->changeset_phase = PHASE_REM;
......
......@@ -32,6 +32,15 @@ typedef struct serialize_ctx serialize_ctx_t;
*/
serialize_ctx_t *serialize_init(const changeset_t *ch);
/*!
* \brief Init serialization context.
*
* \param z Zone to be serialized like zone-in-journal changeset.
*
* \return Context.
*/
serialize_ctx_t *serialize_zone_init(const zone_contents_t *z);
/*!
* \brief Pre-check and space computation before serializing a chunk.
*
......
......@@ -503,42 +503,6 @@ bool changeset_differs_just_serial(const changeset_t *ch)
return ret;
}
changeset_t *changeset_from_contents(const zone_contents_t *contents)
{
zone_contents_t *copy = NULL;
if (zone_contents_shallow_copy(contents, &copy) != KNOT_EOK) {
return NULL;
}
changeset_t *res = changeset_new(copy->apex->owner);
knot_rrset_t soa_rr = node_rrset(copy->apex, KNOT_RRTYPE_SOA);;
res->soa_to = knot_rrset_copy(&soa_rr, NULL);
node_remove_rdataset(copy->apex, KNOT_RRTYPE_SOA);
zone_contents_deep_free(res->add);
res->add = copy;
zone_contents_deep_free(res->remove);
res->remove = NULL;
return res;
}
void changeset_from_contents_free(changeset_t *ch)
{
assert(ch);
assert(ch->soa_from == NULL);
assert(ch->remove == NULL);
update_free_zone(ch->add);
zone_contents_deep_free(ch->remove);
knot_rrset_free(ch->soa_from, NULL);
knot_rrset_free(ch->soa_to, NULL);
free(ch->data);
free(ch);
}
void changesets_clear(list_t *chgs)
{
if (chgs) {
......
......@@ -192,22 +192,6 @@ int changeset_cancelout(changeset_t *ch);
*/
bool changeset_differs_just_serial(const changeset_t *ch);
/*!
* \brief Creates a bootstrap changeset from zone.
*
* \param contents Contents to include, will be freed!
*
* \return Changeset, which shall be freed with changeset_from_contents_free()
*/
changeset_t *changeset_from_contents(const zone_contents_t *contents);
/*!
* \brief Frees single changeset.
*
* \param ch Changeset from changeset_from_contents() to free.
*/
void changeset_from_contents_free(changeset_t *ch);
/*!
* \brief Clears changesets in list. Changesets are not free'd. Legacy.
*
......
......@@ -264,10 +264,7 @@ int zone_in_journal_store(conf_t *conf, zone_t *zone, zone_contents_t *new_conte
return KNOT_EINVAL;
}
changeset_t *co_ch = changeset_from_contents(new_contents);
int ret = co_ch ? journal_insert_zone(zone_journal(zone), co_ch) : KNOT_ENOMEM;
changeset_from_contents_free(co_ch);
int ret = journal_insert_zone(zone_journal(zone), new_contents);
if (ret == KNOT_EOK) {
log_zone_info(zone->name, "zone stored to journal, serial %u",
zone_contents_serial(new_contents));
......
......@@ -431,7 +431,10 @@ static void test_store_load(const knot_dname_t *apex)
changeset_init(&e_ch, apex);
init_random_changeset(&e_ch, 0, 1, 200, apex, true);
ret = journal_insert_zone(jj, &e_ch);
zone_node_t *n = NULL;
zone_contents_add_rr(e_ch.add, e_ch.soa_to, &n);
ret = journal_insert_zone(jj, e_ch.add);
zone_contents_remove_rr(e_ch.add, e_ch.soa_to, &n);
is_int(KNOT_EOK, ret, "journal: insert zone-in-journal (%s)", knot_strerror(ret));
changeset_init(&r_ch, apex);
init_random_changeset(&r_ch, 1, 2, 200, apex, false);
......
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