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