Commit 509e465a authored by Daniel Salzman's avatar Daniel Salzman

Merge branch 'cow_trie8' into 'master'

Implementation of COW trie for zone updates

See merge request !988
parents 0ab4110d 957201ea
......@@ -37,6 +37,8 @@ src/contrib/openbsd/strlcpy.c
src/contrib/openbsd/strlcpy.h
src/contrib/qp-trie/trie.c
src/contrib/qp-trie/trie.h
src/contrib/semaphore.c
src/contrib/semaphore.h
src/contrib/sockaddr.c
src/contrib/sockaddr.h
src/contrib/string.c
......
......@@ -36,6 +36,8 @@ libcontrib_la_SOURCES = \
contrib/net.h \
contrib/qp-trie/trie.c \
contrib/qp-trie/trie.h \
contrib/semaphore.c \
contrib/semaphore.h \
contrib/sockaddr.c \
contrib/sockaddr.h \
contrib/string.c \
......
/* Copyright (C) 2019 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/>.
*/
#include "semaphore.h"
#include <stdlib.h>
void knot_sem_init(knot_sem_t *sem, unsigned int value)
{
int ret = sem_init(&sem->semaphore, 1, value);
if (ret == 0) {
sem->status = -1;
} else {
sem->status = value;
sem->status_lock = malloc(sizeof(*sem->status_lock));
pthread_mutex_init(&sem->status_lock->mutex, NULL);
pthread_cond_init(&sem->status_lock->cond, NULL);
}
}
void knot_sem_wait(knot_sem_t *sem)
{
if (sem->status < 0) {
sem_wait(&sem->semaphore);
} else {
pthread_mutex_lock(&sem->status_lock->mutex);
while (sem->status == 0) {
pthread_cond_wait(&sem->status_lock->cond, &sem->status_lock->mutex);
}
sem->status--;
pthread_mutex_unlock(&sem->status_lock->mutex);
}
}
void knot_sem_post(knot_sem_t *sem)
{
if (sem->status < 0) {
sem_post(&sem->semaphore);
} else {
pthread_mutex_lock(&sem->status_lock->mutex);
sem->status++;
pthread_cond_signal(&sem->status_lock->cond);
pthread_mutex_unlock(&sem->status_lock->mutex);
}
}
void knot_sem_destroy(knot_sem_t *sem)
{
knot_sem_wait(sem);
if (sem->status < 0) {
sem_destroy(&sem->semaphore);
} else {
pthread_cond_destroy(&sem->status_lock->cond);
pthread_mutex_destroy(&sem->status_lock->mutex);
free(sem->status_lock);
}
}
/* Copyright (C) 2019 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/>.
*/
#include <pthread.h>
#include <semaphore.h>
#pragma once
typedef struct {
pthread_mutex_t mutex;
pthread_cond_t cond;
} knot_sem_mutex_t;
typedef struct {
int status;
union {
sem_t semaphore;
knot_sem_mutex_t *status_lock;
};
} knot_sem_t;
void knot_sem_init(knot_sem_t *sem, unsigned int value);
void knot_sem_wait(knot_sem_t *sem);
void knot_sem_post(knot_sem_t *sem);
void knot_sem_destroy(knot_sem_t *sem);
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 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
......@@ -157,25 +157,25 @@ int knot_nsec_chain_iterate_create(zone_tree_t *nodes,
assert(nodes);
assert(callback);
trie_it_t *it = trie_it_begin(nodes);
if (!it) {
return KNOT_ENOMEM;
zone_tree_it_t it = { 0 };
int result = zone_tree_it_begin(nodes, &it);
if (result != KNOT_EOK) {
return result;
}
if (trie_it_finished(it)) {
trie_it_free(it);
if (zone_tree_it_finished(&it)) {
zone_tree_it_free(&it);
return KNOT_EINVAL;
}
zone_node_t *first = (zone_node_t *)*trie_it_val(it);
zone_node_t *first = zone_tree_it_val(&it);
zone_node_t *previous = first;
zone_node_t *current = first;
trie_it_next(it);
zone_tree_it_next(&it);
int result = KNOT_EOK;
while (!trie_it_finished(it)) {
current = (zone_node_t *)*trie_it_val(it);
while (!zone_tree_it_finished(&it)) {
current = zone_tree_it_val(&it);
result = callback(previous, current, data);
if (result == NSEC_NODE_SKIP) {
......@@ -184,30 +184,25 @@ int knot_nsec_chain_iterate_create(zone_tree_t *nodes,
} else if (result == KNOT_EOK) {
previous = current;
} else {
trie_it_free(it);
zone_tree_it_free(&it);
return result;
}
trie_it_next(it);
zone_tree_it_next(&it);
}
trie_it_free(it);
zone_tree_it_free(&it);
return result == NSEC_NODE_SKIP ? callback(previous, first, data) :
callback(current, first, data);
}
inline static zone_node_t *it_val(trie_it_t *it)
{
return (zone_node_t *)*trie_it_val(it);
}
inline static zone_node_t *it_next0(trie_it_t *it, zone_node_t *first)
inline static zone_node_t *it_next0(zone_tree_it_t *it, zone_node_t *first)
{
trie_it_next(it);
return (trie_it_finished(it) ? first : it_val(it));
zone_tree_it_next(it);
return (zone_tree_it_finished(it) ? first : zone_tree_it_val(it));
}
static zone_node_t *it_next1(trie_it_t *it, zone_node_t *first)
static zone_node_t *it_next1(zone_tree_it_t *it, zone_node_t *first)
{
zone_node_t *res;
do {
......@@ -216,7 +211,7 @@ static zone_node_t *it_next1(trie_it_t *it, zone_node_t *first)
return res;
}
static zone_node_t *it_next2(trie_it_t *it, zone_node_t *first, changeset_t *ch)
static zone_node_t *it_next2(zone_tree_it_t *it, zone_node_t *first, changeset_t *ch)
{
zone_node_t *res = it_next0(it, first);
while (knot_nsec_empty_nsec_and_rrsigs_in_node(res) || (res->flags & NODE_FLAGS_NONAUTH)) {
......@@ -245,24 +240,25 @@ int knot_nsec_chain_iterate_fix(zone_tree_t *old_nodes, zone_tree_t *new_nodes,
assert(new_nodes);
assert(callback);
int ret = KNOT_EOK;
trie_it_t *old_it = trie_it_begin(old_nodes), *new_it = trie_it_begin(new_nodes);
if (old_it == NULL || new_it == NULL) {
ret = KNOT_ENOMEM;
zone_tree_it_t old_it = { 0 }, new_it = { 0 };
int ret = zone_tree_it_begin(old_nodes, &old_it);
if (ret == KNOT_EOK) {
ret = zone_tree_it_begin(new_nodes, &new_it);
}
if (ret != KNOT_EOK) {
goto cleanup;
}
if (trie_it_finished(new_it)) {
if (zone_tree_it_finished(&new_it)) {
ret = KNOT_ENORECORD;
goto cleanup;
}
if (trie_it_finished(old_it)) {
if (zone_tree_it_finished(&old_it)) {
ret = KNOT_ENORECORD;
goto cleanup;
}
zone_node_t *old_first = it_val(old_it), *new_first = it_val(new_it);
zone_node_t *old_first = zone_tree_it_val(&old_it), *new_first = zone_tree_it_val(&new_it);
if (!knot_dname_is_equal(old_first->owner, new_first->owner)) {
// this may happen with NSEC3 (on NSEC, it will be apex)
......@@ -280,8 +276,8 @@ int knot_nsec_chain_iterate_fix(zone_tree_t *old_nodes, zone_tree_t *new_nodes,
}
zone_node_t *old_prev = old_first, *new_prev = new_first;
zone_node_t *old_curr = it_next1(old_it, old_first);
zone_node_t *new_curr = it_next2(new_it, new_first, data->changeset);
zone_node_t *old_curr = it_next1(&old_it, old_first);
zone_node_t *new_curr = it_next2(&new_it, new_first, data->changeset);
while (1) {
bool bitmap_change = !node_bitmap_equal(old_prev, new_prev);
......@@ -305,7 +301,7 @@ int knot_nsec_chain_iterate_fix(zone_tree_t *old_nodes, zone_tree_t *new_nodes,
ret = knot_nsec_changeset_remove(old_curr, data->changeset);
CHECK_RET;
old_prev = old_curr;
old_curr = it_next1(old_it, old_first);
old_curr = it_next1(&old_it, old_first);
ret = callback(new_prev, new_curr, data);
CHECK_RET;
} else {
......@@ -315,7 +311,7 @@ int knot_nsec_chain_iterate_fix(zone_tree_t *old_nodes, zone_tree_t *new_nodes,
ret = callback(new_prev, new_curr, data);
CHECK_RET;
new_prev = new_curr;
new_curr = it_next2(new_it, new_first, data->changeset);
new_curr = it_next2(&new_it, new_first, data->changeset);
ret = callback(new_prev, new_curr, data);
CHECK_RET;
}
......@@ -328,13 +324,13 @@ int knot_nsec_chain_iterate_fix(zone_tree_t *old_nodes, zone_tree_t *new_nodes,
old_prev = old_curr;
new_prev = new_curr;
old_curr = it_next1(old_it, old_first);
new_curr = it_next2(new_it, new_first, data->changeset);
old_curr = it_next1(&old_it, old_first);
new_curr = it_next2(&new_it, new_first, data->changeset);
}
cleanup:
trie_it_free(old_it);
trie_it_free(new_it);
zone_tree_it_free(&old_it);
zone_tree_it_free(&new_it);
return ret;
}
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 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
......@@ -54,7 +54,7 @@ inline static void bitmap_add_node_rrsets(dnssec_nsec_bitmap_t *bitmap,
const zone_node_t *node)
{
bool deleg = node->flags & NODE_FLAGS_DELEG;
bool apex = node->parent == NULL;
bool apex = node->flags & NODE_FLAGS_APEX;
for (int i = 0; i < node->rrset_count; i++) {
knot_rrset_t rr = node_rrset_at(node, i);
if (deleg && (rr.type != KNOT_RRTYPE_NS && rr.type != KNOT_RRTYPE_DS)) {
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 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
......@@ -126,10 +126,9 @@ static int copy_signatures(zone_tree_t *from, zone_tree_t *to)
assert(to);
trie_it_t *it = trie_it_begin(from);
for (/* NOP */; !trie_it_finished(it); trie_it_next(it)) {
zone_node_t *node_from = (zone_node_t *)*trie_it_val(it);
zone_tree_it_t it = { 0 };
for ((void)zone_tree_it_begin(from, &it); !zone_tree_it_finished(&it); zone_tree_it_next(&it)) {
zone_node_t *node_from = zone_tree_it_val(&it);
zone_node_t *node_to = zone_tree_get(to, node_from->owner);
if (node_to == NULL) {
......@@ -142,12 +141,12 @@ static int copy_signatures(zone_tree_t *from, zone_tree_t *to)
int ret = shallow_copy_signature(node_from, node_to);
if (ret != KNOT_EOK) {
trie_it_free(it);
zone_tree_it_free(&it);
return ret;
}
}
trie_it_free(it);
zone_tree_it_free(&it);
return KNOT_EOK;
}
......@@ -159,9 +158,9 @@ static void free_nsec3_tree(zone_tree_t *nodes)
{
assert(nodes);
trie_it_t *it = trie_it_begin(nodes);
for (/* NOP */; !trie_it_finished(it); trie_it_next(it)) {
zone_node_t *node = (zone_node_t *)*trie_it_val(it);
zone_tree_it_t it = { 0 };
for ((void)zone_tree_it_begin(nodes, &it); !zone_tree_it_finished(&it); zone_tree_it_next(&it)) {
zone_node_t *node = zone_tree_it_val(&it);
// newly allocated NSEC3 nodes
knot_rdataset_t *nsec3 = node_rdataset(node, KNOT_RRTYPE_NSEC3);
knot_rdataset_t *rrsig = node_rdataset(node, KNOT_RRTYPE_RRSIG);
......@@ -170,7 +169,7 @@ static void free_nsec3_tree(zone_tree_t *nodes)
node_free(node, NULL);
}
trie_it_free(it);
zone_tree_it_free(&it);
zone_tree_free(&nodes);
}
......@@ -292,13 +291,11 @@ static zone_node_t *create_nsec3_node(const knot_dname_t *owner,
assert(apex_node);
assert(rr_types);
zone_node_t *new_node = node_new(owner, NULL);
zone_node_t *new_node = node_new(owner, false, false, NULL);
if (!new_node) {
return NULL;
}
node_set_parent(new_node, apex_node);
knot_rrset_t nsec3_rrset;
int ret = create_nsec3_rrset(&nsec3_rrset, owner, nsec3_params,
rr_types, NULL, ttl);
......@@ -497,11 +494,11 @@ static int create_nsec3_nodes(const zone_contents_t *zone,
assert(nsec3_nodes);
assert(chgset);
int result = KNOT_EOK;
zone_tree_it_t it = { 0 };
int result = zone_tree_it_begin(zone->nodes, &it);
trie_it_t *it = trie_it_begin(zone->nodes);
while (!trie_it_finished(it)) {
zone_node_t *node = (zone_node_t *)*trie_it_val(it);
while (!zone_tree_it_finished(&it)) {
zone_node_t *node = zone_tree_it_val(&it);
/*!
* Remove possible NSEC from the node. (Do not allow both NSEC
......@@ -511,8 +508,8 @@ static int create_nsec3_nodes(const zone_contents_t *zone,
if (result != KNOT_EOK) {
break;
}
if (node->flags & NODE_FLAGS_NONAUTH || node->flags & NODE_FLAGS_EMPTY) {
trie_it_next(it);
if (node->flags & NODE_FLAGS_NONAUTH || node->flags & NODE_FLAGS_EMPTY || node->flags & NODE_FLAGS_DELETED) {
zone_tree_it_next(&it);
continue;
}
......@@ -524,15 +521,15 @@ static int create_nsec3_nodes(const zone_contents_t *zone,
break;
}
result = zone_tree_insert(nsec3_nodes, nsec3_node);
result = zone_tree_insert(nsec3_nodes, &nsec3_node);
if (result != KNOT_EOK) {
break;
}
trie_it_next(it);
zone_tree_it_next(&it);
}
trie_it_free(it);
zone_tree_it_free(&it);
return result;
}
......@@ -634,6 +631,7 @@ static int fix_nsec3_for_node(zone_update_t *update, const dnssec_nsec3_params_t
ret = changeset_add_addition(chgset, &nsec3, CHANGESET_CHECK | CHANGESET_CHECK_CANCELOUT);
}
}
binode_unify(new_nsec3_n, false, NULL);
node_free_rrsets(new_nsec3_n, NULL);
node_free(new_nsec3_n, NULL);
}
......@@ -646,23 +644,28 @@ static int fix_nsec3_nodes(zone_update_t *update, const dnssec_nsec3_params_t *p
{
assert(update);
int ret = KNOT_EOK;
zone_tree_it_t it = { 0 };
int ret = zone_tree_it_begin(update->change.remove->nodes, &it);
trie_it_t *rem_it = trie_it_begin(update->change.remove->nodes);
while (!trie_it_finished(rem_it) && ret == KNOT_EOK) {
zone_node_t *n = (zone_node_t *)*trie_it_val(rem_it);
while (!zone_tree_it_finished(&it) && ret == KNOT_EOK) {
zone_node_t *n = zone_tree_it_val(&it);
ret = fix_nsec3_for_node(update, params, ttl, opt_out, chgset, n->owner);
trie_it_next(rem_it);
zone_tree_it_next(&it);
}
trie_it_free(rem_it);
trie_it_t *add_it = trie_it_begin(update->change.add->nodes);
while (!trie_it_finished(add_it) && ret == KNOT_EOK) {
zone_node_t *n = (zone_node_t *)*trie_it_val(add_it);
ret = fix_nsec3_for_node(update, params, ttl, opt_out, chgset, n->owner);
trie_it_next(add_it);
if (ret == KNOT_EOK) {
zone_tree_it_free(&it);
ret = zone_tree_it_begin(update->change.add->nodes, &it);
}
trie_it_free(add_it);
while (!zone_tree_it_finished(&it) && ret == KNOT_EOK) {
zone_node_t *n = zone_tree_it_val(&it);
if (zone_tree_get(update->change.remove->nodes, n->owner) == NULL) {
ret = fix_nsec3_for_node(update, params, ttl, opt_out, chgset, n->owner);
}
zone_tree_it_next(&it);
}
zone_tree_it_free(&it);
return ret;
}
......@@ -687,10 +690,8 @@ static bool nsec3_is_empty(zone_node_t *node, bool opt_out)
* It also lowers the children count for the parent of marked node. This must be
* fixed before further operations on the zone.
*/
static int nsec3_mark_empty(zone_node_t **node_p, void *data)
static int nsec3_mark_empty(zone_node_t *node, void *data)
{
zone_node_t *node = *node_p;
if (!(node->flags & NODE_FLAGS_EMPTY) && nsec3_is_empty(node, (data != NULL))) {
/*!
* Mark this node and all parent nodes that meet the same
......@@ -698,14 +699,14 @@ static int nsec3_mark_empty(zone_node_t **node_p, void *data)
*/
node->flags |= NODE_FLAGS_EMPTY;
if (node->parent) {
if (!(node->flags & NODE_FLAGS_APEX)) {
/* We must decrease the parent's children count,
* but only temporarily! It must be set back right after
* the operation
*/
node->parent->children--;
node_parent(node)->children--;
/* Recurse using the parent node */
return nsec3_mark_empty(&node->parent, data);
return nsec3_mark_empty(node_parent(node), data);
}
}
......@@ -719,16 +720,14 @@ static int nsec3_mark_empty(zone_node_t **node_p, void *data)
* The children count of node's parent is increased if this node was marked as
* empty, as it was previously decreased in the \a nsec3_mark_empty() function.
*/
static int nsec3_reset(zone_node_t **node_p, void *data)
static int nsec3_reset(zone_node_t *node, void *data)
{
UNUSED(data);
zone_node_t *node = *node_p;
if (node->flags & NODE_FLAGS_EMPTY) {
/* If node was marked as empty, increase its parent's children
* count.
*/
node->parent->children++;
node_parent(node)->children++;
/* Clear the 'empty' flag. */
node->flags &= ~NODE_FLAGS_EMPTY;
}
......@@ -753,7 +752,7 @@ int knot_nsec3_create_chain(const zone_contents_t *zone,
int result;
zone_tree_t *nsec3_nodes = zone_tree_create();
zone_tree_t *nsec3_nodes = zone_tree_create(false);
if (!nsec3_nodes) {
return KNOT_ENOMEM;
}
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 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
......@@ -46,7 +46,7 @@ static int delete_nsec3_chain(const zone_contents_t *zone, changeset_t *changese
return KNOT_EOK;
}
zone_tree_t *empty_tree = zone_tree_create();
zone_tree_t *empty_tree = zone_tree_create(false);
if (!empty_tree) {
return KNOT_ENOMEM;
}
......
......@@ -524,14 +524,14 @@ typedef struct {
* \param node Node to be signed.
* \param data Callback data, node_sign_args_t.
*/
static int sign_node(zone_node_t **node, void *data)
static int sign_node(zone_node_t *node, void *data)
{
assert(node && *node);
assert(node);
assert(data);
node_sign_args_t *args = (node_sign_args_t *)data;
if ((*node)->rrset_count == 0) {
if (node->rrset_count == 0) {
return KNOT_EOK;
}
......@@ -539,7 +539,7 @@ static int sign_node(zone_node_t **node, void *data)
return KNOT_EOK;
}
int result = sign_node_rrsets(*node, args->sign_ctx,
int result = sign_node_rrsets(node, args->sign_ctx,
&args->changeset, &args->expires_at);
return result;
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 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
......@@ -33,7 +33,9 @@ int event_expire(conf_t *conf, zone_t *zone)
log_zone_info(zone->name, "zone expired");
synchronize_rcu();
knot_sem_wait(&zone->cow_lock);
zone_contents_deep_free(expired);
knot_sem_post(&zone->cow_lock);
zone->zonefile.exists = false;
mem_trim();
......
......@@ -193,7 +193,7 @@ static void xfr_log_publish(const struct refresh_data *data,
static int axfr_init(struct refresh_data *data)
{
zone_contents_t *new_zone = zone_contents_new(data->zone->name);
zone_contents_t *new_zone = zone_contents_new(data->zone->name, true);
if (new_zone == NULL) {
return KNOT_ENOMEM;
}
......
......@@ -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.
......
......@@ -183,7 +183,7 @@ static int add_rr_to_contents(zone_contents_t *z, const knot_rrset_t *rrset)
bool journal_read_changeset(journal_read_t *ctx, changeset_t *ch)
{
zone_contents_t *tree = zone_contents_new(ctx->zone);
zone_contents_t *tree = zone_contents_new(ctx->zone, false);
knot_rrset_t *soa = calloc(1, sizeof(*soa)), rr = { 0 };
if (tree == NULL || soa == NULL) {
ctx->txn.ret = KNOT_ENOMEM;
......@@ -203,7 +203,7 @@ bool journal_read_changeset(journal_read_t *ctx, changeset_t *ch)
ch->soa_from = soa;
ch->remove = tree;
soa = malloc(sizeof(*soa));
tree = zone_contents_new(ctx->zone);
tree = zone_contents_new(ctx->zone, false);
if (tree == NULL || soa == NULL) {
ctx->txn.ret = KNOT_ENOMEM;
goto fail;
......
......@@ -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));