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