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