]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
Fix #1467 about ActionOnPurge with Devices having space
[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 */
682
683    if (job->AllowDuplicateJobs) {
684       return true;
685    }
686    if (!job->AllowHigherDuplicates) {
687       foreach_jcr(djcr) {
688          if (jcr == djcr || djcr->JobId == 0) {
689             continue;                   /* do not cancel this job or consoles */
690          }
691          if (strcmp(job->name(), djcr->job->name()) == 0) {
692             bool cancel_queued = false;
693             if (job->DuplicateJobProximity > 0) {
694                utime_t now = (utime_t)time(NULL);
695                if ((now - djcr->start_time) > job->DuplicateJobProximity) {
696                   continue;               /* not really a duplicate */
697                }
698             }
699             /* Cancel */
700             /* If CancelQueuedDuplicates is set do so only if job is queued */
701             if (job->CancelQueuedDuplicates) {
702                 switch (djcr->JobStatus) {
703                 case JS_Created:
704                 case JS_WaitJobRes:
705                 case JS_WaitClientRes:
706                 case JS_WaitStoreRes:
707                 case JS_WaitPriority:
708                 case JS_WaitMaxJobs:
709                 case JS_WaitStartTime:
710                    cancel_queued = true;
711                    break;
712                 default:
713                    break;
714                 }
715             }
716             if (cancel_queued || job->CancelRunningDuplicates) {
717                UAContext *ua = new_ua_context(djcr);
718                Jmsg(jcr, M_INFO, 0, _("Cancelling duplicate JobId=%d.\n"), djcr->JobId);
719                ua->jcr = djcr;
720                cancel_job(ua, djcr);
721                free_ua_context(ua);
722                Dmsg2(800, "Have cancelled JCR %p JobId=%d\n", djcr, djcr->JobId);
723             } else {
724                /* Zap current job */
725                Jmsg(jcr, M_FATAL, 0, _("JobId %d already running. Duplicate job not allowed.\n"),
726                   djcr->JobId);
727             }
728             break;                 /* did our work, get out */
729          }
730       }
731       endeach_jcr(djcr);
732    }
733    return true;   
734 }
735
736 void apply_pool_overrides(JCR *jcr)
737 {
738    bool pool_override = false;
739
740    if (jcr->run_pool_override) {
741       pm_strcpy(jcr->pool_source, _("Run pool override"));
742    }
743    /*
744     * Apply any level related Pool selections
745     */
746    switch (jcr->getJobLevel()) {
747    case L_FULL:
748       if (jcr->full_pool) {
749          jcr->pool = jcr->full_pool;
750          pool_override = true;
751          if (jcr->run_full_pool_override) {
752             pm_strcpy(jcr->pool_source, _("Run FullPool override"));
753          } else {
754             pm_strcpy(jcr->pool_source, _("Job FullPool override"));
755          }
756       }
757       break;
758    case L_INCREMENTAL:
759       if (jcr->inc_pool) {
760          jcr->pool = jcr->inc_pool;
761          pool_override = true;
762          if (jcr->run_inc_pool_override) {
763             pm_strcpy(jcr->pool_source, _("Run IncPool override"));
764          } else {
765             pm_strcpy(jcr->pool_source, _("Job IncPool override"));
766          }
767       }
768       break;
769    case L_DIFFERENTIAL:
770       if (jcr->diff_pool) {
771          jcr->pool = jcr->diff_pool;
772          pool_override = true;
773          if (jcr->run_diff_pool_override) {
774             pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
775          } else {
776             pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
777          }
778       }
779       break;
780    }
781    /* Update catalog if pool overridden */
782    if (pool_override && jcr->pool->catalog) {
783       jcr->catalog = jcr->pool->catalog;
784       pm_strcpy(jcr->catalog_source, _("Pool resource"));
785    }
786 }
787
788
789 /*
790  * Get or create a Client record for this Job
791  */
792 bool get_or_create_client_record(JCR *jcr)
793 {
794    CLIENT_DBR cr;
795
796    memset(&cr, 0, sizeof(cr));
797    bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
798    cr.AutoPrune = jcr->client->AutoPrune;
799    cr.FileRetention = jcr->client->FileRetention;
800    cr.JobRetention = jcr->client->JobRetention;
801    if (!jcr->client_name) {
802       jcr->client_name = get_pool_memory(PM_NAME);
803    }
804    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
805    if (!db_create_client_record(jcr, jcr->db, &cr)) {
806       Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
807          db_strerror(jcr->db));
808       return false;
809    }
810    jcr->jr.ClientId = cr.ClientId;
811    if (cr.Uname[0]) {
812       if (!jcr->client_uname) {
813          jcr->client_uname = get_pool_memory(PM_NAME);
814       }
815       pm_strcpy(jcr->client_uname, cr.Uname);
816    }
817    Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
818       jcr->jr.ClientId);
819    return true;
820 }
821
822 bool get_or_create_fileset_record(JCR *jcr)
823 {
824    FILESET_DBR fsr;
825    /*
826     * Get or Create FileSet record
827     */
828    memset(&fsr, 0, sizeof(FILESET_DBR));
829    bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
830    if (jcr->fileset->have_MD5) {
831       struct MD5Context md5c;
832       unsigned char digest[MD5HashSize];
833       memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
834       MD5Final(digest, &md5c);
835       /*
836        * Keep the flag (last arg) set to false otherwise old FileSets will
837        * get new MD5 sums and the user will get Full backups on everything
838        */
839       bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
840       bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
841    } else {
842       Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
843    }
844    if (!jcr->fileset->ignore_fs_changes ||
845        !db_get_fileset_record(jcr, jcr->db, &fsr)) {
846       if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
847          Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
848             fsr.FileSet, db_strerror(jcr->db));
849          return false;
850       }
851    }
852    jcr->jr.FileSetId = fsr.FileSetId;
853    bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
854    Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
855       jcr->jr.FileSetId);
856    return true;
857 }
858
859 void init_jcr_job_record(JCR *jcr)
860 {
861    jcr->jr.SchedTime = jcr->sched_time;
862    jcr->jr.StartTime = jcr->start_time;
863    jcr->jr.EndTime = 0;               /* perhaps rescheduled, clear it */
864    jcr->jr.JobType = jcr->getJobType();
865    jcr->jr.JobLevel = jcr->getJobLevel();
866    jcr->jr.JobStatus = jcr->JobStatus;
867    jcr->jr.JobId = jcr->JobId;
868    bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
869    bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
870 }
871
872 /*
873  * Write status and such in DB
874  */
875 void update_job_end_record(JCR *jcr)
876 {
877    jcr->jr.EndTime = time(NULL);
878    jcr->end_time = jcr->jr.EndTime;
879    jcr->jr.JobId = jcr->JobId;
880    jcr->jr.JobStatus = jcr->JobStatus;
881    jcr->jr.JobFiles = jcr->JobFiles;
882    jcr->jr.JobBytes = jcr->JobBytes;
883    jcr->jr.ReadBytes = jcr->ReadBytes;
884    jcr->jr.VolSessionId = jcr->VolSessionId;
885    jcr->jr.VolSessionTime = jcr->VolSessionTime;
886    jcr->jr.JobErrors = jcr->JobErrors;
887    jcr->jr.HasBase = jcr->HasBase;
888    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
889       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
890          db_strerror(jcr->db));
891    }
892 }
893
894 /*
895  * Takes base_name and appends (unique) current
896  *   date and time to form unique job name.
897  *
898  *  Note, the seconds are actually a sequence number. This
899  *   permits us to start a maximum fo 59 unique jobs a second, which
900  *   should be sufficient.
901  *
902  *  Returns: unique job name in jcr->Job
903  *    date/time in jcr->start_time
904  */
905 void create_unique_job_name(JCR *jcr, const char *base_name)
906 {
907    /* Job start mutex */
908    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
909    static time_t last_start_time = 0;
910    static int seq = 0;
911    time_t now = time(NULL);
912    struct tm tm;
913    char dt[MAX_TIME_LENGTH];
914    char name[MAX_NAME_LENGTH];
915    char *p;
916    int len;
917
918    /* Guarantee unique start time -- maximum one per second, and
919     * thus unique Job Name
920     */
921    P(mutex);                          /* lock creation of jobs */
922    seq++;
923    if (seq > 59) {                    /* wrap as if it is seconds */
924       seq = 0;
925       while (now == last_start_time) {
926          bmicrosleep(0, 500000);
927          now = time(NULL);
928       }
929    }
930    last_start_time = now;
931    V(mutex);                          /* allow creation of jobs */
932    jcr->start_time = now;
933    /* Form Unique JobName */
934    (void)localtime_r(&now, &tm);
935    /* Use only characters that are permitted in Windows filenames */
936    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
937    len = strlen(dt) + 5;   /* dt + .%02d EOS */
938    bstrncpy(name, base_name, sizeof(name));
939    name[sizeof(name)-len] = 0;          /* truncate if too long */
940    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s_%02d", name, dt, seq); /* add date & time */
941    /* Convert spaces into underscores */
942    for (p=jcr->Job; *p; p++) {
943       if (*p == ' ') {
944          *p = '_';
945       }
946    }
947    Dmsg2(100, "JobId=%u created Job=%s\n", jcr->JobId, jcr->Job);
948 }
949
950 /* Called directly from job rescheduling */
951 void dird_free_jcr_pointers(JCR *jcr)
952 {
953    if (jcr->sd_auth_key) {
954       free(jcr->sd_auth_key);
955       jcr->sd_auth_key = NULL;
956    }
957    if (jcr->where) {
958       free(jcr->where);
959       jcr->where = NULL;
960    }
961    if (jcr->file_bsock) {
962       Dmsg0(200, "Close File bsock\n");
963       bnet_close(jcr->file_bsock);
964       jcr->file_bsock = NULL;
965    }
966    if (jcr->store_bsock) {
967       Dmsg0(200, "Close Store bsock\n");
968       bnet_close(jcr->store_bsock);
969       jcr->store_bsock = NULL;
970    }
971    if (jcr->comment) {
972       free_pool_memory(jcr->comment);
973       jcr->comment = NULL;
974    }
975    if (jcr->fname) {
976       Dmsg0(200, "Free JCR fname\n");
977       free_pool_memory(jcr->fname);
978       jcr->fname = NULL;
979    }
980    if (jcr->RestoreBootstrap) {
981       free(jcr->RestoreBootstrap);
982       jcr->RestoreBootstrap = NULL;
983    }
984    if (jcr->client_uname) {
985       free_pool_memory(jcr->client_uname);
986       jcr->client_uname = NULL;
987    }
988    if (jcr->attr) {
989       free_pool_memory(jcr->attr);
990       jcr->attr = NULL;
991    }
992    if (jcr->ar) {
993       free(jcr->ar);
994       jcr->ar = NULL;
995    }
996 }
997
998 /*
999  * Free the Job Control Record if no one is still using it.
1000  *  Called from main free_jcr() routine in src/lib/jcr.c so
1001  *  that we can do our Director specific cleanup of the jcr.
1002  */
1003 void dird_free_jcr(JCR *jcr)
1004 {
1005    Dmsg0(200, "Start dird free_jcr\n");
1006
1007    dird_free_jcr_pointers(jcr);
1008    if (jcr->term_wait_inited) {
1009       pthread_cond_destroy(&jcr->term_wait);
1010       jcr->term_wait_inited = false;
1011    }
1012    if (jcr->db_batch) {
1013       db_close_database(jcr, jcr->db_batch);
1014       jcr->db_batch = NULL;
1015       jcr->batch_started = false;
1016    }
1017    if (jcr->db) {
1018       db_close_database(jcr, jcr->db);
1019       jcr->db = NULL;
1020    }
1021    if (jcr->stime) {
1022       Dmsg0(200, "Free JCR stime\n");
1023       free_pool_memory(jcr->stime);
1024       jcr->stime = NULL;
1025    }
1026    if (jcr->fname) {
1027       Dmsg0(200, "Free JCR fname\n");
1028       free_pool_memory(jcr->fname);
1029       jcr->fname = NULL;
1030    }
1031    if (jcr->pool_source) {
1032       free_pool_memory(jcr->pool_source);
1033       jcr->pool_source = NULL;
1034    }
1035    if (jcr->catalog_source) {
1036       free_pool_memory(jcr->catalog_source);
1037       jcr->catalog_source = NULL;
1038    }
1039    if (jcr->rpool_source) {
1040       free_pool_memory(jcr->rpool_source);
1041       jcr->rpool_source = NULL;
1042    }
1043    if (jcr->wstore_source) {
1044       free_pool_memory(jcr->wstore_source);
1045       jcr->wstore_source = NULL;
1046    }
1047    if (jcr->rstore_source) {
1048       free_pool_memory(jcr->rstore_source);
1049       jcr->rstore_source = NULL;
1050    }
1051
1052    /* Delete lists setup to hold storage pointers */
1053    free_rwstorage(jcr);
1054
1055    jcr->job_end_push.destroy();
1056
1057    if (jcr->JobId != 0)
1058       write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
1059
1060    free_plugins(jcr);                 /* release instantiated plugins */
1061
1062    Dmsg0(200, "End dird free_jcr\n");
1063 }
1064
1065 /* 
1066  * The Job storage definition must be either in the Job record
1067  *  or in the Pool record.  The Pool record overrides the Job 
1068  *  record.
1069  */
1070 void get_job_storage(USTORE *store, JOB *job, RUN *run) 
1071 {
1072    if (run && run->pool && run->pool->storage) {
1073       store->store = (STORE *)run->pool->storage->first();
1074       pm_strcpy(store->store_source, _("Run pool override"));
1075       return;
1076    }
1077    if (run && run->storage) {
1078       store->store = run->storage;
1079       pm_strcpy(store->store_source, _("Run storage override"));
1080       return;
1081    }
1082    if (job->pool->storage) {
1083       store->store = (STORE *)job->pool->storage->first();
1084       pm_strcpy(store->store_source, _("Pool resource"));
1085    } else {
1086       store->store = (STORE *)job->storage->first();
1087       pm_strcpy(store->store_source, _("Job resource"));
1088    }
1089 }
1090
1091 /*
1092  * Set some defaults in the JCR necessary to
1093  * run. These items are pulled from the job
1094  * definition as defaults, but can be overridden
1095  * later either by the Run record in the Schedule resource,
1096  * or by the Console program.
1097  */
1098 void set_jcr_defaults(JCR *jcr, JOB *job)
1099 {
1100    jcr->job = job;
1101    jcr->set_JobType(job->JobType);
1102    jcr->JobStatus = JS_Created;
1103
1104    switch (jcr->getJobType()) {
1105    case JT_ADMIN:
1106       jcr->set_JobLevel(L_NONE);
1107       break;
1108    default:
1109       jcr->set_JobLevel(job->JobLevel);
1110       break;
1111    }
1112
1113    if (!jcr->fname) {
1114       jcr->fname = get_pool_memory(PM_FNAME);
1115    }
1116    if (!jcr->pool_source) {
1117       jcr->pool_source = get_pool_memory(PM_MESSAGE);
1118       pm_strcpy(jcr->pool_source, _("unknown source"));
1119    }
1120    if (!jcr->catalog_source) {
1121       jcr->catalog_source = get_pool_memory(PM_MESSAGE);
1122       pm_strcpy(jcr->catalog_source, _("unknown source"));
1123    }
1124
1125    jcr->JobPriority = job->Priority;
1126    /* Copy storage definitions -- deleted in dir_free_jcr above */
1127    if (job->storage) {
1128       copy_rwstorage(jcr, job->storage, _("Job resource"));
1129    } else {
1130       copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
1131    }
1132    jcr->client = job->client;
1133    if (!jcr->client_name) {
1134       jcr->client_name = get_pool_memory(PM_NAME);
1135    }
1136    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
1137    pm_strcpy(jcr->pool_source, _("Job resource"));
1138    jcr->pool = job->pool;
1139    jcr->full_pool = job->full_pool;
1140    jcr->inc_pool = job->inc_pool;
1141    jcr->diff_pool = job->diff_pool;
1142    if (job->pool->catalog) {
1143       jcr->catalog = job->pool->catalog;
1144       pm_strcpy(jcr->catalog_source, _("Pool resource"));
1145    } else {
1146       jcr->catalog = job->client->catalog;
1147       pm_strcpy(jcr->catalog_source, _("Client resource"));
1148    }
1149    jcr->fileset = job->fileset;
1150    jcr->messages = job->messages;
1151    jcr->spool_data = job->spool_data;
1152    jcr->spool_size = job->spool_size;
1153    jcr->write_part_after_job = job->write_part_after_job;
1154    jcr->accurate = job->accurate;
1155    if (jcr->RestoreBootstrap) {
1156       free(jcr->RestoreBootstrap);
1157       jcr->RestoreBootstrap = NULL;
1158    }
1159    /* This can be overridden by Console program */
1160    if (job->RestoreBootstrap) {
1161       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1162    }
1163    /* This can be overridden by Console program */
1164    jcr->verify_job = job->verify_job;
1165    /* If no default level given, set one */
1166    if (jcr->getJobLevel() == 0) {
1167       switch (jcr->getJobType()) {
1168       case JT_VERIFY:
1169          jcr->set_JobLevel(L_VERIFY_CATALOG);
1170          break;
1171       case JT_BACKUP:
1172          jcr->set_JobLevel(L_INCREMENTAL);
1173          break;
1174       case JT_RESTORE:
1175       case JT_ADMIN:
1176          jcr->set_JobLevel(L_NONE);
1177          break;
1178       default:
1179          jcr->set_JobLevel(L_FULL);
1180          break;
1181       }
1182    }
1183 }
1184
1185 /* 
1186  * Copy the storage definitions from an alist to the JCR
1187  */
1188 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1189 {
1190    if (jcr->JobReads()) {
1191       copy_rstorage(jcr, storage, where);
1192    }
1193    copy_wstorage(jcr, storage, where);
1194 }
1195
1196
1197 /* Set storage override.  Releases any previous storage definition */
1198 void set_rwstorage(JCR *jcr, USTORE *store)
1199 {
1200    if (!store) {
1201       Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1202       return;
1203    }
1204    if (jcr->JobReads()) {
1205       set_rstorage(jcr, store);
1206    }
1207    set_wstorage(jcr, store);
1208 }
1209
1210 void free_rwstorage(JCR *jcr)
1211 {
1212    free_rstorage(jcr);
1213    free_wstorage(jcr);
1214 }
1215
1216 /* 
1217  * Copy the storage definitions from an alist to the JCR
1218  */
1219 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1220 {
1221    if (storage) {
1222       STORE *st;
1223       if (jcr->rstorage) {
1224          delete jcr->rstorage;
1225       }
1226       jcr->rstorage = New(alist(10, not_owned_by_alist));
1227       foreach_alist(st, storage) {
1228          jcr->rstorage->append(st);
1229       }
1230       if (!jcr->rstore_source) {
1231          jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1232       }
1233       pm_strcpy(jcr->rstore_source, where);
1234       if (jcr->rstorage) {
1235          jcr->rstore = (STORE *)jcr->rstorage->first();
1236       }
1237    }
1238 }
1239
1240
1241 /* Set storage override.  Remove all previous storage */
1242 void set_rstorage(JCR *jcr, USTORE *store)
1243 {
1244    STORE *storage;
1245
1246    if (!store->store) {
1247       return;
1248    }
1249    if (jcr->rstorage) {
1250       free_rstorage(jcr);
1251    }
1252    if (!jcr->rstorage) {
1253       jcr->rstorage = New(alist(10, not_owned_by_alist));
1254    }
1255    jcr->rstore = store->store;
1256    if (!jcr->rstore_source) {
1257       jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1258    }
1259    pm_strcpy(jcr->rstore_source, store->store_source);
1260    foreach_alist(storage, jcr->rstorage) {
1261       if (store->store == storage) {
1262          return;
1263       }
1264    }
1265    /* Store not in list, so add it */
1266    jcr->rstorage->prepend(store->store);
1267 }
1268
1269 void free_rstorage(JCR *jcr)
1270 {
1271    if (jcr->rstorage) {
1272       delete jcr->rstorage;
1273       jcr->rstorage = NULL;
1274    }
1275    jcr->rstore = NULL;
1276 }
1277
1278 /* 
1279  * Copy the storage definitions from an alist to the JCR
1280  */
1281 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1282 {
1283    if (storage) {
1284       STORE *st;
1285       if (jcr->wstorage) {
1286          delete jcr->wstorage;
1287       }
1288       jcr->wstorage = New(alist(10, not_owned_by_alist));
1289       foreach_alist(st, storage) {
1290          Dmsg1(100, "wstorage=%s\n", st->name());
1291          jcr->wstorage->append(st);
1292       }
1293       if (!jcr->wstore_source) {
1294          jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1295       }
1296       pm_strcpy(jcr->wstore_source, where);
1297       if (jcr->wstorage) {
1298          jcr->wstore = (STORE *)jcr->wstorage->first();
1299          Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1300       }
1301    }
1302 }
1303
1304
1305 /* Set storage override. Remove all previous storage */
1306 void set_wstorage(JCR *jcr, USTORE *store)
1307 {
1308    STORE *storage;
1309
1310    if (!store->store) {
1311       return;
1312    }
1313    if (jcr->wstorage) {
1314       free_wstorage(jcr);
1315    }
1316    if (!jcr->wstorage) {
1317       jcr->wstorage = New(alist(10, not_owned_by_alist));
1318    }
1319    jcr->wstore = store->store;
1320    if (!jcr->wstore_source) {
1321       jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1322    }
1323    pm_strcpy(jcr->wstore_source, store->store_source);
1324    Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1325    foreach_alist(storage, jcr->wstorage) {
1326       if (store->store == storage) {
1327          return;
1328       }
1329    }
1330    /* Store not in list, so add it */
1331    jcr->wstorage->prepend(store->store);
1332 }
1333
1334 void free_wstorage(JCR *jcr)
1335 {
1336    if (jcr->wstorage) {
1337       delete jcr->wstorage;
1338       jcr->wstorage = NULL;
1339    }
1340    jcr->wstore = NULL;
1341 }
1342
1343 char *job_code_callback_clones(JCR *jcr, const char* param) 
1344 {
1345    if (param[0] == 'p') {
1346       return jcr->pool->name();
1347    }
1348    return NULL;
1349 }
1350
1351 void create_clones(JCR *jcr)
1352 {
1353    /*
1354     * Fire off any clone jobs (run directives)
1355     */
1356    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1357    if (!jcr->cloned && jcr->job->run_cmds) {
1358       char *runcmd;
1359       JOB *job = jcr->job;
1360       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1361       UAContext *ua = new_ua_context(jcr);
1362       ua->batch = true;
1363       foreach_alist(runcmd, job->run_cmds) {
1364          cmd = edit_job_codes(jcr, cmd, runcmd, "", job_code_callback_clones);
1365          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1366          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1367          parse_ua_args(ua);                 /* parse command */
1368          int stat = run_cmd(ua, ua->cmd);
1369          if (stat == 0) {
1370             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job: \"%s\".\n"),
1371                  ua->cmd);
1372          } else {
1373             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1374          }
1375       }
1376       free_ua_context(ua);
1377       free_pool_memory(cmd);
1378    }
1379 }
1380
1381 /*
1382  * Given: a JobId in jcr->previous_jr.JobId,
1383  *  this subroutine writes a bsr file to restore that job.
1384  * Returns: -1 on error
1385  *           number of files if OK
1386  */
1387 int create_restore_bootstrap_file(JCR *jcr)
1388 {
1389    RESTORE_CTX rx;
1390    UAContext *ua;
1391    int files;
1392
1393    memset(&rx, 0, sizeof(rx));
1394    rx.bsr = new_bsr();
1395    rx.JobIds = (char *)"";                       
1396    rx.bsr->JobId = jcr->previous_jr.JobId;
1397    ua = new_ua_context(jcr);
1398    if (!complete_bsr(ua, rx.bsr)) {
1399       files = -1;
1400       goto bail_out;
1401    }
1402    rx.bsr->fi = new_findex();
1403    rx.bsr->fi->findex = 1;
1404    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1405    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1406    if (jcr->ExpectedFiles == 0) {
1407       files = 0;
1408       goto bail_out;
1409    }
1410    free_ua_context(ua);
1411    free_bsr(rx.bsr);
1412    jcr->needs_sd = true;
1413    return jcr->ExpectedFiles;
1414
1415 bail_out:
1416    free_ua_context(ua);
1417    free_bsr(rx.bsr);
1418    return files;
1419 }
1420
1421 /* TODO: redirect command ouput to job log */
1422 bool run_console_command(JCR *jcr, const char *cmd)
1423 {
1424    UAContext *ua;
1425    bool ok;
1426    JCR *ljcr = new_control_jcr("-RunScript-", JT_CONSOLE);
1427    ua = new_ua_context(ljcr);
1428    /* run from runscript and check if commands are autorized */
1429    ua->runscript = true;
1430    Mmsg(ua->cmd, "%s", cmd);
1431    Dmsg1(100, "Console command: %s\n", ua->cmd);
1432    parse_ua_args(ua);
1433    ok= do_a_command(ua);
1434    free_ua_context(ua);
1435    free_jcr(ljcr);
1436    return ok;
1437 }