2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Bacula Director Job processing routines
32 * Kern Sibbald, October MM
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.bstrerror(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.bstrerror(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.bstrerror(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(100, "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));
135 db_close_database(jcr, jcr->db);
139 Dmsg0(150, "DB opened\n");
142 jcr->fname = get_pool_memory(PM_FNAME);
144 if (!jcr->pool_source) {
145 jcr->pool_source = get_pool_memory(PM_MESSAGE);
146 pm_strcpy(jcr->pool_source, _("unknown source"));
148 Dmsg2(500, "pool=%s (From %s)\n", jcr->pool->name(), jcr->pool_source);
149 if (jcr->JobType == JT_MIGRATE) {
150 if (!jcr->rpool_source) {
151 jcr->rpool_source = get_pool_memory(PM_MESSAGE);
152 pm_strcpy(jcr->rpool_source, _("unknown source"));
159 init_jcr_job_record(jcr);
160 if (!get_or_create_client_record(jcr)) {
164 if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
165 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
168 jcr->JobId = jcr->jr.JobId;
169 Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
170 jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
172 generate_daemon_event(jcr, "JobStart");
174 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");
223 void update_job_end(JCR *jcr, int TermCode)
225 dequeue_messages(jcr); /* display any queued messages */
226 set_jcr_job_status(jcr, TermCode);
227 update_job_end_record(jcr);
231 * This is the engine called by jobq.c:jobq_add() when we were pulled
232 * from the work queue.
233 * At this point, we are running in our own thread and all
234 * necessary resources are allocated -- see jobq.c
236 static void *job_thread(void *arg)
238 JCR *jcr = (JCR *)arg;
240 pthread_detach(pthread_self());
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);
332 run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
334 /* Send off any queued messages */
335 if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
336 dequeue_messages(jcr);
339 generate_daemon_event(jcr, "JobEnd");
340 Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
341 sm_check(__FILE__, __LINE__, true);
347 * Cancel a job -- typically called by the UA (Console program), but may also
348 * be called by the job watchdog.
350 * Returns: true if cancel appears to be successful
351 * false on failure. Message sent to ua->jcr.
353 bool cancel_job(UAContext *ua, JCR *jcr)
358 set_jcr_job_status(jcr, JS_Canceled);
360 switch (jcr->JobStatus) {
363 case JS_WaitClientRes:
364 case JS_WaitStoreRes:
365 case JS_WaitPriority:
367 case JS_WaitStartTime:
368 ua->info_msg(_("JobId %s, Job %s marked to be canceled.\n"),
369 edit_uint64(jcr->JobId, ed1), jcr->Job);
370 jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
374 /* Cancel File daemon */
375 if (jcr->file_bsock) {
376 ua->jcr->client = jcr->client;
377 if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
378 ua->error_msg(_("Failed to connect to File daemon.\n"));
381 Dmsg0(200, "Connected to file daemon\n");
382 fd = ua->jcr->file_bsock;
383 bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
384 while (bnet_recv(fd) >= 0) {
385 ua->send_msg("%s", fd->msg);
387 bnet_sig(fd, BNET_TERMINATE);
389 ua->jcr->file_bsock = NULL;
392 /* Cancel Storage daemon */
393 if (jcr->store_bsock) {
394 if (!ua->jcr->wstorage) {
396 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
398 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
403 store.store = jcr->rstore;
405 store.store = jcr->wstore;
407 set_wstorage(ua->jcr, &store);
410 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
411 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
414 Dmsg0(200, "Connected to storage daemon\n");
415 sd = ua->jcr->store_bsock;
416 sd->fsend("cancel Job=%s\n", jcr->Job);
417 while (sd->recv() >= 0) {
418 ua->send_msg("%s", sd->msg);
420 sd->signal(BNET_TERMINATE);
422 ua->jcr->store_bsock = NULL;
429 void cancel_storage_daemon_job(JCR *jcr)
431 UAContext *ua = new_ua_context(jcr);
432 JCR *control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);
435 ua->jcr = control_jcr;
436 if (jcr->store_bsock) {
437 if (!ua->jcr->wstorage) {
439 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
441 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
446 store.store = jcr->rstore;
448 store.store = jcr->wstore;
450 set_wstorage(ua->jcr, &store);
453 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
456 Dmsg0(200, "Connected to storage daemon\n");
457 sd = ua->jcr->store_bsock;
458 sd->fsend("cancel Job=%s\n", jcr->Job);
459 while (sd->recv() >= 0) {
461 sd->signal(BNET_TERMINATE);
463 ua->jcr->store_bsock = NULL;
466 free_jcr(control_jcr);
470 static void job_monitor_destructor(watchdog_t *self)
472 JCR *control_jcr = (JCR *)self->data;
474 free_jcr(control_jcr);
477 static void job_monitor_watchdog(watchdog_t *self)
479 JCR *control_jcr, *jcr;
481 control_jcr = (JCR *)self->data;
484 Dmsg1(800, "job_monitor_watchdog %p called\n", self);
489 if (jcr->JobId == 0 || job_canceled(jcr)) {
490 Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
494 /* check MaxWaitTime */
495 if (job_check_maxwaittime(control_jcr, jcr)) {
496 set_jcr_job_status(jcr, JS_Canceled);
497 Jmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
499 /* check MaxRunTime */
500 } else if (job_check_maxruntime(control_jcr, jcr)) {
501 set_jcr_job_status(jcr, JS_Canceled);
502 Jmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
507 Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
508 UAContext *ua = new_ua_context(jcr);
509 ua->jcr = control_jcr;
512 Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
516 /* Keep reference counts correct */
521 * Check if the maxwaittime has expired and it is possible
524 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
529 if (job_canceled(jcr)) {
530 return false; /* already canceled */
532 if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
533 job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
536 if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
537 (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
539 } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
540 (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
542 } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
543 (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
545 } else if (job->MaxWaitTime != 0 &&
546 (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
554 * Check if maxruntime has expired and if the job can be
557 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
559 if (jcr->job->MaxRunTime == 0 || job_canceled(jcr) || jcr->JobStatus == JS_Created) {
562 if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
563 Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
564 jcr, jcr->Job, jcr->job->MaxRunTime);
572 * Get or create a Pool record with the given name.
573 * Returns: 0 on error
576 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
580 memset(&pr, 0, sizeof(pr));
581 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
582 Dmsg1(110, "get_or_create_pool=%s\n", pool_name);
584 while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
585 /* Try to create the pool */
586 if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
587 Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
588 db_strerror(jcr->db));
591 Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
597 void apply_pool_overrides(JCR *jcr)
599 if (jcr->run_pool_override) {
600 pm_strcpy(jcr->pool_source, _("Run pool override"));
603 * Apply any level related Pool selections
605 switch (jcr->JobLevel) {
607 if (jcr->full_pool) {
608 jcr->pool = jcr->full_pool;
609 if (jcr->run_full_pool_override) {
610 pm_strcpy(jcr->pool_source, _("Run FullPool override"));
612 pm_strcpy(jcr->pool_source, _("Job FullPool override"));
618 jcr->pool = jcr->inc_pool;
619 if (jcr->run_inc_pool_override) {
620 pm_strcpy(jcr->pool_source, _("Run IncPool override"));
622 pm_strcpy(jcr->pool_source, _("Job IncPool override"));
627 if (jcr->diff_pool) {
628 jcr->pool = jcr->diff_pool;
629 if (jcr->run_diff_pool_override) {
630 pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
632 pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
641 * Get or create a Client record for this Job
643 bool get_or_create_client_record(JCR *jcr)
647 memset(&cr, 0, sizeof(cr));
648 bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
649 cr.AutoPrune = jcr->client->AutoPrune;
650 cr.FileRetention = jcr->client->FileRetention;
651 cr.JobRetention = jcr->client->JobRetention;
652 if (!jcr->client_name) {
653 jcr->client_name = get_pool_memory(PM_NAME);
655 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
656 if (!db_create_client_record(jcr, jcr->db, &cr)) {
657 Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
658 db_strerror(jcr->db));
661 jcr->jr.ClientId = cr.ClientId;
663 if (!jcr->client_uname) {
664 jcr->client_uname = get_pool_memory(PM_NAME);
666 pm_strcpy(jcr->client_uname, cr.Uname);
668 Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
673 bool get_or_create_fileset_record(JCR *jcr)
677 * Get or Create FileSet record
679 memset(&fsr, 0, sizeof(FILESET_DBR));
680 bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
681 if (jcr->fileset->have_MD5) {
682 struct MD5Context md5c;
683 unsigned char digest[MD5HashSize];
684 memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
685 MD5Final(digest, &md5c);
687 * Keep the flag (last arg) set to false otherwise old FileSets will
688 * get new MD5 sums and the user will get Full backups on everything
690 bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
691 bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
693 Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
695 if (!jcr->fileset->ignore_fs_changes ||
696 !db_get_fileset_record(jcr, jcr->db, &fsr)) {
697 if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
698 Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
699 fsr.FileSet, db_strerror(jcr->db));
703 jcr->jr.FileSetId = fsr.FileSetId;
704 bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
705 Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
710 void init_jcr_job_record(JCR *jcr)
712 jcr->jr.SchedTime = jcr->sched_time;
713 jcr->jr.StartTime = jcr->start_time;
714 jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
715 jcr->jr.JobType = jcr->JobType;
716 jcr->jr.JobLevel = jcr->JobLevel;
717 jcr->jr.JobStatus = jcr->JobStatus;
718 jcr->jr.JobId = jcr->JobId;
719 bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
720 bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
724 * Write status and such in DB
726 void update_job_end_record(JCR *jcr)
728 jcr->jr.EndTime = time(NULL);
729 jcr->end_time = jcr->jr.EndTime;
730 jcr->jr.JobId = jcr->JobId;
731 jcr->jr.JobStatus = jcr->JobStatus;
732 jcr->jr.JobFiles = jcr->JobFiles;
733 jcr->jr.JobBytes = jcr->JobBytes;
734 jcr->jr.VolSessionId = jcr->VolSessionId;
735 jcr->jr.VolSessionTime = jcr->VolSessionTime;
736 jcr->jr.JobErrors = jcr->Errors;
737 if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
738 Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
739 db_strerror(jcr->db));
744 * Takes base_name and appends (unique) current
745 * date and time to form unique job name.
747 * Note, the seconds are actually a sequence number. This
748 * permits us to start a maximum fo 59 unique jobs a second, which
749 * should be sufficient.
751 * Returns: unique job name in jcr->Job
752 * date/time in jcr->start_time
754 void create_unique_job_name(JCR *jcr, const char *base_name)
756 /* Job start mutex */
757 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
758 static time_t last_start_time = 0;
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 */
772 if (seq > 59) { /* wrap as if it is seconds */
774 while (now == last_start_time) {
775 bmicrosleep(0, 500000);
779 last_start_time = now;
780 V(mutex); /* allow creation of jobs */
781 jcr->start_time = now;
782 /* Form Unique JobName */
783 (void)localtime_r(&now, &tm);
784 /* Use only characters that are permitted in Windows filenames */
785 strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M", &tm);
786 bstrncpy(name, base_name, sizeof(name));
787 name[sizeof(name)-22] = 0; /* truncate if too long */
788 bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s.%02d", name, dt, seq); /* add date & time */
789 /* Convert spaces into underscores */
790 for (p=jcr->Job; *p; p++) {
797 /* Called directly from job rescheduling */
798 void dird_free_jcr_pointers(JCR *jcr)
800 if (jcr->sd_auth_key) {
801 free(jcr->sd_auth_key);
802 jcr->sd_auth_key = NULL;
808 if (jcr->file_bsock) {
809 Dmsg0(200, "Close File bsock\n");
810 bnet_close(jcr->file_bsock);
811 jcr->file_bsock = NULL;
813 if (jcr->store_bsock) {
814 Dmsg0(200, "Close Store bsock\n");
815 bnet_close(jcr->store_bsock);
816 jcr->store_bsock = NULL;
819 Dmsg0(200, "Free JCR fname\n");
820 free_pool_memory(jcr->fname);
823 if (jcr->RestoreBootstrap) {
824 free(jcr->RestoreBootstrap);
825 jcr->RestoreBootstrap = NULL;
827 if (jcr->client_uname) {
828 free_pool_memory(jcr->client_uname);
829 jcr->client_uname = NULL;
832 free_pool_memory(jcr->attr);
842 * Free the Job Control Record if no one is still using it.
843 * Called from main free_jcr() routine in src/lib/jcr.c so
844 * that we can do our Director specific cleanup of the jcr.
846 void dird_free_jcr(JCR *jcr)
848 Dmsg0(200, "Start dird free_jcr\n");
850 dird_free_jcr_pointers(jcr);
851 if (jcr->term_wait_inited) {
852 pthread_cond_destroy(&jcr->term_wait);
853 jcr->term_wait_inited = false;
855 if (jcr->db_batch && jcr->db_batch != jcr->db) {
856 db_close_database(jcr, jcr->db_batch);
858 jcr->db_batch = NULL;
860 db_close_database(jcr, jcr->db);
864 Dmsg0(200, "Free JCR stime\n");
865 free_pool_memory(jcr->stime);
869 Dmsg0(200, "Free JCR fname\n");
870 free_pool_memory(jcr->fname);
873 if (jcr->pool_source) {
874 free_pool_memory(jcr->pool_source);
875 jcr->pool_source = NULL;
877 if (jcr->rpool_source) {
878 free_pool_memory(jcr->rpool_source);
879 jcr->rpool_source = NULL;
881 if (jcr->wstore_source) {
882 free_pool_memory(jcr->wstore_source);
883 jcr->wstore_source = NULL;
885 if (jcr->rstore_source) {
886 free_pool_memory(jcr->rstore_source);
887 jcr->rstore_source = NULL;
890 /* Delete lists setup to hold storage pointers */
893 jcr->job_end_push.destroy();
894 Dmsg0(200, "End dird free_jcr\n");
898 * The Job storage definition must be either in the Job record
899 * or in the Pool record. The Pool record overrides the Job
902 void get_job_storage(USTORE *store, JOB *job, RUN *run)
904 if (run && run->pool && run->pool->storage) {
905 store->store = (STORE *)run->pool->storage->first();
906 pm_strcpy(store->store_source, _("Run pool override"));
909 if (run && run->storage) {
910 store->store = run->storage;
911 pm_strcpy(store->store_source, _("Run storage override"));
914 if (job->pool->storage) {
915 store->store = (STORE *)job->pool->storage->first();
916 pm_strcpy(store->store_source, _("Pool resource"));
918 store->store = (STORE *)job->storage->first();
919 pm_strcpy(store->store_source, _("Job resource"));
924 * Set some defaults in the JCR necessary to
925 * run. These items are pulled from the job
926 * definition as defaults, but can be overridden
927 * later either by the Run record in the Schedule resource,
928 * or by the Console program.
930 void set_jcr_defaults(JCR *jcr, JOB *job)
933 jcr->JobType = job->JobType;
934 jcr->JobStatus = JS_Created;
935 switch (jcr->JobType) {
938 jcr->JobLevel = L_NONE;
941 if (!jcr->rpool_source) {
942 jcr->rpool_source = get_pool_memory(PM_MESSAGE);
943 pm_strcpy(jcr->rpool_source, _("unknown source"));
945 /* Fall-through wanted */
947 jcr->JobLevel = job->JobLevel;
951 jcr->fname = get_pool_memory(PM_FNAME);
953 if (!jcr->pool_source) {
954 jcr->pool_source = get_pool_memory(PM_MESSAGE);
955 pm_strcpy(jcr->pool_source, _("unknown source"));
958 jcr->JobPriority = job->Priority;
959 /* Copy storage definitions -- deleted in dir_free_jcr above */
961 copy_rwstorage(jcr, job->storage, _("Job resource"));
963 copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
965 jcr->client = job->client;
966 if (!jcr->client_name) {
967 jcr->client_name = get_pool_memory(PM_NAME);
969 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
970 pm_strcpy(jcr->pool_source, _("Job resource"));
971 jcr->pool = job->pool;
972 jcr->full_pool = job->full_pool;
973 jcr->inc_pool = job->inc_pool;
974 jcr->diff_pool = job->diff_pool;
975 jcr->catalog = job->client->catalog;
976 jcr->fileset = job->fileset;
977 jcr->messages = job->messages;
978 jcr->spool_data = job->spool_data;
979 jcr->write_part_after_job = job->write_part_after_job;
980 if (jcr->RestoreBootstrap) {
981 free(jcr->RestoreBootstrap);
982 jcr->RestoreBootstrap = NULL;
984 /* This can be overridden by Console program */
985 if (job->RestoreBootstrap) {
986 jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
988 /* This can be overridden by Console program */
989 jcr->verify_job = job->verify_job;
990 /* If no default level given, set one */
991 if (jcr->JobLevel == 0) {
992 switch (jcr->JobType) {
994 jcr->JobLevel = L_VERIFY_CATALOG;
997 jcr->JobLevel = L_INCREMENTAL;
1001 jcr->JobLevel = L_NONE;
1004 jcr->JobLevel = L_FULL;
1011 * Copy the storage definitions from an alist to the JCR
1013 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1015 switch(jcr->JobType) {
1019 copy_rstorage(jcr, storage, where);
1022 copy_wstorage(jcr, storage, where);
1028 /* Set storage override. Releases any previous storage definition */
1029 void set_rwstorage(JCR *jcr, USTORE *store)
1032 Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1035 switch(jcr->JobType) {
1039 set_rstorage(jcr, store);
1042 set_wstorage(jcr, store);
1047 void free_rwstorage(JCR *jcr)
1054 * Copy the storage definitions from an alist to the JCR
1056 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1060 if (jcr->rstorage) {
1061 delete jcr->rstorage;
1063 jcr->rstorage = New(alist(10, not_owned_by_alist));
1064 foreach_alist(st, storage) {
1065 jcr->rstorage->append(st);
1067 if (!jcr->rstore_source) {
1068 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1070 pm_strcpy(jcr->rstore_source, where);
1071 if (jcr->rstorage) {
1072 jcr->rstore = (STORE *)jcr->rstorage->first();
1078 /* Set storage override. Remove all previous storage */
1079 void set_rstorage(JCR *jcr, USTORE *store)
1083 if (!store->store) {
1086 if (jcr->rstorage) {
1089 if (!jcr->rstorage) {
1090 jcr->rstorage = New(alist(10, not_owned_by_alist));
1092 jcr->rstore = store->store;
1093 if (!jcr->rstore_source) {
1094 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1096 pm_strcpy(jcr->rstore_source, store->store_source);
1097 foreach_alist(storage, jcr->rstorage) {
1098 if (store->store == storage) {
1102 /* Store not in list, so add it */
1103 jcr->rstorage->prepend(store->store);
1106 void free_rstorage(JCR *jcr)
1108 if (jcr->rstorage) {
1109 delete jcr->rstorage;
1110 jcr->rstorage = NULL;
1116 * Copy the storage definitions from an alist to the JCR
1118 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1122 if (jcr->wstorage) {
1123 delete jcr->wstorage;
1125 jcr->wstorage = New(alist(10, not_owned_by_alist));
1126 foreach_alist(st, storage) {
1127 Dmsg1(100, "wstorage=%s\n", st->name());
1128 jcr->wstorage->append(st);
1130 if (!jcr->wstore_source) {
1131 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1133 pm_strcpy(jcr->wstore_source, where);
1134 if (jcr->wstorage) {
1135 jcr->wstore = (STORE *)jcr->wstorage->first();
1136 Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1142 /* Set storage override. Remove all previous storage */
1143 void set_wstorage(JCR *jcr, USTORE *store)
1147 if (!store->store) {
1150 if (jcr->wstorage) {
1153 if (!jcr->wstorage) {
1154 jcr->wstorage = New(alist(10, not_owned_by_alist));
1156 jcr->wstore = store->store;
1157 if (!jcr->wstore_source) {
1158 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1160 pm_strcpy(jcr->wstore_source, store->store_source);
1161 Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1162 foreach_alist(storage, jcr->wstorage) {
1163 if (store->store == storage) {
1167 /* Store not in list, so add it */
1168 jcr->wstorage->prepend(store->store);
1171 void free_wstorage(JCR *jcr)
1173 if (jcr->wstorage) {
1174 delete jcr->wstorage;
1175 jcr->wstorage = NULL;
1180 void create_clones(JCR *jcr)
1183 * Fire off any clone jobs (run directives)
1185 Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1186 if (!jcr->cloned && jcr->job->run_cmds) {
1188 JOB *job = jcr->job;
1189 POOLMEM *cmd = get_pool_memory(PM_FNAME);
1190 UAContext *ua = new_ua_context(jcr);
1192 foreach_alist(runcmd, job->run_cmds) {
1193 cmd = edit_job_codes(jcr, cmd, runcmd, "");
1194 Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1195 Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1196 parse_ua_args(ua); /* parse command */
1197 int stat = run_cmd(ua, ua->cmd);
1199 Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1201 Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1204 free_ua_context(ua);
1205 free_pool_memory(cmd);
1209 bool create_restore_bootstrap_file(JCR *jcr)
1213 memset(&rx, 0, sizeof(rx));
1215 rx.JobIds = (char *)"";
1216 rx.bsr->JobId = jcr->previous_jr.JobId;
1217 ua = new_ua_context(jcr);
1218 complete_bsr(ua, rx.bsr);
1219 rx.bsr->fi = new_findex();
1220 rx.bsr->fi->findex = 1;
1221 rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1222 jcr->ExpectedFiles = write_bsr_file(ua, rx);
1223 if (jcr->ExpectedFiles == 0) {
1224 free_ua_context(ua);
1228 free_ua_context(ua);
1230 jcr->needs_sd = true;