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