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