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