3 * Bacula Director Job processing routines
5 * Kern Sibbald, October MM
10 Bacula® - The Network Backup Solution
12 Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
14 The main author of Bacula is Kern Sibbald, with contributions from
15 many others, a complete list can be found in the file AUTHORS.
16 This program is Free Software; you can redistribute it and/or
17 modify it under the terms of version two of the GNU General Public
18 License as published by the Free Software Foundation plus additions
19 that are listed in the file LICENSE.
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 Bacula® is a registered trademark of John Walker.
32 The licensor of Bacula is the Free Software Foundation Europe
33 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
34 Switzerland, email:ftf@fsfeurope.org.
40 /* Forward referenced subroutines */
41 static void *job_thread(void *arg);
42 static void job_monitor_watchdog(watchdog_t *self);
43 static void job_monitor_destructor(watchdog_t *self);
44 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr);
45 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr);
47 /* Imported subroutines */
48 extern void term_scheduler();
49 extern void term_ua_server();
51 /* Imported variables */
55 void init_job_server(int max_workers)
60 if ((stat = jobq_init(&job_queue, max_workers, job_thread)) != 0) {
62 Emsg1(M_ABORT, 0, _("Could not init job queue: ERR=%s\n"), be.strerror(stat));
65 wd->callback = job_monitor_watchdog;
66 wd->destructor = job_monitor_destructor;
69 wd->data = new_control_jcr("*JobMonitor*", JT_SYSTEM);
70 register_watchdog(wd);
73 void term_job_server()
75 jobq_destroy(&job_queue); /* ignore any errors */
79 * Run a job -- typically called by the scheduler, but may also
80 * be called by the UA (Console program).
82 * Returns: 0 on failure
86 JobId_t run_job(JCR *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) {
94 Jmsg(jcr, M_FATAL, 0, _("Could not add job queue: ERR=%s\n"), be.strerror(stat));
102 bool setup_job(JCR *jcr)
107 sm_check(__FILE__, __LINE__, true);
108 init_msg(jcr, jcr->messages);
110 /* Initialize termination condition variable */
111 if ((errstat = pthread_cond_init(&jcr->term_wait, NULL)) != 0) {
113 Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.strerror(errstat));
116 jcr->term_wait_inited = true;
118 create_unique_job_name(jcr, jcr->job->name());
119 set_jcr_job_status(jcr, JS_Created);
125 Dmsg0(50, "Open database\n");
126 jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user,
127 jcr->catalog->db_password, jcr->catalog->db_address,
128 jcr->catalog->db_port, jcr->catalog->db_socket,
129 jcr->catalog->mult_db_connections);
130 if (!jcr->db || !db_open_database(jcr, jcr->db)) {
131 Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
132 jcr->catalog->db_name);
134 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
138 Dmsg0(50, "DB opened\n");
141 jcr->fname = get_pool_memory(PM_FNAME);
143 if (!jcr->pool_source) {
144 jcr->pool_source = get_pool_memory(PM_MESSAGE);
145 pm_strcpy(jcr->pool_source, _("unknown source"));
147 Dmsg2(500, "pool=%s (From %s)\n", jcr->pool->name(), jcr->pool_source);
148 if (jcr->JobType == JT_MIGRATE) {
149 if (!jcr->rpool_source) {
150 jcr->rpool_source = get_pool_memory(PM_MESSAGE);
151 pm_strcpy(jcr->rpool_source, _("unknown source"));
158 init_jcr_job_record(jcr);
159 if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
160 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
163 jcr->JobId = jcr->jr.JobId;
164 Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
165 jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
167 if (!get_or_create_client_record(jcr)) {
171 generate_daemon_event(jcr, "JobStart");
173 if (job_canceled(jcr)) {
179 * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
180 * this allows us to setup a proper job start record for restarting
181 * in case of later errors.
183 switch (jcr->JobType) {
185 if (!do_backup_init(jcr)) {
186 backup_cleanup(jcr, JS_ErrorTerminated);
190 if (!do_verify_init(jcr)) {
191 verify_cleanup(jcr, JS_ErrorTerminated);
195 if (!do_restore_init(jcr)) {
196 restore_cleanup(jcr, JS_ErrorTerminated);
200 if (!do_admin_init(jcr)) {
201 admin_cleanup(jcr, JS_ErrorTerminated);
205 if (!do_migration_init(jcr)) {
206 migration_cleanup(jcr, JS_ErrorTerminated);
210 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
211 set_jcr_job_status(jcr, JS_ErrorTerminated);
215 generate_job_event(jcr, "JobInit");
224 * This is the engine called by jobq.c:jobq_add() when we were pulled
225 * from the work queue.
226 * At this point, we are running in our own thread and all
227 * necessary resources are allocated -- see jobq.c
229 static void *job_thread(void *arg)
231 JCR *jcr = (JCR *)arg;
233 jcr->my_thread_id = pthread_self();
234 pthread_detach(jcr->my_thread_id);
235 sm_check(__FILE__, __LINE__, true);
237 Dmsg0(200, "=====Start Job=========\n");
238 set_jcr_job_status(jcr, JS_Running); /* this will be set only if no error */
239 jcr->start_time = time(NULL); /* set the real start time */
240 jcr->jr.StartTime = jcr->start_time;
242 if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
243 (utime_t)(jcr->start_time - jcr->sched_time)) {
244 Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
245 set_jcr_job_status(jcr, JS_Canceled);
248 /* TODO : check if it is used somewhere */
249 if (jcr->job->RunScripts == NULL) {
250 Dmsg0(200, "Warning, job->RunScripts is empty\n");
251 jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
254 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
255 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
258 /* Run any script BeforeJob on dird */
259 run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
261 if (job_canceled(jcr)) {
262 update_job_end_record(jcr);
266 * We re-update the job start record so that the start
267 * time is set after the run before job. This avoids
268 * that any files created by the run before job will
269 * be saved twice. They will be backed up in the current
270 * job, but not in the next one unless they are changed.
271 * Without this, they will be backed up in this job and
272 * in the next job run because in that case, their date
273 * is after the start of this run.
275 jcr->start_time = time(NULL);
276 jcr->jr.StartTime = jcr->start_time;
277 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
278 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
280 generate_job_event(jcr, "JobRun");
282 switch (jcr->JobType) {
284 if (do_backup(jcr)) {
287 backup_cleanup(jcr, JS_ErrorTerminated);
291 if (do_verify(jcr)) {
294 verify_cleanup(jcr, JS_ErrorTerminated);
298 if (do_restore(jcr)) {
301 restore_cleanup(jcr, JS_ErrorTerminated);
308 admin_cleanup(jcr, JS_ErrorTerminated);
314 if (do_migration(jcr)) {
317 migration_cleanup(jcr, JS_ErrorTerminated);
321 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
325 run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
327 /* Send off any queued messages */
328 if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
329 dequeue_messages(jcr);
333 generate_daemon_event(jcr, "JobEnd");
334 Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
335 sm_check(__FILE__, __LINE__, true);
341 * Cancel a job -- typically called by the UA (Console program), but may also
342 * be called by the job watchdog.
344 * Returns: true if cancel appears to be successful
345 * false on failure. Message sent to ua->jcr.
347 bool cancel_job(UAContext *ua, JCR *jcr)
351 set_jcr_job_status(jcr, JS_Canceled);
353 switch (jcr->JobStatus) {
356 case JS_WaitClientRes:
357 case JS_WaitStoreRes:
358 case JS_WaitPriority:
360 case JS_WaitStartTime:
361 bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"),
362 jcr->JobId, jcr->Job);
363 jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
367 /* Cancel File daemon */
368 if (jcr->file_bsock) {
369 ua->jcr->client = jcr->client;
370 if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
371 bsendmsg(ua, _("Failed to connect to File daemon.\n"));
374 Dmsg0(200, "Connected to file daemon\n");
375 fd = ua->jcr->file_bsock;
376 bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
377 while (bnet_recv(fd) >= 0) {
378 bsendmsg(ua, "%s", fd->msg);
380 bnet_sig(fd, BNET_TERMINATE);
382 ua->jcr->file_bsock = NULL;
385 /* Cancel Storage daemon */
386 if (jcr->store_bsock) {
387 if (!ua->jcr->wstorage) {
389 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
391 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
396 store.store = jcr->rstore;
397 pm_strcpy(store.store_source, jcr->rstore_source);
399 store.store = jcr->wstore;
400 pm_strcpy(store.store_source, jcr->wstore_source);
402 set_wstorage(ua->jcr, &store);
405 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
406 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
409 Dmsg0(200, "Connected to storage daemon\n");
410 sd = ua->jcr->store_bsock;
411 bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
412 while (bnet_recv(sd) >= 0) {
413 bsendmsg(ua, "%s", sd->msg);
415 bnet_sig(sd, BNET_TERMINATE);
417 ua->jcr->store_bsock = NULL;
425 static void job_monitor_destructor(watchdog_t *self)
427 JCR *control_jcr = (JCR *)self->data;
429 free_jcr(control_jcr);
432 static void job_monitor_watchdog(watchdog_t *self)
434 JCR *control_jcr, *jcr;
436 control_jcr = (JCR *)self->data;
438 Dmsg1(800, "job_monitor_watchdog %p called\n", self);
443 if (jcr->JobId == 0) {
444 Dmsg2(800, "Skipping JCR %p (%s) with JobId 0\n",
449 /* check MaxWaitTime */
450 cancel = job_check_maxwaittime(control_jcr, jcr);
452 /* check MaxRunTime */
453 cancel |= job_check_maxruntime(control_jcr, jcr);
456 Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n",
457 jcr, jcr->JobId, jcr->Job);
459 UAContext *ua = new_ua_context(jcr);
460 ua->jcr = control_jcr;
464 Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
467 /* Keep reference counts correct */
473 * Check if the maxwaittime has expired and it is possible
476 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
479 bool ok_to_cancel = false;
482 if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
483 job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
486 if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
487 (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
489 } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
490 (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
492 } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
493 (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
495 } else if (job->MaxWaitTime != 0 &&
496 (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
502 Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, "
504 jcr->JobId, jcr->Job, job->MaxWaitTime);
505 switch (jcr->JobStatus) {
510 case JS_WaitStoreRes:
511 case JS_WaitClientRes:
513 case JS_WaitPriority:
515 case JS_WaitStartTime:
517 Dmsg0(200, "JCR blocked in #1\n");
520 Dmsg0(800, "JCR running, checking SD status\n");
521 switch (jcr->SDJobStatus) {
526 Dmsg0(800, "JCR blocked in #2\n");
529 Dmsg0(800, "JCR not blocked in #2\n");
534 case JS_ErrorTerminated:
537 Dmsg0(800, "JCR already dead in #3\n");
540 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
543 Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n",
544 cancel ? "" : "do not ", jcr, jcr->job);
550 * Check if maxruntime has expired and if the job can be
553 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
557 if (jcr->job->MaxRunTime == 0) {
560 if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
561 Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
562 jcr, jcr->Job, jcr->job->MaxRunTime);
566 switch (jcr->JobStatus) {
572 case JS_WaitStoreRes:
573 case JS_WaitClientRes:
575 case JS_WaitPriority:
577 case JS_WaitStartTime:
582 case JS_ErrorTerminated:
588 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
592 Dmsg3(200, "MaxRunTime result: %scancel JCR %p (%s)\n",
593 cancel ? "" : "do not ", jcr, jcr->job);
599 * Get or create a Pool record with the given name.
600 * Returns: 0 on error
603 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
607 memset(&pr, 0, sizeof(pr));
608 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
609 Dmsg1(010, "get_or_create_pool=%s\n", pool_name);
611 while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
612 /* Try to create the pool */
613 if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
614 Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
615 db_strerror(jcr->db));
618 Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
624 void apply_pool_overrides(JCR *jcr)
626 if (jcr->run_pool_override) {
627 pm_strcpy(jcr->pool_source, _("Run pool override"));
630 * Apply any level related Pool selections
632 switch (jcr->JobLevel) {
634 if (jcr->full_pool) {
635 jcr->pool = jcr->full_pool;
636 if (jcr->run_full_pool_override) {
637 pm_strcpy(jcr->pool_source, _("Run FullPool override"));
639 pm_strcpy(jcr->pool_source, _("Job FullPool override"));
645 jcr->pool = jcr->inc_pool;
646 if (jcr->run_inc_pool_override) {
647 pm_strcpy(jcr->pool_source, _("Run IncPool override"));
649 pm_strcpy(jcr->pool_source, _("Job IncPool override"));
654 if (jcr->diff_pool) {
655 jcr->pool = jcr->diff_pool;
656 if (jcr->run_diff_pool_override) {
657 pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
659 pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
668 * Get or create a Client record for this Job
670 bool get_or_create_client_record(JCR *jcr)
674 memset(&cr, 0, sizeof(cr));
675 bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
676 cr.AutoPrune = jcr->client->AutoPrune;
677 cr.FileRetention = jcr->client->FileRetention;
678 cr.JobRetention = jcr->client->JobRetention;
679 if (!jcr->client_name) {
680 jcr->client_name = get_pool_memory(PM_NAME);
682 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
683 if (!db_create_client_record(jcr, jcr->db, &cr)) {
684 Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
685 db_strerror(jcr->db));
688 jcr->jr.ClientId = cr.ClientId;
690 if (!jcr->client_uname) {
691 jcr->client_uname = get_pool_memory(PM_NAME);
693 pm_strcpy(jcr->client_uname, cr.Uname);
695 Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
700 bool get_or_create_fileset_record(JCR *jcr)
704 * Get or Create FileSet record
706 memset(&fsr, 0, sizeof(FILESET_DBR));
707 bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
708 if (jcr->fileset->have_MD5) {
709 struct MD5Context md5c;
710 unsigned char digest[MD5HashSize];
711 memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
712 MD5Final(digest, &md5c);
714 * Keep the flag (last arg) set to false otherwise old FileSets will
715 * get new MD5 sums and the user will get Full backups on everything
717 bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
718 bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
720 Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
722 if (!jcr->fileset->ignore_fs_changes ||
723 !db_get_fileset_record(jcr, jcr->db, &fsr)) {
724 if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
725 Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
726 fsr.FileSet, db_strerror(jcr->db));
730 jcr->jr.FileSetId = fsr.FileSetId;
731 bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
732 Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
737 void init_jcr_job_record(JCR *jcr)
739 jcr->jr.SchedTime = jcr->sched_time;
740 jcr->jr.StartTime = jcr->start_time;
741 jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
742 jcr->jr.JobType = jcr->JobType;
743 jcr->jr.JobLevel = jcr->JobLevel;
744 jcr->jr.JobStatus = jcr->JobStatus;
745 jcr->jr.JobId = jcr->JobId;
746 bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
747 bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
751 * Write status and such in DB
753 void update_job_end_record(JCR *jcr)
755 jcr->jr.EndTime = time(NULL);
756 jcr->end_time = jcr->jr.EndTime;
757 jcr->jr.JobId = jcr->JobId;
758 jcr->jr.JobStatus = jcr->JobStatus;
759 jcr->jr.JobFiles = jcr->JobFiles;
760 jcr->jr.JobBytes = jcr->JobBytes;
761 jcr->jr.VolSessionId = jcr->VolSessionId;
762 jcr->jr.VolSessionTime = jcr->VolSessionTime;
763 jcr->jr.JobErrors = jcr->Errors;
764 if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
765 Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
766 db_strerror(jcr->db));
771 * Takes base_name and appends (unique) current
772 * date and time to form unique job name.
774 * Returns: unique job name in jcr->Job
775 * date/time in jcr->start_time
777 void create_unique_job_name(JCR *jcr, const char *base_name)
779 /* Job start mutex */
780 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
781 static time_t last_start_time = 0;
784 char dt[MAX_TIME_LENGTH];
785 char name[MAX_NAME_LENGTH];
788 /* Guarantee unique start time -- maximum one per second, and
789 * thus unique Job Name
791 P(mutex); /* lock creation of jobs */
793 while (now == last_start_time) {
794 bmicrosleep(0, 500000);
797 last_start_time = now;
798 V(mutex); /* allow creation of jobs */
799 jcr->start_time = now;
800 /* Form Unique JobName */
801 (void)localtime_r(&now, &tm);
802 /* Use only characters that are permitted in Windows filenames */
803 strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
804 bstrncpy(name, base_name, sizeof(name));
805 name[sizeof(name)-22] = 0; /* truncate if too long */
806 bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
807 /* Convert spaces into underscores */
808 for (p=jcr->Job; *p; p++) {
815 /* Called directly from job rescheduling */
816 void dird_free_jcr_pointers(JCR *jcr)
818 if (jcr->sd_auth_key) {
819 free(jcr->sd_auth_key);
820 jcr->sd_auth_key = NULL;
826 if (jcr->file_bsock) {
827 Dmsg0(200, "Close File bsock\n");
828 bnet_close(jcr->file_bsock);
829 jcr->file_bsock = NULL;
831 if (jcr->store_bsock) {
832 Dmsg0(200, "Close Store bsock\n");
833 bnet_close(jcr->store_bsock);
834 jcr->store_bsock = NULL;
837 Dmsg0(200, "Free JCR fname\n");
838 free_pool_memory(jcr->fname);
841 if (jcr->pool_source) {
842 free_pool_memory(jcr->pool_source);
843 jcr->pool_source = NULL;
845 if (jcr->rpool_source) {
846 free_pool_memory(jcr->rpool_source);
847 jcr->rpool_source = NULL;
849 if (jcr->wstore_source) {
850 free_pool_memory(jcr->wstore_source);
851 jcr->wstore_source = NULL;
853 if (jcr->rstore_source) {
854 free_pool_memory(jcr->rstore_source);
855 jcr->rstore_source = NULL;
858 Dmsg0(200, "Free JCR stime\n");
859 free_pool_memory(jcr->stime);
862 if (jcr->RestoreBootstrap) {
863 free(jcr->RestoreBootstrap);
864 jcr->RestoreBootstrap = NULL;
866 if (jcr->client_uname) {
867 free_pool_memory(jcr->client_uname);
868 jcr->client_uname = NULL;
871 free_pool_memory(jcr->attr);
881 * Free the Job Control Record if no one is still using it.
882 * Called from main free_jcr() routine in src/lib/jcr.c so
883 * that we can do our Director specific cleanup of the jcr.
885 void dird_free_jcr(JCR *jcr)
887 Dmsg0(200, "Start dird free_jcr\n");
889 dird_free_jcr_pointers(jcr);
890 if (jcr->term_wait_inited) {
891 pthread_cond_destroy(&jcr->term_wait);
892 jcr->term_wait_inited = false;
895 /* Delete lists setup to hold storage pointers */
898 jcr->job_end_push.destroy();
899 Dmsg0(200, "End dird free_jcr\n");
903 * The Job storage definition must be either in the Job record
904 * or in the Pool record. The Pool record overrides the Job
907 void get_job_storage(USTORE *store, JOB *job, RUN *run)
909 if (run && run->pool && run->pool->storage) {
910 store->store = (STORE *)run->pool->storage->first();
911 pm_strcpy(store->store_source, _("Run pool override"));
914 if (run && run->storage) {
915 store->store = run->storage;
916 pm_strcpy(store->store_source, _("Run storage override"));
919 if (job->pool->storage) {
920 store->store = (STORE *)job->pool->storage->first();
921 pm_strcpy(store->store_source, _("Pool resource"));
923 store->store = (STORE *)job->storage->first();
924 pm_strcpy(store->store_source, _("Job resource"));
929 * Set some defaults in the JCR necessary to
930 * run. These items are pulled from the job
931 * definition as defaults, but can be overridden
932 * later either by the Run record in the Schedule resource,
933 * or by the Console program.
935 void set_jcr_defaults(JCR *jcr, JOB *job)
938 jcr->JobType = job->JobType;
939 switch (jcr->JobType) {
942 jcr->JobLevel = L_NONE;
945 jcr->JobLevel = job->JobLevel;
949 jcr->fname = get_pool_memory(PM_FNAME);
951 if (!jcr->pool_source) {
952 jcr->pool_source = get_pool_memory(PM_MESSAGE);
953 pm_strcpy(jcr->pool_source, _("unknown source"));
955 jcr->JobPriority = job->Priority;
956 /* Copy storage definitions -- deleted in dir_free_jcr above */
958 copy_rwstorage(jcr, job->storage, _("Job resource"));
960 copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
962 jcr->client = job->client;
963 if (!jcr->client_name) {
964 jcr->client_name = get_pool_memory(PM_NAME);
966 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
967 pm_strcpy(jcr->pool_source, _("Job resource"));
968 jcr->pool = job->pool;
969 jcr->full_pool = job->full_pool;
970 jcr->inc_pool = job->inc_pool;
971 jcr->diff_pool = job->diff_pool;
972 jcr->catalog = job->client->catalog;
973 jcr->fileset = job->fileset;
974 jcr->messages = job->messages;
975 jcr->spool_data = job->spool_data;
976 jcr->write_part_after_job = job->write_part_after_job;
977 if (jcr->RestoreBootstrap) {
978 free(jcr->RestoreBootstrap);
979 jcr->RestoreBootstrap = NULL;
981 /* This can be overridden by Console program */
982 if (job->RestoreBootstrap) {
983 jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
985 /* This can be overridden by Console program */
986 jcr->verify_job = job->verify_job;
987 /* If no default level given, set one */
988 if (jcr->JobLevel == 0) {
989 switch (jcr->JobType) {
991 jcr->JobLevel = L_VERIFY_CATALOG;
994 jcr->JobLevel = L_INCREMENTAL;
998 jcr->JobLevel = L_NONE;
1001 jcr->JobLevel = L_FULL;
1008 * Copy the storage definitions from an alist to the JCR
1010 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1012 switch(jcr->JobType) {
1016 copy_rstorage(jcr, storage, where);
1019 copy_wstorage(jcr, storage, where);
1025 /* Set storage override */
1026 void set_rwstorage(JCR *jcr, USTORE *store)
1029 Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1032 switch(jcr->JobType) {
1036 set_rstorage(jcr, store);
1039 set_wstorage(jcr, store);
1044 void free_rwstorage(JCR *jcr)
1051 * Copy the storage definitions from an alist to the JCR
1053 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1057 if (jcr->rstorage) {
1058 delete jcr->rstorage;
1060 jcr->rstorage = New(alist(10, not_owned_by_alist));
1061 foreach_alist(st, storage) {
1062 jcr->rstorage->append(st);
1064 if (!jcr->rstore_source) {
1065 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1067 pm_strcpy(jcr->rstore_source, where);
1068 if (jcr->rstorage) {
1069 jcr->rstore = (STORE *)jcr->rstorage->first();
1075 /* Set storage override */
1076 void set_rstorage(JCR *jcr, USTORE *store)
1080 if (!store->store) {
1083 if (!jcr->rstorage) {
1084 jcr->rstorage = New(alist(10, not_owned_by_alist));
1086 jcr->rstore = store->store;
1087 if (!jcr->rstore_source) {
1088 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1090 pm_strcpy(jcr->rstore_source, store->store_source);
1091 foreach_alist(storage, jcr->rstorage) {
1092 if (store->store == storage) {
1096 /* Store not in list, so add it */
1097 jcr->rstorage->prepend(store->store);
1100 void free_rstorage(JCR *jcr)
1102 if (jcr->rstorage) {
1103 delete jcr->rstorage;
1104 jcr->rstorage = NULL;
1110 * Copy the storage definitions from an alist to the JCR
1112 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1116 if (jcr->wstorage) {
1117 delete jcr->wstorage;
1119 jcr->wstorage = New(alist(10, not_owned_by_alist));
1120 foreach_alist(st, storage) {
1121 Dmsg1(50, "storage=%s\n", st->name());
1122 jcr->wstorage->append(st);
1124 if (!jcr->wstore_source) {
1125 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1127 pm_strcpy(jcr->wstore_source, where);
1128 if (jcr->wstorage) {
1129 jcr->wstore = (STORE *)jcr->wstorage->first();
1130 Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1136 /* Set storage override */
1137 void set_wstorage(JCR *jcr, USTORE *store)
1141 if (!store->store) {
1144 if (!jcr->wstorage) {
1145 jcr->wstorage = New(alist(10, not_owned_by_alist));
1147 jcr->wstore = store->store;
1148 if (!jcr->wstore_source) {
1149 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1151 pm_strcpy(jcr->wstore_source, store->store_source);
1152 Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1153 foreach_alist(storage, jcr->wstorage) {
1154 if (store->store == storage) {
1158 /* Store not in list, so add it */
1159 jcr->wstorage->prepend(store->store);
1162 void free_wstorage(JCR *jcr)
1164 if (jcr->wstorage) {
1165 delete jcr->wstorage;
1166 jcr->wstorage = NULL;
1171 void create_clones(JCR *jcr)
1174 * Fire off any clone jobs (run directives)
1176 Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1177 if (!jcr->cloned && jcr->job->run_cmds) {
1179 JOB *job = jcr->job;
1180 POOLMEM *cmd = get_pool_memory(PM_FNAME);
1181 UAContext *ua = new_ua_context(jcr);
1183 foreach_alist(runcmd, job->run_cmds) {
1184 cmd = edit_job_codes(jcr, cmd, runcmd, "");
1185 Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1186 Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1187 parse_ua_args(ua); /* parse command */
1188 int stat = run_cmd(ua, ua->cmd);
1190 Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1192 Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1195 free_ua_context(ua);
1196 free_pool_memory(cmd);
1200 bool create_restore_bootstrap_file(JCR *jcr)
1204 memset(&rx, 0, sizeof(rx));
1207 rx.bsr->JobId = jcr->previous_jr.JobId;
1208 ua = new_ua_context(jcr);
1209 complete_bsr(ua, rx.bsr);
1210 rx.bsr->fi = new_findex();
1211 rx.bsr->fi->findex = 1;
1212 rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1213 jcr->ExpectedFiles = write_bsr_file(ua, rx);
1214 if (jcr->ExpectedFiles == 0) {
1215 free_ua_context(ua);
1219 free_ua_context(ua);
1221 jcr->needs_sd = true;