]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
kes Remove previous changes to compat.cpp as they create problems.
[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
40 jobq_t job_queue;
41
42 void init_job_server(int max_workers)
43 {
44    int stat;
45    watchdog_t *wd;
46
47    if ((stat = jobq_init(&job_queue, max_workers, job_thread)) != 0) {
48       berrno be;
49       Emsg1(M_ABORT, 0, _("Could not init job queue: ERR=%s\n"), be.strerror(stat));
50    }
51    wd = new_watchdog();
52    wd->callback = job_monitor_watchdog;
53    wd->destructor = job_monitor_destructor;
54    wd->one_shot = false;
55    wd->interval = 60;
56    wd->data = new_control_jcr("*JobMonitor*", JT_SYSTEM);
57    register_watchdog(wd);
58 }
59
60 void term_job_server()
61 {
62    jobq_destroy(&job_queue);          /* ignore any errors */
63 }
64
65 /*
66  * Run a job -- typically called by the scheduler, but may also
67  *              be called by the UA (Console program).
68  *
69  *  Returns: 0 on failure
70  *           JobId on success
71  *
72  */
73 JobId_t run_job(JCR *jcr)
74 {
75    int stat;
76    if (setup_job(jcr)) {
77       /* Queue the job to be run */
78       if ((stat = jobq_add(&job_queue, jcr)) != 0) {
79          berrno be;
80          Jmsg(jcr, M_FATAL, 0, _("Could not add job queue: ERR=%s\n"), be.strerror(stat));
81          return 0;
82       }
83       return jcr->JobId;
84    }
85    return 0;
86 }            
87
88 bool setup_job(JCR *jcr) 
89 {
90    int errstat;
91
92    jcr->lock();
93    sm_check(__FILE__, __LINE__, true);
94    init_msg(jcr, jcr->messages);
95
96    /* Initialize termination condition variable */
97    if ((errstat = pthread_cond_init(&jcr->term_wait, NULL)) != 0) {
98       berrno be;
99       Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.strerror(errstat));
100       goto bail_out;
101    }
102    jcr->term_wait_inited = true;
103
104    create_unique_job_name(jcr, jcr->job->hdr.name);
105    set_jcr_job_status(jcr, JS_Created);
106    jcr->unlock();
107
108    /*
109     * Open database
110     */
111    Dmsg0(50, "Open database\n");
112    jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user,
113                             jcr->catalog->db_password, jcr->catalog->db_address,
114                             jcr->catalog->db_port, jcr->catalog->db_socket,
115                             jcr->catalog->mult_db_connections);
116    if (!jcr->db || !db_open_database(jcr, jcr->db)) {
117       Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
118                  jcr->catalog->db_name);
119       if (jcr->db) {
120          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
121       }
122       goto bail_out;
123    }
124    Dmsg0(50, "DB opened\n");
125
126    if (!jcr->fname) {
127       jcr->fname = get_pool_memory(PM_FNAME);
128    }
129    if (!jcr->pool_source) {
130       jcr->pool_source = get_pool_memory(PM_MESSAGE);
131       pm_strcpy(jcr->pool_source, _("unknown source"));
132    }
133    if (!jcr->storage_source) {
134       jcr->storage_source = get_pool_memory(PM_MESSAGE);
135       pm_strcpy(jcr->storage_source, _("unknown source"));
136    }
137
138    /*
139     * Create Job record
140     */
141    init_jcr_job_record(jcr);
142    if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
143       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
144       goto bail_out;
145    }
146    jcr->JobId = jcr->jr.JobId;
147    Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
148        jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
149
150    generate_daemon_event(jcr, "JobStart");
151
152    if (!get_or_create_client_record(jcr)) {
153       goto bail_out;
154    }
155
156    if (job_canceled(jcr)) {
157       goto bail_out;
158    }
159
160
161    /*
162     * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
163     *  this allows us to setup a proper job start record for restarting
164     *  in case of later errors.
165     */
166    switch (jcr->JobType) {
167    case JT_BACKUP:
168       if (!do_backup_init(jcr)) {
169          backup_cleanup(jcr, JS_ErrorTerminated);
170       }
171       break;
172    case JT_VERIFY:
173       if (!do_verify_init(jcr)) {
174          verify_cleanup(jcr, JS_ErrorTerminated);
175       }
176       break;
177    case JT_RESTORE:
178       if (!do_restore_init(jcr)) {
179          restore_cleanup(jcr, JS_ErrorTerminated);
180       }
181       break;
182    case JT_ADMIN:
183       if (!do_admin_init(jcr)) {
184          admin_cleanup(jcr, JS_ErrorTerminated);
185       }
186       break;
187    case JT_MIGRATE:
188       if (!do_migration_init(jcr)) { 
189          migration_cleanup(jcr, JS_ErrorTerminated);
190       }
191       break;
192    default:
193       Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
194       set_jcr_job_status(jcr, JS_ErrorTerminated);
195       break;
196    }
197
198    generate_job_event(jcr, "JobInit");
199
200    Dmsg0(200, "Add jrc to work queue\n");
201    return true;
202
203 bail_out:
204    return false;
205 }
206
207
208 /*
209  * This is the engine called by jobq.c:jobq_add() when we were pulled
210  *  from the work queue.
211  *  At this point, we are running in our own thread and all
212  *    necessary resources are allocated -- see jobq.c
213  */
214 static void *job_thread(void *arg)
215 {
216    JCR *jcr = (JCR *)arg;
217
218    jcr->my_thread_id = pthread_self();
219    pthread_detach(jcr->my_thread_id);
220    sm_check(__FILE__, __LINE__, true);
221
222    Dmsg0(200, "=====Start Job=========\n");
223    set_jcr_job_status(jcr, JS_Running);   /* this will be set only if no error */
224    jcr->start_time = time(NULL);      /* set the real start time */
225    jcr->jr.StartTime = jcr->start_time;
226
227    if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
228        (utime_t)(jcr->start_time - jcr->sched_time)) {
229       Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
230       set_jcr_job_status(jcr, JS_Canceled);
231    }
232
233    /* TODO : check if it is used somewhere */
234    if (jcr->job->RunScripts == NULL) {
235       Dmsg0(200, "Warning, job->RunScripts is empty\n");
236       jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
237    }
238
239    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
240       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
241    }
242
243    if (job_canceled(jcr)) {
244       update_job_end_record(jcr);
245    } else {
246       /* Run any script BeforeJob on dird */
247       run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
248
249       /*
250        * We re-update the job start record so that the start
251        *  time is set after the run before job.  This avoids
252        *  that any files created by the run before job will
253        *  be saved twice.  They will be backed up in the current
254        *  job, but not in the next one unless they are changed.
255        *  Without this, they will be backed up in this job and
256        *  in the next job run because in that case, their date
257        *   is after the start of this run.
258        */
259       jcr->start_time = time(NULL);
260       jcr->jr.StartTime = jcr->start_time;
261       if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
262          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
263       }
264       generate_job_event(jcr, "JobRun");
265
266       switch (jcr->JobType) {
267       case JT_BACKUP:
268          if (do_backup(jcr)) {
269             do_autoprune(jcr);
270          } else {
271             backup_cleanup(jcr, JS_ErrorTerminated);
272          }
273          break;
274       case JT_VERIFY:
275          if (do_verify(jcr)) {
276             do_autoprune(jcr);
277          } else {
278             verify_cleanup(jcr, JS_ErrorTerminated);
279          }
280          break;
281       case JT_RESTORE:
282          if (do_restore(jcr)) {
283             do_autoprune(jcr);
284          } else {
285             restore_cleanup(jcr, JS_ErrorTerminated);
286          }
287          break;
288       case JT_ADMIN:
289          if (do_admin(jcr)) {
290             do_autoprune(jcr);
291          } else {
292             admin_cleanup(jcr, JS_ErrorTerminated);
293          }
294          break;
295       case JT_MIGRATE:
296       case JT_COPY:
297       case JT_ARCHIVE:
298          if (do_migration(jcr)) {
299             do_autoprune(jcr);
300          } else {
301             migration_cleanup(jcr, JS_ErrorTerminated);
302          }
303          break;
304       default:
305          Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
306          break;
307       }
308
309       run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
310
311       /* Send off any queued messages */
312       if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
313          dequeue_messages(jcr);
314       }
315    }
316
317    generate_daemon_event(jcr, "JobEnd");
318    Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
319    sm_check(__FILE__, __LINE__, true);
320    return NULL;
321 }
322
323
324 /*
325  * Cancel a job -- typically called by the UA (Console program), but may also
326  *              be called by the job watchdog.
327  *
328  *  Returns: true  if cancel appears to be successful
329  *           false on failure. Message sent to ua->jcr.
330  */
331 bool cancel_job(UAContext *ua, JCR *jcr)
332 {
333    BSOCK *sd, *fd;
334
335    set_jcr_job_status(jcr, JS_Canceled);
336
337    switch (jcr->JobStatus) {
338    case JS_Created:
339    case JS_WaitJobRes:
340    case JS_WaitClientRes:
341    case JS_WaitStoreRes:
342    case JS_WaitPriority:
343    case JS_WaitMaxJobs:
344    case JS_WaitStartTime:
345       bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"),
346               jcr->JobId, jcr->Job);
347       jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
348       return true;
349
350    default:
351       /* Cancel File daemon */
352       if (jcr->file_bsock) {
353          ua->jcr->client = jcr->client;
354          if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
355             bsendmsg(ua, _("Failed to connect to File daemon.\n"));
356             return 0;
357          }
358          Dmsg0(200, "Connected to file daemon\n");
359          fd = ua->jcr->file_bsock;
360          bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
361          while (bnet_recv(fd) >= 0) {
362             bsendmsg(ua, "%s", fd->msg);
363          }
364          bnet_sig(fd, BNET_TERMINATE);
365          bnet_close(fd);
366          ua->jcr->file_bsock = NULL;
367       }
368
369       /* Cancel Storage daemon */
370       if (jcr->store_bsock) {
371          if (!ua->jcr->wstorage) {
372             if (jcr->rstorage) {
373                copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
374             } else {
375                copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
376             }
377          } else {
378             if (jcr->rstorage) {
379                set_wstorage(ua->jcr, jcr->rstore);
380             } else {
381                set_wstorage(ua->jcr, jcr->wstore);
382             }
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       /*
692        * Keep the flag (last arg) set to false otherwise old FileSets will
693        * get new MD5 sums and the user will get Full backups on everything
694        */
695       bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
696       bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
697    } else {
698       Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
699    }
700    if (!jcr->fileset->ignore_fs_changes ||
701        !db_get_fileset_record(jcr, jcr->db, &fsr)) {
702       if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
703          Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
704             fsr.FileSet, db_strerror(jcr->db));
705          return false;
706       }
707    }
708    jcr->jr.FileSetId = fsr.FileSetId;
709    bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
710    Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
711       jcr->jr.FileSetId);
712    return true;
713 }
714
715 void init_jcr_job_record(JCR *jcr)
716 {
717    jcr->jr.SchedTime = jcr->sched_time;
718    jcr->jr.StartTime = jcr->start_time;
719    jcr->jr.EndTime = 0;               /* perhaps rescheduled, clear it */
720    jcr->jr.JobType = jcr->JobType;
721    jcr->jr.JobLevel = jcr->JobLevel;
722    jcr->jr.JobStatus = jcr->JobStatus;
723    jcr->jr.JobId = jcr->JobId;
724    bstrncpy(jcr->jr.Name, jcr->job->hdr.name, sizeof(jcr->jr.Name));
725    bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
726 }
727
728 /*
729  * Write status and such in DB
730  */
731 void update_job_end_record(JCR *jcr)
732 {
733    jcr->jr.EndTime = time(NULL);
734    jcr->end_time = jcr->jr.EndTime;
735    jcr->jr.JobId = jcr->JobId;
736    jcr->jr.JobStatus = jcr->JobStatus;
737    jcr->jr.JobFiles = jcr->JobFiles;
738    jcr->jr.JobBytes = jcr->JobBytes;
739    jcr->jr.VolSessionId = jcr->VolSessionId;
740    jcr->jr.VolSessionTime = jcr->VolSessionTime;
741    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
742       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
743          db_strerror(jcr->db));
744    }
745 }
746
747 /*
748  * Takes base_name and appends (unique) current
749  *   date and time to form unique job name.
750  *
751  *  Returns: unique job name in jcr->Job
752  *    date/time in jcr->start_time
753  */
754 void create_unique_job_name(JCR *jcr, const char *base_name)
755 {
756    /* Job start mutex */
757    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
758    static time_t last_start_time = 0;
759    time_t now;
760    struct tm tm;
761    char dt[MAX_TIME_LENGTH];
762    char name[MAX_NAME_LENGTH];
763    char *p;
764
765    /* Guarantee unique start time -- maximum one per second, and
766     * thus unique Job Name
767     */
768    P(mutex);                          /* lock creation of jobs */
769    now = time(NULL);
770    while (now == last_start_time) {
771       bmicrosleep(0, 500000);
772       now = time(NULL);
773    }
774    last_start_time = now;
775    V(mutex);                          /* allow creation of jobs */
776    jcr->start_time = now;
777    /* Form Unique JobName */
778    (void)localtime_r(&now, &tm);
779    /* Use only characters that are permitted in Windows filenames */
780    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
781    bstrncpy(name, base_name, sizeof(name));
782    name[sizeof(name)-22] = 0;          /* truncate if too long */
783    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
784    /* Convert spaces into underscores */
785    for (p=jcr->Job; *p; p++) {
786       if (*p == ' ') {
787          *p = '_';
788       }
789    }
790 }
791
792 /* Called directly from job rescheduling */
793 void dird_free_jcr_pointers(JCR *jcr)
794 {
795    if (jcr->sd_auth_key) {
796       free(jcr->sd_auth_key);
797       jcr->sd_auth_key = NULL;
798    }
799    if (jcr->where) {
800       free(jcr->where);
801       jcr->where = NULL;
802    }
803    if (jcr->file_bsock) {
804       Dmsg0(200, "Close File bsock\n");
805       bnet_close(jcr->file_bsock);
806       jcr->file_bsock = NULL;
807    }
808    if (jcr->store_bsock) {
809       Dmsg0(200, "Close Store bsock\n");
810       bnet_close(jcr->store_bsock);
811       jcr->store_bsock = NULL;
812    }
813    if (jcr->fname) {
814       Dmsg0(200, "Free JCR fname\n");
815       free_pool_memory(jcr->fname);
816       jcr->fname = NULL;
817    }
818    if (jcr->pool_source) {
819       free_pool_memory(jcr->pool_source);
820       jcr->pool_source = NULL;
821    }
822    if (jcr->storage_source) {
823       free_pool_memory(jcr->storage_source);
824       jcr->storage_source = NULL;
825    }
826    if (jcr->stime) {
827       Dmsg0(200, "Free JCR stime\n");
828       free_pool_memory(jcr->stime);
829       jcr->stime = NULL;
830    }
831    if (jcr->RestoreBootstrap) {
832       free(jcr->RestoreBootstrap);
833       jcr->RestoreBootstrap = NULL;
834    }
835    if (jcr->client_uname) {
836       free_pool_memory(jcr->client_uname);
837       jcr->client_uname = NULL;
838    }
839    if (jcr->attr) {
840       free_pool_memory(jcr->attr);
841       jcr->attr = NULL;
842    }
843    if (jcr->ar) {
844       free(jcr->ar);
845       jcr->ar = NULL;
846    }
847 }
848
849 /*
850  * Free the Job Control Record if no one is still using it.
851  *  Called from main free_jcr() routine in src/lib/jcr.c so
852  *  that we can do our Director specific cleanup of the jcr.
853  */
854 void dird_free_jcr(JCR *jcr)
855 {
856    Dmsg0(200, "Start dird free_jcr\n");
857
858    dird_free_jcr_pointers(jcr);
859    if (jcr->term_wait_inited) {
860       pthread_cond_destroy(&jcr->term_wait);
861       jcr->term_wait_inited = false;
862    }
863
864    /* Delete lists setup to hold storage pointers */
865    free_rwstorage(jcr);
866
867    jcr->job_end_push.destroy();
868    Dmsg0(200, "End dird free_jcr\n");
869 }
870
871 /*
872  * Set some defaults in the JCR necessary to
873  * run. These items are pulled from the job
874  * definition as defaults, but can be overridden
875  * later either by the Run record in the Schedule resource,
876  * or by the Console program.
877  */
878 void set_jcr_defaults(JCR *jcr, JOB *job)
879 {
880    jcr->job = job;
881    jcr->JobType = job->JobType;
882    switch (jcr->JobType) {
883    case JT_ADMIN:
884    case JT_RESTORE:
885       jcr->JobLevel = L_NONE;
886       break;
887    default:
888       jcr->JobLevel = job->JobLevel;
889       break;
890    }
891    if (!jcr->fname) {
892       jcr->fname = get_pool_memory(PM_FNAME);
893    }
894    if (!jcr->pool_source) {
895       jcr->pool_source = get_pool_memory(PM_MESSAGE);
896       pm_strcpy(jcr->pool_source, _("unknown source"));
897    }
898    if (!jcr->storage_source) {
899       jcr->storage_source = get_pool_memory(PM_MESSAGE);
900       pm_strcpy(jcr->storage_source, _("unknown source"));
901    }
902    jcr->JobPriority = job->Priority;
903    /* Copy storage definitions -- deleted in dir_free_jcr above */
904    copy_rwstorage(jcr, job->storage, _("Job resource"));
905    jcr->client = job->client;
906    if (!jcr->client_name) {
907       jcr->client_name = get_pool_memory(PM_NAME);
908    }
909    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
910    pm_strcpy(jcr->pool_source, _("Job resource"));
911    jcr->pool = job->pool;
912    jcr->full_pool = job->full_pool;
913    jcr->inc_pool = job->inc_pool;
914    jcr->diff_pool = job->diff_pool;
915    jcr->catalog = job->client->catalog;
916    jcr->fileset = job->fileset;
917    jcr->messages = job->messages;
918    jcr->spool_data = job->spool_data;
919    jcr->write_part_after_job = job->write_part_after_job;
920    if (jcr->RestoreBootstrap) {
921       free(jcr->RestoreBootstrap);
922       jcr->RestoreBootstrap = NULL;
923    }
924    /* This can be overridden by Console program */
925    if (job->RestoreBootstrap) {
926       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
927    }
928    /* This can be overridden by Console program */
929    jcr->verify_job = job->verify_job;
930    /* If no default level given, set one */
931    if (jcr->JobLevel == 0) {
932       switch (jcr->JobType) {
933       case JT_VERIFY:
934          jcr->JobLevel = L_VERIFY_CATALOG;
935          break;
936       case JT_BACKUP:
937          jcr->JobLevel = L_INCREMENTAL;
938          break;
939       case JT_RESTORE:
940       case JT_ADMIN:
941          jcr->JobLevel = L_NONE;
942          break;
943       default:
944          break;
945       }
946    }
947 }
948
949 /* 
950  * Copy the storage definitions from an alist to the JCR
951  */
952 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
953 {
954    copy_rstorage(jcr, storage, where);
955    copy_wstorage(jcr, storage, where);
956 }
957
958
959 /* Set storage override */
960 void set_rwstorage(JCR *jcr, STORE *store)
961 {
962    set_rstorage(jcr, store);
963    set_wstorage(jcr, store);
964 }
965
966 void free_rwstorage(JCR *jcr)
967 {
968    free_rstorage(jcr);
969    free_wstorage(jcr);
970 }
971
972 /* 
973  * Copy the storage definitions from an alist to the JCR
974  */
975 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
976 {
977    if (storage) {
978       STORE *st;
979       if (jcr->rstorage) {
980          delete jcr->rstorage;
981       }
982       jcr->rstorage = New(alist(10, not_owned_by_alist));
983       foreach_alist(st, storage) {
984          jcr->rstorage->append(st);
985       }
986       pm_strcpy(jcr->storage_source, where);
987    }               
988    if (jcr->rstorage) {
989       jcr->rstore = (STORE *)jcr->rstorage->first();
990    }
991 }
992
993
994 /* Set storage override */
995 void set_rstorage(JCR *jcr, STORE *store)
996 {
997    STORE *storage;
998
999    jcr->rstore = store;
1000    foreach_alist(storage, jcr->rstorage) {
1001       if (store == storage) {
1002          return;
1003       }
1004    }
1005    /* Store not in list, so add it */
1006    jcr->rstorage->prepend(store);
1007 }
1008
1009 void free_rstorage(JCR *jcr)
1010 {
1011    if (jcr->rstorage) {
1012       delete jcr->rstorage;
1013       jcr->rstorage = NULL;
1014    }
1015    jcr->rstore = NULL;
1016 }
1017
1018 /* 
1019  * Copy the storage definitions from an alist to the JCR
1020  */
1021 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1022 {
1023    if (storage) {
1024       STORE *st;
1025       if (jcr->wstorage) {
1026          delete jcr->wstorage;
1027       }
1028       jcr->wstorage = New(alist(10, not_owned_by_alist));
1029       foreach_alist(st, storage) {
1030          jcr->wstorage->append(st);
1031       }
1032       pm_strcpy(jcr->storage_source, where);
1033    }               
1034    if (jcr->wstorage) {
1035       jcr->wstore = (STORE *)jcr->wstorage->first();
1036    }
1037 }
1038
1039
1040 /* Set storage override */
1041 void set_wstorage(JCR *jcr, STORE *store)
1042 {
1043    STORE *storage;
1044
1045    jcr->wstore = store;
1046    foreach_alist(storage, jcr->wstorage) {
1047       if (store == storage) {
1048          return;
1049       }
1050    }
1051    /* Store not in list, so add it */
1052    jcr->wstorage->prepend(store);
1053 }
1054
1055 void free_wstorage(JCR *jcr)
1056 {
1057    if (jcr->wstorage) {
1058       delete jcr->wstorage;
1059       jcr->wstorage = NULL;
1060    }
1061    jcr->wstore = NULL;
1062 }
1063
1064
1065
1066 void create_clones(JCR *jcr)
1067 {
1068    /*
1069     * Fire off any clone jobs (run directives)
1070     */
1071    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1072    if (!jcr->cloned && jcr->job->run_cmds) {
1073       char *runcmd;
1074       JOB *job = jcr->job;
1075       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1076       UAContext *ua = new_ua_context(jcr);
1077       ua->batch = true;
1078       foreach_alist(runcmd, job->run_cmds) {
1079          cmd = edit_job_codes(jcr, cmd, runcmd, "");              
1080          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1081          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1082          parse_ua_args(ua);                 /* parse command */
1083          int stat = run_cmd(ua, ua->cmd);
1084          if (stat == 0) {
1085             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1086          } else {
1087             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1088          }
1089       }
1090       free_ua_context(ua);
1091       free_pool_memory(cmd);
1092    }
1093 }
1094
1095 bool create_restore_bootstrap_file(JCR *jcr)
1096 {
1097    RESTORE_CTX rx;
1098    UAContext *ua;
1099    memset(&rx, 0, sizeof(rx));
1100    rx.bsr = new_bsr();
1101    rx.JobIds = "";                       
1102    rx.bsr->JobId = jcr->previous_jr.JobId;
1103    ua = new_ua_context(jcr);
1104    complete_bsr(ua, rx.bsr);
1105    rx.bsr->fi = new_findex();
1106    rx.bsr->fi->findex = 1;
1107    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1108    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1109    if (jcr->ExpectedFiles == 0) {
1110       free_ua_context(ua);
1111       free_bsr(rx.bsr);
1112       return false;
1113    }
1114    free_ua_context(ua);
1115    free_bsr(rx.bsr);
1116    jcr->needs_sd = true;
1117    return true;
1118 }