2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2010 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 Kern Sibbald.
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
39 /* Forward referenced subroutines */
40 static void *job_thread(void *arg);
41 static void job_monitor_watchdog(watchdog_t *self);
42 static void job_monitor_destructor(watchdog_t *self);
43 static bool job_check_maxwaittime(JCR *jcr);
44 static bool job_check_maxruntime(JCR *jcr);
45 static bool job_check_maxschedruntime(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));
117 jcr->term_wait_inited = true;
119 create_unique_job_name(jcr, jcr->job->name());
120 jcr->setJobStatus(JS_Created);
126 Dmsg0(100, "Open database\n");
127 jcr->db=db_init(jcr, jcr->catalog->db_driver, jcr->catalog->db_name,
128 jcr->catalog->db_user,
129 jcr->catalog->db_password, jcr->catalog->db_address,
130 jcr->catalog->db_port, jcr->catalog->db_socket,
131 jcr->catalog->mult_db_connections);
132 if (!jcr->db || !db_open_database(jcr, jcr->db)) {
133 Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
134 jcr->catalog->db_name);
136 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
137 db_close_database(jcr, jcr->db);
141 Dmsg0(150, "DB opened\n");
144 jcr->fname = get_pool_memory(PM_FNAME);
146 if (!jcr->pool_source) {
147 jcr->pool_source = get_pool_memory(PM_MESSAGE);
148 pm_strcpy(jcr->pool_source, _("unknown source"));
151 if (jcr->JobReads()) {
152 if (!jcr->rpool_source) {
153 jcr->rpool_source = get_pool_memory(PM_MESSAGE);
154 pm_strcpy(jcr->rpool_source, _("unknown source"));
161 init_jcr_job_record(jcr);
162 if (!get_or_create_client_record(jcr)) {
166 if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
167 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
170 jcr->JobId = jcr->jr.JobId;
171 Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
172 jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
174 generate_daemon_event(jcr, "JobStart");
175 new_plugins(jcr); /* instantiate plugins for this jcr */
176 generate_plugin_event(jcr, bEventJobStart);
178 if (job_canceled(jcr)) {
182 if (jcr->JobReads() && !jcr->rstorage) {
183 if (jcr->job->storage) {
184 copy_rwstorage(jcr, jcr->job->storage, _("Job resource"));
186 copy_rwstorage(jcr, jcr->job->pool->storage, _("Pool resource"));
189 if (!jcr->JobReads()) {
194 * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
195 * this allows us to setup a proper job start record for restarting
196 * in case of later errors.
198 switch (jcr->getJobType()) {
200 if (!do_backup_init(jcr)) {
201 backup_cleanup(jcr, JS_ErrorTerminated);
206 if (!do_verify_init(jcr)) {
207 verify_cleanup(jcr, JS_ErrorTerminated);
212 if (!do_restore_init(jcr)) {
213 restore_cleanup(jcr, JS_ErrorTerminated);
218 if (!do_admin_init(jcr)) {
219 admin_cleanup(jcr, JS_ErrorTerminated);
225 if (!do_migration_init(jcr)) {
226 migration_cleanup(jcr, JS_ErrorTerminated);
231 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->getJobType());
232 jcr->setJobStatus(JS_ErrorTerminated);
236 generate_job_event(jcr, "JobInit");
237 generate_plugin_event(jcr, bEventJobInit);
245 void update_job_end(JCR *jcr, int TermCode)
247 dequeue_messages(jcr); /* display any queued messages */
248 jcr->setJobStatus(TermCode);
249 update_job_end_record(jcr);
253 * This is the engine called by jobq.c:jobq_add() when we were pulled
254 * from the work queue.
255 * At this point, we are running in our own thread and all
256 * necessary resources are allocated -- see jobq.c
258 static void *job_thread(void *arg)
260 JCR *jcr = (JCR *)arg;
262 pthread_detach(pthread_self());
265 Dmsg0(200, "=====Start Job=========\n");
266 jcr->setJobStatus(JS_Running); /* this will be set only if no error */
267 jcr->start_time = time(NULL); /* set the real start time */
268 jcr->jr.StartTime = jcr->start_time;
270 if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
271 (utime_t)(jcr->start_time - jcr->sched_time)) {
272 jcr->setJobStatus(JS_Canceled);
273 Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
276 if (job_check_maxschedruntime(jcr)) {
277 jcr->setJobStatus(JS_Canceled);
278 Jmsg(jcr, M_FATAL, 0, _("Job canceled because max sched run time exceeded.\n"));
281 /* TODO : check if it is used somewhere */
282 if (jcr->job->RunScripts == NULL) {
283 Dmsg0(200, "Warning, job->RunScripts is empty\n");
284 jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
287 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
288 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
291 /* Run any script BeforeJob on dird */
292 run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
295 * We re-update the job start record so that the start
296 * time is set after the run before job. This avoids
297 * that any files created by the run before job will
298 * be saved twice. They will be backed up in the current
299 * job, but not in the next one unless they are changed.
300 * Without this, they will be backed up in this job and
301 * in the next job run because in that case, their date
302 * is after the start of this run.
304 jcr->start_time = time(NULL);
305 jcr->jr.StartTime = jcr->start_time;
306 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
307 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
309 generate_job_event(jcr, "JobRun");
310 generate_plugin_event(jcr, bEventJobRun);
312 switch (jcr->getJobType()) {
314 if (!job_canceled(jcr) && do_backup(jcr)) {
317 backup_cleanup(jcr, JS_ErrorTerminated);
321 if (!job_canceled(jcr) && do_verify(jcr)) {
324 verify_cleanup(jcr, JS_ErrorTerminated);
328 if (!job_canceled(jcr) && do_restore(jcr)) {
331 restore_cleanup(jcr, JS_ErrorTerminated);
335 if (!job_canceled(jcr) && do_admin(jcr)) {
338 admin_cleanup(jcr, JS_ErrorTerminated);
343 if (!job_canceled(jcr) && do_migration(jcr)) {
346 migration_cleanup(jcr, JS_ErrorTerminated);
350 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->getJobType());
354 run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
356 /* Send off any queued messages */
357 if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
358 dequeue_messages(jcr);
361 generate_daemon_event(jcr, "JobEnd");
362 generate_plugin_event(jcr, bEventJobEnd);
363 Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
364 sm_check(__FILE__, __LINE__, true);
370 * Cancel a job -- typically called by the UA (Console program), but may also
371 * be called by the job watchdog.
373 * Returns: true if cancel appears to be successful
374 * false on failure. Message sent to ua->jcr.
376 bool cancel_job(UAContext *ua, JCR *jcr)
380 int32_t old_status = jcr->JobStatus;
382 jcr->setJobStatus(JS_Canceled);
384 switch (old_status) {
387 case JS_WaitClientRes:
388 case JS_WaitStoreRes:
389 case JS_WaitPriority:
391 case JS_WaitStartTime:
392 ua->info_msg(_("JobId %s, Job %s marked to be canceled.\n"),
393 edit_uint64(jcr->JobId, ed1), jcr->Job);
394 jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
398 /* Cancel File daemon */
399 if (jcr->file_bsock) {
400 ua->jcr->client = jcr->client;
401 if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
402 ua->error_msg(_("Failed to connect to File daemon.\n"));
405 Dmsg0(200, "Connected to file daemon\n");
406 fd = ua->jcr->file_bsock;
407 fd->fsend("cancel Job=%s\n", jcr->Job);
408 while (fd->recv() >= 0) {
409 ua->send_msg("%s", fd->msg);
411 fd->signal(BNET_TERMINATE);
413 ua->jcr->file_bsock = NULL;
414 jcr->file_bsock->set_terminated();
415 if (jcr->my_thread_id && !pthread_equal(jcr->my_thread_id, pthread_self())) {
416 pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
417 Dmsg1(800, "Send kill to jid=%d\n", jcr->JobId);
421 /* Cancel Storage daemon */
422 if (jcr->store_bsock) {
423 if (!ua->jcr->wstorage) {
425 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
427 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
432 store.store = jcr->rstore;
434 store.store = jcr->wstore;
436 set_wstorage(ua->jcr, &store);
439 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
440 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
443 Dmsg0(200, "Connected to storage daemon\n");
444 sd = ua->jcr->store_bsock;
445 sd->fsend("cancel Job=%s\n", jcr->Job);
446 while (sd->recv() >= 0) {
447 ua->send_msg("%s", sd->msg);
449 sd->signal(BNET_TERMINATE);
451 ua->jcr->store_bsock = NULL;
452 jcr->store_bsock->set_timed_out();
453 jcr->store_bsock->set_terminated();
454 if (jcr->SD_msg_chan && !pthread_equal(jcr->SD_msg_chan, pthread_self())) {
455 Dmsg2(400, "kill jobid=%d use=%d\n", (int)jcr->JobId, jcr->use_count());
456 pthread_kill(jcr->SD_msg_chan, TIMEOUT_SIGNAL);
458 if (jcr->my_thread_id && !pthread_equal(jcr->my_thread_id, pthread_self())) {
459 pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
468 void cancel_storage_daemon_job(JCR *jcr)
470 if (jcr->sd_canceled) {
471 return; /* cancel only once */
474 UAContext *ua = new_ua_context(jcr);
475 JCR *control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);
478 ua->jcr = control_jcr;
479 if (jcr->store_bsock) {
480 if (!ua->jcr->wstorage) {
482 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
484 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
489 store.store = jcr->rstore;
491 store.store = jcr->wstore;
493 set_wstorage(ua->jcr, &store);
496 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
499 Dmsg0(200, "Connected to storage daemon\n");
500 sd = ua->jcr->store_bsock;
501 sd->fsend("cancel Job=%s\n", jcr->Job);
502 while (sd->recv() >= 0) {
504 sd->signal(BNET_TERMINATE);
506 ua->jcr->store_bsock = NULL;
507 jcr->sd_canceled = true;
508 jcr->store_bsock->set_timed_out();
509 jcr->store_bsock->set_terminated();
510 if (jcr->SD_msg_chan && !pthread_equal(jcr->SD_msg_chan, pthread_self())) {
511 Dmsg2(400, "kill jobid=%d use=%d\n", (int)jcr->JobId, jcr->use_count());
512 pthread_kill(jcr->SD_msg_chan, TIMEOUT_SIGNAL);
514 if (jcr->my_thread_id && !pthread_equal(jcr->my_thread_id, pthread_self())) {
515 pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
519 free_jcr(control_jcr);
523 static void job_monitor_destructor(watchdog_t *self)
525 JCR *control_jcr = (JCR *)self->data;
527 free_jcr(control_jcr);
530 static void job_monitor_watchdog(watchdog_t *self)
532 JCR *control_jcr, *jcr;
534 control_jcr = (JCR *)self->data;
537 Dmsg1(800, "job_monitor_watchdog %p called\n", self);
542 if (jcr->JobId == 0 || job_canceled(jcr) || jcr->no_maxtime) {
543 Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
547 /* check MaxWaitTime */
548 if (job_check_maxwaittime(jcr)) {
549 jcr->setJobStatus(JS_Canceled);
550 Qmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
552 /* check MaxRunTime */
553 } else if (job_check_maxruntime(jcr)) {
554 jcr->setJobStatus(JS_Canceled);
555 Qmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
557 /* check MaxRunSchedTime */
558 } else if (job_check_maxschedruntime(jcr)) {
559 jcr->setJobStatus(JS_Canceled);
560 Qmsg(jcr, M_FATAL, 0, _("Max sched run time exceeded. Job canceled.\n"));
565 Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
566 UAContext *ua = new_ua_context(jcr);
567 ua->jcr = control_jcr;
570 Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
574 /* Keep reference counts correct */
579 * Check if the maxwaittime has expired and it is possible
582 static bool job_check_maxwaittime(JCR *jcr)
588 if (!job_waiting(jcr)) {
592 if (jcr->wait_time) {
593 current = watchdog_time - jcr->wait_time;
596 Dmsg2(200, "check maxwaittime %u >= %u\n",
597 current + jcr->wait_time_sum, job->MaxWaitTime);
598 if (job->MaxWaitTime != 0 &&
599 (current + jcr->wait_time_sum) >= job->MaxWaitTime) {
607 * Check if maxruntime has expired and if the job can be
610 static bool job_check_maxruntime(JCR *jcr)
616 if (job_canceled(jcr) || jcr->JobStatus == JS_Created) {
619 if (jcr->job->MaxRunTime == 0 && job->FullMaxRunTime == 0 &&
620 job->IncMaxRunTime == 0 && job->DiffMaxRunTime == 0) {
623 run_time = watchdog_time - jcr->start_time;
624 Dmsg7(200, "check_maxruntime %llu-%u=%llu >= %llu|%llu|%llu|%llu\n",
625 watchdog_time, jcr->start_time, run_time, job->MaxRunTime, job->FullMaxRunTime,
626 job->IncMaxRunTime, job->DiffMaxRunTime);
628 if (jcr->getJobLevel() == L_FULL && job->FullMaxRunTime != 0 &&
629 run_time >= job->FullMaxRunTime) {
630 Dmsg0(200, "check_maxwaittime: FullMaxcancel\n");
632 } else if (jcr->getJobLevel() == L_DIFFERENTIAL && job->DiffMaxRunTime != 0 &&
633 run_time >= job->DiffMaxRunTime) {
634 Dmsg0(200, "check_maxwaittime: DiffMaxcancel\n");
636 } else if (jcr->getJobLevel() == L_INCREMENTAL && job->IncMaxRunTime != 0 &&
637 run_time >= job->IncMaxRunTime) {
638 Dmsg0(200, "check_maxwaittime: IncMaxcancel\n");
640 } else if (job->MaxRunTime > 0 && run_time >= job->MaxRunTime) {
641 Dmsg0(200, "check_maxwaittime: Maxcancel\n");
649 * Check if MaxRunSchedTime has expired and if the job can be
652 static bool job_check_maxschedruntime(JCR *jcr)
654 if (jcr->job->MaxRunSchedTime == 0 || job_canceled(jcr)) {
657 if ((watchdog_time - jcr->sched_time) < jcr->job->MaxRunSchedTime) {
658 Dmsg3(200, "Job %p (%s) with MaxRunSchedTime %d not expired\n",
659 jcr, jcr->Job, jcr->job->MaxRunSchedTime);
667 * Get or create a Pool record with the given name.
668 * Returns: 0 on error
671 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
675 memset(&pr, 0, sizeof(pr));
676 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
677 Dmsg1(110, "get_or_create_pool=%s\n", pool_name);
679 while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
680 /* Try to create the pool */
681 if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
682 Jmsg(jcr, M_FATAL, 0, _("Pool \"%s\" not in database. ERR=%s"), pr.Name,
683 db_strerror(jcr->db));
686 Jmsg(jcr, M_INFO, 0, _("Created database record for Pool \"%s\".\n"), pr.Name);
693 * Check for duplicate jobs.
694 * Returns: true if current job should continue
695 * false if current job should terminate
697 bool allow_duplicate_job(JCR *jcr)
700 JCR *djcr; /* possible duplicate job */
702 if (job->AllowDuplicateJobs) {
705 Dmsg0(800, "Enter allow_duplicate_job\n");
707 * After this point, we do not want to allow any duplicate
712 if (jcr == djcr || djcr->JobId == 0) {
713 continue; /* do not cancel this job or consoles */
715 if (strcmp(job->name(), djcr->job->name()) == 0) {
716 bool cancel_dup = false;
717 bool cancel_me = false;
718 if (job->DuplicateJobProximity > 0) {
719 utime_t now = (utime_t)time(NULL);
720 if ((now - djcr->start_time) > job->DuplicateJobProximity) {
721 continue; /* not really a duplicate */
724 if (job->CancelLowerLevelDuplicates &&
725 djcr->getJobType() == 'B' && jcr->getJobType() == 'B') {
726 switch (jcr->getJobLevel()) {
728 if (djcr->getJobLevel() == L_DIFFERENTIAL ||
729 djcr->getJobLevel() == L_INCREMENTAL) {
734 if (djcr->getJobLevel() == L_INCREMENTAL) {
737 if (djcr->getJobLevel() == L_FULL) {
742 if (djcr->getJobLevel() == L_FULL ||
743 djcr->getJobLevel() == L_DIFFERENTIAL) {
748 * cancel_dup will be done below
751 /* Zap current job */
752 Jmsg(jcr, M_FATAL, 0, _("JobId %d already running. Duplicate job not allowed.\n"),
754 break; /* get out of foreach_jcr */
757 /* Cancel one of the two jobs (me or dup) */
758 /* If CancelQueuedDuplicates is set do so only if job is queued */
759 if (job->CancelQueuedDuplicates) {
760 switch (djcr->JobStatus) {
763 case JS_WaitClientRes:
764 case JS_WaitStoreRes:
765 case JS_WaitPriority:
767 case JS_WaitStartTime:
768 cancel_dup = true; /* cancel queued duplicate */
774 if (cancel_dup || job->CancelRunningDuplicates) {
775 /* Zap the duplicated job djcr */
776 UAContext *ua = new_ua_context(jcr);
777 Jmsg(jcr, M_INFO, 0, _("Cancelling duplicate JobId=%d.\n"), djcr->JobId);
778 cancel_job(ua, djcr);
779 bmicrosleep(0, 500000);
780 cancel_job(ua, djcr);
782 Dmsg2(800, "Cancel dup %p JobId=%d\n", djcr, djcr->JobId);
784 /* Zap current job */
785 Jmsg(jcr, M_FATAL, 0, _("JobId %d already running. Duplicate job not allowed.\n"),
787 Dmsg2(800, "Cancel me %p JobId=%d\n", jcr, jcr->JobId);
789 Dmsg4(800, "curJobId=%d use_cnt=%d dupJobId=%d use_cnt=%d\n",
790 jcr->JobId, jcr->use_count(), djcr->JobId, djcr->use_count());
791 break; /* did our work, get out of foreach loop */
799 void apply_pool_overrides(JCR *jcr)
801 bool pool_override = false;
803 if (jcr->run_pool_override) {
804 pm_strcpy(jcr->pool_source, _("Run pool override"));
807 * Apply any level related Pool selections
809 switch (jcr->getJobLevel()) {
811 if (jcr->full_pool) {
812 jcr->pool = jcr->full_pool;
813 pool_override = true;
814 if (jcr->run_full_pool_override) {
815 pm_strcpy(jcr->pool_source, _("Run FullPool override"));
817 pm_strcpy(jcr->pool_source, _("Job FullPool override"));
823 jcr->pool = jcr->inc_pool;
824 pool_override = true;
825 if (jcr->run_inc_pool_override) {
826 pm_strcpy(jcr->pool_source, _("Run IncPool override"));
828 pm_strcpy(jcr->pool_source, _("Job IncPool override"));
833 if (jcr->diff_pool) {
834 jcr->pool = jcr->diff_pool;
835 pool_override = true;
836 if (jcr->run_diff_pool_override) {
837 pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
839 pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
844 /* Update catalog if pool overridden */
845 if (pool_override && jcr->pool->catalog) {
846 jcr->catalog = jcr->pool->catalog;
847 pm_strcpy(jcr->catalog_source, _("Pool resource"));
853 * Get or create a Client record for this Job
855 bool get_or_create_client_record(JCR *jcr)
859 memset(&cr, 0, sizeof(cr));
860 bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
861 cr.AutoPrune = jcr->client->AutoPrune;
862 cr.FileRetention = jcr->client->FileRetention;
863 cr.JobRetention = jcr->client->JobRetention;
864 if (!jcr->client_name) {
865 jcr->client_name = get_pool_memory(PM_NAME);
867 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
868 if (!db_create_client_record(jcr, jcr->db, &cr)) {
869 Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
870 db_strerror(jcr->db));
873 jcr->jr.ClientId = cr.ClientId;
875 if (!jcr->client_uname) {
876 jcr->client_uname = get_pool_memory(PM_NAME);
878 pm_strcpy(jcr->client_uname, cr.Uname);
880 Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
885 bool get_or_create_fileset_record(JCR *jcr)
889 * Get or Create FileSet record
891 memset(&fsr, 0, sizeof(FILESET_DBR));
892 bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
893 if (jcr->fileset->have_MD5) {
894 struct MD5Context md5c;
895 unsigned char digest[MD5HashSize];
896 memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
897 MD5Final(digest, &md5c);
899 * Keep the flag (last arg) set to false otherwise old FileSets will
900 * get new MD5 sums and the user will get Full backups on everything
902 bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
903 bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
905 Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
907 if (!jcr->fileset->ignore_fs_changes ||
908 !db_get_fileset_record(jcr, jcr->db, &fsr)) {
909 if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
910 Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
911 fsr.FileSet, db_strerror(jcr->db));
915 jcr->jr.FileSetId = fsr.FileSetId;
916 bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
917 Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
922 void init_jcr_job_record(JCR *jcr)
924 jcr->jr.SchedTime = jcr->sched_time;
925 jcr->jr.StartTime = jcr->start_time;
926 jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
927 jcr->jr.JobType = jcr->getJobType();
928 jcr->jr.JobLevel = jcr->getJobLevel();
929 jcr->jr.JobStatus = jcr->JobStatus;
930 jcr->jr.JobId = jcr->JobId;
931 bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
932 bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
936 * Write status and such in DB
938 void update_job_end_record(JCR *jcr)
940 jcr->jr.EndTime = time(NULL);
941 jcr->end_time = jcr->jr.EndTime;
942 jcr->jr.JobId = jcr->JobId;
943 jcr->jr.JobStatus = jcr->JobStatus;
944 jcr->jr.JobFiles = jcr->JobFiles;
945 jcr->jr.JobBytes = jcr->JobBytes;
946 jcr->jr.ReadBytes = jcr->ReadBytes;
947 jcr->jr.VolSessionId = jcr->VolSessionId;
948 jcr->jr.VolSessionTime = jcr->VolSessionTime;
949 jcr->jr.JobErrors = jcr->JobErrors;
950 jcr->jr.HasBase = jcr->HasBase;
951 if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
952 Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
953 db_strerror(jcr->db));
958 * Takes base_name and appends (unique) current
959 * date and time to form unique job name.
961 * Note, the seconds are actually a sequence number. This
962 * permits us to start a maximum fo 59 unique jobs a second, which
963 * should be sufficient.
965 * Returns: unique job name in jcr->Job
966 * date/time in jcr->start_time
968 void create_unique_job_name(JCR *jcr, const char *base_name)
970 /* Job start mutex */
971 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
972 static time_t last_start_time = 0;
974 time_t now = time(NULL);
976 char dt[MAX_TIME_LENGTH];
977 char name[MAX_NAME_LENGTH];
981 /* Guarantee unique start time -- maximum one per second, and
982 * thus unique Job Name
984 P(mutex); /* lock creation of jobs */
986 if (seq > 59) { /* wrap as if it is seconds */
988 while (now == last_start_time) {
989 bmicrosleep(0, 500000);
993 last_start_time = now;
994 V(mutex); /* allow creation of jobs */
995 jcr->start_time = now;
996 /* Form Unique JobName */
997 (void)localtime_r(&now, &tm);
998 /* Use only characters that are permitted in Windows filenames */
999 strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
1000 len = strlen(dt) + 5; /* dt + .%02d EOS */
1001 bstrncpy(name, base_name, sizeof(name));
1002 name[sizeof(name)-len] = 0; /* truncate if too long */
1003 bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s_%02d", name, dt, seq); /* add date & time */
1004 /* Convert spaces into underscores */
1005 for (p=jcr->Job; *p; p++) {
1010 Dmsg2(100, "JobId=%u created Job=%s\n", jcr->JobId, jcr->Job);
1013 /* Called directly from job rescheduling */
1014 void dird_free_jcr_pointers(JCR *jcr)
1016 if (jcr->sd_auth_key) {
1017 free(jcr->sd_auth_key);
1018 jcr->sd_auth_key = NULL;
1024 if (jcr->file_bsock) {
1025 Dmsg0(200, "Close File bsock\n");
1026 bnet_close(jcr->file_bsock);
1027 jcr->file_bsock = NULL;
1029 if (jcr->store_bsock) {
1030 Dmsg0(200, "Close Store bsock\n");
1031 bnet_close(jcr->store_bsock);
1032 jcr->store_bsock = NULL;
1035 Dmsg0(200, "Free JCR fname\n");
1036 free_pool_memory(jcr->fname);
1039 if (jcr->RestoreBootstrap) {
1040 free(jcr->RestoreBootstrap);
1041 jcr->RestoreBootstrap = NULL;
1043 if (jcr->client_uname) {
1044 free_pool_memory(jcr->client_uname);
1045 jcr->client_uname = NULL;
1048 free_pool_memory(jcr->attr);
1058 * Free the Job Control Record if no one is still using it.
1059 * Called from main free_jcr() routine in src/lib/jcr.c so
1060 * that we can do our Director specific cleanup of the jcr.
1062 void dird_free_jcr(JCR *jcr)
1064 Dmsg0(200, "Start dird free_jcr\n");
1066 dird_free_jcr_pointers(jcr);
1067 if (jcr->term_wait_inited) {
1068 pthread_cond_destroy(&jcr->term_wait);
1069 jcr->term_wait_inited = false;
1071 if (jcr->db_batch) {
1072 db_close_database(jcr, jcr->db_batch);
1073 jcr->db_batch = NULL;
1074 jcr->batch_started = false;
1077 db_close_database(jcr, jcr->db);
1081 Dmsg0(200, "Free JCR stime\n");
1082 free_pool_memory(jcr->stime);
1086 Dmsg0(200, "Free JCR fname\n");
1087 free_pool_memory(jcr->fname);
1090 if (jcr->pool_source) {
1091 free_pool_memory(jcr->pool_source);
1092 jcr->pool_source = NULL;
1094 if (jcr->catalog_source) {
1095 free_pool_memory(jcr->catalog_source);
1096 jcr->catalog_source = NULL;
1098 if (jcr->rpool_source) {
1099 free_pool_memory(jcr->rpool_source);
1100 jcr->rpool_source = NULL;
1102 if (jcr->wstore_source) {
1103 free_pool_memory(jcr->wstore_source);
1104 jcr->wstore_source = NULL;
1106 if (jcr->rstore_source) {
1107 free_pool_memory(jcr->rstore_source);
1108 jcr->rstore_source = NULL;
1111 /* Delete lists setup to hold storage pointers */
1112 free_rwstorage(jcr);
1114 jcr->job_end_push.destroy();
1116 if (jcr->JobId != 0)
1117 write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
1119 free_plugins(jcr); /* release instantiated plugins */
1121 Dmsg0(200, "End dird free_jcr\n");
1125 * The Job storage definition must be either in the Job record
1126 * or in the Pool record. The Pool record overrides the Job
1129 void get_job_storage(USTORE *store, JOB *job, RUN *run)
1131 if (run && run->pool && run->pool->storage) {
1132 store->store = (STORE *)run->pool->storage->first();
1133 pm_strcpy(store->store_source, _("Run pool override"));
1136 if (run && run->storage) {
1137 store->store = run->storage;
1138 pm_strcpy(store->store_source, _("Run storage override"));
1141 if (job->pool->storage) {
1142 store->store = (STORE *)job->pool->storage->first();
1143 pm_strcpy(store->store_source, _("Pool resource"));
1145 store->store = (STORE *)job->storage->first();
1146 pm_strcpy(store->store_source, _("Job resource"));
1151 * Set some defaults in the JCR necessary to
1152 * run. These items are pulled from the job
1153 * definition as defaults, but can be overridden
1154 * later either by the Run record in the Schedule resource,
1155 * or by the Console program.
1157 void set_jcr_defaults(JCR *jcr, JOB *job)
1160 jcr->set_JobType(job->JobType);
1161 jcr->JobStatus = JS_Created;
1163 switch (jcr->getJobType()) {
1165 jcr->set_JobLevel(L_NONE);
1168 jcr->set_JobLevel(job->JobLevel);
1173 jcr->fname = get_pool_memory(PM_FNAME);
1175 if (!jcr->pool_source) {
1176 jcr->pool_source = get_pool_memory(PM_MESSAGE);
1177 pm_strcpy(jcr->pool_source, _("unknown source"));
1179 if (!jcr->catalog_source) {
1180 jcr->catalog_source = get_pool_memory(PM_MESSAGE);
1181 pm_strcpy(jcr->catalog_source, _("unknown source"));
1184 jcr->JobPriority = job->Priority;
1185 /* Copy storage definitions -- deleted in dir_free_jcr above */
1187 copy_rwstorage(jcr, job->storage, _("Job resource"));
1189 copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
1191 jcr->client = job->client;
1192 if (!jcr->client_name) {
1193 jcr->client_name = get_pool_memory(PM_NAME);
1195 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
1196 pm_strcpy(jcr->pool_source, _("Job resource"));
1197 jcr->pool = job->pool;
1198 jcr->full_pool = job->full_pool;
1199 jcr->inc_pool = job->inc_pool;
1200 jcr->diff_pool = job->diff_pool;
1201 if (job->pool->catalog) {
1202 jcr->catalog = job->pool->catalog;
1203 pm_strcpy(jcr->catalog_source, _("Pool resource"));
1205 jcr->catalog = job->client->catalog;
1206 pm_strcpy(jcr->catalog_source, _("Client resource"));
1208 jcr->fileset = job->fileset;
1209 jcr->messages = job->messages;
1210 jcr->spool_data = job->spool_data;
1211 jcr->spool_size = job->spool_size;
1212 jcr->write_part_after_job = job->write_part_after_job;
1213 jcr->accurate = job->accurate;
1214 if (jcr->RestoreBootstrap) {
1215 free(jcr->RestoreBootstrap);
1216 jcr->RestoreBootstrap = NULL;
1218 /* This can be overridden by Console program */
1219 if (job->RestoreBootstrap) {
1220 jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1222 /* This can be overridden by Console program */
1223 jcr->verify_job = job->verify_job;
1224 /* If no default level given, set one */
1225 if (jcr->getJobLevel() == 0) {
1226 switch (jcr->getJobType()) {
1228 jcr->set_JobLevel(L_VERIFY_CATALOG);
1231 jcr->set_JobLevel(L_INCREMENTAL);
1235 jcr->set_JobLevel(L_NONE);
1238 jcr->set_JobLevel(L_FULL);
1245 * Copy the storage definitions from an alist to the JCR
1247 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1249 if (jcr->JobReads()) {
1250 copy_rstorage(jcr, storage, where);
1252 copy_wstorage(jcr, storage, where);
1256 /* Set storage override. Releases any previous storage definition */
1257 void set_rwstorage(JCR *jcr, USTORE *store)
1260 Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1263 if (jcr->JobReads()) {
1264 set_rstorage(jcr, store);
1266 set_wstorage(jcr, store);
1269 void free_rwstorage(JCR *jcr)
1276 * Copy the storage definitions from an alist to the JCR
1278 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1282 if (jcr->rstorage) {
1283 delete jcr->rstorage;
1285 jcr->rstorage = New(alist(10, not_owned_by_alist));
1286 foreach_alist(st, storage) {
1287 jcr->rstorage->append(st);
1289 if (!jcr->rstore_source) {
1290 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1292 pm_strcpy(jcr->rstore_source, where);
1293 if (jcr->rstorage) {
1294 jcr->rstore = (STORE *)jcr->rstorage->first();
1300 /* Set storage override. Remove all previous storage */
1301 void set_rstorage(JCR *jcr, USTORE *store)
1305 if (!store->store) {
1308 if (jcr->rstorage) {
1311 if (!jcr->rstorage) {
1312 jcr->rstorage = New(alist(10, not_owned_by_alist));
1314 jcr->rstore = store->store;
1315 if (!jcr->rstore_source) {
1316 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1318 pm_strcpy(jcr->rstore_source, store->store_source);
1319 foreach_alist(storage, jcr->rstorage) {
1320 if (store->store == storage) {
1324 /* Store not in list, so add it */
1325 jcr->rstorage->prepend(store->store);
1328 void free_rstorage(JCR *jcr)
1330 if (jcr->rstorage) {
1331 delete jcr->rstorage;
1332 jcr->rstorage = NULL;
1338 * Copy the storage definitions from an alist to the JCR
1340 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1344 if (jcr->wstorage) {
1345 delete jcr->wstorage;
1347 jcr->wstorage = New(alist(10, not_owned_by_alist));
1348 foreach_alist(st, storage) {
1349 Dmsg1(100, "wstorage=%s\n", st->name());
1350 jcr->wstorage->append(st);
1352 if (!jcr->wstore_source) {
1353 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1355 pm_strcpy(jcr->wstore_source, where);
1356 if (jcr->wstorage) {
1357 jcr->wstore = (STORE *)jcr->wstorage->first();
1358 Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1364 /* Set storage override. Remove all previous storage */
1365 void set_wstorage(JCR *jcr, USTORE *store)
1369 if (!store->store) {
1372 if (jcr->wstorage) {
1375 if (!jcr->wstorage) {
1376 jcr->wstorage = New(alist(10, not_owned_by_alist));
1378 jcr->wstore = store->store;
1379 if (!jcr->wstore_source) {
1380 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1382 pm_strcpy(jcr->wstore_source, store->store_source);
1383 Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1384 foreach_alist(storage, jcr->wstorage) {
1385 if (store->store == storage) {
1389 /* Store not in list, so add it */
1390 jcr->wstorage->prepend(store->store);
1393 void free_wstorage(JCR *jcr)
1395 if (jcr->wstorage) {
1396 delete jcr->wstorage;
1397 jcr->wstorage = NULL;
1402 char *job_code_callback_clones(JCR *jcr, const char* param)
1404 if (param[0] == 'p') {
1405 return jcr->pool->name();
1410 void create_clones(JCR *jcr)
1413 * Fire off any clone jobs (run directives)
1415 Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1416 if (!jcr->cloned && jcr->job->run_cmds) {
1418 JOB *job = jcr->job;
1419 POOLMEM *cmd = get_pool_memory(PM_FNAME);
1420 UAContext *ua = new_ua_context(jcr);
1422 foreach_alist(runcmd, job->run_cmds) {
1423 cmd = edit_job_codes(jcr, cmd, runcmd, "", job_code_callback_clones);
1424 Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1425 Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1426 parse_ua_args(ua); /* parse command */
1427 int stat = run_cmd(ua, ua->cmd);
1429 Jmsg(jcr, M_ERROR, 0, _("Could not start clone job: \"%s\".\n"),
1432 Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1435 free_ua_context(ua);
1436 free_pool_memory(cmd);
1441 * Given: a JobId in jcr->previous_jr.JobId,
1442 * this subroutine writes a bsr file to restore that job.
1443 * Returns: -1 on error
1444 * number of files if OK
1446 int create_restore_bootstrap_file(JCR *jcr)
1452 memset(&rx, 0, sizeof(rx));
1454 rx.JobIds = (char *)"";
1455 rx.bsr->JobId = jcr->previous_jr.JobId;
1456 ua = new_ua_context(jcr);
1457 if (!complete_bsr(ua, rx.bsr)) {
1461 rx.bsr->fi = new_findex();
1462 rx.bsr->fi->findex = 1;
1463 rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1464 jcr->ExpectedFiles = write_bsr_file(ua, rx);
1465 if (jcr->ExpectedFiles == 0) {
1469 free_ua_context(ua);
1471 jcr->needs_sd = true;
1472 return jcr->ExpectedFiles;
1475 free_ua_context(ua);
1480 /* TODO: redirect command ouput to job log */
1481 bool run_console_command(JCR *jcr, const char *cmd)
1485 JCR *ljcr = new_control_jcr("-RunScript-", JT_CONSOLE);
1486 ua = new_ua_context(ljcr);
1487 /* run from runscript and check if commands are autorized */
1488 ua->runscript = true;
1489 Mmsg(ua->cmd, "%s", cmd);
1490 Dmsg1(100, "Console command: %s\n", ua->cmd);
1492 ok= do_a_command(ua);
1493 free_ua_context(ua);