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