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