makefile nit and modstack.

git-svn-id: file:///svn/unbound/trunk@801 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-12-04 13:23:41 +00:00
parent 1c33240c16
commit 8892d4b63c
9 changed files with 301 additions and 156 deletions

View File

@ -138,7 +138,7 @@ unbound-checkconf: $(CHECKCONF_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(CHECKCONF_OBJ)) $(LIBS)
unbound-host: $(HOST_OBJ) lib
unbound-host: $(HOST_OBJ) libunbound.la
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(HOST_OBJ)) -L. -L.libs -lunbound $(LIBS)

View File

@ -51,10 +51,8 @@
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "services/localzone.h"
#include "services/modstack.h"
#include "util/module.h"
#include "iterator/iterator.h"
#include "validator/validator.h"
#include "util/fptr_wlist.h"
#include <signal.h>
/** How many quit requests happened. */
@ -129,7 +127,7 @@ daemon_init()
checklock_start();
ERR_load_crypto_strings();
daemon->need_to_exit = 0;
daemon->num_modules = 0;
modstack_init(&daemon->mods);
if(!(daemon->env = (struct module_env*)calloc(1,
sizeof(*daemon->env)))) {
free(daemon);
@ -158,136 +156,19 @@ daemon_open_shared_ports(struct daemon* daemon)
return 1;
}
/** count number of modules (words) in the string */
static int
count_modules(const char* s)
{
int num = 0;
if(!s)
return 0;
while(*s) {
/* skip whitespace */
while(*s && isspace((int)*s))
s++;
if(*s && !isspace((int)*s)) {
/* skip identifier */
num++;
while(*s && !isspace((int)*s))
s++;
}
}
return num;
}
/**
* Get funcblock for module name
* @param str: string with module name. Advanced to next value on success.
* @return funcblock or NULL on error.
*/
static struct module_func_block*
daemon_module_factory(const char** str)
{
/* these are the modules available */
int num = 2;
const char* names[] = {"iterator", "validator", NULL};
struct module_func_block* (*fb[])(void) =
{&iter_get_funcblock, &val_get_funcblock, NULL};
int i;
const char* s = *str;
while(*s && isspace((int)*s))
s++;
for(i=0; i<num; i++) {
if(strncmp(names[i], s, strlen(names[i])) == 0) {
s += strlen(names[i]);
*str = s;
return (*fb[i])();
}
}
return NULL;
}
/**
* Read config file module settings and set up the modfunc block
* @param daemon: the daemon.
* @return false on error
*/
static int
daemon_config_modules(struct daemon* daemon)
{
const char* str = daemon->cfg->module_conf;
int i;
verbose(VERB_DETAIL, "module config: \"%s\"", str);
daemon->num_modules = count_modules(str);
if(daemon->num_modules == 0) {
log_err("error: no modules specified");
return 0;
}
if(daemon->num_modules > MAX_MODULE) {
log_err("error: too many modules (%d max %d)",
daemon->num_modules, MAX_MODULE);
return 0;
}
daemon->modfunc = (struct module_func_block**)calloc((size_t)
daemon->num_modules, sizeof(struct module_func_block*));
if(!daemon->modfunc) {
log_err("out of memory");
return 0;
}
for(i=0; i<daemon->num_modules; i++) {
daemon->modfunc[i] = daemon_module_factory(&str);
if(!daemon->modfunc[i]) {
log_err("Unknown value for first module in: '%s'",
str);
return 0;
}
}
return 1;
}
/**
* Desetup the modules, deinit, delete.
* @param daemon: the daemon.
*/
static void
daemon_desetup_modules(struct daemon* daemon)
{
int i;
for(i=0; i<daemon->num_modules; i++) {
log_assert(fptr_whitelist_mod_deinit(
daemon->modfunc[i]->deinit));
(*daemon->modfunc[i]->deinit)(daemon->env, i);
}
daemon->num_modules = 0;
free(daemon->modfunc);
daemon->modfunc = 0;
}
/**
* Setup modules. Assigns ids and calls module_init.
* Setup modules. setup module stack.
* @param daemon: the daemon
*/
static void daemon_setup_modules(struct daemon* daemon)
{
int i;
if(daemon->num_modules != 0)
daemon_desetup_modules(daemon);
/* fixed setup of the modules */
if(!daemon_config_modules(daemon)) {
fatal_exit("failed to setup modules");
}
daemon->env->cfg = daemon->cfg;
daemon->env->alloc = &daemon->superalloc;
daemon->env->worker = NULL;
daemon->env->need_to_validate = 0; /* set by module init below */
for(i=0; i<daemon->num_modules; i++) {
verbose(VERB_OPS, "init module %d: %s",
i, daemon->modfunc[i]->name);
log_assert(fptr_whitelist_mod_init(daemon->modfunc[i]->init));
if(!(*daemon->modfunc[i]->init)(daemon->env, i)) {
fatal_exit("module init for module %s failed",
daemon->modfunc[i]->name);
}
if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf,
daemon->env)) {
fatal_exit("failed to setup modules");
}
}
@ -475,7 +356,7 @@ daemon_delete(struct daemon* daemon)
{
if(!daemon)
return;
daemon_desetup_modules(daemon);
modstack_desetup(&daemon->mods, daemon->env);
listening_ports_free(daemon->ports);
if(daemon->env) {
slabhash_delete(daemon->env->msg_cache);

View File

@ -44,6 +44,7 @@
#include "util/locks.h"
#include "util/alloc.h"
#include "services/modstack.h"
struct config_file;
struct worker;
struct listen_port;
@ -76,10 +77,8 @@ struct daemon {
struct alloc_cache superalloc;
/** the module environment master value, copied and changed by threads*/
struct module_env* env;
/** number of modules active, ids from 0 to num-1. */
int num_modules;
/** the module callbacks, array of num_modules length */
struct module_func_block** modfunc;
/** stack of module callbacks */
struct module_stack mods;
/** access control, which client IPs are allowed to connect */
struct acl_list* acl;
/** local authority zones */

View File

@ -967,8 +967,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
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, &worker->env);
worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
worker->env.detach_subs = &mesh_detach_subs;
worker->env.attach_sub = &mesh_attach_sub;
worker->env.kill_sub = &mesh_state_delete;

View File

@ -1,3 +1,8 @@
4 December 2007: Wouter
- minor Makefile fixup.
- moved module-stack code out of daemon/daemon into services/modstack,
preparing for code-reuse.
3 December 2007: Wouter
- changed checkconf/ to smallapp/ to make room for more support tools.
(such as unbound-host).

View File

@ -88,8 +88,7 @@ mesh_state_ref_compare(const void* ap, const void* bp)
}
struct mesh_area*
mesh_create(int num_modules, struct module_func_block** modfunc,
struct module_env* env)
mesh_create(struct module_stack* stack, struct module_env* env)
{
struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area));
if(!mesh) {
@ -102,8 +101,7 @@ mesh_create(int num_modules, struct module_func_block** modfunc,
log_err("mesh area alloc: out of memory");
return NULL;
}
mesh->num_modules = num_modules;
mesh->modfunc = modfunc;
mesh->mods = *stack;
mesh->env = env;
rbtree_init(&mesh->run, &mesh_state_compare);
rbtree_init(&mesh->all, &mesh_state_compare);
@ -237,7 +235,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
mstate->s.env = env;
mstate->s.mesh_info = mstate;
/* init modules */
for(i=0; i<env->mesh->num_modules; i++) {
for(i=0; i<env->mesh->mods.num; i++) {
mstate->s.minfo[i] = NULL;
mstate->s.ext_state[i] = module_state_initial;
}
@ -253,9 +251,9 @@ mesh_state_cleanup(struct mesh_state* mstate)
return;
/* de-init modules */
mesh = mstate->s.env->mesh;
for(i=0; i<mesh->num_modules; i++) {
log_assert(fptr_whitelist_mod_clear(mesh->modfunc[i]->clear));
(*mesh->modfunc[i]->clear)(&mstate->s, i);
for(i=0; i<mesh->mods.num; i++) {
log_assert(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear));
(*mesh->mods.mod[i]->clear)(&mstate->s, i);
mstate->s.minfo[i] = NULL;
mstate->s.ext_state[i] = module_finished;
}
@ -493,8 +491,8 @@ void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
(void)rbtree_insert(&mesh->run, &ref->s->run_node);
/* callback the function to inform super of result */
log_assert(fptr_whitelist_mod_inform_super(
mesh->modfunc[ref->s->s.curmod]->inform_super));
(*mesh->modfunc[ref->s->s.curmod]->inform_super)(&mstate->s,
mesh->mods.mod[ref->s->s.curmod]->inform_super));
(*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
ref->s->s.curmod, &ref->s->s);
}
}
@ -565,7 +563,7 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
if(s == module_wait_module) {
/* start next module */
mstate->s.curmod++;
if(mesh->num_modules == mstate->s.curmod) {
if(mesh->mods.num == mstate->s.curmod) {
log_err("Cannot pass to next module; at last module");
log_query_info(VERB_DETAIL, "pass error for qstate",
&mstate->s.qinfo);
@ -602,8 +600,8 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
while(mstate) {
/* run the module */
log_assert(fptr_whitelist_mod_operate(
mesh->modfunc[mstate->s.curmod]->operate));
(*mesh->modfunc[mstate->s.curmod]->operate)
mesh->mods.mod[mstate->s.curmod]->operate));
(*mesh->mods.mod[mstate->s.curmod]->operate)
(&mstate->s, ev, mstate->s.curmod, e);
/* examine results */
@ -611,7 +609,7 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
regional_free_all(mstate->s.env->scratch);
s = mstate->s.ext_state[mstate->s.curmod];
verbose(VERB_ALGO, "mesh_run: %s module exit state is %s",
mesh->modfunc[mstate->s.curmod]->name, strextstate(s));
mesh->mods.mod[mstate->s.curmod]->name, strextstate(s));
e = NULL;
if(mesh_continue(mesh, mstate, s, &ev))
continue;

View File

@ -50,6 +50,7 @@
#include "util/netevent.h"
#include "util/data/msgparse.h"
#include "util/module.h"
#include "services/modstack.h"
struct mesh_state;
struct mesh_reply;
struct query_info;
@ -67,10 +68,8 @@ struct timehist;
* Mesh of query states
*/
struct mesh_area {
/** the number of modules */
int num_modules;
/** the module callbacks, array of num_modules length (ref only) */
struct module_func_block** modfunc;
/** active module stack */
struct module_stack mods;
/** environment for new states */
struct module_env* env;
@ -160,14 +159,12 @@ struct mesh_reply {
/**
* Allocate mesh, to empty.
* @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.
* @param stack: module stack to activate, copied (as readonly reference).
* @param env: environment for new queries.
* @return mesh: the new mesh or NULL on error.
*/
struct mesh_area* mesh_create(int num_modules,
struct module_func_block** modfunc, struct module_env* env);
struct mesh_area* mesh_create(struct module_stack* stack,
struct module_env* env);
/**
* Delete mesh, and all query states and replies in it.

167
services/modstack.c Normal file
View File

@ -0,0 +1,167 @@
/*
* services/modstack.c - stack of modules
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to help maintain a stack of modules.
*/
#include "config.h"
#include "services/modstack.h"
#include "util/module.h"
#include "util/fptr_wlist.h"
#include "iterator/iterator.h"
#include "validator/validator.h"
/** count number of modules (words) in the string */
static int
count_modules(const char* s)
{
int num = 0;
if(!s)
return 0;
while(*s) {
/* skip whitespace */
while(*s && isspace((int)*s))
s++;
if(*s && !isspace((int)*s)) {
/* skip identifier */
num++;
while(*s && !isspace((int)*s))
s++;
}
}
return num;
}
void
modstack_init(struct module_stack* stack)
{
stack->num = 0;
stack->mod = NULL;
}
int
modstack_config(struct module_stack* stack, const char* module_conf)
{
int i;
verbose(VERB_DETAIL, "module config: \"%s\"", module_conf);
stack->num = count_modules(module_conf);
if(stack->num == 0) {
log_err("error: no modules specified");
return 0;
}
if(stack->num > MAX_MODULE) {
log_err("error: too many modules (%d max %d)",
stack->num, MAX_MODULE);
return 0;
}
stack->mod = (struct module_func_block**)calloc((size_t)
stack->num, sizeof(struct module_func_block*));
if(!stack->mod) {
log_err("out of memory");
return 0;
}
for(i=0; i<stack->num; i++) {
stack->mod[i] = module_factory(&module_conf);
if(!stack->mod[i]) {
log_err("Unknown value for next module: '%s'",
module_conf);
return 0;
}
}
return 1;
}
struct
module_func_block* module_factory(const char** str)
{
/* these are the modules available */
int num = 2;
const char* names[] = {"iterator", "validator", NULL};
struct module_func_block* (*fb[])(void) =
{&iter_get_funcblock, &val_get_funcblock, NULL};
int i;
const char* s = *str;
while(*s && isspace((int)*s))
s++;
for(i=0; i<num; i++) {
if(strncmp(names[i], s, strlen(names[i])) == 0) {
s += strlen(names[i]);
*str = s;
return (*fb[i])();
}
}
return NULL;
}
int
modstack_setup(struct module_stack* stack, const char* module_conf,
struct module_env* env)
{
int i;
if(stack->num != 0)
modstack_desetup(stack, env);
/* fixed setup of the modules */
if(!modstack_config(stack, module_conf)) {
return 0;
}
env->need_to_validate = 0; /* set by module init below */
for(i=0; i<stack->num; i++) {
verbose(VERB_OPS, "init module %d: %s",
i, stack->mod[i]->name);
log_assert(fptr_whitelist_mod_init(stack->mod[i]->init));
if(!(*stack->mod[i]->init)(env, i)) {
log_err("module init for module %s failed",
stack->mod[i]->name);
return 0;
}
}
return 1;
}
void
modstack_desetup(struct module_stack* stack, struct module_env* env)
{
int i;
for(i=0; i<stack->num; i++) {
log_assert(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
(*stack->mod[i]->deinit)(env, i);
}
stack->num = 0;
free(stack->mod);
stack->mod = NULL;
}

99
services/modstack.h Normal file
View File

@ -0,0 +1,99 @@
/*
* services/modstack.h - stack of modules
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to help maintain a stack of modules.
*/
#ifndef SERVICES_MODSTACK_H
#define SERVICES_MODSTACK_H
struct module_func_block;
struct module_env;
/**
* Stack of modules.
*/
struct module_stack {
/** the number of modules */
int num;
/** the module callbacks, array of num_modules length (ref only) */
struct module_func_block** mod;
};
/**
* Init a stack of modules
* @param stack: initialised as empty.
*/
void modstack_init(struct module_stack* stack);
/**
* Read config file module settings and set up the modfunc block
* @param stack: the stack of modules (empty before call).
* @param module_conf: string what modules to insert.
* @return false on error
*/
int modstack_config(struct module_stack* stack, const char* module_conf);
/**
* Get funcblock for module name
* @param str: string with module name. Advanced to next value on success.
* The string is assumed whitespace separated list of module names.
* @return funcblock or NULL on error.
*/
struct module_func_block* module_factory(const char** str);
/**
* Setup modules. Assigns ids and calls module_init.
* @param stack: if not empty beforehand, it will be desetup()ed.
* It is then modstack_configged().
* @param module_conf: string what modules to insert.
* @param env: module environment which is inited by the modules.
* environment should have a superalloc, cfg,
* env.need_to_validate is set by the modules.
* @return on false a module init failed.
*/
int modstack_setup(struct module_stack* stack, const char* module_conf,
struct module_env* env);
/**
* Desetup the modules, deinit, delete.
* @param stack: made empty.
* @param env: module env for module deinit() calls.
*/
void modstack_desetup(struct module_stack* stack, struct module_env* env);
#endif /* SERVICES_MODSTACK_H */