further mesh.

git-svn-id: file:///svn/unbound/trunk@419 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-06-22 12:39:08 +00:00
parent fcd489a12a
commit e939a7689f
5 changed files with 133 additions and 35 deletions

View file

@ -54,6 +54,7 @@
#include "services/outside_network.h"
#include "services/outbound_list.h"
#include "services/cache/rrset.h"
#include "services/mesh.h"
#include "util/data/msgparse.h"
#include "util/data/msgencode.h"
@ -734,7 +735,6 @@ reqs_init(struct worker* worker)
sizeof(struct work_query));
if(!q) return 0;
q->state.buf = worker->front->udp_buff;
q->state.scratch = worker->scratchpad;
q->state.region = region_create_custom(malloc, free, 1024,
64, 16, 0);
if(!q->state.region) {
@ -869,6 +869,13 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker->env.worker = worker;
worker->env.alloc = &worker->alloc;
worker->env.rnd = worker->rndstate;
worker->env.scratch = worker->scratchpad;
worker->env.mesh = mesh_create(worker->daemon->num_modules,
worker->daemon->modfunc);
if(!worker->env.mesh) {
worker_delete(worker);
return 0;
}
return 1;
}
@ -884,6 +891,7 @@ worker_delete(struct worker* worker)
if(!worker)
return;
server_stats_log(&worker->stats, worker->thread_num);
mesh_delete(worker->env.mesh);
reqs_delete(worker);
qstate_free_recurs_list(worker, worker->slumber_list);
listen_delete(worker->front);

View file

