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)) {
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;
402 pm_strcpy(store.store_source, jcr->rstore_source);
404 store.store = jcr->wstore;
405 pm_strcpy(store.store_source, jcr->wstore_source);
407 set_wstorage(ua->jcr, &store);
410 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
411 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
414 Dmsg0(200, "Connected to storage daemon\n");
415 sd = ua->jcr->store_bsock;
416 bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
417 while (bnet_recv(sd) >= 0) {
418 bsendmsg(ua, "%s", sd->msg);
420 bnet_sig(sd, BNET_TERMINATE);
422 ua->jcr->store_bsock = NULL;
430 static void job_monitor_destructor(watchdog_t *self)
432 JCR *control_jcr = (JCR *)self->data;
434 free_jcr(control_jcr);
437 static void job_monitor_watchdog(watchdog_t *self)
439 JCR *control_jcr, *jcr;
441 control_jcr = (JCR *)self->data;
443 Dmsg1(800, "job_monitor_watchdog %p called\n", self);
448 if (jcr->JobId == 0 || job_canceled(jcr)) {
449 Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
453 /* check MaxWaitTime */
454 if (job_check_maxwaittime(control_jcr, jcr)) {
455 set_jcr_job_status(jcr, JS_Canceled);
456 Jmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
458 /* check MaxRunTime */
459 } else if (job_check_maxruntime(control_jcr, jcr)) {
460 set_jcr_job_status(jcr, JS_Canceled);
461 Jmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
466 Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
467 UAContext *ua = new_ua_context(jcr);
468 ua->jcr = control_jcr;
471 Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
475 /* Keep reference counts correct */
480 * Check if the maxwaittime has expired and it is possible
483 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
486 bool ok_to_cancel = false;
489 if (job_canceled(jcr)) {
490 return false; /* already canceled */
492 if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
493 job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
496 if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
497 (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
499 } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
500 (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
502 } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
503 (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
505 } else if (job->MaxWaitTime != 0 &&
506 (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
514 * I don't see the need for all this -- kes 17Dec06
517 Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, "
519 jcr->JobId, jcr->Job, job->MaxWaitTime);
520 switch (jcr->JobStatus) {
525 case JS_WaitStoreRes:
526 case JS_WaitClientRes:
528 case JS_WaitPriority:
530 case JS_WaitStartTime:
532 Dmsg0(200, "JCR blocked in #1\n");
535 Dmsg0(800, "JCR running, checking SD status\n");
536 switch (jcr->SDJobStatus) {
541 Dmsg0(800, "JCR blocked in #2\n");
544 Dmsg0(800, "JCR not blocked in #2\n");
549 case JS_ErrorTerminated:
552 Dmsg0(800, "JCR already dead in #3\n");
555 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
558 Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n",
559 cancel ? "" : "do not ", jcr, jcr->job);
565 * Check if maxruntime has expired and if the job can be
568 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
572 if (jcr->job->MaxRunTime == 0 || job_canceled(jcr)) {
575 if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
576 Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
577 jcr, jcr->Job, jcr->job->MaxRunTime);
582 switch (jcr->JobStatus) {
588 case JS_WaitStoreRes:
589 case JS_WaitClientRes:
591 case JS_WaitPriority:
593 case JS_WaitStartTime:
598 case JS_ErrorTerminated:
604 Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
608 Dmsg3(200, "MaxRunTime result: %scancel JCR %p (%s)\n",
609 cancel ? "" : "do not ", jcr, jcr->job);
615 * Get or create a Pool record with the given name.
616 * Returns: 0 on error
619 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
623 memset(&pr, 0, sizeof(pr));
624 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
625 Dmsg1(010, "get_or_create_pool=%s\n", pool_name);
627 while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
628 /* Try to create the pool */
629 if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
630 Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
631 db_strerror(jcr->db));
634 Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
640 void apply_pool_overrides(JCR *jcr)
642 if (jcr->run_pool_override) {
643 pm_strcpy(jcr->pool_source, _("Run pool override"));
646 * Apply any level related Pool selections
648 switch (jcr->JobLevel) {
650 if (jcr->full_pool) {
651 jcr->pool = jcr->full_pool;
652 if (jcr->run_full_pool_override) {
653 pm_strcpy(jcr->pool_source, _("Run FullPool override"));
655 pm_strcpy(jcr->pool_source, _("Job FullPool override"));
661 jcr->pool = jcr->inc_pool;
662 if (jcr->run_inc_pool_override) {
663 pm_strcpy(jcr->pool_source, _("Run IncPool override"));
665 pm_strcpy(jcr->pool_source, _("Job IncPool override"));
670 if (jcr->diff_pool) {
671 jcr->pool = jcr->diff_pool;
672 if (jcr->run_diff_pool_override) {
673 pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
675 pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
684 * Get or create a Client record for this Job
686 bool get_or_create_client_record(JCR *jcr)
690 memset(&cr, 0, sizeof(cr));
691 bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
692 cr.AutoPrune = jcr->client->AutoPrune;
693 cr.FileRetention = jcr->client->FileRetention;
694 cr.JobRetention = jcr->client->JobRetention;
695 if (!jcr->client_name) {
696 jcr->client_name = get_pool_memory(PM_NAME);
698 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
699 if (!db_create_client_record(jcr, jcr->db, &cr)) {
700 Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
701 db_strerror(jcr->db));
704 jcr->jr.ClientId = cr.ClientId;
706 if (!jcr->client_uname) {
707 jcr->client_uname = get_pool_memory(PM_NAME);
709 pm_strcpy(jcr->client_uname, cr.Uname);
711 Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
716 bool get_or_create_fileset_record(JCR *jcr)
720 * Get or Create FileSet record
722 memset(&fsr, 0, sizeof(FILESET_DBR));
723 bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
724 if (jcr->fileset->have_MD5) {
725 struct MD5Context md5c;
726 unsigned char digest[MD5HashSize];
727 memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
728 MD5Final(digest, &md5c);
730 * Keep the flag (last arg) set to false otherwise old FileSets will
731 * get new MD5 sums and the user will get Full backups on everything
733 bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
734 bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
736 Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
738 if (!jcr->fileset->ignore_fs_changes ||
739 !db_get_fileset_record(jcr, jcr->db, &fsr)) {
740 if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
741 Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
742 fsr.FileSet, db_strerror(jcr->db));
746 jcr->jr.FileSetId = fsr.FileSetId;
747 bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
748 Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
753 void init_jcr_job_record(JCR *jcr)
755 jcr->jr.SchedTime = jcr->sched_time;
756 jcr->jr.StartTime = jcr->start_time;
757 jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
758 jcr->jr.JobType = jcr->JobType;
759 jcr->jr.JobLevel = jcr->JobLevel;
760 jcr->jr.JobStatus = jcr->JobStatus;
761 jcr->jr.JobId = jcr->JobId;
762 bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
763 bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
767 * Write status and such in DB
769 void update_job_end_record(JCR *jcr)
771 jcr->jr.EndTime = time(NULL);
772 jcr->end_time = jcr->jr.EndTime;
773 jcr->jr.JobId = jcr->JobId;
774 jcr->jr.JobStatus = jcr->JobStatus;
775 jcr->jr.JobFiles = jcr->JobFiles;
776 jcr->jr.JobBytes = jcr->JobBytes;
777 jcr->jr.VolSessionId = jcr->VolSessionId;
778 jcr->jr.VolSessionTime = jcr->VolSessionTime;
779 jcr->jr.JobErrors = jcr->Errors;
780 if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
781 Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
782 db_strerror(jcr->db));
787 * Takes base_name and appends (unique) current
788 * date and time to form unique job name.
790 * Returns: unique job name in jcr->Job
791 * date/time in jcr->start_time
793 void create_unique_job_name(JCR *jcr, const char *base_name)
795 /* Job start mutex */
796 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
797 static time_t last_start_time = 0;
800 char dt[MAX_TIME_LENGTH];
801 char name[MAX_NAME_LENGTH];
804 /* Guarantee unique start time -- maximum one per second, and
805 * thus unique Job Name
807 P(mutex); /* lock creation of jobs */
809 while (now == last_start_time) {
810 bmicrosleep(0, 500000);
813 last_start_time = now;
814 V(mutex); /* allow creation of jobs */
815 jcr->start_time = now;
816 /* Form Unique JobName */
817 (void)localtime_r(&now, &tm);
818 /* Use only characters that are permitted in Windows filenames */
819 strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
820 bstrncpy(name, base_name, sizeof(name));
821 name[sizeof(name)-22] = 0; /* truncate if too long */
822 bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
823 /* Convert spaces into underscores */
824 for (p=jcr->Job; *p; p++) {
831 /* Called directly from job rescheduling */
832 void dird_free_jcr_pointers(JCR *jcr)
834 if (jcr->sd_auth_key) {
835 free(jcr->sd_auth_key);
836 jcr->sd_auth_key = NULL;
842 if (jcr->file_bsock) {
843 Dmsg0(200, "Close File bsock\n");
844 bnet_close(jcr->file_bsock);
845 jcr->file_bsock = NULL;
847 if (jcr->store_bsock) {
848 Dmsg0(200, "Close Store bsock\n");
849 bnet_close(jcr->store_bsock);
850 jcr->store_bsock = NULL;
853 Dmsg0(200, "Free JCR fname\n");
854 free_pool_memory(jcr->fname);
857 if (jcr->pool_source) {
858 free_pool_memory(jcr->pool_source);
859 jcr->pool_source = NULL;
861 if (jcr->rpool_source) {
862 free_pool_memory(jcr->rpool_source);
863 jcr->rpool_source = NULL;
865 if (jcr->wstore_source) {
866 free_pool_memory(jcr->wstore_source);
867 jcr->wstore_source = NULL;
869 if (jcr->rstore_source) {
870 free_pool_memory(jcr->rstore_source);
871 jcr->rstore_source = NULL;
874 Dmsg0(200, "Free JCR stime\n");
875 free_pool_memory(jcr->stime);
878 if (jcr->RestoreBootstrap) {
879 free(jcr->RestoreBootstrap);
880 jcr->RestoreBootstrap = NULL;
882 if (jcr->client_uname) {
883 free_pool_memory(jcr->client_uname);
884 jcr->client_uname = NULL;
887 free_pool_memory(jcr->attr);
897 * Free the Job Control Record if no one is still using it.
898 * Called from main free_jcr() routine in src/lib/jcr.c so
899 * that we can do our Director specific cleanup of the jcr.
901 void dird_free_jcr(JCR *jcr)
903 Dmsg0(200, "Start dird free_jcr\n");
905 dird_free_jcr_pointers(jcr);
906 if (jcr->term_wait_inited) {
907 pthread_cond_destroy(&jcr->term_wait);
908 jcr->term_wait_inited = false;
911 /* Delete lists setup to hold storage pointers */
914 jcr->job_end_push.destroy();
915 Dmsg0(200, "End dird free_jcr\n");
919 * The Job storage definition must be either in the Job record
920 * or in the Pool record. The Pool record overrides the Job
923 void get_job_storage(USTORE *store, JOB *job, RUN *run)
925 if (run && run->pool && run->pool->storage) {
926 store->store = (STORE *)run->pool->storage->first();
927 pm_strcpy(store->store_source, _("Run pool override"));
930 if (run && run->storage) {
931 store->store = run->storage;
932 pm_strcpy(store->store_source, _("Run storage override"));
935 if (job->pool->storage) {
936 store->store = (STORE *)job->pool->storage->first();
937 pm_strcpy(store->store_source, _("Pool resource"));
939 store->store = (STORE *)job->storage->first();
940 pm_strcpy(store->store_source, _("Job resource"));
945 * Set some defaults in the JCR necessary to
946 * run. These items are pulled from the job
947 * definition as defaults, but can be overridden
948 * later either by the Run record in the Schedule resource,
949 * or by the Console program.
951 void set_jcr_defaults(JCR *jcr, JOB *job)
954 jcr->JobType = job->JobType;
955 switch (jcr->JobType) {
958 jcr->JobLevel = L_NONE;
961 jcr->JobLevel = job->JobLevel;
965 jcr->fname = get_pool_memory(PM_FNAME);
967 if (!jcr->pool_source) {
968 jcr->pool_source = get_pool_memory(PM_MESSAGE);
969 pm_strcpy(jcr->pool_source, _("unknown source"));
971 jcr->JobPriority = job->Priority;
972 /* Copy storage definitions -- deleted in dir_free_jcr above */
974 copy_rwstorage(jcr, job->storage, _("Job resource"));
976 copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
978 jcr->client = job->client;
979 if (!jcr->client_name) {
980 jcr->client_name = get_pool_memory(PM_NAME);
982 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
983 pm_strcpy(jcr->pool_source, _("Job resource"));
984 jcr->pool = job->pool;
985 jcr->full_pool = job->full_pool;
986 jcr->inc_pool = job->inc_pool;
987 jcr->diff_pool = job->diff_pool;
988 jcr->catalog = job->client->catalog;
989 jcr->fileset = job->fileset;
990 jcr->messages = job->messages;
991 jcr->spool_data = job->spool_data;
992 jcr->write_part_after_job = job->write_part_after_job;
993 if (jcr->RestoreBootstrap) {
994 free(jcr->RestoreBootstrap);
995 jcr->RestoreBootstrap = NULL;
997 /* This can be overridden by Console program */
998 if (job->RestoreBootstrap) {
999 jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1001 /* This can be overridden by Console program */
1002 jcr->verify_job = job->verify_job;
1003 /* If no default level given, set one */
1004 if (jcr->JobLevel == 0) {
1005 switch (jcr->JobType) {
1007 jcr->JobLevel = L_VERIFY_CATALOG;
1010 jcr->JobLevel = L_INCREMENTAL;
1014 jcr->JobLevel = L_NONE;
1017 jcr->JobLevel = L_FULL;
1024 * Copy the storage definitions from an alist to the JCR
1026 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1028 switch(jcr->JobType) {
1032 copy_rstorage(jcr, storage, where);
1035 copy_wstorage(jcr, storage, where);
1041 /* Set storage override */
1042 void set_rwstorage(JCR *jcr, USTORE *store)
1045 Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1048 switch(jcr->JobType) {
1052 set_rstorage(jcr, store);
1055 set_wstorage(jcr, store);
1060 void free_rwstorage(JCR *jcr)
1067 * Copy the storage definitions from an alist to the JCR
1069 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1073 if (jcr->rstorage) {
1074 delete jcr->rstorage;
1076 jcr->rstorage = New(alist(10, not_owned_by_alist));
1077 foreach_alist(st, storage) {
1078 jcr->rstorage->append(st);
1080 if (!jcr->rstore_source) {
1081 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1083 pm_strcpy(jcr->rstore_source, where);
1084 if (jcr->rstorage) {
1085 jcr->rstore = (STORE *)jcr->rstorage->first();
1091 /* Set storage override */
1092 void set_rstorage(JCR *jcr, USTORE *store)
1096 if (!store->store) {
1099 if (!jcr->rstorage) {
1100 jcr->rstorage = New(alist(10, not_owned_by_alist));
1102 jcr->rstore = store->store;
1103 if (!jcr->rstore_source) {
1104 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1106 pm_strcpy(jcr->rstore_source, store->store_source);
1107 foreach_alist(storage, jcr->rstorage) {
1108 if (store->store == storage) {
1112 /* Store not in list, so add it */
1113 jcr->rstorage->prepend(store->store);
1116 void free_rstorage(JCR *jcr)
1118 if (jcr->rstorage) {
1119 delete jcr->rstorage;
1120 jcr->rstorage = NULL;
1126 * Copy the storage definitions from an alist to the JCR
1128 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1132 if (jcr->wstorage) {
1133 delete jcr->wstorage;
1135 jcr->wstorage = New(alist(10, not_owned_by_alist));
1136 foreach_alist(st, storage) {
1137 Dmsg1(50, "storage=%s\n", st->name());
1138 jcr->wstorage->append(st);
1140 if (!jcr->wstore_source) {
1141 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1143 pm_strcpy(jcr->wstore_source, where);
1144 if (jcr->wstorage) {
1145 jcr->wstore = (STORE *)jcr->wstorage->first();
1146 Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1152 /* Set storage override */
1153 void set_wstorage(JCR *jcr, USTORE *store)
1157 if (!store->store) {
1160 if (!jcr->wstorage) {
1161 jcr->wstorage = New(alist(10, not_owned_by_alist));
1163 jcr->wstore = store->store;
1164 if (!jcr->wstore_source) {
1165 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1167 pm_strcpy(jcr->wstore_source, store->store_source);
1168 Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1169 foreach_alist(storage, jcr->wstorage) {
1170 if (store->store == storage) {
1174 /* Store not in list, so add it */
1175 jcr->wstorage->prepend(store->store);
1178 void free_wstorage(JCR *jcr)
1180 if (jcr->wstorage) {
1181 delete jcr->wstorage;
1182 jcr->wstorage = NULL;
1187 void create_clones(JCR *jcr)
1190 * Fire off any clone jobs (run directives)
1192 Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1193 if (!jcr->cloned && jcr->job->run_cmds) {
1195 JOB *job = jcr->job;
1196 POOLMEM *cmd = get_pool_memory(PM_FNAME);
1197 UAContext *ua = new_ua_context(jcr);
1199 foreach_alist(runcmd, job->run_cmds) {
1200 cmd = edit_job_codes(jcr, cmd, runcmd, "");
1201 Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1202 Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1203 parse_ua_args(ua); /* parse command */
1204 int stat = run_cmd(ua, ua->cmd);
1206 Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1208 Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1211 free_ua_context(ua);
1212 free_pool_memory(cmd);
1216 bool create_restore_bootstrap_file(JCR *jcr)
1220 memset(&rx, 0, sizeof(rx));
1223 rx.bsr->JobId = jcr->previous_jr.JobId;
1224 ua = new_ua_context(jcr);
1225 complete_bsr(ua, rx.bsr);
1226 rx.bsr->fi = new_findex();
1227 rx.bsr->fi->findex = 1;
1228 rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1229 jcr->ExpectedFiles = write_bsr_file(ua, rx);
1230 if (jcr->ExpectedFiles == 0) {
1231 free_ua_context(ua);
1235 free_ua_context(ua);
1237 jcr->needs_sd = true;