src/knot/events/handlers/freeze_thaw.c
src/knot/events/handlers/load.c
src/knot/events/handlers/notify.c
+src/knot/events/handlers/purge.c
src/knot/events/handlers/refresh.c
src/knot/events/handlers/update.c
src/knot/events/handlers/validate.c
knot/events/handlers/freeze_thaw.c \
knot/events/handlers/load.c \
knot/events/handlers/notify.c \
+ knot/events/handlers/purge.c \
knot/events/handlers/refresh.c \
knot/events/handlers/update.c \
knot/events/handlers/validate.c \
static int zone_purge(zone_t *zone, ctl_args_t *args)
{
- if (MATCH_OR_FILTER(args, CTL_FILTER_PURGE_EXPIRE)) {
- // Abort possible editing transaction.
- int ret = zone_txn_abort(zone, args);
- if (ret != KNOT_EOK && ret != KNOT_TXN_ENOTEXISTS) {
- log_zone_error(zone->name,
- "failed to abort pending transaction (%s)",
- knot_strerror(ret));
- return ret;
- }
-
- // Expire the zone.
- // No ret, KNOT_EOK is the only return value from event_expire().
- (void)zone_events_schedule_blocking(zone, ZONE_EVENT_EXPIRE, true);
- }
-
const purge_flag_t params =
MATCH_OR_FILTER(args, CTL_FILTER_PURGE_TIMERS) * PURGE_ZONE_TIMERS |
MATCH_OR_FILTER(args, CTL_FILTER_PURGE_ZONEFILE) * PURGE_ZONE_ZONEFILE |
MATCH_OR_FILTER(args, CTL_FILTER_PURGE_JOURNAL) * PURGE_ZONE_JOURNAL |
MATCH_OR_FILTER(args, CTL_FILTER_PURGE_KASPDB) * PURGE_ZONE_KASPDB |
MATCH_OR_FILTER(args, CTL_FILTER_PURGE_CATALOG) * PURGE_ZONE_CATALOG |
+ MATCH_OR_FILTER(args, CTL_FILTER_PURGE_EXPIRE) * PURGE_ZONE_EXPIRE |
PURGE_ZONE_NOSYNC; // Purge even zonefiles with disabled syncing.
- // Purge the requested zone data.
- return selective_zone_purge(conf(), zone, params);
+ zone_set_flag(zone, (zone_flag_t)params);
+ return schedule_trigger(zone, args, ZONE_EVENT_PURGE, true);
}
int ctl_dump_ctr(stats_dump_params_t *params, stats_dump_ctx_t *ctx)
{ ZONE_EVENT_REFRESH, event_refresh, "refresh" },
{ ZONE_EVENT_UPDATE, event_update, "update" },
{ ZONE_EVENT_EXPIRE, event_expire, "expiration" },
+ { ZONE_EVENT_PURGE, event_purge, "purge" },
{ ZONE_EVENT_FLUSH, event_flush, "flush" },
{ ZONE_EVENT_BACKUP, event_backup, "backup/restore" },
{ ZONE_EVENT_NOTIFY, event_notify, "notify" },
case ZONE_EVENT_LOAD:
case ZONE_EVENT_REFRESH:
case ZONE_EVENT_UPDATE:
+ case ZONE_EVENT_PURGE:
case ZONE_EVENT_FLUSH:
case ZONE_EVENT_DNSSEC:
case ZONE_EVENT_DS_CHECK:
ZONE_EVENT_REFRESH,
ZONE_EVENT_UPDATE,
ZONE_EVENT_EXPIRE,
+ ZONE_EVENT_PURGE,
ZONE_EVENT_FLUSH,
ZONE_EVENT_BACKUP,
ZONE_EVENT_NOTIFY,
int event_update(conf_t *conf, zone_t *zone);
/*! \brief Empties in-memory zone contents. */
int event_expire(conf_t *conf, zone_t *zone);
+/*! \brief Expires the zone and purges metadata based on zone->flags. */
+int event_purge(conf_t *conf, zone_t *zone);
/*! \brief Flushes zone contents into text file. */
int event_flush(conf_t *conf, zone_t *zone);
/*! \brief Backs up zone contents, metadata, keys, etc to a directory. */
* For more information, see <https://www.knot-dns.cz/>
*/
-#include <assert.h>
-#include <urcu.h>
-
-#include "knot/common/log.h"
-#include "knot/conf/conf.h"
-#include "knot/events/handlers.h"
-#include "knot/events/replan.h"
-#include "knot/zone/contents.h"
#include "knot/zone/zone.h"
int event_expire(conf_t *conf, zone_t *zone)
{
- assert(zone);
-
- zone_contents_t *expired = zone_switch_contents(zone, NULL);
- log_zone_info(zone->name, "zone expired");
-
- synchronize_rcu();
-
- pthread_mutex_lock(&zone->cu_lock);
- assert(zone->control_update == NULL || !(zone->control_update->flags & UPDATE_WFEV));
- zone_control_clear(zone);
- pthread_mutex_unlock(&zone->cu_lock);
-
- knot_sem_wait(&zone->cow_lock);
- zone_contents_deep_free(expired);
- knot_sem_post(&zone->cow_lock);
-
- zone->zonefile.exists = false;
-
- zone_set_last_master(zone, NULL);
-
- zone->timers.next_expire = time(NULL);
- zone->timers.next_refresh = zone->timers.next_expire;
- replan_from_timers(conf, zone);
+ zone_perform_expire(conf, zone);
return KNOT_EOK;
}
--- /dev/null
+/* Copyright (C) CZ.NIC, z.s.p.o. and contributors
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * For more information, see <https://www.knot-dns.cz/>
+ */
+
+#include "knot/zone/zone.h"
+
+int event_purge(conf_t *conf, zone_t *zone)
+{
+ purge_flag_t what = (purge_flag_t)zone_get_flag(zone, (zone_flag_t)PURGE_ZONE_FLAGS, true);
+
+ if (what & PURGE_ZONE_EXPIRE) {
+ zone_perform_expire(conf, zone);
+ }
+
+ return selective_zone_purge(conf, zone, what);
+}
const zone_event_type_t types[] = {
ZONE_EVENT_REFRESH,
+ ZONE_EVENT_PURGE,
ZONE_EVENT_FLUSH,
ZONE_EVENT_BACKUP,
ZONE_EVENT_NOTIFY,
return KNOT_EOK;
}
+void zone_perform_expire(conf_t *conf, zone_t *zone)
+{
+ zone_contents_t *expired = zone_switch_contents(zone, NULL);
+ log_zone_info(zone->name, "zone expired");
+
+ synchronize_rcu();
+
+ pthread_mutex_lock(&zone->cu_lock);
+ assert(zone->control_update == NULL || !(zone->control_update->flags & UPDATE_WFEV));
+ zone_control_clear(zone);
+ pthread_mutex_unlock(&zone->cu_lock);
+
+ knot_sem_wait(&zone->cow_lock);
+ zone_contents_deep_free(expired);
+ knot_sem_post(&zone->cow_lock);
+
+ zone->zonefile.exists = false;
+
+ zone_set_last_master(zone, NULL);
+
+ zone->timers.next_expire = time(NULL);
+ zone->timers.next_refresh = zone->timers.next_expire;
+ replan_from_timers(conf, zone);
+}
+
knot_lmdb_db_t *zone_journaldb(const zone_t *zone)
{
return &zone->server->journaldb;
ZONE_USER_FLUSH = 1 << 8, /*!< User-triggered flush. */
ZONE_LAST_SIGN_OK = 1 << 9, /*!< Last full-sign event finished OK. */
ZONE_PREF_MASTER_2X = 1 << 10, /*!< Preferred master has been overwritten at least once. */
+
+ ZONE_FLAG_MAX = 1 << 19, /*!< Maximal usable flag below purge_flag_t. */
+ ZONE_FLAG_TYPESIZE = 1 << 30, /*!< Enforces the compiler to use 32-bit variable for this enum. */
} zone_flag_t;
/*!
/*!
* \brief Zone purging parameter flags.
+ *
+ * \warning Note they are and must be mutually exclusive with zone_flag_t so that they can be stored in zone->flags.
*/
typedef enum {
- PURGE_ZONE_BEST = 1 << 0, /*!< Best effort -- continue on failures. */
- PURGE_ZONE_LOG = 1 << 1, /*!< Log a purged zone even if requested less. */
- PURGE_ZONE_NOSYNC = 1 << 2, /*!< Remove even zone files with disabled syncing. */
- PURGE_ZONE_TIMERS = 1 << 3, /*!< Purge the zone timers. */
- PURGE_ZONE_ZONEFILE = 1 << 4, /*!< Purge the zone file. */
- PURGE_ZONE_JOURNAL = 1 << 5, /*!< Purge the zone journal. */
- PURGE_ZONE_KASPDB = 1 << 6, /*!< Purge KASP DB. */
- PURGE_ZONE_CATALOG = 1 << 7, /*!< Purge the catalog. */
+ PURGE_ZONE_BEST = 1 << 20, /*!< Best effort -- continue on failures. */
+ PURGE_ZONE_LOG = 1 << 21, /*!< Log a purged zone even if requested less. */
+ PURGE_ZONE_NOSYNC = 1 << 22, /*!< Remove even zone files with disabled syncing. */
+ PURGE_ZONE_TIMERS = 1 << 23, /*!< Purge the zone timers. */
+ PURGE_ZONE_ZONEFILE = 1 << 24, /*!< Purge the zone file. */
+ PURGE_ZONE_JOURNAL = 1 << 25, /*!< Purge the zone journal. */
+ PURGE_ZONE_KASPDB = 1 << 26, /*!< Purge KASP DB. */
+ PURGE_ZONE_CATALOG = 1 << 27, /*!< Purge the catalog. */
+ PURGE_ZONE_EXPIRE = 1 << 28, /*!< Expire the zone, free contents. */
} purge_flag_t;
/*!< All data. */
/*!< Standard purge (respect C_ZONEFILE_SYNC param). */
#define PURGE_ZONE_ALL (PURGE_ZONE_DATA | PURGE_ZONE_BEST | PURGE_ZONE_LOG)
+/*!< All purge-related flags. */
+#define PURGE_ZONE_FLAGS (PURGE_ZONE_ALL | PURGE_ZONE_NOSYNC | PURGE_ZONE_EXPIRE)
+
/*!
* \brief Structure for holding DNS zone.
*/
*/
int selective_zone_purge(conf_t *conf, zone_t *zone, purge_flag_t params);
+/*!
+ * \brief Expire zone, NULL and free zone->contents, clear CTL txn, expire timers, replan events.
+ */
+void zone_perform_expire(conf_t *conf, zone_t *zone);
+
/*!
* \brief Clears possible control update transaction.
*