]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
Extract restore object and send to FD first cut
[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->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
1026    bfree_and_null(jcr->sd_auth_key);
1027    bfree_and_null(jcr->where);
1028    bfree_and_null(jcr->RestoreBootstrap);
1029    bfree_and_null(jcr->ar);
1030
1031    free_and_null_pool_memory(jcr->JobIds);
1032    free_and_null_pool_memory(jcr->client_uname);
1033    free_and_null_pool_memory(jcr->attr);
1034    free_and_null_pool_memory(jcr->fname);
1035 }
1036
1037 /*
1038  * Free the Job Control Record if no one is still using it.
1039  *  Called from main free_jcr() routine in src/lib/jcr.c so
1040  *  that we can do our Director specific cleanup of the jcr.
1041  */
1042 void dird_free_jcr(JCR *jcr)
1043 {
1044    Dmsg0(200, "Start dird free_jcr\n");
1045
1046    dird_free_jcr_pointers(jcr);
1047    if (jcr->term_wait_inited) {
1048       pthread_cond_destroy(&jcr->term_wait);
1049       jcr->term_wait_inited = false;
1050    }
1051    if (jcr->db_batch) {
1052       db_close_database(jcr, jcr->db_batch);
1053       jcr->db_batch = NULL;
1054       jcr->batch_started = false;
1055    }
1056    if (jcr->db) {
1057       db_close_database(jcr, jcr->db);
1058       jcr->db = NULL;
1059    }
1060
1061    free_and_null_pool_memory(jcr->stime);
1062    free_and_null_pool_memory(jcr->fname);
1063    free_and_null_pool_memory(jcr->pool_source);
1064    free_and_null_pool_memory(jcr->catalog_source);
1065    free_and_null_pool_memory(jcr->rpool_source);
1066    free_and_null_pool_memory(jcr->wstore_source);
1067    free_and_null_pool_memory(jcr->rstore_source);
1068
1069    /* Delete lists setup to hold storage pointers */
1070    free_rwstorage(jcr);
1071
1072    jcr->job_end_push.destroy();
1073
1074    if (jcr->JobId != 0)
1075       write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
1076
1077    free_plugins(jcr);                 /* release instantiated plugins */
1078
1079    Dmsg0(200, "End dird free_jcr\n");
1080 }
1081
1082 /* 
1083  * The Job storage definition must be either in the Job record
1084  *  or in the Pool record.  The Pool record overrides the Job 
1085  *  record.
1086  */
1087 void get_job_storage(USTORE *store, JOB *job, RUN *run) 
1088 {
1089    if (run && run->pool && run->pool->storage) {
1090       store->store = (STORE *)run->pool->storage->first();
1091       pm_strcpy(store->store_source, _("Run pool override"));
1092       return;
1093    }
1094    if (run && run->storage) {
1095       store->store = run->storage;
1096       pm_strcpy(store->store_source, _("Run storage override"));
1097       return;
1098    }
1099    if (job->pool->storage) {
1100       store->store = (STORE *)job->pool->storage->first();
1101       pm_strcpy(store->store_source, _("Pool resource"));
1102    } else {
1103       store->store = (STORE *)job->storage->first();
1104       pm_strcpy(store->store_source, _("Job resource"));
1105    }
1106 }
1107
1108 /*
1109  * Set some defaults in the JCR necessary to
1110  * run. These items are pulled from the job
1111  * definition as defaults, but can be overridden
1112  * later either by the Run record in the Schedule resource,
1113  * or by the Console program.
1114  */
1115 void set_jcr_defaults(JCR *jcr, JOB *job)
1116 {
1117    jcr->job = job;
1118    jcr->set_JobType(job->JobType);
1119    jcr->JobStatus = JS_Created;
1120
1121    switch (jcr->getJobType()) {
1122    case JT_ADMIN:
1123       jcr->set_JobLevel(L_NONE);
1124       break;
1125    default:
1126       jcr->set_JobLevel(job->JobLevel);
1127       break;
1128    }
1129
1130    if (!jcr->fname) {
1131       jcr->fname = get_pool_memory(PM_FNAME);
1132    }
1133    if (!jcr->pool_source) {
1134       jcr->pool_source = get_pool_memory(PM_MESSAGE);
1135       pm_strcpy(jcr->pool_source, _("unknown source"));
1136    }
1137    if (!jcr->catalog_source) {
1138       jcr->catalog_source = get_pool_memory(PM_MESSAGE);
1139       pm_strcpy(jcr->catalog_source, _("unknown source"));
1140    }
1141
1142    jcr->JobPriority = job->Priority;
1143    /* Copy storage definitions -- deleted in dir_free_jcr above */
1144    if (job->storage) {
1145       copy_rwstorage(jcr, job->storage, _("Job resource"));
1146    } else {
1147       copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
1148    }
1149    jcr->client = job->client;
1150    if (!jcr->client_name) {
1151       jcr->client_name = get_pool_memory(PM_NAME);
1152    }
1153    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
1154    pm_strcpy(jcr->pool_source, _("Job resource"));
1155    jcr->pool = job->pool;
1156    jcr->full_pool = job->full_pool;
1157    jcr->inc_pool = job->inc_pool;
1158    jcr->diff_pool = job->diff_pool;
1159    if (job->pool->catalog) {
1160       jcr->catalog = job->pool->catalog;
1161       pm_strcpy(jcr->catalog_source, _("Pool resource"));
1162    } else {
1163       jcr->catalog = job->client->catalog;
1164       pm_strcpy(jcr->catalog_source, _("Client resource"));
1165    }
1166    jcr->fileset = job->fileset;
1167    jcr->messages = job->messages;
1168    jcr->spool_data = job->spool_data;
1169    jcr->spool_size = job->spool_size;
1170    jcr->write_part_after_job = job->write_part_after_job;
1171    jcr->accurate = job->accurate;
1172    if (jcr->RestoreBootstrap) {
1173       free(jcr->RestoreBootstrap);
1174       jcr->RestoreBootstrap = NULL;
1175    }
1176    /* This can be overridden by Console program */
1177    if (job->RestoreBootstrap) {
1178       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1179    }
1180    /* This can be overridden by Console program */
1181    jcr->verify_job = job->verify_job;
1182    /* If no default level given, set one */
1183    if (jcr->getJobLevel() == 0) {
1184       switch (jcr->getJobType()) {
1185       case JT_VERIFY:
1186          jcr->set_JobLevel(L_VERIFY_CATALOG);
1187          break;
1188       case JT_BACKUP:
1189          jcr->set_JobLevel(L_INCREMENTAL);
1190          break;
1191       case JT_RESTORE:
1192       case JT_ADMIN:
1193          jcr->set_JobLevel(L_NONE);
1194          break;
1195       default:
1196          jcr->set_JobLevel(L_FULL);
1197          break;
1198       }
1199    }
1200 }
1201
1202 /* 
1203  * Copy the storage definitions from an alist to the JCR
1204  */
1205 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1206 {
1207    if (jcr->JobReads()) {
1208       copy_rstorage(jcr, storage, where);
1209    }
1210    copy_wstorage(jcr, storage, where);
1211 }
1212
1213
1214 /* Set storage override.  Releases any previous storage definition */
1215 void set_rwstorage(JCR *jcr, USTORE *store)
1216 {
1217    if (!store) {
1218       Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1219       return;
1220    }
1221    if (jcr->JobReads()) {
1222       set_rstorage(jcr, store);
1223    }
1224    set_wstorage(jcr, store);
1225 }
1226
1227 void free_rwstorage(JCR *jcr)
1228 {
1229    free_rstorage(jcr);
1230    free_wstorage(jcr);
1231 }
1232
1233 /* 
1234  * Copy the storage definitions from an alist to the JCR
1235  */
1236 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1237 {
1238    if (storage) {
1239       STORE *st;
1240       if (jcr->rstorage) {
1241          delete jcr->rstorage;
1242       }
1243       jcr->rstorage = New(alist(10, not_owned_by_alist));
1244       foreach_alist(st, storage) {
1245          jcr->rstorage->append(st);
1246       }
1247       if (!jcr->rstore_source) {
1248          jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1249       }
1250       pm_strcpy(jcr->rstore_source, where);
1251       if (jcr->rstorage) {
1252          jcr->rstore = (STORE *)jcr->rstorage->first();
1253       }
1254    }
1255 }
1256
1257
1258 /* Set storage override.  Remove all previous storage */
1259 void set_rstorage(JCR *jcr, USTORE *store)
1260 {
1261    STORE *storage;
1262
1263    if (!store->store) {
1264       return;
1265    }
1266    if (jcr->rstorage) {
1267       free_rstorage(jcr);
1268    }
1269    if (!jcr->rstorage) {
1270       jcr->rstorage = New(alist(10, not_owned_by_alist));
1271    }
1272    jcr->rstore = store->store;
1273    if (!jcr->rstore_source) {
1274       jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1275    }
1276    pm_strcpy(jcr->rstore_source, store->store_source);
1277    foreach_alist(storage, jcr->rstorage) {
1278       if (store->store == storage) {
1279          return;
1280       }
1281    }
1282    /* Store not in list, so add it */
1283    jcr->rstorage->prepend(store->store);
1284 }
1285
1286 void free_rstorage(JCR *jcr)
1287 {
1288    if (jcr->rstorage) {
1289       delete jcr->rstorage;
1290       jcr->rstorage = NULL;
1291    }
1292    jcr->rstore = NULL;
1293 }
1294
1295 /* 
1296  * Copy the storage definitions from an alist to the JCR
1297  */
1298 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1299 {
1300    if (storage) {
1301       STORE *st;
1302       if (jcr->wstorage) {
1303          delete jcr->wstorage;
1304       }
1305       jcr->wstorage = New(alist(10, not_owned_by_alist));
1306       foreach_alist(st, storage) {
1307          Dmsg1(100, "wstorage=%s\n", st->name());
1308          jcr->wstorage->append(st);
1309       }
1310       if (!jcr->wstore_source) {
1311          jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1312       }
1313       pm_strcpy(jcr->wstore_source, where);
1314       if (jcr->wstorage) {
1315          jcr->wstore = (STORE *)jcr->wstorage->first();
1316          Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1317       }
1318    }
1319 }
1320
1321
1322 /* Set storage override. Remove all previous storage */
1323 void set_wstorage(JCR *jcr, USTORE *store)
1324 {
1325    STORE *storage;
1326
1327    if (!store->store) {
1328       return;
1329    }
1330    if (jcr->wstorage) {
1331       free_wstorage(jcr);
1332    }
1333    if (!jcr->wstorage) {
1334       jcr->wstorage = New(alist(10, not_owned_by_alist));
1335    }
1336    jcr->wstore = store->store;
1337    if (!jcr->wstore_source) {
1338       jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1339    }
1340    pm_strcpy(jcr->wstore_source, store->store_source);
1341    Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1342    foreach_alist(storage, jcr->wstorage) {
1343       if (store->store == storage) {
1344          return;
1345       }
1346    }
1347    /* Store not in list, so add it */
1348    jcr->wstorage->prepend(store->store);
1349 }
1350
1351 void free_wstorage(JCR *jcr)
1352 {
1353    if (jcr->wstorage) {
1354       delete jcr->wstorage;
1355       jcr->wstorage = NULL;
1356    }
1357    jcr->wstore = NULL;
1358 }
1359
1360 char *job_code_callback_clones(JCR *jcr, const char* param) 
1361 {
1362    if (param[0] == 'p') {
1363       return jcr->pool->name();
1364    }
1365    return NULL;
1366 }
1367
1368 void create_clones(JCR *jcr)
1369 {
1370    /*
1371     * Fire off any clone jobs (run directives)
1372     */
1373    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1374    if (!jcr->cloned && jcr->job->run_cmds) {
1375       char *runcmd;
1376       JOB *job = jcr->job;
1377       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1378       UAContext *ua = new_ua_context(jcr);
1379       ua->batch = true;
1380       foreach_alist(runcmd, job->run_cmds) {
1381          cmd = edit_job_codes(jcr, cmd, runcmd, "", job_code_callback_clones);
1382          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1383          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1384          parse_ua_args(ua);                 /* parse command */
1385          int stat = run_cmd(ua, ua->cmd);
1386          if (stat == 0) {
1387             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job: \"%s\".\n"),
1388                  ua->cmd);
1389          } else {
1390             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1391          }
1392       }
1393       free_ua_context(ua);
1394       free_pool_memory(cmd);
1395    }
1396 }
1397
1398 /*
1399  * Given: a JobId in jcr->previous_jr.JobId,
1400  *  this subroutine writes a bsr file to restore that job.
1401  * Returns: -1 on error
1402  *           number of files if OK
1403  */
1404 int create_restore_bootstrap_file(JCR *jcr)
1405 {
1406    RESTORE_CTX rx;
1407    UAContext *ua;
1408    int files;
1409
1410    memset(&rx, 0, sizeof(rx));
1411    rx.bsr = new_bsr();
1412    rx.JobIds = (char *)"";                       
1413    rx.bsr->JobId = jcr->previous_jr.JobId;
1414    ua = new_ua_context(jcr);
1415    if (!complete_bsr(ua, rx.bsr)) {
1416       files = -1;
1417       goto bail_out;
1418    }
1419    rx.bsr->fi = new_findex();
1420    rx.bsr->fi->findex = 1;
1421    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1422    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1423    if (jcr->ExpectedFiles == 0) {
1424       files = 0;
1425       goto bail_out;
1426    }
1427    free_ua_context(ua);
1428    free_bsr(rx.bsr);
1429    jcr->needs_sd = true;
1430    return jcr->ExpectedFiles;
1431
1432 bail_out:
1433    free_ua_context(ua);
1434    free_bsr(rx.bsr);
1435    return files;
1436 }
1437
1438 /* TODO: redirect command ouput to job log */
1439 bool run_console_command(JCR *jcr, const char *cmd)
1440 {
1441    UAContext *ua;
1442    bool ok;
1443    JCR *ljcr = new_control_jcr("-RunScript-", JT_CONSOLE);
1444    ua = new_ua_context(ljcr);
1445    /* run from runscript and check if commands are autorized */
1446    ua->runscript = true;
1447    Mmsg(ua->cmd, "%s", cmd);
1448    Dmsg1(100, "Console command: %s\n", ua->cmd);
1449    parse_ua_args(ua);
1450    ok= do_a_command(ua);
1451    free_ua_context(ua);
1452    free_jcr(ljcr);
1453    return ok;
1454 }