]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
252a89a8651692c35c91dddb0490e0dd2ec4e0a7
[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)) {
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 (strcmp(job->name(), djcr->job->name()) == 0) {
676             bool cancel_queued = false;
677             if (job->DuplicateJobProximity > 0) {
678                utime_t now = (utime_t)time(NULL);
679                if ((now - djcr->start_time) > job->DuplicateJobProximity) {
680                   continue;               /* not really a duplicate */
681                }
682             }
683             /* Cancel */
684             if (!(job->CancelQueuedDuplicates || job->CancelRunningDuplicates)) {
685                /* Zap current job */
686                Jmsg(jcr, M_FATAL, 0, _("Duplicate job not allowed. JobId=%s\n"),
687                   edit_uint64(djcr->JobId, ec1));
688                return false;
689             }
690             /* If CancelQueuedDuplicates is set do so only if job is queued */
691             if (job->CancelQueuedDuplicates) {
692                 switch (djcr->JobStatus) {
693                 case JS_Created:
694                 case JS_WaitJobRes:
695                 case JS_WaitClientRes:
696                 case JS_WaitStoreRes:
697                 case JS_WaitPriority:
698                 case JS_WaitMaxJobs:
699                 case JS_WaitStartTime:
700                    cancel_queued = true;
701                    break;
702                 default:
703                    break;
704                 }
705             }
706             if (cancel_queued || job->CancelRunningDuplicates) {
707                UAContext *ua = new_ua_context(djcr);
708                Jmsg(jcr, M_INFO, 0, _("Cancelling duplicate JobId=%s.\n"), 
709                   edit_uint64(djcr->JobId, ec1));
710                ua->jcr = djcr;
711                cancel_job(ua, djcr);
712                free_ua_context(ua);
713                Dmsg2(800, "Have cancelled JCR %p Job=%d\n", djcr, djcr->JobId);
714             }
715          }
716       }
717       endeach_jcr(djcr);
718    }
719    return true;   
720 }
721
722 void apply_pool_overrides(JCR *jcr)
723 {
724    bool pool_override = false;
725
726    if (jcr->run_pool_override) {
727       pm_strcpy(jcr->pool_source, _("Run pool override"));
728    }
729    /*
730     * Apply any level related Pool selections
731     */
732    switch (jcr->get_JobLevel()) {
733    case L_FULL:
734       if (jcr->full_pool) {
735          jcr->pool = jcr->full_pool;
736          pool_override = true;
737          if (jcr->run_full_pool_override) {
738             pm_strcpy(jcr->pool_source, _("Run FullPool override"));
739          } else {
740             pm_strcpy(jcr->pool_source, _("Job FullPool override"));
741          }
742       }
743       break;
744    case L_INCREMENTAL:
745       if (jcr->inc_pool) {
746          jcr->pool = jcr->inc_pool;
747          pool_override = true;
748          if (jcr->run_inc_pool_override) {
749             pm_strcpy(jcr->pool_source, _("Run IncPool override"));
750          } else {
751             pm_strcpy(jcr->pool_source, _("Job IncPool override"));
752          }
753       }
754       break;
755    case L_DIFFERENTIAL:
756       if (jcr->diff_pool) {
757          jcr->pool = jcr->diff_pool;
758          pool_override = true;
759          if (jcr->run_diff_pool_override) {
760             pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
761          } else {
762             pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
763          }
764       }
765       break;
766    }
767    /* Update catalog if pool overridden */
768    if (pool_override && jcr->pool->catalog) {
769       jcr->catalog = jcr->pool->catalog;
770       pm_strcpy(jcr->catalog_source, _("Pool resource"));
771    }
772 }
773
774
775 /*
776  * Get or create a Client record for this Job
777  */
778 bool get_or_create_client_record(JCR *jcr)
779 {
780    CLIENT_DBR cr;
781
782    memset(&cr, 0, sizeof(cr));
783    bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
784    cr.AutoPrune = jcr->client->AutoPrune;
785    cr.FileRetention = jcr->client->FileRetention;
786    cr.JobRetention = jcr->client->JobRetention;
787    if (!jcr->client_name) {
788       jcr->client_name = get_pool_memory(PM_NAME);
789    }
790    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
791    if (!db_create_client_record(jcr, jcr->db, &cr)) {
792       Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
793          db_strerror(jcr->db));
794       return false;
795    }
796    jcr->jr.ClientId = cr.ClientId;
797    if (cr.Uname[0]) {
798       if (!jcr->client_uname) {
799          jcr->client_uname = get_pool_memory(PM_NAME);
800       }
801       pm_strcpy(jcr->client_uname, cr.Uname);
802    }
803    Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
804       jcr->jr.ClientId);
805    return true;
806 }
807
808 bool get_or_create_fileset_record(JCR *jcr)
809 {
810    FILESET_DBR fsr;
811    /*
812     * Get or Create FileSet record
813     */
814    memset(&fsr, 0, sizeof(FILESET_DBR));
815    bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
816    if (jcr->fileset->have_MD5) {
817       struct MD5Context md5c;
818       unsigned char digest[MD5HashSize];
819       memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
820       MD5Final(digest, &md5c);
821       /*
822        * Keep the flag (last arg) set to false otherwise old FileSets will
823        * get new MD5 sums and the user will get Full backups on everything
824        */
825       bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
826       bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
827    } else {
828       Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
829    }
830    if (!jcr->fileset->ignore_fs_changes ||
831        !db_get_fileset_record(jcr, jcr->db, &fsr)) {
832       if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
833          Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
834             fsr.FileSet, db_strerror(jcr->db));
835          return false;
836       }
837    }
838    jcr->jr.FileSetId = fsr.FileSetId;
839    bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
840    Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
841       jcr->jr.FileSetId);
842    return true;
843 }
844
845 void init_jcr_job_record(JCR *jcr)
846 {
847    jcr->jr.SchedTime = jcr->sched_time;
848    jcr->jr.StartTime = jcr->start_time;
849    jcr->jr.EndTime = 0;               /* perhaps rescheduled, clear it */
850    jcr->jr.JobType = jcr->get_JobType();
851    jcr->jr.JobLevel = jcr->get_JobLevel();
852    jcr->jr.JobStatus = jcr->JobStatus;
853    jcr->jr.JobId = jcr->JobId;
854    bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
855    bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
856 }
857
858 /*
859  * Write status and such in DB
860  */
861 void update_job_end_record(JCR *jcr)
862 {
863    jcr->jr.EndTime = time(NULL);
864    jcr->end_time = jcr->jr.EndTime;
865    jcr->jr.JobId = jcr->JobId;
866    jcr->jr.JobStatus = jcr->JobStatus;
867    jcr->jr.JobFiles = jcr->JobFiles;
868    jcr->jr.JobBytes = jcr->JobBytes;
869    jcr->jr.ReadBytes = jcr->ReadBytes;
870    jcr->jr.VolSessionId = jcr->VolSessionId;
871    jcr->jr.VolSessionTime = jcr->VolSessionTime;
872    jcr->jr.JobErrors = jcr->JobErrors;
873    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
874       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
875          db_strerror(jcr->db));
876    }
877 }
878
879 /*
880  * Takes base_name and appends (unique) current
881  *   date and time to form unique job name.
882  *
883  *  Note, the seconds are actually a sequence number. This
884  *   permits us to start a maximum fo 59 unique jobs a second, which
885  *   should be sufficient.
886  *
887  *  Returns: unique job name in jcr->Job
888  *    date/time in jcr->start_time
889  */
890 void create_unique_job_name(JCR *jcr, const char *base_name)
891 {
892    /* Job start mutex */
893    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
894    static time_t last_start_time = 0;
895    static int seq = 0;
896    time_t now = time(NULL);
897    struct tm tm;
898    char dt[MAX_TIME_LENGTH];
899    char name[MAX_NAME_LENGTH];
900    char *p;
901    int len;
902
903    /* Guarantee unique start time -- maximum one per second, and
904     * thus unique Job Name
905     */
906    P(mutex);                          /* lock creation of jobs */
907    seq++;
908    if (seq > 59) {                    /* wrap as if it is seconds */
909       seq = 0;
910       while (now == last_start_time) {
911          bmicrosleep(0, 500000);
912          now = time(NULL);
913       }
914    }
915    last_start_time = now;
916    V(mutex);                          /* allow creation of jobs */
917    jcr->start_time = now;
918    /* Form Unique JobName */
919    (void)localtime_r(&now, &tm);
920    /* Use only characters that are permitted in Windows filenames */
921    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
922    len = strlen(dt) + 5;   /* dt + .%02d EOS */
923    bstrncpy(name, base_name, sizeof(name));
924    name[sizeof(name)-len] = 0;          /* truncate if too long */
925    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s_%02d", name, dt, seq); /* add date & time */
926    /* Convert spaces into underscores */
927    for (p=jcr->Job; *p; p++) {
928       if (*p == ' ') {
929          *p = '_';
930       }
931    }
932    Dmsg2(100, "JobId=%u created Job=%s\n", jcr->JobId, jcr->Job);
933 }
934
935 /* Called directly from job rescheduling */
936 void dird_free_jcr_pointers(JCR *jcr)
937 {
938    if (jcr->sd_auth_key) {
939       free(jcr->sd_auth_key);
940       jcr->sd_auth_key = NULL;
941    }
942    if (jcr->where) {
943       free(jcr->where);
944       jcr->where = NULL;
945    }
946    if (jcr->file_bsock) {
947       Dmsg0(200, "Close File bsock\n");
948       bnet_close(jcr->file_bsock);
949       jcr->file_bsock = NULL;
950    }
951    if (jcr->store_bsock) {
952       Dmsg0(200, "Close Store bsock\n");
953       bnet_close(jcr->store_bsock);
954       jcr->store_bsock = NULL;
955    }
956    if (jcr->fname) {
957       Dmsg0(200, "Free JCR fname\n");
958       free_pool_memory(jcr->fname);
959       jcr->fname = NULL;
960    }
961    if (jcr->RestoreBootstrap) {
962       free(jcr->RestoreBootstrap);
963       jcr->RestoreBootstrap = NULL;
964    }
965    if (jcr->client_uname) {
966       free_pool_memory(jcr->client_uname);
967       jcr->client_uname = NULL;
968    }
969    if (jcr->attr) {
970       free_pool_memory(jcr->attr);
971       jcr->attr = NULL;
972    }
973    if (jcr->ar) {
974       free(jcr->ar);
975       jcr->ar = NULL;
976    }
977 }
978
979 /*
980  * Free the Job Control Record if no one is still using it.
981  *  Called from main free_jcr() routine in src/lib/jcr.c so
982  *  that we can do our Director specific cleanup of the jcr.
983  */
984 void dird_free_jcr(JCR *jcr)
985 {
986    Dmsg0(200, "Start dird free_jcr\n");
987
988    dird_free_jcr_pointers(jcr);
989    if (jcr->term_wait_inited) {
990       pthread_cond_destroy(&jcr->term_wait);
991       jcr->term_wait_inited = false;
992    }
993    if (jcr->db_batch) {
994       db_close_database(jcr, jcr->db_batch);
995       jcr->db_batch = NULL;
996       jcr->batch_started = false;
997    }
998    if (jcr->db) {
999       db_close_database(jcr, jcr->db);
1000       jcr->db = NULL;
1001    }
1002    if (jcr->stime) {
1003       Dmsg0(200, "Free JCR stime\n");
1004       free_pool_memory(jcr->stime);
1005       jcr->stime = NULL;
1006    }
1007    if (jcr->fname) {
1008       Dmsg0(200, "Free JCR fname\n");
1009       free_pool_memory(jcr->fname);
1010       jcr->fname = NULL;
1011    }
1012    if (jcr->pool_source) {
1013       free_pool_memory(jcr->pool_source);
1014       jcr->pool_source = NULL;
1015    }
1016    if (jcr->catalog_source) {
1017       free_pool_memory(jcr->catalog_source);
1018       jcr->catalog_source = NULL;
1019    }
1020    if (jcr->rpool_source) {
1021       free_pool_memory(jcr->rpool_source);
1022       jcr->rpool_source = NULL;
1023    }
1024    if (jcr->wstore_source) {
1025       free_pool_memory(jcr->wstore_source);
1026       jcr->wstore_source = NULL;
1027    }
1028    if (jcr->rstore_source) {
1029       free_pool_memory(jcr->rstore_source);
1030       jcr->rstore_source = NULL;
1031    }
1032
1033    /* Delete lists setup to hold storage pointers */
1034    free_rwstorage(jcr);
1035
1036    jcr->job_end_push.destroy();
1037
1038    if (jcr->JobId != 0)
1039       write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
1040
1041    free_plugins(jcr);                 /* release instantiated plugins */
1042
1043    Dmsg0(200, "End dird free_jcr\n");
1044 }
1045
1046 /* 
1047  * The Job storage definition must be either in the Job record
1048  *  or in the Pool record.  The Pool record overrides the Job 
1049  *  record.
1050  */
1051 void get_job_storage(USTORE *store, JOB *job, RUN *run) 
1052 {
1053    if (run && run->pool && run->pool->storage) {
1054       store->store = (STORE *)run->pool->storage->first();
1055       pm_strcpy(store->store_source, _("Run pool override"));
1056       return;
1057    }
1058    if (run && run->storage) {
1059       store->store = run->storage;
1060       pm_strcpy(store->store_source, _("Run storage override"));
1061       return;
1062    }
1063    if (job->pool->storage) {
1064       store->store = (STORE *)job->pool->storage->first();
1065       pm_strcpy(store->store_source, _("Pool resource"));
1066    } else {
1067       store->store = (STORE *)job->storage->first();
1068       pm_strcpy(store->store_source, _("Job resource"));
1069    }
1070 }
1071
1072 /*
1073  * Set some defaults in the JCR necessary to
1074  * run. These items are pulled from the job
1075  * definition as defaults, but can be overridden
1076  * later either by the Run record in the Schedule resource,
1077  * or by the Console program.
1078  */
1079 void set_jcr_defaults(JCR *jcr, JOB *job)
1080 {
1081    jcr->job = job;
1082    jcr->set_JobType(job->JobType);
1083    jcr->JobStatus = JS_Created;
1084
1085    switch (jcr->get_JobType()) {
1086    case JT_ADMIN:
1087       jcr->set_JobLevel(L_NONE);
1088       break;
1089    default:
1090       jcr->set_JobLevel(job->JobLevel);
1091       break;
1092    }
1093
1094    if (!jcr->fname) {
1095       jcr->fname = get_pool_memory(PM_FNAME);
1096    }
1097    if (!jcr->pool_source) {
1098       jcr->pool_source = get_pool_memory(PM_MESSAGE);
1099       pm_strcpy(jcr->pool_source, _("unknown source"));
1100    }
1101    if (!jcr->catalog_source) {
1102       jcr->catalog_source = get_pool_memory(PM_MESSAGE);
1103       pm_strcpy(jcr->catalog_source, _("unknown source"));
1104    }
1105
1106    jcr->JobPriority = job->Priority;
1107    /* Copy storage definitions -- deleted in dir_free_jcr above */
1108    if (job->storage) {
1109       copy_rwstorage(jcr, job->storage, _("Job resource"));
1110    } else {
1111       copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
1112    }
1113    jcr->client = job->client;
1114    if (!jcr->client_name) {
1115       jcr->client_name = get_pool_memory(PM_NAME);
1116    }
1117    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
1118    pm_strcpy(jcr->pool_source, _("Job resource"));
1119    jcr->pool = job->pool;
1120    jcr->full_pool = job->full_pool;
1121    jcr->inc_pool = job->inc_pool;
1122    jcr->diff_pool = job->diff_pool;
1123    if (job->pool->catalog) {
1124       jcr->catalog = job->pool->catalog;
1125       pm_strcpy(jcr->catalog_source, _("Pool resource"));
1126    } else {
1127       jcr->catalog = job->client->catalog;
1128       pm_strcpy(jcr->catalog_source, _("Client resource"));
1129    }
1130    jcr->fileset = job->fileset;
1131    jcr->messages = job->messages;
1132    jcr->spool_data = job->spool_data;
1133    jcr->spool_size = job->spool_size;
1134    jcr->write_part_after_job = job->write_part_after_job;
1135    jcr->accurate = job->accurate;
1136    if (jcr->RestoreBootstrap) {
1137       free(jcr->RestoreBootstrap);
1138       jcr->RestoreBootstrap = NULL;
1139    }
1140    /* This can be overridden by Console program */
1141    if (job->RestoreBootstrap) {
1142       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1143    }
1144    /* This can be overridden by Console program */
1145    jcr->verify_job = job->verify_job;
1146    /* If no default level given, set one */
1147    if (jcr->get_JobLevel() == 0) {
1148       switch (jcr->get_JobType()) {
1149       case JT_VERIFY:
1150          jcr->set_JobLevel(L_VERIFY_CATALOG);
1151          break;
1152       case JT_BACKUP:
1153          jcr->set_JobLevel(L_INCREMENTAL);
1154          break;
1155       case JT_RESTORE:
1156       case JT_ADMIN:
1157          jcr->set_JobLevel(L_NONE);
1158          break;
1159       default:
1160          jcr->set_JobLevel(L_FULL);
1161          break;
1162       }
1163    }
1164 }
1165
1166 /* 
1167  * Copy the storage definitions from an alist to the JCR
1168  */
1169 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1170 {
1171    if (jcr->JobReads()) {
1172       copy_rstorage(jcr, storage, where);
1173    }
1174    copy_wstorage(jcr, storage, where);
1175 }
1176
1177
1178 /* Set storage override.  Releases any previous storage definition */
1179 void set_rwstorage(JCR *jcr, USTORE *store)
1180 {
1181    if (!store) {
1182       Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1183       return;
1184    }
1185    if (jcr->JobReads()) {
1186       set_rstorage(jcr, store);
1187    }
1188    set_wstorage(jcr, store);
1189 }
1190
1191 void free_rwstorage(JCR *jcr)
1192 {
1193    free_rstorage(jcr);
1194    free_wstorage(jcr);
1195 }
1196
1197 /* 
1198  * Copy the storage definitions from an alist to the JCR
1199  */
1200 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1201 {
1202    if (storage) {
1203       STORE *st;
1204       if (jcr->rstorage) {
1205          delete jcr->rstorage;
1206       }
1207       jcr->rstorage = New(alist(10, not_owned_by_alist));
1208       foreach_alist(st, storage) {
1209          jcr->rstorage->append(st);
1210       }
1211       if (!jcr->rstore_source) {
1212          jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1213       }
1214       pm_strcpy(jcr->rstore_source, where);
1215       if (jcr->rstorage) {
1216          jcr->rstore = (STORE *)jcr->rstorage->first();
1217       }
1218    }
1219 }
1220
1221
1222 /* Set storage override.  Remove all previous storage */
1223 void set_rstorage(JCR *jcr, USTORE *store)
1224 {
1225    STORE *storage;
1226
1227    if (!store->store) {
1228       return;
1229    }
1230    if (jcr->rstorage) {
1231       free_rstorage(jcr);
1232    }
1233    if (!jcr->rstorage) {
1234       jcr->rstorage = New(alist(10, not_owned_by_alist));
1235    }
1236    jcr->rstore = store->store;
1237    if (!jcr->rstore_source) {
1238       jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1239    }
1240    pm_strcpy(jcr->rstore_source, store->store_source);
1241    foreach_alist(storage, jcr->rstorage) {
1242       if (store->store == storage) {
1243          return;
1244       }
1245    }
1246    /* Store not in list, so add it */
1247    jcr->rstorage->prepend(store->store);
1248 }
1249
1250 void free_rstorage(JCR *jcr)
1251 {
1252    if (jcr->rstorage) {
1253       delete jcr->rstorage;
1254       jcr->rstorage = NULL;
1255    }
1256    jcr->rstore = NULL;
1257 }
1258
1259 /* 
1260  * Copy the storage definitions from an alist to the JCR
1261  */
1262 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1263 {
1264    if (storage) {
1265       STORE *st;
1266       if (jcr->wstorage) {
1267          delete jcr->wstorage;
1268       }
1269       jcr->wstorage = New(alist(10, not_owned_by_alist));
1270       foreach_alist(st, storage) {
1271          Dmsg1(100, "wstorage=%s\n", st->name());
1272          jcr->wstorage->append(st);
1273       }
1274       if (!jcr->wstore_source) {
1275          jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1276       }
1277       pm_strcpy(jcr->wstore_source, where);
1278       if (jcr->wstorage) {
1279          jcr->wstore = (STORE *)jcr->wstorage->first();
1280          Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1281       }
1282    }
1283 }
1284
1285
1286 /* Set storage override. Remove all previous storage */
1287 void set_wstorage(JCR *jcr, USTORE *store)
1288 {
1289    STORE *storage;
1290
1291    if (!store->store) {
1292       return;
1293    }
1294    if (jcr->wstorage) {
1295       free_wstorage(jcr);
1296    }
1297    if (!jcr->wstorage) {
1298       jcr->wstorage = New(alist(10, not_owned_by_alist));
1299    }
1300    jcr->wstore = store->store;
1301    if (!jcr->wstore_source) {
1302       jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1303    }
1304    pm_strcpy(jcr->wstore_source, store->store_source);
1305    Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1306    foreach_alist(storage, jcr->wstorage) {
1307       if (store->store == storage) {
1308          return;
1309       }
1310    }
1311    /* Store not in list, so add it */
1312    jcr->wstorage->prepend(store->store);
1313 }
1314
1315 void free_wstorage(JCR *jcr)
1316 {
1317    if (jcr->wstorage) {
1318       delete jcr->wstorage;
1319       jcr->wstorage = NULL;
1320    }
1321    jcr->wstore = NULL;
1322 }
1323
1324 char *job_code_callback_clones(JCR *jcr, const char* param) 
1325 {
1326    if (param[0] == 'p') {
1327       return jcr->pool->name();
1328    }
1329    return NULL;
1330 }
1331
1332 void create_clones(JCR *jcr)
1333 {
1334    /*
1335     * Fire off any clone jobs (run directives)
1336     */
1337    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1338    if (!jcr->cloned && jcr->job->run_cmds) {
1339       char *runcmd;
1340       JOB *job = jcr->job;
1341       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1342       UAContext *ua = new_ua_context(jcr);
1343       ua->batch = true;
1344       foreach_alist(runcmd, job->run_cmds) {
1345          cmd = edit_job_codes(jcr, cmd, runcmd, "", job_code_callback_clones);
1346          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1347          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1348          parse_ua_args(ua);                 /* parse command */
1349          int stat = run_cmd(ua, ua->cmd);
1350          if (stat == 0) {
1351             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job: \"%s\".\n"),
1352                  ua->cmd);
1353          } else {
1354             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1355          }
1356       }
1357       free_ua_context(ua);
1358       free_pool_memory(cmd);
1359    }
1360 }
1361
1362 /*
1363  * Given: a JobId in jcr->previous_jr.JobId,
1364  *  this subroutine writes a bsr file to restore that job.
1365  */
1366 bool create_restore_bootstrap_file(JCR *jcr)
1367 {
1368    RESTORE_CTX rx;
1369    UAContext *ua;
1370    memset(&rx, 0, sizeof(rx));
1371    rx.bsr = new_bsr();
1372    rx.JobIds = (char *)"";                       
1373    rx.bsr->JobId = jcr->previous_jr.JobId;
1374    ua = new_ua_context(jcr);
1375    if (!complete_bsr(ua, rx.bsr)) {
1376       goto bail_out;
1377    }
1378    rx.bsr->fi = new_findex();
1379    rx.bsr->fi->findex = 1;
1380    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1381    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1382    if (jcr->ExpectedFiles == 0) {
1383       goto bail_out;
1384    }
1385    free_ua_context(ua);
1386    free_bsr(rx.bsr);
1387    jcr->needs_sd = true;
1388    return true;
1389
1390 bail_out:
1391    free_ua_context(ua);
1392    free_bsr(rx.bsr);
1393    return false;
1394 }
1395
1396 /* TODO: redirect command ouput to job log */
1397 bool run_console_command(JCR *jcr, const char *cmd)
1398 {
1399    UAContext *ua;
1400    bool ok;
1401    JCR *ljcr = new_control_jcr("-RunScript-", JT_CONSOLE);
1402    ua = new_ua_context(ljcr);
1403    /* run from runscript and check if commands are autorized */
1404    ua->runscript = true;
1405    Mmsg(ua->cmd, "%s", cmd);
1406    Dmsg1(100, "Console command: %s\n", ua->cmd);
1407    parse_ua_args(ua);
1408    ok= do_a_command(ua);
1409    free_ua_context(ua);
1410    free_jcr(ljcr);
1411    return ok;
1412 }