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