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