]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
d296abf44aeb72de19fbbcfc8924a1b43bcc181b
[bacula/bacula] / bacula / src / dird / job.c
1 /*
2  *
3  *   Bacula Director Job processing routines
4  *
5  *     Kern Sibbald, October MM
6  *
7  *    Version $Id$
8  */
9 /*
10    Copyright (C) 2000-2006 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 amended 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 *job_thread(void *arg);
29 static void job_monitor_watchdog(watchdog_t *self);
30 static void job_monitor_destructor(watchdog_t *self);
31 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr);
32 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr);
33
34 /* Imported subroutines */
35 extern void term_scheduler();
36 extern void term_ua_server();
37
38 /* Imported variables */
39
40 jobq_t job_queue;
41
42 void init_job_server(int max_workers)
43 {
44    int stat;
45    watchdog_t *wd;
46
47    if ((stat = jobq_init(&job_queue, max_workers, job_thread)) != 0) {
48       berrno be;
49       Emsg1(M_ABORT, 0, _("Could not init job queue: ERR=%s\n"), be.strerror(stat));
50    }
51    wd = new_watchdog();
52    wd->callback = job_monitor_watchdog;
53    wd->destructor = job_monitor_destructor;
54    wd->one_shot = false;
55    wd->interval = 60;
56    wd->data = new_control_jcr("*JobMonitor*", JT_SYSTEM);
57    register_watchdog(wd);
58 }
59
60 void term_job_server()
61 {
62    jobq_destroy(&job_queue);          /* ignore any errors */
63 }
64
65 /*
66  * Run a job -- typically called by the scheduler, but may also
67  *              be called by the UA (Console program).
68  *
69  *  Returns: 0 on failure
70  *           JobId on success
71  *
72  */
73 JobId_t run_job(JCR *jcr)
74 {
75    int stat;
76    if (setup_job(jcr)) {
77       /* Queue the job to be run */
78       if ((stat = jobq_add(&job_queue, jcr)) != 0) {
79          berrno be;
80          Jmsg(jcr, M_FATAL, 0, _("Could not add job queue: ERR=%s\n"), be.strerror(stat));
81          return 0;
82       }
83       return jcr->JobId;
84    }
85    return 0;
86 }            
87
88 bool setup_job(JCR *jcr) 
89 {
90    int errstat;
91
92    jcr->lock();
93    sm_check(__FILE__, __LINE__, true);
94    init_msg(jcr, jcr->messages);
95
96    /* Initialize termination condition variable */
97    if ((errstat = pthread_cond_init(&jcr->term_wait, NULL)) != 0) {
98       berrno be;
99       Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.strerror(errstat));
100       goto bail_out;
101    }
102    jcr->term_wait_inited = true;
103
104    create_unique_job_name(jcr, jcr->job->hdr.name);
105    set_jcr_job_status(jcr, JS_Created);
106    jcr->unlock();
107
108    /*
109     * Open database
110     */
111    Dmsg0(50, "Open database\n");
112    jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user,
113                             jcr->catalog->db_password, jcr->catalog->db_address,
114                             jcr->catalog->db_port, jcr->catalog->db_socket,
115                             jcr->catalog->mult_db_connections);
116    if (!jcr->db || !db_open_database(jcr, jcr->db)) {
117       Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
118                  jcr->catalog->db_name);
119       if (jcr->db) {
120          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
121       }
122       goto bail_out;
123    }
124    Dmsg0(50, "DB opened\n");
125
126    if (!jcr->fname) {
127       jcr->fname = get_pool_memory(PM_FNAME);
128    }
129    if (!jcr->pool_source) {
130       jcr->pool_source = get_pool_memory(PM_MESSAGE);
131       pm_strcpy(jcr->pool_source, _("unknown source"));
132    }
133    if (!jcr->storage_source) {
134       jcr->storage_source = get_pool_memory(PM_MESSAGE);
135       pm_strcpy(jcr->storage_source, _("unknown source"));
136    }
137
138    /*
139     * Create Job record
140     */
141    init_jcr_job_record(jcr);
142    if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
143       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
144       goto bail_out;
145    }
146    jcr->JobId = jcr->jr.JobId;
147    Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
148        jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
149
150    generate_daemon_event(jcr, "JobStart");
151
152    if (!get_or_create_client_record(jcr)) {
153       goto bail_out;
154    }
155
156    if (job_canceled(jcr)) {
157       goto bail_out;
158    }
159
160
161    /*
162     * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
163     *  this allows us to setup a proper job start record for restarting
164     *  in case of later errors.
165     */
166    switch (jcr->JobType) {
167    case JT_BACKUP:
168       if (!do_backup_init(jcr)) {
169          backup_cleanup(jcr, JS_ErrorTerminated);
170       }
171       break;
172    case JT_VERIFY:
173       if (!do_verify_init(jcr)) {
174          verify_cleanup(jcr, JS_ErrorTerminated);
175       }
176       break;
177    case JT_RESTORE:
178       if (!do_restore_init(jcr)) {
179          restore_cleanup(jcr, JS_ErrorTerminated);
180       }
181       break;
182    case JT_ADMIN:
183       if (!do_admin_init(jcr)) {
184          admin_cleanup(jcr, JS_ErrorTerminated);
185       }
186       break;
187    case JT_MIGRATE:
188       if (!do_migration_init(jcr)) { 
189          migration_cleanup(jcr, JS_ErrorTerminated);
190       }
191       break;
192    default:
193       Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
194       set_jcr_job_status(jcr, JS_ErrorTerminated);
195       break;
196    }
197
198    generate_job_event(jcr, "JobInit");
199
200    Dmsg0(200, "Add jrc to work queue\n");
201    return true;
202
203 bail_out:
204    return false;
205 }
206
207
208 /*
209  * This is the engine called by jobq.c:jobq_add() when we were pulled
210  *  from the work queue.
211  *  At this point, we are running in our own thread and all
212  *    necessary resources are allocated -- see jobq.c
213  */
214 static void *job_thread(void *arg)
215 {
216    JCR *jcr = (JCR *)arg;
217
218    jcr->my_thread_id = pthread_self();
219    pthread_detach(jcr->my_thread_id);
220    sm_check(__FILE__, __LINE__, true);
221
222    Dmsg0(200, "=====Start Job=========\n");
223    set_jcr_job_status(jcr, JS_Running);   /* this will be set only if no error */
224    jcr->start_time = time(NULL);      /* set the real start time */
225    jcr->jr.StartTime = jcr->start_time;
226
227    if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
228        (utime_t)(jcr->start_time - jcr->sched_time)) {
229       Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
230       set_jcr_job_status(jcr, JS_Canceled);
231    }
232
233    /* TODO : check if it is used somewhere */
234    if (jcr->job->RunScripts == NULL) {
235       Dmsg0(200, "Warning, job->RunScripts is empty\n");
236       jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
237    }
238
239    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
240       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
241    }
242
243    if (job_canceled(jcr)) {
244       update_job_end_record(jcr);
245    } else {
246       /* Run any script BeforeJob on dird */
247       run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
248
249       /*
250        * We re-update the job start record so that the start
251        *  time is set after the run before job.  This avoids
252        *  that any files created by the run before job will
253        *  be saved twice.  They will be backed up in the current
254        *  job, but not in the next one unless they are changed.
255        *  Without this, they will be backed up in this job and
256        *  in the next job run because in that case, their date
257        *   is after the start of this run.
258        */
259       jcr->start_time = time(NULL);
260       jcr->jr.StartTime = jcr->start_time;
261       if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
262          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
263       }
264       generate_job_event(jcr, "JobRun");
265
266       switch (jcr->JobType) {
267       case JT_BACKUP:
268          if (do_backup(jcr)) {
269             do_autoprune(jcr);
270          } else {
271             backup_cleanup(jcr, JS_ErrorTerminated);
272          }
273          break;
274       case JT_VERIFY:
275          if (do_verify(jcr)) {
276             do_autoprune(jcr);
277          } else {
278             verify_cleanup(jcr, JS_ErrorTerminated);
279          }
280          break;
281       case JT_RESTORE:
282          if (do_restore(jcr)) {
283             do_autoprune(jcr);
284          } else {
285             restore_cleanup(jcr, JS_ErrorTerminated);
286          }
287          break;
288       case JT_ADMIN:
289          if (do_admin(jcr)) {
290             do_autoprune(jcr);
291          } else {
292             admin_cleanup(jcr, JS_ErrorTerminated);
293          }
294          break;
295       case JT_MIGRATE:
296       case JT_COPY:
297       case JT_ARCHIVE:
298          if (do_migration(jcr)) {
299             do_autoprune(jcr);
300          } else {
301             migration_cleanup(jcr, JS_ErrorTerminated);
302          }
303          break;
304       default:
305          Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
306          break;
307       }
308
309       run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
310
311       /* Send off any queued messages */
312       if (jcr->msg_queue->size() > 0) {
313          dequeue_messages(jcr);
314       }
315    }
316
317    generate_daemon_event(jcr, "JobEnd");
318    Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
319    sm_check(__FILE__, __LINE__, true);
320    return NULL;
321 }
322
323
324 /*
325  * Cancel a job -- typically called by the UA (Console program), but may also
326  *              be called by the job watchdog.
327  *
328  *  Returns: true  if cancel appears to be successful
329  *           false on failure. Message sent to ua->jcr.
330  */
331 bool cancel_job(UAContext *ua, JCR *jcr)
332 {
333    BSOCK *sd, *fd;
334
335    set_jcr_job_status(jcr, JS_Canceled);
336
337    switch (jcr->JobStatus) {
338    case JS_Created:
339    case JS_WaitJobRes:
340    case JS_WaitClientRes:
341    case JS_WaitStoreRes:
342    case JS_WaitPriority:
343    case JS_WaitMaxJobs:
344    case JS_WaitStartTime:
345       bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"),
346               jcr->JobId, jcr->Job);
347       jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
348       return true;
349
350    default:
351       /* Cancel File daemon */
352       if (jcr->file_bsock) {
353          ua->jcr->client = jcr->client;
354          if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
355             bsendmsg(ua, _("Failed to connect to File daemon.\n"));
356             return 0;
357          }
358          Dmsg0(200, "Connected to file daemon\n");
359          fd = ua->jcr->file_bsock;
360          bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
361          while (bnet_recv(fd) >= 0) {
362             bsendmsg(ua, "%s", fd->msg);
363          }
364          bnet_sig(fd, BNET_TERMINATE);
365          bnet_close(fd);
366          ua->jcr->file_bsock = NULL;
367       }
368
369       /* Cancel Storage daemon */
370       if (jcr->store_bsock) {
371          if (!ua->jcr->wstorage) {
372             if (jcr->rstorage) {
373                copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
374             } else {
375                copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
376             }
377          } else {
378             if (jcr->rstorage) {
379                set_wstorage(ua->jcr, jcr->rstore);
380             } else {
381                set_wstorage(ua->jcr, jcr->wstore);
382             }
383          }
384          if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
385             bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
386             return false;
387          }
388          Dmsg0(200, "Connected to storage daemon\n");
389          sd = ua->jcr->store_bsock;
390          bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
391          while (bnet_recv(sd) >= 0) {
392             bsendmsg(ua, "%s", sd->msg);
393          }
394          bnet_sig(sd, BNET_TERMINATE);
395          bnet_close(sd);
396          ua->jcr->store_bsock = NULL;
397       }
398    }
399
400    return true;
401 }
402
403
404 static void job_monitor_destructor(watchdog_t *self)
405 {
406    JCR *control_jcr = (JCR *)self->data;
407
408    free_jcr(control_jcr);
409 }
410
411 static void job_monitor_watchdog(watchdog_t *self)
412 {
413    JCR *control_jcr, *jcr;
414
415    control_jcr = (JCR *)self->data;
416
417    Dmsg1(800, "job_monitor_watchdog %p called\n", self);
418
419    foreach_jcr(jcr) {
420       bool cancel;
421
422       if (jcr->JobId == 0) {
423          Dmsg2(800, "Skipping JCR %p (%s) with JobId 0\n",
424                jcr, jcr->Job);
425          continue;
426       }
427
428       /* check MaxWaitTime */
429       cancel = job_check_maxwaittime(control_jcr, jcr);
430
431       /* check MaxRunTime */
432       cancel |= job_check_maxruntime(control_jcr, jcr);
433
434       if (cancel) {
435          Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n",
436                jcr, jcr->JobId, jcr->Job);
437
438          UAContext *ua = new_ua_context(jcr);
439          ua->jcr = control_jcr;
440          cancel_job(ua, jcr);
441          free_ua_context(ua);
442
443          Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
444       }
445
446       /* Keep reference counts correct */
447    }
448    endeach_jcr(jcr);
449 }
450
451 /*
452  * Check if the maxwaittime has expired and it is possible
453  *  to cancel the job.
454  */
455 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
456 {
457    bool cancel = false;
458    bool ok_to_cancel = false;
459    JOB *job = jcr->job;
460
461    if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
462        job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
463       return false;
464    } 
465    if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
466          (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
467       ok_to_cancel = true;
468    } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
469          (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
470       ok_to_cancel = true;
471    } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
472          (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
473       ok_to_cancel = true;
474    } else if (job->MaxWaitTime != 0 &&
475          (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
476       ok_to_cancel = true;
477    }
478    if (!ok_to_cancel) {
479       return false;
480    }
481    Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, "
482          "checking status\n",
483          jcr->JobId, jcr->Job, job->MaxWaitTime);
484    switch (jcr->JobStatus) {
485    case JS_Created:
486    case JS_Blocked:
487    case JS_WaitFD:
488    case JS_WaitSD:
489    case JS_WaitStoreRes:
490    case JS_WaitClientRes:
491    case JS_WaitJobRes:
492    case JS_WaitPriority:
493    case JS_WaitMaxJobs:
494    case JS_WaitStartTime:
495       cancel = true;
496       Dmsg0(200, "JCR blocked in #1\n");
497       break;
498    case JS_Running:
499       Dmsg0(800, "JCR running, checking SD status\n");
500       switch (jcr->SDJobStatus) {
501       case JS_WaitMount:
502       case JS_WaitMedia:
503       case JS_WaitFD:
504          cancel = true;
505          Dmsg0(800, "JCR blocked in #2\n");
506          break;
507       default:
508          Dmsg0(800, "JCR not blocked in #2\n");
509          break;
510       }
511       break;
512    case JS_Terminated:
513    case JS_ErrorTerminated:
514    case JS_Canceled:
515    case JS_FatalError:
516       Dmsg0(800, "JCR already dead in #3\n");
517       break;
518    default:
519       Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
520             jcr->JobStatus);
521    }
522    Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n",
523          cancel ? "" : "do not ", jcr, jcr->job);
524
525    return cancel;
526 }
527
528 /*
529  * Check if maxruntime has expired and if the job can be
530  *   canceled.
531  */
532 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
533 {
534    bool cancel = false;
535
536    if (jcr->job->MaxRunTime == 0) {
537       return false;
538    }
539    if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
540       Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
541             jcr, jcr->Job, jcr->job->MaxRunTime);
542       return false;
543    }
544
545    switch (jcr->JobStatus) {
546    case JS_Created:
547    case JS_Running:
548    case JS_Blocked:
549    case JS_WaitFD:
550    case JS_WaitSD:
551    case JS_WaitStoreRes:
552    case JS_WaitClientRes:
553    case JS_WaitJobRes:
554    case JS_WaitPriority:
555    case JS_WaitMaxJobs:
556    case JS_WaitStartTime:
557    case JS_Differences:
558       cancel = true;
559       break;
560    case JS_Terminated:
561    case JS_ErrorTerminated:
562    case JS_Canceled:
563    case JS_FatalError:
564       cancel = false;
565       break;
566    default:
567       Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
568             jcr->JobStatus);
569    }
570
571    Dmsg3(200, "MaxRunTime result: %scancel JCR %p (%s)\n",
572          cancel ? "" : "do not ", jcr, jcr->job);
573
574    return cancel;
575 }
576
577 /*
578  * Get or create a Pool record with the given name.
579  * Returns: 0 on error
580  *          poolid if OK
581  */
582 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
583 {
584    POOL_DBR pr;
585
586    memset(&pr, 0, sizeof(pr));
587    bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
588
589    while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
590       /* Try to create the pool */
591       if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
592          Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
593             db_strerror(jcr->db));
594          return 0;
595       } else {
596          Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
597       }
598    }
599    return pr.PoolId;
600 }
601
602 void apply_pool_overrides(JCR *jcr)
603 {
604    if (jcr->run_pool_override) {
605       pm_strcpy(jcr->pool_source, _("Run Pool override"));
606    }
607    /*
608     * Apply any level related Pool selections
609     */
610    switch (jcr->JobLevel) {
611    case L_FULL:
612       if (jcr->full_pool) {
613          jcr->pool = jcr->full_pool;
614          if (jcr->run_full_pool_override) {
615             pm_strcpy(jcr->pool_source, _("Run FullPool override"));
616          } else {
617             pm_strcpy(jcr->pool_source, _("Job FullPool override"));
618          }
619       }
620       break;
621    case L_INCREMENTAL:
622       if (jcr->inc_pool) {
623          jcr->pool = jcr->inc_pool;
624          if (jcr->run_inc_pool_override) {
625             pm_strcpy(jcr->pool_source, _("Run IncPool override"));
626          } else {
627             pm_strcpy(jcr->pool_source, _("Job IncPool override"));
628          }
629       }
630       break;
631    case L_DIFFERENTIAL:
632       if (jcr->diff_pool) {
633          jcr->pool = jcr->diff_pool;
634          if (jcr->run_diff_pool_override) {
635             pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
636          } else {
637             pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
638          }
639       }
640       break;
641    }
642 }
643
644
645 /*
646  * Get or create a Client record for this Job
647  */
648 bool get_or_create_client_record(JCR *jcr)
649 {
650    CLIENT_DBR cr;
651
652    memset(&cr, 0, sizeof(cr));
653    bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
654    cr.AutoPrune = jcr->client->AutoPrune;
655    cr.FileRetention = jcr->client->FileRetention;
656    cr.JobRetention = jcr->client->JobRetention;
657    if (!jcr->client_name) {
658       jcr->client_name = get_pool_memory(PM_NAME);
659    }
660    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
661    if (!db_create_client_record(jcr, jcr->db, &cr)) {
662       Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
663          db_strerror(jcr->db));
664       return false;
665    }
666    jcr->jr.ClientId = cr.ClientId;
667    if (cr.Uname[0]) {
668       if (!jcr->client_uname) {
669          jcr->client_uname = get_pool_memory(PM_NAME);
670       }
671       pm_strcpy(jcr->client_uname, cr.Uname);
672    }
673    Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
674       jcr->jr.ClientId);
675    return true;
676 }
677
678 bool get_or_create_fileset_record(JCR *jcr)
679 {
680    FILESET_DBR fsr;
681    /*
682     * Get or Create FileSet record
683     */
684    memset(&fsr, 0, sizeof(FILESET_DBR));
685    bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
686    if (jcr->fileset->have_MD5) {
687       struct MD5Context md5c;
688       unsigned char digest[MD5HashSize];
689       memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
690       MD5Final(digest, &md5c);
691       bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, true);
692       bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
693    } else {
694       Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
695    }
696    if (!jcr->fileset->ignore_fs_changes ||
697        !db_get_fileset_record(jcr, jcr->db, &fsr)) {
698       if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
699          Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
700             fsr.FileSet, db_strerror(jcr->db));
701          return false;
702       }
703    }
704    jcr->jr.FileSetId = fsr.FileSetId;
705    bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
706    Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
707       jcr->jr.FileSetId);
708    return true;
709 }
710
711 void init_jcr_job_record(JCR *jcr)
712 {
713    jcr->jr.SchedTime = jcr->sched_time;
714    jcr->jr.StartTime = jcr->start_time;
715    jcr->jr.EndTime = 0;               /* perhaps rescheduled, clear it */
716    jcr->jr.JobType = jcr->JobType;
717    jcr->jr.JobLevel = jcr->JobLevel;
718    jcr->jr.JobStatus = jcr->JobStatus;
719    jcr->jr.JobId = jcr->JobId;
720    bstrncpy(jcr->jr.Name, jcr->job->hdr.name, sizeof(jcr->jr.Name));
721    bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
722 }
723
724 /*
725  * Write status and such in DB
726  */
727 void update_job_end_record(JCR *jcr)
728 {
729    jcr->jr.EndTime = time(NULL);
730    jcr->end_time = jcr->jr.EndTime;
731    jcr->jr.JobId = jcr->JobId;
732    jcr->jr.JobStatus = jcr->JobStatus;
733    jcr->jr.JobFiles = jcr->JobFiles;
734    jcr->jr.JobBytes = jcr->JobBytes;
735    jcr->jr.VolSessionId = jcr->VolSessionId;
736    jcr->jr.VolSessionTime = jcr->VolSessionTime;
737    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
738       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
739          db_strerror(jcr->db));
740    }
741 }
742
743 /*
744  * Takes base_name and appends (unique) current
745  *   date and time to form unique job name.
746  *
747  *  Returns: unique job name in jcr->Job
748  *    date/time in jcr->start_time
749  */
750 void create_unique_job_name(JCR *jcr, const char *base_name)
751 {
752    /* Job start mutex */
753    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
754    static time_t last_start_time = 0;
755    time_t now;
756    struct tm tm;
757    char dt[MAX_TIME_LENGTH];
758    char name[MAX_NAME_LENGTH];
759    char *p;
760
761    /* Guarantee unique start time -- maximum one per second, and
762     * thus unique Job Name
763     */
764    P(mutex);                          /* lock creation of jobs */
765    now = time(NULL);
766    while (now == last_start_time) {
767       bmicrosleep(0, 500000);
768       now = time(NULL);
769    }
770    last_start_time = now;
771    V(mutex);                          /* allow creation of jobs */
772    jcr->start_time = now;
773    /* Form Unique JobName */
774    (void)localtime_r(&now, &tm);
775    /* Use only characters that are permitted in Windows filenames */
776    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
777    bstrncpy(name, base_name, sizeof(name));
778    name[sizeof(name)-22] = 0;          /* truncate if too long */
779    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
780    /* Convert spaces into underscores */
781    for (p=jcr->Job; *p; p++) {
782       if (*p == ' ') {
783          *p = '_';
784       }
785    }
786 }
787
788 /* Called directly from job rescheduling */
789 void dird_free_jcr_pointers(JCR *jcr)
790 {
791    if (jcr->sd_auth_key) {
792       free(jcr->sd_auth_key);
793       jcr->sd_auth_key = NULL;
794    }
795    if (jcr->where) {
796       free(jcr->where);
797       jcr->where = NULL;
798    }
799    if (jcr->file_bsock) {
800       Dmsg0(200, "Close File bsock\n");
801       bnet_close(jcr->file_bsock);
802       jcr->file_bsock = NULL;
803    }
804    if (jcr->store_bsock) {
805       Dmsg0(200, "Close Store bsock\n");
806       bnet_close(jcr->store_bsock);
807       jcr->store_bsock = NULL;
808    }
809    if (jcr->fname) {
810       Dmsg0(200, "Free JCR fname\n");
811       free_pool_memory(jcr->fname);
812       jcr->fname = NULL;
813    }
814    if (jcr->pool_source) {
815       free_pool_memory(jcr->pool_source);
816       jcr->pool_source = NULL;
817    }
818    if (jcr->storage_source) {
819       free_pool_memory(jcr->storage_source);
820       jcr->storage_source = NULL;
821    }
822    if (jcr->stime) {
823       Dmsg0(200, "Free JCR stime\n");
824       free_pool_memory(jcr->stime);
825       jcr->stime = NULL;
826    }
827    if (jcr->RestoreBootstrap) {
828       free(jcr->RestoreBootstrap);
829       jcr->RestoreBootstrap = NULL;
830    }
831    if (jcr->client_uname) {
832       free_pool_memory(jcr->client_uname);
833       jcr->client_uname = NULL;
834    }
835    if (jcr->attr) {
836       free_pool_memory(jcr->attr);
837       jcr->attr = NULL;
838    }
839    if (jcr->ar) {
840       free(jcr->ar);
841       jcr->ar = NULL;
842    }
843 }
844
845 /*
846  * Free the Job Control Record if no one is still using it.
847  *  Called from main free_jcr() routine in src/lib/jcr.c so
848  *  that we can do our Director specific cleanup of the jcr.
849  */
850 void dird_free_jcr(JCR *jcr)
851 {
852    Dmsg0(200, "Start dird free_jcr\n");
853
854    dird_free_jcr_pointers(jcr);
855    if (jcr->term_wait_inited) {
856       pthread_cond_destroy(&jcr->term_wait);
857       jcr->term_wait_inited = false;
858    }
859
860    /* Delete lists setup to hold storage pointers */
861    free_rwstorage(jcr);
862
863    jcr->job_end_push.destroy();
864    Dmsg0(200, "End dird free_jcr\n");
865 }
866
867 /*
868  * Set some defaults in the JCR necessary to
869  * run. These items are pulled from the job
870  * definition as defaults, but can be overridden
871  * later either by the Run record in the Schedule resource,
872  * or by the Console program.
873  */
874 void set_jcr_defaults(JCR *jcr, JOB *job)
875 {
876    jcr->job = job;
877    jcr->JobType = job->JobType;
878    switch (jcr->JobType) {
879    case JT_ADMIN:
880    case JT_RESTORE:
881       jcr->JobLevel = L_NONE;
882       break;
883    default:
884       jcr->JobLevel = job->JobLevel;
885       break;
886    }
887    if (!jcr->fname) {
888       jcr->fname = get_pool_memory(PM_FNAME);
889    }
890    if (!jcr->pool_source) {
891       jcr->pool_source = get_pool_memory(PM_MESSAGE);
892       pm_strcpy(jcr->pool_source, _("unknown source"));
893    }
894    if (!jcr->storage_source) {
895       jcr->storage_source = get_pool_memory(PM_MESSAGE);
896       pm_strcpy(jcr->storage_source, _("unknown source"));
897    }
898    jcr->JobPriority = job->Priority;
899    /* Copy storage definitions -- deleted in dir_free_jcr above */
900    copy_rwstorage(jcr, job->storage, _("Job resource"));
901    jcr->client = job->client;
902    if (!jcr->client_name) {
903       jcr->client_name = get_pool_memory(PM_NAME);
904    }
905    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
906    pm_strcpy(jcr->pool_source, _("Job resource"));
907    jcr->pool = job->pool;
908    jcr->full_pool = job->full_pool;
909    jcr->inc_pool = job->inc_pool;
910    jcr->diff_pool = job->diff_pool;
911    jcr->catalog = job->client->catalog;
912    jcr->fileset = job->fileset;
913    jcr->messages = job->messages;
914    jcr->spool_data = job->spool_data;
915    jcr->write_part_after_job = job->write_part_after_job;
916    if (jcr->RestoreBootstrap) {
917       free(jcr->RestoreBootstrap);
918       jcr->RestoreBootstrap = NULL;
919    }
920    /* This can be overridden by Console program */
921    if (job->RestoreBootstrap) {
922       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
923    }
924    /* This can be overridden by Console program */
925    jcr->verify_job = job->verify_job;
926    /* If no default level given, set one */
927    if (jcr->JobLevel == 0) {
928       switch (jcr->JobType) {
929       case JT_VERIFY:
930          jcr->JobLevel = L_VERIFY_CATALOG;
931          break;
932       case JT_BACKUP:
933          jcr->JobLevel = L_INCREMENTAL;
934          break;
935       case JT_RESTORE:
936       case JT_ADMIN:
937          jcr->JobLevel = L_NONE;
938          break;
939       default:
940          break;
941       }
942    }
943 }
944
945 /* 
946  * Copy the storage definitions from an alist to the JCR
947  */
948 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
949 {
950    copy_rstorage(jcr, storage, where);
951    copy_wstorage(jcr, storage, where);
952 }
953
954
955 /* Set storage override */
956 void set_rwstorage(JCR *jcr, STORE *store)
957 {
958    set_rstorage(jcr, store);
959    set_wstorage(jcr, store);
960 }
961
962 void free_rwstorage(JCR *jcr)
963 {
964    free_rstorage(jcr);
965    free_wstorage(jcr);
966 }
967
968 /* 
969  * Copy the storage definitions from an alist to the JCR
970  */
971 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
972 {
973    if (storage) {
974       STORE *st;
975       if (jcr->rstorage) {
976          delete jcr->rstorage;
977       }
978       jcr->rstorage = New(alist(10, not_owned_by_alist));
979       foreach_alist(st, storage) {
980          jcr->rstorage->append(st);
981       }
982       pm_strcpy(jcr->storage_source, where);
983    }               
984    if (jcr->rstorage) {
985       jcr->rstore = (STORE *)jcr->rstorage->first();
986    }
987 }
988
989
990 /* Set storage override */
991 void set_rstorage(JCR *jcr, STORE *store)
992 {
993    STORE *storage;
994
995    jcr->rstore = store;
996    foreach_alist(storage, jcr->rstorage) {
997       if (store == storage) {
998          return;
999       }
1000    }
1001    /* Store not in list, so add it */
1002    jcr->rstorage->prepend(store);
1003 }
1004
1005 void free_rstorage(JCR *jcr)
1006 {
1007    if (jcr->rstorage) {
1008       delete jcr->rstorage;
1009       jcr->rstorage = NULL;
1010    }
1011    jcr->rstore = NULL;
1012 }
1013
1014 /* 
1015  * Copy the storage definitions from an alist to the JCR
1016  */
1017 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1018 {
1019    if (storage) {
1020       STORE *st;
1021       if (jcr->wstorage) {
1022          delete jcr->wstorage;
1023       }
1024       jcr->wstorage = New(alist(10, not_owned_by_alist));
1025       foreach_alist(st, storage) {
1026          jcr->wstorage->append(st);
1027       }
1028       pm_strcpy(jcr->storage_source, where);
1029    }               
1030    if (jcr->wstorage) {
1031       jcr->wstore = (STORE *)jcr->wstorage->first();
1032    }
1033 }
1034
1035
1036 /* Set storage override */
1037 void set_wstorage(JCR *jcr, STORE *store)
1038 {
1039    STORE *storage;
1040
1041    jcr->wstore = store;
1042    foreach_alist(storage, jcr->wstorage) {
1043       if (store == storage) {
1044          return;
1045       }
1046    }
1047    /* Store not in list, so add it */
1048    jcr->wstorage->prepend(store);
1049 }
1050
1051 void free_wstorage(JCR *jcr)
1052 {
1053    if (jcr->wstorage) {
1054       delete jcr->wstorage;
1055       jcr->wstorage = NULL;
1056    }
1057    jcr->wstore = NULL;
1058 }
1059
1060
1061
1062 void create_clones(JCR *jcr)
1063 {
1064    /*
1065     * Fire off any clone jobs (run directives)
1066     */
1067    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1068    if (!jcr->cloned && jcr->job->run_cmds) {
1069       char *runcmd;
1070       JOB *job = jcr->job;
1071       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1072       UAContext *ua = new_ua_context(jcr);
1073       ua->batch = true;
1074       foreach_alist(runcmd, job->run_cmds) {
1075          cmd = edit_job_codes(jcr, cmd, runcmd, "");              
1076          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1077          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1078          parse_ua_args(ua);                 /* parse command */
1079          int stat = run_cmd(ua, ua->cmd);
1080          if (stat == 0) {
1081             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1082          } else {
1083             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1084          }
1085       }
1086       free_ua_context(ua);
1087       free_pool_memory(cmd);
1088    }
1089 }
1090
1091 bool create_restore_bootstrap_file(JCR *jcr)
1092 {
1093    RESTORE_CTX rx;
1094    UAContext *ua;
1095    memset(&rx, 0, sizeof(rx));
1096    rx.bsr = new_bsr();
1097    rx.JobIds = "";                       
1098    rx.bsr->JobId = jcr->previous_jr.JobId;
1099    ua = new_ua_context(jcr);
1100    complete_bsr(ua, rx.bsr);
1101    rx.bsr->fi = new_findex();
1102    rx.bsr->fi->findex = 1;
1103    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1104    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1105    if (jcr->ExpectedFiles == 0) {
1106       free_ua_context(ua);
1107       free_bsr(rx.bsr);
1108       return false;
1109    }
1110    free_ua_context(ua);
1111    free_bsr(rx.bsr);
1112    jcr->needs_sd = true;
1113    return true;
1114 }