1 /* $NetBSD: journal.h,v 1.9 2025/01/26 16:25:27 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #pragma once 17 18 /***** 19 ***** Module Info 20 *****/ 21 22 /*! \file dns/journal.h 23 * \brief 24 * Database journaling. 25 */ 26 27 /*** 28 *** Imports 29 ***/ 30 31 #include <inttypes.h> 32 #include <stdbool.h> 33 34 #include <isc/lang.h> 35 #include <isc/magic.h> 36 37 #include <dns/diff.h> 38 #include <dns/name.h> 39 #include <dns/rdata.h> 40 #include <dns/types.h> 41 42 /*** 43 *** Defines. 44 ***/ 45 #define DNS_JOURNALOPT_RESIGN 0x00000001 46 47 #define DNS_JOURNAL_READ 0x00000000 /* false */ 48 #define DNS_JOURNAL_CREATE 0x00000001 /* true */ 49 #define DNS_JOURNAL_WRITE 0x00000002 50 51 #define DNS_JOURNAL_SIZE_MAX INT32_MAX 52 #define DNS_JOURNAL_SIZE_MIN 4096 53 54 /*% Print transaction header data */ 55 #define DNS_JOURNAL_PRINTXHDR 0x0001 56 57 /*% Rewrite whole journal file instead of compacting */ 58 #define DNS_JOURNAL_COMPACTALL 0x0001 59 #define DNS_JOURNAL_VERSION1 0x0002 60 61 /*** 62 *** Types 63 ***/ 64 65 /*% 66 * A dns_journal_t represents an open journal file. This is an opaque type. 67 * 68 * A particular dns_journal_t object may be opened for writing, in which case 69 * it can be used for writing transactions to a journal file, or it can be 70 * opened for reading, in which case it can be used for reading transactions 71 * from (iterating over) a journal file. A single dns_journal_t object may 72 * not be used for both purposes. 73 */ 74 typedef struct dns_journal dns_journal_t; 75 76 /*** 77 *** Functions 78 ***/ 79 80 ISC_LANG_BEGINDECLS 81 82 /**************************************************************************/ 83 84 isc_result_t 85 dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx, 86 dns_diffop_t op, dns_difftuple_t **tp); 87 /*!< brief 88 * Create a diff tuple for the current database SOA. 89 * XXX this probably belongs somewhere else. 90 */ 91 92 /*@{*/ 93 #define DNS_SERIAL_GT(a, b) ((int)(((a) - (b)) & 0xFFFFFFFF) > 0) 94 #define DNS_SERIAL_GE(a, b) ((int)(((a) - (b)) & 0xFFFFFFFF) >= 0) 95 /*!< brief 96 * Compare SOA serial numbers. DNS_SERIAL_GT(a, b) returns true iff 97 * a is "greater than" b where "greater than" is as defined in RFC1982. 98 * DNS_SERIAL_GE(a, b) returns true iff a is "greater than or equal to" b. 99 */ 100 /*@}*/ 101 102 /**************************************************************************/ 103 /* 104 * Journal object creation and destruction. 105 */ 106 107 isc_result_t 108 dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode, 109 dns_journal_t **journalp); 110 /*%< 111 * Open the journal file 'filename' and create a dns_journal_t object for it. 112 * 113 * DNS_JOURNAL_CREATE open the journal for reading and writing and create 114 * the journal if it does not exist. 115 * DNS_JOURNAL_WRITE open the journal for reading and writing. 116 * DNS_JOURNAL_READ open the journal for reading only. 117 */ 118 119 void 120 dns_journal_destroy(dns_journal_t **journalp); 121 /*%< 122 * Destroy a dns_journal_t, closing any open files and freeing its memory. 123 */ 124 125 /**************************************************************************/ 126 /* 127 * Writing transactions to journals. 128 */ 129 130 isc_result_t 131 dns_journal_begin_transaction(dns_journal_t *j); 132 /*%< 133 * Prepare to write a new transaction to the open journal file 'j'. 134 * 135 * Requires: 136 * \li 'j' is open for writing. 137 */ 138 139 isc_result_t 140 dns_journal_writediff(dns_journal_t *j, dns_diff_t *diff); 141 /*%< 142 * Write 'diff' to the current transaction of journal file 'j'. 143 * 144 * Requires: 145 * \li 'j' is open for writing and dns_journal_begin_transaction() 146 * has been called. 147 * 148 *\li 'diff' is a full or partial, correctly ordered IXFR 149 * difference sequence. 150 */ 151 152 isc_result_t 153 dns_journal_commit(dns_journal_t *j); 154 /*%< 155 * Commit the current transaction of journal file 'j'. 156 * 157 * Requires: 158 * \li 'j' is open for writing and dns_journal_begin_transaction() 159 * has been called. 160 * 161 * \li dns_journal_writediff() has been called one or more times 162 * to form a complete, correctly ordered IXFR difference 163 * sequence. 164 */ 165 166 isc_result_t 167 dns_journal_write_transaction(dns_journal_t *j, dns_diff_t *diff); 168 /*% 169 * Write a complete transaction at once to a journal file, 170 * sorting it if necessary, and commit it. Equivalent to calling 171 * dns_diff_sort(), dns_journal_begin_transaction(), 172 * dns_journal_writediff(), and dns_journal_commit(). 173 * 174 * Requires: 175 *\li 'j' is open for writing. 176 * 177 * \li 'diff' contains exactly one SOA deletion, one SOA addition 178 * with a greater serial number, and possibly other changes, 179 * in arbitrary order. 180 */ 181 182 /**************************************************************************/ 183 /* 184 * Reading transactions from journals. 185 */ 186 187 bool 188 dns_journal_empty(dns_journal_t *j); 189 /*< 190 * Find out if a journal is empty. 191 */ 192 193 bool 194 dns_journal_recovered(dns_journal_t *j); 195 /*< 196 * Find out if the journal could be opened using old journal format 197 */ 198 199 uint32_t 200 dns_journal_first_serial(dns_journal_t *j); 201 uint32_t 202 dns_journal_last_serial(dns_journal_t *j); 203 /*%< 204 * Get the first and last addressable serial number in the journal. 205 */ 206 207 isc_result_t 208 dns_journal_iter_init(dns_journal_t *j, uint32_t begin_serial, 209 uint32_t end_serial, size_t *xfrsizep); 210 /*%< 211 * Prepare to iterate over the transactions that will bring the database 212 * from SOA serial number 'begin_serial' to 'end_serial'. 213 * 214 * If 'xfrsizep' is not NULL, then on success it will be set to the 215 * total size of all records in the iteration (excluding headers). This 216 * is meant to be a rough approximation of the size of an incremental 217 * zone transfer, though it does not account for DNS message overhead 218 * or name compression.) 219 * 220 * Returns: 221 *\li ISC_R_SUCCESS 222 *\li ISC_R_RANGE begin_serial is outside the addressable range. 223 *\li ISC_R_NOTFOUND begin_serial is within the range of addressable 224 * serial numbers covered by the journal, but 225 * this particular serial number does not exist. 226 */ 227 228 /*@{*/ 229 isc_result_t 230 dns_journal_first_rr(dns_journal_t *j); 231 isc_result_t 232 dns_journal_next_rr(dns_journal_t *j); 233 /*%< 234 * Position the iterator at the first/next RR in a journal 235 * transaction sequence established using dns_journal_iter_init(). 236 * 237 * Requires: 238 * \li dns_journal_iter_init() has been called. 239 * 240 */ 241 /*@}*/ 242 243 void 244 dns_journal_current_rr(dns_journal_t *j, dns_name_t **name, uint32_t *ttl, 245 dns_rdata_t **rdata); 246 /*%< 247 * Get the name, ttl, and rdata of the current journal RR. 248 * 249 * Requires: 250 * \li The last call to dns_journal_first_rr() or dns_journal_next_rr() 251 * returned ISC_R_SUCCESS. 252 */ 253 254 /**************************************************************************/ 255 /* 256 * Database roll-forward. 257 */ 258 259 isc_result_t 260 dns_journal_rollforward(dns_journal_t *j, dns_db_t *db, unsigned int options); 261 /*%< 262 * Roll forward (play back) the journal file "filename" into the 263 * database "db". This should be called when the server starts 264 * after a shutdown or crash. 265 * 266 * Requires: 267 *\li 'journal' is a valid journal 268 *\li 'db' is a valid database which does not have a version 269 * open for writing. 270 * 271 * Returns: 272 *\li ISC_R_NOTFOUND when current serial in not in journal. 273 *\li ISC_R_RANGE when current serial in not in journals range. 274 *\li DNS_R_UPTODATE when the database was already up to date. 275 *\li ISC_R_SUCCESS journal has been applied successfully to the 276 * database without any issues. 277 * 278 * others 279 */ 280 281 isc_result_t 282 dns_journal_print(isc_mem_t *mctx, uint32_t flags, const char *filename, 283 FILE *file); 284 /* For debugging not general use */ 285 286 isc_result_t 287 dns_db_diff(isc_mem_t *mctx, dns_db_t *dba, dns_dbversion_t *dbvera, 288 dns_db_t *dbb, dns_dbversion_t *dbverb, 289 const char *journal_filename); 290 291 isc_result_t 292 dns_db_diffx(dns_diff_t *diff, dns_db_t *dba, dns_dbversion_t *dbvera, 293 dns_db_t *dbb, dns_dbversion_t *dbverb, 294 const char *journal_filename); 295 /*%< 296 * Compare the databases 'dba' and 'dbb' and generate a diff/journal 297 * entry containing the changes to make 'dba' from 'dbb' (note 298 * the order). This journal entry will consist of a single, 299 * possibly very large transaction. Append the journal 300 * entry to the journal file specified by 'journal_filename' if 301 * non-NULL. 302 */ 303 304 isc_result_t 305 dns_journal_compact(isc_mem_t *mctx, char *filename, uint32_t serial, 306 uint32_t flags, uint32_t target_size); 307 /*%< 308 * Attempt to compact the journal if it is greater that 'target_size'. 309 * Changes from 'serial' onwards will be preserved. Changes prior than 310 * that may be dropped in order to get the journal below `target_size`. 311 * 312 * If 'flags' includes DNS_JOURNAL_COMPACTALL, the entire journal is copied. 313 * In this case, `serial` is ignored. This flag is used when upgrading or 314 * downgrading the format version of the journal. If 'flags' also includes 315 * DNS_JOURNAL_VERSION1, then the journal is copied out in the original 316 * format used prior to BIND 9.16.12; otherwise it is copied in the 317 * current format. 318 * 319 * If _COMPACTALL is not in use, and the journal file exists and is 320 * non-empty, then 'serial' must exist in the journal. 321 * 322 * Returns: 323 *\li ISC_R_SUCCESS 324 *\li ISC_R_RANGE serial is outside the range existing in the journal 325 * 326 * Other errors may be returned from file operations. 327 */ 328 329 bool 330 dns_journal_get_sourceserial(dns_journal_t *j, uint32_t *sourceserial); 331 void 332 dns_journal_set_sourceserial(dns_journal_t *j, uint32_t sourceserial); 333 /*%< 334 * Get and set source serial. 335 * 336 * Returns: 337 * true if sourceserial has previously been set. 338 */ 339 340 ISC_LANG_ENDDECLS 341