From e939a7689ffb28e1ec45b315e8ec2eb1068d72b4 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Fri, 22 Jun 2007 12:39:08 +0000 Subject: [PATCH] further mesh. git-svn-id: file:///svn/unbound/trunk@419 be551aaa-1e26-0410-a405-d3ace91eadb9 --- daemon/worker.c | 10 +++++- iterator/iterator.c | 16 ++++----- services/mesh.c | 80 ++++++++++++++++++++++++++++++++++++++++++--- services/mesh.h | 32 +++++++++++++----- util/module.h | 30 +++++++++-------- 5 files changed, 133 insertions(+), 35 deletions(-) diff --git a/daemon/worker.c b/daemon/worker.c index 46c3e74fc..c4683f726 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -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); diff --git a/iterator/iterator.c b/iterator/iterator.c index 0c977b337..ba11830ad 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -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 */ diff --git a/services/mesh.c b/services/mesh.c index d285b34f3..ef185f162 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -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; imesh->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; inum_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); +} diff --git a/services/mesh.h b/services/mesh.h index b0883b24f..c1260920f 100644 --- a/services/mesh.h +++ b/services/mesh.h @@ -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 */ diff --git a/util/module.h b/util/module.h index 27aca62a8..f10b97bef 100644 --- a/util/module.h +++ b/util/module.h @@ -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) */ -- 2.47.2