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 /* Run any script BeforeJob on dird */
244 run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
246 if (job_canceled(jcr)) {
247 update_job_end_record(jcr);
251 * We re-update the job start record so that the start
252 * time is set after the run before job. This avoids
253 * that any files created by the run before job will
254 * be saved twice. They will be backed up in the current
255 * job, but not in the next one unless they are changed.
256 * Without this, they will be backed up in this job and
257 * in the next job run because in that case, their date
258 * is after the start of this run.
260 jcr->start_time = time(NULL);
261 jcr->jr.StartTime = jcr->start_time;
262 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
263 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
265 generate_job_event(jcr, "JobRun");
267 switch (jcr->JobType) {
269 if (do_backup(jcr)) {
272 backup_cleanup(jcr, JS_ErrorTerminated);
276 if (do_verify(jcr)) {
279 verify_cleanup(jcr, JS_ErrorTerminated);
283 if (do_restore(jcr)) {
286 restore_cleanup(jcr, JS_ErrorTerminated);
293 admin_cleanup(jcr, JS_ErrorTerminated);
299 if (do_migration(jcr)) {
302 migration_cleanup(jcr, JS_ErrorTerminated);
306 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
310 run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
312 /* Send off any queued messages */
313 if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
314 dequeue_messages(jcr);
318 generate_daemon_event(jcr, "JobEnd");
319 Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
320 sm_check(__FILE__, __LINE__, true);
326 * Cancel a job -- typically called by the UA (Console program), but may also
327 * be called by the job watchdog.
329 * Returns: true if cancel appears to be successful
330 * false on failure. Message sent to ua->jcr.
332 bool cancel_job(UAContext *ua, JCR *jcr)
336 set_jcr_job_status(jcr, JS_Canceled);
338 switch (jcr->JobStatus) {
341 case JS_WaitClientRes:
342 case JS_WaitStoreRes:
343 case JS_WaitPriority:
345 case JS_WaitStartTime:
346 bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"),
347 jcr->JobId, jcr->Job);
348 jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
352 /* Cancel File daemon */
353 if (jcr->file_bsock) {
354 ua->jcr->client = jcr->client;
355 if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
356 bsendmsg(ua, _("Failed to connect to File daemon.\n"));
359 Dmsg0(200, "Connected to file daemon\n");
360 fd = ua->jcr->file_bsock;
361 bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
362 while (bnet_recv(fd) >= 0) {
363 bsendmsg(ua, "%s", fd->msg);
365 bnet_sig(fd, BNET_TERMINATE);
367 ua->jcr->file_bsock = NULL;
370 /* Cancel Storage daemon */
371 if (jcr->store_bsock) {
372 if (!ua->jcr->wstorage) {
374 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
376 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
380 set_wstorage(ua->jcr, jcr->rstore);
382 set_wstorage(ua->jcr, jcr->wstore);
385 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
386 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
389 Dmsg0(200, "Connected to storage daemon\n");
390 sd = ua->jcr->store_bsock;
391 bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
392 while (bnet_recv(sd) >= 0) {
393 bsendmsg(ua, "%s", sd->msg);
395 bnet_sig(sd, BNET_TERMINATE);
397 ua->jcr->store_bsock = NULL;
405 static void job_monitor_destructor(watchdog_t *self)
407 JCR *control_jcr = (JCR *)self->data;
409 free_jcr(control_jcr);
412 static void job_monitor_watchdog(watchdog_t *self)
414 JCR *control_jcr, *jcr;
416 control_jcr = (JCR *)self->data;
418 Dmsg1(800, "job_monitor_watchdog %p called\n", self);
423 if (jcr->JobId == 0) {
424 Dmsg2(800, "Skipping JCR %p (%s) with JobId 0\n",
429 /* check MaxWaitTime */
430 cancel = job_check_maxwaittime(control_jcr, jcr);
432 /* check MaxRunTime */
433 cancel |= job_check_maxruntime(control_jcr, jcr);
436 Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n",
437 jcr, jcr->JobId, jcr->Job);
439 UAContext *ua = new_ua_context(jcr);
440 ua->jcr = control_jcr;
444 Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
447 /* Keep reference counts correct */
453 * Check if the maxwaittime has expired and it is possible
456 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
459 bool ok_to_cancel = false;
462 if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
463 job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
466 if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
467 (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
469 } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
470 (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
472 } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
473 (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
475 } else if (job->MaxWaitTime != 0 &&
476 (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
482 Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, "
484 jcr->JobId, jcr->Job, job->MaxWaitTime);
485 switch (jcr->JobStatus) {
490 case JS_WaitStoreRes:
491 case JS_WaitClientRes:
493 case JS_WaitPriority:
495 case JS_WaitStartTime:
497 Dmsg0(200, "JCR blocked in #1\n");
500 Dmsg0(800, "JCR running, checking SD status\n");
501 switch (jcr->SDJobStatus) {
506 Dmsg0(800, "JCR blocked in #2\n");
509 Dmsg0(800, "JCR not blocked in #2\n");
514 case JS_ErrorTerminated:
517 Dmsg0(800, "JCR already dead in #3\n");
520 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
523 Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n",
524 cancel ? "" : "do not ", jcr, jcr->job);
530 * Check if maxruntime has expired and if the job can be
533 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
537 if (jcr->job->MaxRunTime == 0) {
540 if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
541 Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
542 jcr, jcr->Job, jcr->job->MaxRunTime);
546 switch (jcr->JobStatus) {
552 case JS_WaitStoreRes:
553 case JS_WaitClientRes:
555 case JS_WaitPriority:
557 case JS_WaitStartTime:
562 case JS_ErrorTerminated:
568 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
572 Dmsg3(200, "MaxRunTime result: %scancel JCR %p (%s)\n",
573 cancel ? "" : "do not ", jcr, jcr->job);
579 * Get or create a Pool record with the given name.
580 * Returns: 0 on error
583 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
587 memset(&pr, 0, sizeof(pr));
588 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
590 while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
591 /* Try to create the pool */
592 if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
593 Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
594 db_strerror(jcr->db));
597 Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
603 void apply_pool_overrides(JCR *jcr)
605 if (jcr->run_pool_override) {
606 pm_strcpy(jcr->pool_source, _("Run Pool override"));
609 * Apply any level related Pool selections
611 switch (jcr->JobLevel) {
613 if (jcr->full_pool) {
614 jcr->pool = jcr->full_pool;
615 if (jcr->run_full_pool_override) {
616 pm_strcpy(jcr->pool_source, _("Run FullPool override"));
618 pm_strcpy(jcr->pool_source, _("Job FullPool override"));
624 jcr->pool = jcr->inc_pool;
625 if (jcr->run_inc_pool_override) {
626 pm_strcpy(jcr->pool_source, _("Run IncPool override"));
628 pm_strcpy(jcr->pool_source, _("Job IncPool override"));
633 if (jcr->diff_pool) {
634 jcr->pool = jcr->diff_pool;
635 if (jcr->run_diff_pool_override) {
636 pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
638 pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
647 * Get or create a Client record for this Job
649 bool get_or_create_client_record(JCR *jcr)
653 memset(&cr, 0, sizeof(cr));
654 bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
655 cr.AutoPrune = jcr->client->AutoPrune;
656 cr.FileRetention = jcr->client->FileRetention;
657 cr.JobRetention = jcr->client->JobRetention;
658 if (!jcr->client_name) {
659 jcr->client_name = get_pool_memory(PM_NAME);
661 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
662 if (!db_create_client_record(jcr, jcr->db, &cr)) {
663 Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
664 db_strerror(jcr->db));
667 jcr->jr.ClientId = cr.ClientId;
669 if (!jcr->client_uname) {
670 jcr->client_uname = get_pool_memory(PM_NAME);
672 pm_strcpy(jcr->client_uname, cr.Uname);
674 Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
679 bool get_or_create_fileset_record(JCR *jcr)
683 * Get or Create FileSet record
685 memset(&fsr, 0, sizeof(FILESET_DBR));
686 bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
687 if (jcr->fileset->have_MD5) {
688 struct MD5Context md5c;
689 unsigned char digest[MD5HashSize];
690 memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
691 MD5Final(digest, &md5c);
693 * Keep the flag (last arg) set to false otherwise old FileSets will
694 * get new MD5 sums and the user will get Full backups on everything
696 bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
697 bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
699 Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
701 if (!jcr->fileset->ignore_fs_changes ||
702 !db_get_fileset_record(jcr, jcr->db, &fsr)) {
703 if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
704 Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
705 fsr.FileSet, db_strerror(jcr->db));
709 jcr->jr.FileSetId = fsr.FileSetId;
710 bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
711 Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
716 void init_jcr_job_record(JCR *jcr)
718 jcr->jr.SchedTime = jcr->sched_time;
719 jcr->jr.StartTime = jcr->start_time;
720 jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
721 jcr->jr.JobType = jcr->JobType;
722 jcr->jr.JobLevel = jcr->JobLevel;
723 jcr->jr.JobStatus = jcr->JobStatus;
724 jcr->jr.JobId = jcr->JobId;
725 bstrncpy(jcr->jr.Name, jcr->job->hdr.name, sizeof(jcr->jr.Name));
726 bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
730 * Write status and such in DB
732 void update_job_end_record(JCR *jcr)
734 jcr->jr.EndTime = time(NULL);
735 jcr->end_time = jcr->jr.EndTime;
736 jcr->jr.JobId = jcr->JobId;
737 jcr->jr.JobStatus = jcr->JobStatus;
738 jcr->jr.JobFiles = jcr->JobFiles;
739 jcr->jr.JobBytes = jcr->JobBytes;
740 jcr->jr.VolSessionId = jcr->VolSessionId;
741 jcr->jr.VolSessionTime = jcr->VolSessionTime;
742 if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
743 Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
744 db_strerror(jcr->db));
749 * Takes base_name and appends (unique) current
750 * date and time to form unique job name.
752 * Returns: unique job name in jcr->Job
753 * date/time in jcr->start_time
755 void create_unique_job_name(JCR *jcr, const char *base_name)
757 /* Job start mutex */
758 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
759 static time_t last_start_time = 0;
762 char dt[MAX_TIME_LENGTH];
763 char name[MAX_NAME_LENGTH];
766 /* Guarantee unique start time -- maximum one per second, and
767 * thus unique Job Name
769 P(mutex); /* lock creation of jobs */
771 while (now == last_start_time) {
772 bmicrosleep(0, 500000);
775 last_start_time = now;
776 V(mutex); /* allow creation of jobs */
777 jcr->start_time = now;
778 /* Form Unique JobName */
779 (void)localtime_r(&now, &tm);
780 /* Use only characters that are permitted in Windows filenames */
781 strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
782 bstrncpy(name, base_name, sizeof(name));
783 name[sizeof(name)-22] = 0; /* truncate if too long */
784 bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
785 /* Convert spaces into underscores */
786 for (p=jcr->Job; *p; p++) {
793 /* Called directly from job rescheduling */
794 void dird_free_jcr_pointers(JCR *jcr)
796 if (jcr->sd_auth_key) {
797 free(jcr->sd_auth_key);
798 jcr->sd_auth_key = NULL;
804 if (jcr->file_bsock) {
805 Dmsg0(200, "Close File bsock\n");
806 bnet_close(jcr->file_bsock);
807 jcr->file_bsock = NULL;
809 if (jcr->store_bsock) {
810 Dmsg0(200, "Close Store bsock\n");
811 bnet_close(jcr->store_bsock);
812 jcr->store_bsock = NULL;
815 Dmsg0(200, "Free JCR fname\n");
816 free_pool_memory(jcr->fname);
819 if (jcr->pool_source) {
820 free_pool_memory(jcr->pool_source);
821 jcr->pool_source = NULL;
823 if (jcr->storage_source) {
824 free_pool_memory(jcr->storage_source);
825 jcr->storage_source = NULL;
828 Dmsg0(200, "Free JCR stime\n");
829 free_pool_memory(jcr->stime);
832 if (jcr->RestoreBootstrap) {
833 free(jcr->RestoreBootstrap);
834 jcr->RestoreBootstrap = NULL;
836 if (jcr->client_uname) {
837 free_pool_memory(jcr->client_uname);
838 jcr->client_uname = NULL;
841 free_pool_memory(jcr->attr);
851 * Free the Job Control Record if no one is still using it.
852 * Called from main free_jcr() routine in src/lib/jcr.c so
853 * that we can do our Director specific cleanup of the jcr.
855 void dird_free_jcr(JCR *jcr)
857 Dmsg0(200, "Start dird free_jcr\n");
859 dird_free_jcr_pointers(jcr);
860 if (jcr->term_wait_inited) {
861 pthread_cond_destroy(&jcr->term_wait);
862 jcr->term_wait_inited = false;
865 /* Delete lists setup to hold storage pointers */
868 jcr->job_end_push.destroy();
869 Dmsg0(200, "End dird free_jcr\n");
873 * Set some defaults in the JCR necessary to
874 * run. These items are pulled from the job
875 * definition as defaults, but can be overridden
876 * later either by the Run record in the Schedule resource,
877 * or by the Console program.
879 void set_jcr_defaults(JCR *jcr, JOB *job)
882 jcr->JobType = job->JobType;
883 switch (jcr->JobType) {
886 jcr->JobLevel = L_NONE;
889 jcr->JobLevel = job->JobLevel;
893 jcr->fname = get_pool_memory(PM_FNAME);
895 if (!jcr->pool_source) {
896 jcr->pool_source = get_pool_memory(PM_MESSAGE);
897 pm_strcpy(jcr->pool_source, _("unknown source"));
899 if (!jcr->storage_source) {
900 jcr->storage_source = get_pool_memory(PM_MESSAGE);
901 pm_strcpy(jcr->storage_source, _("unknown source"));
903 jcr->JobPriority = job->Priority;
904 /* Copy storage definitions -- deleted in dir_free_jcr above */
905 copy_rwstorage(jcr, job->storage, _("Job resource"));
906 jcr->client = job->client;
907 if (!jcr->client_name) {
908 jcr->client_name = get_pool_memory(PM_NAME);
910 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
911 pm_strcpy(jcr->pool_source, _("Job resource"));
912 jcr->pool = job->pool;
913 jcr->full_pool = job->full_pool;
914 jcr->inc_pool = job->inc_pool;
915 jcr->diff_pool = job->diff_pool;
916 jcr->catalog = job->client->catalog;
917 jcr->fileset = job->fileset;
918 jcr->messages = job->messages;
919 jcr->spool_data = job->spool_data;
920 jcr->write_part_after_job = job->write_part_after_job;
921 if (jcr->RestoreBootstrap) {
922 free(jcr->RestoreBootstrap);
923 jcr->RestoreBootstrap = NULL;
925 /* This can be overridden by Console program */
926 if (job->RestoreBootstrap) {
927 jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
929 /* This can be overridden by Console program */
930 jcr->verify_job = job->verify_job;
931 /* If no default level given, set one */
932 if (jcr->JobLevel == 0) {
933 switch (jcr->JobType) {
935 jcr->JobLevel = L_VERIFY_CATALOG;
938 jcr->JobLevel = L_INCREMENTAL;
942 jcr->JobLevel = L_NONE;
951 * Copy the storage definitions from an alist to the JCR
953 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
955 copy_rstorage(jcr, storage, where);
956 copy_wstorage(jcr, storage, where);
960 /* Set storage override */
961 void set_rwstorage(JCR *jcr, STORE *store)
963 set_rstorage(jcr, store);
964 set_wstorage(jcr, store);
967 void free_rwstorage(JCR *jcr)
974 * Copy the storage definitions from an alist to the JCR
976 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
981 delete jcr->rstorage;
983 jcr->rstorage = New(alist(10, not_owned_by_alist));
984 foreach_alist(st, storage) {
985 jcr->rstorage->append(st);
987 pm_strcpy(jcr->storage_source, where);
990 jcr->rstore = (STORE *)jcr->rstorage->first();
995 /* Set storage override */
996 void set_rstorage(JCR *jcr, STORE *store)
1000 jcr->rstore = store;
1001 foreach_alist(storage, jcr->rstorage) {
1002 if (store == storage) {
1006 /* Store not in list, so add it */
1007 jcr->rstorage->prepend(store);
1010 void free_rstorage(JCR *jcr)
1012 if (jcr->rstorage) {
1013 delete jcr->rstorage;
1014 jcr->rstorage = NULL;
1020 * Copy the storage definitions from an alist to the JCR
1022 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1026 if (jcr->wstorage) {
1027 delete jcr->wstorage;
1029 jcr->wstorage = New(alist(10, not_owned_by_alist));
1030 foreach_alist(st, storage) {
1031 jcr->wstorage->append(st);
1033 pm_strcpy(jcr->storage_source, where);
1035 if (jcr->wstorage) {
1036 jcr->wstore = (STORE *)jcr->wstorage->first();
1041 /* Set storage override */
1042 void set_wstorage(JCR *jcr, STORE *store)
1046 jcr->wstore = store;
1047 foreach_alist(storage, jcr->wstorage) {
1048 if (store == storage) {
1052 /* Store not in list, so add it */
1053 jcr->wstorage->prepend(store);
1056 void free_wstorage(JCR *jcr)
1058 if (jcr->wstorage) {
1059 delete jcr->wstorage;
1060 jcr->wstorage = NULL;
1067 void create_clones(JCR *jcr)
1070 * Fire off any clone jobs (run directives)
1072 Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1073 if (!jcr->cloned && jcr->job->run_cmds) {
1075 JOB *job = jcr->job;
1076 POOLMEM *cmd = get_pool_memory(PM_FNAME);
1077 UAContext *ua = new_ua_context(jcr);
1079 foreach_alist(runcmd, job->run_cmds) {
1080 cmd = edit_job_codes(jcr, cmd, runcmd, "");
1081 Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1082 Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1083 parse_ua_args(ua); /* parse command */
1084 int stat = run_cmd(ua, ua->cmd);
1086 Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1088 Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1091 free_ua_context(ua);
1092 free_pool_memory(cmd);
1096 bool create_restore_bootstrap_file(JCR *jcr)
1100 memset(&rx, 0, sizeof(rx));
1103 rx.bsr->JobId = jcr->previous_jr.JobId;
1104 ua = new_ua_context(jcr);
1105 complete_bsr(ua, rx.bsr);
1106 rx.bsr->fi = new_findex();
1107 rx.bsr->fi->findex = 1;
1108 rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1109 jcr->ExpectedFiles = write_bsr_file(ua, rx);
1110 if (jcr->ExpectedFiles == 0) {
1111 free_ua_context(ua);
1115 free_ua_context(ua);
1117 jcr->needs_sd = true;