move_into_cache(struct ub_packed_rrset_key* k, 
	struct packed_rrset_data* d, struct worker* worker)
{
	struct ub_packed_rrset_key* ak;
	struct packed_rrset_data* ad;
	size_t s, i, num = d->count + d->rrsig_count;
	struct rrset_ref ref;
	uint8_t* p;

	ak = alloc_special_obtain(&worker->alloc);
	if(!ak) {
		log_warn("error out of memory");
		return 0;
	}
	ak->entry.data = NULL;
	ak->rk = k->rk;
	ak->entry.hash = rrset_key_hash(&k->rk);
	ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len);
	if(!ak->rk.dname) {
		log_warn("error out of memory");
		ub_packed_rrset_parsedelete(ak, &worker->alloc);
		return 0;
	}
	s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) + 
		sizeof(time_t))* num;
	for(i=0; i<num; i++)
		s += d->rr_len[i];
	ad = (struct packed_rrset_data*)malloc(s);
	if(!ad) {
		log_warn("error out of memory");
		ub_packed_rrset_parsedelete(ak, &worker->alloc);
		return 0;
	}
	p = (uint8_t*)ad;
	memmove(p, d, sizeof(*ad));
	p += sizeof(*ad);
	memmove(p, &d->rr_len[0], sizeof(size_t)*num);
	p += sizeof(size_t)*num;
	memmove(p, &d->rr_data[0], sizeof(uint8_t*)*num);
	p += sizeof(uint8_t*)*num;
	memmove(p, &d->rr_ttl[0], sizeof(time_t)*num);
	p += sizeof(time_t)*num;
	for(i=0; i<num; i++) {
		memmove(p, d->rr_data[i], d->rr_len[i]);
		p += d->rr_len[i];
	}
	packed_rrset_ptr_fixup(ad);

	ak->entry.data = ad;

	ref.key = ak;
	ref.id = ak->id;
	(void)rrset_cache_update(worker->env.rrset_cache, &ref,
		&worker->alloc, *worker->env.now);
	return 1;
}
move_into_cache(struct ub_packed_rrset_key* k, 
	struct packed_rrset_data* d, struct worker* worker)
{
	struct ub_packed_rrset_key* ak;
	struct packed_rrset_data* ad;
	size_t s, i, num = d->count + d->rrsig_count;
	struct rrset_ref ref;
	uint8_t* p;

	ak = alloc_special_obtain(&worker->alloc);
	if(!ak) {
		log_warn("error out of memory");
		return 0;
	}
	ak->entry.data = NULL;
	ak->rk = k->rk;
	ak->entry.hash = rrset_key_hash(&k->rk);
	ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len);
	if(!ak->rk.dname) {
		log_warn("error out of memory");
		ub_packed_rrset_parsedelete(ak, &worker->alloc);
		return 0;
	}
	s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) + 
		sizeof(time_t))* num;
	for(i=0; i<num; i++)
		s += d->rr_len[i];
	ad = (struct packed_rrset_data*)malloc(s);
	if(!ad) {
		log_warn("error out of memory");
		ub_packed_rrset_parsedelete(ak, &worker->alloc);
		return 0;
	}
	p = (uint8_t*)ad;
	memmove(p, d, sizeof(*ad));
	p += sizeof(*ad);
	memmove(p, &d->rr_len[0], sizeof(size_t)*num);
	p += sizeof(size_t)*num;
	memmove(p, &d->rr_data[0], sizeof(uint8_t*)*num);
	p += sizeof(uint8_t*)*num;
	memmove(p, &d->rr_ttl[0], sizeof(time_t)*num);
	p += sizeof(time_t)*num;
	for(i=0; i<num; i++) {
		memmove(p, d->rr_data[i], d->rr_len[i]);
		p += d->rr_len[i];
	}
	packed_rrset_ptr_fixup(ad);

	ak->entry.data = ad;

	ref.key = ak;
	ref.id = ak->id;
	(void)rrset_cache_update(worker->env.rrset_cache, &ref,
		&worker->alloc, *worker->env.now);
	return 1;
}