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