diff options
Diffstat (limited to 'conf')
-rw-r--r-- | conf/conf.c | 121 | ||||
-rw-r--r-- | conf/conf.h | 18 |
2 files changed, 129 insertions, 10 deletions
diff --git a/conf/conf.c b/conf/conf.c index ea65183..1c5401b 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -1,7 +1,7 @@ /* * BIRD Internet Routing Daemon -- Configuration File Handling * - * (c) 1999 Martin Mares <mj@ucw.cz> + * (c) 1998--2000 Martin Mares <mj@ucw.cz> * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -9,18 +9,22 @@ #include <setjmp.h> #include <stdarg.h> +#define LOCAL_DEBUG + #include "nest/bird.h" #include "nest/route.h" #include "nest/protocol.h" #include "nest/iface.h" #include "lib/resource.h" #include "lib/string.h" +#include "lib/event.h" #include "conf/conf.h" #include "filter/filter.h" static jmp_buf conf_jmpbuf; -struct config *config, *new_config; +struct config *config, *new_config, *old_config, *future_config; +static event *config_event; struct config * config_alloc(byte *name) @@ -77,12 +81,117 @@ config_free(struct config *c) } void -config_commit(struct config *c) +config_add_obstacle(struct config *c) +{ + DBG("+++ adding obstacle %d\n", c->obstacle_count); + c->obstacle_count++; +} + +void +config_del_obstacle(struct config *c) { + DBG("+++ deleting obstacle %d\n", c->obstacle_count); + c->obstacle_count--; + if (!c->obstacle_count) + { + ASSERT(config_event); + ev_schedule(config_event); + } +} + +static int +global_commit(struct config *c, struct config *old) +{ + if (!old) + return 0; + if (c->router_id != old->router_id) + return 1; + return 0; +} + +static int +config_do_commit(struct config *c) +{ + int force_restart, nobs; + + DBG("do_commit\n"); + old_config = config; config = c; - sysdep_commit(c); - rt_commit(c); - protos_commit(c); + if (old_config) + old_config->obstacle_count++; + DBG("sysdep_commit\n"); + force_restart = sysdep_commit(c, old_config); + DBG("global_commit\n"); + force_restart |= global_commit(c, old_config); + DBG("rt_commit\n"); + rt_commit(c, old_config); + DBG("protos_commit\n"); + protos_commit(c, old_config, force_restart); + new_config = NULL; /* Just to be sure nobody uses that now */ + if (old_config) + nobs = --old_config->obstacle_count; + else + nobs = 0; + DBG("do_commit finished with %d obstacles remaining\n", nobs); + return !nobs; +} + +static int +config_done(void *unused) +{ + struct config *c; + + DBG("config_done\n"); + for(;;) + { + log(L_INFO "Reconfigured"); + if (old_config) + { + config_free(old_config); + old_config = NULL; + } + if (!future_config) + break; + c = future_config; + future_config = NULL; + log(L_INFO "Switching to queued configuration..."); + if (!config_do_commit(c)) + break; + } + return 0; +} + +int +config_commit(struct config *c) +{ + if (!config) /* First-time configuration */ + { + config_do_commit(c); + return CONF_DONE; + } + if (old_config) /* Reconfiguration already in progress */ + { + if (future_config) + { + log(L_INFO "Queueing new configuration, ignoring the one already queued"); + config_free(future_config); + } + else + log(L_INFO "Queued new configuration"); + future_config = c; + return CONF_QUEUED; + } + if (config_do_commit(c)) + { + config_done(NULL); + return CONF_DONE; + } + if (!config_event) + { + config_event = ev_new(&root_pool); + config_event->hook = config_done; + } + return CONF_PROGRESS; } void diff --git a/conf/conf.h b/conf/conf.h index b0a3811..7d13ae9 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -1,7 +1,7 @@ /* * BIRD Internet Routing Daemon -- Configuration File Handling * - * (c) 1998--1999 Martin Mares <mj@ucw.cz> + * (c) 1998--2000 Martin Mares <mj@ucw.cz> * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -26,17 +26,27 @@ struct config { char *file_name; /* Name of configuration file */ struct symbol **sym_hash; /* Lexer: symbol hash table */ struct symbol **sym_fallback; /* Lexer: fallback symbol hash table */ + int obstacle_count; /* Number of items blocking freeing of this config */ }; -extern struct config *config, *new_config; /* Please don't use these variables in protocols. Use proto_config->global instead. */ +extern struct config *config; /* Currently active configuration */ +extern struct config *new_config; /* Configuration being parsed */ +extern struct config *old_config; /* Old configuration when reconfiguration is in progress */ +extern struct config *future_config; /* New config held here if recon requested during recon */ struct config *config_alloc(byte *name); int config_parse(struct config *); int cli_parse(struct config *); void config_free(struct config *); -void config_commit(struct config *); +int config_commit(struct config *); void cf_error(char *msg, ...) NORET; +void config_add_obstacle(struct config *); +void config_del_obstacle(struct config *); + +#define CONF_DONE 0 +#define CONF_PROGRESS 1 +#define CONF_QUEUED 2 /* Pools */ @@ -87,6 +97,6 @@ int cf_parse(void); /* Sysdep hooks */ void sysdep_preconfig(struct config *); -void sysdep_commit(struct config *); +int sysdep_commit(struct config *, struct config *); #endif |