3 * Bacula Director Job processing routines
5 * Kern Sibbald, October MM
10 Copyright (C) 2000-2006 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
27 /* Forward referenced subroutines */
28 static void *job_thread(void *arg);
29 static void job_monitor_watchdog(watchdog_t *self);
30 static void job_monitor_destructor(watchdog_t *self);
31 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr);
32 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr);
34 /* Imported subroutines */
35 extern void term_scheduler();
36 extern void term_ua_server();
38 /* Imported variables */
42 void init_job_server(int max_workers)
47 if ((stat = jobq_init(&job_queue, max_workers, job_thread)) != 0) {
49 Emsg1(M_ABORT, 0, _("Could not init job queue: ERR=%s\n"), be.strerror(stat));
52 wd->callback = job_monitor_watchdog;
53 wd->destructor = job_monitor_destructor;
56 wd->data = new_control_jcr("*JobMonitor*", JT_SYSTEM);
57 register_watchdog(wd);
60 void term_job_server()
62 jobq_destroy(&job_queue); /* ignore any errors */
66 * Run a job -- typically called by the scheduler, but may also
67 * be called by the UA (Console program).
69 * Returns: 0 on failure
73 JobId_t run_job(JCR *jcr)
77 /* Queue the job to be run */
78 if ((stat = jobq_add(&job_queue, jcr)) != 0) {
80 Jmsg(jcr, M_FATAL, 0, _("Could not add job queue: ERR=%s\n"), be.strerror(stat));
88 bool setup_job(JCR *jcr)
93 sm_check(__FILE__, __LINE__, true);
94 init_msg(jcr, jcr->messages);
96 /* Initialize termination condition variable */
97 if ((errstat = pthread_cond_init(&jcr->term_wait, NULL)) != 0) {
99 Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.strerror(errstat));
102 jcr->term_wait_inited = true;
104 create_unique_job_name(jcr, jcr->job->hdr.name);
105 set_jcr_job_status(jcr, JS_Created);
111 Dmsg0(50, "Open database\n");
112 jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user,
113 jcr->catalog->db_password, jcr->catalog->db_address,
114 jcr->catalog->db_port, jcr->catalog->db_socket,
115 jcr->catalog->mult_db_connections);
116 if (!jcr->db || !db_open_database(jcr, jcr->db)) {
117 Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
118 jcr->catalog->db_name);
120 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
124 Dmsg0(50, "DB opened\n");
127 jcr->fname = get_pool_memory(PM_FNAME);
129 if (!jcr->pool_source) {
130 jcr->pool_source = get_pool_memory(PM_MESSAGE);
131 pm_strcpy(jcr->pool_source, _("unknown source"));
133 if (!jcr->storage_source) {
134 jcr->storage_source = get_pool_memory(PM_MESSAGE);
135 pm_strcpy(jcr->storage_source, _("unknown source"));
141 init_jcr_job_record(jcr);
142 if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
143 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
146 jcr->JobId = jcr->jr.JobId;
147 Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
148 jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
150 generate_daemon_event(jcr, "JobStart");
152 if (!get_or_create_client_record(jcr)) {
156 if (job_canceled(jcr)) {
160 Dmsg0(200, "Add jrc to work queue\n");
169 * This is the engine called by jobq.c:jobq_add() when we were pulled
170 * from the work queue.
171 * At this point, we are running in our own thread and all
172 * necessary resources are allocated -- see jobq.c
174 static void *job_thread(void *arg)
176 JCR *jcr = (JCR *)arg;
178 jcr->my_thread_id = pthread_self();
179 pthread_detach(jcr->my_thread_id);
180 sm_check(__FILE__, __LINE__, true);
182 Dmsg0(200, "=====Start Job=========\n");
183 jcr->start_time = time(NULL); /* set the real start time */
184 jcr->jr.StartTime = jcr->start_time;
186 if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
187 (utime_t)(jcr->start_time - jcr->sched_time)) {
188 Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
189 set_jcr_job_status(jcr, JS_Canceled);
192 /* TODO : check if it is used somewhere */
193 if (jcr->job->RunScripts == NULL)
195 Dmsg0(200, "Warning, job->RunScripts is empty\n");
196 jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
200 * Note, we continue, even if the job is canceled above. This
201 * will permit proper setting of the job start record and
202 * the error (cancel) will be picked up below.
205 generate_job_event(jcr, "JobInit");
206 set_jcr_job_status(jcr, JS_Running); /* this will be set only if no error */
210 * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
211 * this allows us to setup a proper job start record for restarting
212 * in case of later errors.
214 switch (jcr->JobType) {
216 if (!do_backup_init(jcr)) {
217 backup_cleanup(jcr, JS_ErrorTerminated);
221 if (!do_verify_init(jcr)) {
222 verify_cleanup(jcr, JS_ErrorTerminated);
226 if (!do_restore_init(jcr)) {
227 restore_cleanup(jcr, JS_ErrorTerminated);
231 if (!do_admin_init(jcr)) {
232 admin_cleanup(jcr, JS_ErrorTerminated);
236 if (!do_migration_init(jcr)) {
237 migration_cleanup(jcr, JS_ErrorTerminated);
241 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
242 set_jcr_job_status(jcr, JS_ErrorTerminated);
246 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
247 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
250 if (job_canceled(jcr)) {
251 update_job_end_record(jcr);
253 /* Run any script BeforeJob on dird */
254 run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
257 * We re-update the job start record so that the start
258 * time is set after the run before job. This avoids
259 * that any files created by the run before job will
260 * be saved twice. They will be backed up in the current
261 * job, but not in the next one unless they are changed.
262 * Without this, they will be backed up in this job and
263 * in the next job run because in that case, their date
264 * is after the start of this run.
266 jcr->start_time = time(NULL);
267 jcr->jr.StartTime = jcr->start_time;
268 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
269 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
271 generate_job_event(jcr, "JobRun");
273 switch (jcr->JobType) {
275 if (do_backup(jcr)) {
278 backup_cleanup(jcr, JS_ErrorTerminated);
282 if (do_verify(jcr)) {
285 verify_cleanup(jcr, JS_ErrorTerminated);
289 if (do_restore(jcr)) {
292 restore_cleanup(jcr, JS_ErrorTerminated);
299 admin_cleanup(jcr, JS_ErrorTerminated);
305 if (do_migration(jcr)) {
308 migration_cleanup(jcr, JS_ErrorTerminated);
312 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
316 run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
318 /* Send off any queued messages */
319 if (jcr->msg_queue->size() > 0) {
320 dequeue_messages(jcr);
324 generate_daemon_event(jcr, "JobEnd");
325 Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
326 sm_check(__FILE__, __LINE__, true);
332 * Cancel a job -- typically called by the UA (Console program), but may also
333 * be called by the job watchdog.
335 * Returns: true if cancel appears to be successful
336 * false on failure. Message sent to ua->jcr.
338 bool cancel_job(UAContext *ua, JCR *jcr)
342 set_jcr_job_status(jcr, JS_Canceled);
344 switch (jcr->JobStatus) {
347 case JS_WaitClientRes:
348 case JS_WaitStoreRes:
349 case JS_WaitPriority:
351 case JS_WaitStartTime:
352 bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"),
353 jcr->JobId, jcr->Job);
354 jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
358 /* Cancel File daemon */
359 if (jcr->file_bsock) {
360 ua->jcr->client = jcr->client;
361 if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
362 bsendmsg(ua, _("Failed to connect to File daemon.\n"));
365 Dmsg0(200, "Connected to file daemon\n");
366 fd = ua->jcr->file_bsock;
367 bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
368 while (bnet_recv(fd) >= 0) {
369 bsendmsg(ua, "%s", fd->msg);
371 bnet_sig(fd, BNET_TERMINATE);
373 ua->jcr->file_bsock = NULL;
376 /* Cancel Storage daemon */
377 if (jcr->store_bsock) {
378 if (!ua->jcr->storage) {
379 copy_storage(ua->jcr, jcr->storage, _("Job resource"));
381 set_storage(ua->jcr, jcr->store);
383 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
384 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
387 Dmsg0(200, "Connected to storage daemon\n");
388 sd = ua->jcr->store_bsock;
389 bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
390 while (bnet_recv(sd) >= 0) {
391 bsendmsg(ua, "%s", sd->msg);
393 bnet_sig(sd, BNET_TERMINATE);
395 ua->jcr->store_bsock = NULL;
403 static void job_monitor_destructor(watchdog_t *self)
405 JCR *control_jcr = (JCR *)self->data;
407 free_jcr(control_jcr);
410 static void job_monitor_watchdog(watchdog_t *self)
412 JCR *control_jcr, *jcr;
414 control_jcr = (JCR *)self->data;
416 Dmsg1(800, "job_monitor_watchdog %p called\n", self);
421 if (jcr->JobId == 0) {
422 Dmsg2(800, "Skipping JCR %p (%s) with JobId 0\n",
427 /* check MaxWaitTime */
428 cancel = job_check_maxwaittime(control_jcr, jcr);
430 /* check MaxRunTime */
431 cancel |= job_check_maxruntime(control_jcr, jcr);
434 Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n",
435 jcr, jcr->JobId, jcr->Job);
437 UAContext *ua = new_ua_context(jcr);
438 ua->jcr = control_jcr;
442 Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
445 /* Keep reference counts correct */
451 * Check if the maxwaittime has expired and it is possible
454 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
457 bool ok_to_cancel = false;
460 if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
461 job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
464 if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
465 (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
467 } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
468 (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
470 } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
471 (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
473 } else if (job->MaxWaitTime != 0 &&
474 (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
480 Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, "
482 jcr->JobId, jcr->Job, job->MaxWaitTime);
483 switch (jcr->JobStatus) {
488 case JS_WaitStoreRes:
489 case JS_WaitClientRes:
491 case JS_WaitPriority:
493 case JS_WaitStartTime:
495 Dmsg0(200, "JCR blocked in #1\n");
498 Dmsg0(800, "JCR running, checking SD status\n");
499 switch (jcr->SDJobStatus) {
504 Dmsg0(800, "JCR blocked in #2\n");
507 Dmsg0(800, "JCR not blocked in #2\n");
512 case JS_ErrorTerminated:
515 Dmsg0(800, "JCR already dead in #3\n");
518 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
521 Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n",
522 cancel ? "" : "do not ", jcr, jcr->job);
528 * Check if maxruntime has expired and if the job can be
531 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
535 if (jcr->job->MaxRunTime == 0) {
538 if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
539 Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
540 jcr, jcr->Job, jcr->job->MaxRunTime);
544 switch (jcr->JobStatus) {
550 case JS_WaitStoreRes:
551 case JS_WaitClientRes:
553 case JS_WaitPriority:
555 case JS_WaitStartTime:
560 case JS_ErrorTerminated:
566 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
570 Dmsg3(200, "MaxRunTime result: %scancel JCR %p (%s)\n",
571 cancel ? "" : "do not ", jcr, jcr->job);
577 * Get or create a Pool record with the given name.
578 * Returns: 0 on error
581 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
585 memset(&pr, 0, sizeof(pr));
586 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
588 while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
589 /* Try to create the pool */
590 if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
591 Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
592 db_strerror(jcr->db));
595 Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
601 void apply_pool_overrides(JCR *jcr)
603 if (jcr->run_pool_override) {
604 pm_strcpy(jcr->pool_source, _("Run Pool override"));
607 * Apply any level related Pool selections
609 switch (jcr->JobLevel) {
611 if (jcr->full_pool) {
612 jcr->pool = jcr->full_pool;
613 if (jcr->run_full_pool_override) {
614 pm_strcpy(jcr->pool_source, _("Run FullPool override"));
616 pm_strcpy(jcr->pool_source, _("Job FullPool override"));
622 jcr->pool = jcr->inc_pool;
623 if (jcr->run_inc_pool_override) {
624 pm_strcpy(jcr->pool_source, _("Run IncPool override"));
626 pm_strcpy(jcr->pool_source, _("Job IncPool override"));
631 if (jcr->diff_pool) {
632 jcr->pool = jcr->diff_pool;
633 if (jcr->run_diff_pool_override) {
634 pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
636 pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
645 * Get or create a Client record for this Job
647 bool get_or_create_client_record(JCR *jcr)
651 memset(&cr, 0, sizeof(cr));
652 bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
653 cr.AutoPrune = jcr->client->AutoPrune;
654 cr.FileRetention = jcr->client->FileRetention;
655 cr.JobRetention = jcr->client->JobRetention;
656 if (!jcr->client_name) {
657 jcr->client_name = get_pool_memory(PM_NAME);
659 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
660 if (!db_create_client_record(jcr, jcr->db, &cr)) {
661 Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
662 db_strerror(jcr->db));
665 jcr->jr.ClientId = cr.ClientId;
667 if (!jcr->client_uname) {
668 jcr->client_uname = get_pool_memory(PM_NAME);
670 pm_strcpy(jcr->client_uname, cr.Uname);
672 Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
677 bool get_or_create_fileset_record(JCR *jcr)
681 * Get or Create FileSet record
683 memset(&fsr, 0, sizeof(FILESET_DBR));
684 bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
685 if (jcr->fileset->have_MD5) {
686 struct MD5Context md5c;
687 unsigned char digest[MD5HashSize];
688 memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
689 MD5Final(digest, &md5c);
690 bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, true);
691 bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
693 Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
695 if (!jcr->fileset->ignore_fs_changes ||
696 !db_get_fileset_record(jcr, jcr->db, &fsr)) {
697 if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
698 Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
699 fsr.FileSet, db_strerror(jcr->db));
703 jcr->jr.FileSetId = fsr.FileSetId;
704 bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
705 Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
710 void init_jcr_job_record(JCR *jcr)
712 jcr->jr.SchedTime = jcr->sched_time;
713 jcr->jr.StartTime = jcr->start_time;
714 jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
715 jcr->jr.JobType = jcr->JobType;
716 jcr->jr.JobLevel = jcr->JobLevel;
717 jcr->jr.JobStatus = jcr->JobStatus;
718 jcr->jr.JobId = jcr->JobId;
719 bstrncpy(jcr->jr.Name, jcr->job->hdr.name, sizeof(jcr->jr.Name));
720 bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
724 * Write status and such in DB
726 void update_job_end_record(JCR *jcr)
728 jcr->jr.EndTime = time(NULL);
729 jcr->end_time = jcr->jr.EndTime;
730 jcr->jr.JobId = jcr->JobId;
731 jcr->jr.JobStatus = jcr->JobStatus;
732 jcr->jr.JobFiles = jcr->JobFiles;
733 jcr->jr.JobBytes = jcr->JobBytes;
734 jcr->jr.VolSessionId = jcr->VolSessionId;
735 jcr->jr.VolSessionTime = jcr->VolSessionTime;
736 if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
737 Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
738 db_strerror(jcr->db));
743 * Takes base_name and appends (unique) current
744 * date and time to form unique job name.
746 * Returns: unique job name in jcr->Job
747 * date/time in jcr->start_time
749 void create_unique_job_name(JCR *jcr, const char *base_name)
751 /* Job start mutex */
752 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
753 static time_t last_start_time = 0;
756 char dt[MAX_TIME_LENGTH];
757 char name[MAX_NAME_LENGTH];
760 /* Guarantee unique start time -- maximum one per second, and
761 * thus unique Job Name
763 P(mutex); /* lock creation of jobs */
765 while (now == last_start_time) {
766 bmicrosleep(0, 500000);
769 last_start_time = now;
770 V(mutex); /* allow creation of jobs */
771 jcr->start_time = now;
772 /* Form Unique JobName */
773 (void)localtime_r(&now, &tm);
774 /* Use only characters that are permitted in Windows filenames */
775 strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
776 bstrncpy(name, base_name, sizeof(name));
777 name[sizeof(name)-22] = 0; /* truncate if too long */
778 bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
779 /* Convert spaces into underscores */
780 for (p=jcr->Job; *p; p++) {
787 /* Called directly from job rescheduling */
788 void dird_free_jcr_pointers(JCR *jcr)
790 if (jcr->sd_auth_key) {
791 free(jcr->sd_auth_key);
792 jcr->sd_auth_key = NULL;
798 if (jcr->file_bsock) {
799 Dmsg0(200, "Close File bsock\n");
800 bnet_close(jcr->file_bsock);
801 jcr->file_bsock = NULL;
803 if (jcr->store_bsock) {
804 Dmsg0(200, "Close Store bsock\n");
805 bnet_close(jcr->store_bsock);
806 jcr->store_bsock = NULL;
809 Dmsg0(200, "Free JCR fname\n");
810 free_pool_memory(jcr->fname);
813 if (jcr->pool_source) {
814 free_pool_memory(jcr->pool_source);
815 jcr->pool_source = NULL;
817 if (jcr->storage_source) {
818 free_pool_memory(jcr->storage_source);
819 jcr->storage_source = NULL;
822 Dmsg0(200, "Free JCR stime\n");
823 free_pool_memory(jcr->stime);
826 if (jcr->RestoreBootstrap) {
827 free(jcr->RestoreBootstrap);
828 jcr->RestoreBootstrap = NULL;
830 if (jcr->client_uname) {
831 free_pool_memory(jcr->client_uname);
832 jcr->client_uname = NULL;
835 free_pool_memory(jcr->attr);
845 * Free the Job Control Record if no one is still using it.
846 * Called from main free_jcr() routine in src/lib/jcr.c so
847 * that we can do our Director specific cleanup of the jcr.
849 void dird_free_jcr(JCR *jcr)
851 Dmsg0(200, "Start dird free_jcr\n");
853 dird_free_jcr_pointers(jcr);
854 if (jcr->term_wait_inited) {
855 pthread_cond_destroy(&jcr->term_wait);
856 jcr->term_wait_inited = false;
859 /* Delete lists setup to hold storage pointers */
863 jcr->job_end_push.destroy();
864 Dmsg0(200, "End dird free_jcr\n");
868 * Set some defaults in the JCR necessary to
869 * run. These items are pulled from the job
870 * definition as defaults, but can be overridden
871 * later either by the Run record in the Schedule resource,
872 * or by the Console program.
874 void set_jcr_defaults(JCR *jcr, JOB *job)
877 jcr->JobType = job->JobType;
878 switch (jcr->JobType) {
881 jcr->JobLevel = L_NONE;
884 jcr->JobLevel = job->JobLevel;
888 jcr->fname = get_pool_memory(PM_FNAME);
890 if (!jcr->pool_source) {
891 jcr->pool_source = get_pool_memory(PM_MESSAGE);
892 pm_strcpy(jcr->pool_source, _("unknown source"));
894 if (!jcr->storage_source) {
895 jcr->storage_source = get_pool_memory(PM_MESSAGE);
896 pm_strcpy(jcr->storage_source, _("unknown source"));
898 jcr->JobPriority = job->Priority;
899 /* Copy storage definitions -- deleted in dir_free_jcr above */
900 copy_storage(jcr, job->storage, _("Job resource"));
901 jcr->client = job->client;
902 if (!jcr->client_name) {
903 jcr->client_name = get_pool_memory(PM_NAME);
905 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
906 pm_strcpy(jcr->pool_source, _("Job resource"));
907 jcr->pool = job->pool;
908 jcr->full_pool = job->full_pool;
909 jcr->inc_pool = job->inc_pool;
910 jcr->diff_pool = job->diff_pool;
911 jcr->catalog = job->client->catalog;
912 jcr->fileset = job->fileset;
913 jcr->messages = job->messages;
914 jcr->spool_data = job->spool_data;
915 jcr->write_part_after_job = job->write_part_after_job;
916 if (jcr->RestoreBootstrap) {
917 free(jcr->RestoreBootstrap);
918 jcr->RestoreBootstrap = NULL;
920 /* This can be overridden by Console program */
921 if (job->RestoreBootstrap) {
922 jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
924 /* This can be overridden by Console program */
925 jcr->verify_job = job->verify_job;
926 /* If no default level given, set one */
927 if (jcr->JobLevel == 0) {
928 switch (jcr->JobType) {
930 jcr->JobLevel = L_VERIFY_CATALOG;
933 jcr->JobLevel = L_INCREMENTAL;
937 jcr->JobLevel = L_NONE;
947 * Copy the storage definitions from an alist to the JCR
949 void copy_storage(JCR *jcr, alist *storage, const char *where)
956 jcr->storage = New(alist(10, not_owned_by_alist));
957 foreach_alist(st, storage) {
958 jcr->storage->append(st);
960 pm_strcpy(jcr->storage_source, where);
963 jcr->store = (STORE *)jcr->storage->first();
968 /* Set storage override */
969 void set_storage(JCR *jcr, STORE *store)
974 foreach_alist(storage, jcr->storage) {
975 if (store == storage) {
979 /* Store not in list, so add it */
980 jcr->storage->prepend(store);
983 void create_clones(JCR *jcr)
986 * Fire off any clone jobs (run directives)
988 Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
989 if (!jcr->cloned && jcr->job->run_cmds) {
992 POOLMEM *cmd = get_pool_memory(PM_FNAME);
993 UAContext *ua = new_ua_context(jcr);
995 foreach_alist(runcmd, job->run_cmds) {
996 cmd = edit_job_codes(jcr, cmd, runcmd, "");
997 Mmsg(ua->cmd, "run %s cloned=yes", cmd);
998 Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
999 parse_ua_args(ua); /* parse command */
1000 int stat = run_cmd(ua, ua->cmd);
1002 Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1004 Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1007 free_ua_context(ua);
1008 free_pool_memory(cmd);
1012 bool create_restore_bootstrap_file(JCR *jcr)
1016 memset(&rx, 0, sizeof(rx));
1019 rx.bsr->JobId = jcr->previous_jr.JobId;
1020 ua = new_ua_context(jcr);
1021 complete_bsr(ua, rx.bsr);
1022 rx.bsr->fi = new_findex();
1023 rx.bsr->fi->findex = 1;
1024 rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1025 jcr->ExpectedFiles = write_bsr_file(ua, rx);
1026 if (jcr->ExpectedFiles == 0) {
1027 free_ua_context(ua);
1031 free_ua_context(ua);
1033 jcr->needs_sd = true;