\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
**-l**, **--limit** *limit*
Limits the number of displayed changes.
+**-s**, **--serial** *soa*
+ Start at specific SOA serial.
+
**-d**, **--debug**
Debug mode brief output.
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)
{
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;
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;
}
*/
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.
*
"\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"
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)
}
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) {
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) {
.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' },
};
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) {
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;
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");