]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/dird.c
Use light weight non-recursive locking on jcr chain.
[bacula/bacula] / bacula / src / dird / dird.c
1 /*
2  *
3  *   Bacula Director daemon -- this is the main program
4  *
5  *     Kern Sibbald, March MM
6  *
7  *   Version $Id$
8  */
9 /*
10    Copyright (C) 2000-2005 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    version 2 as ammended with additional clauses defined in the
15    file LICENSE in the main source directory.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
20    the file LICENSE for additional details.
21
22  */
23
24 #include "bacula.h"
25 #include "dird.h"
26
27 /* Forward referenced subroutines */
28 static void terminate_dird(int sig);
29 static int check_resources();
30
31 /* Exported subroutines */
32
33 extern "C" void reload_config(int sig);
34
35
36 /* Imported subroutines */
37 JCR *wait_for_next_job(char *runjob);
38 void term_scheduler();
39 void term_ua_server();
40 void start_UA_server(dlist *addrs);
41 void init_job_server(int max_workers);
42 void term_job_server();
43 void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass);
44 void store_level(LEX *lc, RES_ITEM *item, int index, int pass);
45 void store_replace(LEX *lc, RES_ITEM *item, int index, int pass);
46 void init_device_resources();
47
48 static char *configfile = NULL;
49 static char *runjob = NULL;
50 static int background = 1;
51 static void init_reload(void);
52
53 /* Globals Exported */
54 DIRRES *director;                     /* Director resource */
55 int FDConnectTimeout;
56 int SDConnectTimeout;
57
58 /* Globals Imported */
59 extern int r_first, r_last;           /* first and last resources */
60 extern RES_TABLE resources[];
61 extern RES **res_head;
62 extern RES_ITEM job_items[];
63 extern URES res_all;
64
65
66 #define CONFIG_FILE "./bacula-dir.conf" /* default configuration file */
67
68 static void usage()
69 {
70    fprintf(stderr, _(
71 "Copyright (C) 2000-2005 Kern Sibbald.\n"
72 "\nVersion: " VERSION " (" BDATE ")\n\n"
73 "Usage: dird [-f -s] [-c config_file] [-d debug_level] [config_file]\n"
74 "       -c <file>   set configuration file to file\n"
75 "       -dnn        set debug level to nn\n"
76 "       -f          run in foreground (for debugging)\n"
77 "       -g          groupid\n"
78 "       -r <job>    run <job> now\n"
79 "       -s          no signals\n"
80 "       -t          test - read configuration and exit\n"
81 "       -u          userid\n"
82 "       -v          verbose user messages\n"
83 "       -?          print this message.\n"
84 "\n"));
85
86    exit(1);
87 }
88
89
90 /*********************************************************************
91  *
92  *         Main Bacula Server program
93  *
94  */
95 int main (int argc, char *argv[])
96 {
97    int ch;
98    JCR *jcr;
99    int no_signals = FALSE;
100    int test_config = FALSE;
101    char *uid = NULL;
102    char *gid = NULL;
103
104    init_stack_dump();
105    my_name_is(argc, argv, "bacula-dir");
106    textdomain("bacula");
107    init_msg(NULL, NULL);              /* initialize message handler */
108    init_reload();
109    daemon_start_time = time(NULL);
110
111    while ((ch = getopt(argc, argv, "c:d:fg:r:stu:v?")) != -1) {
112       switch (ch) {
113       case 'c':                    /* specify config file */
114          if (configfile != NULL) {
115             free(configfile);
116          }
117          configfile = bstrdup(optarg);
118          break;
119
120       case 'd':                    /* set debug level */
121          debug_level = atoi(optarg);
122          if (debug_level <= 0) {
123             debug_level = 1;
124          }
125          Dmsg1(0, "Debug level = %d\n", debug_level);
126          break;
127
128       case 'f':                    /* run in foreground */
129          background = FALSE;
130          break;
131
132       case 'g':                    /* set group id */
133          gid = optarg;
134          break;
135
136       case 'r':                    /* run job */
137          if (runjob != NULL) {
138             free(runjob);
139          }
140          if (optarg) {
141             runjob = bstrdup(optarg);
142          }
143          break;
144
145       case 's':                    /* turn off signals */
146          no_signals = TRUE;
147          break;
148
149       case 't':                    /* test config */
150          test_config = TRUE;
151          break;
152
153       case 'u':                    /* set uid */
154          uid = optarg;
155          break;
156
157       case 'v':                    /* verbose */
158          verbose++;
159          break;
160
161       case '?':
162       default:
163          usage();
164
165       }
166    }
167    argc -= optind;
168    argv += optind;
169
170    if (!no_signals) {
171       init_signals(terminate_dird);
172    }
173
174    if (argc) {
175       if (configfile != NULL) {
176          free(configfile);
177       }
178       configfile = bstrdup(*argv);
179       argc--;
180       argv++;
181    }
182    if (argc) {
183       usage();
184    }
185
186    if (configfile == NULL) {
187       configfile = bstrdup(CONFIG_FILE);
188    }
189
190    parse_config(configfile);
191
192    if (init_tls() != 0) {
193       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("TLS library initialization failed.\n"));
194    }
195
196    if (!check_resources()) {
197       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
198    }
199
200    if (test_config) {
201       terminate_dird(0);
202    }
203
204    my_name_is(0, NULL, director->hdr.name);    /* set user defined name */
205
206    FDConnectTimeout = (int)director->FDConnectTimeout;
207    SDConnectTimeout = (int)director->SDConnectTimeout;
208
209    if (background) {
210       daemon_start();
211       init_stack_dump();              /* grab new pid */
212    }
213
214    /* Create pid must come after we are a daemon -- so we have our final pid */
215    create_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
216    read_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
217
218    drop(uid, gid);                    /* reduce priveleges if requested */
219
220    signal(SIGHUP, reload_config);
221
222    init_console_msg(working_directory);
223
224    init_python_interpreter(director->hdr.name, director->scripts_directory, 
225        "DirStartUp");
226
227    set_thread_concurrency(director->MaxConcurrentJobs * 2 +
228       4 /* UA */ + 4 /* sched+watchdog+jobsvr+misc */);
229
230    Dmsg0(200, "Start UA server\n");
231    start_UA_server(director->DIRaddrs);
232
233    start_watchdog();                  /* start network watchdog thread */
234
235    init_jcr_subsystem();              /* start JCR watchdogs etc. */
236
237    init_job_server(director->MaxConcurrentJobs);
238
239    Dmsg0(200, "wait for next job\n");
240    /* Main loop -- call scheduler to get next job to run */
241    while ((jcr = wait_for_next_job(runjob))) {
242       run_job(jcr);                   /* run job */
243       free_jcr(jcr);                  /* release jcr */
244       if (runjob) {                   /* command line, run a single job? */
245          break;                       /* yes, terminate */
246       }
247    }
248
249    terminate_dird(0);
250 }
251
252 /* Cleanup and then exit */
253 static void terminate_dird(int sig)
254 {
255    static bool already_here = false;
256
257    if (already_here) {                /* avoid recursive temination problems */
258       exit(1);
259    }
260    already_here = true;
261    generate_daemon_event(NULL, "Exit");
262    write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
263    delete_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
264 // signal(SIGCHLD, SIG_IGN);          /* don't worry about children now */
265    term_scheduler();
266    term_job_server();
267    if (runjob) {
268       free(runjob);
269    }
270    if (configfile != NULL) {
271       free(configfile);
272    }
273    if (debug_level > 5) {
274       print_memory_pool_stats();
275    }
276    free_config_resources();
277    term_ua_server();
278    term_msg();                        /* terminate message handler */
279    stop_watchdog();
280    cleanup_tls();
281    close_memory_pool();               /* release free memory in pool */
282    sm_dump(false);
283    exit(sig);
284 }
285
286 struct RELOAD_TABLE {
287    int job_count;
288    RES **res_table;
289 };
290
291 static const int max_reloads = 10;
292 static RELOAD_TABLE reload_table[max_reloads];
293
294 static void init_reload(void)
295 {
296    for (int i=0; i < max_reloads; i++) {
297       reload_table[i].job_count = 0;
298       reload_table[i].res_table = NULL;
299    }
300 }
301
302 static void free_saved_resources(int table)
303 {
304    int num = r_last - r_first + 1;
305    RES **res_tab = reload_table[table].res_table;
306    if (!res_tab) {
307       Dmsg1(100, "res_tab for table %d already released.\n", table);
308       return;
309    }
310    Dmsg1(100, "Freeing resources for table %d\n", table);
311    for (int j=0; j<num; j++) {
312       free_resource(res_tab[j], r_first + j);
313    }
314    free(res_tab);
315    reload_table[table].job_count = 0;
316    reload_table[table].res_table = NULL;
317 }
318
319 /*
320  * Called here at the end of every job that was
321  * hooked decrementing the active job_count. When
322  * it goes to zero, no one is using the associated
323  * resource table, so free it.
324  */
325 static void reload_job_end_cb(JCR *jcr, void *ctx)
326 {
327    int reload_id = (int)((long int)ctx);
328    Dmsg3(100, "reload job_end JobId=%d table=%d cnt=%d\n", jcr->JobId,
329       reload_id, reload_table[reload_id].job_count);
330    lock_jobs();
331    LockRes();
332    if (--reload_table[reload_id].job_count <= 0) {
333       free_saved_resources(reload_id);
334    }
335    UnlockRes();
336    unlock_jobs();
337 }
338
339 static int find_free_reload_table_entry()
340 {
341    int table = -1;
342    for (int i=0; i < max_reloads; i++) {
343       if (reload_table[i].res_table == NULL) {
344          table = i;
345          break;
346       }
347    }
348    return table;
349 }
350
351 /*
352  * If we get here, we have received a SIGHUP, which means to
353  *    reread our configuration file.
354  *
355  * The algorithm used is as follows: we count how many jobs are
356  *   running and mark the running jobs to make a callback on
357  *   exiting. The old config is saved with the reload table
358  *   id in a reload table. The new config file is read. Now, as
359  *   each job exits, it calls back to the reload_job_end_cb(), which
360  *   decrements the count of open jobs for the given reload table.
361  *   When the count goes to zero, we release those resources.
362  *   This allows us to have pointers into the resource table (from
363  *   jobs), and once they exit and all the pointers are released, we
364  *   release the old table. Note, if no new jobs are running since the
365  *   last reload, then the old resources will be immediately release.
366  *   A console is considered a job because it may have pointers to
367  *   resources, but a SYSTEM job is not since it *should* not have any
368  *   permanent pointers to jobs.
369  */
370 extern "C"
371 void reload_config(int sig)
372 {
373    static bool already_here = false;
374    sigset_t set;
375    JCR *jcr;
376    int njobs = 0;                     /* number of running jobs */
377    int table, rtable;
378    bool ok;       
379
380    if (already_here) {
381       abort();                        /* Oops, recursion -> die */
382    }
383    already_here = true;
384    sigemptyset(&set);
385    sigaddset(&set, SIGHUP);
386    sigprocmask(SIG_BLOCK, &set, NULL);
387
388    lock_jobs();
389    LockRes();
390
391    table = find_free_reload_table_entry();
392    if (table < 0) {
393       Jmsg(NULL, M_ERROR, 0, _("Too many open reload requests. Request ignored.\n"));
394       goto bail_out;
395    }
396
397    Dmsg1(100, "Reload_config njobs=%d\n", njobs);
398    reload_table[table].res_table = save_config_resources();
399    Dmsg1(100, "Saved old config in table %d\n", table);
400
401    ok = parse_config(configfile, 0);  /* no exit on error */
402
403    Dmsg0(100, "Reloaded config file\n");
404    if (!ok || !check_resources()) {
405       rtable = find_free_reload_table_entry();    /* save new, bad table */
406       if (rtable < 0) {
407          Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
408          Jmsg(NULL, M_ERROR_TERM, 0, _("Out of reload table entries. Giving up.\n"));
409       } else {
410          Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
411          Jmsg(NULL, M_ERROR, 0, _("Resetting previous configuration.\n"));
412       }
413       reload_table[rtable].res_table = save_config_resources();
414       /* Now restore old resoure values */
415       int num = r_last - r_first + 1;
416       RES **res_tab = reload_table[table].res_table;
417       for (int i=0; i<num; i++) {
418          res_head[i] = res_tab[i];
419       }
420       table = rtable;                 /* release new, bad, saved table below */
421    } else {
422       /*
423        * Hook all active jobs so that they release this table
424        */
425       foreach_jcr(jcr) {
426          if (jcr->JobType != JT_SYSTEM) {
427             reload_table[table].job_count++;
428             job_end_push(jcr, reload_job_end_cb, (void *)((long int)table));
429             njobs++;
430          }
431          free_jcr(jcr);
432       }
433    }
434
435    /* Reset globals */
436    set_working_directory(director->working_directory);
437    FDConnectTimeout = director->FDConnectTimeout;
438    SDConnectTimeout = director->SDConnectTimeout;
439    Dmsg0(0, "Director's configuration file reread.\n");
440
441    /* Now release saved resources, if no jobs using the resources */
442    if (njobs == 0) {
443       free_saved_resources(table);
444    }
445
446 bail_out:
447    UnlockRes();
448    unlock_jobs();
449    sigprocmask(SIG_UNBLOCK, &set, NULL);
450    signal(SIGHUP, reload_config);
451    already_here = false;
452 }
453
454 /*
455  * Make a quick check to see that we have all the
456  * resources needed.
457  *
458  *  **** FIXME **** this routine could be a lot more
459  *   intelligent and comprehensive.
460  */
461 static int check_resources()
462 {
463    bool OK = true;
464    JOB *job;
465
466    LockRes();
467
468    job = (JOB *)GetNextRes(R_JOB, NULL);
469    director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
470    if (!director) {
471       Jmsg(NULL, M_FATAL, 0, _("No Director resource defined in %s\n"
472 "Without that I don't know who I am :-(\n"), configfile);
473       OK = false;
474    } else {
475       set_working_directory(director->working_directory);
476       if (!director->messages) {       /* If message resource not specified */
477          director->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
478          if (!director->messages) {
479             Jmsg(NULL, M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile);
480             OK = false;
481          }
482       }
483       if (GetNextRes(R_DIRECTOR, (RES *)director) != NULL) {
484          Jmsg(NULL, M_FATAL, 0, _("Only one Director resource permitted in %s\n"),
485             configfile);
486          OK = false;
487       }
488 #ifdef HAVE_TLS
489       /* tls_require implies tls_enable */
490       if (director->tls_require) {
491          director->tls_enable = true;
492       }
493
494       if (!director->tls_certfile && director->tls_enable) {
495          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
496             director->hdr.name, configfile);
497          OK = false;
498       }
499
500       if (!director->tls_keyfile && director->tls_enable) {
501          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
502             director->hdr.name, configfile);
503          OK = false;
504       }
505
506       if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable && director->tls_verify_peer) {
507          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
508               " Certificate Dir\" are defined for Director \"%s\" in %s."
509               " At least one CA certificate store is required"
510               " when using \"TLS Verify Peer\".\n"),
511               director->hdr.name, configfile);
512          OK = false;
513       }
514
515       /* If everything is well, attempt to initialize our per-resource TLS context */
516       if (OK && (director->tls_enable || director->tls_require)) {
517          /* Initialize TLS context:
518           * Args: CA certfile, CA certdir, Certfile, Keyfile,
519           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
520          director->tls_ctx = new_tls_context(director->tls_ca_certfile,
521             director->tls_ca_certdir, director->tls_certfile,
522             director->tls_keyfile, NULL, NULL, director->tls_dhfile,
523             director->tls_verify_peer);
524          
525          if (!director->tls_ctx) {
526             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
527                  director->hdr.name, configfile);
528             OK = false;
529          }
530       }
531 #endif /* HAVE_TLS */
532    }
533
534    if (!job) {
535       Jmsg(NULL, M_FATAL, 0, _("No Job records defined in %s\n"), configfile);
536       OK = false;
537    }
538    foreach_res(job, R_JOB) {
539       int i;
540
541       if (job->jobdefs) {
542          /* Handle Storage alists specifically */
543          JOB *jobdefs = job->jobdefs;
544          if (jobdefs->storage && !job->storage) {
545             STORE *st;
546             job->storage = New(alist(10, not_owned_by_alist));
547             foreach_alist(st, jobdefs->storage) {
548                job->storage->append(st);
549             }
550          }
551
552          /* Transfer default items from JobDefs Resource */
553          for (i=0; job_items[i].name; i++) {
554             char **def_svalue, **svalue;  /* string value */
555             int *def_ivalue, *ivalue;     /* integer value */
556             int64_t *def_lvalue, *lvalue; /* 64 bit values */
557             uint32_t offset;
558
559             Dmsg4(1400, "Job \"%s\", field \"%s\" bit=%d def=%d\n",
560                 job->hdr.name, job_items[i].name,
561                 bit_is_set(i, job->hdr.item_present),
562                 bit_is_set(i, job->jobdefs->hdr.item_present));
563
564             if (!bit_is_set(i, job->hdr.item_present) &&
565                  bit_is_set(i, job->jobdefs->hdr.item_present)) {
566                Dmsg2(400, "Job \"%s\", field \"%s\": getting default.\n",
567                  job->hdr.name, job_items[i].name);
568                offset = (char *)(job_items[i].value) - (char *)&res_all;
569                /*
570                 * Handle strings and directory strings
571                 */
572                if (job_items[i].handler == store_str ||
573                    job_items[i].handler == store_dir) {
574                   def_svalue = (char **)((char *)(job->jobdefs) + offset);
575                   Dmsg5(400, "Job \"%s\", field \"%s\" def_svalue=%s item %d offset=%u\n",
576                        job->hdr.name, job_items[i].name, *def_svalue, i, offset);
577                   svalue = (char **)((char *)job + offset);
578                   if (*svalue) {
579                      Pmsg1(000, "Hey something is wrong. p=0x%lu\n", *svalue);
580                   }
581                   *svalue = bstrdup(*def_svalue);
582                   set_bit(i, job->hdr.item_present);
583                /*
584                 * Handle resources
585                 */
586                } else if (job_items[i].handler == store_res) {
587                   def_svalue = (char **)((char *)(job->jobdefs) + offset);
588                   Dmsg4(400, "Job \"%s\", field \"%s\" item %d offset=%u\n",
589                        job->hdr.name, job_items[i].name, i, offset);
590                   svalue = (char **)((char *)job + offset);
591                   if (*svalue) {
592                      Pmsg1(000, "Hey something is wrong. p=0x%lu\n", *svalue);
593                   }
594                   *svalue = *def_svalue;
595                   set_bit(i, job->hdr.item_present);
596                /*
597                 * Handle alist resources
598                 */
599                } else if (job_items[i].handler == store_alist_res) {
600                   if (bit_is_set(i, job->jobdefs->hdr.item_present)) {
601                      set_bit(i, job->hdr.item_present);
602                   }
603                /*
604                 * Handle integer fields
605                 *    Note, our store_yesno does not handle bitmaped fields
606                 */
607                } else if (job_items[i].handler == store_yesno   ||
608                           job_items[i].handler == store_pint    ||
609                           job_items[i].handler == store_jobtype ||
610                           job_items[i].handler == store_level   ||
611                           job_items[i].handler == store_pint    ||
612                           job_items[i].handler == store_replace) {
613                   def_ivalue = (int *)((char *)(job->jobdefs) + offset);
614                   Dmsg5(400, "Job \"%s\", field \"%s\" def_ivalue=%d item %d offset=%u\n",
615                        job->hdr.name, job_items[i].name, *def_ivalue, i, offset);
616                   ivalue = (int *)((char *)job + offset);
617                   *ivalue = *def_ivalue;
618                   set_bit(i, job->hdr.item_present);
619                /*
620                 * Handle 64 bit integer fields
621                 */
622                } else if (job_items[i].handler == store_time   ||
623                           job_items[i].handler == store_size   ||
624                           job_items[i].handler == store_int64) {
625                   def_lvalue = (int64_t *)((char *)(job->jobdefs) + offset);
626                   Dmsg5(400, "Job \"%s\", field \"%s\" def_lvalue=%" lld " item %d offset=%u\n",
627                        job->hdr.name, job_items[i].name, *def_lvalue, i, offset);
628                   lvalue = (int64_t *)((char *)job + offset);
629                   *lvalue = *def_lvalue;
630                   set_bit(i, job->hdr.item_present);
631                }
632             }
633          }
634       }
635       /*
636        * Ensure that all required items are present
637        */
638       for (i=0; job_items[i].name; i++) {
639          if (job_items[i].flags & ITEM_REQUIRED) {
640                if (!bit_is_set(i, job->hdr.item_present)) {
641                   Jmsg(NULL, M_FATAL, 0, "\"%s\" directive in Job \"%s\" resource is required, but not found.\n",
642                     job_items[i].name, job->hdr.name);
643                   OK = false;
644                 }
645          }
646          /* If this triggers, take a look at lib/parse_conf.h */
647          if (i >= MAX_RES_ITEMS) {
648             Emsg0(M_ERROR_TERM, 0, "Too many items in Job resource\n");
649          }
650       }
651    } /* End loop over Job res */
652
653    /* Loop over databases */
654    CAT *catalog;
655    foreach_res(catalog, R_CATALOG) {
656       B_DB *db;
657       /*
658        * Make sure we can open catalog, otherwise print a warning
659        * message because the server is probably not running.
660        */
661       db = db_init_database(NULL, catalog->db_name, catalog->db_user,
662                          catalog->db_password, catalog->db_address,
663                          catalog->db_port, catalog->db_socket,
664                          catalog->mult_db_connections);
665       if (!db || !db_open_database(NULL, db)) {
666          Jmsg(NULL, M_FATAL, 0, _("Could not open database \"%s\".\n"),
667               catalog->db_name);
668          if (db) {
669             Jmsg(NULL, M_FATAL, 0, _("%s"), db_strerror(db));
670          }
671          OK = false;
672          continue;
673       }
674
675       /* Loop over all pools, defining/updating them in each database */
676       POOL *pool;
677       foreach_res(pool, R_POOL) {
678          create_pool(NULL, db, pool, POOL_OP_UPDATE);  /* update request */
679       }
680
681       STORE *store;
682       foreach_res(store, R_STORAGE) {
683          STORAGE_DBR sr;
684          MEDIATYPE_DBR mr;
685          if (store->media_type) {
686             bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
687             mr.ReadOnly = 0;
688             db_create_mediatype_record(NULL, db, &mr);
689          } else {
690             mr.MediaTypeId = 0;
691          }
692          bstrncpy(sr.Name, store->name(), sizeof(sr.Name));
693          sr.AutoChanger = store->autochanger;
694          db_create_storage_record(NULL, db, &sr);
695          store->StorageId = sr.StorageId;   /* set storage Id */
696          if (!sr.created) {                 /* if not created, update it */
697             db_update_storage_record(NULL, db, &sr);
698          }
699
700 #ifdef HAVE_TLS
701          /* tls_require implies tls_enable */
702          if (store->tls_require) {
703             store->tls_enable = true;
704          } 
705
706          if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && store->tls_enable) {
707             Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
708                  " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s.\n"),
709                  store->hdr.name, configfile);
710             OK = false;
711          }
712
713          /* If everything is well, attempt to initialize our per-resource TLS context */
714          if (OK && (store->tls_enable || store->tls_require)) {
715            /* Initialize TLS context:
716             * Args: CA certfile, CA certdir, Certfile, Keyfile,
717             * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
718             store->tls_ctx = new_tls_context(store->tls_ca_certfile,
719                store->tls_ca_certdir, store->tls_certfile,
720                store->tls_keyfile, NULL, NULL, NULL, true);
721          
722             if (!store->tls_ctx) {
723                Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
724                     store->hdr.name, configfile);
725                OK = false;
726             }
727          }
728 #endif /* HAVE_TLS */
729       }
730
731       /* Loop over all counters, defining them in each database */
732       /* Set default value in all counters */
733       COUNTER *counter;
734       foreach_res(counter, R_COUNTER) {
735          /* Write to catalog? */
736          if (!counter->created && counter->Catalog == catalog) {
737             COUNTER_DBR cr;
738             bstrncpy(cr.Counter, counter->hdr.name, sizeof(cr.Counter));
739             cr.MinValue = counter->MinValue;
740             cr.MaxValue = counter->MaxValue;
741             cr.CurrentValue = counter->MinValue;
742             if (counter->WrapCounter) {
743                bstrncpy(cr.WrapCounter, counter->WrapCounter->hdr.name, sizeof(cr.WrapCounter));
744             } else {
745                cr.WrapCounter[0] = 0;  /* empty string */
746             }
747             if (db_create_counter_record(NULL, db, &cr)) {
748                counter->CurrentValue = cr.CurrentValue;
749                counter->created = true;
750                Dmsg2(100, "Create counter %s val=%d\n", counter->hdr.name, counter->CurrentValue);
751             }
752          }
753          if (!counter->created) {
754             counter->CurrentValue = counter->MinValue;  /* default value */
755          }
756       }
757       db_close_database(NULL, db);
758    }
759
760 #ifdef HAVE_TLS
761    /* Loop over Consoles */
762    CONRES *cons;
763    foreach_res(cons, R_CONSOLE) {
764       /* tls_require implies tls_enable */
765       if (cons->tls_require) {
766          cons->tls_enable = true;
767       }
768
769       if (!cons->tls_certfile && cons->tls_enable) {
770          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Console \"%s\" in %s.\n"),
771             cons->hdr.name, configfile);
772          OK = false;
773       }
774
775       if (!cons->tls_keyfile && cons->tls_enable) {
776          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Console \"%s\" in %s.\n"),
777             cons->hdr.name, configfile);
778          OK = false;
779       }
780
781       if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) && cons->tls_enable && cons->tls_verify_peer) {
782          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
783             " Certificate Dir\" are defined for Console \"%s\" in %s."
784             " At least one CA certificate store is required"
785             " when using \"TLS Verify Peer\".\n"),
786             cons->hdr.name, configfile);
787          OK = false;
788       }
789       /* If everything is well, attempt to initialize our per-resource TLS context */
790       if (OK && (cons->tls_enable || cons->tls_require)) {
791          /* Initialize TLS context:
792           * Args: CA certfile, CA certdir, Certfile, Keyfile,
793           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
794          cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
795             cons->tls_ca_certdir, cons->tls_certfile,
796             cons->tls_keyfile, NULL, NULL, cons->tls_dhfile, cons->tls_verify_peer);
797          
798          if (!cons->tls_ctx) {
799             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
800                cons->hdr.name, configfile);
801             OK = false;
802          }
803       }
804
805    }
806 #endif /* HAVE_TLS */
807
808 #ifdef HAVE_TLS
809    /* Loop over Clients */
810    CLIENT *client;
811    foreach_res(client, R_CLIENT) {
812       /* tls_require implies tls_enable */
813       if (client->tls_require) {
814          client->tls_enable = true;
815       }
816
817       if ((!client->tls_ca_certfile && !client->tls_ca_certdir) && client->tls_enable) {
818          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
819             " or \"TLS CA Certificate Dir\" are defined for File daemon \"%s\" in %s.\n"),
820             client->hdr.name, configfile);
821          OK = false;
822       }
823
824       /* If everything is well, attempt to initialize our per-resource TLS context */
825       if (OK && (client->tls_enable || client->tls_require)) {
826          /* Initialize TLS context:
827           * Args: CA certfile, CA certdir, Certfile, Keyfile,
828           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
829          client->tls_ctx = new_tls_context(client->tls_ca_certfile,
830             client->tls_ca_certdir, client->tls_certfile,
831             client->tls_keyfile, NULL, NULL, NULL,
832             true);
833          
834          if (!client->tls_ctx) {
835             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
836                client->hdr.name, configfile);
837             OK = false;
838          }
839       }
840    }
841 #endif /* HAVE_TLS */
842
843    UnlockRes();
844    if (OK) {
845       close_msg(NULL);                /* close temp message handler */
846       init_msg(NULL, director->messages); /* open daemon message handler */
847    }
848    return OK;
849 }