/* Globals Imported */
extern int r_first, r_last; /* first and last resources */
extern RES_TABLE resources[];
+extern RES **res_head;
extern RES_ITEM job_items[];
extern URES res_all;
drop(uid, gid); /* reduce priveleges if requested */
- /* signal(SIGHUP, reload_config); */
+ signal(SIGHUP, reload_config);
init_console_msg(working_directory);
term_msg(); /* terminate message handler */
stop_watchdog();
close_memory_pool(); /* release free memory in pool */
- sm_dump(false);
+ sm_dump(false);
exit(sig);
}
{
int num = r_last - r_first + 1;
RES **res_tab = reload_table[table].res_table;
- Dmsg1(000, "Freeing resources for table %d\n", table);
+ if (!res_tab) {
+ Dmsg1(100, "res_tab for table %d already released.\n", table);
+ return;
+ }
+ Dmsg1(100, "Freeing resources for table %d\n", table);
for (int j=0; j<num; j++) {
free_resource(res_tab[j], r_first + j);
}
* it goes to zero, no one is using the associated
* resource table, so free it.
*/
-static void reload_job_end_cb(JCR *jcr)
+static void reload_job_end_cb(JCR *jcr, void *ctx)
{
-#ifdef working
- int i = jcr->reload_id - 1;
- Dmsg1(000, "reload job_end JobId=%d\n", jcr->JobId);
+ int reload_id = (int)ctx;
+ Dmsg3(100, "reload job_end JobId=%d table=%d cnt=%d\n", jcr->JobId,
+ reload_id, reload_table[reload_id].job_count);
lock_jcr_chain();
LockRes();
- if (--reload_table[i].job_count <= 0) {
- free_saved_resources(i);
+ if (--reload_table[reload_id].job_count <= 0) {
+ free_saved_resources(reload_id);
}
UnlockRes();
unlock_jcr_chain();
-#endif
}
-static int find_free_table()
+static int find_free_reload_table_entry()
{
int table = -1;
for (int i=0; i < max_reloads; i++) {
/*
* If we get here, we have received a SIGHUP, which means to
* reread our configuration file.
+ *
+ * The algorithm used is as follows: we count how many jobs are
+ * running and mark the running jobs to make a callback on
+ * exiting. The old config is saved with the reload table
+ * id in a reload table. The new config file is read. Now, as
+ * each job exits, it calls back to the reload_job_end_cb(), which
+ * decrements the count of open jobs for the given reload table.
+ * When the count goes to zero, we release those resources.
+ * This allows us to have pointers into the resource table (from
+ * jobs), and once they exit and all the pointers are released, we
+ * release the old table. Note, if no new jobs are running since the
+ * last reload, then the old resources will be immediately release.
+ * A console is considered a job because it may have pointers to
+ * resources, but a SYSTEM job is not since it *should* not have any
+ * permanent pointers to jobs.
*/
extern "C"
void reload_config(int sig)
static bool already_here = false;
sigset_t set;
JCR *jcr;
- int njobs = 0;
+ int njobs = 0; /* number of running jobs */
int table, rtable;
- Jmsg(NULL, M_ERROR, 0, _("Command not implemented\n"));
- return;
-
if (already_here) {
abort(); /* Oops, recursion -> die */
}
already_here = true;
- sigfillset(&set);
+ sigemptyset(&set);
+ sigaddset(&set, SIGHUP);
sigprocmask(SIG_BLOCK, &set, NULL);
+// Jmsg(NULL, M_INFO, 0, "Entering experimental reload config code. Bug reports will not be accepted.\n");
+
lock_jcr_chain();
LockRes();
- table = find_free_table();
+ table = find_free_reload_table_entry();
if (table < 0) {
- Jmsg(NULL, M_ERROR, 0, _("Too many reload requests.\n"));
+ Jmsg(NULL, M_ERROR, 0, _("Too many open reload requests. Request ignored.\n"));
goto bail_out;
}
- /*
- * Hook all active jobs that are not already hooked (i.e.
- * reload_id == 0
- */
- foreach_jcr(jcr) {
- if (jcr->reload_id == 0) {
- reload_table[table].job_count++;
- jcr->reload_id = table + 1;
- job_end_push(jcr, reload_job_end_cb);
- njobs++;
- }
- free_locked_jcr(jcr);
- }
- Dmsg1(000, "Reload_config njobs=%d\n", njobs);
+ Dmsg1(100, "Reload_config njobs=%d\n", njobs);
reload_table[table].res_table = save_config_resources();
- Dmsg1(000, "Saved old config in table %d\n", table);
+ Dmsg1(100, "Saved old config in table %d\n", table);
- Dmsg0(000, "Calling parse config\n");
parse_config(configfile);
- Dmsg0(000, "Reloaded config file\n");
+ Dmsg0(100, "Reloaded config file\n");
if (!check_resources()) {
- rtable = find_free_table(); /* save new, bad table */
+ rtable = find_free_reload_table_entry(); /* save new, bad table */
if (rtable < 0) {
- Jmsg(NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
+ Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
+ Jmsg(NULL, M_ERROR_TERM, 0, _("Out of reload table entries. Giving up.\n"));
} else {
Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
}
int num = r_last - r_first + 1;
RES **res_tab = reload_table[table].res_table;
for (int i=0; i<num; i++) {
- resources[i].res_head = res_tab[i];
+ res_head[i] = res_tab[i];
}
table = rtable; /* release new, bad, saved table below */
+ } else {
+ /*
+ * Hook all active jobs so that they release this table
+ */
+ foreach_jcr(jcr) {
+ if (jcr->JobType != JT_SYSTEM) {
+ reload_table[table].job_count++;
+ job_end_push(jcr, reload_job_end_cb, (void *)table);
+ njobs++;
+ }
+ free_locked_jcr(jcr);
+ }
}
/* Reset globals */
SDConnectTimeout = director->SDConnectTimeout;
Dmsg0(0, "Director's configuration file reread.\n");
- /* Now release saved resources */
- free_saved_resources(table);
+ /* Now release saved resources, if no jobs using the resources */
+ if (njobs == 0) {
+ free_saved_resources(table);
+ }
bail_out:
UnlockRes();
job->hdr.name, job_items[i].name, *def_svalue, i, offset);
svalue = (char **)((char *)job + offset);
if (*svalue) {
- Dmsg1(000, "Hey something is wrong. p=0x%lu\n", *svalue);
+ Pmsg1(000, "Hey something is wrong. p=0x%lu\n", *svalue);
}
*svalue = bstrdup(*def_svalue);
set_bit(i, job->hdr.item_present);
job->hdr.name, job_items[i].name, i, offset);
svalue = (char **)((char *)job + offset);
if (*svalue) {
- Dmsg1(000, "Hey something is wrong. p=0x%lu\n", *svalue);
+ Pmsg1(000, "Hey something is wrong. p=0x%lu\n", *svalue);
}
*svalue = *def_svalue;
set_bit(i, job->hdr.item_present);