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