From d8e1f51a04d85283c2ea2a244651fa23d74d617e Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Thu, 24 Mar 2022 20:24:00 +0000 Subject: [PATCH] Process the 'version' record of the catalog zone first When processing a new or updated catalog zone, the record datasets from the database are being processed in order. This creates a problem because we need to know the version of the catalog zone schema to process some of the records differently, but we do not know the version until the 'version' record gets processed. Find the 'version' record and process it first, only then iterate over the database to process the rest, making sure not to process the 'version' record twice. (cherry picked from commit 6035980bb1af8a84a40efbd9d7ff98d20beab26b) --- lib/dns/catz.c | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/lib/dns/catz.c b/lib/dns/catz.c index 28fc33be0e..0ec243312c 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -1831,12 +1831,14 @@ dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) { isc_result_t result; isc_region_t r; dns_dbnode_t *node = NULL; + const dns_dbnode_t *vers_node = NULL; dns_dbiterator_t *it = NULL; dns_fixedname_t fixname; dns_name_t *name; dns_rdatasetiter_t *rdsiter = NULL; dns_rdataset_t rdataset; char bname[DNS_NAME_FORMATSIZE]; + bool is_vers_processed = false; uint32_t vers; REQUIRE(DNS_DB_VALID(db)); @@ -1896,16 +1898,38 @@ dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) { name = dns_fixedname_initname(&fixname); /* - * Iterate over database to fill the new zone. + * Take the version record to process first, because the other + * records might be processed differently depending on the version of + * the catalog zone's schema. */ - result = dns_dbiterator_first(it); + result = dns_name_fromstring2(name, "version", &db->origin, 0, NULL); if (result != ISC_R_SUCCESS) { + dns_dbiterator_destroy(&it); + dns_catz_zone_detach(&newzone); + dns_db_closeversion(db, &oldzone->dbversion, false); isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER, ISC_LOG_ERROR, - "catz: failed to get db iterator - %s", + "catz: failed to create name from string - %s", isc_result_totext(result)); + return; + } + result = dns_dbiterator_seek(it, name); + if (result != ISC_R_SUCCESS) { + dns_dbiterator_destroy(&it); + dns_catz_zone_detach(&newzone); + dns_db_closeversion(db, &oldzone->dbversion, false); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_MASTER, ISC_LOG_ERROR, + "catz: zone '%s' has no 'version' record (%s)", + bname, isc_result_totext(result)); + return; } + name = dns_fixedname_initname(&fixname); + + /* + * Iterate over database to fill the new zone. + */ while (result == ISC_R_SUCCESS) { result = dns_dbiterator_current(it, &node, name); if (result != ISC_R_SUCCESS) { @@ -1916,6 +1940,16 @@ dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) { break; } + if (!is_vers_processed) { + /* Keep the version node to skip it later in the loop */ + vers_node = node; + } else if (node == vers_node) { + /* Skip the already processed version node */ + dns_db_detachnode(db, &node); + result = dns_dbiterator_next(it); + continue; + } + result = dns_db_allrdatasets(db, node, oldzone->dbversion, 0, &rdsiter); if (result != ISC_R_SUCCESS) { @@ -1963,7 +1997,13 @@ dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) { dns_rdatasetiter_destroy(&rdsiter); dns_db_detachnode(db, &node); - result = dns_dbiterator_next(it); + + if (!is_vers_processed) { + is_vers_processed = true; + result = dns_dbiterator_first(it); + } else { + result = dns_dbiterator_next(it); + } } dns_dbiterator_destroy(&it);