Commit bf8558bc authored by Martin Mareš's avatar Martin Mareš

Converted shutdown to a kind of reconfiguration, it's no more handled

as a exception in protocol state machines. Introduced a `shutdown'
CLI command. Killed few reconfiguration bugs.
parent ebc793a5
...@@ -30,8 +30,6 @@ Core ...@@ -30,8 +30,6 @@ Core
- config: useless rules when protocols disabled - config: useless rules when protocols disabled
- config: remove protocol startup priority hacks? - config: remove protocol startup priority hacks?
- config: better datetime format - config: better datetime format
- config: treat shutdown as reconfiguration to null config? (what about config of logging etc. ?)
- config: fix auto_router_id
- krt: rescan interfaces when route addition fails? - krt: rescan interfaces when route addition fails?
- krt: does PERSIST mode have any sense if kernel syncer is shut down as last? - krt: does PERSIST mode have any sense if kernel syncer is shut down as last?
......
...@@ -25,6 +25,7 @@ static jmp_buf conf_jmpbuf; ...@@ -25,6 +25,7 @@ static jmp_buf conf_jmpbuf;
struct config *config, *new_config, *old_config, *future_config; struct config *config, *new_config, *old_config, *future_config;
static event *config_event; static event *config_event;
int shutting_down;
struct config * struct config *
config_alloc(byte *name) config_alloc(byte *name)
...@@ -100,11 +101,13 @@ config_del_obstacle(struct config *c) ...@@ -100,11 +101,13 @@ config_del_obstacle(struct config *c)
} }
static int static int
global_commit(struct config *c, struct config *old) global_commit(struct config *new, struct config *old)
{ {
if (!old) if (!old)
return 0; return 0;
if (c->router_id != old->router_id) if (!new->router_id)
new->router_id = old->router_id;
if (new->router_id != old->router_id)
return 1; return 1;
return 0; return 0;
} }
...@@ -116,7 +119,7 @@ config_do_commit(struct config *c) ...@@ -116,7 +119,7 @@ config_do_commit(struct config *c)
DBG("do_commit\n"); DBG("do_commit\n");
old_config = config; old_config = config;
config = c; config = new_config = c;
if (old_config) if (old_config)
old_config->obstacle_count++; old_config->obstacle_count++;
DBG("sysdep_commit\n"); DBG("sysdep_commit\n");
...@@ -144,6 +147,8 @@ config_done(void *unused) ...@@ -144,6 +147,8 @@ config_done(void *unused)
DBG("config_done\n"); DBG("config_done\n");
for(;;) for(;;)
{ {
if (config->shutdown)
sysdep_shutdown_done();
log(L_INFO "Reconfigured"); log(L_INFO "Reconfigured");
if (old_config) if (old_config)
{ {
...@@ -171,6 +176,12 @@ config_commit(struct config *c) ...@@ -171,6 +176,12 @@ config_commit(struct config *c)
} }
if (old_config) /* Reconfiguration already in progress */ if (old_config) /* Reconfiguration already in progress */
{ {
if (shutting_down)
{
log(L_INFO "New configuration discarded due to shutdown");
config_free(c);
return CONF_SHUTDOWN;
}
if (future_config) if (future_config)
{ {
log(L_INFO "Queueing new configuration, ignoring the one already queued"); log(L_INFO "Queueing new configuration, ignoring the one already queued");
...@@ -194,6 +205,23 @@ config_commit(struct config *c) ...@@ -194,6 +205,23 @@ config_commit(struct config *c)
return CONF_PROGRESS; return CONF_PROGRESS;
} }
void
order_shutdown(void)
{
struct config *c;
if (shutting_down)
return;
log(L_INFO "Shutting down");
c = lp_alloc(config->mem, sizeof(struct config));
memcpy(c, config, sizeof(struct config));
init_list(&c->protos);
init_list(&c->tables);
c->shutdown = 1;
config_commit(c);
shutting_down = 1;
}
void void
cf_error(char *msg, ...) cf_error(char *msg, ...)
{ {
......
...@@ -27,6 +27,7 @@ struct config { ...@@ -27,6 +27,7 @@ struct config {
struct symbol **sym_hash; /* Lexer: symbol hash table */ struct symbol **sym_hash; /* Lexer: symbol hash table */
struct symbol **sym_fallback; /* Lexer: fallback symbol hash table */ struct symbol **sym_fallback; /* Lexer: fallback symbol hash table */
int obstacle_count; /* Number of items blocking freeing of this config */ int obstacle_count; /* Number of items blocking freeing of this config */
int shutdown; /* This is a pseudo-config for daemon shutdown */
}; };
/* Please don't use these variables in protocols. Use proto_config->global instead. */ /* Please don't use these variables in protocols. Use proto_config->global instead. */
...@@ -35,6 +36,8 @@ extern struct config *new_config; /* Configuration being parsed */ ...@@ -35,6 +36,8 @@ extern struct config *new_config; /* Configuration being parsed */
extern struct config *old_config; /* Old configuration when reconfiguration is in progress */ 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 */ extern struct config *future_config; /* New config held here if recon requested during recon */
extern int shutting_down;
struct config *config_alloc(byte *name); struct config *config_alloc(byte *name);
int config_parse(struct config *); int config_parse(struct config *);
int cli_parse(struct config *); int cli_parse(struct config *);
...@@ -43,10 +46,12 @@ int config_commit(struct config *); ...@@ -43,10 +46,12 @@ int config_commit(struct config *);
void cf_error(char *msg, ...) NORET; void cf_error(char *msg, ...) NORET;
void config_add_obstacle(struct config *); void config_add_obstacle(struct config *);
void config_del_obstacle(struct config *); void config_del_obstacle(struct config *);
void order_shutdown(void);
#define CONF_DONE 0 #define CONF_DONE 0
#define CONF_PROGRESS 1 #define CONF_PROGRESS 1
#define CONF_QUEUED 2 #define CONF_QUEUED 2
#define CONF_SHUTDOWN 3
/* Pools */ /* Pools */
...@@ -98,5 +103,6 @@ int cf_parse(void); ...@@ -98,5 +103,6 @@ int cf_parse(void);
void sysdep_preconfig(struct config *); void sysdep_preconfig(struct config *);
int sysdep_commit(struct config *, struct config *); int sysdep_commit(struct config *, struct config *);
void sysdep_shutdown_done(void);
#endif #endif
...@@ -11,6 +11,11 @@ Reply codes of BIRD command-line interface ...@@ -11,6 +11,11 @@ Reply codes of BIRD command-line interface
0000 OK 0000 OK
0001 Welcome 0001 Welcome
0002 Reading configuration 0002 Reading configuration
0003 Reconfigured
0004 Reconfiguration in progress
0005 Reconfiguration already in progress, queueing
0006 Reconfiguration ignored, shutting down
0007 Shutdown ordered
1000 BIRD version 1000 BIRD version
1001 Interface list 1001 Interface list
......
/* /*
* BIRD Internet Routing Daemon -- Basic Declarations * BIRD Internet Routing Daemon -- Basic Declarations
* *
* (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. * Can be freely distributed and used under the terms of the GNU GPL.
*/ */
...@@ -13,6 +13,4 @@ ...@@ -13,6 +13,4 @@
#include "lib/birdlib.h" #include "lib/birdlib.h"
#include "lib/ip.h" #include "lib/ip.h"
extern int shutting_down; /* The daemon is shutting down */
#endif #endif
...@@ -30,8 +30,6 @@ static list inactive_proto_list; ...@@ -30,8 +30,6 @@ static list inactive_proto_list;
static list initial_proto_list; static list initial_proto_list;
static list flush_proto_list; static list flush_proto_list;
static int proto_shutdown_counter;
static event *proto_flush_event; static event *proto_flush_event;
static char *p_states[] = { "DOWN", "START", "UP", "STOP" }; static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
...@@ -221,7 +219,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig) ...@@ -221,7 +219,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig)
{ {
struct proto *p = oc->proto; struct proto *p = oc->proto;
struct symbol *sym = cf_find_symbol(oc->name); struct symbol *sym = cf_find_symbol(oc->name);
if (sym && sym->class == SYM_PROTO) if (sym && sym->class == SYM_PROTO && !new->shutdown)
{ {
/* Found match, let's check if we can smoothly switch to new configuration */ /* Found match, let's check if we can smoothly switch to new configuration */
nc = sym->def; nc = sym->def;
...@@ -236,7 +234,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig) ...@@ -236,7 +234,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig)
{ {
/* Generic attributes match, try converting them and then ask the protocol */ /* Generic attributes match, try converting them and then ask the protocol */
p->debug = nc->debug; p->debug = nc->debug;
if (p->proto->reconfigure(p, nc)) if (p->proto->reconfigure && p->proto->reconfigure(p, nc))
{ {
DBG("\t%s: same\n", oc->name); DBG("\t%s: same\n", oc->name);
p->cf = nc; p->cf = nc;
...@@ -247,6 +245,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig) ...@@ -247,6 +245,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig)
/* Unsuccessful, force reconfig */ /* Unsuccessful, force reconfig */
DBG("\t%s: power cycling\n", oc->name); DBG("\t%s: power cycling\n", oc->name);
p->cf_new = nc; p->cf_new = nc;
nc->proto = p;
} }
else else
{ {
...@@ -290,7 +289,7 @@ proto_rethink_goal(struct proto *p) ...@@ -290,7 +289,7 @@ proto_rethink_goal(struct proto *p)
} }
/* Determine what state we want to reach */ /* Determine what state we want to reach */
if (p->disabled || shutting_down || p->reconfiguring) if (p->disabled || p->reconfiguring)
p->core_goal = FS_HUNGRY; p->core_goal = FS_HUNGRY;
else else
p->core_goal = FS_HAPPY; p->core_goal = FS_HAPPY;
...@@ -320,25 +319,6 @@ proto_rethink_goal(struct proto *p) ...@@ -320,25 +319,6 @@ proto_rethink_goal(struct proto *p)
} }
} }
void
protos_shutdown(void)
{
struct proto *p, *n;
debug("Protocol shutdown\n");
WALK_LIST_BACKWARDS_DELSAFE(p, n, inactive_proto_list)
if (p->core_state != FS_HUNGRY || p->proto_state != PS_DOWN)
{
proto_shutdown_counter++;
proto_rethink_goal(p);
}
WALK_LIST_BACKWARDS_DELSAFE(p, n, proto_list)
{
proto_shutdown_counter++;
proto_rethink_goal(p);
}
}
void void
protos_dump_all(void) protos_dump_all(void)
{ {
...@@ -389,8 +369,6 @@ proto_fell_down(struct proto *p) ...@@ -389,8 +369,6 @@ proto_fell_down(struct proto *p)
{ {
DBG("Protocol %s down\n", p->name); DBG("Protocol %s down\n", p->name);
rt_unlock_table(p->table); rt_unlock_table(p->table);
if (!--proto_shutdown_counter)
protos_shutdown_notify();
proto_rethink_goal(p); proto_rethink_goal(p);
} }
......
...@@ -56,7 +56,6 @@ void protos_preconfig(struct config *); ...@@ -56,7 +56,6 @@ void protos_preconfig(struct config *);
void protos_postconfig(struct config *); void protos_postconfig(struct config *);
void protos_commit(struct config *new, struct config *old, int force_restart); void protos_commit(struct config *new, struct config *old, int force_restart);
void protos_dump_all(void); void protos_dump_all(void);
void protos_shutdown(void);
extern list protocol_list; extern list protocol_list;
...@@ -251,10 +250,4 @@ struct announce_hook { ...@@ -251,10 +250,4 @@ struct announce_hook {
struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *); struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *);
/*
* Callback to sysdep code when shutdown is finished
*/
void protos_shutdown_notify(void);
#endif #endif
...@@ -513,7 +513,7 @@ rt_commit(struct config *new, struct config *old) ...@@ -513,7 +513,7 @@ rt_commit(struct config *new, struct config *old)
if (!ot->deleted) if (!ot->deleted)
{ {
struct symbol *sym = cf_find_symbol(o->name); struct symbol *sym = cf_find_symbol(o->name);
if (sym && sym->class == SYM_TABLE) if (sym && sym->class == SYM_TABLE && !new->shutdown)
{ {
DBG("\t%s: same\n", o->name); DBG("\t%s: same\n", o->name);
r = sym->def; r = sym->def;
...@@ -522,7 +522,7 @@ rt_commit(struct config *new, struct config *old) ...@@ -522,7 +522,7 @@ rt_commit(struct config *new, struct config *old)
} }
else else
{ {
DBG("\t%s: deleted", o->name); DBG("\t%s: deleted\n", o->name);
ot->deleted = old; ot->deleted = old;
config_add_obstacle(old); config_add_obstacle(old);
rt_lock_table(ot); rt_lock_table(ot);
......
...@@ -67,6 +67,9 @@ log_cat: ...@@ -67,6 +67,9 @@ log_cat:
CF_CLI(CONFIGURE, cfg_name, [<file>], [[Reload configuration]]) CF_CLI(CONFIGURE, cfg_name, [<file>], [[Reload configuration]])
{ cmd_reconfig($2); } ; { cmd_reconfig($2); } ;
CF_CLI(SHUTDOWN,,, [[Shut the daemon down]])
{ cli_msg(7, "Shutdown ordered"); order_shutdown(); } ;
cfg_name: cfg_name:
/* empty */ { $$ = NULL; } /* empty */ { $$ = NULL; }
| TEXT | TEXT
......
...@@ -29,8 +29,6 @@ ...@@ -29,8 +29,6 @@
#include "unix.h" #include "unix.h"
#include "krt.h" #include "krt.h"
int shutting_down;
/* /*
* Debugging * Debugging
*/ */
...@@ -153,6 +151,9 @@ cmd_reconfig(char *name) ...@@ -153,6 +151,9 @@ cmd_reconfig(char *name)
case CONF_PROGRESS: case CONF_PROGRESS:
cli_msg(4, "Reconfiguration in progress."); cli_msg(4, "Reconfiguration in progress.");
break; break;
case CONF_SHUTDOWN:
cli_msg(6, "Reconfiguration ignored, shutting down.");
break;
default: default:
cli_msg(5, "Reconfiguration already in progress, queueing new config"); cli_msg(5, "Reconfiguration already in progress, queueing new config");
} }
...@@ -275,12 +276,11 @@ void ...@@ -275,12 +276,11 @@ void
async_shutdown(void) async_shutdown(void)
{ {
debug("Shutting down...\n"); debug("Shutting down...\n");
shutting_down = 1; order_shutdown();
protos_shutdown();
} }
void void
protos_shutdown_notify(void) sysdep_shutdown_done(void)
{ {
unlink(PATH_CONTROL_SOCKET); unlink(PATH_CONTROL_SOCKET);
die("System shutdown completed"); die("System shutdown completed");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment