]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
kes Add additional messages when Job canceled automatically for
[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    Bacula® - The Network Backup Solution
11
12    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
13
14    The main author of Bacula is Kern Sibbald, with contributions from
15    many others, a complete list can be found in the file AUTHORS.
16    This program is Free Software; you can redistribute it and/or
17    modify it under the terms of version two of the GNU General Public
18    License as published by the Free Software Foundation plus additions
19    that are listed in the file LICENSE.
20
21    This program is distributed in the hope that it will be useful, but
22    WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24    General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program; if not, write to the Free Software
28    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29    02110-1301, USA.
30
31    Bacula® is a registered trademark of John Walker.
32    The licensor of Bacula is the Free Software Foundation Europe
33    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
34    Switzerland, email:ftf@fsfeurope.org.
35 */
36
37 #include "bacula.h"
38 #include "dird.h"
39
40 /* Forward referenced subroutines */
41 static void *job_thread(void *arg);
42 static void job_monitor_watchdog(watchdog_t *self);
43 static void job_monitor_destructor(watchdog_t *self);
44 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr);
45 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr);
46
47 /* Imported subroutines */
48 extern void term_scheduler();
49 extern void term_ua_server();
50
51 /* Imported variables */
52
53 jobq_t job_queue;
54
55 void init_job_server(int max_workers)
56 {
57    int stat;
58    watchdog_t *wd;
59
60    if ((stat = jobq_init(&job_queue, max_workers, job_thread)) != 0) {
61       berrno be;
62       Emsg1(M_ABORT, 0, _("Could not init job queue: ERR=%s\n"), be.strerror(stat));
63    }
64    wd = new_watchdog();
65    wd->callback = job_monitor_watchdog;
66    wd->destructor = job_monitor_destructor;
67    wd->one_shot = false;
68    wd->interval = 60;
69    wd->data = new_control_jcr("*JobMonitor*", JT_SYSTEM);
70    register_watchdog(wd);
71 }
72
73 void term_job_server()
74 {
75    jobq_destroy(&job_queue);          /* ignore any errors */
76 }
77
78 /*
79  * Run a job -- typically called by the scheduler, but may also
80  *              be called by the UA (Console program).
81  *
82  *  Returns: 0 on failure
83  *           JobId on success
84  *
85  */
86 JobId_t run_job(JCR *jcr)
87 {
88    int stat;
89    if (setup_job(jcr)) {
90       Dmsg0(200, "Add jrc to work queue\n");
91       /* Queue the job to be run */
92       if ((stat = jobq_add(&job_queue, jcr)) != 0) {
93          berrno be;
94          Jmsg(jcr, M_FATAL, 0, _("Could not add job queue: ERR=%s\n"), be.strerror(stat));
95          return 0;
96       }
97       return jcr->JobId;
98    }
99    return 0;
100 }            
101
102 bool setup_job(JCR *jcr) 
103 {
104    int errstat;
105
106    jcr->lock();
107    sm_check(__FILE__, __LINE__, true);
108    init_msg(jcr, jcr->messages);
109
110    /* Initialize termination condition variable */
111    if ((errstat = pthread_cond_init(&jcr->term_wait, NULL)) != 0) {
112       berrno be;
113       Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.strerror(errstat));
114       goto bail_out;
115    }
116    jcr->term_wait_inited = true;
117
118    create_unique_job_name(jcr, jcr->job->name());
119    set_jcr_job_status(jcr, JS_Created);
120    jcr->unlock();
121
122    /*
123     * Open database
124     */
125    Dmsg0(50, "Open database\n");
126    jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user,
127                             jcr->catalog->db_password, jcr->catalog->db_address,
128                             jcr->catalog->db_port, jcr->catalog->db_socket,
129                             jcr->catalog->mult_db_connections);
130    if (!jcr->db || !db_open_database(jcr, jcr->db)) {
131       Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
132                  jcr->catalog->db_name);
133       if (jcr->db) {
134          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
135       }
136       goto bail_out;
137    }
138    Dmsg0(50, "DB opened\n");
139
140    if (!jcr->fname) {
141       jcr->fname = get_pool_memory(PM_FNAME);
142    }
143    if (!jcr->pool_source) {
144       jcr->pool_source = get_pool_memory(PM_MESSAGE);
145       pm_strcpy(jcr->pool_source, _("unknown source"));
146    }
147    Dmsg2(500, "pool=%s (From %s)\n", jcr->pool->name(), jcr->pool_source);
148    if (jcr->JobType == JT_MIGRATE) {
149       if (!jcr->rpool_source) {
150          jcr->rpool_source = get_pool_memory(PM_MESSAGE);
151          pm_strcpy(jcr->rpool_source, _("unknown source"));
152       }
153    }
154
155    /*
156     * Create Job record
157     */
158    init_jcr_job_record(jcr);
159    if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
160       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
161       goto bail_out;
162    }
163    jcr->JobId = jcr->jr.JobId;
164    Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
165        jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
166
167    if (!get_or_create_client_record(jcr)) {
168       goto bail_out;
169    }
170
171    generate_daemon_event(jcr, "JobStart");
172
173    if (job_canceled(jcr)) {
174       goto bail_out;
175    }
176
177    /*
178     * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
179     *  this allows us to setup a proper job start record for restarting
180     *  in case of later errors.
181     */
182    switch (jcr->JobType) {
183    case JT_BACKUP:
184       if (!do_backup_init(jcr)) {
185          backup_cleanup(jcr, JS_ErrorTerminated);
186       }
187       break;
188    case JT_VERIFY:
189       if (!do_verify_init(jcr)) {
190          verify_cleanup(jcr, JS_ErrorTerminated);
191       }
192       break;
193    case JT_RESTORE:
194       if (!do_restore_init(jcr)) {
195          restore_cleanup(jcr, JS_ErrorTerminated);
196       }
197       break;
198    case JT_ADMIN:
199       if (!do_admin_init(jcr)) {
200          admin_cleanup(jcr, JS_ErrorTerminated);
201       }
202       break;
203    case JT_MIGRATE:
204       if (!do_migration_init(jcr)) { 
205          migration_cleanup(jcr, JS_ErrorTerminated);
206       }
207       break;
208    default:
209       Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
210       set_jcr_job_status(jcr, JS_ErrorTerminated);
211       break;
212    }
213
214    generate_job_event(jcr, "JobInit");
215    return true;
216
217 bail_out:
218    return false;
219 }
220
221 void update_job_end(JCR *jcr, int TermCode)
222 {
223    dequeue_messages(jcr);             /* display any queued messages */
224    set_jcr_job_status(jcr, TermCode);
225    run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
226    update_job_end_record(jcr);
227 }
228
229 /*
230  * This is the engine called by jobq.c:jobq_add() when we were pulled
231  *  from the work queue.
232  *  At this point, we are running in our own thread and all
233  *    necessary resources are allocated -- see jobq.c
234  */
235 static void *job_thread(void *arg)
236 {
237    JCR *jcr = (JCR *)arg;
238
239    jcr->my_thread_id = pthread_self();
240    pthread_detach(jcr->my_thread_id);
241    sm_check(__FILE__, __LINE__, true);
242
243    Dmsg0(200, "=====Start Job=========\n");
244    set_jcr_job_status(jcr, JS_Running);   /* this will be set only if no error */
245    jcr->start_time = time(NULL);      /* set the real start time */
246    jcr->jr.StartTime = jcr->start_time;
247
248    if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
249        (utime_t)(jcr->start_time - jcr->sched_time)) {
250       set_jcr_job_status(jcr, JS_Canceled);
251       Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
252    }
253
254    /* TODO : check if it is used somewhere */
255    if (jcr->job->RunScripts == NULL) {
256       Dmsg0(200, "Warning, job->RunScripts is empty\n");
257       jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
258    }
259
260    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
261       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
262    }
263
264    /* Run any script BeforeJob on dird */
265    run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
266
267    if (job_canceled(jcr)) {
268       update_job_end(jcr, jcr->JobStatus);
269
270    } else {
271       /*
272        * We re-update the job start record so that the start
273        *  time is set after the run before job.  This avoids
274        *  that any files created by the run before job will
275        *  be saved twice.  They will be backed up in the current
276        *  job, but not in the next one unless they are changed.
277        *  Without this, they will be backed up in this job and
278        *  in the next job run because in that case, their date
279        *   is after the start of this run.
280        */
281       jcr->start_time = time(NULL);
282       jcr->jr.StartTime = jcr->start_time;
283       if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
284          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
285       }
286       generate_job_event(jcr, "JobRun");
287
288       switch (jcr->JobType) {
289       case JT_BACKUP:
290          if (do_backup(jcr)) {
291             do_autoprune(jcr);
292          } else {
293             backup_cleanup(jcr, JS_ErrorTerminated);
294          }
295          break;
296       case JT_VERIFY:
297          if (do_verify(jcr)) {
298             do_autoprune(jcr);
299          } else {
300             verify_cleanup(jcr, JS_ErrorTerminated);
301          }
302          break;
303       case JT_RESTORE:
304          if (do_restore(jcr)) {
305             do_autoprune(jcr);
306          } else {
307             restore_cleanup(jcr, JS_ErrorTerminated);
308          }
309          break;
310       case JT_ADMIN:
311          if (do_admin(jcr)) {
312             do_autoprune(jcr);
313          } else {
314             admin_cleanup(jcr, JS_ErrorTerminated);
315          }
316          break;
317       case JT_MIGRATE:
318       case JT_COPY:
319       case JT_ARCHIVE:
320          if (do_migration(jcr)) {
321             do_autoprune(jcr);
322          } else {
323             migration_cleanup(jcr, JS_ErrorTerminated);
324          }
325          break;
326       default:
327          Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
328          break;
329       }
330
331       /* Send off any queued messages */
332       if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
333          dequeue_messages(jcr);
334       }
335    }
336
337    generate_daemon_event(jcr, "JobEnd");
338    Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
339    sm_check(__FILE__, __LINE__, true);
340    return NULL;
341 }
342
343
344 /*
345  * Cancel a job -- typically called by the UA (Console program), but may also
346  *              be called by the job watchdog.
347  *
348  *  Returns: true  if cancel appears to be successful
349  *           false on failure. Message sent to ua->jcr.
350  */
351 bool cancel_job(UAContext *ua, JCR *jcr)
352 {
353    BSOCK *sd, *fd;
354    char ed1[50];
355
356    set_jcr_job_status(jcr, JS_Canceled);
357
358    switch (jcr->JobStatus) {
359    case JS_Created:
360    case JS_WaitJobRes:
361    case JS_WaitClientRes:
362    case JS_WaitStoreRes:
363    case JS_WaitPriority:
364    case JS_WaitMaxJobs:
365    case JS_WaitStartTime:
366       bsendmsg(ua, _("JobId %s, Job %s marked to be canceled.\n"),
367               edit_uint64(jcr->JobId, ed1), jcr->Job);
368       jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
369       return true;
370
371    default:
372       /* Cancel File daemon */
373       if (jcr->file_bsock) {
374          ua->jcr->client = jcr->client;
375          if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
376             bsendmsg(ua, _("Failed to connect to File daemon.\n"));
377             return 0;
378          }
379          Dmsg0(200, "Connected to file daemon\n");
380          fd = ua->jcr->file_bsock;
381          bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
382          while (bnet_recv(fd) >= 0) {
383             bsendmsg(ua, "%s", fd->msg);
384          }
385          bnet_sig(fd, BNET_TERMINATE);
386          bnet_close(fd);
387          ua->jcr->file_bsock = NULL;
388       }
389
390       /* Cancel Storage daemon */
391       if (jcr->store_bsock) {
392          if (!ua->jcr->wstorage) {
393             if (jcr->rstorage) {
394                copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
395             } else {
396                copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
397             }
398          } else {
399             USTORE store;
400             if (jcr->rstorage) {
401                store.store = jcr->rstore;
402                pm_strcpy(store.store_source, jcr->rstore_source);
403             } else {
404                store.store = jcr->wstore;
405                pm_strcpy(store.store_source, jcr->wstore_source);
406             }
407             set_wstorage(ua->jcr, &store);
408          }
409
410          if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
411             bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
412             return false;
413          }
414          Dmsg0(200, "Connected to storage daemon\n");
415          sd = ua->jcr->store_bsock;
416          bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
417          while (bnet_recv(sd) >= 0) {
418             bsendmsg(ua, "%s", sd->msg);
419          }
420          bnet_sig(sd, BNET_TERMINATE);
421          bnet_close(sd);
422          ua->jcr->store_bsock = NULL;
423       }
424    }
425
426    return true;
427 }
428
429
430 static void job_monitor_destructor(watchdog_t *self)
431 {
432    JCR *control_jcr = (JCR *)self->data;
433
434    free_jcr(control_jcr);
435 }
436
437 static void job_monitor_watchdog(watchdog_t *self)
438 {
439    JCR *control_jcr, *jcr;
440
441    control_jcr = (JCR *)self->data;
442
443    Dmsg1(800, "job_monitor_watchdog %p called\n", self);
444
445    foreach_jcr(jcr) {
446       bool cancel;
447
448       if (jcr->JobId == 0 || job_canceled(jcr)) {
449          Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
450          continue;
451       }
452
453       /* check MaxWaitTime */
454       if (job_check_maxwaittime(control_jcr, jcr)) {
455          set_jcr_job_status(jcr, JS_Canceled);
456          Jmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
457          cancel = true;
458       /* check MaxRunTime */
459       } else if (job_check_maxruntime(control_jcr, jcr)) {
460          set_jcr_job_status(jcr, JS_Canceled);
461          Jmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
462          cancel = true;
463       }
464
465       if (cancel) {
466          Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
467          UAContext *ua = new_ua_context(jcr);
468          ua->jcr = control_jcr;
469          cancel_job(ua, jcr);
470          free_ua_context(ua);
471          Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
472       }
473
474    }
475    /* Keep reference counts correct */
476    endeach_jcr(jcr);
477 }
478
479 /*
480  * Check if the maxwaittime has expired and it is possible
481  *  to cancel the job.
482  */
483 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
484 {
485    bool cancel = false;
486    bool ok_to_cancel = false;
487    JOB *job = jcr->job;
488
489    if (job_canceled(jcr)) {
490       return false;                /* already canceled */
491    }
492    if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
493        job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
494       return false;
495    } 
496    if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
497          (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
498       ok_to_cancel = true;
499    } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
500          (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
501       ok_to_cancel = true;
502    } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
503          (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
504       ok_to_cancel = true;
505    } else if (job->MaxWaitTime != 0 &&
506          (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
507       ok_to_cancel = true;
508    }
509    if (!ok_to_cancel) {
510       return false;
511    }
512
513 /*
514  * I don't see the need for all this -- kes 17Dec06
515  */
516 #ifdef xxx
517    Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, "
518          "checking status\n",
519          jcr->JobId, jcr->Job, job->MaxWaitTime);
520    switch (jcr->JobStatus) {
521    case JS_Created:
522    case JS_Blocked:
523    case JS_WaitFD:
524    case JS_WaitSD:
525    case JS_WaitStoreRes:
526    case JS_WaitClientRes:
527    case JS_WaitJobRes:
528    case JS_WaitPriority:
529    case JS_WaitMaxJobs:
530    case JS_WaitStartTime:
531       cancel = true;
532       Dmsg0(200, "JCR blocked in #1\n");
533       break;
534    case JS_Running:
535       Dmsg0(800, "JCR running, checking SD status\n");
536       switch (jcr->SDJobStatus) {
537       case JS_WaitMount:
538       case JS_WaitMedia:
539       case JS_WaitFD:
540          cancel = true;
541          Dmsg0(800, "JCR blocked in #2\n");
542          break;
543       default:
544          Dmsg0(800, "JCR not blocked in #2\n");
545          break;
546       }
547       break;
548    case JS_Terminated:
549    case JS_ErrorTerminated:
550    case JS_Canceled:
551    case JS_FatalError:
552       Dmsg0(800, "JCR already dead in #3\n");
553       break;
554    default:
555       Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
556             jcr->JobStatus);
557    }
558    Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n",
559          cancel ? "" : "do not ", jcr, jcr->job);
560 #endif
561    return cancel;
562 }
563
564 /*
565  * Check if maxruntime has expired and if the job can be
566  *   canceled.
567  */
568 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
569 {
570    bool cancel = false;
571
572    if (jcr->job->MaxRunTime == 0 || job_canceled(jcr)) {
573       return false;
574    }
575    if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
576       Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
577             jcr, jcr->Job, jcr->job->MaxRunTime);
578       return false;
579    }
580
581 #ifdef xxx
582    switch (jcr->JobStatus) {
583    case JS_Created:
584    case JS_Running:
585    case JS_Blocked:
586    case JS_WaitFD:
587    case JS_WaitSD:
588    case JS_WaitStoreRes:
589    case JS_WaitClientRes:
590    case JS_WaitJobRes:
591    case JS_WaitPriority:
592    case JS_WaitMaxJobs:
593    case JS_WaitStartTime:
594    case JS_Differences:
595       cancel = true;
596       break;
597    case JS_Terminated:
598    case JS_ErrorTerminated:
599    case JS_Canceled:
600    case JS_FatalError:
601       cancel = false;
602       break;
603    default:
604       Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
605             jcr->JobStatus);
606    }
607
608    Dmsg3(200, "MaxRunTime result: %scancel JCR %p (%s)\n",
609          cancel ? "" : "do not ", jcr, jcr->job);
610 #endif
611    return cancel;
612 }
613
614 /*
615  * Get or create a Pool record with the given name.
616  * Returns: 0 on error
617  *          poolid if OK
618  */
619 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
620 {
621    POOL_DBR pr;
622
623    memset(&pr, 0, sizeof(pr));
624    bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
625    Dmsg1(010, "get_or_create_pool=%s\n", pool_name);
626
627    while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
628       /* Try to create the pool */
629       if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
630          Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
631             db_strerror(jcr->db));
632          return 0;
633       } else {
634          Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
635       }
636    }
637    return pr.PoolId;
638 }
639
640 void apply_pool_overrides(JCR *jcr)
641 {
642    if (jcr->run_pool_override) {
643       pm_strcpy(jcr->pool_source, _("Run pool override"));
644    }
645    /*
646     * Apply any level related Pool selections
647     */
648    switch (jcr->JobLevel) {
649    case L_FULL:
650       if (jcr->full_pool) {
651          jcr->pool = jcr->full_pool;
652          if (jcr->run_full_pool_override) {
653             pm_strcpy(jcr->pool_source, _("Run FullPool override"));
654          } else {
655             pm_strcpy(jcr->pool_source, _("Job FullPool override"));
656          }
657       }
658       break;
659    case L_INCREMENTAL:
660       if (jcr->inc_pool) {
661          jcr->pool = jcr->inc_pool;
662          if (jcr->run_inc_pool_override) {
663             pm_strcpy(jcr->pool_source, _("Run IncPool override"));
664          } else {
665             pm_strcpy(jcr->pool_source, _("Job IncPool override"));
666          }
667       }
668       break;
669    case L_DIFFERENTIAL:
670       if (jcr->diff_pool) {
671          jcr->pool = jcr->diff_pool;
672          if (jcr->run_diff_pool_override) {
673             pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
674          } else {
675             pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
676          }
677       }
678       break;
679    }
680 }
681
682
683 /*
684  * Get or create a Client record for this Job
685  */
686 bool get_or_create_client_record(JCR *jcr)
687 {
688    CLIENT_DBR cr;
689
690    memset(&cr, 0, sizeof(cr));
691    bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
692    cr.AutoPrune = jcr->client->AutoPrune;
693    cr.FileRetention = jcr->client->FileRetention;
694    cr.JobRetention = jcr->client->JobRetention;
695    if (!jcr->client_name) {
696       jcr->client_name = get_pool_memory(PM_NAME);
697    }
698    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
699    if (!db_create_client_record(jcr, jcr->db, &cr)) {
700       Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
701          db_strerror(jcr->db));
702       return false;
703    }
704    jcr->jr.ClientId = cr.ClientId;
705    if (cr.Uname[0]) {
706       if (!jcr->client_uname) {
707          jcr->client_uname = get_pool_memory(PM_NAME);
708       }
709       pm_strcpy(jcr->client_uname, cr.Uname);
710    }
711    Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
712       jcr->jr.ClientId);
713    return true;
714 }
715
716 bool get_or_create_fileset_record(JCR *jcr)
717 {
718    FILESET_DBR fsr;
719    /*
720     * Get or Create FileSet record
721     */
722    memset(&fsr, 0, sizeof(FILESET_DBR));
723    bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
724    if (jcr->fileset->have_MD5) {
725       struct MD5Context md5c;
726       unsigned char digest[MD5HashSize];
727       memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
728       MD5Final(digest, &md5c);
729       /*
730        * Keep the flag (last arg) set to false otherwise old FileSets will
731        * get new MD5 sums and the user will get Full backups on everything
732        */
733       bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
734       bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
735    } else {
736       Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
737    }
738    if (!jcr->fileset->ignore_fs_changes ||
739        !db_get_fileset_record(jcr, jcr->db, &fsr)) {
740       if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
741          Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
742             fsr.FileSet, db_strerror(jcr->db));
743          return false;
744       }
745    }
746    jcr->jr.FileSetId = fsr.FileSetId;
747    bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
748    Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
749       jcr->jr.FileSetId);
750    return true;
751 }
752
753 void init_jcr_job_record(JCR *jcr)
754 {
755    jcr->jr.SchedTime = jcr->sched_time;
756    jcr->jr.StartTime = jcr->start_time;
757    jcr->jr.EndTime = 0;               /* perhaps rescheduled, clear it */
758    jcr->jr.JobType = jcr->JobType;
759    jcr->jr.JobLevel = jcr->JobLevel;
760    jcr->jr.JobStatus = jcr->JobStatus;
761    jcr->jr.JobId = jcr->JobId;
762    bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
763    bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
764 }
765
766 /*
767  * Write status and such in DB
768  */
769 void update_job_end_record(JCR *jcr)
770 {
771    jcr->jr.EndTime = time(NULL);
772    jcr->end_time = jcr->jr.EndTime;
773    jcr->jr.JobId = jcr->JobId;
774    jcr->jr.JobStatus = jcr->JobStatus;
775    jcr->jr.JobFiles = jcr->JobFiles;
776    jcr->jr.JobBytes = jcr->JobBytes;
777    jcr->jr.VolSessionId = jcr->VolSessionId;
778    jcr->jr.VolSessionTime = jcr->VolSessionTime;
779    jcr->jr.JobErrors = jcr->Errors;
780    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
781       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
782          db_strerror(jcr->db));
783    }
784 }
785
786 /*
787  * Takes base_name and appends (unique) current
788  *   date and time to form unique job name.
789  *
790  *  Returns: unique job name in jcr->Job
791  *    date/time in jcr->start_time
792  */
793 void create_unique_job_name(JCR *jcr, const char *base_name)
794 {
795    /* Job start mutex */
796    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
797    static time_t last_start_time = 0;
798    time_t now;
799    struct tm tm;
800    char dt[MAX_TIME_LENGTH];
801    char name[MAX_NAME_LENGTH];
802    char *p;
803
804    /* Guarantee unique start time -- maximum one per second, and
805     * thus unique Job Name
806     */
807    P(mutex);                          /* lock creation of jobs */
808    now = time(NULL);
809    while (now == last_start_time) {
810       bmicrosleep(0, 500000);
811       now = time(NULL);
812    }
813    last_start_time = now;
814    V(mutex);                          /* allow creation of jobs */
815    jcr->start_time = now;
816    /* Form Unique JobName */
817    (void)localtime_r(&now, &tm);
818    /* Use only characters that are permitted in Windows filenames */
819    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
820    bstrncpy(name, base_name, sizeof(name));
821    name[sizeof(name)-22] = 0;          /* truncate if too long */
822    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
823    /* Convert spaces into underscores */
824    for (p=jcr->Job; *p; p++) {
825       if (*p == ' ') {
826          *p = '_';
827       }
828    }
829 }
830
831 /* Called directly from job rescheduling */
832 void dird_free_jcr_pointers(JCR *jcr)
833 {
834    if (jcr->sd_auth_key) {
835       free(jcr->sd_auth_key);
836       jcr->sd_auth_key = NULL;
837    }
838    if (jcr->where) {
839       free(jcr->where);
840       jcr->where = NULL;
841    }
842    if (jcr->file_bsock) {
843       Dmsg0(200, "Close File bsock\n");
844       bnet_close(jcr->file_bsock);
845       jcr->file_bsock = NULL;
846    }
847    if (jcr->store_bsock) {
848       Dmsg0(200, "Close Store bsock\n");
849       bnet_close(jcr->store_bsock);
850       jcr->store_bsock = NULL;
851    }
852    if (jcr->fname) {
853       Dmsg0(200, "Free JCR fname\n");
854       free_pool_memory(jcr->fname);
855       jcr->fname = NULL;
856    }
857    if (jcr->pool_source) {
858       free_pool_memory(jcr->pool_source);
859       jcr->pool_source = NULL;
860    }
861    if (jcr->rpool_source) {
862       free_pool_memory(jcr->rpool_source);
863       jcr->rpool_source = NULL;
864    }
865    if (jcr->wstore_source) {
866       free_pool_memory(jcr->wstore_source);
867       jcr->wstore_source = NULL;
868    }
869    if (jcr->rstore_source) {
870       free_pool_memory(jcr->rstore_source);
871       jcr->rstore_source = NULL;
872    }
873    if (jcr->stime) {
874       Dmsg0(200, "Free JCR stime\n");
875       free_pool_memory(jcr->stime);
876       jcr->stime = NULL;
877    }
878    if (jcr->RestoreBootstrap) {
879       free(jcr->RestoreBootstrap);
880       jcr->RestoreBootstrap = NULL;
881    }
882    if (jcr->client_uname) {
883       free_pool_memory(jcr->client_uname);
884       jcr->client_uname = NULL;
885    }
886    if (jcr->attr) {
887       free_pool_memory(jcr->attr);
888       jcr->attr = NULL;
889    }
890    if (jcr->ar) {
891       free(jcr->ar);
892       jcr->ar = NULL;
893    }
894 }
895
896 /*
897  * Free the Job Control Record if no one is still using it.
898  *  Called from main free_jcr() routine in src/lib/jcr.c so
899  *  that we can do our Director specific cleanup of the jcr.
900  */
901 void dird_free_jcr(JCR *jcr)
902 {
903    Dmsg0(200, "Start dird free_jcr\n");
904
905    dird_free_jcr_pointers(jcr);
906    if (jcr->term_wait_inited) {
907       pthread_cond_destroy(&jcr->term_wait);
908       jcr->term_wait_inited = false;
909    }
910
911    /* Delete lists setup to hold storage pointers */
912    free_rwstorage(jcr);
913
914    jcr->job_end_push.destroy();
915    Dmsg0(200, "End dird free_jcr\n");
916 }
917
918 /* 
919  * The Job storage definition must be either in the Job record
920  *  or in the Pool record.  The Pool record overrides the Job 
921  *  record.
922  */
923 void get_job_storage(USTORE *store, JOB *job, RUN *run) 
924 {
925    if (run && run->pool && run->pool->storage) {
926       store->store = (STORE *)run->pool->storage->first();
927       pm_strcpy(store->store_source, _("Run pool override"));
928       return;
929    }
930    if (run && run->storage) {
931       store->store = run->storage;
932       pm_strcpy(store->store_source, _("Run storage override"));
933       return;
934    }
935    if (job->pool->storage) {
936       store->store = (STORE *)job->pool->storage->first();
937       pm_strcpy(store->store_source, _("Pool resource"));
938    } else {
939       store->store = (STORE *)job->storage->first();
940       pm_strcpy(store->store_source, _("Job resource"));
941    }
942 }
943
944 /*
945  * Set some defaults in the JCR necessary to
946  * run. These items are pulled from the job
947  * definition as defaults, but can be overridden
948  * later either by the Run record in the Schedule resource,
949  * or by the Console program.
950  */
951 void set_jcr_defaults(JCR *jcr, JOB *job)
952 {
953    jcr->job = job;
954    jcr->JobType = job->JobType;
955    switch (jcr->JobType) {
956    case JT_ADMIN:
957    case JT_RESTORE:
958       jcr->JobLevel = L_NONE;
959       break;
960    default:
961       jcr->JobLevel = job->JobLevel;
962       break;
963    }
964    if (!jcr->fname) {
965       jcr->fname = get_pool_memory(PM_FNAME);
966    }
967    if (!jcr->pool_source) {
968       jcr->pool_source = get_pool_memory(PM_MESSAGE);
969       pm_strcpy(jcr->pool_source, _("unknown source"));
970    }
971    jcr->JobPriority = job->Priority;
972    /* Copy storage definitions -- deleted in dir_free_jcr above */
973    if (job->storage) {
974       copy_rwstorage(jcr, job->storage, _("Job resource"));
975    } else {
976       copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
977    }
978    jcr->client = job->client;
979    if (!jcr->client_name) {
980       jcr->client_name = get_pool_memory(PM_NAME);
981    }
982    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
983    pm_strcpy(jcr->pool_source, _("Job resource"));
984    jcr->pool = job->pool;
985    jcr->full_pool = job->full_pool;
986    jcr->inc_pool = job->inc_pool;
987    jcr->diff_pool = job->diff_pool;
988    jcr->catalog = job->client->catalog;
989    jcr->fileset = job->fileset;
990    jcr->messages = job->messages;
991    jcr->spool_data = job->spool_data;
992    jcr->write_part_after_job = job->write_part_after_job;
993    if (jcr->RestoreBootstrap) {
994       free(jcr->RestoreBootstrap);
995       jcr->RestoreBootstrap = NULL;
996    }
997    /* This can be overridden by Console program */
998    if (job->RestoreBootstrap) {
999       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1000    }
1001    /* This can be overridden by Console program */
1002    jcr->verify_job = job->verify_job;
1003    /* If no default level given, set one */
1004    if (jcr->JobLevel == 0) {
1005       switch (jcr->JobType) {
1006       case JT_VERIFY:
1007          jcr->JobLevel = L_VERIFY_CATALOG;
1008          break;
1009       case JT_BACKUP:
1010          jcr->JobLevel = L_INCREMENTAL;
1011          break;
1012       case JT_RESTORE:
1013       case JT_ADMIN:
1014          jcr->JobLevel = L_NONE;
1015          break;
1016       default:
1017          jcr->JobLevel = L_FULL;
1018          break;
1019       }
1020    }
1021 }
1022
1023 /* 
1024  * Copy the storage definitions from an alist to the JCR
1025  */
1026 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1027 {
1028    switch(jcr->JobType) {
1029    case JT_RESTORE:
1030    case JT_VERIFY:
1031    case JT_MIGRATE:
1032       copy_rstorage(jcr, storage, where);
1033       break;
1034    default:
1035       copy_wstorage(jcr, storage, where);
1036       break;
1037    }
1038 }
1039
1040
1041 /* Set storage override */
1042 void set_rwstorage(JCR *jcr, USTORE *store)
1043 {
1044    if (!store) {
1045       Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1046       return;
1047    }
1048    switch(jcr->JobType) {
1049    case JT_RESTORE:
1050    case JT_VERIFY:
1051    case JT_MIGRATE:
1052       set_rstorage(jcr, store);
1053       break;
1054    default:
1055       set_wstorage(jcr, store);
1056       break;
1057    }
1058 }
1059
1060 void free_rwstorage(JCR *jcr)
1061 {
1062    free_rstorage(jcr);
1063    free_wstorage(jcr);
1064 }
1065
1066 /* 
1067  * Copy the storage definitions from an alist to the JCR
1068  */
1069 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1070 {
1071    if (storage) {
1072       STORE *st;
1073       if (jcr->rstorage) {
1074          delete jcr->rstorage;
1075       }
1076       jcr->rstorage = New(alist(10, not_owned_by_alist));
1077       foreach_alist(st, storage) {
1078          jcr->rstorage->append(st);
1079       }
1080       if (!jcr->rstore_source) {
1081          jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1082       }
1083       pm_strcpy(jcr->rstore_source, where);
1084       if (jcr->rstorage) {
1085          jcr->rstore = (STORE *)jcr->rstorage->first();
1086       }
1087    }
1088 }
1089
1090
1091 /* Set storage override */
1092 void set_rstorage(JCR *jcr, USTORE *store)
1093 {
1094    STORE *storage;
1095
1096    if (!store->store) {
1097       return;
1098    }
1099    if (!jcr->rstorage) {
1100       jcr->rstorage = New(alist(10, not_owned_by_alist));
1101    }
1102    jcr->rstore = store->store;
1103    if (!jcr->rstore_source) {
1104       jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1105    }
1106    pm_strcpy(jcr->rstore_source, store->store_source);
1107    foreach_alist(storage, jcr->rstorage) {
1108       if (store->store == storage) {
1109          return;
1110       }
1111    }
1112    /* Store not in list, so add it */
1113    jcr->rstorage->prepend(store->store);
1114 }
1115
1116 void free_rstorage(JCR *jcr)
1117 {
1118    if (jcr->rstorage) {
1119       delete jcr->rstorage;
1120       jcr->rstorage = NULL;
1121    }
1122    jcr->rstore = NULL;
1123 }
1124
1125 /* 
1126  * Copy the storage definitions from an alist to the JCR
1127  */
1128 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1129 {
1130    if (storage) {
1131       STORE *st;
1132       if (jcr->wstorage) {
1133          delete jcr->wstorage;
1134       }
1135       jcr->wstorage = New(alist(10, not_owned_by_alist));
1136       foreach_alist(st, storage) {
1137          Dmsg1(50, "storage=%s\n", st->name());
1138          jcr->wstorage->append(st);
1139       }
1140       if (!jcr->wstore_source) {
1141          jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1142       }
1143       pm_strcpy(jcr->wstore_source, where);
1144       if (jcr->wstorage) {
1145          jcr->wstore = (STORE *)jcr->wstorage->first();
1146          Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1147       }
1148    }
1149 }
1150
1151
1152 /* Set storage override */
1153 void set_wstorage(JCR *jcr, USTORE *store)
1154 {
1155    STORE *storage;
1156
1157    if (!store->store) {
1158       return;
1159    }
1160    if (!jcr->wstorage) {
1161       jcr->wstorage = New(alist(10, not_owned_by_alist));
1162    }
1163    jcr->wstore = store->store;
1164    if (!jcr->wstore_source) {
1165       jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1166    }
1167    pm_strcpy(jcr->wstore_source, store->store_source);
1168    Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1169    foreach_alist(storage, jcr->wstorage) {
1170       if (store->store == storage) {
1171          return;
1172       }
1173    }
1174    /* Store not in list, so add it */
1175    jcr->wstorage->prepend(store->store);
1176 }
1177
1178 void free_wstorage(JCR *jcr)
1179 {
1180    if (jcr->wstorage) {
1181       delete jcr->wstorage;
1182       jcr->wstorage = NULL;
1183    }
1184    jcr->wstore = NULL;
1185 }
1186
1187 void create_clones(JCR *jcr)
1188 {
1189    /*
1190     * Fire off any clone jobs (run directives)
1191     */
1192    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1193    if (!jcr->cloned && jcr->job->run_cmds) {
1194       char *runcmd;
1195       JOB *job = jcr->job;
1196       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1197       UAContext *ua = new_ua_context(jcr);
1198       ua->batch = true;
1199       foreach_alist(runcmd, job->run_cmds) {
1200          cmd = edit_job_codes(jcr, cmd, runcmd, "");              
1201          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1202          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1203          parse_ua_args(ua);                 /* parse command */
1204          int stat = run_cmd(ua, ua->cmd);
1205          if (stat == 0) {
1206             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1207          } else {
1208             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1209          }
1210       }
1211       free_ua_context(ua);
1212       free_pool_memory(cmd);
1213    }
1214 }
1215
1216 bool create_restore_bootstrap_file(JCR *jcr)
1217 {
1218    RESTORE_CTX rx;
1219    UAContext *ua;
1220    memset(&rx, 0, sizeof(rx));
1221    rx.bsr = new_bsr();
1222    rx.JobIds = "";                       
1223    rx.bsr->JobId = jcr->previous_jr.JobId;
1224    ua = new_ua_context(jcr);
1225    complete_bsr(ua, rx.bsr);
1226    rx.bsr->fi = new_findex();
1227    rx.bsr->fi->findex = 1;
1228    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1229    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1230    if (jcr->ExpectedFiles == 0) {
1231       free_ua_context(ua);
1232       free_bsr(rx.bsr);
1233       return false;
1234    }
1235    free_ua_context(ua);
1236    free_bsr(rx.bsr);
1237    jcr->needs_sd = true;
1238    return true;
1239 }