X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fjob.c;h=70be904b25069ab1c3dd83bcf47294726a3eae40;hb=c205f98aff775e96e18dc0af2f194e76f2ddaaa9;hp=d71fb8fb23c4232bbcfc94acfbb0f8a928260431;hpb=6c210279bc094ec7bfedf140e515ed98eb2734a3;p=bacula%2Fbacula diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index d71fb8fb23..70be904b25 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + 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. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + 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. +*/ /* * * Bacula Director Job processing routines @@ -6,20 +33,6 @@ * * Version $Id$ */ -/* - Copyright (C) 2000-2006 Kern Sibbald - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - version 2 as amended with additional clauses defined in the - file LICENSE in the main source directory. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - the file LICENSE for additional details. - - */ #include "bacula.h" #include "dird.h" @@ -46,7 +59,7 @@ void init_job_server(int max_workers) if ((stat = jobq_init(&job_queue, max_workers, job_thread)) != 0) { berrno be; - Emsg1(M_ABORT, 0, _("Could not init job queue: ERR=%s\n"), be.strerror(stat)); + Emsg1(M_ABORT, 0, _("Could not init job queue: ERR=%s\n"), be.bstrerror(stat)); } wd = new_watchdog(); wd->callback = job_monitor_watchdog; @@ -74,10 +87,11 @@ JobId_t run_job(JCR *jcr) { 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; - Jmsg(jcr, M_FATAL, 0, _("Could not add job queue: ERR=%s\n"), be.strerror(stat)); + Jmsg(jcr, M_FATAL, 0, _("Could not add job queue: ERR=%s\n"), be.bstrerror(stat)); return 0; } return jcr->JobId; @@ -96,19 +110,19 @@ bool setup_job(JCR *jcr) /* Initialize termination condition variable */ if ((errstat = pthread_cond_init(&jcr->term_wait, NULL)) != 0) { berrno be; - Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.strerror(errstat)); + Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.bstrerror(errstat)); goto bail_out; } 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(100, "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, @@ -118,10 +132,11 @@ bool setup_job(JCR *jcr) jcr->catalog->db_name); if (jcr->db) { Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); + db_close_database(jcr, jcr->db); } goto bail_out; } - Dmsg0(50, "DB opened\n"); + Dmsg0(150, "DB opened\n"); if (!jcr->fname) { jcr->fname = get_pool_memory(PM_FNAME); @@ -130,15 +145,22 @@ bool setup_job(JCR *jcr) 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; @@ -149,15 +171,10 @@ bool setup_job(JCR *jcr) 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 @@ -196,14 +213,19 @@ bool setup_job(JCR *jcr) } generate_job_event(jcr, "JobInit"); - - Dmsg0(200, "Add jrc to work queue\n"); + Dsm_check(1); 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 @@ -217,7 +239,7 @@ static void *job_thread(void *arg) jcr->my_thread_id = pthread_self(); pthread_detach(jcr->my_thread_id); - sm_check(__FILE__, __LINE__, true); + Dsm_check(1); Dmsg0(200, "=====Start Job=========\n"); set_jcr_job_status(jcr, JS_Running); /* this will be set only if no error */ @@ -226,8 +248,8 @@ static void *job_thread(void *arg) 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 */ @@ -240,12 +262,13 @@ static void *job_thread(void *arg) Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); } + /* Run any script BeforeJob on dird */ + run_scripts(jcr, jcr->job->RunScripts, "BeforeJob"); + if (job_canceled(jcr)) { - update_job_end_record(jcr); - } else { - /* Run any script BeforeJob on dird */ - run_scripts(jcr, jcr->job->RunScripts, "BeforeJob"); + update_job_end(jcr, jcr->JobStatus); + } else { /* * We re-update the job start record so that the start * time is set after the run before job. This avoids @@ -305,13 +328,13 @@ static void *job_thread(void *arg) 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"); @@ -331,6 +354,7 @@ static void *job_thread(void *arg) bool cancel_job(UAContext *ua, JCR *jcr) { BSOCK *sd, *fd; + char ed1[50]; set_jcr_job_status(jcr, JS_Canceled); @@ -342,8 +366,8 @@ bool cancel_job(UAContext *ua, JCR *jcr) case JS_WaitPriority: case JS_WaitMaxJobs: case JS_WaitStartTime: - bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"), - jcr->JobId, jcr->Job); + ua->info_msg(_("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; @@ -352,14 +376,14 @@ bool cancel_job(UAContext *ua, JCR *jcr) if (jcr->file_bsock) { ua->jcr->client = jcr->client; if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to File daemon.\n")); + ua->error_msg(_("Failed to connect to File daemon.\n")); return 0; } Dmsg0(200, "Connected to file daemon\n"); fd = ua->jcr->file_bsock; bnet_fsend(fd, "cancel Job=%s\n", jcr->Job); while (bnet_recv(fd) >= 0) { - bsendmsg(ua, "%s", fd->msg); + ua->send_msg("%s", fd->msg); } bnet_sig(fd, BNET_TERMINATE); bnet_close(fd); @@ -375,24 +399,27 @@ bool cancel_job(UAContext *ua, JCR *jcr) 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")); + ua->error_msg(_("Failed to connect to Storage daemon.\n")); return false; } Dmsg0(200, "Connected to storage daemon\n"); sd = ua->jcr->store_bsock; - bnet_fsend(sd, "cancel Job=%s\n", jcr->Job); - while (bnet_recv(sd) >= 0) { - bsendmsg(ua, "%s", sd->msg); + sd->fsend("cancel Job=%s\n", jcr->Job); + while (sd->recv() >= 0) { + ua->send_msg("%s", sd->msg); } - bnet_sig(sd, BNET_TERMINATE); - bnet_close(sd); + sd->signal(BNET_TERMINATE); + sd->close(); ua->jcr->store_bsock = NULL; } } @@ -414,37 +441,40 @@ static void job_monitor_watchdog(watchdog_t *self) control_jcr = (JCR *)self->data; + Dsm_check(1); 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); } @@ -455,72 +485,28 @@ static void job_monitor_watchdog(watchdog_t *self) 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; } @@ -531,9 +517,7 @@ static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr) */ 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) { @@ -542,36 +526,7 @@ static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr) 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; } /* @@ -585,6 +540,7 @@ DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name) 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 */ @@ -602,7 +558,7 @@ DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name) 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 @@ -721,7 +677,7 @@ void init_jcr_job_record(JCR *jcr) 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)); } @@ -738,6 +694,7 @@ void update_job_end_record(JCR *jcr) jcr->jr.JobBytes = jcr->JobBytes; jcr->jr.VolSessionId = jcr->VolSessionId; jcr->jr.VolSessionTime = jcr->VolSessionTime; + jcr->jr.JobErrors = jcr->Errors; if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) { Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"), db_strerror(jcr->db)); @@ -815,19 +772,6 @@ void dird_free_jcr_pointers(JCR *jcr) 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; @@ -860,6 +804,40 @@ void dird_free_jcr(JCR *jcr) pthread_cond_destroy(&jcr->term_wait); jcr->term_wait_inited = false; } + if (jcr->db_batch && jcr->db_batch != jcr->db) { + db_close_database(jcr, jcr->db_batch); + } + jcr->db_batch = NULL; + if (jcr->db) { + db_close_database(jcr, jcr->db); + jcr->db = 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); @@ -868,6 +846,32 @@ void dird_free_jcr(JCR *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 @@ -884,6 +888,12 @@ void set_jcr_defaults(JCR *jcr, JOB *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; @@ -895,13 +905,14 @@ void set_jcr_defaults(JCR *jcr, JOB *job) 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); @@ -941,6 +952,7 @@ void set_jcr_defaults(JCR *jcr, JOB *job) jcr->JobLevel = L_NONE; break; default: + jcr->JobLevel = L_FULL; break; } } @@ -951,16 +963,36 @@ void set_jcr_defaults(JCR *jcr, JOB *job) */ 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) +/* Set storage override. Releases any previous storage definition */ +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) @@ -983,27 +1015,43 @@ void copy_rstorage(JCR *jcr, alist *storage, const char *where) 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) +/* Set storage override. Remove all previous storage */ +void set_rstorage(JCR *jcr, USTORE *store) { STORE *storage; - jcr->rstore = store; + if (!store->store) { + return; + } + if (jcr->rstorage) { + free_rstorage(jcr); + } + 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) @@ -1027,29 +1075,48 @@ void copy_wstorage(JCR *jcr, alist *storage, const char *where) } 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) +/* Set storage override. Remove all previous storage */ +void set_wstorage(JCR *jcr, USTORE *store) { STORE *storage; - jcr->wstore = store; + if (!store->store) { + return; + } + if (jcr->wstorage) { + free_wstorage(jcr); + } + 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) @@ -1061,8 +1128,6 @@ void free_wstorage(JCR *jcr) jcr->wstore = NULL; } - - void create_clones(JCR *jcr) { /*