]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
Cleanup attribute catalog insert errors + cancel SD only once
[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    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
885       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
886          db_strerror(jcr->db));
887    }
888 }
889
890 /*
891  * Takes base_name and appends (unique) current
892  *   date and time to form unique job name.
893  *
894  *  Note, the seconds are actually a sequence number. This
895  *   permits us to start a maximum fo 59 unique jobs a second, which
896  *   should be sufficient.
897  *
898  *  Returns: unique job name in jcr->Job
899  *    date/time in jcr->start_time
900  */
901 void create_unique_job_name(JCR *jcr, const char *base_name)
902 {
903    /* Job start mutex */
904    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
905    static time_t last_start_time = 0;
906    static int seq = 0;
907    time_t now = time(NULL);
908    struct tm tm;
909    char dt[MAX_TIME_LENGTH];
910    char name[MAX_NAME_LENGTH];
911    char *p;
912    int len;
913
914    /* Guarantee unique start time -- maximum one per second, and
915     * thus unique Job Name
916     */
917    P(mutex);                          /* lock creation of jobs */
918    seq++;
919    if (seq > 59) {                    /* wrap as if it is seconds */
920       seq = 0;
921       while (now == last_start_time) {
922          bmicrosleep(0, 500000);
923          now = time(NULL);
924       }
925    }
926    last_start_time = now;
927    V(mutex);                          /* allow creation of jobs */
928    jcr->start_time = now;
929    /* Form Unique JobName */
930    (void)localtime_r(&now, &tm);
931    /* Use only characters that are permitted in Windows filenames */
932    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
933    len = strlen(dt) + 5;   /* dt + .%02d EOS */
934    bstrncpy(name, base_name, sizeof(name));
935    name[sizeof(name)-len] = 0;          /* truncate if too long */
936    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s_%02d", name, dt, seq); /* add date & time */
937    /* Convert spaces into underscores */
938    for (p=jcr->Job; *p; p++) {
939       if (*p == ' ') {
940          *p = '_';
941       }
942    }
943    Dmsg2(100, "JobId=%u created Job=%s\n", jcr->JobId, jcr->Job);
944 }
945
946 /* Called directly from job rescheduling */
947 void dird_free_jcr_pointers(JCR *jcr)
948 {
949    if (jcr->sd_auth_key) {
950       free(jcr->sd_auth_key);
951       jcr->sd_auth_key = NULL;
952    }
953    if (jcr->where) {
954       free(jcr->where);
955       jcr->where = NULL;
956    }
957    if (jcr->file_bsock) {
958       Dmsg0(200, "Close File bsock\n");
959       bnet_close(jcr->file_bsock);
960       jcr->file_bsock = NULL;
961    }
962    if (jcr->store_bsock) {
963       Dmsg0(200, "Close Store bsock\n");
964       bnet_close(jcr->store_bsock);
965       jcr->store_bsock = NULL;
966    }
967    if (jcr->fname) {
968       Dmsg0(200, "Free JCR fname\n");
969       free_pool_memory(jcr->fname);
970       jcr->fname = NULL;
971    }
972    if (jcr->RestoreBootstrap) {
973       free(jcr->RestoreBootstrap);
974       jcr->RestoreBootstrap = NULL;
975    }
976    if (jcr->client_uname) {
977       free_pool_memory(jcr->client_uname);
978       jcr->client_uname = NULL;
979    }
980    if (jcr->attr) {
981       free_pool_memory(jcr->attr);
982       jcr->attr = NULL;
983    }
984    if (jcr->ar) {
985       free(jcr->ar);
986       jcr->ar = NULL;
987    }
988 }
989
990 /*
991  * Free the Job Control Record if no one is still using it.
992  *  Called from main free_jcr() routine in src/lib/jcr.c so
993  *  that we can do our Director specific cleanup of the jcr.
994  */
995 void dird_free_jcr(JCR *jcr)
996 {
997    Dmsg0(200, "Start dird free_jcr\n");
998
999    dird_free_jcr_pointers(jcr);
1000    if (jcr->term_wait_inited) {
1001       pthread_cond_destroy(&jcr->term_wait);
1002       jcr->term_wait_inited = false;
1003    }
1004    if (jcr->db_batch) {
1005       db_close_database(jcr, jcr->db_batch);
1006       jcr->db_batch = NULL;
1007       jcr->batch_started = false;
1008    }
1009    if (jcr->db) {
1010       db_close_database(jcr, jcr->db);
1011       jcr->db = NULL;
1012    }
1013    if (jcr->stime) {
1014       Dmsg0(200, "Free JCR stime\n");
1015       free_pool_memory(jcr->stime);
1016       jcr->stime = NULL;
1017    }
1018    if (jcr->fname) {
1019       Dmsg0(200, "Free JCR fname\n");
1020       free_pool_memory(jcr->fname);
1021       jcr->fname = NULL;
1022    }
1023    if (jcr->pool_source) {
1024       free_pool_memory(jcr->pool_source);
1025       jcr->pool_source = NULL;
1026    }
1027    if (jcr->catalog_source) {
1028       free_pool_memory(jcr->catalog_source);
1029       jcr->catalog_source = NULL;
1030    }
1031    if (jcr->rpool_source) {
1032       free_pool_memory(jcr->rpool_source);
1033       jcr->rpool_source = NULL;
1034    }
1035    if (jcr->wstore_source) {
1036       free_pool_memory(jcr->wstore_source);
1037       jcr->wstore_source = NULL;
1038    }
1039    if (jcr->rstore_source) {
1040       free_pool_memory(jcr->rstore_source);
1041       jcr->rstore_source = NULL;
1042    }
1043
1044    /* Delete lists setup to hold storage pointers */
1045    free_rwstorage(jcr);
1046
1047    jcr->job_end_push.destroy();
1048
1049    if (jcr->JobId != 0)
1050       write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
1051
1052    free_plugins(jcr);                 /* release instantiated plugins */
1053
1054    Dmsg0(200, "End dird free_jcr\n");
1055 }
1056
1057 /* 
1058  * The Job storage definition must be either in the Job record
1059  *  or in the Pool record.  The Pool record overrides the Job 
1060  *  record.
1061  */
1062 void get_job_storage(USTORE *store, JOB *job, RUN *run) 
1063 {
1064    if (run && run->pool && run->pool->storage) {
1065       store->store = (STORE *)run->pool->storage->first();
1066       pm_strcpy(store->store_source, _("Run pool override"));
1067       return;
1068    }
1069    if (run && run->storage) {
1070       store->store = run->storage;
1071       pm_strcpy(store->store_source, _("Run storage override"));
1072       return;
1073    }
1074    if (job->pool->storage) {
1075       store->store = (STORE *)job->pool->storage->first();
1076       pm_strcpy(store->store_source, _("Pool resource"));
1077    } else {
1078       store->store = (STORE *)job->storage->first();
1079       pm_strcpy(store->store_source, _("Job resource"));
1080    }
1081 }
1082
1083 /*
1084  * Set some defaults in the JCR necessary to
1085  * run. These items are pulled from the job
1086  * definition as defaults, but can be overridden
1087  * later either by the Run record in the Schedule resource,
1088  * or by the Console program.
1089  */
1090 void set_jcr_defaults(JCR *jcr, JOB *job)
1091 {
1092    jcr->job = job;
1093    jcr->set_JobType(job->JobType);
1094    jcr->JobStatus = JS_Created;
1095
1096    switch (jcr->get_JobType()) {
1097    case JT_ADMIN:
1098       jcr->set_JobLevel(L_NONE);
1099       break;
1100    default:
1101       jcr->set_JobLevel(job->JobLevel);
1102       break;
1103    }
1104
1105    if (!jcr->fname) {
1106       jcr->fname = get_pool_memory(PM_FNAME);
1107    }
1108    if (!jcr->pool_source) {
1109       jcr->pool_source = get_pool_memory(PM_MESSAGE);
1110       pm_strcpy(jcr->pool_source, _("unknown source"));
1111    }
1112    if (!jcr->catalog_source) {
1113       jcr->catalog_source = get_pool_memory(PM_MESSAGE);
1114       pm_strcpy(jcr->catalog_source, _("unknown source"));
1115    }
1116
1117    jcr->JobPriority = job->Priority;
1118    /* Copy storage definitions -- deleted in dir_free_jcr above */
1119    if (job->storage) {
1120       copy_rwstorage(jcr, job->storage, _("Job resource"));
1121    } else {
1122       copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
1123    }
1124    jcr->client = job->client;
1125    if (!jcr->client_name) {
1126       jcr->client_name = get_pool_memory(PM_NAME);
1127    }
1128    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
1129    pm_strcpy(jcr->pool_source, _("Job resource"));
1130    jcr->pool = job->pool;
1131    jcr->full_pool = job->full_pool;
1132    jcr->inc_pool = job->inc_pool;
1133    jcr->diff_pool = job->diff_pool;
1134    if (job->pool->catalog) {
1135       jcr->catalog = job->pool->catalog;
1136       pm_strcpy(jcr->catalog_source, _("Pool resource"));
1137    } else {
1138       jcr->catalog = job->client->catalog;
1139       pm_strcpy(jcr->catalog_source, _("Client resource"));
1140    }
1141    jcr->fileset = job->fileset;
1142    jcr->messages = job->messages;
1143    jcr->spool_data = job->spool_data;
1144    jcr->spool_size = job->spool_size;
1145    jcr->write_part_after_job = job->write_part_after_job;
1146    jcr->accurate = job->accurate;
1147    if (jcr->RestoreBootstrap) {
1148       free(jcr->RestoreBootstrap);
1149       jcr->RestoreBootstrap = NULL;
1150    }
1151    /* This can be overridden by Console program */
1152    if (job->RestoreBootstrap) {
1153       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1154    }
1155    /* This can be overridden by Console program */
1156    jcr->verify_job = job->verify_job;
1157    /* If no default level given, set one */
1158    if (jcr->get_JobLevel() == 0) {
1159       switch (jcr->get_JobType()) {
1160       case JT_VERIFY:
1161          jcr->set_JobLevel(L_VERIFY_CATALOG);
1162          break;
1163       case JT_BACKUP:
1164          jcr->set_JobLevel(L_INCREMENTAL);
1165          break;
1166       case JT_RESTORE:
1167       case JT_ADMIN:
1168          jcr->set_JobLevel(L_NONE);
1169          break;
1170       default:
1171          jcr->set_JobLevel(L_FULL);
1172          break;
1173       }
1174    }
1175 }
1176
1177 /* 
1178  * Copy the storage definitions from an alist to the JCR
1179  */
1180 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1181 {
1182    if (jcr->JobReads()) {
1183       copy_rstorage(jcr, storage, where);
1184    }
1185    copy_wstorage(jcr, storage, where);
1186 }
1187
1188
1189 /* Set storage override.  Releases any previous storage definition */
1190 void set_rwstorage(JCR *jcr, USTORE *store)
1191 {
1192    if (!store) {
1193       Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1194       return;
1195    }
1196    if (jcr->JobReads()) {
1197       set_rstorage(jcr, store);
1198    }
1199    set_wstorage(jcr, store);
1200 }
1201
1202 void free_rwstorage(JCR *jcr)
1203 {
1204    free_rstorage(jcr);
1205    free_wstorage(jcr);
1206 }
1207
1208 /* 
1209  * Copy the storage definitions from an alist to the JCR
1210  */
1211 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1212 {
1213    if (storage) {
1214       STORE *st;
1215       if (jcr->rstorage) {
1216          delete jcr->rstorage;
1217       }
1218       jcr->rstorage = New(alist(10, not_owned_by_alist));
1219       foreach_alist(st, storage) {
1220          jcr->rstorage->append(st);
1221       }
1222       if (!jcr->rstore_source) {
1223          jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1224       }
1225       pm_strcpy(jcr->rstore_source, where);
1226       if (jcr->rstorage) {
1227          jcr->rstore = (STORE *)jcr->rstorage->first();
1228       }
1229    }
1230 }
1231
1232
1233 /* Set storage override.  Remove all previous storage */
1234 void set_rstorage(JCR *jcr, USTORE *store)
1235 {
1236    STORE *storage;
1237
1238    if (!store->store) {
1239       return;
1240    }
1241    if (jcr->rstorage) {
1242       free_rstorage(jcr);
1243    }
1244    if (!jcr->rstorage) {
1245       jcr->rstorage = New(alist(10, not_owned_by_alist));
1246    }
1247    jcr->rstore = store->store;
1248    if (!jcr->rstore_source) {
1249       jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1250    }
1251    pm_strcpy(jcr->rstore_source, store->store_source);
1252    foreach_alist(storage, jcr->rstorage) {
1253       if (store->store == storage) {
1254          return;
1255       }
1256    }
1257    /* Store not in list, so add it */
1258    jcr->rstorage->prepend(store->store);
1259 }
1260
1261 void free_rstorage(JCR *jcr)
1262 {
1263    if (jcr->rstorage) {
1264       delete jcr->rstorage;
1265       jcr->rstorage = NULL;
1266    }
1267    jcr->rstore = NULL;
1268 }
1269
1270 /* 
1271  * Copy the storage definitions from an alist to the JCR
1272  */
1273 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1274 {
1275    if (storage) {
1276       STORE *st;
1277       if (jcr->wstorage) {
1278          delete jcr->wstorage;
1279       }
1280       jcr->wstorage = New(alist(10, not_owned_by_alist));
1281       foreach_alist(st, storage) {
1282          Dmsg1(100, "wstorage=%s\n", st->name());
1283          jcr->wstorage->append(st);
1284       }
1285       if (!jcr->wstore_source) {
1286          jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1287       }
1288       pm_strcpy(jcr->wstore_source, where);
1289       if (jcr->wstorage) {
1290          jcr->wstore = (STORE *)jcr->wstorage->first();
1291          Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1292       }
1293    }
1294 }
1295
1296
1297 /* Set storage override. Remove all previous storage */
1298 void set_wstorage(JCR *jcr, USTORE *store)
1299 {
1300    STORE *storage;
1301
1302    if (!store->store) {
1303       return;
1304    }
1305    if (jcr->wstorage) {
1306       free_wstorage(jcr);
1307    }
1308    if (!jcr->wstorage) {
1309       jcr->wstorage = New(alist(10, not_owned_by_alist));
1310    }
1311    jcr->wstore = store->store;
1312    if (!jcr->wstore_source) {
1313       jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1314    }
1315    pm_strcpy(jcr->wstore_source, store->store_source);
1316    Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1317    foreach_alist(storage, jcr->wstorage) {
1318       if (store->store == storage) {
1319          return;
1320       }
1321    }
1322    /* Store not in list, so add it */
1323    jcr->wstorage->prepend(store->store);
1324 }
1325
1326 void free_wstorage(JCR *jcr)
1327 {
1328    if (jcr->wstorage) {
1329       delete jcr->wstorage;
1330       jcr->wstorage = NULL;
1331    }
1332    jcr->wstore = NULL;
1333 }
1334
1335 char *job_code_callback_clones(JCR *jcr, const char* param) 
1336 {
1337    if (param[0] == 'p') {
1338       return jcr->pool->name();
1339    }
1340    return NULL;
1341 }
1342
1343 void create_clones(JCR *jcr)
1344 {
1345    /*
1346     * Fire off any clone jobs (run directives)
1347     */
1348    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1349    if (!jcr->cloned && jcr->job->run_cmds) {
1350       char *runcmd;
1351       JOB *job = jcr->job;
1352       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1353       UAContext *ua = new_ua_context(jcr);
1354       ua->batch = true;
1355       foreach_alist(runcmd, job->run_cmds) {
1356          cmd = edit_job_codes(jcr, cmd, runcmd, "", job_code_callback_clones);
1357          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1358          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1359          parse_ua_args(ua);                 /* parse command */
1360          int stat = run_cmd(ua, ua->cmd);
1361          if (stat == 0) {
1362             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job: \"%s\".\n"),
1363                  ua->cmd);
1364          } else {
1365             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1366          }
1367       }
1368       free_ua_context(ua);
1369       free_pool_memory(cmd);
1370    }
1371 }
1372
1373 /*
1374  * Given: a JobId in jcr->previous_jr.JobId,
1375  *  this subroutine writes a bsr file to restore that job.
1376  * Returns: -1 on error
1377  *           number of files if OK
1378  */
1379 int create_restore_bootstrap_file(JCR *jcr)
1380 {
1381    RESTORE_CTX rx;
1382    UAContext *ua;
1383    int files;
1384
1385    memset(&rx, 0, sizeof(rx));
1386    rx.bsr = new_bsr();
1387    rx.JobIds = (char *)"";                       
1388    rx.bsr->JobId = jcr->previous_jr.JobId;
1389    ua = new_ua_context(jcr);
1390    if (!complete_bsr(ua, rx.bsr)) {
1391       files = -1;
1392       goto bail_out;
1393    }
1394    rx.bsr->fi = new_findex();
1395    rx.bsr->fi->findex = 1;
1396    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1397    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1398    if (jcr->ExpectedFiles == 0) {
1399       files = 0;
1400       goto bail_out;
1401    }
1402    free_ua_context(ua);
1403    free_bsr(rx.bsr);
1404    jcr->needs_sd = true;
1405    return jcr->ExpectedFiles;
1406
1407 bail_out:
1408    free_ua_context(ua);
1409    free_bsr(rx.bsr);
1410    return files;
1411 }
1412
1413 /* TODO: redirect command ouput to job log */
1414 bool run_console_command(JCR *jcr, const char *cmd)
1415 {
1416    UAContext *ua;
1417    bool ok;
1418    JCR *ljcr = new_control_jcr("-RunScript-", JT_CONSOLE);
1419    ua = new_ua_context(ljcr);
1420    /* run from runscript and check if commands are autorized */
1421    ua->runscript = true;
1422    Mmsg(ua->cmd, "%s", cmd);
1423    Dmsg1(100, "Console command: %s\n", ua->cmd);
1424    parse_ua_args(ua);
1425    ok= do_a_command(ua);
1426    free_ua_context(ua);
1427    free_jcr(ljcr);
1428    return ok;
1429 }