Skip to content
Snippets Groups Projects
Commit d0d375fa authored by Daniel Salzman's avatar Daniel Salzman
Browse files

zone: add optimized zonedb loading

parent 09222d11
No related branches found
No related tags found
No related merge requests found
......@@ -29,6 +29,7 @@
#include <stdint.h>
#include "knot/conf/conf.h"
#include "knot/conf/confio.h"
#include "knot/server/journal.h"
#include "knot/events/events.h"
#include "knot/zone/contents.h"
......@@ -57,6 +58,9 @@ typedef struct zone
zone_contents_t *contents;
zone_flag_t flags;
/*! \brief Dynamic configuration zone change type. */
conf_io_type_t change_type;
/*! \brief Zonefile parameters. */
struct {
time_t mtime;
......
......@@ -17,6 +17,7 @@
#include <assert.h>
#include <urcu.h>
#include "knot/conf/confio.h"
#include "knot/zone/zonedb-load.h"
#include "knot/zone/zone-load.h"
#include "knot/zone/zone.h"
......@@ -268,6 +269,28 @@ static zone_t *create_zone(conf_t *conf, const knot_dname_t *name, server_t *ser
}
}
static void mark_changed_zones(knot_zonedb_t *zonedb, hattrie_t *changed)
{
if (changed == NULL) {
return;
}
hattrie_iter_t *it = hattrie_iter_begin(changed, false);
for (; !hattrie_iter_finished(it); hattrie_iter_next(it)) {
size_t len;
const knot_dname_t *name =
(const knot_dname_t *)hattrie_iter_key(it, &len);
zone_t *zone = knot_zonedb_find(zonedb, name);
if (zone != NULL) {
conf_io_type_t type = (conf_io_type_t)(*hattrie_iter_val(it));
assert(!(type & CONF_IO_TSET));
zone->change_type = type;
}
}
hattrie_iter_free(it);
}
/*!
* \brief Create new zone database.
*
......@@ -290,13 +313,31 @@ static knot_zonedb_t *create_zonedb(conf_t *conf, server_t *server)
return NULL;
}
bool full = !(conf->io.flags & CONF_IO_FACTIVE) ||
(conf->io.flags & CONF_IO_FRLD_ZONES);
/* Mark changed zones. */
if (!full) {
mark_changed_zones(server->zone_db, conf->io.zones);
}
for (conf_iter_t iter = conf_iter(conf, C_ZONE); iter.code == KNOT_EOK;
conf_iter_next(conf, &iter)) {
conf_val_t id = conf_iter_id(conf, &iter);
zone_t *old_zone = knot_zonedb_find(db_old, conf_dname(&id));
zone_t *zone = create_zone(conf, conf_dname(&id), server, old_zone);
if (!zone) {
log_zone_error(id.data, "zone cannot be created");
const knot_dname_t *name = conf_dname(&id);
zone_t *old_zone = knot_zonedb_find(db_old, name);
if (old_zone != NULL && !full) {
/* Reuse unchanged zone. */
if (!(old_zone->change_type & CONF_IO_TRELOAD)) {
knot_zonedb_insert(db_new, old_zone);
continue;
}
}
zone_t *zone = create_zone(conf, name, server, old_zone);
if (zone == NULL) {
log_zone_error(name, "zone cannot be created");
continue;
}
......@@ -315,35 +356,56 @@ static knot_zonedb_t *create_zonedb(conf_t *conf, server_t *server)
* \note Zone content may be preserved in the new zone database, in this case
* new and old zone share the contents. Shared content is not freed.
*
* \param db_new New zone database.
* \param db_old Old zone database.
* \param conf New server configuration.
* \param db_old Old zone database to remove.
* \param db_new New zone database for comparison if full reload.
*/
static void remove_old_zonedb(const knot_zonedb_t *db_new, knot_zonedb_t *db_old)
static void remove_old_zonedb(conf_t *conf, knot_zonedb_t *db_old,
knot_zonedb_t *db_new)
{
if (db_old == NULL) {
return;
}
bool full = !(conf->io.flags & CONF_IO_FACTIVE) ||
(conf->io.flags & CONF_IO_FRLD_ZONES);
knot_zonedb_iter_t it;
knot_zonedb_iter_begin(db_new, &it);
knot_zonedb_iter_begin(db_old, &it);
while(!knot_zonedb_iter_finished(&it)) {
zone_t *new_zone = knot_zonedb_iter_val(&it);
zone_t *old_zone = knot_zonedb_find(db_old, new_zone->name);
while (!knot_zonedb_iter_finished(&it)) {
zone_t *zone = knot_zonedb_iter_val(&it);
if (old_zone) {
old_zone->contents = NULL;
if (full) {
/* Check if reloaded (reused contents). */
if (knot_zonedb_find(db_new, zone->name)) {
zone->contents = NULL;
}
/* Completely new zone. */
} else {
/* Check if reloaded (reused contents). */
if (zone->change_type & CONF_IO_TRELOAD) {
zone->contents = NULL;
zone_free(&zone);
/* Check if removed (drop also contents). */
} else if (zone->change_type & CONF_IO_TUNSET) {
zone_free(&zone);
}
/* Completely reused zone. */
}
knot_zonedb_iter_next(&it);
}
knot_zonedb_deep_free(&db_old);
if (full) {
knot_zonedb_deep_free(&db_old);
} else {
knot_zonedb_free(&db_old);
}
}
void zonedb_reload(conf_t *conf, server_t *server)
{
/* Check parameters */
if (conf == NULL || server == NULL) {
return;
}
......@@ -368,10 +430,6 @@ void zonedb_reload(conf_t *conf, server_t *server)
/* Sweep the timer database. */
sweep_timer_db(server->timers_db, db_new);
/*
* Remove all zones present in the new DB from the old DB.
* No new thread can access these zones in the old DB, as the
* databases are already switched.
*/
remove_old_zonedb(db_new, db_old);
/* Remove old zone DB. */
remove_old_zonedb(conf, db_old, db_new);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment