3 * Bacula Director Job processing routines
5 * Kern Sibbald, October MM
10 Bacula® - The Network Backup Solution
12 Copyright (C) 2000-2007 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 (!get_or_create_client_record(jcr)) {
163 if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
164 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
167 jcr->JobId = jcr->jr.JobId;
168 Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
169 jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
171 generate_daemon_event(jcr, "JobStart");
173 if (job_canceled(jcr)) {
178 * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
179 * this allows us to setup a proper job start record for restarting
180 * in case of later errors.
182 switch (jcr->JobType) {
184 if (!do_backup_init(jcr)) {
185 backup_cleanup(jcr, JS_ErrorTerminated);
189 if (!do_verify_init(jcr)) {
190 verify_cleanup(jcr, JS_ErrorTerminated);
194 if (!do_restore_init(jcr)) {
195 restore_cleanup(jcr, JS_ErrorTerminated);
199 if (!do_admin_init(jcr)) {
200 admin_cleanup(jcr, JS_ErrorTerminated);
204 if (!do_migration_init(jcr)) {
205 migration_cleanup(jcr, JS_ErrorTerminated);
209 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
210 set_jcr_job_status(jcr, JS_ErrorTerminated);
214 generate_job_event(jcr, "JobInit");
221 void update_job_end(JCR *jcr, int TermCode)
223 dequeue_messages(jcr); /* display any queued messages */
224 set_jcr_job_status(jcr, TermCode);
225 run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
226 update_job_end_record(jcr);
230 * This is the engine called by jobq.c:jobq_add() when we were pulled
231 * from the work queue.
232 * At this point, we are running in our own thread and all
233 * necessary resources are allocated -- see jobq.c
235 static void *job_thread(void *arg)
237 JCR *jcr = (JCR *)arg;
239 jcr->my_thread_id = pthread_self();
240 pthread_detach(jcr->my_thread_id);
241 sm_check(__FILE__, __LINE__, true);
243 Dmsg0(200, "=====Start Job=========\n");
244 set_jcr_job_status(jcr, JS_Running); /* this will be set only if no error */
245 jcr->start_time = time(NULL); /* set the real start time */
246 jcr->jr.StartTime = jcr->start_time;
248 if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
249 (utime_t)(jcr->start_time - jcr->sched_time)) {
250 set_jcr_job_status(jcr, JS_Canceled);
251 Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
254 /* TODO : check if it is used somewhere */
255 if (jcr->job->RunScripts == NULL) {
256 Dmsg0(200, "Warning, job->RunScripts is empty\n");
257 jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
260 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
261 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
264 /* Run any script BeforeJob on dird */
265 run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
267 if (job_canceled(jcr)) {
268 update_job_end(jcr, jcr->JobStatus);
272 * We re-update the job start record so that the start
273 * time is set after the run before job. This avoids
274 * that any files created by the run before job will
275 * be saved twice. They will be backed up in the current
276 * job, but not in the next one unless they are changed.
277 * Without this, they will be backed up in this job and
278 * in the next job run because in that case, their date
279 * is after the start of this run.
281 jcr->start_time = time(NULL);
282 jcr->jr.StartTime = jcr->start_time;
283 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
284 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
286 generate_job_event(jcr, "JobRun");
288 switch (jcr->JobType) {
290 if (do_backup(jcr)) {
293 backup_cleanup(jcr, JS_ErrorTerminated);
297 if (do_verify(jcr)) {
300 verify_cleanup(jcr, JS_ErrorTerminated);
304 if (do_restore(jcr)) {
307 restore_cleanup(jcr, JS_ErrorTerminated);
314 admin_cleanup(jcr, JS_ErrorTerminated);
320 if (do_migration(jcr)) {
323 migration_cleanup(jcr, JS_ErrorTerminated);
327 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
331 /* Send off any queued messages */
332 if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
333 dequeue_messages(jcr);
337 generate_daemon_event(jcr, "JobEnd");
338 Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
339 sm_check(__FILE__, __LINE__, true);
345 * Cancel a job -- typically called by the UA (Console program), but may also
346 * be called by the job watchdog.
348 * Returns: true if cancel appears to be successful
349 * false on failure. Message sent to ua->jcr.
351 bool cancel_job(UAContext *ua, JCR *jcr)
356 set_jcr_job_status(jcr, JS_Canceled);
358 switch (jcr->JobStatus) {
361 case JS_WaitClientRes:
362 case JS_WaitStoreRes:
363 case JS_WaitPriority:
365 case JS_WaitStartTime:
366 bsendmsg(ua, _("JobId %s, Job %s marked to be canceled.\n"),
367 edit_uint64(jcr->JobId, ed1), jcr->Job);
368 jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
372 /* Cancel File daemon */
373 if (jcr->file_bsock) {
374 ua->jcr->client = jcr->client;
375 if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
376 bsendmsg(ua, _("Failed to connect to File daemon.\n"));
379 Dmsg0(200, "Connected to file daemon\n");
380 fd = ua->jcr->file_bsock;
381 bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
382 while (bnet_recv(fd) >= 0) {
383 bsendmsg(ua, "%s", fd->msg);
385 bnet_sig(fd, BNET_TERMINATE);
387 ua->jcr->file_bsock = NULL;
390 /* Cancel Storage daemon */
391 if (jcr->store_bsock) {
392 if (!ua->jcr->wstorage) {
394 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
396 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
401 store.store = jcr->rstore;
403 store.store = jcr->wstore;
405 set_wstorage(ua->jcr, &store);
408 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
409 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
412 Dmsg0(200, "Connected to storage daemon\n");
413 sd = ua->jcr->store_bsock;
414 bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
415 while (bnet_recv(sd) >= 0) {
416 bsendmsg(ua, "%s", sd->msg);
418 bnet_sig(sd, BNET_TERMINATE);
420 ua->jcr->store_bsock = NULL;
428 static void job_monitor_destructor(watchdog_t *self)
430 JCR *control_jcr = (JCR *)self->data;
432 free_jcr(control_jcr);
435 static void job_monitor_watchdog(watchdog_t *self)
437 JCR *control_jcr, *jcr;
439 control_jcr = (JCR *)self->data;
441 Dmsg1(800, "job_monitor_watchdog %p called\n", self);
446 if (jcr->JobId == 0 || job_canceled(jcr)) {
447 Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
451 /* check MaxWaitTime */
452 if (job_check_maxwaittime(control_jcr, jcr)) {
453 set_jcr_job_status(jcr, JS_Canceled);
454 Jmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
456 /* check MaxRunTime */
457 } else if (job_check_maxruntime(control_jcr, jcr)) {
458 set_jcr_job_status(jcr, JS_Canceled);
459 Jmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
464 Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
465 UAContext *ua = new_ua_context(jcr);
466 ua->jcr = control_jcr;
469 Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
473 /* Keep reference counts correct */
478 * Check if the maxwaittime has expired and it is possible
481 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
484 bool ok_to_cancel = false;
487 if (job_canceled(jcr)) {
488 return false; /* already canceled */
490 if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
491 job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
494 if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
495 (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
497 } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
498 (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
500 } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
501 (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
503 } else if (job->MaxWaitTime != 0 &&
504 (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
512 * I don't see the need for all this -- kes 17Dec06
515 Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, "
517 jcr->JobId, jcr->Job, job->MaxWaitTime);
518 switch (jcr->JobStatus) {
523 case JS_WaitStoreRes:
524 case JS_WaitClientRes:
526 case JS_WaitPriority:
528 case JS_WaitStartTime:
530 Dmsg0(200, "JCR blocked in #1\n");
533 Dmsg0(800, "JCR running, checking SD status\n");
534 switch (jcr->SDJobStatus) {
539 Dmsg0(800, "JCR blocked in #2\n");
542 Dmsg0(800, "JCR not blocked in #2\n");
547 case JS_ErrorTerminated:
550 Dmsg0(800, "JCR already dead in #3\n");
553 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
556 Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n",
557 cancel ? "" : "do not ", jcr, jcr->Job);
563 * Check if maxruntime has expired and if the job can be
566 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
568 if (jcr->job->MaxRunTime == 0 || job_canceled(jcr)) {
571 if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
572 Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
573 jcr, jcr->Job, jcr->job->MaxRunTime);
578 switch (jcr->JobStatus) {
584 case JS_WaitStoreRes:
585 case JS_WaitClientRes:
587 case JS_WaitPriority:
589 case JS_WaitStartTime:
594 case JS_ErrorTerminated:
600 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
604 Dmsg3(200, "MaxRunTime result: %scancel JCR %p (%s)\n",
605 cancel ? "" : "do not ", jcr, jcr->Job);
611 * Get or create a Pool record with the given name.
612 * Returns: 0 on error
615 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
619 memset(&pr, 0, sizeof(pr));
620 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
621 Dmsg1(010, "get_or_create_pool=%s\n", pool_name);
623 while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
624 /* Try to create the pool */
625 if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
626 Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
627 db_strerror(jcr->db));
630 Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
636 void apply_pool_overrides(JCR *jcr)
638 if (jcr->run_pool_override) {
639 pm_strcpy(jcr->pool_source, _("Run pool override"));
642 * Apply any level related Pool selections
644 switch (jcr->JobLevel) {
646 if (jcr->full_pool) {
647 jcr->pool = jcr->full_pool;
648 if (jcr->run_full_pool_override) {
649 pm_strcpy(jcr->pool_source, _("Run FullPool override"));
651 pm_strcpy(jcr->pool_source, _("Job FullPool override"));
657 jcr->pool = jcr->inc_pool;
658 if (jcr->run_inc_pool_override) {
659 pm_strcpy(jcr->pool_source, _("Run IncPool override"));
661 pm_strcpy(jcr->pool_source, _("Job IncPool override"));
666 if (jcr->diff_pool) {
667 jcr->pool = jcr->diff_pool;
668 if (jcr->run_diff_pool_override) {
669 pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
671 pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
680 * Get or create a Client record for this Job
682 bool get_or_create_client_record(JCR *jcr)
686 memset(&cr, 0, sizeof(cr));
687 bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
688 cr.AutoPrune = jcr->client->AutoPrune;
689 cr.FileRetention = jcr->client->FileRetention;
690 cr.JobRetention = jcr->client->JobRetention;
691 if (!jcr->client_name) {
692 jcr->client_name = get_pool_memory(PM_NAME);
694 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
695 if (!db_create_client_record(jcr, jcr->db, &cr)) {
696 Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
697 db_strerror(jcr->db));
700 jcr->jr.ClientId = cr.ClientId;
702 if (!jcr->client_uname) {
703 jcr->client_uname = get_pool_memory(PM_NAME);
705 pm_strcpy(jcr->client_uname, cr.Uname);
707 Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
712 bool get_or_create_fileset_record(JCR *jcr)
716 * Get or Create FileSet record
718 memset(&fsr, 0, sizeof(FILESET_DBR));
719 bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
720 if (jcr->fileset->have_MD5) {
721 struct MD5Context md5c;
722 unsigned char digest[MD5HashSize];
723 memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
724 MD5Final(digest, &md5c);
726 * Keep the flag (last arg) set to false otherwise old FileSets will
727 * get new MD5 sums and the user will get Full backups on everything
729 bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
730 bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
732 Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
734 if (!jcr->fileset->ignore_fs_changes ||
735 !db_get_fileset_record(jcr, jcr->db, &fsr)) {
736 if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
737 Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
738 fsr.FileSet, db_strerror(jcr->db));
742 jcr->jr.FileSetId = fsr.FileSetId;
743 bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
744 Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
749 void init_jcr_job_record(JCR *jcr)
751 jcr->jr.SchedTime = jcr->sched_time;
752 jcr->jr.StartTime = jcr->start_time;
753 jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
754 jcr->jr.JobType = jcr->JobType;
755 jcr->jr.JobLevel = jcr->JobLevel;
756 jcr->jr.JobStatus = jcr->JobStatus;
757 jcr->jr.JobId = jcr->JobId;
758 bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
759 bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
763 * Write status and such in DB
765 void update_job_end_record(JCR *jcr)
767 jcr->jr.EndTime = time(NULL);
768 jcr->end_time = jcr->jr.EndTime;
769 jcr->jr.JobId = jcr->JobId;
770 jcr->jr.JobStatus = jcr->JobStatus;
771 jcr->jr.JobFiles = jcr->JobFiles;
772 jcr->jr.JobBytes = jcr->JobBytes;
773 jcr->jr.VolSessionId = jcr->VolSessionId;
774 jcr->jr.VolSessionTime = jcr->VolSessionTime;
775 jcr->jr.JobErrors = jcr->Errors;
776 if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
777 Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
778 db_strerror(jcr->db));
783 * Takes base_name and appends (unique) current
784 * date and time to form unique job name.
786 * Returns: unique job name in jcr->Job
787 * date/time in jcr->start_time
789 void create_unique_job_name(JCR *jcr, const char *base_name)
791 /* Job start mutex */
792 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
793 static time_t last_start_time = 0;
796 char dt[MAX_TIME_LENGTH];
797 char name[MAX_NAME_LENGTH];
800 /* Guarantee unique start time -- maximum one per second, and
801 * thus unique Job Name
803 P(mutex); /* lock creation of jobs */
805 while (now == last_start_time) {
806 bmicrosleep(0, 500000);
809 last_start_time = now;
810 V(mutex); /* allow creation of jobs */
811 jcr->start_time = now;
812 /* Form Unique JobName */
813 (void)localtime_r(&now, &tm);
814 /* Use only characters that are permitted in Windows filenames */
815 strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
816 bstrncpy(name, base_name, sizeof(name));
817 name[sizeof(name)-22] = 0; /* truncate if too long */
818 bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
819 /* Convert spaces into underscores */
820 for (p=jcr->Job; *p; p++) {
827 /* Called directly from job rescheduling */
828 void dird_free_jcr_pointers(JCR *jcr)
830 if (jcr->sd_auth_key) {
831 free(jcr->sd_auth_key);
832 jcr->sd_auth_key = NULL;
838 if (jcr->file_bsock) {
839 Dmsg0(200, "Close File bsock\n");
840 bnet_close(jcr->file_bsock);
841 jcr->file_bsock = NULL;
843 if (jcr->store_bsock) {
844 Dmsg0(200, "Close Store bsock\n");
845 bnet_close(jcr->store_bsock);
846 jcr->store_bsock = NULL;
849 Dmsg0(200, "Free JCR fname\n");
850 free_pool_memory(jcr->fname);
853 if (jcr->RestoreBootstrap) {
854 free(jcr->RestoreBootstrap);
855 jcr->RestoreBootstrap = NULL;
857 if (jcr->client_uname) {
858 free_pool_memory(jcr->client_uname);
859 jcr->client_uname = NULL;
862 free_pool_memory(jcr->attr);
872 * Free the Job Control Record if no one is still using it.
873 * Called from main free_jcr() routine in src/lib/jcr.c so
874 * that we can do our Director specific cleanup of the jcr.
876 void dird_free_jcr(JCR *jcr)
878 Dmsg0(200, "Start dird free_jcr\n");
880 dird_free_jcr_pointers(jcr);
881 if (jcr->term_wait_inited) {
882 pthread_cond_destroy(&jcr->term_wait);
883 jcr->term_wait_inited = false;
886 db_close_database(jcr, jcr->db);
890 db_close_database(jcr, jcr->db_batch);
891 jcr->db_batch = NULL;
894 Dmsg0(200, "Free JCR stime\n");
895 free_pool_memory(jcr->stime);
899 Dmsg0(200, "Free JCR fname\n");
900 free_pool_memory(jcr->fname);
903 if (jcr->pool_source) {
904 free_pool_memory(jcr->pool_source);
905 jcr->pool_source = NULL;
907 if (jcr->rpool_source) {
908 free_pool_memory(jcr->rpool_source);
909 jcr->rpool_source = NULL;
911 if (jcr->wstore_source) {
912 free_pool_memory(jcr->wstore_source);
913 jcr->wstore_source = NULL;
915 if (jcr->rstore_source) {
916 free_pool_memory(jcr->rstore_source);
917 jcr->rstore_source = NULL;
920 /* Delete lists setup to hold storage pointers */
923 jcr->job_end_push.destroy();
924 Dmsg0(200, "End dird free_jcr\n");
928 * The Job storage definition must be either in the Job record
929 * or in the Pool record. The Pool record overrides the Job
932 void get_job_storage(USTORE *store, JOB *job, RUN *run)
934 if (run && run->pool && run->pool->storage) {
935 store->store = (STORE *)run->pool->storage->first();
936 pm_strcpy(store->store_source, _("Run pool override"));
939 if (run && run->storage) {
940 store->store = run->storage;
941 pm_strcpy(store->store_source, _("Run storage override"));
944 if (job->pool->storage) {
945 store->store = (STORE *)job->pool->storage->first();
946 pm_strcpy(store->store_source, _("Pool resource"));
948 store->store = (STORE *)job->storage->first();
949 pm_strcpy(store->store_source, _("Job resource"));
954 * Set some defaults in the JCR necessary to
955 * run. These items are pulled from the job
956 * definition as defaults, but can be overridden
957 * later either by the Run record in the Schedule resource,
958 * or by the Console program.
960 void set_jcr_defaults(JCR *jcr, JOB *job)
963 jcr->JobType = job->JobType;
964 switch (jcr->JobType) {
967 jcr->JobLevel = L_NONE;
970 if (!jcr->rpool_source) {
971 jcr->rpool_source = get_pool_memory(PM_MESSAGE);
972 pm_strcpy(jcr->rpool_source, _("unknown source"));
974 /* Fall-through wanted */
976 jcr->JobLevel = job->JobLevel;
980 jcr->fname = get_pool_memory(PM_FNAME);
982 if (!jcr->pool_source) {
983 jcr->pool_source = get_pool_memory(PM_MESSAGE);
984 pm_strcpy(jcr->pool_source, _("unknown source"));
987 jcr->JobPriority = job->Priority;
988 /* Copy storage definitions -- deleted in dir_free_jcr above */
990 copy_rwstorage(jcr, job->storage, _("Job resource"));
992 copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
994 jcr->client = job->client;
995 if (!jcr->client_name) {
996 jcr->client_name = get_pool_memory(PM_NAME);
998 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
999 pm_strcpy(jcr->pool_source, _("Job resource"));
1000 jcr->pool = job->pool;
1001 jcr->full_pool = job->full_pool;
1002 jcr->inc_pool = job->inc_pool;
1003 jcr->diff_pool = job->diff_pool;
1004 jcr->catalog = job->client->catalog;
1005 jcr->fileset = job->fileset;
1006 jcr->messages = job->messages;
1007 jcr->spool_data = job->spool_data;
1008 jcr->write_part_after_job = job->write_part_after_job;
1009 if (jcr->RestoreBootstrap) {
1010 free(jcr->RestoreBootstrap);
1011 jcr->RestoreBootstrap = NULL;
1013 /* This can be overridden by Console program */
1014 if (job->RestoreBootstrap) {
1015 jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1017 /* This can be overridden by Console program */
1018 jcr->verify_job = job->verify_job;
1019 /* If no default level given, set one */
1020 if (jcr->JobLevel == 0) {
1021 switch (jcr->JobType) {
1023 jcr->JobLevel = L_VERIFY_CATALOG;
1026 jcr->JobLevel = L_INCREMENTAL;
1030 jcr->JobLevel = L_NONE;
1033 jcr->JobLevel = L_FULL;
1040 * Copy the storage definitions from an alist to the JCR
1042 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1044 switch(jcr->JobType) {
1048 copy_rstorage(jcr, storage, where);
1051 copy_wstorage(jcr, storage, where);
1057 /* Set storage override */
1058 void set_rwstorage(JCR *jcr, USTORE *store)
1061 Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1064 switch(jcr->JobType) {
1068 set_rstorage(jcr, store);
1071 set_wstorage(jcr, store);
1076 void free_rwstorage(JCR *jcr)
1083 * Copy the storage definitions from an alist to the JCR
1085 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1089 if (jcr->rstorage) {
1090 delete jcr->rstorage;
1092 jcr->rstorage = New(alist(10, not_owned_by_alist));
1093 foreach_alist(st, storage) {
1094 jcr->rstorage->append(st);
1096 if (!jcr->rstore_source) {
1097 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1099 pm_strcpy(jcr->rstore_source, where);
1100 if (jcr->rstorage) {
1101 jcr->rstore = (STORE *)jcr->rstorage->first();
1107 /* Set storage override */
1108 void set_rstorage(JCR *jcr, USTORE *store)
1112 if (!store->store) {
1115 if (!jcr->rstorage) {
1116 jcr->rstorage = New(alist(10, not_owned_by_alist));
1118 jcr->rstore = store->store;
1119 if (!jcr->rstore_source) {
1120 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1122 pm_strcpy(jcr->rstore_source, store->store_source);
1123 foreach_alist(storage, jcr->rstorage) {
1124 if (store->store == storage) {
1128 /* Store not in list, so add it */
1129 jcr->rstorage->prepend(store->store);
1132 void free_rstorage(JCR *jcr)
1134 if (jcr->rstorage) {
1135 delete jcr->rstorage;
1136 jcr->rstorage = NULL;
1142 * Copy the storage definitions from an alist to the JCR
1144 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1148 if (jcr->wstorage) {
1149 delete jcr->wstorage;
1151 jcr->wstorage = New(alist(10, not_owned_by_alist));
1152 foreach_alist(st, storage) {
1153 Dmsg1(50, "storage=%s\n", st->name());
1154 jcr->wstorage->append(st);
1156 if (!jcr->wstore_source) {
1157 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1159 pm_strcpy(jcr->wstore_source, where);
1160 if (jcr->wstorage) {
1161 jcr->wstore = (STORE *)jcr->wstorage->first();
1162 Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1168 /* Set storage override */
1169 void set_wstorage(JCR *jcr, USTORE *store)
1173 if (!store->store) {
1176 if (!jcr->wstorage) {
1177 jcr->wstorage = New(alist(10, not_owned_by_alist));
1179 jcr->wstore = store->store;
1180 if (!jcr->wstore_source) {
1181 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1183 pm_strcpy(jcr->wstore_source, store->store_source);
1184 Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1185 foreach_alist(storage, jcr->wstorage) {
1186 if (store->store == storage) {
1190 /* Store not in list, so add it */
1191 jcr->wstorage->prepend(store->store);
1194 void free_wstorage(JCR *jcr)
1196 if (jcr->wstorage) {
1197 delete jcr->wstorage;
1198 jcr->wstorage = NULL;
1203 void create_clones(JCR *jcr)
1206 * Fire off any clone jobs (run directives)
1208 Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1209 if (!jcr->cloned && jcr->job->run_cmds) {
1211 JOB *job = jcr->job;
1212 POOLMEM *cmd = get_pool_memory(PM_FNAME);
1213 UAContext *ua = new_ua_context(jcr);
1215 foreach_alist(runcmd, job->run_cmds) {
1216 cmd = edit_job_codes(jcr, cmd, runcmd, "");
1217 Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1218 Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1219 parse_ua_args(ua); /* parse command */
1220 int stat = run_cmd(ua, ua->cmd);
1222 Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1224 Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1227 free_ua_context(ua);
1228 free_pool_memory(cmd);
1232 bool create_restore_bootstrap_file(JCR *jcr)
1236 memset(&rx, 0, sizeof(rx));
1239 rx.bsr->JobId = jcr->previous_jr.JobId;
1240 ua = new_ua_context(jcr);
1241 complete_bsr(ua, rx.bsr);
1242 rx.bsr->fi = new_findex();
1243 rx.bsr->fi->findex = 1;
1244 rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1245 jcr->ExpectedFiles = write_bsr_file(ua, rx);
1246 if (jcr->ExpectedFiles == 0) {
1247 free_ua_context(ua);
1251 free_ua_context(ua);
1253 jcr->needs_sd = true;