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