]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
Eliminate double job report when do_xxx_init() returns failure
[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    set_jcr_job_status(jcr, 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    set_jcr_job_status(jcr, 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       set_jcr_job_status(jcr, 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       set_jcr_job_status(jcr, 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       return true;
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    }
450
451    return true;
452 }
453
454 void cancel_storage_daemon_job(JCR *jcr)
455 {
456    UAContext *ua = new_ua_context(jcr);
457    JCR *control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);
458    BSOCK *sd;
459
460    ua->jcr = control_jcr;
461    if (jcr->store_bsock) {
462       if (!ua->jcr->wstorage) {
463          if (jcr->rstorage) {
464             copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
465          } else {
466             copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
467          }
468       } else {
469          USTORE store;
470          if (jcr->rstorage) {
471             store.store = jcr->rstore;
472          } else {
473             store.store = jcr->wstore;
474          }
475          set_wstorage(ua->jcr, &store);
476       }
477
478       if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
479          goto bail_out;
480       }
481       Dmsg0(200, "Connected to storage daemon\n");
482       sd = ua->jcr->store_bsock;
483       sd->fsend("cancel Job=%s\n", jcr->Job);
484       while (sd->recv() >= 0) {
485       }
486       sd->signal(BNET_TERMINATE);
487       sd->close();
488       ua->jcr->store_bsock = NULL;
489    }
490 bail_out:
491    free_jcr(control_jcr);
492    free_ua_context(ua);
493 }
494
495 static void job_monitor_destructor(watchdog_t *self)
496 {
497    JCR *control_jcr = (JCR *)self->data;
498
499    free_jcr(control_jcr);
500 }
501
502 static void job_monitor_watchdog(watchdog_t *self)
503 {
504    JCR *control_jcr, *jcr;
505
506    control_jcr = (JCR *)self->data;
507
508    Dsm_check(1);
509    Dmsg1(800, "job_monitor_watchdog %p called\n", self);
510
511    foreach_jcr(jcr) {
512       bool cancel = false;
513
514       if (jcr->JobId == 0 || job_canceled(jcr) || jcr->no_maxtime) {
515          Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
516          continue;
517       }
518
519       /* check MaxWaitTime */
520       if (job_check_maxwaittime(jcr)) {
521          set_jcr_job_status(jcr, JS_Canceled);
522          Qmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
523          cancel = true;
524       /* check MaxRunTime */
525       } else if (job_check_maxruntime(jcr)) {
526          set_jcr_job_status(jcr, JS_Canceled);
527          Qmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
528          cancel = true;
529       /* check MaxRunSchedTime */ 
530       } else if (job_check_maxschedruntime(jcr)) {
531          set_jcr_job_status(jcr, JS_Canceled);
532          Qmsg(jcr, M_FATAL, 0, _("Max sched run time exceeded. Job canceled.\n"));
533          cancel = true;
534       }
535
536       if (cancel) {
537          Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
538          UAContext *ua = new_ua_context(jcr);
539          ua->jcr = control_jcr;
540          cancel_job(ua, jcr);
541          free_ua_context(ua);
542          Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
543       }
544
545    }
546    /* Keep reference counts correct */
547    endeach_jcr(jcr);
548 }
549
550 /*
551  * Check if the maxwaittime has expired and it is possible
552  *  to cancel the job.
553  */
554 static bool job_check_maxwaittime(JCR *jcr)
555 {
556    bool cancel = false;
557    JOB *job = jcr->job;
558    utime_t current=0;
559
560    if (!job_waiting(jcr)) {
561       return false;
562    }
563
564    if (jcr->wait_time) {
565       current = watchdog_time - jcr->wait_time;
566    }
567
568    Dmsg2(200, "check maxwaittime %u >= %u\n", 
569          current + jcr->wait_time_sum, job->MaxWaitTime);
570    if (job->MaxWaitTime != 0 &&
571        (current + jcr->wait_time_sum) >= job->MaxWaitTime) {
572       cancel = true;
573    }
574
575    return cancel;
576 }
577
578 /*
579  * Check if maxruntime has expired and if the job can be
580  *   canceled.
581  */
582 static bool job_check_maxruntime(JCR *jcr)
583 {
584    bool cancel = false;
585    JOB *job = jcr->job;
586    utime_t run_time;
587
588    if (job_canceled(jcr) || jcr->JobStatus == JS_Created) {
589       return false;
590    }
591    if (jcr->job->MaxRunTime == 0 && job->FullMaxRunTime == 0 &&
592        job->IncMaxRunTime == 0 && job->DiffMaxRunTime == 0) {
593       return false;
594    }
595    run_time = watchdog_time - jcr->start_time;
596    Dmsg7(200, "check_maxruntime %llu-%u=%llu >= %llu|%llu|%llu|%llu\n",
597          watchdog_time, jcr->start_time, run_time, job->MaxRunTime, job->FullMaxRunTime, 
598          job->IncMaxRunTime, job->DiffMaxRunTime);
599
600    if (jcr->get_JobLevel() == L_FULL && job->FullMaxRunTime != 0 &&
601          run_time >= job->FullMaxRunTime) {
602       Dmsg0(200, "check_maxwaittime: FullMaxcancel\n");
603       cancel = true;
604    } else if (jcr->get_JobLevel() == L_DIFFERENTIAL && job->DiffMaxRunTime != 0 &&
605          run_time >= job->DiffMaxRunTime) {
606       Dmsg0(200, "check_maxwaittime: DiffMaxcancel\n");
607       cancel = true;
608    } else if (jcr->get_JobLevel() == L_INCREMENTAL && job->IncMaxRunTime != 0 &&
609          run_time >= job->IncMaxRunTime) {
610       Dmsg0(200, "check_maxwaittime: IncMaxcancel\n");
611       cancel = true;
612    } else if (job->MaxRunTime > 0 && run_time >= job->MaxRunTime) {
613       Dmsg0(200, "check_maxwaittime: Maxcancel\n");
614       cancel = true;
615    }
616  
617    return cancel;
618 }
619
620 /*
621  * Check if MaxRunSchedTime has expired and if the job can be
622  *   canceled.
623  */
624 static bool job_check_maxschedruntime(JCR *jcr)
625 {
626    if (jcr->job->MaxRunSchedTime == 0 || job_canceled(jcr)) {
627       return false;
628    }
629    if ((watchdog_time - jcr->sched_time) < jcr->job->MaxRunSchedTime) {
630       Dmsg3(200, "Job %p (%s) with MaxRunSchedTime %d not expired\n",
631             jcr, jcr->Job, jcr->job->MaxRunSchedTime);
632       return false;
633    }
634
635    return true;
636 }
637
638 /*
639  * Get or create a Pool record with the given name.
640  * Returns: 0 on error
641  *          poolid if OK
642  */
643 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
644 {
645    POOL_DBR pr;
646
647    memset(&pr, 0, sizeof(pr));
648    bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
649    Dmsg1(110, "get_or_create_pool=%s\n", pool_name);
650
651    while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
652       /* Try to create the pool */
653       if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
654          Jmsg(jcr, M_FATAL, 0, _("Pool \"%s\" not in database. ERR=%s"), pr.Name,
655             db_strerror(jcr->db));
656          return 0;
657       } else {
658          Jmsg(jcr, M_INFO, 0, _("Created database record for Pool \"%s\".\n"), pr.Name);
659       }
660    }
661    return pr.PoolId;
662 }
663
664 /*
665  * Check for duplicate jobs.
666  *  Returns: true  if current job should continue
667  *           false if current job should terminate
668  */
669 bool allow_duplicate_job(JCR *jcr)
670 {
671    JOB *job = jcr->job;
672    JCR *djcr;                /* possible duplicate */
673
674    if (job->AllowDuplicateJobs) {
675       return true;
676    }
677    if (!job->AllowHigherDuplicates) {
678       foreach_jcr(djcr) {
679          char ec1[50];
680          if (jcr == djcr) {
681             continue;                   /* do not cancel this job */
682          }
683          if (strcmp(job->name(), djcr->job->name()) == 0) {
684             bool cancel_queued = false;
685             if (job->DuplicateJobProximity > 0) {
686                utime_t now = (utime_t)time(NULL);
687                if ((now - djcr->start_time) > job->DuplicateJobProximity) {
688                   continue;               /* not really a duplicate */
689                }
690             }
691             /* Cancel */
692             if (!(job->CancelQueuedDuplicates || job->CancelRunningDuplicates)) {
693                /* Zap current job */
694                Jmsg(jcr, M_FATAL, 0, _("Duplicate job not allowed. JobId=%s\n"),
695                   edit_uint64(djcr->JobId, ec1));
696                return false;
697             }
698             /* If CancelQueuedDuplicates is set do so only if job is queued */
699             if (job->CancelQueuedDuplicates) {
700                 switch (djcr->JobStatus) {
701                 case JS_Created:
702                 case JS_WaitJobRes:
703                 case JS_WaitClientRes:
704                 case JS_WaitStoreRes:
705                 case JS_WaitPriority:
706                 case JS_WaitMaxJobs:
707                 case JS_WaitStartTime:
708                    cancel_queued = true;
709                    break;
710                 default:
711                    break;
712                 }
713             }
714             if (cancel_queued || job->CancelRunningDuplicates) {
715                UAContext *ua = new_ua_context(djcr);
716                Jmsg(jcr, M_INFO, 0, _("Cancelling duplicate JobId=%s.\n"), 
717                   edit_uint64(djcr->JobId, ec1));
718                ua->jcr = djcr;
719                cancel_job(ua, djcr);
720                free_ua_context(ua);
721                Dmsg2(800, "Have cancelled JCR %p Job=%d\n", djcr, djcr->JobId);
722             }
723          }
724       }
725       endeach_jcr(djcr);
726    }
727    return true;   
728 }
729
730 void apply_pool_overrides(JCR *jcr)
731 {
732    bool pool_override = false;
733
734    if (jcr->run_pool_override) {
735       pm_strcpy(jcr->pool_source, _("Run pool override"));
736    }
737    /*
738     * Apply any level related Pool selections
739     */
740    switch (jcr->get_JobLevel()) {
741    case L_FULL:
742       if (jcr->full_pool) {
743          jcr->pool = jcr->full_pool;
744          pool_override = true;
745          if (jcr->run_full_pool_override) {
746             pm_strcpy(jcr->pool_source, _("Run FullPool override"));
747          } else {
748             pm_strcpy(jcr->pool_source, _("Job FullPool override"));
749          }
750       }
751       break;
752    case L_INCREMENTAL:
753       if (jcr->inc_pool) {
754          jcr->pool = jcr->inc_pool;
755          pool_override = true;
756          if (jcr->run_inc_pool_override) {
757             pm_strcpy(jcr->pool_source, _("Run IncPool override"));
758          } else {
759             pm_strcpy(jcr->pool_source, _("Job IncPool override"));
760          }
761       }
762       break;
763    case L_DIFFERENTIAL:
764       if (jcr->diff_pool) {
765          jcr->pool = jcr->diff_pool;
766          pool_override = true;
767          if (jcr->run_diff_pool_override) {
768             pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
769          } else {
770             pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
771          }
772       }
773       break;
774    }
775    /* Update catalog if pool overridden */
776    if (pool_override && jcr->pool->catalog) {
777       jcr->catalog = jcr->pool->catalog;
778       pm_strcpy(jcr->catalog_source, _("Pool resource"));
779    }
780 }
781
782
783 /*
784  * Get or create a Client record for this Job
785  */
786 bool get_or_create_client_record(JCR *jcr)
787 {
788    CLIENT_DBR cr;
789
790    memset(&cr, 0, sizeof(cr));
791    bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
792    cr.AutoPrune = jcr->client->AutoPrune;
793    cr.FileRetention = jcr->client->FileRetention;
794    cr.JobRetention = jcr->client->JobRetention;
795    if (!jcr->client_name) {
796       jcr->client_name = get_pool_memory(PM_NAME);
797    }
798    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
799    if (!db_create_client_record(jcr, jcr->db, &cr)) {
800       Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
801          db_strerror(jcr->db));
802       return false;
803    }
804    jcr->jr.ClientId = cr.ClientId;
805    if (cr.Uname[0]) {
806       if (!jcr->client_uname) {
807          jcr->client_uname = get_pool_memory(PM_NAME);
808       }
809       pm_strcpy(jcr->client_uname, cr.Uname);
810    }
811    Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
812       jcr->jr.ClientId);
813    return true;
814 }
815
816 bool get_or_create_fileset_record(JCR *jcr)
817 {
818    FILESET_DBR fsr;
819    /*
820     * Get or Create FileSet record
821     */
822    memset(&fsr, 0, sizeof(FILESET_DBR));
823    bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
824    if (jcr->fileset->have_MD5) {
825       struct MD5Context md5c;
826       unsigned char digest[MD5HashSize];
827       memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
828       MD5Final(digest, &md5c);
829       /*
830        * Keep the flag (last arg) set to false otherwise old FileSets will
831        * get new MD5 sums and the user will get Full backups on everything
832        */
833       bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
834       bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
835    } else {
836       Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
837    }
838    if (!jcr->fileset->ignore_fs_changes ||
839        !db_get_fileset_record(jcr, jcr->db, &fsr)) {
840       if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
841          Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
842             fsr.FileSet, db_strerror(jcr->db));
843          return false;
844       }
845    }
846    jcr->jr.FileSetId = fsr.FileSetId;
847    bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
848    Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
849       jcr->jr.FileSetId);
850    return true;
851 }
852
853 void init_jcr_job_record(JCR *jcr)
854 {
855    jcr->jr.SchedTime = jcr->sched_time;
856    jcr->jr.StartTime = jcr->start_time;
857    jcr->jr.EndTime = 0;               /* perhaps rescheduled, clear it */
858    jcr->jr.JobType = jcr->get_JobType();
859    jcr->jr.JobLevel = jcr->get_JobLevel();
860    jcr->jr.JobStatus = jcr->JobStatus;
861    jcr->jr.JobId = jcr->JobId;
862    bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
863    bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
864 }
865
866 /*
867  * Write status and such in DB
868  */
869 void update_job_end_record(JCR *jcr)
870 {
871    jcr->jr.EndTime = time(NULL);
872    jcr->end_time = jcr->jr.EndTime;
873    jcr->jr.JobId = jcr->JobId;
874    jcr->jr.JobStatus = jcr->JobStatus;
875    jcr->jr.JobFiles = jcr->JobFiles;
876    jcr->jr.JobBytes = jcr->JobBytes;
877    jcr->jr.ReadBytes = jcr->ReadBytes;
878    jcr->jr.VolSessionId = jcr->VolSessionId;
879    jcr->jr.VolSessionTime = jcr->VolSessionTime;
880    jcr->jr.JobErrors = jcr->JobErrors;
881    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
882       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
883          db_strerror(jcr->db));
884    }
885 }
886
887 /*
888  * Takes base_name and appends (unique) current
889  *   date and time to form unique job name.
890  *
891  *  Note, the seconds are actually a sequence number. This
892  *   permits us to start a maximum fo 59 unique jobs a second, which
893  *   should be sufficient.
894  *
895  *  Returns: unique job name in jcr->Job
896  *    date/time in jcr->start_time
897  */
898 void create_unique_job_name(JCR *jcr, const char *base_name)
899 {
900    /* Job start mutex */
901    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
902    static time_t last_start_time = 0;
903    static int seq = 0;
904    time_t now = time(NULL);
905    struct tm tm;
906    char dt[MAX_TIME_LENGTH];
907    char name[MAX_NAME_LENGTH];
908    char *p;
909    int len;
910
911    /* Guarantee unique start time -- maximum one per second, and
912     * thus unique Job Name
913     */
914    P(mutex);                          /* lock creation of jobs */
915    seq++;
916    if (seq > 59) {                    /* wrap as if it is seconds */
917       seq = 0;
918       while (now == last_start_time) {
919          bmicrosleep(0, 500000);
920          now = time(NULL);
921       }
922    }
923    last_start_time = now;
924    V(mutex);                          /* allow creation of jobs */
925    jcr->start_time = now;
926    /* Form Unique JobName */
927    (void)localtime_r(&now, &tm);
928    /* Use only characters that are permitted in Windows filenames */
929    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
930    len = strlen(dt) + 5;   /* dt + .%02d EOS */
931    bstrncpy(name, base_name, sizeof(name));
932    name[sizeof(name)-len] = 0;          /* truncate if too long */
933    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s_%02d", name, dt, seq); /* add date & time */
934    /* Convert spaces into underscores */
935    for (p=jcr->Job; *p; p++) {
936       if (*p == ' ') {
937          *p = '_';
938       }
939    }
940    Dmsg2(100, "JobId=%u created Job=%s\n", jcr->JobId, jcr->Job);
941 }
942
943 /* Called directly from job rescheduling */
944 void dird_free_jcr_pointers(JCR *jcr)
945 {
946    if (jcr->sd_auth_key) {
947       free(jcr->sd_auth_key);
948       jcr->sd_auth_key = NULL;
949    }
950    if (jcr->where) {
951       free(jcr->where);
952       jcr->where = NULL;
953    }
954    if (jcr->file_bsock) {
955       Dmsg0(200, "Close File bsock\n");
956       bnet_close(jcr->file_bsock);
957       jcr->file_bsock = NULL;
958    }
959    if (jcr->store_bsock) {
960       Dmsg0(200, "Close Store bsock\n");
961       bnet_close(jcr->store_bsock);
962       jcr->store_bsock = NULL;
963    }
964    if (jcr->fname) {
965       Dmsg0(200, "Free JCR fname\n");
966       free_pool_memory(jcr->fname);
967       jcr->fname = NULL;
968    }
969    if (jcr->RestoreBootstrap) {
970       free(jcr->RestoreBootstrap);
971       jcr->RestoreBootstrap = NULL;
972    }
973    if (jcr->client_uname) {
974       free_pool_memory(jcr->client_uname);
975       jcr->client_uname = NULL;
976    }
977    if (jcr->attr) {
978       free_pool_memory(jcr->attr);
979       jcr->attr = NULL;
980    }
981    if (jcr->ar) {
982       free(jcr->ar);
983       jcr->ar = NULL;
984    }
985 }
986
987 /*
988  * Free the Job Control Record if no one is still using it.
989  *  Called from main free_jcr() routine in src/lib/jcr.c so
990  *  that we can do our Director specific cleanup of the jcr.
991  */
992 void dird_free_jcr(JCR *jcr)
993 {
994    Dmsg0(200, "Start dird free_jcr\n");
995
996    dird_free_jcr_pointers(jcr);
997    if (jcr->term_wait_inited) {
998       pthread_cond_destroy(&jcr->term_wait);
999       jcr->term_wait_inited = false;
1000    }
1001    if (jcr->db_batch) {
1002       db_close_database(jcr, jcr->db_batch);
1003       jcr->db_batch = NULL;
1004       jcr->batch_started = false;
1005    }
1006    if (jcr->db) {
1007       db_close_database(jcr, jcr->db);
1008       jcr->db = NULL;
1009    }
1010    if (jcr->stime) {
1011       Dmsg0(200, "Free JCR stime\n");
1012       free_pool_memory(jcr->stime);
1013       jcr->stime = NULL;
1014    }
1015    if (jcr->fname) {
1016       Dmsg0(200, "Free JCR fname\n");
1017       free_pool_memory(jcr->fname);
1018       jcr->fname = NULL;
1019    }
1020    if (jcr->pool_source) {
1021       free_pool_memory(jcr->pool_source);
1022       jcr->pool_source = NULL;
1023    }
1024    if (jcr->catalog_source) {
1025       free_pool_memory(jcr->catalog_source);
1026       jcr->catalog_source = NULL;
1027    }
1028    if (jcr->rpool_source) {
1029       free_pool_memory(jcr->rpool_source);
1030       jcr->rpool_source = NULL;
1031    }
1032    if (jcr->wstore_source) {
1033       free_pool_memory(jcr->wstore_source);
1034       jcr->wstore_source = NULL;
1035    }
1036    if (jcr->rstore_source) {
1037       free_pool_memory(jcr->rstore_source);
1038       jcr->rstore_source = NULL;
1039    }
1040
1041    /* Delete lists setup to hold storage pointers */
1042    free_rwstorage(jcr);
1043
1044    jcr->job_end_push.destroy();
1045
1046    if (jcr->JobId != 0)
1047       write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
1048
1049    free_plugins(jcr);                 /* release instantiated plugins */
1050
1051    Dmsg0(200, "End dird free_jcr\n");
1052 }
1053
1054 /* 
1055  * The Job storage definition must be either in the Job record
1056  *  or in the Pool record.  The Pool record overrides the Job 
1057  *  record.
1058  */
1059 void get_job_storage(USTORE *store, JOB *job, RUN *run) 
1060 {
1061    if (run && run->pool && run->pool->storage) {
1062       store->store = (STORE *)run->pool->storage->first();
1063       pm_strcpy(store->store_source, _("Run pool override"));
1064       return;
1065    }
1066    if (run && run->storage) {
1067       store->store = run->storage;
1068       pm_strcpy(store->store_source, _("Run storage override"));
1069       return;
1070    }
1071    if (job->pool->storage) {
1072       store->store = (STORE *)job->pool->storage->first();
1073       pm_strcpy(store->store_source, _("Pool resource"));
1074    } else {
1075       store->store = (STORE *)job->storage->first();
1076       pm_strcpy(store->store_source, _("Job resource"));
1077    }
1078 }
1079
1080 /*
1081  * Set some defaults in the JCR necessary to
1082  * run. These items are pulled from the job
1083  * definition as defaults, but can be overridden
1084  * later either by the Run record in the Schedule resource,
1085  * or by the Console program.
1086  */
1087 void set_jcr_defaults(JCR *jcr, JOB *job)
1088 {
1089    jcr->job = job;
1090    jcr->set_JobType(job->JobType);
1091    jcr->JobStatus = JS_Created;
1092
1093    switch (jcr->get_JobType()) {
1094    case JT_ADMIN:
1095       jcr->set_JobLevel(L_NONE);
1096       break;
1097    default:
1098       jcr->set_JobLevel(job->JobLevel);
1099       break;
1100    }
1101
1102    if (!jcr->fname) {
1103       jcr->fname = get_pool_memory(PM_FNAME);
1104    }
1105    if (!jcr->pool_source) {
1106       jcr->pool_source = get_pool_memory(PM_MESSAGE);
1107       pm_strcpy(jcr->pool_source, _("unknown source"));
1108    }
1109    if (!jcr->catalog_source) {
1110       jcr->catalog_source = get_pool_memory(PM_MESSAGE);
1111       pm_strcpy(jcr->catalog_source, _("unknown source"));
1112    }
1113
1114    jcr->JobPriority = job->Priority;
1115    /* Copy storage definitions -- deleted in dir_free_jcr above */
1116    if (job->storage) {
1117       copy_rwstorage(jcr, job->storage, _("Job resource"));
1118    } else {
1119       copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
1120    }
1121    jcr->client = job->client;
1122    if (!jcr->client_name) {
1123       jcr->client_name = get_pool_memory(PM_NAME);
1124    }
1125    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
1126    pm_strcpy(jcr->pool_source, _("Job resource"));
1127    jcr->pool = job->pool;
1128    jcr->full_pool = job->full_pool;
1129    jcr->inc_pool = job->inc_pool;
1130    jcr->diff_pool = job->diff_pool;
1131    if (job->pool->catalog) {
1132       jcr->catalog = job->pool->catalog;
1133       pm_strcpy(jcr->catalog_source, _("Pool resource"));
1134    } else {
1135       jcr->catalog = job->client->catalog;
1136       pm_strcpy(jcr->catalog_source, _("Client resource"));
1137    }
1138    jcr->fileset = job->fileset;
1139    jcr->messages = job->messages;
1140    jcr->spool_data = job->spool_data;
1141    jcr->spool_size = job->spool_size;
1142    jcr->write_part_after_job = job->write_part_after_job;
1143    jcr->accurate = job->accurate;
1144    if (jcr->RestoreBootstrap) {
1145       free(jcr->RestoreBootstrap);
1146       jcr->RestoreBootstrap = NULL;
1147    }
1148    /* This can be overridden by Console program */
1149    if (job->RestoreBootstrap) {
1150       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1151    }
1152    /* This can be overridden by Console program */
1153    jcr->verify_job = job->verify_job;
1154    /* If no default level given, set one */
1155    if (jcr->get_JobLevel() == 0) {
1156       switch (jcr->get_JobType()) {
1157       case JT_VERIFY:
1158          jcr->set_JobLevel(L_VERIFY_CATALOG);
1159          break;
1160       case JT_BACKUP:
1161          jcr->set_JobLevel(L_INCREMENTAL);
1162          break;
1163       case JT_RESTORE:
1164       case JT_ADMIN:
1165          jcr->set_JobLevel(L_NONE);
1166          break;
1167       default:
1168          jcr->set_JobLevel(L_FULL);
1169          break;
1170       }
1171    }
1172 }
1173
1174 /* 
1175  * Copy the storage definitions from an alist to the JCR
1176  */
1177 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1178 {
1179    if (jcr->JobReads()) {
1180       copy_rstorage(jcr, storage, where);
1181    }
1182    copy_wstorage(jcr, storage, where);
1183 }
1184
1185
1186 /* Set storage override.  Releases any previous storage definition */
1187 void set_rwstorage(JCR *jcr, USTORE *store)
1188 {
1189    if (!store) {
1190       Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1191       return;
1192    }
1193    if (jcr->JobReads()) {
1194       set_rstorage(jcr, store);
1195    }
1196    set_wstorage(jcr, store);
1197 }
1198
1199 void free_rwstorage(JCR *jcr)
1200 {
1201    free_rstorage(jcr);
1202    free_wstorage(jcr);
1203 }
1204
1205 /* 
1206  * Copy the storage definitions from an alist to the JCR
1207  */
1208 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1209 {
1210    if (storage) {
1211       STORE *st;
1212       if (jcr->rstorage) {
1213          delete jcr->rstorage;
1214       }
1215       jcr->rstorage = New(alist(10, not_owned_by_alist));
1216       foreach_alist(st, storage) {
1217          jcr->rstorage->append(st);
1218       }
1219       if (!jcr->rstore_source) {
1220          jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1221       }
1222       pm_strcpy(jcr->rstore_source, where);
1223       if (jcr->rstorage) {
1224          jcr->rstore = (STORE *)jcr->rstorage->first();
1225       }
1226    }
1227 }
1228
1229
1230 /* Set storage override.  Remove all previous storage */
1231 void set_rstorage(JCR *jcr, USTORE *store)
1232 {
1233    STORE *storage;
1234
1235    if (!store->store) {
1236       return;
1237    }
1238    if (jcr->rstorage) {
1239       free_rstorage(jcr);
1240    }
1241    if (!jcr->rstorage) {
1242       jcr->rstorage = New(alist(10, not_owned_by_alist));
1243    }
1244    jcr->rstore = store->store;
1245    if (!jcr->rstore_source) {
1246       jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1247    }
1248    pm_strcpy(jcr->rstore_source, store->store_source);
1249    foreach_alist(storage, jcr->rstorage) {
1250       if (store->store == storage) {
1251          return;
1252       }
1253    }
1254    /* Store not in list, so add it */
1255    jcr->rstorage->prepend(store->store);
1256 }
1257
1258 void free_rstorage(JCR *jcr)
1259 {
1260    if (jcr->rstorage) {
1261       delete jcr->rstorage;
1262       jcr->rstorage = NULL;
1263    }
1264    jcr->rstore = NULL;
1265 }
1266
1267 /* 
1268  * Copy the storage definitions from an alist to the JCR
1269  */
1270 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1271 {
1272    if (storage) {
1273       STORE *st;
1274       if (jcr->wstorage) {
1275          delete jcr->wstorage;
1276       }
1277       jcr->wstorage = New(alist(10, not_owned_by_alist));
1278       foreach_alist(st, storage) {
1279          Dmsg1(100, "wstorage=%s\n", st->name());
1280          jcr->wstorage->append(st);
1281       }
1282       if (!jcr->wstore_source) {
1283          jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1284       }
1285       pm_strcpy(jcr->wstore_source, where);
1286       if (jcr->wstorage) {
1287          jcr->wstore = (STORE *)jcr->wstorage->first();
1288          Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1289       }
1290    }
1291 }
1292
1293
1294 /* Set storage override. Remove all previous storage */
1295 void set_wstorage(JCR *jcr, USTORE *store)
1296 {
1297    STORE *storage;
1298
1299    if (!store->store) {
1300       return;
1301    }
1302    if (jcr->wstorage) {
1303       free_wstorage(jcr);
1304    }
1305    if (!jcr->wstorage) {
1306       jcr->wstorage = New(alist(10, not_owned_by_alist));
1307    }
1308    jcr->wstore = store->store;
1309    if (!jcr->wstore_source) {
1310       jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1311    }
1312    pm_strcpy(jcr->wstore_source, store->store_source);
1313    Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1314    foreach_alist(storage, jcr->wstorage) {
1315       if (store->store == storage) {
1316          return;
1317       }
1318    }
1319    /* Store not in list, so add it */
1320    jcr->wstorage->prepend(store->store);
1321 }
1322
1323 void free_wstorage(JCR *jcr)
1324 {
1325    if (jcr->wstorage) {
1326       delete jcr->wstorage;
1327       jcr->wstorage = NULL;
1328    }
1329    jcr->wstore = NULL;
1330 }
1331
1332 char *job_code_callback_clones(JCR *jcr, const char* param) 
1333 {
1334    if (param[0] == 'p') {
1335       return jcr->pool->name();
1336    }
1337    return NULL;
1338 }
1339
1340 void create_clones(JCR *jcr)
1341 {
1342    /*
1343     * Fire off any clone jobs (run directives)
1344     */
1345    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1346    if (!jcr->cloned && jcr->job->run_cmds) {
1347       char *runcmd;
1348       JOB *job = jcr->job;
1349       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1350       UAContext *ua = new_ua_context(jcr);
1351       ua->batch = true;
1352       foreach_alist(runcmd, job->run_cmds) {
1353          cmd = edit_job_codes(jcr, cmd, runcmd, "", job_code_callback_clones);
1354          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1355          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1356          parse_ua_args(ua);                 /* parse command */
1357          int stat = run_cmd(ua, ua->cmd);
1358          if (stat == 0) {
1359             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job: \"%s\".\n"),
1360                  ua->cmd);
1361          } else {
1362             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1363          }
1364       }
1365       free_ua_context(ua);
1366       free_pool_memory(cmd);
1367    }
1368 }
1369
1370 /*
1371  * Given: a JobId in jcr->previous_jr.JobId,
1372  *  this subroutine writes a bsr file to restore that job.
1373  */
1374 bool create_restore_bootstrap_file(JCR *jcr)
1375 {
1376    RESTORE_CTX rx;
1377    UAContext *ua;
1378    memset(&rx, 0, sizeof(rx));
1379    rx.bsr = new_bsr();
1380    rx.JobIds = (char *)"";                       
1381    rx.bsr->JobId = jcr->previous_jr.JobId;
1382    ua = new_ua_context(jcr);
1383    if (!complete_bsr(ua, rx.bsr)) {
1384       goto bail_out;
1385    }
1386    rx.bsr->fi = new_findex();
1387    rx.bsr->fi->findex = 1;
1388    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1389    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1390    if (jcr->ExpectedFiles == 0) {
1391       goto bail_out;
1392    }
1393    free_ua_context(ua);
1394    free_bsr(rx.bsr);
1395    jcr->needs_sd = true;
1396    return true;
1397
1398 bail_out:
1399    free_ua_context(ua);
1400    free_bsr(rx.bsr);
1401    return false;
1402 }
1403
1404 /* TODO: redirect command ouput to job log */
1405 bool run_console_command(JCR *jcr, const char *cmd)
1406 {
1407    UAContext *ua;
1408    bool ok;
1409    JCR *ljcr = new_control_jcr("-RunScript-", JT_CONSOLE);
1410    ua = new_ua_context(ljcr);
1411    /* run from runscript and check if commands are autorized */
1412    ua->runscript = true;
1413    Mmsg(ua->cmd, "%s", cmd);
1414    Dmsg1(100, "Console command: %s\n", ua->cmd);
1415    parse_ua_args(ua);
1416    ok= do_a_command(ua);
1417    free_ua_context(ua);
1418    free_jcr(ljcr);
1419    return ok;
1420 }