From: Libor Peltan Date: Wed, 14 Oct 2020 10:06:16 +0000 (+0200) Subject: kjournalprint: start at specific SOA serial (like IXFR) X-Git-Tag: v3.1.0~284^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4e51dcfd89ddd446e14713a8db02ec4e5f8c2f3d;p=thirdparty%2Fknot-dns.git kjournalprint: start at specific SOA serial (like IXFR) --- diff --git a/doc/man/kjournalprint.8in b/doc/man/kjournalprint.8in index 4f7917d467..b4cd172a93 100644 --- a/doc/man/kjournalprint.8in +++ b/doc/man/kjournalprint.8in @@ -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 diff --git a/doc/man_kjournalprint.rst b/doc/man_kjournalprint.rst index 2f621b9f8e..709e72c9bb 100644 --- a/doc/man_kjournalprint.rst +++ b/doc/man_kjournalprint.rst @@ -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. diff --git a/src/knot/journal/journal_read.c b/src/knot/journal/journal_read.c index 1240acc6d6..14a2cfe80e 100644 --- a/src/knot/journal/journal_read.c +++ b/src/knot/journal/journal_read.c @@ -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; } diff --git a/src/knot/journal/journal_read.h b/src/knot/journal/journal_read.h index 5659ca0b5a..92cad9f801 100644 --- a/src/knot/journal/journal_read.h +++ b/src/knot/journal/journal_read.h @@ -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. * diff --git a/src/utils/kjournalprint/main.c b/src/utils/kjournalprint/main.c index ae1f8727e4..ff00e18f89 100644 --- a/src/utils/kjournalprint/main.c +++ b/src/utils/kjournalprint/main.c @@ -37,6 +37,7 @@ static void print_help(void) "\n" "Parameters:\n" " -l, --limit Read only newest changes.\n" + " -s, --serial 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 ( 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, ¶ms.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, ¶ms.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");