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

📄 rbtdb.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
		}	}}static voiddetach(dns_db_t **dbp) {	dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)(*dbp);	unsigned int refs;	REQUIRE(VALID_RBTDB(rbtdb));	isc_refcount_decrement(&rbtdb->references, &refs);	if (refs == 0)		maybe_free_rbtdb(rbtdb);	*dbp = NULL;}static voidcurrentversion(dns_db_t *db, dns_dbversion_t **versionp) {	dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;	rbtdb_version_t *version;	REQUIRE(VALID_RBTDB(rbtdb));	LOCK(&rbtdb->lock);	version = rbtdb->current_version;	if (version->references == 0)		PREPEND(rbtdb->open_versions, version, link);	version->references++;	UNLOCK(&rbtdb->lock);	*versionp = (dns_dbversion_t *)version;}static inline rbtdb_version_t *allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial,		 unsigned int references, isc_boolean_t writer){	rbtdb_version_t *version;	version = isc_mem_get(mctx, sizeof(*version));	if (version == NULL)		return (NULL);	version->serial = serial;	version->references = references;	version->writer = writer;	version->commit_ok = ISC_FALSE;	ISC_LIST_INIT(version->changed_list);	ISC_LINK_INIT(version, link);	return (version);}static isc_result_tnewversion(dns_db_t *db, dns_dbversion_t **versionp) {	dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;	rbtdb_version_t *version;	REQUIRE(VALID_RBTDB(rbtdb));	REQUIRE(versionp != NULL && *versionp == NULL);	REQUIRE(rbtdb->future_version == NULL);	LOCK(&rbtdb->lock);	RUNTIME_CHECK(rbtdb->next_serial != 0);		/* XXX Error? */	version = allocate_version(rbtdb->common.mctx, rbtdb->next_serial, 1,				   ISC_TRUE);	if (version != NULL) {		version->commit_ok = ISC_TRUE;		rbtdb->next_serial++;		rbtdb->future_version = version;	}	UNLOCK(&rbtdb->lock);	if (version == NULL)		return (ISC_R_NOMEMORY);	*versionp = version;	return (ISC_R_SUCCESS);}static voidattachversion(dns_db_t *db, dns_dbversion_t *source,	      dns_dbversion_t **targetp){	dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;	rbtdb_version_t *rbtversion = source;	REQUIRE(VALID_RBTDB(rbtdb));	LOCK(&rbtdb->lock);	INSIST(rbtversion->references > 0);	rbtversion->references++;	INSIST(rbtversion->references != 0);	UNLOCK(&rbtdb->lock);	*targetp = rbtversion;}static rbtdb_changed_t *add_changed(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,	    dns_rbtnode_t *node){	rbtdb_changed_t *changed;	/*	 * Caller must be holding the node lock.	 */	changed = isc_mem_get(rbtdb->common.mctx, sizeof(*changed));	LOCK(&rbtdb->lock);	REQUIRE(version->writer);	if (changed != NULL) {		INSIST(node->references > 0);		node->references++;		INSIST(node->references != 0);		changed->node = node;		changed->dirty = ISC_FALSE;		ISC_LIST_INITANDAPPEND(version->changed_list, changed, link);	} else		version->commit_ok = ISC_FALSE;	UNLOCK(&rbtdb->lock);	return (changed);}static inline voidfree_noqname(isc_mem_t *mctx, struct noqname **noqname) {	if (dns_name_dynamic(&(*noqname)->name))		dns_name_free(&(*noqname)->name, mctx);	if ((*noqname)->nsec != NULL)		isc_mem_put(mctx, (*noqname)->nsec,			    dns_rdataslab_size((*noqname)->nsec, 0));	if ((*noqname)->nsec != NULL)		isc_mem_put(mctx, (*noqname)->nsecsig,			    dns_rdataslab_size((*noqname)->nsecsig, 0));	isc_mem_put(mctx, *noqname, sizeof(**noqname));	*noqname = NULL;}static inline voidfree_rdataset(isc_mem_t *mctx, rdatasetheader_t *rdataset) {	unsigned int size;	if (rdataset->noqname != NULL)		free_noqname(mctx, &rdataset->noqname);		if ((rdataset->attributes & RDATASET_ATTR_NONEXISTENT) != 0)		size = sizeof(*rdataset);	else		size = dns_rdataslab_size((unsigned char *)rdataset,					  sizeof(*rdataset));	isc_mem_put(mctx, rdataset, size);}static inline voidrollback_node(dns_rbtnode_t *node, rbtdb_serial_t serial) {	rdatasetheader_t *header, *dcurrent;	isc_boolean_t make_dirty = ISC_FALSE;	/*	 * Caller must hold the node lock.	 */	/*	 * We set the IGNORE attribute on rdatasets with serial number	 * 'serial'.  When the reference count goes to zero, these rdatasets	 * will be cleaned up; until that time, they will be ignored.	 */	for (header = node->data; header != NULL; header = header->next) {		if (header->serial == serial) {			header->attributes |= RDATASET_ATTR_IGNORE;			make_dirty = ISC_TRUE;		}		for (dcurrent = header->down;		     dcurrent != NULL;		     dcurrent = dcurrent->down) {			if (dcurrent->serial == serial) {				dcurrent->attributes |= RDATASET_ATTR_IGNORE;				make_dirty = ISC_TRUE;			}		}	}	if (make_dirty)		node->dirty = 1;}static inline voidclean_cache_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {	rdatasetheader_t *current, *dcurrent, *top_prev, *top_next, *down_next;	isc_mem_t *mctx = rbtdb->common.mctx;	/*	 * Caller must be holding the node lock.	 */	top_prev = NULL;	for (current = node->data; current != NULL; current = top_next) {		top_next = current->next;		dcurrent = current->down;		if (dcurrent != NULL) {			do {				down_next = dcurrent->down;				free_rdataset(mctx, dcurrent);				dcurrent = down_next;			} while (dcurrent != NULL);			current->down = NULL;		}		/*		 * If current is nonexistent or stale, we can clean it up.		 */		if ((current->attributes &		     (RDATASET_ATTR_NONEXISTENT|RDATASET_ATTR_STALE)) != 0) {			if (top_prev != NULL)				top_prev->next = current->next;			else				node->data = current->next;			free_rdataset(mctx, current);		} else			top_prev = current;	}	node->dirty = 0;}static inline voidclean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,		rbtdb_serial_t least_serial){	rdatasetheader_t *current, *dcurrent, *down_next, *dparent;	rdatasetheader_t *top_prev, *top_next;	isc_mem_t *mctx = rbtdb->common.mctx;	isc_boolean_t still_dirty = ISC_FALSE;	/*	 * Caller must be holding the node lock.	 */	REQUIRE(least_serial != 0);	top_prev = NULL;	for (current = node->data; current != NULL; current = top_next) {		top_next = current->next;		/*		 * First, we clean up any instances of multiple rdatasets		 * with the same serial number, or that have the IGNORE		 * attribute.		 */		dparent = current;		for (dcurrent = current->down;		     dcurrent != NULL;		     dcurrent = down_next) {			down_next = dcurrent->down;			INSIST(dcurrent->serial <= dparent->serial);			if (dcurrent->serial == dparent->serial ||			    IGNORE(dcurrent)) {				if (down_next != NULL)					down_next->next = dparent;				dparent->down = down_next;				free_rdataset(mctx, dcurrent);			} else				dparent = dcurrent;		}		/*		 * We've now eliminated all IGNORE datasets with the possible		 * exception of current, which we now check.		 */		if (IGNORE(current)) {			down_next = current->down;			if (down_next == NULL) {				if (top_prev != NULL)					top_prev->next = current->next;				else					node->data = current->next;				free_rdataset(mctx, current);				/*				 * current no longer exists, so we can				 * just continue with the loop.				 */				continue;			} else {				/*				 * Pull up current->down, making it the new				 * current.				 */				if (top_prev != NULL)					top_prev->next = down_next;				else					node->data = down_next;				down_next->next = top_next;				free_rdataset(mctx, current);				current = down_next;			}		}		/*		 * We now try to find the first down node less than the		 * least serial.		 */		dparent = current;		for (dcurrent = current->down;		     dcurrent != NULL;		     dcurrent = down_next) {			down_next = dcurrent->down;			if (dcurrent->serial < least_serial)				break;			dparent = dcurrent;		}		/*		 * If there is a such an rdataset, delete it and any older		 * versions.		 */		if (dcurrent != NULL) {			do {				down_next = dcurrent->down;				INSIST(dcurrent->serial <= least_serial);				free_rdataset(mctx, dcurrent);				dcurrent = down_next;			} while (dcurrent != NULL);			dparent->down = NULL;		}		/*		 * Note.  The serial number of 'current' might be less than		 * least_serial too, but we cannot delete it because it is		 * the most recent version, unless it is a NONEXISTENT		 * rdataset.		 */		if (current->down != NULL) {			still_dirty = ISC_TRUE;			top_prev = current;		} else {			/*			 * If this is a NONEXISTENT rdataset, we can delete it.			 */			if (NONEXISTENT(current)) {				if (top_prev != NULL)					top_prev->next = current->next;				else					node->data = current->next;				free_rdataset(mctx, current);			} else				top_prev = current;		}	}	if (!still_dirty)		node->dirty = 0;}static inline voidnew_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {	if (node->references == 0) {		rbtdb->node_locks[node->locknum].references++;		INSIST(rbtdb->node_locks[node->locknum].references != 0);	}	node->references++;	INSIST(node->references != 0);}static voidno_references(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,	      rbtdb_serial_t least_serial, isc_rwlocktype_t lock){	isc_result_t result;	isc_boolean_t write_locked;	unsigned int locknum;	/*	 * Caller must be holding the node lock.	 */	REQUIRE(node->references == 0);	if (node->dirty) {		if (IS_CACHE(rbtdb))			clean_cache_node(rbtdb, node);		else {			if (least_serial == 0) {				/*				 * Caller doesn't know the least serial.				 * Get it.				 */				LOCK(&rbtdb->lock);				least_serial = rbtdb->least_serial;				UNLOCK(&rbtdb->lock);			}			clean_zone_node(rbtdb, node, least_serial);		}	}	locknum = node->locknum;	INSIST(rbtdb->node_locks[locknum].references > 0);	rbtdb->node_locks[locknum].references--;	/*	 * XXXDCL should this only be done for cache zones?	 */	if (node->data != NULL || node->down != NULL)		return;	/*	 * XXXDCL need to add a deferred delete method for ISC_R_LOCKBUSY.	 */	if (lock != isc_rwlocktype_write) {		/*		 * Locking hierarchy notwithstanding, we don't need to free		 * the node lock before acquiring the tree write lock because		 * we only do a trylock.		 */		if (lock == isc_rwlocktype_read)			result = isc_rwlock_tryupgrade(&rbtdb->tree_lock);		else			result = isc_rwlock_trylock(&rbtdb->tree_lock,						    isc_rwlocktype_write);		RUNTIME_CHECK(result == ISC_R_SUCCESS ||			      result == ISC_R_LOCKBUSY); 		write_locked = ISC_TF(result == ISC_R_SUCCESS);	} else		write_locked = ISC_TRUE;	if (write_locked) {		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) {			char printname[DNS_NAME_FORMATSIZE];			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),				      "no_references: delete from rbt: %p %s",				      node,				      dns_rbt_formatnodename(node, printname,							   sizeof(printname)));		}		result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);		if (result != ISC_R_SUCCESS)			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,				      "no_references: dns_rbt_deletenode: %s",				      isc_result_totext(result));	}	/*	 * Relock a read lock, or unlock the write lock if no lock was held.	 */	if (lock == isc_rwlocktype_none)		if (write_locked)			RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);	if (lock == isc_rwlocktype_read)		if (write_locked)			isc_rwlock_downgrade(&rbtdb->tree_lock);}static inline voidmake_least_version(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,		   rbtdb_changedlist_t *cleanup_list){	/*	 * Caller must be holding the database lock.	 */	rbtdb->least_serial = version->serial;	*cleanup_list = version->changed_list;	ISC_LIST_INIT(version->changed_list);}static inline voidcleanup_nondirty(rbtdb_version_t *version, rbtdb_changedlist_t *cleanup_list) {	rbtdb_changed_t *changed, *next_changed;	/*	 * If the changed record is dirty, then	 * an update created multiple versions of	 * a given rdataset.  We keep this list	 * until we're the least open version, at	 * which point it's safe to get rid of any	 * older versions.	 *	 * If the changed record isn't dirty, then	 * we don't need it anymore since we're	 * committing and not rolling back.	 *	 * The caller must be holding the database lock.	 */	for (changed = HEAD(version->changed_list);	     changed != NULL;	     changed = next_changed) {		next_changed = NEXT(changed, link);

⌨️ 快捷键说明

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