]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
Fix bscan segfault with new comment field
[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->fname) {
143       jcr->fname = get_pool_memory(PM_FNAME);
144    }
145    if (!jcr->pool_source) {
146       jcr->pool_source = get_pool_memory(PM_MESSAGE);
147       pm_strcpy(jcr->pool_source, _("unknown source"));
148    }
149
150    if (jcr->JobReads()) {
151       if (!jcr->rpool_source) {
152          jcr->rpool_source = get_pool_memory(PM_MESSAGE);
153          pm_strcpy(jcr->rpool_source, _("unknown source"));
154       }
155    }
156
157    /*
158     * Create Job record
159     */
160    init_jcr_job_record(jcr);
161    if (!get_or_create_client_record(jcr)) {
162       goto bail_out;
163    }
164
165    if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
166       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
167       goto bail_out;
168    }
169    jcr->JobId = jcr->jr.JobId;
170    Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
171        jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
172
173    generate_daemon_event(jcr, "JobStart");
174    new_plugins(jcr);                  /* instantiate plugins for this jcr */
175    generate_plugin_event(jcr, bEventJobStart);
176
177    if (job_canceled(jcr)) {
178       goto bail_out;
179    }
180
181    if (jcr->JobReads() && !jcr->rstorage) {
182       if (jcr->job->storage) {
183          copy_rwstorage(jcr, jcr->job->storage, _("Job resource"));
184       } else {
185          copy_rwstorage(jcr, jcr->job->pool->storage, _("Pool resource"));
186       }
187    }
188    if (!jcr->JobReads()) {
189       free_rstorage(jcr);
190    }
191
192    /*
193     * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
194     *  this allows us to setup a proper job start record for restarting
195     *  in case of later errors.
196     */
197    switch (jcr->getJobType()) {
198    case JT_BACKUP:
199       if (!do_backup_init(jcr)) {
200          backup_cleanup(jcr, JS_ErrorTerminated);
201          goto bail_out;
202       }
203       break;
204    case JT_VERIFY:
205       if (!do_verify_init(jcr)) {
206          verify_cleanup(jcr, JS_ErrorTerminated);
207          goto bail_out;
208       }
209       break;
210    case JT_RESTORE:
211       if (!do_restore_init(jcr)) {
212          restore_cleanup(jcr, JS_ErrorTerminated);
213          goto bail_out;
214       }
215       break;
216    case JT_ADMIN:
217       if (!do_admin_init(jcr)) {
218          admin_cleanup(jcr, JS_ErrorTerminated);
219          goto bail_out;
220       }
221       break;
222    case JT_COPY:
223    case JT_MIGRATE:
224       if (!do_migration_init(jcr)) { 
225          migration_cleanup(jcr, JS_ErrorTerminated);
226          goto bail_out;
227       }
228       break;
229    default:
230       Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->getJobType());
231       jcr->setJobStatus(JS_ErrorTerminated);
232       goto bail_out;
233    }
234
235    generate_job_event(jcr, "JobInit");
236    generate_plugin_event(jcr, bEventJobInit);
237    Dsm_check(1);
238    return true;
239
240 bail_out:
241    return false;
242 }
243
244 void update_job_end(JCR *jcr, int TermCode)
245 {
246    dequeue_messages(jcr);             /* display any queued messages */
247    jcr->setJobStatus(TermCode);
248    update_job_end_record(jcr);
249 }
250
251 /*
252  * This is the engine called by jobq.c:jobq_add() when we were pulled
253  *  from the work queue.
254  *  At this point, we are running in our own thread and all
255  *    necessary resources are allocated -- see jobq.c
256  */
257 static void *job_thread(void *arg)
258 {
259    JCR *jcr = (JCR *)arg;
260
261    pthread_detach(pthread_self());
262    Dsm_check(1);
263
264    Dmsg0(200, "=====Start Job=========\n");
265    jcr->setJobStatus(JS_Running);   /* this will be set only if no error */
266    jcr->start_time = time(NULL);      /* set the real start time */
267    jcr->jr.StartTime = jcr->start_time;
268
269    if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
270        (utime_t)(jcr->start_time - jcr->sched_time)) {
271       jcr->setJobStatus(JS_Canceled);
272       Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
273    }
274
275    if (job_check_maxschedruntime(jcr)) {
276       jcr->setJobStatus(JS_Canceled);
277       Jmsg(jcr, M_FATAL, 0, _("Job canceled because max sched run time exceeded.\n"));
278    }
279
280    /* TODO : check if it is used somewhere */
281    if (jcr->job->RunScripts == NULL) {
282       Dmsg0(200, "Warning, job->RunScripts is empty\n");
283       jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
284    }
285
286    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
287       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
288    }
289
290    /* Run any script BeforeJob on dird */
291    run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
292
293    /*
294     * We re-update the job start record so that the start
295     *  time is set after the run before job.  This avoids
296     *  that any files created by the run before job will
297     *  be saved twice.  They will be backed up in the current
298     *  job, but not in the next one unless they are changed.
299     *  Without this, they will be backed up in this job and
300     *  in the next job run because in that case, their date
301     *   is after the start of this run.
302     */
303    jcr->start_time = time(NULL);
304    jcr->jr.StartTime = jcr->start_time;
305    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
306       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
307    }
308    generate_job_event(jcr, "JobRun");
309    generate_plugin_event(jcr, bEventJobRun);
310
311    switch (jcr->getJobType()) {
312    case JT_BACKUP:
313       if (!job_canceled(jcr) && do_backup(jcr)) {
314          do_autoprune(jcr);
315       } else {
316          backup_cleanup(jcr, JS_ErrorTerminated);
317       }
318       break;
319    case JT_VERIFY:
320       if (!job_canceled(jcr) && do_verify(jcr)) {
321          do_autoprune(jcr);
322       } else {
323          verify_cleanup(jcr, JS_ErrorTerminated);
324       }
325       break;
326    case JT_RESTORE:
327       if (!job_canceled(jcr) && do_restore(jcr)) {
328          do_autoprune(jcr);
329       } else {
330          restore_cleanup(jcr, JS_ErrorTerminated);
331       }
332       break;
333    case JT_ADMIN:
334       if (!job_canceled(jcr) && do_admin(jcr)) {
335          do_autoprune(jcr);
336       } else {
337          admin_cleanup(jcr, JS_ErrorTerminated);
338       }
339       break;
340    case JT_COPY:
341    case JT_MIGRATE:
342       if (!job_canceled(jcr) && do_migration(jcr)) {
343          do_autoprune(jcr);
344       } else {
345          migration_cleanup(jcr, JS_ErrorTerminated);
346       }
347       break;
348    default:
349       Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->getJobType());
350       break;
351    }
352
353    run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
354
355    /* Send off any queued messages */
356    if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
357       dequeue_messages(jcr);
358    }
359
360    generate_daemon_event(jcr, "JobEnd");
361    generate_plugin_event(jcr, bEventJobEnd);
362    Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
363    sm_check(__FILE__, __LINE__, true);
364    return NULL;
365 }
366
367
368 /*
369  * Cancel a job -- typically called by the UA (Console program), but may also
370  *              be called by the job watchdog.
371  *
372  *  Returns: true  if cancel appears to be successful
373  *           false on failure. Message sent to ua->jcr.
374  */
375 bool cancel_job(UAContext *ua, JCR *jcr)
376 {
377    BSOCK *sd, *fd;
378    char ed1[50];
379    int32_t old_status = jcr->JobStatus;
380
381    jcr->setJobStatus(JS_Canceled);
382
383    switch (old_status) {
384    case JS_Created:
385    case JS_WaitJobRes:
386    case JS_WaitClientRes:
387    case JS_WaitStoreRes:
388    case JS_WaitPriority:
389    case JS_WaitMaxJobs:
390    case JS_WaitStartTime:
391       ua->info_msg(_("JobId %s, Job %s marked to be canceled.\n"),
392               edit_uint64(jcr->JobId, ed1), jcr->Job);
393       jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
394       break;
395
396    default:
397       /* Cancel File daemon */
398       if (jcr->file_bsock) {
399          ua->jcr->client = jcr->client;
400          if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
401             ua->error_msg(_("Failed to connect to File daemon.\n"));
402             return 0;
403          }
404          Dmsg0(200, "Connected to file daemon\n");
405          fd = ua->jcr->file_bsock;
406          fd->fsend("cancel Job=%s\n", jcr->Job);
407          while (fd->recv() >= 0) {
408             ua->send_msg("%s", fd->msg);
409          }
410          fd->signal(BNET_TERMINATE);
411          fd->close();
412          ua->jcr->file_bsock = NULL;
413          jcr->file_bsock->set_terminated();
414          if (jcr->my_thread_id) {
415             pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
416             Dmsg1(800, "Send kill to jid=%d\n", jcr->JobId);
417          }
418       }
419
420       /* Cancel Storage daemon */
421       if (jcr->store_bsock) {
422          if (!ua->jcr->wstorage) {
423             if (jcr->rstorage) {
424                copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
425             } else {
426                copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
427             }
428          } else {
429             USTORE store;
430             if (jcr->rstorage) {
431                store.store = jcr->rstore;
432             } else {
433                store.store = jcr->wstore;
434             }
435             set_wstorage(ua->jcr, &store);
436          }
437
438          if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
439             ua->error_msg(_("Failed to connect to Storage daemon.\n"));
440             return false;
441          }
442          Dmsg0(200, "Connected to storage daemon\n");
443          sd = ua->jcr->store_bsock;
444          sd->fsend("cancel Job=%s\n", jcr->Job);
445          while (sd->recv() >= 0) {
446             ua->send_msg("%s", sd->msg);
447          }
448          sd->signal(BNET_TERMINATE);
449          sd->close();
450          ua->jcr->store_bsock = NULL;
451          jcr->store_bsock->set_timed_out();
452          jcr->store_bsock->set_terminated();
453          if (jcr->SD_msg_chan) {
454             Dmsg2(400, "kill jobid=%d use=%d\n", (int)jcr->JobId, jcr->use_count());
455             pthread_kill(jcr->SD_msg_chan, TIMEOUT_SIGNAL);
456          }
457          if (jcr->my_thread_id) {
458             pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
459          }
460       }
461       break;
462    }
463
464    return true;
465 }
466
467 void cancel_storage_daemon_job(JCR *jcr)
468 {
469    if (jcr->sd_canceled) { 
470       return;                   /* cancel only once */
471    }
472
473    UAContext *ua = new_ua_context(jcr);
474    JCR *control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);
475    BSOCK *sd;
476
477    ua->jcr = control_jcr;
478    if (jcr->store_bsock) {
479       if (!ua->jcr->wstorage) {
480          if (jcr->rstorage) {
481             copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
482          } else {
483             copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
484          }
485       } else {
486          USTORE store;
487          if (jcr->rstorage) {
488             store.store = jcr->rstore;
489          } else {
490             store.store = jcr->wstore;
491          }
492          set_wstorage(ua->jcr, &store);
493       }
494
495       if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
496          goto bail_out;
497       }
498       Dmsg0(200, "Connected to storage daemon\n");
499       sd = ua->jcr->store_bsock;
500       sd->fsend("cancel Job=%s\n", jcr->Job);
501       while (sd->recv() >= 0) {
502       }
503       sd->signal(BNET_TERMINATE);
504       sd->close();
505       ua->jcr->store_bsock = NULL;
506       jcr->sd_canceled = true;
507       jcr->store_bsock->set_timed_out();
508       jcr->store_bsock->set_terminated();
509       if (jcr->SD_msg_chan) {
510          Dmsg2(400, "kill jobid=%d use=%d\n", (int)jcr->JobId, jcr->use_count());
511          pthread_kill(jcr->SD_msg_chan, TIMEOUT_SIGNAL);
512       }
513       if (jcr->my_thread_id) {
514          pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
515       }
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 }