]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
kjournalprint: start at specific SOA serial (like IXFR)
authorLibor Peltan <libor.peltan@nic.cz>
Wed, 14 Oct 2020 10:06:16 +0000 (12:06 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Sat, 12 Dec 2020 20:38:17 +0000 (21:38 +0100)
doc/man/kjournalprint.8in
doc/man_kjournalprint.rst
src/knot/journal/journal_read.c
src/knot/journal/journal_read.h
src/utils/kjournalprint/main.c

index 4f7917d4676ee3b751ac1f26e69623a68cedf89b..b4cd172a93f361eb6638501646834ee85376a9f5 100644 (file)
@@ -43,6 +43,9 @@ changes are colored for terminal.
 \fB\-l\fP, \fB\-\-limit\fP \fIlimit\fP
 Limits the number of displayed changes.
 .TP
+\fB\-s\fP, \fB\-\-serial\fP \fIsoa\fP
+Start at specific SOA serial.
+.TP
 \fB\-d\fP, \fB\-\-debug\fP
 Debug mode brief output.
 .TP
index 2f621b9f8ef84ed05d5d767d1b8a6ad1898486fe..709e72c9bbbbdf61f0264c3f439891c58dca61f3 100644 (file)
@@ -20,6 +20,9 @@ Options
 **-l**, **--limit** *limit*
   Limits the number of displayed changes.
 
+**-s**, **--serial** *soa*
+  Start at specific SOA serial.
+
 **-d**, **--debug**
   Debug mode brief output.
 
index 1240acc6d605af19e1cb55dc9d68891b5f7f97ea..14a2cfe80ef3586396f2297c678582a1ed023ae3 100644 (file)
@@ -253,6 +253,36 @@ static int just_load_md(zone_journal_t j, journal_metadata_t *md, bool *has_zij)
        return txn.ret;
 }
 
