*/
typedef struct {
unsigned char size[4]; /*%< In bytes, excluding header. */
+ unsigned char count[4]; /*%< Number of records in transaction */
unsigned char serial0[4]; /*%< SOA serial before update. */
unsigned char serial1[4]; /*%< SOA serial after update. */
} journal_rawxhdr_t;
/*%
* The in-core representation of the transaction header.
*/
-
typedef struct {
uint32_t size;
+ uint32_t count;
uint32_t serial0;
uint32_t serial1;
} journal_xhdr_t;
isc_offset_t offset; /*%< Current file offset */
journal_header_t header; /*%< In-core journal header */
unsigned char *rawindex; /*%< In-core buffer for journal index
- * in
- * on-disk format */
+ * in on-disk format */
journal_pos_t *index; /*%< In-core journal index */
/*% Current transaction state (when writing). */
struct {
unsigned int n_soa; /*%< Number of SOAs seen */
+ unsigned int n_rr; /*%< Number of RRs to write */
journal_pos_t pos[2]; /*%< Begin/end position */
} x;
uint32_t current_serial; /*%< Current SOA serial
* */
isc_buffer_t source; /*%< Data from disk */
- isc_buffer_t target; /*%< Data from _fromwire check
- * */
+ isc_buffer_t target; /*%< Data from _fromwire check */
dns_decompress_t dctx; /*%< Dummy decompression ctx */
dns_name_t name; /*%< Current domain name */
dns_rdata_t rdata; /*%< Current rdata */
return (result);
}
xhdr->size = decode_uint32(raw.size);
+ xhdr->count = decode_uint32(raw.count);
xhdr->serial0 = decode_uint32(raw.serial0);
xhdr->serial1 = decode_uint32(raw.serial1);
return (ISC_R_SUCCESS);
}
static isc_result_t
-journal_write_xhdr(dns_journal_t *j, uint32_t size, uint32_t serial0,
- uint32_t serial1) {
+journal_write_xhdr(dns_journal_t *j, uint32_t size, uint32_t count,
+ uint32_t serial0, uint32_t serial1) {
journal_rawxhdr_t raw;
encode_uint32(size, raw.size);
+ encode_uint32(count, raw.count);
encode_uint32(serial0, raw.serial0);
encode_uint32(serial1, raw.serial1);
return (journal_write(j, &raw, sizeof(raw)));
dns_difftuple_t *t;
isc_buffer_t buffer;
void *mem = NULL;
- uint64_t size;
+ uint64_t size = 0;
+ uint32_t rrcount = 0;
isc_result_t result;
isc_region_t used;
* Pass 1: determine the buffer size needed, and
* keep track of SOA serial numbers.
*/
- size = 0;
for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
t = ISC_LIST_NEXT(t, link)) {
if (t->rdata.type == dns_rdatatype_soa) {
isc_buffer_putuint16(&buffer, (uint16_t)t->rdata.length);
INSIST(isc_buffer_availablelength(&buffer) >= t->rdata.length);
isc_buffer_putmem(&buffer, t->rdata.data, t->rdata.length);
+
+ rrcount++;
}
isc_buffer_usedregion(&buffer, &used);
INSIST(used.length == size);
j->x.pos[1].offset += used.length;
+ j->x.n_rr = rrcount;
/*
* Write the buffer contents to the journal file.
* Update the transaction header.
*/
CHECK(journal_seek(j, j->x.pos[0].offset));
- CHECK(journal_write_xhdr(j, offset, j->x.pos[0].serial,
+ CHECK(journal_write_xhdr(j, offset, j->x.n_rr,
+ j->x.pos[0].serial,
j->x.pos[1].serial));
}
CHECK(DNS_R_UPTODATE);
}
- CHECK(dns_journal_iter_init(j, db_serial, end_serial));
+ CHECK(dns_journal_iter_init(j, db_serial, end_serial, NULL));
for (result = dns_journal_first_rr(j); result == ISC_R_SUCCESS;
result = dns_journal_next_rr(j))
start_serial = dns_journal_first_serial(j);
end_serial = dns_journal_last_serial(j);
- CHECK(dns_journal_iter_init(j, start_serial, end_serial));
+ CHECK(dns_journal_iter_init(j, start_serial, end_serial, NULL));
for (result = dns_journal_first_rr(j); result == ISC_R_SUCCESS;
result = dns_journal_next_rr(j))
isc_result_t
dns_journal_iter_init(dns_journal_t *j, uint32_t begin_serial,
- uint32_t end_serial) {
+ uint32_t end_serial, size_t *xfrsizep) {
isc_result_t result;
CHECK(journal_find(j, begin_serial, &j->it.bpos));
CHECK(journal_find(j, end_serial, &j->it.epos));
INSIST(j->it.epos.serial == end_serial);
+ if (xfrsizep != NULL) {
+ journal_pos_t pos = j->it.bpos;
+ journal_xhdr_t xhdr;
+ uint64_t size = 0;
+ uint32_t count = 0;
+
+ /*
+ * We already know the beginning and ending serial
+ * numbers are in the journal. Scan through them,
+ * adding up sizes and RR counts so we can calculate
+ * the IXFR size.
+ */
+ CHECK(journal_seek(j, pos.offset));
+ do {
+ CHECK(journal_read_xhdr(j, &xhdr));
+
+ size += xhdr.size;
+ count += xhdr.count;
+
+ result = journal_next(j, &pos);
+ if (result == ISC_R_NOMORE) {
+ result = ISC_R_SUCCESS;
+ }
+ CHECK(result);
+ } while (pos.serial != end_serial);
+
+ /*
+ * For each RR, subtract the length of the RR header,
+ * as this would not be present in IXFR messages.
+ * (We don't need to worry about the transaction header
+ * because that was already excluded from xdr.size.)
+ */
+ *xfrsizep = size - (count * sizeof(journal_rawrrhdr_t));
+ }
+
result = ISC_R_SUCCESS;
failure:
j->it.result = result;