Skip to content
Snippets Groups Projects
Commit b8d17135 authored by Jan Kadlec's avatar Jan Kadlec
Browse files

persistent events: reusing the events + db sweep

parent 678e9361
Branches
Tags
No related merge requests found
......@@ -74,10 +74,12 @@ static knot_namedb_t* init(const char *handle, mm_ctx_t *mm)
static void deinit(knot_namedb_t *db)
{
struct lmdb_env *env = db;
if (db) {
struct lmdb_env *env = db;
dbase_close(env);
mm_free(env->pool, env);
dbase_close(env);
mm_free(env->pool, env);
}
}
static int txn_begin(knot_namedb_t *db, knot_txn_t *txn, unsigned flags)
......@@ -136,7 +138,11 @@ static int find(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flag
int ret = mdb_get(txn->txn, env->dbi, &db_key, &data);
if (ret != 0) {
return KNOT_ERROR;
if (ret == MDB_NOTFOUND) {
return KNOT_ENOENT;
} else {
return KNOT_ERROR;
}
}
val->data = data.mv_data;
......@@ -262,9 +268,11 @@ struct namedb_api *namedb_lmdb_api(void)
#else
#include <stdlib.h>
struct namedb_api *namedb_lmdb_api(void)
{
return NULL;
}
#endif
\ No newline at end of file
#endif
......@@ -329,10 +329,7 @@ int main(int argc, char **argv)
/* Open zone timers db. */
int ret = open_timers_db(config);
if (ret != KNOT_EOK) {
server_deinit(&server);
conf_free(conf());
log_close();
return EXIT_FAILURE;
log_warning("Cannot open timers db (%s)\n", knot_strerror(ret));
}
/* Register base signal handling. */
......
......@@ -113,87 +113,149 @@ static void log_zone_load_info(const zone_t *zone, const char *zone_name,
log_zone_info(zone->name, "zone %s, serial %u", action, serial);
}
static int create_zone_reload(zone_t *zone, conf_zone_t *zone_conf, server_t *server,
zone_t *old_zone)
static zone_t *create_zone_from(zone_t *old_zone, conf_zone_t *zone_conf, server_t *server)
{
}
static int create_zone_restart(zone_t *zone, conf_zone_t *zone_conf, server_t *server)
{
}
/*!
* \brief Load or reload the zone.
*
* \param zone_conf Zone configuration.
* \param server Server.
* \param old_zone Already loaded zone (can be NULL).
*
* \return Error code, KNOT_EOK if successful.
*/
static zone_t *create_zone(conf_zone_t *zone_conf, server_t *server, zone_t *old_zone)
{
assert(zone_conf);
assert(server);
time_t timers[ZONE_EVENT_COUNT];
memset(timers, 0, sizeof(timers));
zone_t *zone = zone_new(zone_conf);
if (!zone) {
return NULL;
}
if (old_zone) {
zone->contents = old_zone->contents;
} else {
// Get persistent timers
int ret = read_zone_timers(conf(), zone, timers);
if (ret != KNOT_EOK) {
zone->conf = NULL;
zone_free(&zone);
return NULL;
}
}
zone_status_t zstatus = zone_file_status(old_zone, zone_conf);
int result = zone_events_setup(zone, server->workers, &server->sched);
if (result != KNOT_EOK) {
zone->conf = NULL;
zone_free(&zone);
return NULL;
}
return zone;
}
static zone_t *create_zone_reload(conf_zone_t *zone_conf, server_t *server,
zone_t *old_zone)
{
zone_t *zone = create_zone_from(old_zone, zone_conf, server);
if (!zone) {
return NULL;
}
zone->contents = old_zone->contents;
const zone_status_t zstatus = zone_file_status(old_zone, zone_conf);
switch (zstatus) {
case ZONE_STATUS_FOUND_NEW: // TIMERS: sort new
case ZONE_STATUS_FOUND_UPDATED:
/* Enqueueing makes the first zone load waitable. */
zone_events_enqueue(zone, ZONE_EVENT_RELOAD);
/* Replan DDNS processing if there are pending updates. */
zone_events_replan_ddns(zone, old_zone);
break;
case ZONE_STATUS_BOOSTRAP: // TIMERS: sort bootstrap
#warning should not call this if we have old zone!
zone_events_schedule(zone, ZONE_EVENT_REFRESH, ZONE_EVENT_NOW);
break;
case ZONE_STATUS_NOT_FOUND:
break;
case ZONE_STATUS_FOUND_CURRENT:
assert(old_zone);
zone->zonefile_mtime = old_zone->zonefile_mtime;
zone->zonefile_serial = old_zone->zonefile_serial;
/* Reuse events from old zone. */
zone_events_update(zone, old_zone);
break;
default:
assert(0);
}
return zone;
}
log_zone_load_info(zone, zone_conf->name, zstatus);
static bool slave_event(zone_event_type_t event)
{
return event == ZONE_EVENT_EXPIRE || event == ZONE_EVENT_REFRESH;
}
static void reuse_uvents(zone_t *zone, const time_t *timers)
{
for (zone_event_type_t event = 0; event < ZONE_EVENT_COUNT; ++event) {
if (timers[event] == 0) {
// Timer unset.
continue;
}
if (slave_event(event) && !zone_master(zone)) {
// Slave-only event.
continue;
}
zone_events_schedule_at(zone, event, timers[event]);
}
}
static bool zone_expired(const time_t *timers)
{
const time_t now = time(NULL);
return now <= timers[ZONE_EVENT_EXPIRE];
}
static zone_t *create_zone_new(conf_zone_t *zone_conf, server_t *server)
{
zone_t *zone = create_zone_from(NULL, zone_conf, server);
if (!zone) {
return NULL;
}
time_t timers[ZONE_EVENT_COUNT];
memset(timers, 0, sizeof(timers));
// Get persistent timers
int ret = read_zone_timers(conf(), zone, timers);
if (ret != KNOT_EOK) {
log_zone_error(zone->name, "cannot read zone timers (%s)",
knot_strerror(ret));
zone->conf = NULL;
zone_free(&zone);
return NULL;
}
reuse_uvents(zone, timers);
const zone_status_t zstatus = zone_file_status(NULL, zone_conf);
switch (zstatus) {
case ZONE_STATUS_FOUND_NEW:
if (!zone_expired(timers)) {
/* Enqueueing makes the first zone load waitable. */
zone_events_enqueue(zone, ZONE_EVENT_RELOAD);
}
break;
case ZONE_STATUS_BOOSTRAP:
if (timers[ZONE_EVENT_REFRESH] == 0) {
// Plan immediate refresh if not already planned.
zone_events_schedule(zone, ZONE_EVENT_REFRESH, ZONE_EVENT_NOW);
}
break;
case ZONE_STATUS_NOT_FOUND:
break;
default:
assert(0);
}
log_zone_load_info(zone, zone_conf->name, zstatus);
return zone;
}
/*!
* \brief Load or reload the zone.
*
* \param zone_conf Zone configuration.
* \param server Server.
* \param old_zone Already loaded zone (can be NULL).
*
* \return Error code, KNOT_EOK if successful.
*/
static zone_t *create_zone(conf_zone_t *zone_conf, server_t *server, zone_t *old_zone)
{
assert(zone_conf);
assert(server);
if (old_zone) {
return create_zone_reload(zone_conf, server, old_zone);
} else {
return create_zone_new(zone_conf, server);
}
}
/*!
* \brief Create new zone database.
*
......@@ -304,6 +366,9 @@ int zonedb_reload(const conf_t *conf, struct server_t *server)
/* Wait for readers to finish reading old zone database. */
synchronize_rcu();
/* Sweep the timer database. */
sweep_timer_db((conf_t *)conf, db_new);
/*
* Remove all zones present in the new DB from the old DB.
......
......@@ -44,7 +44,7 @@ static char *str_key_rand(size_t len, mm_ctx_t *pool)
#define ASORT_PREFIX(X) str_key_##X
#define ASORT_KEY_TYPE char*
#define ASORT_LT(x, y) (strcmp((x), (y)) < 0)
#include "common/array-sort.h"
#include "common-knot/array-sort.h"
static int namedb_test_set(unsigned nkeys, char **keys, char *dbid,
struct namedb_api *api, mm_ctx_t *pool)
......
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