⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 journal.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 4 页
字号:
	dns_journal_destroy(&j);	return (result);}/**************************************************************************//* * Miscellaneous accessors. */isc_uint32_t dns_journal_first_serial(dns_journal_t *j) {	return (j->header.begin.serial);}isc_uint32_t dns_journal_last_serial(dns_journal_t *j) {	return (j->header.end.serial);}/**************************************************************************//* * Iteration support. * * When serving an outgoing IXFR, we transmit a part the journal starting * at the serial number in the IXFR request and ending at the serial * number that is current when the IXFR request arrives.  The ending * serial number is not necessarily at the end of the journal: * the journal may grow while the IXFR is in progress, but we stop * when we reach the serial number that was current when the IXFR started. */static isc_result_t read_one_rr(dns_journal_t *j);/* * Make sure the buffer 'b' is has at least 'size' bytes * allocated, and clear it. * * Requires: *	Either b->base is NULL, or it points to b->length bytes of memory *	previously allocated by isc_mem_get(). */static isc_result_tsize_buffer(isc_mem_t *mctx, isc_buffer_t *b, unsigned size) {	if (b->length < size) {		void *mem = isc_mem_get(mctx, size);		if (mem == NULL)			return (ISC_R_NOMEMORY);		if (b->base != NULL)			isc_mem_put(mctx, b->base, b->length);		b->base = mem;		b->length = size;	}	isc_buffer_clear(b);	return (ISC_R_SUCCESS);}isc_result_tdns_journal_iter_init(dns_journal_t *j,		      isc_uint32_t begin_serial, isc_uint32_t end_serial){	isc_result_t result;	CHECK(journal_find(j, begin_serial, &j->it.bpos));	INSIST(j->it.bpos.serial == begin_serial);	CHECK(journal_find(j, end_serial, &j->it.epos));	INSIST(j->it.epos.serial == end_serial);	result = ISC_R_SUCCESS; failure:	j->it.result = result;	return (j->it.result);}isc_result_tdns_journal_first_rr(dns_journal_t *j) {	isc_result_t result;	/*	 * Seek to the beginning of the first transaction we are	 * interested in.	 */	CHECK(journal_seek(j, j->it.bpos.offset));	j->it.current_serial = j->it.bpos.serial;	j->it.xsize = 0;  /* We have no transaction data yet... */	j->it.xpos = 0;	  /* ...and haven't used any of it. */	return (read_one_rr(j)); failure:	return (result);}static isc_result_tread_one_rr(dns_journal_t *j) {	isc_result_t result;	dns_rdatatype_t rdtype;	dns_rdataclass_t rdclass;	unsigned int rdlen;	isc_uint32_t ttl;	journal_xhdr_t xhdr;	journal_rrhdr_t rrhdr;	INSIST(j->offset <= j->it.epos.offset);	if (j->offset == j->it.epos.offset)		return (ISC_R_NOMORE);	if (j->it.xpos == j->it.xsize) {		/*		 * We are at a transaction boundary.		 * Read another transaction header.		 */		CHECK(journal_read_xhdr(j, &xhdr));		if (xhdr.size == 0) {			isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,				      "journal corrupt: empty transaction");			FAIL(ISC_R_UNEXPECTED);		}		if (xhdr.serial0 != j->it.current_serial) {			isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,					 "%s: journal file corrupt: "					 "expected serial %u, got %u",					 j->filename,					 j->it.current_serial, xhdr.serial0);			FAIL(ISC_R_UNEXPECTED);		}		j->it.xsize = xhdr.size;		j->it.xpos = 0;	}	/*	 * Read an RR.	 */	result = journal_read_rrhdr(j, &rrhdr);	/*	 * Perform a sanity check on the journal RR size.	 * The smallest possible RR has a 1-byte owner name	 * and a 10-byte header.  The largest possible	 * RR has 65535 bytes of data, a header, and a maximum-	 * size owner name, well below 70 k total.	 */	if (rrhdr.size < 1+10 || rrhdr.size > 70000) {		isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,				 "%s: journal corrupt: impossible RR size "				 "(%d bytes)", j->filename, rrhdr.size);		FAIL(ISC_R_UNEXPECTED);	}	CHECK(size_buffer(j->mctx, &j->it.source, rrhdr.size));	CHECK(journal_read(j, j->it.source.base, rrhdr.size));	isc_buffer_add(&j->it.source, rrhdr.size);	/*	 * The target buffer is made the same size	 * as the source buffer, with the assumption that when	 * no compression in present, the output of dns_*_fromwire()	 * is no larger than the input.	 */	CHECK(size_buffer(j->mctx, &j->it.target, rrhdr.size));	/*	 * Parse the owner name.  We don't know where it	 * ends yet, so we make the entire "remaining"	 * part of the buffer "active".	 */	isc_buffer_setactive(&j->it.source,			     j->it.source.used - j->it.source.current);	CHECK(dns_name_fromwire(&j->it.name, &j->it.source,				&j->it.dctx, ISC_FALSE, &j->it.target));	/*	 * Check that the RR header is there, and parse it.	 */	if (isc_buffer_remaininglength(&j->it.source) < 10)		FAIL(DNS_R_FORMERR);	rdtype = isc_buffer_getuint16(&j->it.source);	rdclass = isc_buffer_getuint16(&j->it.source);	ttl = isc_buffer_getuint32(&j->it.source);	rdlen = isc_buffer_getuint16(&j->it.source);	/*	 * Parse the rdata.	 */	isc_buffer_setactive(&j->it.source, rdlen);	dns_rdata_reset(&j->it.rdata);	CHECK(dns_rdata_fromwire(&j->it.rdata, rdclass,				 rdtype, &j->it.source, &j->it.dctx,				 ISC_FALSE, &j->it.target));	j->it.ttl = ttl;	j->it.xpos += sizeof(journal_rawrrhdr_t) + rrhdr.size;	if (rdtype == dns_rdatatype_soa) {		/* XXX could do additional consistency checks here */		j->it.current_serial = dns_soa_getserial(&j->it.rdata);	}	result = ISC_R_SUCCESS; failure:	j->it.result = result;	return (result);}isc_result_tdns_journal_next_rr(dns_journal_t *j) {	j->it.result = read_one_rr(j);	return (j->it.result);}voiddns_journal_current_rr(dns_journal_t *j, dns_name_t **name, isc_uint32_t *ttl,		   dns_rdata_t **rdata){	REQUIRE(j->it.result == ISC_R_SUCCESS);	*name = &j->it.name;	*ttl = j->it.ttl;	*rdata = &j->it.rdata;}/**************************************************************************//* * Generating diffs from databases *//* * Construct a diff containing all the RRs at the current name of the * database iterator 'dbit' in database 'db', version 'ver'. * Set '*name' to the current name, and append the diff to 'diff'. * All new tuples will have the operation 'op'. * * Requires: 'name' must have buffer large enough to hold the name. * Typically, a dns_fixedname_t would be used. */static isc_result_tget_name_diff(dns_db_t *db, dns_dbversion_t *ver, isc_stdtime_t now,	      dns_dbiterator_t *dbit, dns_name_t *name, dns_diffop_t op,	      dns_diff_t *diff){	isc_result_t result;	dns_dbnode_t *node = NULL;	dns_rdatasetiter_t *rdsiter = NULL;	dns_difftuple_t *tuple = NULL;	result = dns_dbiterator_current(dbit, &node, name);	if (result != ISC_R_SUCCESS)		return (result);	result = dns_db_allrdatasets(db, node, ver, now, &rdsiter);	if (result != ISC_R_SUCCESS)		goto cleanup_node;	for (result = dns_rdatasetiter_first(rdsiter);	     result == ISC_R_SUCCESS;	     result = dns_rdatasetiter_next(rdsiter))	{		dns_rdataset_t rdataset;		dns_rdataset_init(&rdataset);		dns_rdatasetiter_current(rdsiter, &rdataset);		for (result = dns_rdataset_first(&rdataset);		     result == ISC_R_SUCCESS;		     result = dns_rdataset_next(&rdataset))		{			dns_rdata_t rdata = DNS_RDATA_INIT;			dns_rdataset_current(&rdataset, &rdata);			result = dns_difftuple_create(diff->mctx, op, name,						      rdataset.ttl, &rdata,						      &tuple);			if (result != ISC_R_SUCCESS) {				dns_rdataset_disassociate(&rdataset);				goto cleanup_iterator;			}			dns_diff_append(diff, &tuple);		}		dns_rdataset_disassociate(&rdataset);		if (result != ISC_R_NOMORE)			goto cleanup_iterator;	}	if (result != ISC_R_NOMORE)		goto cleanup_iterator;	result = ISC_R_SUCCESS; cleanup_iterator:	dns_rdatasetiter_destroy(&rdsiter); cleanup_node:	dns_db_detachnode(db, &node);	return (result);}/* * Comparison function for use by dns_diff_subtract when sorting * the diffs to be subtracted.  The sort keys are the rdata type * and the rdata itself.  The owner name is ignored, because * it is known to be the same for all tuples. */static intrdata_order(const void *av, const void *bv) {	dns_difftuple_t const * const *ap = av;	dns_difftuple_t const * const *bp = bv;	dns_difftuple_t const *a = *ap;	dns_difftuple_t const *b = *bp;	int r;	r = (b->rdata.type - a->rdata.type);	if (r != 0)		return (r);	r = dns_rdata_compare(&a->rdata, &b->rdata);	return (r);}static isc_result_tdns_diff_subtract(dns_diff_t diff[2], dns_diff_t *r) {	isc_result_t result;	dns_difftuple_t *p[2];	int i, t;	CHECK(dns_diff_sort(&diff[0], rdata_order));	CHECK(dns_diff_sort(&diff[1], rdata_order));	for (;;) {		p[0] = ISC_LIST_HEAD(diff[0].tuples);		p[1] = ISC_LIST_HEAD(diff[1].tuples);		if (p[0] == NULL && p[1] == NULL)			break;		for (i = 0; i < 2; i++)			if (p[!i] == NULL) {				ISC_LIST_UNLINK(diff[i].tuples, p[i], link);				ISC_LIST_APPEND(r->tuples, p[i], link);				goto next;			}		t = rdata_order(&p[0], &p[1]);		if (t < 0) {			ISC_LIST_UNLINK(diff[0].tuples, p[0], link);			ISC_LIST_APPEND(r->tuples, p[0], link);			goto next;		}		if (t > 0) {			ISC_LIST_UNLINK(diff[1].tuples, p[1], link);			ISC_LIST_APPEND(r->tuples, p[1], link);			goto next;		}		INSIST(t == 0);		/*		 * Identical RRs in both databases; skip them both.		 */		for (i = 0; i < 2; i++) {			ISC_LIST_UNLINK(diff[i].tuples, p[i], link);			dns_difftuple_free(&p[i]);		}	next: ;	}	result = ISC_R_SUCCESS; failure:	return (result);}/* * Compare the databases 'dba' and 'dbb' and generate a journal * entry containing the changes to make 'dba' from 'dbb' (note * the order).  This journal entry will consist of a single, * possibly very large transaction. */isc_result_tdns_db_diff(isc_mem_t *mctx,	    dns_db_t *dba, dns_dbversion_t *dbvera,	    dns_db_t *dbb, dns_dbversion_t *dbverb,	    const char *journal_filename){	dns_db_t *db[2];	dns_dbversion_t *ver[2];	dns_dbiterator_t *dbit[2] = { NULL, NULL };	isc_boolean_t have[2] = { ISC_FALSE, ISC_FALSE };	dns_fixedname_t fixname[2];	isc_result_t result, itresult[2];	dns_diff_t diff[2], resultdiff;	int i, t;	dns_journal_t *journal = NULL;	db[0] = dba, db[1] = dbb;	ver[0] = dbvera, ver[1] = dbverb;	dns_diff_init(mctx, &diff[0]);	dns_diff_init(mctx, &diff[1]);	dns_diff_init(mctx, &resultdiff);	dns_fixedname_init(&fixname[0]);	dns_fixedname_init(&fixname[1]);	CHECK(dns_journal_open(mctx, journal_filename, ISC_TRUE, &journal));	CHECK(dns_db_createiterator(db[0], ISC_FALSE, &dbit[0]));	CHECK(dns_db_createiterator(db[1], ISC_FALSE, &dbit[1]));	itresult[0] = dns_dbiterator_first(dbit[0]);	itresult[1] = dns_dbiterator_first(dbit[1]);	for (;;) {		for (i = 0; i < 2; i++) {			if (! have[i] && itresult[i] == ISC_R_SUCCESS) {				CHECK(get_name_diff(db[i], ver[i], 0, dbit[i],					    dns_fixedname_name(&fixname[i]),					    i == 0 ?					    DNS_DIFFOP_ADD :					    DNS_DIFFOP_DEL,					    &diff[i]));				itresult[i] = dns_dbiterator_next(dbit[i]);				have[i] = ISC_TRUE;			}		}		if (! have[0] && ! have[1]) {			INSIST(ISC_LIST_EMPTY(diff[0].tuples));			INSIST(ISC_LIST_EMPTY(diff[1].tuples));			break;		}		for (i = 0; i < 2; i++) {			if (! have[!i]) {				ISC_LIST_APPENDLIST(resultdiff.tuples,						    diff[i].tuples, link);				INSIST(ISC_LIST_EMPTY(diff[i].tuples));				have[i] = ISC_FALSE;				goto next;			}		}		t = dns_name_compare(dns_fixedname_name(&fixname[0]),				     dns_fixedname_name(&fixname[1]));		if (t < 0) {			ISC_LIST_APPENDLIST(resultdiff.tuples,					    diff[0].tuples, link);			INSIST(ISC_LIST_EMPTY(diff[0].tuples));			have[0] = ISC_FALSE;			continue;		}		if (t > 0) {			ISC_LIST_APPENDLIST(resultdiff.tuples,					    diff[1].tuples, link);			INSIST(ISC_LIST_EMPTY(diff[1].tuples));			have[1] = ISC_FALSE;			continue;		}		INSIST(t == 0);		CHECK(dns_diff_subtract(diff, &resultdiff));		INSIST(ISC_LIST_EMPTY(diff[0].tuples));		INSIST(ISC_LIST_EMPTY(diff[1].tuples));		have[0] = have[1] = ISC_FALSE;	next: ;	}	if (itresult[0] != ISC_R_NOMORE)		FAIL(itresult[0]);	if (itresult[1] != ISC_R_NOMORE)		FAIL(itresult[1]);	if (ISC_LIST_EMPTY(resultdiff.tuples)) {		isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no changes");	} else {		CHECK(dns_journal_write_transaction(journal, &resultdiff));	}	INSIST(ISC_LIST_EMPTY(diff[0].tuples));	INSIST(ISC_LIST_EMPTY(diff[1].tuples));	dns_diff_clear(&resultdiff); failure:	dns_dbiterator_destroy(&dbit[0]);	dns_dbiterator_destroy(&dbit[1]);	dns_journal_destroy(&journal);	return (result);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -