Commit 8d2ac727 authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

journal: remove old journal implementation

parent 844209ef
......@@ -138,10 +138,6 @@ src/knot/events/handlers/update.c
src/knot/events/replan.c
src/knot/events/replan.h
src/knot/include/module.h
src/knot/journal/chgset_ctx.c
src/knot/journal/chgset_ctx.h
src/knot/journal/journal.c
src/knot/journal/journal.h
src/knot/journal/journal_basic.c
src/knot/journal/journal_basic.h
src/knot/journal/journal_metadata.c
......
......@@ -121,10 +121,6 @@ libknotd_la_SOURCES = \
knot/common/stats.h \
knot/server/dthreads.c \
knot/server/dthreads.h \
knot/journal/chgset_ctx.c \
knot/journal/chgset_ctx.h \
knot/journal/journal.c \
knot/journal/journal.h \
knot/journal/journal_basic.c \
knot/journal/journal_basic.h \
knot/journal/journal_metadata.c \
......
/* 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
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 "chgset_ctx.h"
#include "knot/journal/journal.h"
#include "knot/journal/serialization.h"
chgset_ctx_t *chgset_ctx_create(size_t chunk_count)
{
chgset_ctx_t *ch = calloc(1, sizeof(*ch));
if (ch != NULL) {
ch->chunk_count = chunk_count;
ch->src_chunks = calloc(chunk_count, sizeof(*ch->src_chunks));
ch->chunk_sizes = calloc(chunk_count, sizeof(*ch->chunk_sizes));
if (ch->src_chunks == NULL || ch->chunk_sizes == NULL) {
chgset_ctx_free(ch);
ch = NULL;
}
}
return ch;
}
void chgset_ctx_free(chgset_ctx_t *ch)
{
free(ch->src_chunks);
free(ch->chunk_sizes);
free(ch);
}
void chgset_ctx_list_close(chgset_ctx_list_t *l)
{
chgset_ctx_t *ch = NULL, *nxt = NULL;
WALK_LIST_DELSAFE(ch, nxt, l->l) {
chgset_ctx_free(ch);
}
journal_txn_commit(l->txn);
free(l->txn);
memset(l, 0, sizeof(*l));
}
void chgset_ctx_iterate(chgset_ctx_t *ch)
{
assert(ch->chunk_count > 0);
ch->curr_chunk = 0;
ch->wire = wire_ctx_init(ch->src_chunks[0], ch->chunk_sizes[0]);
ch->phase = CHGSET_CTX_START;
}
int chgset_ctx_next(chgset_ctx_t *ch, knot_rrset_t *rrset)
{
int ret = deserialize_rrset_chunks(&ch->wire, rrset, ch->src_chunks,
ch->chunk_sizes, ch->chunk_count, &ch->curr_chunk);
if (ret != KNOT_EOK) {
return ret;
}
if (ch->phase == CHGSET_CTX_START && rrset->type != KNOT_RRTYPE_SOA) {
return KNOT_EMALF;
}
if (ch->phase == CHGSET_CTX_SOA_FROM || ch->phase == CHGSET_CTX_SOA_TO ||
rrset->type == KNOT_RRTYPE_SOA) {
ch->phase++;
}
if (ch->curr_chunk == ch->chunk_count - 1 && wire_ctx_available(&ch->wire) == 0) {
ch->phase = CHGSET_CTX_DONE;
} else if (ch->phase == CHGSET_CTX_DONE) {
return KNOT_EMALF;
}
return ret;
}
/* 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
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/>.
*/
#pragma once
#include "contrib/ucw/lists.h"
#include "contrib/wire_ctx.h"
#include "libknot/rrset.h"
typedef enum {
CHGSET_CTX_NOITER = 0,
CHGSET_CTX_START,
CHGSET_CTX_SOA_FROM,
CHGSET_CTX_REM,
CHGSET_CTX_SOA_TO,
CHGSET_CTX_ADD,
CHGSET_CTX_DONE,
} chgset_ctx_phase_t;
struct journal_txn; // journal.c
typedef struct {
node_t n;
uint8_t **src_chunks;
size_t *chunk_sizes;
size_t chunk_count;
size_t curr_chunk;
wire_ctx_t wire;
chgset_ctx_phase_t phase;
uint32_t serial_from;
uint32_t serial_to;
} chgset_ctx_t;
typedef struct {
list_t l;
struct journal_txn *txn;
} chgset_ctx_list_t;
chgset_ctx_t *chgset_ctx_create(size_t chunk_count);
void chgset_ctx_free(chgset_ctx_t *ch);
void chgset_ctx_list_close(chgset_ctx_list_t *l);
void chgset_ctx_iterate(chgset_ctx_t *ch);
int chgset_ctx_next(chgset_ctx_t *ch, knot_rrset_t *rrset);
This diff is collapsed.
/* 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/>.
*/
#pragma once
#include <pthread.h>
#include "libknot/db/db.h"
#include "contrib/ucw/lists.h"
#include "knot/updates/changesets.h"
#include "knot/journal/serialization.h"
#include "knot/journal/chgset_ctx.h"
#include "knot/zone/serial.h"
/*! \brief Minimum journal size. */
#define JOURNAL_MIN_FSLIMIT (1 * 1024 * 1024)
typedef struct {
knot_db_t *db;
const knot_db_api_t *db_api;
char *path;
size_t fslimit;
int mode;
pthread_mutex_t db_mutex; // please delete this once you move DB opening from journal_open to db_init
} journal_db_t;
typedef struct {
journal_db_t *db;
knot_dname_t *zone;
} journal_t;
typedef enum {
JOURNAL_CHECK_SILENT = 0, // No logging, just curious for return value.
JOURNAL_CHECK_WARN = 1, // Log journal inconsistencies.
JOURNAL_CHECK_INFO = 2, // Log journal state.
JOURNAL_CHECK_STDERR = 3, // Log everything and redirect to stderr.
} journal_check_level_t;
struct journal_txn;
/*!
* \brief Initialize shared journal DB file. The DB will be open on first use.
*
* \param db Database to be initialized. Must be (*db == NULL) before!
* \param lmdb_dir_path Path to the directory with DB
* \param lmdb_fslimit Maximum size of DB data file
* \param mode Journal DB synchronization mode.
*
* \return KNOT_E*
*/
int journal_db_init(journal_db_t **db, const char *lmdb_dir_path, size_t lmdb_fslimit,
int mode);
/*!
* \brief Close shared journal DB file.
*
* \param db DB to close.
*/
void journal_db_close(journal_db_t **db);
/*!
* \brief List the zones contained in journal DB.
*
* \param[in] db Shared journal DB
* \param[out] zones List of strings (char *) of zone names
*
* \return KNOT_EOK ok
* \retval KNOT_ENOMEM no zones found
* \retval KNOT_EMALF different # of zones found than expected
* \retval KNOT_E* other error
*/
int journal_db_list_zones(journal_db_t **db, list_t *zones);
/*!
* \brief Allocate a new journal structure.
*
* \retval new journal instance if successful.
* \retval NULL on error.
*/
journal_t *journal_new(void);
/*!
* \brief Free a journal structure.
*
* \param journal A journal structure to free.
*/
void journal_free(journal_t **journal);
/*!
* \brief Open/create the journal based on the filesystem path to LMDB directory
*
* \param journal Journal struct to use.
* \param db Shared journal database.
* \param zone_name Name of the zone this journal belongs to.
*
* \retval KNOT_EOK on success.
* \return < KNOT_EOK on other errors.
*/
int journal_open(journal_t *journal, journal_db_t **db,
const knot_dname_t *zone_name);
/*!
* \brief Close journal.
*
* \param journal Journal to close.
*/
void journal_close(journal_t *journal);
/*!
* \brief Load changesets from journal since "from" serial.
*
* \param journal Journal to load from.
* \param dst Store changesets here.
* \param from Start serial.
*
* \retval KNOT_EOK on success.
* \retval KNOT_ENOENT when the lookup of the first entry fails.
* \return < KNOT_EOK on other error.
*/
int journal_load_changesets(journal_t *journal, list_t *dst, uint32_t from);
int journal_load_chgset_ctx(journal_t *j, chgset_ctx_list_t *dst, uint32_t from);
/*!
* \brief Load changesets from journal, starting with bootstrap changeset.
*
* \param journal Journal to load from.
* \param dst Store changesets here, starting with bootstrap changeset.
*
* \retval KNOT_EOK on success.
* \retval KNOT_ENOENT when there is no bootstrap changeset.
* \return < KNOT_EOK on other error.
*/
int journal_load_bootstrap(journal_t *journal, list_t *dst);
/*!
* \brief Store changesets in journal.
*
* \param journal Journal to store in.
* \param src Changesets to store.
*
* \retval KNOT_EOK on success.
* \retval KNOT_EBUSY when full, asking zone to flush itself to zonefile
* to allow cleaning up history and freeing up space
* \retval KNOT_ESPACE when full and not able to free up any space
* \return < KNOT_EOK on other errors.
*/
int journal_store_changesets(journal_t *journal, list_t *src);
/*!
* \brief Store changesets in journal.
*
* \param journal Journal to store in.
* \param change Changeset to store.
*
* \retval (same as for journal_store_changesets())
*/
int journal_store_changeset(journal_t *journal, changeset_t *change);
/*!
* \brief Open the journal database.
*
* This is an "almost static" function, which is mostly called by other journal
* methods like journal_open() and journal_exists(). However it can be called
* separately just for more precise error resolution.
*
* \param db Journal to be opened.
* \return KNOT_E*
*/
int journal_open_db(journal_db_t **db);
/*!
* \brief Check if this (zone's) journal is present in shared journal DB.
*
* \param db Shared journal DB
* \param zone_name Name of the zone of the journal in question
*
* \return true or false
*/
bool journal_exists(journal_db_t **db, knot_dname_t *zone_name);
/*! \brief Tell the journal that zone has been flushed.
*
* \param journal Journal to flush.
*
* \return KNOT_E*
*/
int journal_flush(journal_t *journal);
/*! \brief Remove completely this (zone's) journal from shared journal DB.
*
* This must be called with opened journal.
*
* \param journal Journal to be deleted
*
* \return KNOT_E*
*/
int journal_scrape(journal_t *journal);
/*! \brief Obtain public information from journal metadata
*/
void journal_metadata_info(journal_t *journal, bool *is_empty, kserial_t *merged_serial,
kserial_t *first_serial, kserial_t *last_flushed,
kserial_t *serial_to, uint64_t *occupied, uint64_t *occupied_all_zones);
/*!
* \brief Delete all changesets in zone's journal, keeping metadata.
*
* \param journal Journal to clear.
*
* \return KNOT_E*
*/
int journal_drop_changesets(journal_t *journal);
/*! \brief Check the journal consistency, errors to stderr.
*
* \param journal Journal to check.
* \param warn_level Journal check level.
*
* \return KNOT_E*
*/
int journal_check(journal_t *journal, journal_check_level_t warn_level);
void journal_txn_commit(struct journal_txn *txn);
/*! @} */
......@@ -191,79 +191,6 @@ void serialize_deinit(serialize_ctx_t *ctx)
free(ctx);
}
static int _deserialize_rrset(wire_ctx_t *wire, knot_rrset_t *rrset, long *phase)
{
assert(wire != NULL && rrset != NULL && phase != NULL);
assert(*phase >= SERIALIZE_RRSET_INIT && *phase < SERIALIZE_RRSET_DONE);
if (*phase == SERIALIZE_RRSET_INIT && wire_ctx_available(wire) > 0) {
// Read owner, rtype, rclass and RR count.
size_t size = knot_dname_size(wire->position);
knot_dname_t *owner = knot_dname_copy(wire->position, NULL);
if (owner == NULL || wire_ctx_available(wire) < size + 3 * sizeof(uint16_t)) {
knot_dname_free(owner, NULL);
return KNOT_EMALF;
}
wire_ctx_skip(wire, size);
uint16_t type = wire_ctx_read_u16(wire);
uint16_t rclass = wire_ctx_read_u16(wire);
uint16_t rrcount = wire_ctx_read_u16(wire);
(*phase) = rrcount;
if (wire->error != KNOT_EOK) {
knot_dname_free(owner, NULL);
return wire->error;
}
knot_rrset_init(rrset, owner, type, rclass, 0);
}
bool first = true;
for ( ; *phase > 0 && wire_ctx_available(wire) > 0; (*phase)--) {
uint32_t ttl = wire_ctx_read_u32(wire);
if (first) {
rrset->ttl = ttl;
first = false;
}
uint32_t rdata_size = wire_ctx_read_u16(wire);
if (wire->error != KNOT_EOK ||
wire_ctx_available(wire) < rdata_size ||
knot_rrset_add_rdata(rrset, wire->position, rdata_size,
NULL) != KNOT_EOK) {
knot_rrset_clear(rrset, NULL);
return KNOT_EMALF;
}
wire_ctx_skip(wire, rdata_size);
assert(wire->error == KNOT_EOK);
}
if (*phase == 0) {
*phase = SERIALIZE_RRSET_DONE;
}
return KNOT_EOK;
}
int deserialize_rrset_chunks(wire_ctx_t *wire, knot_rrset_t *rrset,
uint8_t *src_chunks[], const size_t *chunk_sizes,
size_t chunks_count, size_t *cur_chunk)
{
long phase = SERIALIZE_RRSET_INIT;
while (1) {
int ret = _deserialize_rrset(wire, rrset, &phase);
if (ret != KNOT_EOK || phase == SERIALIZE_RRSET_DONE) {
return ret;
}
// now the rrset wasn't whole on this chunk
if (*cur_chunk >= chunks_count - 1) {
return KNOT_EMALF;
}
if (wire->error != KNOT_EOK) {
return wire->error;
}
(*cur_chunk)++;
assert(chunk_sizes[*cur_chunk] > 0);
*wire = wire_ctx_init(src_chunks[*cur_chunk], chunk_sizes[*cur_chunk]);
}
}
static uint64_t rrset_binary_size(const knot_rrset_t *rrset)
{
if (rrset == NULL || rrset->rrs.count == 0) {
......@@ -312,79 +239,6 @@ size_t changeset_serialized_size(const changeset_t *ch)
return soa_from_size + soa_to_size + change_size;
}
int changeset_deserialize(changeset_t *ch, uint8_t *src_chunks[],
const size_t *chunks_sizes, size_t chunks_count)
{
if (ch == NULL || src_chunks == NULL || chunks_sizes == NULL ||
chunks_count == 0) {
return KNOT_EINVAL;
}
size_t cur_chunk = 0;
wire_ctx_t wire = wire_ctx_init_const(src_chunks[0], chunks_sizes[0]);
// Deserialize SOA 'from'.
knot_rrset_t rrset;
int ret = deserialize_rrset_chunks(&wire, &rrset, src_chunks, chunks_sizes,
chunks_count, &cur_chunk);
if (ret != KNOT_EOK) {
return ret;
}
assert(rrset.type == KNOT_RRTYPE_SOA);
ch->soa_from = knot_rrset_copy(&rrset, NULL);
knot_rrset_clear(&rrset, NULL);
if (ch->soa_from == NULL) {
return KNOT_ENOMEM;
}
// Read remaining RRSets.
bool in_remove_section = true;
while (cur_chunk < chunks_count - 1 || wire_ctx_available(&wire) > 0) {
// Parse next RRSet.
ret = deserialize_rrset_chunks(&wire, &rrset, src_chunks, chunks_sizes,
chunks_count, &cur_chunk);
if (ret != KNOT_EOK) {
break;
}
// Check for next (and also last) SOA.
if (rrset.type == KNOT_RRTYPE_SOA) {
// Move to ADD section if in REMOVE.
assert(in_remove_section);
in_remove_section = false;
ch->soa_to = knot_rrset_copy(&rrset, NULL);
if (ch->soa_to == NULL) {
ret = KNOT_ENOMEM;
}
} else {
if (in_remove_section) {
ret = changeset_add_removal(ch, &rrset, 0);
} else {
ret = changeset_add_addition(ch, &rrset, 0);
}
}
knot_rrset_clear(&rrset, NULL);
if (ret != KNOT_EOK) {
return ret;
}
}
// If there was only one SOA record, we are in the bootstrap changeset.
if (in_remove_section) {
ch->soa_to = ch->soa_from;
ch->soa_from = NULL;
zone_contents_t *tmp = ch->add;
ch->add = ch->remove;
ch->remove = tmp;
}
return wire.error;
}
int serialize_rrset(wire_ctx_t *wire, const knot_rrset_t *rrset)
{
assert(wire != NULL && rrset != NULL);
......
......@@ -68,35 +68,6 @@ void serialize_deinit(serialize_ctx_t *ctx);
*/
size_t changeset_serialized_size(const changeset_t *ch);
/*!
* \brief Deserializes chunked area into ch
*
* \param[out] ch The changeset.
* \param[in] src_chunks The chunks to deserialize.
* \param[in] chunks_sizes The size of each chunk.
* \param[in] chunks_count The number of chunks.
*
* \retval KNOT_E*
*/
int changeset_deserialize(changeset_t *ch, uint8_t *src_chunks[],
const size_t *chunks_sizes, size_t chunks_count);
/*!
* \brief Deserializes single RRSet being part of a changeset serialized in chunks.
*
* \param wire[in] Current chunk ready to be parsed.
* \param rrset[out] RRSet to be deserialized (empty before).
* \param src_chunks[in] All chunks of the serialized changeset.
* \param chunk_sizes[in] Their sizes.
* \param chunks_count[in] Their count.
* \param cur_chunk[in+out] Index of current chunk.
*
* \return KNOT_E*
*/
int deserialize_rrset_chunks(wire_ctx_t *wire, knot_rrset_t *rrset,
uint8_t *src_chunks[], const size_t *chunk_sizes,
size_t chunks_count, size_t *cur_chunk);
/*!
* \brief Simply serialize RRset w/o any chunking.
*
......
......@@ -15,7 +15,6 @@
*/
#include "knot/common/log.h"
#include "knot/journal/journal.h"
#include "knot/journal/journal_metadata.h"
#include "knot/journal/journal_read.h"
#include "knot/zone/zone-diff.h"
......
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