]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
Merge branch 'master' into basejobv3
[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    jcr->jr.HasBase = jcr->HasBase;
879    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
880       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
881          db_strerror(jcr->db));
882    }
883 }
884
885 /*
886  * Takes base_name and appends (unique) current
887  *   date and time to form unique job name.
888  *
889  *  Note, the seconds are actually a sequence number. This
890  *   permits us to start a maximum fo 59 unique jobs a second, which
891  *   should be sufficient.
892  *
893  *  Returns: unique job name in jcr->Job
894  *    date/time in jcr->start_time
895  */
896 void create_unique_job_name(JCR *jcr, const char *base_name)
897 {
898    /* Job start mutex */
899    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
900    static time_t last_start_time = 0;
901    static int seq = 0;
902    time_t now = time(NULL);
903    struct tm tm;
904    char dt[MAX_TIME_LENGTH];
905    char name[MAX_NAME_LENGTH];
906    char *p;
907    int len;
908
909    /* Guarantee unique start time -- maximum one per second, and
910     * thus unique Job Name
911     */
912    P(mutex);                          /* lock creation of jobs */
913    seq++;
914    if (seq > 59) {                    /* wrap as if it is seconds */
915       seq = 0;
916       while (now == last_start_time) {
917          bmicrosleep(0, 500000);
918          now = time(NULL);
919       }
920    }
921    last_start_time = now;
922    V(mutex);                          /* allow creation of jobs */
923    jcr->start_time = now;
924    /* Form Unique JobName */
925    (void)localtime_r(&now, &tm);
926    /* Use only characters that are permitted in Windows filenames */
927    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
928    len = strlen(dt) + 5;   /* dt + .%02d EOS */
929    bstrncpy(name, base_name, sizeof(name));
930    name[sizeof(name)-len] = 0;          /* truncate if too long */
931    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s_%02d", name, dt, seq); /* add date & time */
932    /* Convert spaces into underscores */
933    for (p=jcr->Job; *p; p++) {
934       if (*p == ' ') {
935          *p = '_';
936       }
937    }
938    Dmsg2(100, "JobId=%u created Job=%s\n", jcr->JobId, jcr->Job);
939 }
940
941 /* Called directly from job rescheduling */
942 void dird_free_jcr_pointers(JCR *jcr)
943 {
944    if (jcr->sd_auth_key) {
945       free(jcr->sd_auth_key);
946       jcr->sd_auth_key = NULL;
947    }
948    if (jcr->where) {
949       free(jcr->where);
950       jcr->where = NULL;
951    }
952    if (jcr->file_bsock) {
953       Dmsg0(200, "Close File bsock\n");
954       bnet_close(jcr->file_bsock);
955       jcr->file_bsock = NULL;
956    }
957    if (jcr->store_bsock) {
958       Dmsg0(200, "Close Store bsock\n");
959       bnet_close(jcr->store_bsock);
960       jcr->store_bsock = NULL;
961    }
962    if (jcr->fname) {
963       Dmsg0(200, "Free JCR fname\n");
964       free_pool_memory(jcr->fname);
965       jcr->fname = NULL;
966    }
967    if (jcr->RestoreBootstrap) {
968       free(jcr->RestoreBootstrap);
969       jcr->RestoreBootstrap = NULL;
970    }
971    if (jcr->client_uname) {
972       free_pool_memory(jcr->client_uname);
973       jcr->client_uname = NULL;
974    }
975    if (jcr->attr) {
976       free_pool_memory(jcr->attr);
977       jcr->attr = NULL;
978    }
979    if (jcr->ar) {
980       free(jcr->ar);
981       jcr->ar = NULL;
982    }
983 }
984
985 /*
986  * Free the Job Control Record if no one is still using it.
987  *  Called from main free_jcr() routine in src/lib/jcr.c so
988  *  that we can do our Director specific cleanup of the jcr.
989  */
990 void dird_free_jcr(JCR *jcr)
991 {
992    Dmsg0(200, "Start dird free_jcr\n");
993
994    dird_free_jcr_pointers(jcr);
995    if (jcr->term_wait_inited) {
996       pthread_cond_destroy(&jcr->term_wait);
997       jcr->term_wait_inited = false;
998    }
999    if (jcr->db_batch) {
1000       db_close_database(jcr, jcr->db_batch);
1001       jcr->db_batch = NULL;
1002       jcr->batch_started = false;
1003    }
1004    if (jcr->db) {
1005       db_close_database(jcr, jcr->db);
1006       jcr->db = NULL;
1007    }
1008    if (jcr->stime) {
1009       Dmsg0(200, "Free JCR stime\n");
1010       free_pool_memory(jcr->stime);
1011       jcr->stime = NULL;
1012    }
1013    if (jcr->fname) {
1014       Dmsg0(200, "Free JCR fname\n");
1015       free_pool_memory(jcr->fname);
1016       jcr->fname = NULL;
1017    }
1018    if (jcr->pool_source) {
1019       free_pool_memory(jcr->pool_source);
1020       jcr->pool_source = NULL;
1021    }
1022    if (jcr->catalog_source) {
1023       free_pool_memory(jcr->catalog_source);
1024       jcr->catalog_source = NULL;
1025    }
1026    if (jcr->rpool_source) {
1027       free_pool_memory(jcr->rpool_source);
1028       jcr->rpool_source = NULL;
1029    }
1030    if (jcr->wstore_source) {
1031       free_pool_memory(jcr->wstore_source);
1032       jcr->wstore_source = NULL;
1033    }
1034    if (jcr->rstore_source) {
1035       free_pool_memory(jcr->rstore_source);
1036       jcr->rstore_source = NULL;
1037    }
1038
1039    /* Delete lists setup to hold storage pointers */
1040    free_rwstorage(jcr);
1041
1042    jcr->job_end_push.destroy();
1043
1044    if (jcr->JobId != 0)
1045       write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
1046
1047    free_plugins(jcr);                 /* release instantiated plugins */
1048
1049    Dmsg0(200, "End dird free_jcr\n");
1050 }
1051
1052 /* 
1053  * The Job storage definition must be either in the Job record
1054  *  or in the Pool record.  The Pool record overrides the Job 
1055  *  record.
1056  */
1057 void get_job_storage(USTORE *store, JOB *job, RUN *run) 
1058 {
1059    if (run && run->pool && run->pool->storage) {
1060       store->store = (STORE *)run->pool->storage->first();
1061       pm_strcpy(store->store_source, _("Run pool override"));
1062       return;
1063    }
1064    if (run && run->storage) {
1065       store->store = run->storage;
1066       pm_strcpy(store->store_source, _("Run storage override"));
1067       return;
1068    }
1069    if (job->pool->storage) {
1070       store->store = (STORE *)job->pool->storage->first();
1071       pm_strcpy(store->store_source, _("Pool resource"));
1072    } else {
1073       store->store = (STORE *)job->storage->first();
1074       pm_strcpy(store->store_source, _("Job resource"));
1075    }
1076 }
1077
1078 /*
1079  * Set some defaults in the JCR necessary to
1080  * run. These items are pulled from the job
1081  * definition as defaults, but can be overridden
1082  * later either by the Run record in the Schedule resource,
1083  * or by the Console program.
1084  */
1085 void set_jcr_defaults(JCR *jcr, JOB *job)
1086 {
1087    jcr->job = job;
1088    jcr->set_JobType(job->JobType);
1089    jcr->JobStatus = JS_Created;
1090
1091    switch (jcr->get_JobType()) {
1092    case JT_ADMIN:
1093       jcr->set_JobLevel(L_NONE);
1094       break;
1095    default:
1096       jcr->set_JobLevel(job->JobLevel);
1097       break;
1098    }
1099
1100    if (!jcr->fname) {
1101       jcr->fname = get_pool_memory(PM_FNAME);
1102    }
1103    if (!jcr->pool_source) {
1104       jcr->pool_source = get_pool_memory(PM_MESSAGE);
1105       pm_strcpy(jcr->pool_source, _("unknown source"));
1106    }
1107    if (!jcr->catalog_source) {
1108       jcr->catalog_source = get_pool_memory(PM_MESSAGE);
1109       pm_strcpy(jcr->catalog_source, _("unknown source"));
1110    }
1111
1112    jcr->JobPriority = job->Priority;
1113    /* Copy storage definitions -- deleted in dir_free_jcr above */
1114    if (job->storage) {
1115       copy_rwstorage(jcr, job->storage, _("Job resource"));
1116    } else {
1117       copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
1118    }
1119    jcr->client = job->client;
1120    if (!jcr->client_name) {
1121       jcr->client_name = get_pool_memory(PM_NAME);
1122    }
1123    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
1124    pm_strcpy(jcr->pool_source, _("Job resource"));
1125    jcr->pool = job->pool;
1126    jcr->full_pool = job->full_pool;
1127    jcr->inc_pool = job->inc_pool;
1128    jcr->diff_pool = job->diff_pool;
1129    if (job->pool->catalog) {
1130       jcr->catalog = job->pool->catalog;
1131       pm_strcpy(jcr->catalog_source, _("Pool resource"));
1132    } else {
1133       jcr->catalog = job->client->catalog;
1134       pm_strcpy(jcr->catalog_source, _("Client resource"));
1135    }
1136    jcr->fileset = job->fileset;
1137    jcr->messages = job->messages;
1138    jcr->spool_data = job->spool_data;
1139    jcr->spool_size = job->spool_size;
1140    jcr->write_part_after_job = job->write_part_after_job;
1141    jcr->accurate = job->accurate;
1142    if (jcr->RestoreBootstrap) {
1143       free(jcr->RestoreBootstrap);
1144       jcr->RestoreBootstrap = NULL;
1145    }
1146    /* This can be overridden by Console program */
1147    if (job->RestoreBootstrap) {
1148       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1149    }
1150    /* This can be overridden by Console program */
1151    jcr->verify_job = job->verify_job;
1152    /* If no default level given, set one */
1153    if (jcr->get_JobLevel() == 0) {
1154       switch (jcr->get_JobType()) {
1155       case JT_VERIFY:
1156          jcr->set_JobLevel(L_VERIFY_CATALOG);
1157          break;
1158       case JT_BACKUP:
1159          jcr->set_JobLevel(L_INCREMENTAL);
1160          break;
1161       case JT_RESTORE:
1162       case JT_ADMIN:
1163          jcr->set_JobLevel(L_NONE);
1164          break;
1165       default:
1166          jcr->set_JobLevel(L_FULL);
1167          break;
1168       }
1169    }
1170 }
1171
1172 /* 
1173  * Copy the storage definitions from an alist to the JCR
1174  */
1175 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1176 {
1177    if (jcr->JobReads()) {
1178       copy_rstorage(jcr, storage, where);
1179    }
1180    copy_wstorage(jcr, storage, where);
1181 }
1182
1183
1184 /* Set storage override.  Releases any previous storage definition */
1185 void set_rwstorage(JCR *jcr, USTORE *store)
1186 {
1187    if (!store) {
1188       Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1189       return;
1190    }
1191    if (jcr->JobReads()) {
1192       set_rstorage(jcr, store);
1193    }
1194    set_wstorage(jcr, store);
1195 }
1196
1197 void free_rwstorage(JCR *jcr)
1198 {
1199    free_rstorage(jcr);
1200    free_wstorage(jcr);
1201 }
1202
1203 /* 
1204  * Copy the storage definitions from an alist to the JCR
1205  */
1206 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1207 {
1208    if (storage) {
1209       STORE *st;
1210       if (jcr->rstorage) {
1211          delete jcr->rstorage;
1212       }
1213       jcr->rstorage = New(alist(10, not_owned_by_alist));
1214       foreach_alist(st, storage) {
1215          jcr->rstorage->append(st);
1216       }
1217       if (!jcr->rstore_source) {
1218          jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1219       }
1220       pm_strcpy(jcr->rstore_source, where);
1221       if (jcr->rstorage) {
1222          jcr->rstore = (STORE *)jcr->rstorage->first();
1223       }
1224    }
1225 }
1226
1227
1228 /* Set storage override.  Remove all previous storage */
1229 void set_rstorage(JCR *jcr, USTORE *store)
1230 {
1231    STORE *storage;
1232
1233    if (!store->store) {
1234       return;
1235    }
1236    if (jcr->rstorage) {
1237       free_rstorage(jcr);
1238    }
1239    if (!jcr->rstorage) {
1240       jcr->rstorage = New(alist(10, not_owned_by_alist));
1241    }
1242    jcr->rstore = store->store;
1243    if (!jcr->rstore_source) {
1244       jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1245    }
1246    pm_strcpy(jcr->rstore_source, store->store_source);
1247    foreach_alist(storage, jcr->rstorage) {
1248       if (store->store == storage) {
1249          return;
1250       }
1251    }
1252    /* Store not in list, so add it */
1253    jcr->rstorage->prepend(store->store);
1254 }
1255
1256 void free_rstorage(JCR *jcr)
1257 {
1258    if (jcr->rstorage) {
1259       delete jcr->rstorage;
1260       jcr->rstorage = NULL;
1261    }
1262    jcr->rstore = NULL;
1263 }
1264
1265 /* 
1266  * Copy the storage definitions from an alist to the JCR
1267  */
1268 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1269 {
1270    if (storage) {
1271       STORE *st;
1272       if (jcr->wstorage) {
1273          delete jcr->wstorage;
1274       }
1275       jcr->wstorage = New(alist(10, not_owned_by_alist));
1276       foreach_alist(st, storage) {
1277          Dmsg1(100, "wstorage=%s\n", st->name());
1278          jcr->wstorage->append(st);
1279       }
1280       if (!jcr->wstore_source) {
1281          jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1282       }
1283       pm_strcpy(jcr->wstore_source, where);
1284       if (jcr->wstorage) {
1285          jcr->wstore = (STORE *)jcr->wstorage->first();
1286          Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1287       }
1288    }
1289 }
1290
1291
1292 /* Set storage override. Remove all previous storage */
1293 void set_wstorage(JCR *jcr, USTORE *store)
1294 {
1295    STORE *storage;
1296
1297    if (!store->store) {
1298       return;
1299    }
1300    if (jcr->wstorage) {
1301       free_wstorage(jcr);
1302    }
1303    if (!jcr->wstorage) {
1304       jcr->wstorage = New(alist(10, not_owned_by_alist));
1305    }
1306    jcr->wstore = store->store;
1307    if (!jcr->wstore_source) {
1308       jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1309    }
1310    pm_strcpy(jcr->wstore_source, store->store_source);
1311    Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1312    foreach_alist(storage, jcr->wstorage) {
1313       if (store->store == storage) {
1314          return;
1315       }
1316    }
1317    /* Store not in list, so add it */
1318    jcr->wstorage->prepend(store->store);
1319 }
1320
1321 void free_wstorage(JCR *jcr)
1322 {
1323    if (jcr->wstorage) {
1324       delete jcr->wstorage;
1325       jcr->wstorage = NULL;
1326    }
1327    jcr->wstore = NULL;
1328 }
1329
1330 char *job_code_callback_clones(JCR *jcr, const char* param) 
1331 {
1332    if (param[0] == 'p') {
1333       return jcr->pool->name();
1334    }
1335    return NULL;
1336 }
1337
1338 void create_clones(JCR *jcr)
1339 {
1340    /*
1341     * Fire off any clone jobs (run directives)
1342     */
1343    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1344    if (!jcr->cloned && jcr->job->run_cmds) {
1345       char *runcmd;
1346       JOB *job = jcr->job;
1347       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1348       UAContext *ua = new_ua_context(jcr);
1349       ua->batch = true;
1350       foreach_alist(runcmd, job->run_cmds) {
1351          cmd = edit_job_codes(jcr, cmd, runcmd, "", job_code_callback_clones);
1352          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1353          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1354          parse_ua_args(ua);                 /* parse command */
1355          int stat = run_cmd(ua, ua->cmd);
1356          if (stat == 0) {
1357             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job: \"%s\".\n"),
1358                  ua->cmd);
1359          } else {
1360             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1361          }
1362       }
1363       free_ua_context(ua);
1364       free_pool_memory(cmd);
1365    }
1366 }
1367
1368 /*
1369  * Given: a JobId in jcr->previous_jr.JobId,
1370  *  this subroutine writes a bsr file to restore that job.
1371  * Returns: -1 on error
1372  *           number of files if OK
1373  */
1374 int create_restore_bootstrap_file(JCR *jcr)
1375 {
1376    RESTORE_CTX rx;
1377    UAContext *ua;
1378    int files;
1379
1380    memset(&rx, 0, sizeof(rx));
1381    rx.bsr = new_bsr();
1382    rx.JobIds = (char *)"";                       
1383    rx.bsr->JobId = jcr->previous_jr.JobId;
1384    ua = new_ua_context(jcr);
1385    if (!complete_bsr(ua, rx.bsr)) {
1386       files = -1;
1387       goto bail_out;
1388    }
1389    rx.bsr->fi = new_findex();
1390    rx.bsr->fi->findex = 1;
1391    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1392    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1393    if (jcr->ExpectedFiles == 0) {
1394       files = 0;
1395       goto bail_out;
1396    }
1397    free_ua_context(ua);
1398    free_bsr(rx.bsr);
1399    jcr->needs_sd = true;
1400    return jcr->ExpectedFiles;
1401
1402 bail_out:
1403    free_ua_context(ua);
1404    free_bsr(rx.bsr);
1405    return files;
1406 }
1407
1408 /* TODO: redirect command ouput to job log */
1409 bool run_console_command(JCR *jcr, const char *cmd)
1410 {
1411    UAContext *ua;
1412    bool ok;
1413    JCR *ljcr = new_control_jcr("-RunScript-", JT_CONSOLE);
1414    ua = new_ua_context(ljcr);
1415    /* run from runscript and check if commands are autorized */
1416    ua->runscript = true;
1417    Mmsg(ua->cmd, "%s", cmd);
1418    Dmsg1(100, "Console command: %s\n", ua->cmd);
1419    parse_ua_args(ua);
1420    ok= do_a_command(ua);
1421    free_ua_context(ua);
1422    free_jcr(ljcr);
1423    return ok;
1424 }