find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen, 
	uint16_t qclass, time_t now, uint16_t searchtype, int stripfront,
	int noexpiredabove, uint8_t* expiretop, size_t expiretoplen)
{
	struct ub_packed_rrset_key *rrset;
	uint8_t lablen;

	if(stripfront) {
		/* strip off so that DNAMEs have strict subdomain match */
		lablen = *qname;
		qname += lablen + 1;
		qnamelen -= lablen + 1;
	}

	/* snip off front part of qname until the type is found */
	while(qnamelen > 0) {
		if((rrset = rrset_cache_lookup(env->rrset_cache, qname, 
			qnamelen, searchtype, qclass, 0, now, 0))) {
			uint8_t* origqname = qname;
			size_t origqnamelen = qnamelen;
			if(!noexpiredabove)
				return rrset;
			/* if expiretop set, do not look above it, but
			 * qname is equal, so the just found result is also
			 * the nonexpired above part. */
			if(expiretop && qnamelen == expiretoplen &&
				query_dname_compare(qname, expiretop)==0)
				return rrset;
			/* check for expiry, but we have to let go of the rrset
			 * for the lock ordering */
			lock_rw_unlock(&rrset->entry.lock);
			/* the expired_above function always takes off one
			 * label (if qnamelen>0) and returns the final qname
			 * where it searched, so we can continue from there
			 * turning the O N*N search into O N. */
			if(!rrset_expired_above(env, &qname, &qnamelen,
				searchtype, qclass, now, expiretop,
				expiretoplen)) {
				/* we want to return rrset, but it may be
				 * gone from cache, if so, just loop like
				 * it was not in the cache in the first place.
				 */
				if((rrset = rrset_cache_lookup(env->
					rrset_cache, origqname, origqnamelen,
					searchtype, qclass, 0, now, 0))) {
					return rrset;
				}
			}
			log_nametypeclass(VERB_ALGO, "ignoring rrset because expired rrsets exist above it", origqname, searchtype, qclass);
			continue;
		}

		/* snip off front label */
		lablen = *qname;
		qname += lablen + 1;
		qnamelen -= lablen + 1;
	}
	return NULL;
}
find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen, 
	uint16_t qclass, time_t now, uint16_t searchtype, int stripfront,
	int noexpiredabove, uint8_t* expiretop, size_t expiretoplen)
{
	struct ub_packed_rrset_key *rrset;
	uint8_t lablen;

	if(stripfront) {
		 
		lablen = *qname;
		qname += lablen + 1;
		qnamelen -= lablen + 1;
	}

	 
	while(qnamelen > 0) {
		if((rrset = rrset_cache_lookup(env->rrset_cache, qname, 
			qnamelen, searchtype, qclass, 0, now, 0))) {
			uint8_t* origqname = qname;
			size_t origqnamelen = qnamelen;
			if(!noexpiredabove)
				return rrset;
			 
			if(expiretop && qnamelen == expiretoplen &&
				query_dname_compare(qname, expiretop)==0)
				return rrset;
			 
			lock_rw_unlock(&rrset->entry.lock);
			 
			if(!rrset_expired_above(env, &qname, &qnamelen,
				searchtype, qclass, now, expiretop,
				expiretoplen)) {
				 
				if((rrset = rrset_cache_lookup(env->
					rrset_cache, origqname, origqnamelen,
					searchtype, qclass, 0, now, 0))) {
					return rrset;
				}
			}
			log_nametypeclass(VERB_ALGO, "ignoring rrset because expired rrsets exist above it", origqname, searchtype, qclass);
			continue;
		}

		 
		lablen = *qname;
		qname += lablen + 1;
		qnamelen -= lablen + 1;
	}
	return NULL;
}