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