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