if (dnssec_ctx->policy->ds_push && node_rrtype_exists(ch.add->apex, KNOT_RRTYPE_CDS)) {
// there is indeed a change to CDS
update->zone->timers->next_ds_push = time(NULL) + dnssec_ctx->policy->propagation_delay;
+ update->zone->timers->flags |= TIMERS_MODIFIED;
zone_events_schedule_at(update->zone, ZONE_EVENT_DS_PUSH, update->zone->timers->next_ds_push);
}
if (refresh->plan_ds_check) {
zone->timers->next_ds_check = now;
+ zone->timers->flags |= TIMERS_MODIFIED;
}
unsigned jitter = dnskey_sync_jitter(conf, zone);
conf->cache.srv_tcp_remote_io_timeout);
zone->timers->next_ds_check = 0;
+ zone->timers->flags |= TIMERS_MODIFIED;
+
switch (ret) {
case KNOT_NO_READY_KEY:
break;
zone_events_schedule_at(zone, ZONE_EVENT_DS_PUSH, next_push);
zone->timers->next_ds_push = next_push;
}
+ zone->timers->flags |= TIMERS_MODIFIED;
conf_mix_iter_next(&iter);
}
requestor.layer.flags,
"%sserial %u", log_retry, knot_soa_serial(soa->rrs.rdata));
zone->timers->last_notified_serial = knot_soa_serial(soa->rrs.rdata);
- zone->timers->flags |= LAST_NOTIFIED_SERIAL_VALID;
+ zone->timers->flags |= LAST_NOTIFIED_SERIAL_VALID | TIMERS_MODIFIED;
} else if (knot_pkt_ext_rcode(req->resp) == 0) {
NOTIFY_OUT_LOG(LOG_WARNING, zone->name, slave,
requestor.layer.flags,
limit_timer(conf, zone->name, &soa_refresh, "refresh",
C_REFRESH_MIN_INTERVAL, C_REFRESH_MAX_INTERVAL);
zone->timers->next_refresh = now + soa_refresh;
- zone->timers->flags |= LAST_REFRESH_OK;
+ zone->timers->flags |= LAST_REFRESH_OK | TIMERS_MODIFIED;
if (zone->is_catalog_flag) {
// It's already zero in most cases.
// Starting countdown for master transition.
if (data->zone->timers->master_pin_hit == 0) {
data->zone->timers->master_pin_hit = now;
+ data->zone->timers->flags |= TIMERS_MODIFIED;
zone_events_schedule_at(data->zone, ZONE_EVENT_REFRESH, now + data->fallback->pin_tol);
// Switch to a new master.
} else if (data->zone->timers->master_pin_hit + data->fallback->pin_tol <= now) {
time_t now = time(NULL);
zone->timers->next_refresh = now + next;
zone->timers->flags &= ~LAST_REFRESH_OK;
+ zone->timers->flags |= TIMERS_MODIFIED;
char time_str[64] = { 0 };
struct tm time_gm = { 0 };
zone_timers_sanitize(conf, zone);
zone->zonefile.bootstrap_cnt = 0;
} else {
+ zone->timers->flags |= TIMERS_MODIFIED; // otherwise the write is skipped!
ret = zone_timers_write(&ctx->bck_timer_db, zone->name, zone->timers);
}
if (ret != KNOT_EOK) {
}
static void txn_write_timers(knot_lmdb_txn_t *txn, const knot_dname_t *zone,
- const zone_timers_t *timers)
+ zone_timers_t *timers)
{
+ if (!(timers->flags & TIMERS_MODIFIED)) { // TODO move this conditional to txn_zone_write, as it is also in zone_timers_write. Here temporarily to avoid git conflicts.
+ return;
+ }
const char *format = (timers->last_master.sin6_family == AF_INET ||
timers->last_master.sin6_family == AF_INET6) ?
"TTTTTTTTTTBD" :
TIMER_LAST_MASTER, &timers->last_master, sizeof(timers->last_master));
knot_lmdb_insert(txn, &k, &v);
free(v.mv_data);
+
+ if (txn->ret == KNOT_EOK) {
+ timers->flags &= ~TIMERS_MODIFIED;
+ }
}
}
int zone_timers_write(knot_lmdb_db_t *db, const knot_dname_t *zone,
- const zone_timers_t *timers)
+ zone_timers_t *timers)
{
int ret = knot_lmdb_open(db);
- if (ret != KNOT_EOK) {
+ if (ret != KNOT_EOK || !(timers->flags & TIMERS_MODIFIED)) {
return ret;
}
knot_lmdb_txn_t txn = { 0 };
#include "libknot/dname.h"
#include "knot/journal/knot_lmdb.h"
+#define TIMERS_MODIFIED (1 << 0)
#define LAST_SIGNED_SERIAL_FOUND (1 << 1)
#define LAST_SIGNED_SERIAL_VALID (1 << 2)
#define LAST_NOTIFIED_SERIAL_VALID (1 << 3)
* \return KNOT_E*
*/
int zone_timers_write(knot_lmdb_db_t *db, const knot_dname_t *zone,
- const zone_timers_t *timers);
+ zone_timers_t *timers);
/*!
* \brief Write timers for all zones.
flush_journal_replan:
/* Plan next journal flush after proper period. */
zone->timers->last_flush = time(NULL);
+ zone->timers->flags |= TIMERS_MODIFIED;
if (sync_timeout > 0) {
time_t next_flush = zone->timers->last_flush + sync_timeout;
zone_events_schedule_at(zone, ZONE_EVENT_FLUSH, (time_t)0,
time_t member = (zone->catalog_gen != NULL ? zone->timers->catalog_member : 0);
memset(zone->timers, 0, sizeof(*zone->timers));
zone->timers->catalog_member = member;
+ zone->timers->flags |= TIMERS_MODIFIED;
if (member) {
ret = zone_timers_write(&zone->server->timerdb, zone->name,
zone->timers->next_expire = time(NULL);
zone->timers->next_refresh = zone->timers->next_expire;
+ zone->timers->flags |= TIMERS_MODIFIED;
replan_from_timers(conf, zone);
}
memcpy(&zone->timers->last_master, addr, sizeof(zone->timers->last_master));
}
zone->timers->master_pin_hit = 0;
+ zone->timers->flags |= TIMERS_MODIFIED;
}
static void set_flag(zone_t *zone, zone_flag_t flag, bool remove)
assert(zone);
time_t now = time(NULL);
+ zone_timers_t prev = *zone->timers;
// assume now if we don't know when we flushed
time_set_default(&zone->timers->last_flush, now);
zone->timers->flags &= ~LAST_REFRESH_OK;
zone->timers->next_expire = 0;
}
+
+ if (memcmp(&prev, zone->timers, sizeof(prev)) != 0) {
+ zone->timers->flags |= TIMERS_MODIFIED;
+ }
}
int zone_timers_begin(zone_t *zone)
{
bool extra_txn = (zone->control_update != NULL && zone->timers == zone->timers_static && zone_timers_begin(zone) == KNOT_EOK); // zone_update_commit() is not within a zone event in case of control_update
zone->timers->last_signed_serial = serial;
- zone->timers->flags |= LAST_SIGNED_SERIAL_FOUND | LAST_SIGNED_SERIAL_VALID;
+ zone->timers->flags |= LAST_SIGNED_SERIAL_FOUND | LAST_SIGNED_SERIAL_VALID | TIMERS_MODIFIED;
if (extra_txn) {
zone_timers_commit(zone);
}
zone->catalog_gen = knot_dname_copy(conf_dname(&catz), NULL);
if (zone->timers->catalog_member == 0) {
zone->timers->catalog_member = time(NULL);
+ zone->timers->flags |= TIMERS_MODIFIED;
ret = zone_timers_write(&zone->server->timerdb, zone->name,
zone->timers);
}
zone_timers_begin(zone);
zone->timers->next_expire = time(NULL);
zone->timers->next_refresh = zone->timers->next_expire;
+ zone->timers->flags |= TIMERS_MODIFIED;
zone_timers_commit(zone);
}
return zone_switch_contents(zone, NULL);
#include "libknot/error.h"
static const zone_timers_t MOCK_TIMERS = {
- .flags = LAST_SIGNED_SERIAL_FOUND | LAST_SIGNED_SERIAL_VALID,
+ .flags = LAST_SIGNED_SERIAL_FOUND | LAST_SIGNED_SERIAL_VALID | TIMERS_MODIFIED,
.last_flush = 1474559960,
.next_refresh = 1474559961,
.last_notified_serial = 123456,
}
const knot_dname_t *zone = (uint8_t *)"\x7""example""\x3""com";
- struct zone_timers timers = MOCK_TIMERS;
+ struct zone_timers timers = MOCK_TIMERS, timers2 = { 0 };
// Create database
knot_lmdb_db_t _db = { 0 }, *db = &_db;
is_int(KNOT_EOK, ret, "zone_timers_write()");
// Read timers
- memset(&timers, 0, sizeof(timers));
- ret = zone_timers_read(db, zone, &timers);
+ ret = zone_timers_read(db, zone, &timers2);
ok(ret == KNOT_EOK, "zone_timers_read()");
- ok(timers_eq(&timers, &MOCK_TIMERS), "inconsistent timers");
+ ok(timers_eq(&timers2, &timers), "inconsistent timers");
// Sweep none
ret = zone_timers_sweep(db, keep_all, NULL);
is_int(KNOT_EOK, ret, "zone_timers_sweep() none");
- ret = zone_timers_read(db, zone, &timers);
+ ret = zone_timers_read(db, zone, &timers2);
is_int(KNOT_EOK, ret, "zone_timers_read()");
// Sweep all
ret = zone_timers_sweep(db, remove_all, NULL);
is_int(KNOT_EOK, ret, "zone_timers_sweep() all");
- ret = zone_timers_read(db, zone, &timers);
+ ret = zone_timers_read(db, zone, &timers2);
is_int(KNOT_ENOENT, ret, "zone_timers_read() nonexistent");
// Clean up.