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