From: Libor Peltan Date: Fri, 14 Nov 2025 08:02:51 +0000 (+0100) Subject: zone/timers: only write to timerDB if modified X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9cff75c48b0a9c9fa52c62384f1bc097db09de10;p=thirdparty%2Fknot-dns.git zone/timers: only write to timerDB if modified --- diff --git a/src/knot/dnssec/zone-sign.c b/src/knot/dnssec/zone-sign.c index 856c089cf6..7308ec4f9d 100644 --- a/src/knot/dnssec/zone-sign.c +++ b/src/knot/dnssec/zone-sign.c @@ -887,6 +887,7 @@ int knot_zone_sign_update_dnskeys(zone_update_t *update, 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); } diff --git a/src/knot/events/handlers/dnssec.c b/src/knot/events/handlers/dnssec.c index 0150bdd3b6..d0367a76a6 100644 --- a/src/knot/events/handlers/dnssec.c +++ b/src/knot/events/handlers/dnssec.c @@ -41,6 +41,7 @@ void event_dnssec_reschedule(conf_t *conf, zone_t *zone, if (refresh->plan_ds_check) { zone->timers->next_ds_check = now; + zone->timers->flags |= TIMERS_MODIFIED; } unsigned jitter = dnskey_sync_jitter(conf, zone); diff --git a/src/knot/events/handlers/ds_check.c b/src/knot/events/handlers/ds_check.c index f4f8cae2b3..eaf44f5b9e 100644 --- a/src/knot/events/handlers/ds_check.c +++ b/src/knot/events/handlers/ds_check.c @@ -25,6 +25,8 @@ int event_ds_check(conf_t *conf, zone_t *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; diff --git a/src/knot/events/handlers/ds_push.c b/src/knot/events/handlers/ds_push.c index deb6392050..1f59d2fddc 100644 --- a/src/knot/events/handlers/ds_push.c +++ b/src/knot/events/handlers/ds_push.c @@ -249,6 +249,7 @@ int event_ds_push(conf_t *conf, zone_t *zone) 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); } diff --git a/src/knot/events/handlers/notify.c b/src/knot/events/handlers/notify.c index 1cb788cb53..7728dc23a0 100644 --- a/src/knot/events/handlers/notify.c +++ b/src/knot/events/handlers/notify.c @@ -112,7 +112,7 @@ static int send_notify(conf_t *conf, zone_t *zone, const knot_rrset_t *soa, 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, diff --git a/src/knot/events/handlers/refresh.c b/src/knot/events/handlers/refresh.c index fc5f2fbf19..46f7834564 100644 --- a/src/knot/events/handlers/refresh.c +++ b/src/knot/events/handlers/refresh.c @@ -219,7 +219,7 @@ static void finalize_timers_base(struct refresh_data *data, bool also_expire) 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. @@ -1083,6 +1083,7 @@ static bool wait4pinned_master(struct refresh_data *data) // 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) { @@ -1507,6 +1508,7 @@ int event_refresh(conf_t *conf, zone_t *zone) 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 }; diff --git a/src/knot/zone/backup.c b/src/knot/zone/backup.c index 8ffe1441cb..73ec28c50f 100644 --- a/src/knot/zone/backup.c +++ b/src/knot/zone/backup.c @@ -498,6 +498,7 @@ int zone_backup(conf_t *conf, zone_t *zone) 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) { diff --git a/src/knot/zone/timers.c b/src/knot/zone/timers.c index 4e591ee968..e920f11d12 100644 --- a/src/knot/zone/timers.c +++ b/src/knot/zone/timers.c @@ -117,8 +117,11 @@ static int deserialize_timers(zone_timers_t *timers_ptr, } 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" : @@ -139,6 +142,10 @@ static void txn_write_timers(knot_lmdb_txn_t *txn, const knot_dname_t *zone, 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; + } } @@ -186,10 +193,10 @@ int zone_timers_read(knot_lmdb_db_t *db, const knot_dname_t *zone, } 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 }; diff --git a/src/knot/zone/timers.h b/src/knot/zone/timers.h index 17bf72e306..e992c9fde9 100644 --- a/src/knot/zone/timers.h +++ b/src/knot/zone/timers.h @@ -12,6 +12,7 @@ #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) @@ -64,7 +65,7 @@ int zone_timers_read(knot_lmdb_db_t *db, const knot_dname_t *zone, * \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. diff --git a/src/knot/zone/zone.c b/src/knot/zone/zone.c index 3312483af4..01e03f83d5 100644 --- a/src/knot/zone/zone.c +++ b/src/knot/zone/zone.c @@ -141,6 +141,7 @@ static int flush_journal(conf_t *conf, zone_t *zone, bool allow_empty_zone, bool 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, @@ -309,6 +310,7 @@ int selective_zone_purge(conf_t *conf, zone_t *zone, purge_flag_t params) 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, @@ -390,6 +392,7 @@ void zone_perform_expire(conf_t *conf, zone_t *zone) zone->timers->next_expire = time(NULL); zone->timers->next_refresh = zone->timers->next_expire; + zone->timers->flags |= TIMERS_MODIFIED; replan_from_timers(conf, zone); } @@ -599,6 +602,7 @@ void zone_set_last_master(zone_t *zone, const struct sockaddr_storage *addr) 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) @@ -682,6 +686,7 @@ void zone_timers_sanitize(conf_t *conf, zone_t *zone) 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); @@ -698,6 +703,10 @@ void zone_timers_sanitize(conf_t *conf, zone_t *zone) 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) @@ -966,7 +975,7 @@ void zone_set_lastsigned_serial(zone_t *zone, uint32_t serial) { 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); } diff --git a/src/knot/zone/zonedb-load.c b/src/knot/zone/zonedb-load.c index 91d137b9ff..d00f76cb35 100644 --- a/src/knot/zone/zonedb-load.c +++ b/src/knot/zone/zonedb-load.c @@ -146,6 +146,7 @@ static zone_t *create_zone_new(conf_t *conf, const knot_dname_t *name, 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); } @@ -231,6 +232,7 @@ static zone_contents_t *zone_expire(zone_t *zone, bool zonedb_cow) 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); diff --git a/tests/knot/test_zone_timers.c b/tests/knot/test_zone_timers.c index 6fcddc18b2..e0d93f4ce0 100644 --- a/tests/knot/test_zone_timers.c +++ b/tests/knot/test_zone_timers.c @@ -15,7 +15,7 @@ #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, @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) } 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; @@ -82,21 +82,20 @@ int main(int argc, char *argv[]) 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.