+int journal_walk_from(zone_journal_t j, uint32_t from,
+                      journal_walk_cb_t cb, void *ctx)
+{
+       bool at_least_one = false;
+       journal_metadata_t md = { 0 };
+       journal_read_t *read = NULL;
+       changeset_t ch;
+
+       int ret = just_load_md(j, &md, NULL);
+       if (ret != KNOT_EOK) {
+               return ret;
+       }
+
+       if ((md.flags & JOURNAL_SERIAL_TO_VALID) && from != md.serial_to &&
+           ret == KNOT_EOK) {
+               ret = journal_read_begin(j, false, from, &read);
+               while (ret == KNOT_EOK && journal_read_changeset(read, &ch)) {
+                       ret = cb(false, &ch, ctx);
+                       at_least_one = true;
+                       journal_read_clear_changeset(&ch);
+               }
+               ret = journal_read_get_error(read, ret);
+               journal_read_end(read);
+       }
+       if (!at_least_one && ret == KNOT_EOK) {
+               ret = cb(false, NULL, ctx);
+       }
+       return ret;
+}
+
 // beware, this function does not operate in single txn!
 int journal_walk(zone_journal_t j, journal_walk_cb_t cb, void *ctx)
 {
@@ -271,7 +301,7 @@ int journal_walk(zone_journal_t j, journal_walk_cb_t cb, void *ctx)
        journal_metadata_t md = { 0 };
        journal_read_t *read = NULL;
        changeset_t ch;
-       bool at_least_one = false, zone_in_j = false;
+       bool zone_in_j = false;
        ret = just_load_md(j, &md, &zone_in_j);
        if (ret != KNOT_EOK) {
                return ret;
@@ -293,19 +323,8 @@ read_one_special:
                ret = cb(true, NULL, ctx);
        }
 
-       if ((md.flags & JOURNAL_SERIAL_TO_VALID) && md.first_serial != md.serial_to &&
-           ret == KNOT_EOK) {
-               ret = journal_read_begin(j, false, md.first_serial, &read);
-               while (ret == KNOT_EOK && journal_read_changeset(read, &ch)) {
-                       ret = cb(false, &ch, ctx);
-                       at_least_one = true;
-                       journal_read_clear_changeset(&ch);
-               }
-               ret = journal_read_get_error(read, ret);
-               journal_read_end(read);
-       }
-       if (!at_least_one && ret == KNOT_EOK) {
-               ret = cb(false, NULL, ctx);
+       if (ret == KNOT_EOK) {
+               ret = journal_walk_from(j, md.first_serial, cb, ctx);
        }
        return ret;
 }
index 5659ca0b5aab4fcb7d01fed47a62bca7254b36cf..92cad9f801a479116c7cf34826a611062d4d67da 100644 (file)
@@ -107,6 +107,26 @@ int journal_read_get_error(const journal_read_t *ctx, int another_error);
  */
 void journal_read_end(journal_read_t *ctx);
 
+/*!
+ * \brief Call a function for each changeset in journal.
+ *
+ * This is a variant of journal_walk() see below.
+ * The difference is that iteration starts at specified serial.
+ * Similarly to how IXFR works.
+ * The callback is called for each found changeset, or just once
+ * with ch=NULL if none is found.
+ *
+ * \param j      Zone journal to be read.
+ * \param from   SOA serial to start at.
+ * \param cb     Callback to be called for each changeset (or its non-existence).
+ * \param ctx    Arbitrary context to be passed to the callback.
+ *
+ * \return An error code from either journal operations or from the callback.
+ * \retval KNOT_ENOENT if the journal is not empty, but the requested serial not present.
+ */
+int journal_walk_from(zone_journal_t j, uint32_t from,
+                      journal_walk_cb_t cb, void *ctx);
+
 /*!
  * \brief Call a function for each changeset stored in journal.
  *
index ae1f8727e48b7a583a5404e7ff167f7e5c3b8a6a..ff00e18f8961fd23e4a6d72ce5d4c03fb5e9fa35 100644 (file)
@@ -37,6 +37,7 @@ static void print_help(void)
               "\n"
               "Parameters:\n"
               " -l, --limit <num>  Read only <num> newest changes.\n"
+              " -s, --serial <soa> Start with specific SOA serial.\n"
               " -n, --no-color     Get output without terminal coloring.\n"
               " -z, --zone-list    Instead of reading jurnal, display the list\n"
               "                    of zones in the DB (<zone_name> not needed).\n"
@@ -53,6 +54,8 @@ typedef struct {
        bool check;
        int limit;
        int counter;
+       uint32_t serial;
+       bool from_serial;
 } print_params_t;
 
 static void print_changeset(const changeset_t *chs, print_params_t *params)
@@ -194,7 +197,11 @@ int print_journal(char *path, knot_dname_t *name, print_params_t *params)
        }
 
        if (params->limit >= 0 && ret == KNOT_EOK) {
-               ret = journal_walk(j, count_changeset_cb, params);
+               if (params->from_serial) {
+                       ret = journal_walk_from(j, params->serial, count_changeset_cb, params);
+               } else {
+                       ret = journal_walk(j, count_changeset_cb, params);
+               }
        }
        if (ret == KNOT_EOK) {
                if (params->limit < 0 || params->counter <= params->limit) {
@@ -203,7 +210,11 @@ int print_journal(char *path, knot_dname_t *name, print_params_t *params)
                        params->limit = params->counter - params->limit;
                }
                params->counter = 0;
-               ret = journal_walk(j, print_changeset_cb, params);
+               if (params->from_serial) {
+                       ret = journal_walk_from(j, params->serial, print_changeset_cb, params);
+               } else {
+                       ret = journal_walk(j, print_changeset_cb, params);
+               }
        }
 
        if (params->debug && ret == KNOT_EOK) {
@@ -284,10 +295,12 @@ int main(int argc, char *argv[])
                .color = true,
                .check = false,
                .limit = -1,
+               .from_serial = false,
        };
 
        struct option opts[] = {
                { "limit",     required_argument, NULL, 'l' },
+               { "serial",    required_argument, NULL, 's' },
                { "no-color",  no_argument,       NULL, 'n' },
                { "zone-list", no_argument,       NULL, 'z' },
                { "check",     no_argument,       NULL, 'c' },
@@ -298,7 +311,7 @@ int main(int argc, char *argv[])
        };
 
        int opt = 0;
-       while ((opt = getopt_long(argc, argv, "l:nzcdhV", opts, NULL)) != -1) {
+       while ((opt = getopt_long(argc, argv, "l:s:nzcdhV", opts, NULL)) != -1) {
                switch (opt) {
                case 'l':
                        if (str_to_int(optarg, &params.limit, 0, INT_MAX) != KNOT_EOK) {
@@ -306,6 +319,13 @@ int main(int argc, char *argv[])
                                return EXIT_FAILURE;
                        }
                        break;
+               case 's':
+                       if (str_to_u32(optarg, &params.serial) != KNOT_EOK) {
+                               print_help();
+                               return EXIT_FAILURE;
+                       }
+                       params.from_serial = true;
+                       break;
                case 'n':
                        params.color = false;
                        break;
@@ -381,7 +401,11 @@ int main(int argc, char *argv[])
 
        switch (ret) {
        case KNOT_ENOENT:
-               printf("The journal is empty\n");
+               if (params.from_serial) {
+                       printf("The journal is empty or the serial not present\n");
+               } else {
+                       printf("The journal is empty\n");
+               }
                break;
        case KNOT_EFILE:
                fprintf(stderr, "The specified journal DB is invalid\n");