]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
load the journal file if it already exists
authorEvan Hunt <each@isc.org>
Thu, 6 Feb 2025 07:08:27 +0000 (23:08 -0800)
committerEvan Hunt <each@isc.org>
Sat, 14 Jun 2025 04:20:13 +0000 (21:20 -0700)
apply the existing journal file, if any, to the old version of the
database before diffing it against the new version. then, append
the diff to the end of the journal. this allows easy creation of
a journal file with multiple deltas, by running named-makejournal
successively.

bin/tools/named-makejournal.c
bin/tools/named-makejournal.rst

index d67c970be90bac8fc6d72d9fb5e3f72023de7a7c..2c974dc0785b0f84e07e9713c02ba35997562cc2 100644 (file)
@@ -22,6 +22,7 @@
 #include <isc/log.h>
 #include <isc/mem.h>
 #include <isc/result.h>
+#include <isc/serial.h>
 #include <isc/util.h>
 
 #include <dns/db.h>
@@ -67,6 +68,48 @@ loadzone(dns_db_t **db, const char *origin, const char *filename) {
        return result;
 }
 
+static isc_result_t
+loadjournal(dns_db_t *db, const char *file) {
+       dns_journal_t *jnl = NULL;
+       isc_result_t result;
+
+       result = dns_journal_open(mctx, file, DNS_JOURNAL_READ, &jnl);
+       if (result == ISC_R_NOTFOUND) {
+               return ISC_R_SUCCESS;
+       } else if (result != ISC_R_SUCCESS) {
+               fprintf(stderr, "Error: unable to open journal %s: %s\n", file,
+                       isc_result_totext(result));
+               return result;
+       }
+
+       if (dns_journal_empty(jnl)) {
+               dns_journal_destroy(&jnl);
+               return ISC_R_SUCCESS;
+       }
+
+       result = dns_journal_rollforward(jnl, db, 0);
+       switch (result) {
+       case ISC_R_SUCCESS:
+               break;
+       case DNS_R_UPTODATE:
+               result = ISC_R_SUCCESS;
+               break;
+
+       case ISC_R_NOTFOUND:
+       case ISC_R_RANGE:
+               fprintf(stderr, "Error: journal %s out of sync with zone",
+                       file);
+               break;
+
+       default:
+               fprintf(stderr, "Error: journal %s: %s\n", file,
+                       isc_result_totext(result));
+       }
+
+       dns_journal_destroy(&jnl);
+       return result;
+}
+
 int
 main(int argc, char **argv) {
        isc_result_t result;
@@ -75,6 +118,7 @@ main(int argc, char **argv) {
        const char *journal = NULL;
        dns_db_t *olddb = NULL, *newdb = NULL;
        isc_logconfig_t *logconfig = NULL;
+       uint32_t s1, s2, s3;
        int ch;
 
        isc_commandline_init(argc, argv);
@@ -130,22 +174,35 @@ main(int argc, char **argv) {
                goto cleanup;
        }
 
-       uint32_t s1, s2;
        result = dns_db_getsoaserial(olddb, NULL, &s1);
        if (result != ISC_R_SUCCESS) {
-               fprintf(stderr, "Error: no SOA found in %s\n", file1);
+               fprintf(stderr, "Error: %s: SOA lookup failed\n", file1);
                goto cleanup;
        }
-       result = dns_db_getsoaserial(newdb, NULL, &s2);
+
+       result = loadjournal(olddb, journal);
        if (result != ISC_R_SUCCESS) {
-               fprintf(stderr, "Error: no SOA found in %s\n", file2);
                goto cleanup;
        }
-       if (s1 == s2) {
+
+       result = dns_db_getsoaserial(olddb, NULL, &s2);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+       result = dns_db_getsoaserial(newdb, NULL, &s3);
+       if (result != ISC_R_SUCCESS) {
+               fprintf(stderr, "Error: %s: SOA lookup failed\n", file2);
+               goto cleanup;
+       }
+
+       if (isc_serial_eq(s1, s3)) {
                fprintf(stderr,
                        "Error: SOA serial (%u) unchanged between files\n", s1);
                result = ISC_R_FAILURE;
                goto cleanup;
+       } else if (isc_serial_eq(s2, s3)) {
+               fprintf(stderr, "Journal %s already has serial %u\n", journal,
+                       s3);
+               goto cleanup;
        }
 
        result = dns_db_diff(mctx, newdb, NULL, olddb, NULL, journal);
@@ -166,5 +223,5 @@ cleanup:
                isc_mem_detach(&mctx);
        }
 
-       return result != ISC_R_SUCCESS ? 1 : 0;
+       return (result != ISC_R_SUCCESS) ? 1 : 0;
 }
index 1a39a4d8f21f8bcaf0b95db62a1dbd2c0bbf59db..1724d0bfb48238bb34e4ec3a18cf89682c5b24bd 100644 (file)
@@ -40,10 +40,12 @@ If the optional argument ``journal`` is not specified, then the journal
 file name will be formed by appending the extension ``.jnl`` to the
 zone file name specified as ``oldfile``.
 
-If the journal file already exists, a new transaction will be appended
-onto the end of it. (Note, however, that the most recent serial number in
-the existing journal file must match the serial number in ``oldfile``.
-This will be corrected later.)
+If the journal file already exists, then it will be applied to ``oldfile``
+immediately after loading. The difference between the resulting zone and
+the one in ``newfile`` will then be appended onto the end of the journal.
+This allows creation of journal files with multiple transactions, by
+running ``named-makejournal`` multiple times, updating ``newfile`` each
+time.
 
 Options
 ~~~~~~~