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