]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
Done with item 9 = Implement new {Client}Run{Before|After}Job feature.
[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    /* TODO : check if it is used somewhere */
188    if (jcr->job->RunScripts == NULL)
189    {
190       Dmsg0(200, "Warning, job->RunScripts is empty\n");
191       jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
192    }
193
194    /*                                
195     * Note, we continue, even if the job is canceled above. This
196     *  will permit proper setting of the job start record and
197     *  the error (cancel) will be picked up below.
198     */
199
200    generate_job_event(jcr, "JobInit");
201    set_jcr_job_status(jcr, JS_Running);   /* this will be set only if no error */
202
203    if (!jcr->fname) {
204       jcr->fname = get_pool_memory(PM_FNAME);
205    }
206
207    /*
208     * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
209     *  this allows us to setup a proper job start record for restarting
210     *  in case of later errors.
211     */
212    switch (jcr->JobType) {
213    case JT_BACKUP:
214       if (!do_backup_init(jcr)) {
215          backup_cleanup(jcr, JS_ErrorTerminated);
216       }
217       break;
218    case JT_VERIFY:
219       if (!do_verify_init(jcr)) {
220          verify_cleanup(jcr, JS_ErrorTerminated);
221       }
222       break;
223    case JT_RESTORE:
224       if (!do_restore_init(jcr)) {
225          restore_cleanup(jcr, JS_ErrorTerminated);
226       }
227       break;
228    case JT_ADMIN:
229       if (!do_admin_init(jcr)) {
230          admin_cleanup(jcr, JS_ErrorTerminated);
231       }
232       break;
233    case JT_MIGRATE:
234       if (!do_migration_init(jcr)) { 
235          migration_cleanup(jcr, JS_ErrorTerminated);
236       }
237       break;
238    default:
239       Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
240       set_jcr_job_status(jcr, JS_ErrorTerminated);
241       break;
242    }
243
244    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
245       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
246    }
247
248    if (job_canceled(jcr)) {
249       update_job_end_record(jcr);
250
251    } else {
252
253       /* Run any script BeforeJob on dird */
254       run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
255
256       /*
257        * We re-update the job start record so that the start
258        *  time is set after the run before job.  This avoids
259        *  that any files created by the run before job will
260        *  be saved twice.  They will be backed up in the current
261        *  job, but not in the next one unless they are changed.
262        *  Without this, they will be backed up in this job and
263        *  in the next job run because in that case, their date
264        *   is after the start of this run.
265        */
266       jcr->start_time = time(NULL);
267       jcr->jr.StartTime = jcr->start_time;
268       if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
269          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
270       }
271       generate_job_event(jcr, "JobRun");
272
273       switch (jcr->JobType) {
274       case JT_BACKUP:
275          if (do_backup(jcr)) {
276             do_autoprune(jcr);
277          } else {
278             backup_cleanup(jcr, JS_ErrorTerminated);
279          }
280          break;
281       case JT_VERIFY:
282          if (do_verify(jcr)) {
283             do_autoprune(jcr);
284          } else {
285             verify_cleanup(jcr, JS_ErrorTerminated);
286          }
287          break;
288       case JT_RESTORE:
289          if (do_restore(jcr)) {
290             do_autoprune(jcr);
291          } else {
292             restore_cleanup(jcr, JS_ErrorTerminated);
293          }
294          break;
295       case JT_ADMIN:
296          if (do_admin(jcr)) {
297             do_autoprune(jcr);
298          } else {
299             admin_cleanup(jcr, JS_ErrorTerminated);
300          }
301          break;
302       case JT_MIGRATE:
303       case JT_COPY:
304       case JT_ARCHIVE:
305          if (do_migration(jcr)) {
306             do_autoprune(jcr);
307          } else {
308             migration_cleanup(jcr, JS_ErrorTerminated);
309          }
310          break;
311       default:
312          Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
313          break;
314       }
315
316       run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
317
318       /* Send off any queued messages */
319       if (jcr->msg_queue->size() > 0) {
320          dequeue_messages(jcr);
321       }
322    }
323
324 bail_out:
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);
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 /*
579  * Get or create a Client record for this Job
580  */
581 bool get_or_create_client_record(JCR *jcr)
582 {
583    CLIENT_DBR cr;
584
585    memset(&cr, 0, sizeof(cr));
586    bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
587    cr.AutoPrune = jcr->client->AutoPrune;
588    cr.FileRetention = jcr->client->FileRetention;
589    cr.JobRetention = jcr->client->JobRetention;
590    if (!jcr->client_name) {
591       jcr->client_name = get_pool_memory(PM_NAME);
592    }
593    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
594    if (!db_create_client_record(jcr, jcr->db, &cr)) {
595       Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
596          db_strerror(jcr->db));
597       return false;
598    }
599    jcr->jr.ClientId = cr.ClientId;
600    if (cr.Uname[0]) {
601       if (!jcr->client_uname) {
602          jcr->client_uname = get_pool_memory(PM_NAME);
603       }
604       pm_strcpy(jcr->client_uname, cr.Uname);
605    }
606    Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
607       jcr->jr.ClientId);
608    return true;
609 }
610
611 bool get_or_create_fileset_record(JCR *jcr)
612 {
613    FILESET_DBR fsr;
614    /*
615     * Get or Create FileSet record
616     */
617    memset(&fsr, 0, sizeof(FILESET_DBR));
618    bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
619    if (jcr->fileset->have_MD5) {
620       struct MD5Context md5c;
621       unsigned char digest[MD5HashSize];
622       memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
623       MD5Final(digest, &md5c);
624       bin_to_base64(fsr.MD5, (char *)digest, MD5HashSize);
625       bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
626    } else {
627       Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
628    }
629    if (!jcr->fileset->ignore_fs_changes ||
630        !db_get_fileset_record(jcr, jcr->db, &fsr)) {
631       if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
632          Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
633             fsr.FileSet, db_strerror(jcr->db));
634          return false;
635       }
636    }
637    jcr->jr.FileSetId = fsr.FileSetId;
638    bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
639    Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
640       jcr->jr.FileSetId);
641    return true;
642 }
643
644 void init_jcr_job_record(JCR *jcr)
645 {
646    jcr->jr.SchedTime = jcr->sched_time;
647    jcr->jr.StartTime = jcr->start_time;
648    jcr->jr.EndTime = 0;               /* perhaps rescheduled, clear it */
649    jcr->jr.JobType = jcr->JobType;
650    jcr->jr.JobLevel = jcr->JobLevel;
651    jcr->jr.JobStatus = jcr->JobStatus;
652    jcr->jr.JobId = jcr->JobId;
653    bstrncpy(jcr->jr.Name, jcr->job->hdr.name, sizeof(jcr->jr.Name));
654    bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
655 }
656
657 /*
658  * Write status and such in DB
659  */
660 void update_job_end_record(JCR *jcr)
661 {
662    jcr->jr.EndTime = time(NULL);
663    jcr->end_time = jcr->jr.EndTime;
664    jcr->jr.JobId = jcr->JobId;
665    jcr->jr.JobStatus = jcr->JobStatus;
666    jcr->jr.JobFiles = jcr->JobFiles;
667    jcr->jr.JobBytes = jcr->JobBytes;
668    jcr->jr.VolSessionId = jcr->VolSessionId;
669    jcr->jr.VolSessionTime = jcr->VolSessionTime;
670    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
671       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
672          db_strerror(jcr->db));
673    }
674 }
675
676 /*
677  * Takes base_name and appends (unique) current
678  *   date and time to form unique job name.
679  *
680  *  Returns: unique job name in jcr->Job
681  *    date/time in jcr->start_time
682  */
683 void create_unique_job_name(JCR *jcr, const char *base_name)
684 {
685    /* Job start mutex */
686    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
687    static time_t last_start_time = 0;
688    time_t now;
689    struct tm tm;
690    char dt[MAX_TIME_LENGTH];
691    char name[MAX_NAME_LENGTH];
692    char *p;
693
694    /* Guarantee unique start time -- maximum one per second, and
695     * thus unique Job Name
696     */
697    P(mutex);                          /* lock creation of jobs */
698    now = time(NULL);
699    while (now == last_start_time) {
700       bmicrosleep(0, 500000);
701       now = time(NULL);
702    }
703    last_start_time = now;
704    V(mutex);                          /* allow creation of jobs */
705    jcr->start_time = now;
706    /* Form Unique JobName */
707    localtime_r(&now, &tm);
708    /* Use only characters that are permitted in Windows filenames */
709    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
710    bstrncpy(name, base_name, sizeof(name));
711    name[sizeof(name)-22] = 0;          /* truncate if too long */
712    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
713    /* Convert spaces into underscores */
714    for (p=jcr->Job; *p; p++) {
715       if (*p == ' ') {
716          *p = '_';
717       }
718    }
719 }
720
721 /* Called directly from job rescheduling */
722 void dird_free_jcr_pointers(JCR *jcr)
723 {
724    if (jcr->sd_auth_key) {
725       free(jcr->sd_auth_key);
726       jcr->sd_auth_key = NULL;
727    }
728    if (jcr->where) {
729       free(jcr->where);
730       jcr->where = NULL;
731    }
732    if (jcr->file_bsock) {
733       Dmsg0(200, "Close File bsock\n");
734       bnet_close(jcr->file_bsock);
735       jcr->file_bsock = NULL;
736    }
737    if (jcr->store_bsock) {
738       Dmsg0(200, "Close Store bsock\n");
739       bnet_close(jcr->store_bsock);
740       jcr->store_bsock = NULL;
741    }
742    if (jcr->fname) {
743       Dmsg0(200, "Free JCR fname\n");
744       free_pool_memory(jcr->fname);
745       jcr->fname = NULL;
746    }
747    if (jcr->stime) {
748       Dmsg0(200, "Free JCR stime\n");
749       free_pool_memory(jcr->stime);
750       jcr->stime = NULL;
751    }
752    if (jcr->RestoreBootstrap) {
753       free(jcr->RestoreBootstrap);
754       jcr->RestoreBootstrap = NULL;
755    }
756    if (jcr->client_uname) {
757       free_pool_memory(jcr->client_uname);
758       jcr->client_uname = NULL;
759    }
760    if (jcr->attr) {
761       free_pool_memory(jcr->attr);
762       jcr->attr = NULL;
763    }
764    if (jcr->ar) {
765       free(jcr->ar);
766       jcr->ar = NULL;
767    }
768 }
769
770 /*
771  * Free the Job Control Record if no one is still using it.
772  *  Called from main free_jcr() routine in src/lib/jcr.c so
773  *  that we can do our Director specific cleanup of the jcr.
774  */
775 void dird_free_jcr(JCR *jcr)
776 {
777    Dmsg0(200, "Start dird free_jcr\n");
778
779    dird_free_jcr_pointers(jcr);
780    if (jcr->term_wait_inited) {
781       pthread_cond_destroy(&jcr->term_wait);
782       jcr->term_wait_inited = false;
783    }
784
785    /* Delete lists setup to hold storage pointers */
786    if (jcr->storage) {
787       delete jcr->storage;
788    }
789    jcr->job_end_push.destroy();
790    Dmsg0(200, "End dird free_jcr\n");
791 }
792
793 /*
794  * Set some defaults in the JCR necessary to
795  * run. These items are pulled from the job
796  * definition as defaults, but can be overridden
797  * later either by the Run record in the Schedule resource,
798  * or by the Console program.
799  */
800 void set_jcr_defaults(JCR *jcr, JOB *job)
801 {
802    jcr->job = job;
803    jcr->JobType = job->JobType;
804    switch (jcr->JobType) {
805    case JT_ADMIN:
806    case JT_RESTORE:
807       jcr->JobLevel = L_NONE;
808       break;
809    default:
810       jcr->JobLevel = job->JobLevel;
811       break;
812    }
813    jcr->JobPriority = job->Priority;
814    /* Copy storage definitions -- deleted in dir_free_jcr above */
815    copy_storage(jcr, job->storage);
816    jcr->client = job->client;
817    if (!jcr->client_name) {
818       jcr->client_name = get_pool_memory(PM_NAME);
819    }
820    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
821    jcr->pool = job->pool;
822    jcr->full_pool = job->full_pool;
823    jcr->inc_pool = job->inc_pool;
824    jcr->dif_pool = job->dif_pool;
825    jcr->catalog = job->client->catalog;
826    jcr->fileset = job->fileset;
827    jcr->messages = job->messages;
828    jcr->spool_data = job->spool_data;
829    jcr->write_part_after_job = job->write_part_after_job;
830    if (jcr->RestoreBootstrap) {
831       free(jcr->RestoreBootstrap);
832       jcr->RestoreBootstrap = NULL;
833    }
834    /* This can be overridden by Console program */
835    if (job->RestoreBootstrap) {
836       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
837    }
838    /* This can be overridden by Console program */
839    jcr->verify_job = job->verify_job;
840    /* If no default level given, set one */
841    if (jcr->JobLevel == 0) {
842       switch (jcr->JobType) {
843       case JT_VERIFY:
844          jcr->JobLevel = L_VERIFY_CATALOG;
845          break;
846       case JT_BACKUP:
847          jcr->JobLevel = L_INCREMENTAL;
848          break;
849       case JT_RESTORE:
850       case JT_ADMIN:
851          jcr->JobLevel = L_NONE;
852          break;
853       default:
854          break;
855       }
856    }
857 }
858
859
860 /* 
861  * Copy the storage definitions from an alist to the JCR
862  */
863 void copy_storage(JCR *jcr, alist *storage)
864 {
865    if (storage) {
866       STORE *st;
867       if (jcr->storage) {
868          delete jcr->storage;
869       }
870       jcr->storage = New(alist(10, not_owned_by_alist));
871       foreach_alist(st, storage) {
872          jcr->storage->append(st);
873       }
874    }               
875    if (jcr->storage) {
876       jcr->store = (STORE *)jcr->storage->first();
877    }
878 }
879
880
881 /* Set storage override */
882 void set_storage(JCR *jcr, STORE *store)
883 {
884    STORE *storage;
885
886    jcr->store = store;
887    foreach_alist(storage, jcr->storage) {
888       if (store == storage) {
889          return;
890       }
891    }
892    /* Store not in list, so add it */
893    jcr->storage->prepend(store);
894 }
895
896 void create_clones(JCR *jcr)
897 {
898    /*
899     * Fire off any clone jobs (run directives)
900     */
901    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
902    if (!jcr->cloned && jcr->job->run_cmds) {
903       char *runcmd;
904       JOB *job = jcr->job;
905       POOLMEM *cmd = get_pool_memory(PM_FNAME);
906       UAContext *ua = new_ua_context(jcr);
907       ua->batch = true;
908       foreach_alist(runcmd, job->run_cmds) {
909          cmd = edit_job_codes(jcr, cmd, runcmd, "");              
910          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
911          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
912          parse_ua_args(ua);                 /* parse command */
913          int stat = run_cmd(ua, ua->cmd);
914          if (stat == 0) {
915             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
916          } else {
917             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
918          }
919       }
920       free_ua_context(ua);
921       free_pool_memory(cmd);
922    }
923 }
924
925 bool create_restore_bootstrap_file(JCR *jcr)
926 {
927    RESTORE_CTX rx;
928    UAContext *ua;
929    memset(&rx, 0, sizeof(rx));
930    rx.bsr = new_bsr();
931    rx.JobIds = "";                       
932    rx.bsr->JobId = jcr->previous_jr.JobId;
933    ua = new_ua_context(jcr);
934    complete_bsr(ua, rx.bsr);
935    rx.bsr->fi = new_findex();
936    rx.bsr->fi->findex = 1;
937    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
938    jcr->ExpectedFiles = write_bsr_file(ua, rx);
939    if (jcr->ExpectedFiles == 0) {
940       free_ua_context(ua);
941       free_bsr(rx.bsr);
942       return false;
943    }
944    free_ua_context(ua);
945    free_bsr(rx.bsr);
946    jcr->needs_sd = true;
947    return true;
948 }