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 three of the GNU Affero 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 Affero 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_maxrunschedtime(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)
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_database(jcr, jcr->catalog->db_driver, jcr->catalog->db_name,
128 jcr->catalog->db_user, jcr->catalog->db_password,
129 jcr->catalog->db_address, jcr->catalog->db_port,
130 jcr->catalog->db_socket, jcr->catalog->mult_db_connections,
131 jcr->catalog->disable_batch_insert);
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");
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"));
150 if (jcr->JobReads()) {
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");
174 new_plugins(jcr); /* instantiate plugins for this jcr */
175 generate_plugin_event(jcr, bDirEventJobStart);
177 if (job_canceled(jcr)) {
181 if (jcr->JobReads() && !jcr->rstorage) {
182 if (jcr->job->storage) {
183 copy_rwstorage(jcr, jcr->job->storage, _("Job resource"));
185 copy_rwstorage(jcr, jcr->job->pool->storage, _("Pool resource"));
188 if (!jcr->JobReads()) {
193 * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
194 * this allows us to setup a proper job start record for restarting
195 * in case of later errors.
197 switch (jcr->getJobType()) {
199 if (!do_backup_init(jcr)) {
200 backup_cleanup(jcr, JS_ErrorTerminated);
205 if (!do_verify_init(jcr)) {
206 verify_cleanup(jcr, JS_ErrorTerminated);
211 if (!do_restore_init(jcr)) {
212 restore_cleanup(jcr, JS_ErrorTerminated);
217 if (!do_admin_init(jcr)) {
218 admin_cleanup(jcr, JS_ErrorTerminated);
224 if (!do_migration_init(jcr)) {
225 migration_cleanup(jcr, JS_ErrorTerminated);
230 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->getJobType());
231 jcr->setJobStatus(JS_ErrorTerminated);
235 generate_job_event(jcr, "JobInit");
236 generate_plugin_event(jcr, bDirEventJobInit);
244 void update_job_end(JCR *jcr, int TermCode)
246 dequeue_messages(jcr); /* display any queued messages */
247 jcr->setJobStatus(TermCode);
248 update_job_end_record(jcr);
252 * This is the engine called by jobq.c:jobq_add() when we were pulled
253 * from the work queue.
254 * At this point, we are running in our own thread and all
255 * necessary resources are allocated -- see jobq.c
257 static void *job_thread(void *arg)
259 JCR *jcr = (JCR *)arg;
261 pthread_detach(pthread_self());
264 Dmsg0(200, "=====Start Job=========\n");
265 jcr->setJobStatus(JS_Running); /* this will be set only if no error */
266 jcr->start_time = time(NULL); /* set the real start time */
267 jcr->jr.StartTime = jcr->start_time;
269 if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
270 (utime_t)(jcr->start_time - jcr->sched_time)) {
271 jcr->setJobStatus(JS_Canceled);
272 Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
275 if (job_check_maxrunschedtime(jcr)) {
276 jcr->setJobStatus(JS_Canceled);
277 Jmsg(jcr, M_FATAL, 0, _("Job canceled because max run sched time exceeded.\n"));
280 /* TODO : check if it is used somewhere */
281 if (jcr->job->RunScripts == NULL) {
282 Dmsg0(200, "Warning, job->RunScripts is empty\n");
283 jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
286 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
287 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
290 /* Run any script BeforeJob on dird */
291 run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
294 * We re-update the job start record so that the start
295 * time is set after the run before job. This avoids
296 * that any files created by the run before job will
297 * be saved twice. They will be backed up in the current
298 * job, but not in the next one unless they are changed.
299 * Without this, they will be backed up in this job and
300 * in the next job run because in that case, their date
301 * is after the start of this run.
303 jcr->start_time = time(NULL);
304 jcr->jr.StartTime = jcr->start_time;
305 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
306 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
308 generate_job_event(jcr, "JobRun");
309 generate_plugin_event(jcr, bDirEventJobRun);
311 switch (jcr->getJobType()) {
313 if (!job_canceled(jcr) && do_backup(jcr)) {
316 backup_cleanup(jcr, JS_ErrorTerminated);
320 if (!job_canceled(jcr) && do_verify(jcr)) {
323 verify_cleanup(jcr, JS_ErrorTerminated);
327 if (!job_canceled(jcr) && do_restore(jcr)) {
330 restore_cleanup(jcr, JS_ErrorTerminated);
334 if (!job_canceled(jcr) && do_admin(jcr)) {
337 admin_cleanup(jcr, JS_ErrorTerminated);
342 if (!job_canceled(jcr) && do_migration(jcr)) {
345 migration_cleanup(jcr, JS_ErrorTerminated);
349 Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->getJobType());
353 run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
355 /* Send off any queued messages */
356 if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
357 dequeue_messages(jcr);
360 generate_daemon_event(jcr, "JobEnd");
361 generate_plugin_event(jcr, bDirEventJobEnd);
362 Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
367 void sd_msg_thread_send_signal(JCR *jcr, int sig)
370 if ( !jcr->sd_msg_thread_done
372 && !pthread_equal(jcr->SD_msg_chan, pthread_self()))
374 Dmsg1(800, "Send kill to SD msg chan jid=%d\n", jcr->JobId);
375 pthread_kill(jcr->SD_msg_chan, sig);
381 * Cancel a job -- typically called by the UA (Console program), but may also
382 * be called by the job watchdog.
384 * Returns: true if cancel appears to be successful
385 * false on failure. Message sent to ua->jcr.
387 bool cancel_job(UAContext *ua, JCR *jcr)
391 int32_t old_status = jcr->JobStatus;
393 jcr->setJobStatus(JS_Canceled);
395 switch (old_status) {
398 case JS_WaitClientRes:
399 case JS_WaitStoreRes:
400 case JS_WaitPriority:
402 case JS_WaitStartTime:
403 ua->info_msg(_("JobId %s, Job %s marked to be canceled.\n"),
404 edit_uint64(jcr->JobId, ed1), jcr->Job);
405 jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
409 /* Cancel File daemon */
410 if (jcr->file_bsock) {
411 ua->jcr->client = jcr->client;
412 if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
413 ua->error_msg(_("Failed to connect to File daemon.\n"));
416 Dmsg0(200, "Connected to file daemon\n");
417 fd = ua->jcr->file_bsock;
418 fd->fsend("cancel Job=%s\n", jcr->Job);
419 while (fd->recv() >= 0) {
420 ua->send_msg("%s", fd->msg);
422 fd->signal(BNET_TERMINATE);
424 ua->jcr->file_bsock = NULL;
425 jcr->file_bsock->set_terminated();
426 jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
429 /* Cancel Storage daemon */
430 if (jcr->store_bsock) {
431 if (!ua->jcr->wstorage) {
433 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
435 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
440 store.store = jcr->rstore;
442 store.store = jcr->wstore;
444 set_wstorage(ua->jcr, &store);
447 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
448 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
451 Dmsg0(200, "Connected to storage daemon\n");
452 sd = ua->jcr->store_bsock;
453 sd->fsend("cancel Job=%s\n", jcr->Job);
454 while (sd->recv() >= 0) {
455 ua->send_msg("%s", sd->msg);
457 sd->signal(BNET_TERMINATE);
459 ua->jcr->store_bsock = NULL;
460 jcr->store_bsock->set_timed_out();
461 jcr->store_bsock->set_terminated();
462 sd_msg_thread_send_signal(jcr, TIMEOUT_SIGNAL);
463 jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
471 void cancel_storage_daemon_job(JCR *jcr)
473 if (jcr->sd_canceled) {
474 return; /* cancel only once */
477 UAContext *ua = new_ua_context(jcr);
478 JCR *control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);
481 ua->jcr = control_jcr;
482 if (jcr->store_bsock) {
483 if (!ua->jcr->wstorage) {
485 copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
487 copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
492 store.store = jcr->rstore;
494 store.store = jcr->wstore;
496 set_wstorage(ua->jcr, &store);
499 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
502 Dmsg0(200, "Connected to storage daemon\n");
503 sd = ua->jcr->store_bsock;
504 sd->fsend("cancel Job=%s\n", jcr->Job);
505 while (sd->recv() >= 0) {
507 sd->signal(BNET_TERMINATE);
509 ua->jcr->store_bsock = NULL;
510 jcr->sd_canceled = true;
511 jcr->store_bsock->set_timed_out();
512 jcr->store_bsock->set_terminated();
513 sd_msg_thread_send_signal(jcr, TIMEOUT_SIGNAL);
514 jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
517 free_jcr(control_jcr);
521 static void job_monitor_destructor(watchdog_t *self)
523 JCR *control_jcr = (JCR *)self->data;
525 free_jcr(control_jcr);
528 static void job_monitor_watchdog(watchdog_t *self)
530 JCR *control_jcr, *jcr;
532 control_jcr = (JCR *)self->data;
535 Dmsg1(800, "job_monitor_watchdog %p called\n", self);
540 if (jcr->JobId == 0 || job_canceled(jcr) || jcr->no_maxtime) {
541 Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
545 /* check MaxWaitTime */
546 if (job_check_maxwaittime(jcr)) {
547 jcr->setJobStatus(JS_Canceled);
548 Qmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
550 /* check MaxRunTime */
551 } else if (job_check_maxruntime(jcr)) {
552 jcr->setJobStatus(JS_Canceled);
553 Qmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
555 /* check MaxRunSchedTime */
556 } else if (job_check_maxrunschedtime(jcr)) {
557 jcr->setJobStatus(JS_Canceled);
558 Qmsg(jcr, M_FATAL, 0, _("Max run sched time exceeded. Job canceled.\n"));
563 Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
564 UAContext *ua = new_ua_context(jcr);
565 ua->jcr = control_jcr;
568 Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
572 /* Keep reference counts correct */
577 * Check if the maxwaittime has expired and it is possible
580 static bool job_check_maxwaittime(JCR *jcr)
586 if (!job_waiting(jcr)) {
590 if (jcr->wait_time) {
591 current = watchdog_time - jcr->wait_time;
594 Dmsg2(200, "check maxwaittime %u >= %u\n",
595 current + jcr->wait_time_sum, job->MaxWaitTime);
596 if (job->MaxWaitTime != 0 &&
597 (current + jcr->wait_time_sum) >= job->MaxWaitTime) {
605 * Check if maxruntime has expired and if the job can be
608 static bool job_check_maxruntime(JCR *jcr)
614 if (job_canceled(jcr) || jcr->JobStatus == JS_Created) {
617 if (jcr->job->MaxRunTime == 0 && job->FullMaxRunTime == 0 &&
618 job->IncMaxRunTime == 0 && job->DiffMaxRunTime == 0) {
621 run_time = watchdog_time - jcr->start_time;
622 Dmsg7(200, "check_maxruntime %llu-%u=%llu >= %llu|%llu|%llu|%llu\n",
623 watchdog_time, jcr->start_time, run_time, job->MaxRunTime, job->FullMaxRunTime,
624 job->IncMaxRunTime, job->DiffMaxRunTime);
626 if (jcr->getJobLevel() == L_FULL && job->FullMaxRunTime != 0 &&
627 run_time >= job->FullMaxRunTime) {
628 Dmsg0(200, "check_maxwaittime: FullMaxcancel\n");
630 } else if (jcr->getJobLevel() == L_DIFFERENTIAL && job->DiffMaxRunTime != 0 &&
631 run_time >= job->DiffMaxRunTime) {
632 Dmsg0(200, "check_maxwaittime: DiffMaxcancel\n");
634 } else if (jcr->getJobLevel() == L_INCREMENTAL && job->IncMaxRunTime != 0 &&
635 run_time >= job->IncMaxRunTime) {
636 Dmsg0(200, "check_maxwaittime: IncMaxcancel\n");
638 } else if (job->MaxRunTime > 0 && run_time >= job->MaxRunTime) {
639 Dmsg0(200, "check_maxwaittime: Maxcancel\n");
647 * Check if MaxRunSchedTime has expired and if the job can be
650 static bool job_check_maxrunschedtime(JCR *jcr)
652 if (jcr->MaxRunSchedTime == 0 || job_canceled(jcr)) {
655 if ((watchdog_time - jcr->sched_time) < jcr->MaxRunSchedTime) {
656 Dmsg3(200, "Job %p (%s) with MaxRunSchedTime %d not expired\n",
657 jcr, jcr->Job, jcr->MaxRunSchedTime);
665 * Get or create a Pool record with the given name.
666 * Returns: 0 on error
669 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
673 memset(&pr, 0, sizeof(pr));
674 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
675 Dmsg1(110, "get_or_create_pool=%s\n", pool_name);
677 while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
678 /* Try to create the pool */
679 if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
680 Jmsg(jcr, M_FATAL, 0, _("Pool \"%s\" not in database. ERR=%s"), pr.Name,
681 db_strerror(jcr->db));
684 Jmsg(jcr, M_INFO, 0, _("Created database record for Pool \"%s\".\n"), pr.Name);
691 * Check for duplicate jobs.
692 * Returns: true if current job should continue
693 * false if current job should terminate
695 bool allow_duplicate_job(JCR *jcr)
698 JCR *djcr; /* possible duplicate job */
699 bool cancel_dup = false;
700 bool cancel_me = false;
703 * See if AllowDuplicateJobs is set or
704 * if duplicate checking is disabled for this job.
706 if (job->AllowDuplicateJobs || jcr->IgnoreDuplicateJobChecking) {
710 Dmsg0(800, "Enter allow_duplicate_job\n");
713 * After this point, we do not want to allow any duplicate
718 if (jcr == djcr || djcr->JobId == 0) {
719 continue; /* do not cancel this job or consoles */
723 * See if this Job has the IgnoreDuplicateJobChecking flag set, ignore it
724 * for any checking against other jobs.
726 if (djcr->IgnoreDuplicateJobChecking) {
730 if (strcmp(job->name(), djcr->job->name()) == 0) {
731 if (job->DuplicateJobProximity > 0) {
732 utime_t now = (utime_t)time(NULL);
733 if ((now - djcr->start_time) > job->DuplicateJobProximity) {
734 continue; /* not really a duplicate */
737 if (job->CancelLowerLevelDuplicates &&
738 djcr->getJobType() == 'B' && jcr->getJobType() == 'B') {
739 switch (jcr->getJobLevel()) {
741 if (djcr->getJobLevel() == L_DIFFERENTIAL ||
742 djcr->getJobLevel() == L_INCREMENTAL) {
747 if (djcr->getJobLevel() == L_INCREMENTAL) {
750 if (djcr->getJobLevel() == L_FULL) {
755 if (djcr->getJobLevel() == L_FULL ||
756 djcr->getJobLevel() == L_DIFFERENTIAL) {
761 * cancel_dup will be done below
764 /* Zap current job */
765 jcr->setJobStatus(JS_Canceled);
766 Jmsg(jcr, M_FATAL, 0, _("JobId %d already running. Duplicate job not allowed.\n"),
768 break; /* get out of foreach_jcr */
773 * Cancel one of the two jobs (me or dup)
774 * If CancelQueuedDuplicates is set do so only if job is queued.
776 if (job->CancelQueuedDuplicates) {
777 switch (djcr->JobStatus) {
780 case JS_WaitClientRes:
781 case JS_WaitStoreRes:
782 case JS_WaitPriority:
784 case JS_WaitStartTime:
785 cancel_dup = true; /* cancel queued duplicate */
792 if (cancel_dup || job->CancelRunningDuplicates) {
794 * Zap the duplicated job djcr
796 UAContext *ua = new_ua_context(jcr);
797 Jmsg(jcr, M_INFO, 0, _("Cancelling duplicate JobId=%d.\n"), djcr->JobId);
798 cancel_job(ua, djcr);
799 bmicrosleep(0, 500000);
800 djcr->setJobStatus(JS_Canceled);
801 cancel_job(ua, djcr);
803 Dmsg2(800, "Cancel dup %p JobId=%d\n", djcr, djcr->JobId);
808 jcr->setJobStatus(JS_Canceled);
809 Jmsg(jcr, M_FATAL, 0, _("JobId %d already running. Duplicate job not allowed.\n"),
811 Dmsg2(800, "Cancel me %p JobId=%d\n", jcr, jcr->JobId);
813 Dmsg4(800, "curJobId=%d use_cnt=%d dupJobId=%d use_cnt=%d\n",
814 jcr->JobId, jcr->use_count(), djcr->JobId, djcr->use_count());
815 break; /* did our work, get out of foreach loop */
823 void apply_pool_overrides(JCR *jcr)
825 bool pool_override = false;
827 if (jcr->run_pool_override) {
828 pm_strcpy(jcr->pool_source, _("Run pool override"));
831 * Apply any level related Pool selections
833 switch (jcr->getJobLevel()) {
835 if (jcr->full_pool) {
836 jcr->pool = jcr->full_pool;
837 pool_override = true;
838 if (jcr->run_full_pool_override) {
839 pm_strcpy(jcr->pool_source, _("Run FullPool override"));
841 pm_strcpy(jcr->pool_source, _("Job FullPool override"));
847 jcr->pool = jcr->inc_pool;
848 pool_override = true;
849 if (jcr->run_inc_pool_override) {
850 pm_strcpy(jcr->pool_source, _("Run IncPool override"));
852 pm_strcpy(jcr->pool_source, _("Job IncPool override"));
857 if (jcr->diff_pool) {
858 jcr->pool = jcr->diff_pool;
859 pool_override = true;
860 if (jcr->run_diff_pool_override) {
861 pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
863 pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
868 /* Update catalog if pool overridden */
869 if (pool_override && jcr->pool->catalog) {
870 jcr->catalog = jcr->pool->catalog;
871 pm_strcpy(jcr->catalog_source, _("Pool resource"));
877 * Get or create a Client record for this Job
879 bool get_or_create_client_record(JCR *jcr)
883 memset(&cr, 0, sizeof(cr));
884 bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
885 cr.AutoPrune = jcr->client->AutoPrune;
886 cr.FileRetention = jcr->client->FileRetention;
887 cr.JobRetention = jcr->client->JobRetention;
888 if (!jcr->client_name) {
889 jcr->client_name = get_pool_memory(PM_NAME);
891 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
892 if (!db_create_client_record(jcr, jcr->db, &cr)) {
893 Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
894 db_strerror(jcr->db));
897 jcr->jr.ClientId = cr.ClientId;
899 if (!jcr->client_uname) {
900 jcr->client_uname = get_pool_memory(PM_NAME);
902 pm_strcpy(jcr->client_uname, cr.Uname);
904 Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
909 bool get_or_create_fileset_record(JCR *jcr)
913 * Get or Create FileSet record
915 memset(&fsr, 0, sizeof(FILESET_DBR));
916 bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
917 if (jcr->fileset->have_MD5) {
918 struct MD5Context md5c;
919 unsigned char digest[MD5HashSize];
920 memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
921 MD5Final(digest, &md5c);
923 * Keep the flag (last arg) set to false otherwise old FileSets will
924 * get new MD5 sums and the user will get Full backups on everything
926 bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
927 bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
929 Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
931 if (!jcr->fileset->ignore_fs_changes ||
932 !db_get_fileset_record(jcr, jcr->db, &fsr)) {
933 if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
934 Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
935 fsr.FileSet, db_strerror(jcr->db));
939 jcr->jr.FileSetId = fsr.FileSetId;
940 bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
941 Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
946 void init_jcr_job_record(JCR *jcr)
948 jcr->jr.SchedTime = jcr->sched_time;
949 jcr->jr.StartTime = jcr->start_time;
950 jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
951 jcr->jr.JobType = jcr->getJobType();
952 jcr->jr.JobLevel = jcr->getJobLevel();
953 jcr->jr.JobStatus = jcr->JobStatus;
954 jcr->jr.JobId = jcr->JobId;
955 bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
956 bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
960 * Write status and such in DB
962 void update_job_end_record(JCR *jcr)
964 jcr->jr.EndTime = time(NULL);
965 jcr->end_time = jcr->jr.EndTime;
966 jcr->jr.JobId = jcr->JobId;
967 jcr->jr.JobStatus = jcr->JobStatus;
968 jcr->jr.JobFiles = jcr->JobFiles;
969 jcr->jr.JobBytes = jcr->JobBytes;
970 jcr->jr.ReadBytes = jcr->ReadBytes;
971 jcr->jr.VolSessionId = jcr->VolSessionId;
972 jcr->jr.VolSessionTime = jcr->VolSessionTime;
973 jcr->jr.JobErrors = jcr->JobErrors;
974 jcr->jr.HasBase = jcr->HasBase;
975 if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
976 Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
977 db_strerror(jcr->db));
982 * Takes base_name and appends (unique) current
983 * date and time to form unique job name.
985 * Note, the seconds are actually a sequence number. This
986 * permits us to start a maximum fo 59 unique jobs a second, which
987 * should be sufficient.
989 * Returns: unique job name in jcr->Job
990 * date/time in jcr->start_time
992 void create_unique_job_name(JCR *jcr, const char *base_name)
994 /* Job start mutex */
995 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
996 static time_t last_start_time = 0;
998 time_t now = time(NULL);
1000 char dt[MAX_TIME_LENGTH];
1001 char name[MAX_NAME_LENGTH];
1005 /* Guarantee unique start time -- maximum one per second, and
1006 * thus unique Job Name
1008 P(mutex); /* lock creation of jobs */
1010 if (seq > 59) { /* wrap as if it is seconds */
1012 while (now == last_start_time) {
1013 bmicrosleep(0, 500000);
1017 last_start_time = now;
1018 V(mutex); /* allow creation of jobs */
1019 jcr->start_time = now;
1020 /* Form Unique JobName */
1021 (void)localtime_r(&now, &tm);
1022 /* Use only characters that are permitted in Windows filenames */
1023 strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
1024 len = strlen(dt) + 5; /* dt + .%02d EOS */
1025 bstrncpy(name, base_name, sizeof(name));
1026 name[sizeof(name)-len] = 0; /* truncate if too long */
1027 bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s_%02d", name, dt, seq); /* add date & time */
1028 /* Convert spaces into underscores */
1029 for (p=jcr->Job; *p; p++) {
1034 Dmsg2(100, "JobId=%u created Job=%s\n", jcr->JobId, jcr->Job);
1037 /* Called directly from job rescheduling */
1038 void dird_free_jcr_pointers(JCR *jcr)
1040 if (jcr->file_bsock) {
1041 Dmsg0(200, "Close File bsock\n");
1042 bnet_close(jcr->file_bsock);
1043 jcr->file_bsock = NULL;
1045 if (jcr->store_bsock) {
1046 Dmsg0(200, "Close Store bsock\n");
1047 bnet_close(jcr->store_bsock);
1048 jcr->store_bsock = NULL;
1051 bfree_and_null(jcr->sd_auth_key);
1052 bfree_and_null(jcr->where);
1053 bfree_and_null(jcr->RestoreBootstrap);
1054 bfree_and_null(jcr->ar);
1056 free_and_null_pool_memory(jcr->JobIds);
1057 free_and_null_pool_memory(jcr->client_uname);
1058 free_and_null_pool_memory(jcr->attr);
1059 free_and_null_pool_memory(jcr->fname);
1063 * Free the Job Control Record if no one is still using it.
1064 * Called from main free_jcr() routine in src/lib/jcr.c so
1065 * that we can do our Director specific cleanup of the jcr.
1067 void dird_free_jcr(JCR *jcr)
1069 Dmsg0(200, "Start dird free_jcr\n");
1071 dird_free_jcr_pointers(jcr);
1072 if (jcr->term_wait_inited) {
1073 pthread_cond_destroy(&jcr->term_wait);
1074 jcr->term_wait_inited = false;
1076 if (jcr->db_batch) {
1077 db_close_database(jcr, jcr->db_batch);
1078 jcr->db_batch = NULL;
1079 jcr->batch_started = false;
1082 db_close_database(jcr, jcr->db);
1086 free_and_null_pool_memory(jcr->stime);
1087 free_and_null_pool_memory(jcr->fname);
1088 free_and_null_pool_memory(jcr->pool_source);
1089 free_and_null_pool_memory(jcr->catalog_source);
1090 free_and_null_pool_memory(jcr->rpool_source);
1091 free_and_null_pool_memory(jcr->wstore_source);
1092 free_and_null_pool_memory(jcr->rstore_source);
1094 /* Delete lists setup to hold storage pointers */
1095 free_rwstorage(jcr);
1097 jcr->job_end_push.destroy();
1099 if (jcr->JobId != 0)
1100 write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
1102 free_plugins(jcr); /* release instantiated plugins */
1104 Dmsg0(200, "End dird free_jcr\n");
1108 * The Job storage definition must be either in the Job record
1109 * or in the Pool record. The Pool record overrides the Job
1112 void get_job_storage(USTORE *store, JOB *job, RUN *run)
1114 if (run && run->pool && run->pool->storage) {
1115 store->store = (STORE *)run->pool->storage->first();
1116 pm_strcpy(store->store_source, _("Run pool override"));
1119 if (run && run->storage) {
1120 store->store = run->storage;
1121 pm_strcpy(store->store_source, _("Run storage override"));
1124 if (job->pool->storage) {
1125 store->store = (STORE *)job->pool->storage->first();
1126 pm_strcpy(store->store_source, _("Pool resource"));
1128 store->store = (STORE *)job->storage->first();
1129 pm_strcpy(store->store_source, _("Job resource"));
1134 * Set some defaults in the JCR necessary to
1135 * run. These items are pulled from the job
1136 * definition as defaults, but can be overridden
1137 * later either by the Run record in the Schedule resource,
1138 * or by the Console program.
1140 void set_jcr_defaults(JCR *jcr, JOB *job)
1143 jcr->setJobType(job->JobType);
1144 jcr->JobStatus = JS_Created;
1146 switch (jcr->getJobType()) {
1148 jcr->setJobLevel(L_NONE);
1151 jcr->setJobLevel(job->JobLevel);
1156 jcr->fname = get_pool_memory(PM_FNAME);
1158 if (!jcr->pool_source) {
1159 jcr->pool_source = get_pool_memory(PM_MESSAGE);
1160 pm_strcpy(jcr->pool_source, _("unknown source"));
1162 if (!jcr->catalog_source) {
1163 jcr->catalog_source = get_pool_memory(PM_MESSAGE);
1164 pm_strcpy(jcr->catalog_source, _("unknown source"));
1167 jcr->JobPriority = job->Priority;
1168 /* Copy storage definitions -- deleted in dir_free_jcr above */
1170 copy_rwstorage(jcr, job->storage, _("Job resource"));
1172 copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
1174 jcr->client = job->client;
1175 if (!jcr->client_name) {
1176 jcr->client_name = get_pool_memory(PM_NAME);
1178 pm_strcpy(jcr->client_name, jcr->client->hdr.name);
1179 pm_strcpy(jcr->pool_source, _("Job resource"));
1180 jcr->pool = job->pool;
1181 jcr->full_pool = job->full_pool;
1182 jcr->inc_pool = job->inc_pool;
1183 jcr->diff_pool = job->diff_pool;
1184 if (job->pool->catalog) {
1185 jcr->catalog = job->pool->catalog;
1186 pm_strcpy(jcr->catalog_source, _("Pool resource"));
1188 jcr->catalog = job->client->catalog;
1189 pm_strcpy(jcr->catalog_source, _("Client resource"));
1191 jcr->fileset = job->fileset;
1192 jcr->accurate = job->accurate;
1193 jcr->messages = job->messages;
1194 jcr->spool_data = job->spool_data;
1195 jcr->spool_size = job->spool_size;
1196 jcr->write_part_after_job = job->write_part_after_job;
1197 jcr->IgnoreDuplicateJobChecking = job->IgnoreDuplicateJobChecking;
1198 jcr->MaxRunSchedTime = job->MaxRunSchedTime;
1199 if (jcr->RestoreBootstrap) {
1200 free(jcr->RestoreBootstrap);
1201 jcr->RestoreBootstrap = NULL;
1203 /* This can be overridden by Console program */
1204 if (job->RestoreBootstrap) {
1205 jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1207 /* This can be overridden by Console program */
1208 jcr->verify_job = job->verify_job;
1209 /* If no default level given, set one */
1210 if (jcr->getJobLevel() == 0) {
1211 switch (jcr->getJobType()) {
1213 jcr->setJobLevel(L_VERIFY_CATALOG);
1216 jcr->setJobLevel(L_INCREMENTAL);
1220 jcr->setJobLevel(L_NONE);
1223 jcr->setJobLevel(L_FULL);
1230 * Copy the storage definitions from an alist to the JCR
1232 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1234 if (jcr->JobReads()) {
1235 copy_rstorage(jcr, storage, where);
1237 copy_wstorage(jcr, storage, where);
1241 /* Set storage override. Releases any previous storage definition */
1242 void set_rwstorage(JCR *jcr, USTORE *store)
1245 Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1248 if (jcr->JobReads()) {
1249 set_rstorage(jcr, store);
1251 set_wstorage(jcr, store);
1254 void free_rwstorage(JCR *jcr)
1261 * Copy the storage definitions from an alist to the JCR
1263 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1267 if (jcr->rstorage) {
1268 delete jcr->rstorage;
1270 jcr->rstorage = New(alist(10, not_owned_by_alist));
1271 foreach_alist(st, storage) {
1272 jcr->rstorage->append(st);
1274 if (!jcr->rstore_source) {
1275 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1277 pm_strcpy(jcr->rstore_source, where);
1278 if (jcr->rstorage) {
1279 jcr->rstore = (STORE *)jcr->rstorage->first();
1285 /* Set storage override. Remove all previous storage */
1286 void set_rstorage(JCR *jcr, USTORE *store)
1290 if (!store->store) {
1293 if (jcr->rstorage) {
1296 if (!jcr->rstorage) {
1297 jcr->rstorage = New(alist(10, not_owned_by_alist));
1299 jcr->rstore = store->store;
1300 if (!jcr->rstore_source) {
1301 jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1303 pm_strcpy(jcr->rstore_source, store->store_source);
1304 foreach_alist(storage, jcr->rstorage) {
1305 if (store->store == storage) {
1309 /* Store not in list, so add it */
1310 jcr->rstorage->prepend(store->store);
1313 void free_rstorage(JCR *jcr)
1315 if (jcr->rstorage) {
1316 delete jcr->rstorage;
1317 jcr->rstorage = NULL;
1323 * Copy the storage definitions from an alist to the JCR
1325 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1329 if (jcr->wstorage) {
1330 delete jcr->wstorage;
1332 jcr->wstorage = New(alist(10, not_owned_by_alist));
1333 foreach_alist(st, storage) {
1334 Dmsg1(100, "wstorage=%s\n", st->name());
1335 jcr->wstorage->append(st);
1337 if (!jcr->wstore_source) {
1338 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1340 pm_strcpy(jcr->wstore_source, where);
1341 if (jcr->wstorage) {
1342 jcr->wstore = (STORE *)jcr->wstorage->first();
1343 Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1349 /* Set storage override. Remove all previous storage */
1350 void set_wstorage(JCR *jcr, USTORE *store)
1354 if (!store->store) {
1357 if (jcr->wstorage) {
1360 if (!jcr->wstorage) {
1361 jcr->wstorage = New(alist(10, not_owned_by_alist));
1363 jcr->wstore = store->store;
1364 if (!jcr->wstore_source) {
1365 jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1367 pm_strcpy(jcr->wstore_source, store->store_source);
1368 Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1369 foreach_alist(storage, jcr->wstorage) {
1370 if (store->store == storage) {
1374 /* Store not in list, so add it */
1375 jcr->wstorage->prepend(store->store);
1378 void free_wstorage(JCR *jcr)
1380 if (jcr->wstorage) {
1381 delete jcr->wstorage;
1382 jcr->wstorage = NULL;
1387 void create_clones(JCR *jcr)
1390 * Fire off any clone jobs (run directives)
1392 Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1393 if (!jcr->cloned && jcr->job->run_cmds) {
1395 JOB *job = jcr->job;
1396 POOLMEM *cmd = get_pool_memory(PM_FNAME);
1397 UAContext *ua = new_ua_context(jcr);
1399 foreach_alist(runcmd, job->run_cmds) {
1400 cmd = edit_job_codes(jcr, cmd, runcmd, "", job_code_callback_director);
1401 Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1402 Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1403 parse_ua_args(ua); /* parse command */
1404 int stat = run_cmd(ua, ua->cmd);
1406 Jmsg(jcr, M_ERROR, 0, _("Could not start clone job: \"%s\".\n"),
1409 Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1412 free_ua_context(ua);
1413 free_pool_memory(cmd);
1418 * Given: a JobId in jcr->previous_jr.JobId,
1419 * this subroutine writes a bsr file to restore that job.
1420 * Returns: -1 on error
1421 * number of files if OK
1423 int create_restore_bootstrap_file(JCR *jcr)
1429 memset(&rx, 0, sizeof(rx));
1431 rx.JobIds = (char *)"";
1432 rx.bsr->JobId = jcr->previous_jr.JobId;
1433 ua = new_ua_context(jcr);
1434 if (!complete_bsr(ua, rx.bsr)) {
1438 rx.bsr->fi = new_findex();
1439 rx.bsr->fi->findex = 1;
1440 rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1441 jcr->ExpectedFiles = write_bsr_file(ua, rx);
1442 if (jcr->ExpectedFiles == 0) {
1446 free_ua_context(ua);
1448 jcr->needs_sd = true;
1449 return jcr->ExpectedFiles;
1452 free_ua_context(ua);
1457 /* TODO: redirect command ouput to job log */
1458 bool run_console_command(JCR *jcr, const char *cmd)
1462 JCR *ljcr = new_control_jcr("-RunScript-", JT_CONSOLE);
1463 ua = new_ua_context(ljcr);
1464 /* run from runscript and check if commands are authorized */
1465 ua->runscript = true;
1466 Mmsg(ua->cmd, "%s", cmd);
1467 Dmsg1(100, "Console command: %s\n", ua->cmd);
1469 if (ua->argc > 0 && ua->argk[0][0] == '.') {
1470 ok = do_a_dot_command(ua);
1472 ok = do_a_command(ua);
1474 free_ua_context(ua);