/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark ofJohn Walker.
+ Bacula® is a registered trademark of John Walker.
The licensor of Bacula is the Free Software Foundation Europe
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
{
int stat;
if (setup_job(jcr)) {
+ Dmsg0(200, "Add jrc to work queue\n");
/* Queue the job to be run */
if ((stat = jobq_add(&job_queue, jcr)) != 0) {
berrno be;
}
jcr->term_wait_inited = true;
- create_unique_job_name(jcr, jcr->job->hdr.name);
+ create_unique_job_name(jcr, jcr->job->name());
set_jcr_job_status(jcr, JS_Created);
jcr->unlock();
/*
* Open database
*/
- Dmsg0(50, "Open database\n");
+ Dmsg0(150, "Open database\n");
jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user,
jcr->catalog->db_password, jcr->catalog->db_address,
jcr->catalog->db_port, jcr->catalog->db_socket,
}
goto bail_out;
}
- Dmsg0(50, "DB opened\n");
+ Dmsg0(150, "DB opened\n");
if (!jcr->fname) {
jcr->fname = get_pool_memory(PM_FNAME);
jcr->pool_source = get_pool_memory(PM_MESSAGE);
pm_strcpy(jcr->pool_source, _("unknown source"));
}
- if (!jcr->storage_source) {
- jcr->storage_source = get_pool_memory(PM_MESSAGE);
- pm_strcpy(jcr->storage_source, _("unknown source"));
+ Dmsg2(500, "pool=%s (From %s)\n", jcr->pool->name(), jcr->pool_source);
+ if (jcr->JobType == JT_MIGRATE) {
+ if (!jcr->rpool_source) {
+ jcr->rpool_source = get_pool_memory(PM_MESSAGE);
+ pm_strcpy(jcr->rpool_source, _("unknown source"));
+ }
}
/*
* Create Job record
*/
init_jcr_job_record(jcr);
+ if (!get_or_create_client_record(jcr)) {
+ goto bail_out;
+ }
+
if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
goto bail_out;
generate_daemon_event(jcr, "JobStart");
- if (!get_or_create_client_record(jcr)) {
- goto bail_out;
- }
-
if (job_canceled(jcr)) {
goto bail_out;
}
-
/*
* Now, do pre-run stuff, like setting job level (Inc/diff, ...)
* this allows us to setup a proper job start record for restarting
}
generate_job_event(jcr, "JobInit");
-
- Dmsg0(200, "Add jrc to work queue\n");
return true;
bail_out:
return false;
}
+void update_job_end(JCR *jcr, int TermCode)
+{
+ dequeue_messages(jcr); /* display any queued messages */
+ set_jcr_job_status(jcr, TermCode);
+ update_job_end_record(jcr);
+}
/*
* This is the engine called by jobq.c:jobq_add() when we were pulled
if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
(utime_t)(jcr->start_time - jcr->sched_time)) {
- Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
set_jcr_job_status(jcr, JS_Canceled);
+ Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
}
/* TODO : check if it is used somewhere */
run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
if (job_canceled(jcr)) {
- update_job_end_record(jcr);
+ update_job_end(jcr, jcr->JobStatus);
} else {
/*
Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
break;
}
+ }
- run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
+ run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
- /* Send off any queued messages */
- if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
- dequeue_messages(jcr);
- }
+ /* Send off any queued messages */
+ if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
+ dequeue_messages(jcr);
}
generate_daemon_event(jcr, "JobEnd");
bool cancel_job(UAContext *ua, JCR *jcr)
{
BSOCK *sd, *fd;
+ char ed1[50];
set_jcr_job_status(jcr, JS_Canceled);
case JS_WaitPriority:
case JS_WaitMaxJobs:
case JS_WaitStartTime:
- bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"),
- jcr->JobId, jcr->Job);
+ bsendmsg(ua, _("JobId %s, Job %s marked to be canceled.\n"),
+ edit_uint64(jcr->JobId, ed1), jcr->Job);
jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
return true;
copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
}
} else {
+ USTORE store;
if (jcr->rstorage) {
- set_wstorage(ua->jcr, jcr->rstore);
+ store.store = jcr->rstore;
} else {
- set_wstorage(ua->jcr, jcr->wstore);
+ store.store = jcr->wstore;
}
+ set_wstorage(ua->jcr, &store);
}
+
if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
return false;
Dmsg1(800, "job_monitor_watchdog %p called\n", self);
foreach_jcr(jcr) {
- bool cancel;
+ bool cancel = false;
- if (jcr->JobId == 0) {
- Dmsg2(800, "Skipping JCR %p (%s) with JobId 0\n",
- jcr, jcr->Job);
+ if (jcr->JobId == 0 || job_canceled(jcr)) {
+ Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
continue;
}
/* check MaxWaitTime */
- cancel = job_check_maxwaittime(control_jcr, jcr);
-
+ if (job_check_maxwaittime(control_jcr, jcr)) {
+ set_jcr_job_status(jcr, JS_Canceled);
+ Jmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
+ cancel = true;
/* check MaxRunTime */
- cancel |= job_check_maxruntime(control_jcr, jcr);
+ } else if (job_check_maxruntime(control_jcr, jcr)) {
+ set_jcr_job_status(jcr, JS_Canceled);
+ Jmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
+ cancel = true;
+ }
if (cancel) {
- Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n",
- jcr, jcr->JobId, jcr->Job);
-
+ Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
UAContext *ua = new_ua_context(jcr);
ua->jcr = control_jcr;
cancel_job(ua, jcr);
free_ua_context(ua);
-
Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
}
- /* Keep reference counts correct */
}
+ /* Keep reference counts correct */
endeach_jcr(jcr);
}
static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
{
bool cancel = false;
- bool ok_to_cancel = false;
JOB *job = jcr->job;
+ if (job_canceled(jcr)) {
+ return false; /* already canceled */
+ }
if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
return false;
}
if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
(watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
- ok_to_cancel = true;
+ cancel = true;
} else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
(watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
- ok_to_cancel = true;
+ cancel = true;
} else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
(watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
- ok_to_cancel = true;
+ cancel = true;
} else if (job->MaxWaitTime != 0 &&
(watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
- ok_to_cancel = true;
- }
- if (!ok_to_cancel) {
- return false;
- }
- Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, "
- "checking status\n",
- jcr->JobId, jcr->Job, job->MaxWaitTime);
- switch (jcr->JobStatus) {
- case JS_Created:
- case JS_Blocked:
- case JS_WaitFD:
- case JS_WaitSD:
- case JS_WaitStoreRes:
- case JS_WaitClientRes:
- case JS_WaitJobRes:
- case JS_WaitPriority:
- case JS_WaitMaxJobs:
- case JS_WaitStartTime:
cancel = true;
- Dmsg0(200, "JCR blocked in #1\n");
- break;
- case JS_Running:
- Dmsg0(800, "JCR running, checking SD status\n");
- switch (jcr->SDJobStatus) {
- case JS_WaitMount:
- case JS_WaitMedia:
- case JS_WaitFD:
- cancel = true;
- Dmsg0(800, "JCR blocked in #2\n");
- break;
- default:
- Dmsg0(800, "JCR not blocked in #2\n");
- break;
- }
- break;
- case JS_Terminated:
- case JS_ErrorTerminated:
- case JS_Canceled:
- case JS_FatalError:
- Dmsg0(800, "JCR already dead in #3\n");
- break;
- default:
- Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
- jcr->JobStatus);
}
- Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n",
- cancel ? "" : "do not ", jcr, jcr->job);
return cancel;
}
*/
static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
{
- bool cancel = false;
-
- if (jcr->job->MaxRunTime == 0) {
+ if (jcr->job->MaxRunTime == 0 || job_canceled(jcr)) {
return false;
}
if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
return false;
}
- switch (jcr->JobStatus) {
- case JS_Created:
- case JS_Running:
- case JS_Blocked:
- case JS_WaitFD:
- case JS_WaitSD:
- case JS_WaitStoreRes:
- case JS_WaitClientRes:
- case JS_WaitJobRes:
- case JS_WaitPriority:
- case JS_WaitMaxJobs:
- case JS_WaitStartTime:
- case JS_Differences:
- cancel = true;
- break;
- case JS_Terminated:
- case JS_ErrorTerminated:
- case JS_Canceled:
- case JS_FatalError:
- cancel = false;
- break;
- default:
- Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"),
- jcr->JobStatus);
- }
-
- Dmsg3(200, "MaxRunTime result: %scancel JCR %p (%s)\n",
- cancel ? "" : "do not ", jcr, jcr->job);
-
- return cancel;
+ return true;
}
/*
memset(&pr, 0, sizeof(pr));
bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
+ Dmsg1(110, "get_or_create_pool=%s\n", pool_name);
while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
/* Try to create the pool */
void apply_pool_overrides(JCR *jcr)
{
if (jcr->run_pool_override) {
- pm_strcpy(jcr->pool_source, _("Run Pool override"));
+ pm_strcpy(jcr->pool_source, _("Run pool override"));
}
/*
* Apply any level related Pool selections
jcr->jr.JobLevel = jcr->JobLevel;
jcr->jr.JobStatus = jcr->JobStatus;
jcr->jr.JobId = jcr->JobId;
- bstrncpy(jcr->jr.Name, jcr->job->hdr.name, sizeof(jcr->jr.Name));
+ bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
}
free_pool_memory(jcr->fname);
jcr->fname = NULL;
}
- if (jcr->pool_source) {
- free_pool_memory(jcr->pool_source);
- jcr->pool_source = NULL;
- }
- if (jcr->storage_source) {
- free_pool_memory(jcr->storage_source);
- jcr->storage_source = NULL;
- }
- if (jcr->stime) {
- Dmsg0(200, "Free JCR stime\n");
- free_pool_memory(jcr->stime);
- jcr->stime = NULL;
- }
if (jcr->RestoreBootstrap) {
free(jcr->RestoreBootstrap);
jcr->RestoreBootstrap = NULL;
pthread_cond_destroy(&jcr->term_wait);
jcr->term_wait_inited = false;
}
+ if (jcr->db) {
+ db_close_database(jcr, jcr->db);
+ jcr->db = NULL;
+ }
+ if (jcr->db_batch) {
+ db_close_database(jcr, jcr->db_batch);
+ jcr->db_batch = NULL;
+ }
+ if (jcr->stime) {
+ Dmsg0(200, "Free JCR stime\n");
+ free_pool_memory(jcr->stime);
+ jcr->stime = NULL;
+ }
+ if (jcr->fname) {
+ Dmsg0(200, "Free JCR fname\n");
+ free_pool_memory(jcr->fname);
+ jcr->fname = NULL;
+ }
+ if (jcr->pool_source) {
+ free_pool_memory(jcr->pool_source);
+ jcr->pool_source = NULL;
+ }
+ if (jcr->rpool_source) {
+ free_pool_memory(jcr->rpool_source);
+ jcr->rpool_source = NULL;
+ }
+ if (jcr->wstore_source) {
+ free_pool_memory(jcr->wstore_source);
+ jcr->wstore_source = NULL;
+ }
+ if (jcr->rstore_source) {
+ free_pool_memory(jcr->rstore_source);
+ jcr->rstore_source = NULL;
+ }
/* Delete lists setup to hold storage pointers */
free_rwstorage(jcr);
Dmsg0(200, "End dird free_jcr\n");
}
+/*
+ * The Job storage definition must be either in the Job record
+ * or in the Pool record. The Pool record overrides the Job
+ * record.
+ */
+void get_job_storage(USTORE *store, JOB *job, RUN *run)
+{
+ if (run && run->pool && run->pool->storage) {
+ store->store = (STORE *)run->pool->storage->first();
+ pm_strcpy(store->store_source, _("Run pool override"));
+ return;
+ }
+ if (run && run->storage) {
+ store->store = run->storage;
+ pm_strcpy(store->store_source, _("Run storage override"));
+ return;
+ }
+ if (job->pool->storage) {
+ store->store = (STORE *)job->pool->storage->first();
+ pm_strcpy(store->store_source, _("Pool resource"));
+ } else {
+ store->store = (STORE *)job->storage->first();
+ pm_strcpy(store->store_source, _("Job resource"));
+ }
+}
+
/*
* Set some defaults in the JCR necessary to
* run. These items are pulled from the job
case JT_RESTORE:
jcr->JobLevel = L_NONE;
break;
+ case JT_MIGRATE:
+ if (!jcr->rpool_source) {
+ jcr->rpool_source = get_pool_memory(PM_MESSAGE);
+ pm_strcpy(jcr->rpool_source, _("unknown source"));
+ }
+ /* Fall-through wanted */
default:
jcr->JobLevel = job->JobLevel;
break;
jcr->pool_source = get_pool_memory(PM_MESSAGE);
pm_strcpy(jcr->pool_source, _("unknown source"));
}
- if (!jcr->storage_source) {
- jcr->storage_source = get_pool_memory(PM_MESSAGE);
- pm_strcpy(jcr->storage_source, _("unknown source"));
- }
+
jcr->JobPriority = job->Priority;
/* Copy storage definitions -- deleted in dir_free_jcr above */
- copy_rwstorage(jcr, job->storage, _("Job resource"));
+ if (job->storage) {
+ copy_rwstorage(jcr, job->storage, _("Job resource"));
+ } else {
+ copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
+ }
jcr->client = job->client;
if (!jcr->client_name) {
jcr->client_name = get_pool_memory(PM_NAME);
jcr->JobLevel = L_NONE;
break;
default:
+ jcr->JobLevel = L_FULL;
break;
}
}
*/
void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
{
- copy_rstorage(jcr, storage, where);
- copy_wstorage(jcr, storage, where);
+ switch(jcr->JobType) {
+ case JT_RESTORE:
+ case JT_VERIFY:
+ case JT_MIGRATE:
+ copy_rstorage(jcr, storage, where);
+ break;
+ default:
+ copy_wstorage(jcr, storage, where);
+ break;
+ }
}
/* Set storage override */
-void set_rwstorage(JCR *jcr, STORE *store)
+void set_rwstorage(JCR *jcr, USTORE *store)
{
- set_rstorage(jcr, store);
- set_wstorage(jcr, store);
+ if (!store) {
+ Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
+ return;
+ }
+ switch(jcr->JobType) {
+ case JT_RESTORE:
+ case JT_VERIFY:
+ case JT_MIGRATE:
+ set_rstorage(jcr, store);
+ break;
+ default:
+ set_wstorage(jcr, store);
+ break;
+ }
}
void free_rwstorage(JCR *jcr)
foreach_alist(st, storage) {
jcr->rstorage->append(st);
}
- pm_strcpy(jcr->storage_source, where);
- }
- if (jcr->rstorage) {
- jcr->rstore = (STORE *)jcr->rstorage->first();
+ if (!jcr->rstore_source) {
+ jcr->rstore_source = get_pool_memory(PM_MESSAGE);
+ }
+ pm_strcpy(jcr->rstore_source, where);
+ if (jcr->rstorage) {
+ jcr->rstore = (STORE *)jcr->rstorage->first();
+ }
}
}
/* Set storage override */
-void set_rstorage(JCR *jcr, STORE *store)
+void set_rstorage(JCR *jcr, USTORE *store)
{
STORE *storage;
- jcr->rstore = store;
+ if (!store->store) {
+ return;
+ }
+ if (!jcr->rstorage) {
+ jcr->rstorage = New(alist(10, not_owned_by_alist));
+ }
+ jcr->rstore = store->store;
+ if (!jcr->rstore_source) {
+ jcr->rstore_source = get_pool_memory(PM_MESSAGE);
+ }
+ pm_strcpy(jcr->rstore_source, store->store_source);
foreach_alist(storage, jcr->rstorage) {
- if (store == storage) {
+ if (store->store == storage) {
return;
}
}
/* Store not in list, so add it */
- jcr->rstorage->prepend(store);
+ jcr->rstorage->prepend(store->store);
}
void free_rstorage(JCR *jcr)
}
jcr->wstorage = New(alist(10, not_owned_by_alist));
foreach_alist(st, storage) {
+ Dmsg1(100, "wstorage=%s\n", st->name());
jcr->wstorage->append(st);
}
- pm_strcpy(jcr->storage_source, where);
- }
- if (jcr->wstorage) {
- jcr->wstore = (STORE *)jcr->wstorage->first();
+ if (!jcr->wstore_source) {
+ jcr->wstore_source = get_pool_memory(PM_MESSAGE);
+ }
+ pm_strcpy(jcr->wstore_source, where);
+ if (jcr->wstorage) {
+ jcr->wstore = (STORE *)jcr->wstorage->first();
+ Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
+ }
}
}
/* Set storage override */
-void set_wstorage(JCR *jcr, STORE *store)
+void set_wstorage(JCR *jcr, USTORE *store)
{
STORE *storage;
- jcr->wstore = store;
+ if (!store->store) {
+ return;
+ }
+ if (!jcr->wstorage) {
+ jcr->wstorage = New(alist(10, not_owned_by_alist));
+ }
+ jcr->wstore = store->store;
+ if (!jcr->wstore_source) {
+ jcr->wstore_source = get_pool_memory(PM_MESSAGE);
+ }
+ pm_strcpy(jcr->wstore_source, store->store_source);
+ Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
foreach_alist(storage, jcr->wstorage) {
- if (store == storage) {
+ if (store->store == storage) {
return;
}
}
/* Store not in list, so add it */
- jcr->wstorage->prepend(store);
+ jcr->wstorage->prepend(store->store);
}
void free_wstorage(JCR *jcr)
jcr->wstore = NULL;
}
-
-
void create_clones(JCR *jcr)
{
/*