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