load_rrset(RES* ssl, sldns_buffer* buf, struct worker* worker)
{
	char* s = (char*)sldns_buffer_begin(buf);
	struct regional* region = worker->scratchpad;
	struct ub_packed_rrset_key* rk;
	struct packed_rrset_data* d;
	unsigned int rr_count, rrsig_count, trust, security;
	long long ttl;
	unsigned int i;
	int go_on = 1;
	regional_free_all(region);

	rk = (struct ub_packed_rrset_key*)regional_alloc_zero(region, 
		sizeof(*rk));
	d = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*d));
	if(!rk || !d) {
		log_warn("error out of memory");
		return 0;
	}

	if(strncmp(s, ";rrset", 6) != 0) {
		log_warn("error expected ';rrset' but got %s", s);
		return 0;
	}
	s += 6;
	if(strncmp(s, " nsec_apex", 10) == 0) {
		s += 10;
		rk->rk.flags |= PACKED_RRSET_NSEC_AT_APEX;
	}
	if(sscanf(s, " " ARG_LL "d %u %u %u %u", &ttl, &rr_count, &rrsig_count,
		&trust, &security) != 5) {
		log_warn("error bad rrset spec %s", s);
		return 0;
	}
	if(rr_count == 0 && rrsig_count == 0) {
		log_warn("bad rrset without contents");
		return 0;
	}
	if(rr_count > RR_COUNT_MAX || rrsig_count > RR_COUNT_MAX) {
		log_warn("bad rrset with too many rrs");
		return 0;
	}
	d->count = (size_t)rr_count;
	d->rrsig_count = (size_t)rrsig_count;
	d->security = (enum sec_status)security;
	d->trust = (enum rrset_trust)trust;
	d->ttl = (time_t)ttl + *worker->env.now;

	d->rr_len = regional_alloc_zero(region, 
		sizeof(size_t)*(d->count+d->rrsig_count));
	d->rr_ttl = regional_alloc_zero(region, 
		sizeof(time_t)*(d->count+d->rrsig_count));
	d->rr_data = regional_alloc_zero(region, 
		sizeof(uint8_t*)*(d->count+d->rrsig_count));
	if(!d->rr_len || !d->rr_ttl || !d->rr_data) {
		log_warn("error out of memory");
		return 0;
	}
	
	/* read the rr's themselves */
	for(i=0; i<rr_count; i++) {
		if(!load_rr(ssl, buf, region, rk, d, i, 0, 
			&go_on, *worker->env.now)) {
			log_warn("could not read rr %u", i);
			return 0;
		}
	}
	for(i=0; i<rrsig_count; i++) {
		if(!load_rr(ssl, buf, region, rk, d, i+rr_count, 1, 
			&go_on, *worker->env.now)) {
			log_warn("could not read rrsig %u", i);
			return 0;
		}
	}
	if(!go_on) {
		/* skip this entry */
		return 1;
	}

	return move_into_cache(rk, d, worker);
}
load_rrset(RES* ssl, sldns_buffer* buf, struct worker* worker)
{
	char* s = (char*)sldns_buffer_begin(buf);
	struct regional* region = worker->scratchpad;
	struct ub_packed_rrset_key* rk;
	struct packed_rrset_data* d;
	unsigned int rr_count, rrsig_count, trust, security;
	long long ttl;
	unsigned int i;
	int go_on = 1;
	regional_free_all(region);

	rk = (struct ub_packed_rrset_key*)regional_alloc_zero(region, 
		sizeof(*rk));
	d = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*d));
	if(!rk || !d) {
		log_warn("error out of memory");
		return 0;
	}

	if(strncmp(s, ";rrset", 6) != 0) {
		log_warn("error expected ';rrset' but got %s", s);
		return 0;
	}
	s += 6;
	if(strncmp(s, " nsec_apex", 10) == 0) {
		s += 10;
		rk->rk.flags |= PACKED_RRSET_NSEC_AT_APEX;
	}
	if(sscanf(s, " " ARG_LL "d %u %u %u %u", &ttl, &rr_count, &rrsig_count,
		&trust, &security) != 5) {
		log_warn("error bad rrset spec %s", s);
		return 0;
	}
	if(rr_count == 0 && rrsig_count == 0) {
		log_warn("bad rrset without contents");
		return 0;
	}
	if(rr_count > RR_COUNT_MAX || rrsig_count > RR_COUNT_MAX) {
		log_warn("bad rrset with too many rrs");
		return 0;
	}
	d->count = (size_t)rr_count;
	d->rrsig_count = (size_t)rrsig_count;
	d->security = (enum sec_status)security;
	d->trust = (enum rrset_trust)trust;
	d->ttl = (time_t)ttl + *worker->env.now;

	d->rr_len = regional_alloc_zero(region, 
		sizeof(size_t)*(d->count+d->rrsig_count));
	d->rr_ttl = regional_alloc_zero(region, 
		sizeof(time_t)*(d->count+d->rrsig_count));
	d->rr_data = regional_alloc_zero(region, 
		sizeof(uint8_t*)*(d->count+d->rrsig_count));
	if(!d->rr_len || !d->rr_ttl || !d->rr_data) {
		log_warn("error out of memory");
		return 0;
	}
	
	 
	for(i=0; i<rr_count; i++) {
		if(!load_rr(ssl, buf, region, rk, d, i, 0, 
			&go_on, *worker->env.now)) {
			log_warn("could not read rr %u", i);
			return 0;
		}
	}
	for(i=0; i<rrsig_count; i++) {
		if(!load_rr(ssl, buf, region, rk, d, i+rr_count, 1, 
			&go_on, *worker->env.now)) {
			log_warn("could not read rrsig %u", i);
			return 0;
		}
	}
	if(!go_on) {
		 
		return 1;
	}

	return move_into_cache(rk, d, worker);
}