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

📄 journal.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 4 页
字号:
				 "%s: close: %s",				 filename, isc_result_totext(result));		(void)isc_file_remove(filename);		return (ISC_R_UNEXPECTED);	}	return (ISC_R_SUCCESS);}static isc_result_tjournal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,	     isc_boolean_t create, dns_journal_t **journalp) {	FILE *fp = NULL;	isc_result_t result;	journal_rawheader_t rawheader;	dns_journal_t *j;	INSIST(journalp != NULL && *journalp == NULL);	j = isc_mem_get(mctx, sizeof(*j));	if (j == NULL)		return (ISC_R_NOMEMORY);	j->mctx = mctx;	j->state = JOURNAL_STATE_INVALID;	j->fp = NULL;	j->filename = filename;	j->index = NULL;	j->rawindex = NULL;	result = isc_stdio_open(j->filename, write ? "rb+" : "rb", &fp);	if (result == ISC_R_FILENOTFOUND) {		if (create) {			isc_log_write(JOURNAL_COMMON_LOGARGS,				      ISC_LOG_INFO,				      "journal file %s does not exist, "				      "creating it",				      j->filename);			CHECK(journal_file_create(mctx, filename));			/*			 * Retry.			 */			result = isc_stdio_open(j->filename, "rb+", &fp);		} else {			FAIL(ISC_R_NOTFOUND);		}	}	if (result != ISC_R_SUCCESS) {		isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,			      "%s: open: %s",			      j->filename, isc_result_totext(result));		FAIL(ISC_R_UNEXPECTED);	}	j->fp = fp;	/*	 * Set magic early so that seek/read can succeed.	 */	j->magic = DNS_JOURNAL_MAGIC;	CHECK(journal_seek(j, 0));	CHECK(journal_read(j, &rawheader, sizeof(rawheader)));	if (memcmp(rawheader.h.format, initial_journal_header.format,		   sizeof(initial_journal_header.format)) != 0) {		isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,				 "%s: journal format not recognized",				 j->filename);		FAIL(ISC_R_UNEXPECTED);	}	journal_header_decode(&rawheader, &j->header);	/*	 * If there is an index, read the raw index into a dynamically	 * allocated buffer and then convert it into a cooked index.	 */	if (j->header.index_size != 0) {		unsigned int i;		unsigned int rawbytes;		unsigned char *p;		rawbytes = j->header.index_size * sizeof(journal_rawpos_t);		j->rawindex = isc_mem_get(mctx, rawbytes);		if (j->rawindex == NULL)			FAIL(ISC_R_NOMEMORY);		CHECK(journal_read(j, j->rawindex, rawbytes));		j->index = isc_mem_get(mctx, j->header.index_size *				       sizeof(journal_pos_t));		if (j->index == NULL)			FAIL(ISC_R_NOMEMORY);		p = j->rawindex;		for (i = 0; i < j->header.index_size; i++) {			j->index[i].serial = decode_uint32(p);			p += 4;			j->index[i].offset = decode_uint32(p);			p += 4;		}		INSIST(p == j->rawindex + rawbytes);	}	j->offset = -1; /* Invalid, must seek explicitly. */	/*	 * Initialize the iterator.	 */	dns_name_init(&j->it.name, NULL);	dns_rdata_init(&j->it.rdata);	/*	 * Set up empty initial buffers for uncheched and checked	 * wire format RR data.  They will be reallocated	 * later.	 */	isc_buffer_init(&j->it.source, NULL, 0);	isc_buffer_init(&j->it.target, NULL, 0);	dns_decompress_init(&j->it.dctx, -1, DNS_DECOMPRESS_NONE);	j->state =		write ? JOURNAL_STATE_WRITE : JOURNAL_STATE_READ;	*journalp = j;	return (ISC_R_SUCCESS); failure:	j->magic = 0;	if (j->index != NULL) {		isc_mem_put(j->mctx, j->index, j->header.index_size *			    sizeof(journal_rawpos_t));		j->index = NULL;	}	if (j->fp != NULL)		(void)isc_stdio_close(j->fp);	isc_mem_put(j->mctx, j, sizeof(*j));	return (result);}isc_result_tdns_journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,		 dns_journal_t **journalp) {	return (journal_open(mctx, filename, write, write, journalp));}/* * A comparison function defining the sorting order for * entries in the IXFR-style journal file. * * The IXFR format requires that deletions are sorted before * additions, and within either one, SOA records are sorted * before others. * * Also sort the non-SOA records by type as a courtesy to the * server receiving the IXFR - it may help reduce the amount of * rdataset merging it has to do. */static intixfr_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->op == DNS_DIFFOP_DEL) - (a->op == DNS_DIFFOP_DEL);	if (r != 0)		return (r);	r = (b->rdata.type == dns_rdatatype_soa) -		(a->rdata.type == dns_rdatatype_soa);	if (r != 0)		return (r);	r = (a->rdata.type - b->rdata.type);	return (r);}/* * Advance '*pos' to the next journal transaction. * * Requires: *	*pos refers to a valid journal transaction. * * Ensures: *	When ISC_R_SUCCESS is returned, *	*pos refers to the next journal transaction. * * Returns one of: * *    ISC_R_SUCCESS *    ISC_R_NOMORE 	*pos pointed at the last transaction *    Other results due to file errors are possible. */static isc_result_tjournal_next(dns_journal_t *j, journal_pos_t *pos) {	isc_result_t result;	journal_xhdr_t xhdr;	REQUIRE(DNS_JOURNAL_VALID(j));	result = journal_seek(j, pos->offset);	if (result != ISC_R_SUCCESS)		return (result);	if (pos->serial == j->header.end.serial)		return (ISC_R_NOMORE);	/*	 * Read the header of the current transaction.	 * This will return ISC_R_NOMORE if we are at EOF.	 */	result = journal_read_xhdr(j, &xhdr);	if (result != ISC_R_SUCCESS)		return (result);	/*	 * Check serial number consistency.	 */	if (xhdr.serial0 != pos->serial) {		isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,			      "%s: journal file corrupt: "			      "expected serial %u, got %u",			      j->filename, pos->serial, xhdr.serial0);		return (ISC_R_UNEXPECTED);	}	/*	 * Check for offset wraparound.	 */	if ((isc_offset_t)(pos->offset + sizeof(journal_rawxhdr_t) + xhdr.size)	    < pos->offset) {		isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,			      "%s: offset too large", j->filename);		return (ISC_R_UNEXPECTED);	}	pos->offset += sizeof(journal_rawxhdr_t) + xhdr.size;	pos->serial = xhdr.serial1;	return (ISC_R_SUCCESS);}/* * If the index of the journal 'j' contains an entry "better" * than '*best_guess', replace '*best_guess' with it. * * "Better" means having a serial number closer to 'serial' * but not greater than 'serial'. */static voidindex_find(dns_journal_t *j, isc_uint32_t serial, journal_pos_t *best_guess) {	unsigned int i;	if (j->index == NULL)		return;	for (i = 0; i < j->header.index_size; i++) {		if (POS_VALID(j->index[i]) &&		    DNS_SERIAL_GE(serial, j->index[i].serial) &&		    DNS_SERIAL_GT(j->index[i].serial, best_guess->serial))			*best_guess = j->index[i];	}}/* * Add a new index entry.  If there is no room, make room by removing * the odd-numbered entries and compacting the others into the first * half of the index.  This decimates old index entries exponentially * over time, so that the index always contains a much larger fraction * of recent serial numbers than of old ones.  This is deliberate - * most index searches are for outgoing IXFR, and IXFR tends to request * recent versions more often than old ones. */static voidindex_add(dns_journal_t *j, journal_pos_t *pos) {	unsigned int i;	if (j->index == NULL)		return;	/*	 * Search for a vacant position.	 */	for (i = 0; i < j->header.index_size; i++) {		if (! POS_VALID(j->index[i]))			break;	}	if (i == j->header.index_size) {		unsigned int k = 0;		/*		 * Found no vacant position.  Make some room.		 */		for (i = 0; i < j->header.index_size; i += 2) {			j->index[k++] = j->index[i];		}		i = k; /* 'i' identifies the first vacant position. */		while (k < j->header.index_size) {			POS_INVALIDATE(j->index[k]);			k++;		}	}	INSIST(i < j->header.index_size);	INSIST(! POS_VALID(j->index[i]));	/*	 * Store the new index entry.	 */	j->index[i] = *pos;}/* * Invalidate any existing index entries that could become * ambiguous when a new transaction with number 'serial' is added. */static voidindex_invalidate(dns_journal_t *j, isc_uint32_t serial) {	unsigned int i;	if (j->index == NULL)		return;	for (i = 0; i < j->header.index_size; i++) {		if (! DNS_SERIAL_GT(serial, j->index[i].serial))			POS_INVALIDATE(j->index[i]);	}}/* * Try to find a transaction with initial serial number 'serial' * in the journal 'j'. * * If found, store its position at '*pos' and return ISC_R_SUCCESS. * * If 'serial' is current (= the ending serial number of the * last transaction in the journal), set '*pos' to * the position immediately following the last transaction and * return ISC_R_SUCCESS. * * If 'serial' is within the range of addressable serial numbers * covered by the journal but that particular serial number is missing * (from the journal, not just from the index), return ISC_R_NOTFOUND. * * If 'serial' is outside the range of addressable serial numbers * covered by the journal, return ISC_R_RANGE. * */static isc_result_tjournal_find(dns_journal_t *j, isc_uint32_t serial, journal_pos_t *pos) {	isc_result_t result;	journal_pos_t current_pos;	REQUIRE(DNS_JOURNAL_VALID(j));	if (DNS_SERIAL_GT(j->header.begin.serial, serial))		return (ISC_R_RANGE);	if (DNS_SERIAL_GT(serial, j->header.end.serial))		return (ISC_R_RANGE);	if (serial == j->header.end.serial) {		*pos = j->header.end;		return (ISC_R_SUCCESS);	}	current_pos = j->header.begin;	index_find(j, serial, &current_pos);	while (current_pos.serial != serial) {		if (DNS_SERIAL_GT(current_pos.serial, serial))			return (ISC_R_NOTFOUND);		result = journal_next(j, &current_pos);		if (result != ISC_R_SUCCESS)			return (result);	}	*pos = current_pos;	return (ISC_R_SUCCESS);}isc_result_tdns_journal_begin_transaction(dns_journal_t *j) {	isc_uint32_t offset;	isc_result_t result;	journal_rawxhdr_t hdr;	REQUIRE(DNS_JOURNAL_VALID(j));	REQUIRE(j->state == JOURNAL_STATE_WRITE);	/*	 * Find the file offset where the new transaction should	 * be written, and seek there.	 */	if (JOURNAL_EMPTY(&j->header)) {		offset = sizeof(journal_rawheader_t) +			j->header.index_size * sizeof(journal_rawpos_t);	} else {		offset = j->header.end.offset;	}	j->x.pos[0].offset = offset;	j->x.pos[1].offset = offset; /* Initial value, will be incremented. */	j->x.n_soa = 0;	CHECK(journal_seek(j, offset));	/*	 * Write a dummy transaction header of all zeroes to reserve	 * space.  It will be filled in when the transaction is	 * finished.	 */	memset(&hdr, 0, sizeof(hdr));	CHECK(journal_write(j, &hdr, sizeof(hdr)));	j->x.pos[1].offset = j->offset;	j->state = JOURNAL_STATE_TRANSACTION;	result = ISC_R_SUCCESS; failure:	return (result);}isc_result_tdns_journal_writediff(dns_journal_t *j, dns_diff_t *diff) {	dns_difftuple_t *t;	isc_buffer_t buffer;	void *mem = NULL;	unsigned int size;	isc_result_t result;	isc_region_t used;	REQUIRE(DNS_DIFF_VALID(diff));	REQUIRE(j->state == JOURNAL_STATE_TRANSACTION);	isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "writing to journal");	(void)dns_diff_print(diff, NULL);	/*	 * 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) {			if (j->x.n_soa < 2)				j->x.pos[j->x.n_soa].serial =					dns_soa_getserial(&t->rdata);			j->x.n_soa++;		}		size += sizeof(journal_rawrrhdr_t);		size += t->name.length; /* XXX should have access macro? */		size += 10;		size += t->rdata.length;	}	mem = isc_mem_get(j->mctx, size);	if (mem == NULL)		return (ISC_R_NOMEMORY);	isc_buffer_init(&buffer, mem, size);	/*	 * Pass 2.  Write RRs to buffer.	 */	for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;	     t = ISC_LIST_NEXT(t, link))	{		/*		 * Write the RR header.		 */		isc_buffer_putuint32(&buffer, t->name.length + 10 +				     t->rdata.length);		/*		 * Write the owner name, RR header, and RR data.		 */		isc_buffer_putmem(&buffer, t->name.ndata, t->name.length);		isc_buffer_putuint16(&buffer, t->rdata.type);		isc_buffer_putuint16(&buffer, t->rdata.rdclass);		isc_buffer_putuint32(&buffer, t->ttl);		INSIST(t->rdata.length < 65536);		isc_buffer_putuint16(&buffer, (isc_uint16_t)t->rdata.length);		INSIST(isc_buffer_availablelength(&buffer) >= t->rdata.length);		isc_buffer_putmem(&buffer, t->rdata.data, t->rdata.length);	}	isc_buffer_usedregion(&buffer, &used);	INSIST(used.length == size);	j->x.pos[1].offset += used.length;	/*	 * Write the buffer contents to the journal file.	 */	CHECK(journal_write(j, used.base, used.length));	result = ISC_R_SUCCESS; failure:	if (mem != NULL)		isc_mem_put(j->mctx, mem, size);	return (result);}isc_result_tdns_journal_commit(dns_journal_t *j) {	isc_result_t result;	journal_rawheader_t rawheader;	REQUIRE(DNS_JOURNAL_VALID(j));	REQUIRE(j->state == JOURNAL_STATE_TRANSACTION);	/*	 * Perform some basic consistency checks.	 */	if (j->x.n_soa != 2) {		isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,			      "malformed transaction: %d SOAs",			      j->x.n_soa);		return (ISC_R_UNEXPECTED);	}	if (! (DNS_SERIAL_GT(j->x.pos[1].serial, j->x.pos[0].serial) ||	       (bind8_compat &&		j->x.pos[1].serial == j->x.pos[0].serial)))	{		isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,			      "malformed transaction: serial number "			      "would decrease");		return (ISC_R_UNEXPECTED);	}	if (! JOURNAL_EMPTY(&j->header)) {		if (j->x.pos[0].serial != j->header.end.serial) {			isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,					 "malformed transaction: "					 "%s last serial %u != "					 "transaction first serial %u",					 j->filename,					 j->header.end.serial,					 j->x.pos[0].serial);			return (ISC_R_UNEXPECTED);		}	}	/*	 * Some old journal entries may become non-addressable	 * when we increment the current serial number.  Purge them

⌨️ 快捷键说明

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