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)) {
162 * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
163 * this allows us to setup a proper job start record for restarting
164 * in case of later errors.
166 switch (jcr->JobType) {
168 if (!do_backup_init(jcr)) {
169 backup_cleanup(jcr, JS_ErrorTerminated);
173 if (!do_verify_init(jcr)) {
174 verify_cleanup(jcr, JS_ErrorTerminated);
178 if (!do_restore_init(jcr)) {
179 restore_cleanup(jcr, JS_ErrorTerminated);
183 if (!do_admin_init(jcr)) {
184 admin_cleanup(jcr, JS_ErrorTerminated);
188 if (!do_migration_init(jcr)) {
189 migration_cleanup(jcr, JS_ErrorTerminated);
193 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
194 set_jcr_job_status(jcr, JS_ErrorTerminated);
198 generate_job_event(jcr, "JobInit");
200 Dmsg0(200, "Add jrc to work queue\n");
209 * This is the engine called by jobq.c:jobq_add() when we were pulled
210 * from the work queue.
211 * At this point, we are running in our own thread and all
212 * necessary resources are allocated -- see jobq.c
214 static void *job_thread(void *arg)
216 JCR *jcr = (JCR *)arg;
218 jcr->my_thread_id = pthread_self();
219 pthread_detach(jcr->my_thread_id);
220 sm_check(__FILE__, __LINE__, true);
222 Dmsg0(200, "=====Start Job=========\n");
223 set_jcr_job_status(jcr, JS_Running); /* this will be set only if no error */
224 jcr->start_time = time(NULL); /* set the real start time */
225 jcr->jr.StartTime = jcr->start_time;
227 if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
228 (utime_t)(jcr->start_time - jcr->sched_time)) {
229 Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
230 set_jcr_job_status(jcr, JS_Canceled);
233 /* TODO : check if it is used somewhere */
234 if (jcr->job->RunScripts == NULL) {
235 Dmsg0(200, "Warning, job->RunScripts is empty\n");
236 jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
239 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
240 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
243 if (job_canceled(jcr)) {
244 update_job_end_record(jcr);
246 /* Run any script BeforeJob on dird */
247 run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
250 * We re-update the job start record so that the start
251 * time is set after the run before job. This avoids
252 * that any files created by the run before job will
253 * be saved twice. They will be backed up in the current
254 * job, but not in the next one unless they are changed.
255 * Without this, they will be backed up in this job and
256 * in the next job run because in that case, their date
257 * is after the start of this run.
259 jcr->start_time = time(NULL);
260 jcr->jr.StartTime = jcr->start_time;
261 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
262 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
264 generate_job_event(jcr, "JobRun");
266 switch (jcr->JobType) {
268 if (do_backup(jcr)) {
271 backup_cleanup(jcr, JS_ErrorTerminated);
275 if (do_verify(jcr)) {
278 verify_cleanup(jcr, JS_ErrorTerminated);
282 if (do_restore(jcr)) {
285 restore_cleanup(jcr, JS_ErrorTerminated);
292 admin_cleanup(jcr, JS_ErrorTerminated);
298 if (do_migration(jcr)) {
301 migration_cleanup(jcr, JS_ErrorTerminated);
305 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
309 run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
311 /* Send off any queued messages */
312 if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
313 dequeue_messages(jcr);
317 generate_daemon_event(jcr, "JobEnd");
318 Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
319 sm_check(__FILE__, __LINE__, true);
325 * Cancel a job -- typically called by the UA (Console program), but may also
326 * be called by the job watchdog.
328 * Returns: true if cancel appears to be successful
329 * false on failure. Message sent to ua->jcr.
331 bool cancel_job(UAContext *ua, JCR *jcr)
335 set_jcr_job_status(jcr, JS_Canceled);
337 switch (jcr->JobStatus) {
340 case JS_WaitClientRes:
341 case JS_WaitStoreRes:
342 case JS_WaitPriority:
344 case JS_WaitStartTime:
345 bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"),
346 jcr->JobId, jcr->Job);
347 jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
351 /* Cancel File daemon */
352 if (jcr->file_bsock) {
353 ua->jcr->client = jcr->client;
354 if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
355 bsendmsg(ua, _("Failed to connect to File daemon.\n"));
358 Dmsg0(200, "Connected to file daemon\n");
359 fd = ua->jcr->file_bsock;
360 bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
361 while (bnet_recv(fd) >= 0) {
362 bsendmsg(ua, "%s", fd->msg);
364 bnet_sig(fd, BNET_TERMINATE);
366 ua->jcr->file_bsock = NULL;
369 /* Cancel Storage daemon */
370 if (jcr->store_bsock) {
371 if (!ua->jcr->wstorage) {
373 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
375 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
379 set_wstorage(ua->jcr, jcr->rstore);
381 set_wstorage(ua->jcr, jcr->wstore);
384 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
385 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
388 Dmsg0(200, "Connected to storage daemon\n");
389 sd = ua->jcr->store_bsock;
390 bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
391 while (bnet_recv(sd) >= 0) {
392 bsendmsg(ua, "%s", sd->msg);
394 bnet_sig(sd, BNET_TERMINATE);
396 ua->jcr->store_bsock = NULL;
404 static void job_monitor_destructor(watchdog_t *self)
406 JCR *control_jcr = (JCR *)self->data;
408 free_jcr(control_jcr);
411 static void job_monitor_watchdog(watchdog_t *self)
413 JCR *control_jcr, *jcr;
415 control_jcr = (JCR *)self->data;
417 Dmsg1(800, "job_monitor_watchdog %p called\n", self);
422 if (jcr->JobId == 0) {
423 Dmsg2(800, "Skipping JCR %p (%s) with JobId 0\n",
428 /* check MaxWaitTime */
429 cancel = job_check_maxwaittime(control_jcr, jcr);
431 /* check MaxRunTime */
432 cancel |= job_check_maxruntime(control_jcr, jcr);
435 Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n",
436 jcr, jcr->JobId, jcr->Job);
438 UAContext *ua = new_ua_context(jcr);
439 ua->jcr = control_jcr;
443 Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
446 /* Keep reference counts correct */
452 * Check if the maxwaittime has expired and it is possible
455 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
458 bool ok_to_cancel = false;
461 if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
462 job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
465 if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
466 (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
468 } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
469 (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
471 } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
472 (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
474 } else if (job->MaxWaitTime != 0 &&
475 (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
481 Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, "
483 jcr->JobId, jcr->Job, job->MaxWaitTime);
484 switch (jcr->JobStatus) {
489 case JS_WaitStoreRes:
490 case JS_WaitClientRes:
492 case JS_WaitPriority:
494 case JS_WaitStartTime:
496 Dmsg0(200, "JCR blocked in #1\n");
499 Dmsg0(800, "JCR running, checking SD status\n");
500 switch (jcr->SDJobStatus) {
505 Dmsg0(800, "JCR blocked in #2\n");
508 Dmsg0(800, "JCR not blocked in #2\n");
513 case JS_ErrorTerminated:
516 Dmsg0(800, "JCR already dead in #3\n");
519 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
522 Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n",
523 cancel ? "" : "do not ", jcr, jcr->job);
529 * Check if maxruntime has expired and if the job can be
532 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
536 if (jcr->job->MaxRunTime == 0) {
539 if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
540 Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
541 jcr, jcr->Job, jcr->job->MaxRunTime);
545 switch (jcr->JobStatus) {
551 case JS_WaitStoreRes:
552 case JS_WaitClientRes:
554 case JS_WaitPriority:
556 case JS_WaitStartTime:
561 case JS_ErrorTerminated:
567 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
571 Dmsg3(200, "MaxRunTime result: %scancel JCR %p (%s)\n",
572 cancel ? "" : "do not ", jcr, jcr->job);
578 * Get or create a Pool record with the given name.
579 * Returns: 0 on error
582 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
586 memset(&pr, 0, sizeof(pr));
587 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
589 while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
590 /* Try to create the pool */
591 if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
592 Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
593 db_strerror(jcr->db));
596 Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
602 void apply_pool_overrides(JCR *jcr)
604 if (jcr->run_pool_override) {
605 pm_strcpy(jcr->pool_source, _("Run Pool override"));
608 * Apply any level related Pool selections
610 switch (jcr->JobLevel) {
612 if (jcr->full_pool) {
613 jcr->pool = jcr->full_pool;
614 if (jcr->run_full_pool_override) {
615 pm_strcpy(jcr->pool_source, _("Run FullPool override"));
617 pm_strcpy(jcr->pool_source, _("Job FullPool override"));
623 jcr->pool = jcr->inc_pool;
624 if (jcr->run_inc_pool_override) {
625 pm_strcpy(jcr->pool_source, _("Run IncPool override"));
627 pm_strcpy(jcr->pool_source, _("Job IncPool override"));
632 if (jcr->diff_pool) {
633 jcr->pool = jcr->diff_pool;
634 if (jcr->run_diff_pool_override) {
635 pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
637 pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
646 * Get or create a Client record for this Job
648 bool get_or_create_client_record(JCR *jcr)
652 memset(&cr, 0, sizeof(cr));
653 bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
654 cr.AutoPrune = jcr->client->AutoPrune;
655 cr.FileRetention = jcr->client->FileRetention;
656 cr.JobRetention = jcr->client->JobRetention;
657 if (!jcr->client_name) {
658 jcr->client_name = get_pool_memory(PM_NAME);
660 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
661 if (!db_create_client_record(jcr, jcr->db, &cr)) {
662 Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
663 db_strerror(jcr->db));
666 jcr->jr.ClientId = cr.ClientId;
668 if (!jcr->client_uname) {
669 jcr->client_uname = get_pool_memory(PM_NAME);
671 pm_strcpy(jcr->client_uname, cr.Uname);
673 Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
678 bool get_or_create_fileset_record(JCR *jcr)
682 * Get or Create FileSet record
684 memset(&fsr, 0, sizeof(FILESET_DBR));
685 bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
686 if (jcr->fileset->have_MD5) {
687 struct MD5Context md5c;
688 unsigned char digest[MD5HashSize];
689 memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
690 MD5Final(digest, &md5c);
692 * Keep the flag (last arg) set to false otherwise old FileSets will
693 * get new MD5 sums and the user will get Full backups on everything
695 bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
696 bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
698 Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
700 if (!jcr->fileset->ignore_fs_changes ||
701 !db_get_fileset_record(jcr, jcr->db, &fsr)) {
702 if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
703 Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
704 fsr.FileSet, db_strerror(jcr->db));
708 jcr->jr.FileSetId = fsr.FileSetId;
709 bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
710 Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
715 void init_jcr_job_record(JCR *jcr)
717 jcr->jr.SchedTime = jcr->sched_time;
718 jcr->jr.StartTime = jcr->start_time;
719 jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
720 jcr->jr.JobType = jcr->JobType;
721 jcr->jr.JobLevel = jcr->JobLevel;
722 jcr->jr.JobStatus = jcr->JobStatus;
723 jcr->jr.JobId = jcr->JobId;
724 bstrncpy(jcr->jr.Name, jcr->job->hdr.name, sizeof(jcr->jr.Name));
725 bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
729 * Write status and such in DB
731 void update_job_end_record(JCR *jcr)
733 jcr->jr.EndTime = time(NULL);
734 jcr->end_time = jcr->jr.EndTime;
735 jcr->jr.JobId = jcr->JobId;
736 jcr->jr.JobStatus = jcr->JobStatus;
737 jcr->jr.JobFiles = jcr->JobFiles;
738 jcr->jr.JobBytes = jcr->JobBytes;
739 jcr->jr.VolSessionId = jcr->VolSessionId;
740 jcr->jr.VolSessionTime = jcr->VolSessionTime;
741 if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
742 Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
743 db_strerror(jcr->db));
748 * Takes base_name and appends (unique) current
749 * date and time to form unique job name.
751 * Returns: unique job name in jcr->Job
752 * date/time in jcr->start_time
754 void create_unique_job_name(JCR *jcr, const char *base_name)
756 /* Job start mutex */
757 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
758 static time_t last_start_time = 0;
761 char dt[MAX_TIME_LENGTH];
762 char name[MAX_NAME_LENGTH];
765 /* Guarantee unique start time -- maximum one per second, and
766 * thus unique Job Name
768 P(mutex); /* lock creation of jobs */
770 while (now == last_start_time) {
771 bmicrosleep(0, 500000);
774 last_start_time = now;
775 V(mutex); /* allow creation of jobs */
776 jcr->start_time = now;
777 /* Form Unique JobName */
778 (void)localtime_r(&now, &tm);
779 /* Use only characters that are permitted in Windows filenames */
780 strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
781 bstrncpy(name, base_name, sizeof(name));
782 name[sizeof(name)-22] = 0; /* truncate if too long */
783 bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
784 /* Convert spaces into underscores */
785 for (p=jcr->Job; *p; p++) {
792 /* Called directly from job rescheduling */
793 void dird_free_jcr_pointers(JCR *jcr)
795 if (jcr->sd_auth_key) {
796 free(jcr->sd_auth_key);
797 jcr->sd_auth_key = NULL;
803 if (jcr->file_bsock) {
804 Dmsg0(200, "Close File bsock\n");
805 bnet_close(jcr->file_bsock);
806 jcr->file_bsock = NULL;
808 if (jcr->store_bsock) {
809 Dmsg0(200, "Close Store bsock\n");
810 bnet_close(jcr->store_bsock);
811 jcr->store_bsock = NULL;
814 Dmsg0(200, "Free JCR fname\n");
815 free_pool_memory(jcr->fname);
818 if (jcr->pool_source) {
819 free_pool_memory(jcr->pool_source);
820 jcr->pool_source = NULL;
822 if (jcr->storage_source) {
823 free_pool_memory(jcr->storage_source);
824 jcr->storage_source = NULL;
827 Dmsg0(200, "Free JCR stime\n");
828 free_pool_memory(jcr->stime);
831 if (jcr->RestoreBootstrap) {
832 free(jcr->RestoreBootstrap);
833 jcr->RestoreBootstrap = NULL;
835 if (jcr->client_uname) {
836 free_pool_memory(jcr->client_uname);
837 jcr->client_uname = NULL;
840 free_pool_memory(jcr->attr);
850 * Free the Job Control Record if no one is still using it.
851 * Called from main free_jcr() routine in src/lib/jcr.c so
852 * that we can do our Director specific cleanup of the jcr.
854 void dird_free_jcr(JCR *jcr)
856 Dmsg0(200, "Start dird free_jcr\n");
858 dird_free_jcr_pointers(jcr);
859 if (jcr->term_wait_inited) {
860 pthread_cond_destroy(&jcr->term_wait);
861 jcr->term_wait_inited = false;
864 /* Delete lists setup to hold storage pointers */
867 jcr->job_end_push.destroy();
868 Dmsg0(200, "End dird free_jcr\n");
872 * Set some defaults in the JCR necessary to
873 * run. These items are pulled from the job
874 * definition as defaults, but can be overridden
875 * later either by the Run record in the Schedule resource,
876 * or by the Console program.
878 void set_jcr_defaults(JCR *jcr, JOB *job)
881 jcr->JobType = job->JobType;
882 switch (jcr->JobType) {
885 jcr->JobLevel = L_NONE;
888 jcr->JobLevel = job->JobLevel;
892 jcr->fname = get_pool_memory(PM_FNAME);
894 if (!jcr->pool_source) {
895 jcr->pool_source = get_pool_memory(PM_MESSAGE);
896 pm_strcpy(jcr->pool_source, _("unknown source"));
898 if (!jcr->storage_source) {
899 jcr->storage_source = get_pool_memory(PM_MESSAGE);
900 pm_strcpy(jcr->storage_source, _("unknown source"));
902 jcr->JobPriority = job->Priority;
903 /* Copy storage definitions -- deleted in dir_free_jcr above */
904 copy_rwstorage(jcr, job->storage, _("Job resource"));
905 jcr->client = job->client;
906 if (!jcr->client_name) {
907 jcr->client_name = get_pool_memory(PM_NAME);
909 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
910 pm_strcpy(jcr->pool_source, _("Job resource"));
911 jcr->pool = job->pool;
912 jcr->full_pool = job->full_pool;
913 jcr->inc_pool = job->inc_pool;
914 jcr->diff_pool = job->diff_pool;
915 jcr->catalog = job->client->catalog;
916 jcr->fileset = job->fileset;
917 jcr->messages = job->messages;
918 jcr->spool_data = job->spool_data;
919 jcr->write_part_after_job = job->write_part_after_job;
920 if (jcr->RestoreBootstrap) {
921 free(jcr->RestoreBootstrap);
922 jcr->RestoreBootstrap = NULL;
924 /* This can be overridden by Console program */
925 if (job->RestoreBootstrap) {
926 jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
928 /* This can be overridden by Console program */
929 jcr->verify_job = job->verify_job;
930 /* If no default level given, set one */
931 if (jcr->JobLevel == 0) {
932 switch (jcr->JobType) {
934 jcr->JobLevel = L_VERIFY_CATALOG;
937 jcr->JobLevel = L_INCREMENTAL;
941 jcr->JobLevel = L_NONE;
950 * Copy the storage definitions from an alist to the JCR
952 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
954 copy_rstorage(jcr, storage, where);
955 copy_wstorage(jcr, storage, where);
959 /* Set storage override */
960 void set_rwstorage(JCR *jcr, STORE *store)
962 set_rstorage(jcr, store);
963 set_wstorage(jcr, store);
966 void free_rwstorage(JCR *jcr)
973 * Copy the storage definitions from an alist to the JCR
975 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
980 delete jcr->rstorage;
982 jcr->rstorage = New(alist(10, not_owned_by_alist));
983 foreach_alist(st, storage) {
984 jcr->rstorage->append(st);
986 pm_strcpy(jcr->storage_source, where);
989 jcr->rstore = (STORE *)jcr->rstorage->first();
994 /* Set storage override */
995 void set_rstorage(JCR *jcr, STORE *store)
1000 foreach_alist(storage, jcr->rstorage) {
1001 if (store == storage) {
1005 /* Store not in list, so add it */
1006 jcr->rstorage->prepend(store);
1009 void free_rstorage(JCR *jcr)
1011 if (jcr->rstorage) {
1012 delete jcr->rstorage;
1013 jcr->rstorage = NULL;
1019 * Copy the storage definitions from an alist to the JCR
1021 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1025 if (jcr->wstorage) {
1026 delete jcr->wstorage;
1028 jcr->wstorage = New(alist(10, not_owned_by_alist));
1029 foreach_alist(st, storage) {
1030 jcr->wstorage->append(st);
1032 pm_strcpy(jcr->storage_source, where);
1034 if (jcr->wstorage) {
1035 jcr->wstore = (STORE *)jcr->wstorage->first();
1040 /* Set storage override */
1041 void set_wstorage(JCR *jcr, STORE *store)
1045 jcr->wstore = store;
1046 foreach_alist(storage, jcr->wstorage) {
1047 if (store == storage) {
1051 /* Store not in list, so add it */
1052 jcr->wstorage->prepend(store);
1055 void free_wstorage(JCR *jcr)
1057 if (jcr->wstorage) {
1058 delete jcr->wstorage;
1059 jcr->wstorage = NULL;
1066 void create_clones(JCR *jcr)
1069 * Fire off any clone jobs (run directives)
1071 Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1072 if (!jcr->cloned && jcr->job->run_cmds) {
1074 JOB *job = jcr->job;
1075 POOLMEM *cmd = get_pool_memory(PM_FNAME);
1076 UAContext *ua = new_ua_context(jcr);
1078 foreach_alist(runcmd, job->run_cmds) {
1079 cmd = edit_job_codes(jcr, cmd, runcmd, "");
1080 Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1081 Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1082 parse_ua_args(ua); /* parse command */
1083 int stat = run_cmd(ua, ua->cmd);
1085 Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1087 Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1090 free_ua_context(ua);
1091 free_pool_memory(cmd);
1095 bool create_restore_bootstrap_file(JCR *jcr)
1099 memset(&rx, 0, sizeof(rx));
1102 rx.bsr->JobId = jcr->previous_jr.JobId;
1103 ua = new_ua_context(jcr);
1104 complete_bsr(ua, rx.bsr);
1105 rx.bsr->fi = new_findex();
1106 rx.bsr->fi->findex = 1;
1107 rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1108 jcr->ExpectedFiles = write_bsr_file(ua, rx);
1109 if (jcr->ExpectedFiles == 0) {
1110 free_ua_context(ua);
1114 free_ua_context(ua);
1116 jcr->needs_sd = true;