@ -155,7 +155,7 @@ iter_handlereply(struct module_qstate* qstate, int id,
struct edns_data reply_edns;
int r;
if((r=reply_info_parse(qstate->reply->c->buffer, env->alloc,
&reply_qinfo, &reply_msg, qstate->scratch,
&reply_qinfo, &reply_msg, qstate->env->scratch,
&reply_edns))!=0)
return 0;
@ -165,7 +165,7 @@ iter_handlereply(struct module_qstate* qstate, int id,
qstate->edns.bits &= EDNS_DO;
if(!reply_info_answer_encode(&reply_qinfo, reply_msg, 0,
qstate->query_flags, qstate->buf, 0, 0,
qstate->scratch, us, &qstate->edns,
qstate->env->scratch, us, &qstate->edns,
(int)(qstate->edns.bits&EDNS_DO)))
return 0;
dns_cache_store_msg(qstate->env, &reply_qinfo, qstate->query_hash,
@ -345,7 +345,7 @@ iter_encode_respmsg(struct module_qstate* qstate, struct iter_qstate* iq,
edns.ext_rcode = 0;
edns.bits = qstate->edns.bits & EDNS_DO;
if(!reply_info_answer_encode(&qinf, msg->rep, 0, iq->orig_qflags,
qstate->buf, 0, 1, qstate->scratch, qstate->edns.udp_size,
qstate->buf, 0, 1, qstate->env->scratch, qstate->edns.udp_size,
&edns, (int)(qstate->edns.bits & EDNS_DO))) {
/* encode servfail */
error_response(qstate, id, LDNS_RCODE_SERVFAIL);
@ -473,7 +473,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
subq->query_flags = 0; /* OPCODE QUERY, no flags */
subq->edns.udp_size = 65535;
subq->buf = qstate->buf;
subq->scratch = qstate->scratch;
subq->env->scratch = qstate->env->scratch;
subq->region = region_create(malloc, free);
if(!subq->region) {
free(subq->qinfo.qname);
@ -673,7 +673,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
qstate->qinfo.qclass, qstate->region, qstate->scratch);
qstate->qinfo.qclass, qstate->region, qstate->env->scratch);
if(msg) {
/* handle positive cache response */
enum response_type type = response_type_from_cache(msg,
@ -1536,7 +1536,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
}
/* parse message */
prs = (struct msg_parse*)region_alloc(qstate->scratch,
prs = (struct msg_parse*)region_alloc(qstate->env->scratch,
sizeof(struct msg_parse));
if(!prs) {
log_err("out of memory on incoming message");
@ -1547,7 +1547,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
memset(&edns, 0, sizeof(edns));
pkt = qstate->reply->c->buffer;
ldns_buffer_set_position(pkt, 0);
if(parse_packet(pkt, prs, qstate->scratch) != LDNS_RCODE_NOERROR) {
if(parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
verbose(VERB_ALGO, "parse error on reply packet");
goto handle_it;
}
@ -1557,7 +1557,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
/* normalize and sanitize: easy to delete items from linked lists */
if(!scrub_message(pkt, prs, &qstate->qinfo, iq->dp->name,
qstate->scratch))
qstate->env->scratch))
goto handle_it;
/* allocate response dns_msg in region */

View file

@ -61,12 +61,12 @@ mesh_state_compare(const void* ap, const void* bp)
if(!a->is_priming && b->is_priming)
return 1;
if((a->state->query_flags&BIT_RD) && !(b->state->query_flags&BIT_RD))
if((a->s.query_flags&BIT_RD) && !(b->s.query_flags&BIT_RD))
return -1;
if(!(a->state->query_flags&BIT_RD) && (b->state->query_flags&BIT_RD))
if(!(a->s.query_flags&BIT_RD) && (b->s.query_flags&BIT_RD))
return 1;
return query_info_compare(&a->state->qinfo, &b->state->qinfo);
return query_info_compare(&a->s.qinfo, &b->s.qinfo);
}
/** compare two mesh references */
@ -79,14 +79,15 @@ mesh_state_ref_compare(const void* ap, const void* bp)
}
struct mesh_area*
mesh_create(struct worker* worker)
mesh_create(int num_modules, struct module_func_block** modfunc)
{
struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area));
if(!mesh) {
log_err("mesh area alloc: out of memory");
return NULL;
}
mesh->worker = worker;
mesh->num_modules = num_modules;
mesh->modfunc = modfunc;
rbtree_init(&mesh->run, &mesh_state_compare);
rbtree_init(&mesh->all, &mesh_state_compare);
mesh->num_reply_addrs = 0;
@ -98,8 +99,77 @@ mesh_create(struct worker* worker)
void
mesh_delete(struct mesh_area* mesh)
{
struct mesh_state* mstate;
if(!mesh)
return;
/* free all query states */
RBTREE_FOR(mstate, struct mesh_state*, &mesh->all) {
mesh_state_cleanup(mstate);
}
free(mesh);
}
struct mesh_state*
mesh_state_create(struct module_env* env, struct query_info* qinfo,
uint16_t qflags, int prime)
{
region_type* region = region_create(malloc, free);
struct mesh_state* mstate;
int i;
if(!region)
return NULL;
mstate = (struct mesh_state*)region_alloc(region,
sizeof(struct mesh_state));
if(!mstate) {
region_destroy(region);
return NULL;
}
mstate->node = *RBTREE_NULL;
mstate->run_node = *RBTREE_NULL;
mstate->node.key = mstate;
mstate->run_node.key = mstate;
mstate->is_priming = prime;
mstate->reply_list = NULL;
rbtree_init(&mstate->super_set, &mesh_state_ref_compare);
rbtree_init(&mstate->sub_set, &mesh_state_ref_compare);
/* init module qstate */
mstate->s.qinfo.qtype = qinfo->qtype;
mstate->s.qinfo.qclass = qinfo->qclass;
mstate->s.qinfo.qname_len = qinfo->qname_len;
mstate->s.qinfo.qname = region_alloc_init(region, qinfo->qname,
qinfo->qname_len);
if(!mstate->s.qinfo.qname) {
region_destroy(region);
return NULL;
}
/* remove all weird bits from qflags */
mstate->s.query_flags = (qflags & BIT_RD);
mstate->s.reply = NULL;
mstate->s.region = region;
mstate->s.curmod = 0;
mstate->s.env = env;
mstate->s.mesh_info = mstate;
/* init modules */
for(i=0; i<env->mesh->num_modules; i++) {
mstate->s.minfo[i] = NULL;
mstate->s.ext_state[i] = module_state_initial;
}
return mstate;
}
void
mesh_state_cleanup(struct mesh_state* mstate)
{
struct mesh_area* mesh;
int i;
if(!mstate)
return;
/* de-init modules */
mesh = mstate->s.env->mesh;
for(i=0; i<mesh->num_modules; i++) {
(*mesh->modfunc[i]->clear)(&mstate->s, i);
mstate->s.minfo[i] = NULL;
mstate->s.ext_state[i] = module_finished;
}
region_destroy(mstate->s.region);
}

View file

@ -49,10 +49,9 @@
#include "util/rbtree.h"
#include "util/netevent.h"
#include "util/data/msgparse.h"
struct module_qstate;
#include "util/module.h"
struct mesh_state;
struct mesh_reply;
struct worker;
struct query_info;
struct reply_info;
struct outbound_entry;
@ -61,8 +60,11 @@ struct outbound_entry;
* Mesh of query states
*/
struct mesh_area {
/** what worker this is a part of */
struct worker* worker;
/** the number of modules */
int num_modules;
/** the module callbacks, array of num_modules length (ref only) */
struct module_func_block** modfunc;
/** set of runnable queries (mesh_state.run_node) */
rbtree_t run;
/** rbtree of all current queries (mesh_state.node)*/
@ -90,7 +92,7 @@ struct mesh_area {
* region. All parts (rbtree nodes etc) are also allocated in the region.
*/
struct mesh_state {
/** node in mesh_area all tree, key is this struct */
/** node in mesh_area all tree, key is this struct. Must be first. */
rbnode_t node;
/** node in mesh_area runnable tree, key is this struct */
rbnode_t run_node;
@ -98,7 +100,7 @@ struct mesh_state {
int is_priming;
/** the query state. Note that the qinfo and query_flags
* may not change. */
struct module_qstate* state;
struct module_qstate s;
/** the list of replies to clients for the results */
struct mesh_reply* reply_list;
/** set of superstates (that want this state's result)
@ -142,10 +144,13 @@ struct mesh_reply {
/**
* Allocate mesh, to empty.
* @param worker: what worker it is part of.
* @param num_modules: number of modules that are present.
* @param modfunc: array passed (alloced and deleted by caller), that has
* num_modules function callbacks for the modules.
* @return mesh: the new mesh or NULL on error.
*/
struct mesh_area* mesh_create(struct worker* worker);
struct mesh_area* mesh_create(int num_modules,
struct module_func_block** modfunc);
/**
* Delete mesh, and all query states and replies in it.
@ -253,11 +258,22 @@ void mesh_walk_supers(struct module_qstate* qstate, int id, int rcode,
/**
* Create and initialize a new mesh state and its query state
* Does not put the mesh state into rbtrees and so on.
* @param env: module environment to set.
* @param qinfo: query info that the mesh is for.
* @param qflags: flags for query (RD flag).
* @param prime: if true, it is a priming query, set is_priming on mesh state.
* @return: new mesh state or NULL on allocation error.
*/
struct mesh_state* mesh_state_create(struct module_env* env,
struct query_info* qinfo, uint16_t qflags, int prime);
/**
* Cleanup a mesh state and its query state. Does not do rbtree or
* reference cleanup.
* @param mstate: mesh state to cleanup. Its pointer may no longer be used
* afterwards. Cleanup rbtrees before calling this function.
*/
void mesh_state_cleanup(struct mesh_state* mstate);
#endif /* SERVICES_MESH_H */

View file

@ -54,6 +54,8 @@ struct region;
struct worker;
struct module_qstate;
struct ub_randstate;
struct mesh_area;
struct mesh_state;
/** Maximum number of modules in operation */
#define MAX_MODULE 2
@ -127,8 +129,12 @@ struct module_env {
*/
void (*remove_subqueries)(struct module_qstate* qstate);
/** region for temporary usage. May be cleared after operate() call. */
struct region* scratch;
/** internal data for daemon - worker thread. */
struct worker* worker;
/** mesh area with query state dependencies */
struct mesh_area* mesh;
/** allocation service */
struct alloc_cache* alloc;
/** random table to generate random numbers */
@ -185,20 +191,11 @@ enum module_ev {
struct module_qstate {
/** which query is being answered: name, type, class */
struct query_info qinfo;
/** hash value of the query qinfo */
hashvalue_t query_hash;
/** flags uint16 from query */
uint16_t query_flags;
/** edns data from the query */
struct edns_data edns;
/** buffer, store resulting reply here.
* May be cleared when module blocks. */
ldns_buffer* buf;
/** comm_reply contains server replies */
struct comm_reply* reply;
/** region for temporary usage. May be cleared when module blocks. */
struct region* scratch;
/** region for this query. Cleared when query process finishes. */
struct region* region;
@ -210,15 +207,22 @@ struct module_qstate {
void* minfo[MAX_MODULE];
/** environment for this query */
struct module_env* env;
/** worker related state for this query. NULL for (sub)queries that do
* not need to have answers sent to a client. */
struct work_query* work_info;
/** mesh related information for this query */
struct mesh_state* mesh_info;
/** ----- TO DELETE */
struct work_query* work_info;
/** hash value of the query qinfo */
hashvalue_t query_hash;
/** edns data from the query */
struct edns_data edns;
/** buffer, store resulting reply here.
* May be cleared when module blocks. */
ldns_buffer* buf;
/** parent query, only nonNULL for subqueries */
struct module_qstate* parent;
/** pointer to first subquery below this one; makes list with next */
struct module_qstate* subquery_first;
/** pointer to next sibling subquery (not above or below this one) */
struct module_qstate* subquery_next;
/** pointer to prev sibling subquery (not above or below this one) */