2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 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(jcr, jcr->catalog->db_driver, jcr->catalog->db_name,
127 jcr->catalog->db_user,
128 jcr->catalog->db_password, jcr->catalog->db_address,
129 jcr->catalog->db_port, jcr->catalog->db_socket,
130 jcr->catalog->mult_db_connections);
131 if (!jcr->db || !db_open_database(jcr, jcr->db)) {
132 Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
133 jcr->catalog->db_name);
135 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
136 db_close_database(jcr, jcr->db);
140 Dmsg0(150, "DB opened\n");
143 jcr->fname = get_pool_memory(PM_FNAME);
145 if (!jcr->pool_source) {
146 jcr->pool_source = get_pool_memory(PM_MESSAGE);
147 pm_strcpy(jcr->pool_source, _("unknown source"));
149 Dmsg2(500, "pool=%s (From %s)\n", jcr->pool->name(), jcr->pool_source);
150 if (jcr->JobType == JT_MIGRATE) {
151 if (!jcr->rpool_source) {
152 jcr->rpool_source = get_pool_memory(PM_MESSAGE);
153 pm_strcpy(jcr->rpool_source, _("unknown source"));
160 init_jcr_job_record(jcr);
161 if (!get_or_create_client_record(jcr)) {
165 if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
166 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
169 jcr->JobId = jcr->jr.JobId;
170 Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
171 jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
173 generate_daemon_event(jcr, "JobStart");
175 if (job_canceled(jcr)) {
180 * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
181 * this allows us to setup a proper job start record for restarting
182 * in case of later errors.
184 switch (jcr->JobType) {
186 if (!do_backup_init(jcr)) {
187 backup_cleanup(jcr, JS_ErrorTerminated);
191 if (!do_verify_init(jcr)) {
192 verify_cleanup(jcr, JS_ErrorTerminated);
196 if (!do_restore_init(jcr)) {
197 restore_cleanup(jcr, JS_ErrorTerminated);
201 if (!do_admin_init(jcr)) {
202 admin_cleanup(jcr, JS_ErrorTerminated);
206 if (!do_migration_init(jcr)) {
207 migration_cleanup(jcr, JS_ErrorTerminated);
211 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
212 set_jcr_job_status(jcr, JS_ErrorTerminated);
216 generate_job_event(jcr, "JobInit");
224 void update_job_end(JCR *jcr, int TermCode)
226 dequeue_messages(jcr); /* display any queued messages */
227 set_jcr_job_status(jcr, TermCode);
228 update_job_end_record(jcr);
232 * This is the engine called by jobq.c:jobq_add() when we were pulled
233 * from the work queue.
234 * At this point, we are running in our own thread and all
235 * necessary resources are allocated -- see jobq.c
237 static void *job_thread(void *arg)
239 JCR *jcr = (JCR *)arg;
241 pthread_detach(pthread_self());
244 Dmsg0(200, "=====Start Job=========\n");
245 set_jcr_job_status(jcr, JS_Running); /* this will be set only if no error */
246 jcr->start_time = time(NULL); /* set the real start time */
247 jcr->jr.StartTime = jcr->start_time;
249 if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
250 (utime_t)(jcr->start_time - jcr->sched_time)) {
251 set_jcr_job_status(jcr, JS_Canceled);
252 Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
255 /* TODO : check if it is used somewhere */
256 if (jcr->job->RunScripts == NULL) {
257 Dmsg0(200, "Warning, job->RunScripts is empty\n");
258 jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
261 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
262 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
265 /* Run any script BeforeJob on dird */
266 run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
268 if (job_canceled(jcr)) {
269 update_job_end(jcr, jcr->JobStatus);
273 * We re-update the job start record so that the start
274 * time is set after the run before job. This avoids
275 * that any files created by the run before job will
276 * be saved twice. They will be backed up in the current
277 * job, but not in the next one unless they are changed.
278 * Without this, they will be backed up in this job and
279 * in the next job run because in that case, their date
280 * is after the start of this run.
282 jcr->start_time = time(NULL);
283 jcr->jr.StartTime = jcr->start_time;
284 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
285 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
287 generate_job_event(jcr, "JobRun");
289 switch (jcr->JobType) {
291 if (do_backup(jcr)) {
294 backup_cleanup(jcr, JS_ErrorTerminated);
298 if (do_verify(jcr)) {
301 verify_cleanup(jcr, JS_ErrorTerminated);
305 if (do_restore(jcr)) {
308 restore_cleanup(jcr, JS_ErrorTerminated);
315 admin_cleanup(jcr, JS_ErrorTerminated);
321 if (do_migration(jcr)) {
324 migration_cleanup(jcr, JS_ErrorTerminated);
328 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
333 run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
335 /* Send off any queued messages */
336 if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
337 dequeue_messages(jcr);
340 generate_daemon_event(jcr, "JobEnd");
341 Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
342 sm_check(__FILE__, __LINE__, true);
348 * Cancel a job -- typically called by the UA (Console program), but may also
349 * be called by the job watchdog.
351 * Returns: true if cancel appears to be successful
352 * false on failure. Message sent to ua->jcr.
354 bool cancel_job(UAContext *ua, JCR *jcr)
359 set_jcr_job_status(jcr, JS_Canceled);
361 switch (jcr->JobStatus) {
364 case JS_WaitClientRes:
365 case JS_WaitStoreRes:
366 case JS_WaitPriority:
368 case JS_WaitStartTime:
369 ua->info_msg(_("JobId %s, Job %s marked to be canceled.\n"),
370 edit_uint64(jcr->JobId, ed1), jcr->Job);
371 jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
375 /* Cancel File daemon */
376 if (jcr->file_bsock) {
377 ua->jcr->client = jcr->client;
378 if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
379 ua->error_msg(_("Failed to connect to File daemon.\n"));
382 Dmsg0(200, "Connected to file daemon\n");
383 fd = ua->jcr->file_bsock;
384 bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
385 while (bnet_recv(fd) >= 0) {
386 ua->send_msg("%s", fd->msg);
388 bnet_sig(fd, BNET_TERMINATE);
390 ua->jcr->file_bsock = NULL;
393 /* Cancel Storage daemon */
394 if (jcr->store_bsock) {
395 if (!ua->jcr->wstorage) {
397 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
399 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
404 store.store = jcr->rstore;
406 store.store = jcr->wstore;
408 set_wstorage(ua->jcr, &store);
411 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
412 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
415 Dmsg0(200, "Connected to storage daemon\n");
416 sd = ua->jcr->store_bsock;
417 sd->fsend("cancel Job=%s\n", jcr->Job);
418 while (sd->recv() >= 0) {
419 ua->send_msg("%s", sd->msg);
421 sd->signal(BNET_TERMINATE);
423 ua->jcr->store_bsock = NULL;
430 void cancel_storage_daemon_job(JCR *jcr)
432 UAContext *ua = new_ua_context(jcr);
433 JCR *control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);
436 ua->jcr = control_jcr;
437 if (jcr->store_bsock) {
438 if (!ua->jcr->wstorage) {
440 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
442 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
447 store.store = jcr->rstore;
449 store.store = jcr->wstore;
451 set_wstorage(ua->jcr, &store);
454 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
457 Dmsg0(200, "Connected to storage daemon\n");
458 sd = ua->jcr->store_bsock;
459 sd->fsend("cancel Job=%s\n", jcr->Job);
460 while (sd->recv() >= 0) {
462 sd->signal(BNET_TERMINATE);
464 ua->jcr->store_bsock = NULL;
467 free_jcr(control_jcr);
471 static void job_monitor_destructor(watchdog_t *self)
473 JCR *control_jcr = (JCR *)self->data;
475 free_jcr(control_jcr);
478 static void job_monitor_watchdog(watchdog_t *self)
480 JCR *control_jcr, *jcr;
482 control_jcr = (JCR *)self->data;
485 Dmsg1(800, "job_monitor_watchdog %p called\n", self);
490 if (jcr->JobId == 0 || job_canceled(jcr)) {
491 Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
495 /* check MaxWaitTime */
496 if (job_check_maxwaittime(control_jcr, jcr)) {
497 set_jcr_job_status(jcr, JS_Canceled);
498 Jmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
500 /* check MaxRunTime */
501 } else if (job_check_maxruntime(control_jcr, jcr)) {
502 set_jcr_job_status(jcr, JS_Canceled);
503 Jmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
508 Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
509 UAContext *ua = new_ua_context(jcr);
510 ua->jcr = control_jcr;
513 Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
517 /* Keep reference counts correct */
522 * Check if the maxwaittime has expired and it is possible
525 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
530 if (job_canceled(jcr)) {
531 return false; /* already canceled */
533 if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
534 job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
537 if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
538 (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
540 } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
541 (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
543 } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
544 (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
546 } else if (job->MaxWaitTime != 0 &&
547 (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
555 * Check if maxruntime has expired and if the job can be
558 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
560 if (jcr->job->MaxRunTime == 0 || job_canceled(jcr) || jcr->JobStatus == JS_Created) {
563 if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
564 Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
565 jcr, jcr->Job, jcr->job->MaxRunTime);
573 * Get or create a Pool record with the given name.
574 * Returns: 0 on error
577 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
581 memset(&pr, 0, sizeof(pr));
582 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
583 Dmsg1(110, "get_or_create_pool=%s\n", pool_name);
585 while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
586 /* Try to create the pool */
587 if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
588 Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
589 db_strerror(jcr->db));
592 Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
598 void apply_pool_overrides(JCR *jcr)
600 if (jcr->run_pool_override) {
601 pm_strcpy(jcr->pool_source, _("Run pool override"));
604 * Apply any level related Pool selections
606 switch (jcr->JobLevel) {
608 if (jcr->full_pool) {
609 jcr->pool = jcr->full_pool;
610 if (jcr->run_full_pool_override) {
611 pm_strcpy(jcr->pool_source, _("Run FullPool override"));
613 pm_strcpy(jcr->pool_source, _("Job FullPool override"));
619 jcr->pool = jcr->inc_pool;
620 if (jcr->run_inc_pool_override) {
621 pm_strcpy(jcr->pool_source, _("Run IncPool override"));
623 pm_strcpy(jcr->pool_source, _("Job IncPool override"));
628 if (jcr->diff_pool) {
629 jcr->pool = jcr->diff_pool;
630 if (jcr->run_diff_pool_override) {
631 pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
633 pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
642 * Get or create a Client record for this Job
644 bool get_or_create_client_record(JCR *jcr)
648 memset(&cr, 0, sizeof(cr));
649 bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
650 cr.AutoPrune = jcr->client->AutoPrune;
651 cr.FileRetention = jcr->client->FileRetention;
652 cr.JobRetention = jcr->client->JobRetention;
653 if (!jcr->client_name) {
654 jcr->client_name = get_pool_memory(PM_NAME);
656 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
657 if (!db_create_client_record(jcr, jcr->db, &cr)) {
658 Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
659 db_strerror(jcr->db));
662 jcr->jr.ClientId = cr.ClientId;
664 if (!jcr->client_uname) {
665 jcr->client_uname = get_pool_memory(PM_NAME);
667 pm_strcpy(jcr->client_uname, cr.Uname);
669 Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
674 bool get_or_create_fileset_record(JCR *jcr)
678 * Get or Create FileSet record
680 memset(&fsr, 0, sizeof(FILESET_DBR));
681 bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
682 if (jcr->fileset->have_MD5) {
683 struct MD5Context md5c;
684 unsigned char digest[MD5HashSize];
685 memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
686 MD5Final(digest, &md5c);
688 * Keep the flag (last arg) set to false otherwise old FileSets will
689 * get new MD5 sums and the user will get Full backups on everything
691 bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
692 bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
694 Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
696 if (!jcr->fileset->ignore_fs_changes ||
697 !db_get_fileset_record(jcr, jcr->db, &fsr)) {
698 if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
699 Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
700 fsr.FileSet, db_strerror(jcr->db));
704 jcr->jr.FileSetId = fsr.FileSetId;
705 bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
706 Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
711 void init_jcr_job_record(JCR *jcr)
713 jcr->jr.SchedTime = jcr->sched_time;
714 jcr->jr.StartTime = jcr->start_time;
715 jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
716 jcr->jr.JobType = jcr->JobType;
717 jcr->jr.JobLevel = jcr->JobLevel;
718 jcr->jr.JobStatus = jcr->JobStatus;
719 jcr->jr.JobId = jcr->JobId;
720 bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
721 bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
725 * Write status and such in DB
727 void update_job_end_record(JCR *jcr)
729 jcr->jr.EndTime = time(NULL);
730 jcr->end_time = jcr->jr.EndTime;
731 jcr->jr.JobId = jcr->JobId;
732 jcr->jr.JobStatus = jcr->JobStatus;
733 jcr->jr.JobFiles = jcr->JobFiles;
734 jcr->jr.JobBytes = jcr->JobBytes;
735 jcr->jr.VolSessionId = jcr->VolSessionId;
736 jcr->jr.VolSessionTime = jcr->VolSessionTime;
737 jcr->jr.JobErrors = jcr->Errors;
738 if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
739 Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
740 db_strerror(jcr->db));
745 * Takes base_name and appends (unique) current
746 * date and time to form unique job name.
748 * Note, the seconds are actually a sequence number. This
749 * permits us to start a maximum fo 59 unique jobs a second, which
750 * should be sufficient.
752 * Returns: unique job name in jcr->Job
753 * date/time in jcr->start_time
755 void create_unique_job_name(JCR *jcr, const char *base_name)
757 /* Job start mutex */
758 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
759 static time_t last_start_time = 0;
763 char dt[MAX_TIME_LENGTH];
764 char name[MAX_NAME_LENGTH];
767 /* Guarantee unique start time -- maximum one per second, and
768 * thus unique Job Name
770 P(mutex); /* lock creation of jobs */
773 if (seq > 59) { /* wrap as if it is seconds */
775 while (now == last_start_time) {
776 bmicrosleep(0, 500000);
780 last_start_time = now;
781 V(mutex); /* allow creation of jobs */
782 jcr->start_time = now;
783 /* Form Unique JobName */
784 (void)localtime_r(&now, &tm);
785 /* Use only characters that are permitted in Windows filenames */
786 strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M", &tm);
787 bstrncpy(name, base_name, sizeof(name));
788 name[sizeof(name)-22] = 0; /* truncate if too long */
789 bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s.%02d", name, dt, seq); /* add date & time */
790 /* Convert spaces into underscores */
791 for (p=jcr->Job; *p; p++) {
798 /* Called directly from job rescheduling */
799 void dird_free_jcr_pointers(JCR *jcr)
801 if (jcr->sd_auth_key) {
802 free(jcr->sd_auth_key);
803 jcr->sd_auth_key = NULL;
809 if (jcr->file_bsock) {
810 Dmsg0(200, "Close File bsock\n");
811 bnet_close(jcr->file_bsock);
812 jcr->file_bsock = NULL;
814 if (jcr->store_bsock) {
815 Dmsg0(200, "Close Store bsock\n");
816 bnet_close(jcr->store_bsock);
817 jcr->store_bsock = NULL;
820 Dmsg0(200, "Free JCR fname\n");
821 free_pool_memory(jcr->fname);
824 if (jcr->RestoreBootstrap) {
825 free(jcr->RestoreBootstrap);
826 jcr->RestoreBootstrap = NULL;
828 if (jcr->client_uname) {
829 free_pool_memory(jcr->client_uname);
830 jcr->client_uname = NULL;
833 free_pool_memory(jcr->attr);
843 * Free the Job Control Record if no one is still using it.
844 * Called from main free_jcr() routine in src/lib/jcr.c so
845 * that we can do our Director specific cleanup of the jcr.
847 void dird_free_jcr(JCR *jcr)
849 Dmsg0(200, "Start dird free_jcr\n");
851 dird_free_jcr_pointers(jcr);
852 if (jcr->term_wait_inited) {
853 pthread_cond_destroy(&jcr->term_wait);
854 jcr->term_wait_inited = false;
856 if (jcr->db_batch && jcr->db_batch != jcr->db) {
857 db_close_database(jcr, jcr->db_batch);
859 jcr->db_batch = NULL;
861 db_close_database(jcr, jcr->db);
865 Dmsg0(200, "Free JCR stime\n");
866 free_pool_memory(jcr->stime);
870 Dmsg0(200, "Free JCR fname\n");
871 free_pool_memory(jcr->fname);
874 if (jcr->pool_source) {
875 free_pool_memory(jcr->pool_source);
876 jcr->pool_source = NULL;
878 if (jcr->rpool_source) {
879 free_pool_memory(jcr->rpool_source);
880 jcr->rpool_source = NULL;
882 if (jcr->wstore_source) {
883 free_pool_memory(jcr->wstore_source);
884 jcr->wstore_source = NULL;
886 if (jcr->rstore_source) {
887 free_pool_memory(jcr->rstore_source);
888 jcr->rstore_source = NULL;
891 /* Delete lists setup to hold storage pointers */
894 jcr->job_end_push.destroy();
897 write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
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 jcr->JobStatus = JS_Created;
940 switch (jcr->JobType) {
943 jcr->JobLevel = L_NONE;
946 if (!jcr->rpool_source) {
947 jcr->rpool_source = get_pool_memory(PM_MESSAGE);
948 pm_strcpy(jcr->rpool_source, _("unknown source"));
950 /* Fall-through wanted */
952 jcr->JobLevel = job->JobLevel;
956 jcr->fname = get_pool_memory(PM_FNAME);
958 if (!jcr->pool_source) {
959 jcr->pool_source = get_pool_memory(PM_MESSAGE);
960 pm_strcpy(jcr->pool_source, _("unknown source"));
963 jcr->JobPriority = job->Priority;
964 /* Copy storage definitions -- deleted in dir_free_jcr above */
966 copy_rwstorage(jcr, job->storage, _("Job resource"));
968 copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
970 jcr->client = job->client;
971 if (!jcr->client_name) {
972 jcr->client_name = get_pool_memory(PM_NAME);
974 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
975 pm_strcpy(jcr->pool_source, _("Job resource"));
976 jcr->pool = job->pool;
977 jcr->full_pool = job->full_pool;
978 jcr->inc_pool = job->inc_pool;
979 jcr->diff_pool = job->diff_pool;
980 jcr->catalog = job->client->catalog;
981 jcr->fileset = job->fileset;
982 jcr->messages = job->messages;
983 jcr->spool_data = job->spool_data;
984 jcr->spool_size = job->spool_size;
985 jcr->write_part_after_job = job->write_part_after_job;
986 jcr->accurate = job->accurate;
987 if (jcr->RestoreBootstrap) {
988 free(jcr->RestoreBootstrap);
989 jcr->RestoreBootstrap = NULL;
991 /* This can be overridden by Console program */
992 if (job->RestoreBootstrap) {
993 jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
995 /* This can be overridden by Console program */
996 jcr->verify_job = job->verify_job;
997 /* If no default level given, set one */
998 if (jcr->JobLevel == 0) {
999 switch (jcr->JobType) {
1001 jcr->JobLevel = L_VERIFY_CATALOG;
1004 jcr->JobLevel = L_INCREMENTAL;
1008 jcr->JobLevel = L_NONE;
1011 jcr->JobLevel = L_FULL;
1018 * Copy the storage definitions from an alist to the JCR
1020 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1022 switch(jcr->JobType) {
1026 copy_rstorage(jcr, storage, where);
1029 copy_wstorage(jcr, storage, where);
1035 /* Set storage override. Releases any previous storage definition */
1036 void set_rwstorage(JCR *jcr, USTORE *store)
1039 Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1042 switch(jcr->JobType) {
1046 set_rstorage(jcr, store);
1049 set_wstorage(jcr, store);
1054 void free_rwstorage(JCR *jcr)
1061 * Copy the storage definitions from an alist to the JCR
1063 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1067 if (jcr->rstorage) {
1068 delete jcr->rstorage;
1070 jcr->rstorage = New(alist(10, not_owned_by_alist));
1071 foreach_alist(st, storage) {
1072 jcr->rstorage->append(st);
1074 if (!jcr->rstore_source) {
1075 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1077 pm_strcpy(jcr->rstore_source, where);
1078 if (jcr->rstorage) {
1079 jcr->rstore = (STORE *)jcr->rstorage->first();
1085 /* Set storage override. Remove all previous storage */
1086 void set_rstorage(JCR *jcr, USTORE *store)
1090 if (!store->store) {
1093 if (jcr->rstorage) {
1096 if (!jcr->rstorage) {
1097 jcr->rstorage = New(alist(10, not_owned_by_alist));
1099 jcr->rstore = store->store;
1100 if (!jcr->rstore_source) {
1101 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1103 pm_strcpy(jcr->rstore_source, store->store_source);
1104 foreach_alist(storage, jcr->rstorage) {
1105 if (store->store == storage) {
1109 /* Store not in list, so add it */
1110 jcr->rstorage->prepend(store->store);
1113 void free_rstorage(JCR *jcr)
1115 if (jcr->rstorage) {
1116 delete jcr->rstorage;
1117 jcr->rstorage = NULL;
1123 * Copy the storage definitions from an alist to the JCR
1125 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1129 if (jcr->wstorage) {
1130 delete jcr->wstorage;
1132 jcr->wstorage = New(alist(10, not_owned_by_alist));
1133 foreach_alist(st, storage) {
1134 Dmsg1(100, "wstorage=%s\n", st->name());
1135 jcr->wstorage->append(st);
1137 if (!jcr->wstore_source) {
1138 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1140 pm_strcpy(jcr->wstore_source, where);
1141 if (jcr->wstorage) {
1142 jcr->wstore = (STORE *)jcr->wstorage->first();
1143 Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1149 /* Set storage override. Remove all previous storage */
1150 void set_wstorage(JCR *jcr, USTORE *store)
1154 if (!store->store) {
1157 if (jcr->wstorage) {
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));
1222 rx.JobIds = (char *)"";
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;
1241 bool run_console_command(JCR *jcr, const char *cmd){
1245 ua = new_ua_context(jcr);
1246 Mmsg(ua->cmd, "%s", cmd);
1247 Dmsg1(100, "Console command: %s\n", ua->cmd);
1249 ok= do_a_command(ua);
1250 free_ua_context(ua);