From 892f06cfa5f01fa76b0733ac90d9ef6956b3d636 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 8 Jul 2006 20:06:19 +0000 Subject: [PATCH] ======================= Warning ========================== Separate read and write storage in Jobs in the Director. This is a major rewrite of some of the low level code and hence has a high probability of introducing bugs. ========================================================== - Move the job init code up to *before* the job is put into the job queue (resource allocation queue). This permits the job to establish whether it will read or write or do both. - Add name() methods to all the resource classes. - Implement separate read and write storage resource allocation/deallocation in jobq.c git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3129 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kes-1.39 | 13 +++ bacula/src/dird/admin.c | 42 ++++--- bacula/src/dird/backup.c | 20 ++-- bacula/src/dird/catreq.c | 8 +- bacula/src/dird/dird_conf.h | 44 ++++++++ bacula/src/dird/expand.c | 32 ++++-- bacula/src/dird/job.c | 211 ++++++++++++++++++++++++----------- bacula/src/dird/jobq.c | 81 +++++++++++--- bacula/src/dird/migrate.c | 23 ++-- bacula/src/dird/msgchan.c | 8 +- bacula/src/dird/newvol.c | 2 +- bacula/src/dird/next_vol.c | 2 +- bacula/src/dird/protos.h | 11 +- bacula/src/dird/pythondir.c | 20 +++- bacula/src/dird/restore.c | 11 +- bacula/src/dird/scheduler.c | 2 +- bacula/src/dird/ua.h | 2 +- bacula/src/dird/ua_cmds.c | 10 +- bacula/src/dird/ua_label.c | 24 ++-- bacula/src/dird/ua_output.c | 8 +- bacula/src/dird/ua_restore.c | 140 +++-------------------- bacula/src/dird/ua_run.c | 88 +++++++-------- bacula/src/dird/ua_select.c | 6 +- bacula/src/dird/ua_status.c | 30 ++--- bacula/src/dird/verify.c | 10 +- bacula/src/jcr.h | 14 ++- 26 files changed, 491 insertions(+), 371 deletions(-) diff --git a/bacula/kes-1.39 b/bacula/kes-1.39 index d75367ee01..bb290973b8 100644 --- a/bacula/kes-1.39 +++ b/bacula/kes-1.39 @@ -3,6 +3,19 @@ General: 08Jul06 + ======================= Warning ========================== + Separate read and write storage in Jobs in the Director. This + is a major rewrite of some of the low level code and hence has + a high probability of introducing bugs. + ========================================================== + +- Move the job init code up to *before* the job is put into + the job queue (resource allocation queue). This permits the + job to establish whether it will read or write or do both. +- Add name() methods to all the resource classes. +- Implement separate read and write storage resource + allocation/deallocation in jobq.c + ======================= Warning ========================== Implemented new method of getting the default Storage from the Media record rather than from the MediaType for restore. As a fall diff --git a/bacula/src/dird/admin.c b/bacula/src/dird/admin.c index 19d067e6b2..3cce05617a 100644 --- a/bacula/src/dird/admin.c +++ b/bacula/src/dird/admin.c @@ -11,22 +11,17 @@ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2003-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 as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + 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 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., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. */ @@ -37,12 +32,13 @@ bool do_admin_init(JCR *jcr) { + free_rstorage(jcr); return true; } /* * Returns: false on failure - * true on success + * true on success */ bool do_admin(JCR *jcr) { @@ -53,7 +49,7 @@ bool do_admin(JCR *jcr) /* Print Job Start message */ Jmsg(jcr, M_INFO, 0, _("Start Admin JobId %d, Job=%s\n"), - jcr->JobId, jcr->Job); + jcr->JobId, jcr->Job); set_jcr_job_status(jcr, JS_Running); admin_cleanup(jcr, JS_Terminated); @@ -76,15 +72,15 @@ void admin_cleanup(JCR *jcr, int TermCode) memset(&mr, 0, sizeof(mr)); set_jcr_job_status(jcr, TermCode); - update_job_end_record(jcr); /* update database */ + update_job_end_record(jcr); /* update database */ if (!db_get_job_record(jcr, jcr->db, &jcr->jr)) { Jmsg(jcr, M_WARNING, 0, _("Error getting job record for stats: %s"), - db_strerror(jcr->db)); + db_strerror(jcr->db)); set_jcr_job_status(jcr, JS_ErrorTerminated); } - msg_type = M_INFO; /* by default INFO message */ + msg_type = M_INFO; /* by default INFO message */ switch (jcr->JobStatus) { case JS_Terminated: term_msg = _("Admin OK"); @@ -92,7 +88,7 @@ void admin_cleanup(JCR *jcr, int TermCode) case JS_FatalError: case JS_ErrorTerminated: term_msg = _("*** Admin Error ***"); - msg_type = M_ERROR; /* Generate error message */ + msg_type = M_ERROR; /* Generate error message */ break; case JS_Canceled: term_msg = _("Admin Canceled"); @@ -111,12 +107,12 @@ void admin_cleanup(JCR *jcr, int TermCode) " Start time: %s\n" " End time: %s\n" " Termination: %s\n\n"), - edt, - jcr->jr.JobId, - jcr->jr.Job, - sdt, - edt, - term_msg); + edt, + jcr->jr.JobId, + jcr->jr.Job, + sdt, + edt, + term_msg); Dmsg0(100, "Leave admin_cleanup()\n"); } diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c index ef845c7233..25b2af6c7d 100644 --- a/bacula/src/dird/backup.c +++ b/bacula/src/dird/backup.c @@ -49,6 +49,8 @@ static char EndJob[] = "2800 End Job TermCode=%d JobFiles=%u " bool do_backup_init(JCR *jcr) { + free_rstorage(jcr); /* we don't read so release */ + if (!get_or_create_fileset_record(jcr)) { return false; } @@ -66,15 +68,17 @@ bool do_backup_init(JCR *jcr) } /* If pool storage specified, use it instead of job storage */ - copy_storage(jcr, jcr->pool->storage, _("Pool resource")); + copy_wstorage(jcr, jcr->pool->storage, _("Pool resource")); - if (!jcr->storage) { + if (!jcr->wstorage) { Jmsg(jcr, M_FATAL, 0, _("No Storage specification found in Job or Pool.\n")); return false; } create_clones(jcr); /* run any clone jobs */ + Dmsg2(000, "rstore=%p wstore=%p\n", jcr->rstore, jcr->wstore); + return true; } @@ -121,7 +125,7 @@ bool do_backup(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr, NULL, jcr->storage)) { + if (!start_storage_daemon_job(jcr, NULL, jcr->wstorage)) { return false; } @@ -168,7 +172,7 @@ bool do_backup(JCR *jcr) /* * send Storage daemon address to the File daemon */ - store = jcr->store; + store = jcr->wstore; if (store->SDDport == 0) { store->SDDport = store->SDport; } @@ -448,10 +452,10 @@ void backup_cleanup(JCR *jcr, int TermCode) jcr->jr.JobId, jcr->jr.Job, level_to_str(jcr->JobLevel), jcr->since, - jcr->client->hdr.name, cr.Uname, - jcr->fileset->hdr.name, jcr->FSCreateTime, - jcr->pool->hdr.name, jcr->pool_source, - jcr->store->hdr.name, jcr->storage_source, + jcr->client->name(), cr.Uname, + jcr->fileset->name(), jcr->FSCreateTime, + jcr->pool->name(), jcr->pool_source, + jcr->wstore->name(), jcr->storage_source, schedt, sdt, edt, diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index 1d27e8061b..75b1c8b163 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -123,7 +123,7 @@ void catalog_request(JCR *jcr, BSOCK *bs) ok = db_get_pool_record(jcr, jcr->db, &pr); if (ok) { mr.PoolId = pr.PoolId; - mr.StorageId = jcr->store->StorageId; + mr.StorageId = jcr->wstore->StorageId; ok = find_next_volume_for_append(jcr, &mr, index, true /*permit create new vol*/); Dmsg3(100, "find_media idx=%d ok=%d vol=%s\n", index, ok, mr.VolumeName); } @@ -162,7 +162,7 @@ void catalog_request(JCR *jcr, BSOCK *bs) */ if (mr.PoolId != jcr->jr.PoolId) { reason = _("not in Pool"); - } else if (strcmp(mr.MediaType, jcr->store->media_type) != 0) { + } else if (strcmp(mr.MediaType, jcr->wstore->media_type) != 0) { reason = _("not correct MediaType"); } else { /* @@ -255,8 +255,8 @@ void catalog_request(JCR *jcr, BSOCK *bs) mr.VolWriteTime = sdmr.VolWriteTime; mr.VolParts = sdmr.VolParts; bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus)); - if (jcr->store->StorageId) { - mr.StorageId = jcr->store->StorageId; + if (jcr->wstore->StorageId) { + mr.StorageId = jcr->wstore->StorageId; } Dmsg2(400, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName); diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 56efa2fb2d..f4387202c3 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -113,8 +113,13 @@ public: bool tls_enable; /* Enable TLS */ bool tls_require; /* Require TLS */ bool tls_verify_peer; /* TLS Verify Client Certificate */ + + /* Methods */ + char *name() const; }; +inline char *DIRRES::name() const { return hdr.name; } + /* * Device Resource * This resource is a bit different from the other resources @@ -143,8 +148,13 @@ public: char ChangerName[MAX_NAME_LENGTH]; char VolumeName[MAX_NAME_LENGTH]; char MediaType[MAX_NAME_LENGTH]; + + /* Methods */ + char *name() const; }; +inline char *DEVICE::name() const { return hdr.name; } + /* * Console ACL positions */ @@ -179,8 +189,13 @@ public: bool tls_enable; /* Enable TLS */ bool tls_require; /* Require TLS */ bool tls_verify_peer; /* TLS Verify Client Certificate */ + + /* Methods */ + char *name() const; }; +inline char *CONRES::name() const { return hdr.name; } + /* * Catalog Resource @@ -197,8 +212,13 @@ public: char *db_user; char *db_name; int mult_db_connections; /* set if multiple connections wanted */ + + /* Methods */ + char *name() const; }; +inline char *CAT::name() const { return hdr.name; } + /* * Client Resource @@ -224,8 +244,14 @@ public: bool tls_enable; /* Enable TLS */ bool tls_require; /* Require TLS */ bool AutoPrune; /* Do automatic pruning? */ + + /* Methods */ + char *name() const; }; +inline char *CLIENT::name() const { return hdr.name; } + + /* * Store Resource * @@ -327,8 +353,13 @@ public: JOB *jobdefs; /* Job defaults */ alist *run_cmds; /* Run commands */ uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ + + /* Methods */ + char *name() const; }; +inline char *JOB::name() const { return hdr.name; } + #undef MAX_FOPTS #define MAX_FOPTS 34 @@ -374,8 +405,12 @@ public: char MD5[30]; /* base 64 representation of MD5 */ bool ignore_fs_changes; /* Don't force Full if FS changed */ bool enable_vss; /* Enable Volume Shadow Copy */ + + /* Methods */ + char *name() const; }; +inline char *FILESET::name() const { return hdr.name; } /* * Schedule Resource @@ -401,8 +436,12 @@ public: COUNTER *WrapCounter; /* Wrap counter name */ CAT *Catalog; /* Where to store */ bool created; /* Created in DB */ + /* Methods */ + char *name() const; }; +inline char *COUNTER::name() const { return hdr.name; } + /* * Pool Resource * @@ -434,8 +473,13 @@ public: bool recycle_current_volume; /* attempt recycle of current volume */ bool AutoPrune; /* default for pool auto prune */ bool Recycle; /* default for media recycle yes/no */ + + /* Methods */ + char *name() const; }; +inline char *POOL::name() const { return hdr.name; } + diff --git a/bacula/src/dird/expand.c b/bacula/src/dird/expand.c index 3a41434215..21fd34e8ff 100644 --- a/bacula/src/dird/expand.c +++ b/bacula/src/dird/expand.c @@ -79,7 +79,7 @@ static int job_item(JCR *jcr, int code, switch (code) { case 1: /* Job */ - str = jcr->job->hdr.name; + str = jcr->job->name(); break; case 2: /* Director's name */ str = my_name; @@ -95,7 +95,7 @@ static int job_item(JCR *jcr, int code, str = buf; break; case 6: /* Client */ - str = jcr->client->hdr.name; + str = jcr->client->name(); if (!str) { str = " "; } @@ -105,16 +105,24 @@ static int job_item(JCR *jcr, int code, str = buf; break; case 8: /* Pool */ - str = jcr->pool->hdr.name; + str = jcr->pool->name(); break; case 9: /* Storage */ - str = jcr->store->hdr.name; + if (jcr->wstore) { + str = jcr->wstore->name(); + } else { + str = jcr->rstore->name(); + } break; case 10: /* Catalog */ - str = jcr->catalog->hdr.name; + str = jcr->catalog->name(); break; case 11: /* MediaType */ - str = jcr->store->media_type; + if (jcr->wstore) { + str = jcr->wstore->media_type; + } else { + str = jcr->rstore->media_type; + } break; case 12: /* JobName */ str = jcr->Job; @@ -200,7 +208,7 @@ static var_rc_t lookup_counter_var(var_t *ctx, void *my_ctx, buf[var_len] = 0; LockRes(); for (COUNTER *counter=NULL; (counter = (COUNTER *)GetNextRes(R_COUNTER, (RES *)counter)); ) { - if (strcmp(counter->hdr.name, buf) == 0) { + if (strcmp(counter->name(), buf) == 0) { Dmsg2(100, "Counter=%s val=%d\n", buf, counter->CurrentValue); /* -1 => return size of array */ if (var_index == -1) { @@ -225,19 +233,19 @@ static var_rc_t lookup_counter_var(var_t *ctx, void *my_ctx, COUNTER_DBR cr; JCR *jcr = (JCR *)my_ctx; memset(&cr, 0, sizeof(cr)); - bstrncpy(cr.Counter, counter->hdr.name, sizeof(cr.Counter)); + bstrncpy(cr.Counter, counter->name(), sizeof(cr.Counter)); cr.MinValue = counter->MinValue; cr.MaxValue = counter->MaxValue; cr.CurrentValue = counter->CurrentValue; Dmsg1(100, "New value=%d\n", cr.CurrentValue); if (counter->WrapCounter) { - bstrncpy(cr.WrapCounter, counter->WrapCounter->hdr.name, sizeof(cr.WrapCounter)); + bstrncpy(cr.WrapCounter, counter->WrapCounter->name(), sizeof(cr.WrapCounter)); } else { cr.WrapCounter[0] = 0; } if (!db_update_counter_record(jcr, jcr->db, &cr)) { Jmsg(jcr, M_ERROR, 0, _("Count not update counter %s: ERR=%s\n"), - counter->hdr.name, db_strerror(jcr->db)); + counter->name(), db_strerror(jcr->db)); } } } @@ -375,8 +383,8 @@ static var_rc_t operate_var(var_t *var, void *my_ctx, Dmsg1(100, "Val=%s\n", buf); LockRes(); for (COUNTER *counter=NULL; (counter = (COUNTER *)GetNextRes(R_COUNTER, (RES *)counter)); ) { - if (strcmp(counter->hdr.name, buf) == 0) { - Dmsg2(100, "counter=%s val=%s\n", counter->hdr.name, buf); + if (strcmp(counter->name(), buf) == 0) { + Dmsg2(100, "counter=%s val=%s\n", counter->name(), buf); break; } } diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 9f3ba200a0..d296abf44a 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -157,54 +157,6 @@ bool setup_job(JCR *jcr) goto bail_out; } - Dmsg0(200, "Add jrc to work queue\n"); - return true; - -bail_out: - return false; -} - - -/* - * This is the engine called by jobq.c:jobq_add() when we were pulled - * from the work queue. - * At this point, we are running in our own thread and all - * necessary resources are allocated -- see jobq.c - */ -static void *job_thread(void *arg) -{ - JCR *jcr = (JCR *)arg; - - jcr->my_thread_id = pthread_self(); - pthread_detach(jcr->my_thread_id); - sm_check(__FILE__, __LINE__, true); - - Dmsg0(200, "=====Start Job=========\n"); - jcr->start_time = time(NULL); /* set the real start time */ - jcr->jr.StartTime = jcr->start_time; - - 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); - } - - /* TODO : check if it is used somewhere */ - if (jcr->job->RunScripts == NULL) - { - Dmsg0(200, "Warning, job->RunScripts is empty\n"); - jcr->job->RunScripts = New(alist(10, not_owned_by_alist)); - } - - /* - * Note, we continue, even if the job is canceled above. This - * will permit proper setting of the job start record and - * the error (cancel) will be picked up below. - */ - - generate_job_event(jcr, "JobInit"); - set_jcr_job_status(jcr, JS_Running); /* this will be set only if no error */ - /* * Now, do pre-run stuff, like setting job level (Inc/diff, ...) @@ -243,6 +195,47 @@ static void *job_thread(void *arg) break; } + generate_job_event(jcr, "JobInit"); + + Dmsg0(200, "Add jrc to work queue\n"); + return true; + +bail_out: + return false; +} + + +/* + * This is the engine called by jobq.c:jobq_add() when we were pulled + * from the work queue. + * At this point, we are running in our own thread and all + * necessary resources are allocated -- see jobq.c + */ +static void *job_thread(void *arg) +{ + JCR *jcr = (JCR *)arg; + + jcr->my_thread_id = pthread_self(); + pthread_detach(jcr->my_thread_id); + sm_check(__FILE__, __LINE__, true); + + Dmsg0(200, "=====Start Job=========\n"); + set_jcr_job_status(jcr, JS_Running); /* this will be set only if no error */ + jcr->start_time = time(NULL); /* set the real start time */ + jcr->jr.StartTime = jcr->start_time; + + 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); + } + + /* TODO : check if it is used somewhere */ + if (jcr->job->RunScripts == NULL) { + Dmsg0(200, "Warning, job->RunScripts is empty\n"); + jcr->job->RunScripts = New(alist(10, not_owned_by_alist)); + } + if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) { Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); } @@ -375,10 +368,18 @@ bool cancel_job(UAContext *ua, JCR *jcr) /* Cancel Storage daemon */ if (jcr->store_bsock) { - if (!ua->jcr->storage) { - copy_storage(ua->jcr, jcr->storage, _("Job resource")); + if (!ua->jcr->wstorage) { + if (jcr->rstorage) { + copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); + } else { + copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); + } } else { - set_storage(ua->jcr, jcr->store); + if (jcr->rstorage) { + set_wstorage(ua->jcr, jcr->rstore); + } else { + set_wstorage(ua->jcr, jcr->wstore); + } } if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); @@ -857,9 +858,8 @@ void dird_free_jcr(JCR *jcr) } /* Delete lists setup to hold storage pointers */ - if (jcr->storage) { - delete jcr->storage; - } + free_rwstorage(jcr); + jcr->job_end_push.destroy(); Dmsg0(200, "End dird free_jcr\n"); } @@ -897,7 +897,7 @@ void set_jcr_defaults(JCR *jcr, JOB *job) } jcr->JobPriority = job->Priority; /* Copy storage definitions -- deleted in dir_free_jcr above */ - copy_storage(jcr, job->storage, _("Job resource")); + copy_rwstorage(jcr, job->storage, _("Job resource")); jcr->client = job->client; if (!jcr->client_name) { jcr->client_name = get_pool_memory(PM_NAME); @@ -942,44 +942,123 @@ void set_jcr_defaults(JCR *jcr, JOB *job) } } +/* + * Copy the storage definitions from an alist to the JCR + */ +void copy_rwstorage(JCR *jcr, alist *storage, const char *where) +{ + copy_rstorage(jcr, storage, where); + copy_wstorage(jcr, storage, where); +} + + +/* Set storage override */ +void set_rwstorage(JCR *jcr, STORE *store) +{ + set_rstorage(jcr, store); + set_wstorage(jcr, store); +} + +void free_rwstorage(JCR *jcr) +{ + free_rstorage(jcr); + free_wstorage(jcr); +} + +/* + * Copy the storage definitions from an alist to the JCR + */ +void copy_rstorage(JCR *jcr, alist *storage, const char *where) +{ + if (storage) { + STORE *st; + if (jcr->rstorage) { + delete jcr->rstorage; + } + jcr->rstorage = New(alist(10, not_owned_by_alist)); + foreach_alist(st, storage) { + jcr->rstorage->append(st); + } + pm_strcpy(jcr->storage_source, where); + } + if (jcr->rstorage) { + jcr->rstore = (STORE *)jcr->rstorage->first(); + } +} + + +/* Set storage override */ +void set_rstorage(JCR *jcr, STORE *store) +{ + STORE *storage; + + jcr->rstore = store; + foreach_alist(storage, jcr->rstorage) { + if (store == storage) { + return; + } + } + /* Store not in list, so add it */ + jcr->rstorage->prepend(store); +} + +void free_rstorage(JCR *jcr) +{ + if (jcr->rstorage) { + delete jcr->rstorage; + jcr->rstorage = NULL; + } + jcr->rstore = NULL; +} /* * Copy the storage definitions from an alist to the JCR */ -void copy_storage(JCR *jcr, alist *storage, const char *where) +void copy_wstorage(JCR *jcr, alist *storage, const char *where) { if (storage) { STORE *st; - if (jcr->storage) { - delete jcr->storage; + if (jcr->wstorage) { + delete jcr->wstorage; } - jcr->storage = New(alist(10, not_owned_by_alist)); + jcr->wstorage = New(alist(10, not_owned_by_alist)); foreach_alist(st, storage) { - jcr->storage->append(st); + jcr->wstorage->append(st); } pm_strcpy(jcr->storage_source, where); } - if (jcr->storage) { - jcr->store = (STORE *)jcr->storage->first(); + if (jcr->wstorage) { + jcr->wstore = (STORE *)jcr->wstorage->first(); } } /* Set storage override */ -void set_storage(JCR *jcr, STORE *store) +void set_wstorage(JCR *jcr, STORE *store) { STORE *storage; - jcr->store = store; - foreach_alist(storage, jcr->storage) { + jcr->wstore = store; + foreach_alist(storage, jcr->wstorage) { if (store == storage) { return; } } /* Store not in list, so add it */ - jcr->storage->prepend(store); + jcr->wstorage->prepend(store); +} + +void free_wstorage(JCR *jcr) +{ + if (jcr->wstorage) { + delete jcr->wstorage; + jcr->wstorage = NULL; + } + jcr->wstore = NULL; } + + void create_clones(JCR *jcr) { /* diff --git a/bacula/src/dird/jobq.c b/bacula/src/dird/jobq.c index 1535aebc07..f700327435 100755 --- a/bacula/src/dird/jobq.c +++ b/bacula/src/dird/jobq.c @@ -463,9 +463,17 @@ void *jobq_server(void *arg) * put into the ready queue. */ if (jcr->acquired_resource_locks) { - jcr->store->NumConcurrentJobs--; + if (jcr->rstore) { + jcr->rstore->NumConcurrentJobs = 0; + Dmsg1(000, "Dec rncj=%d\n", jcr->rstore->NumConcurrentJobs); + } + if (jcr->wstore) { + jcr->wstore->NumConcurrentJobs--; + Dmsg1(000, "Dec wncj=%d\n", jcr->wstore->NumConcurrentJobs); + } jcr->client->NumConcurrentJobs--; jcr->job->NumConcurrentJobs--; + jcr->acquired_resource_locks = false; } /* @@ -519,7 +527,16 @@ void *jobq_server(void *arg) njcr->JobLevel = jcr->JobLevel; njcr->JobStatus = -1; set_jcr_job_status(njcr, jcr->JobStatus); - copy_storage(njcr, jcr->storage, _("previous Job")); + if (jcr->rstore) { + copy_rstorage(njcr, jcr->rstorage, _("previous Job")); + } else { + free_rstorage(njcr); + } + if (jcr->wstore) { + copy_wstorage(njcr, jcr->wstorage, _("previous Job")); + } else { + free_wstorage(njcr); + } njcr->messages = jcr->messages; Dmsg0(2300, "Call to run new job\n"); V(jq->mutex); @@ -582,7 +599,6 @@ void *jobq_server(void *arg) /* Got all locks, now remove it from wait queue and append it * to the ready queue */ - jcr->acquired_resource_locks = true; jq->waiting_jobs->remove(je); jq->ready_jobs->append(je); Dmsg1(2300, "moved JobId=%d from wait to ready queue\n", je->jcr->JobId); @@ -649,26 +665,40 @@ static bool acquire_resources(JCR *jcr) { bool skip_this_jcr = false; - if (jcr->JobType == JT_RESTORE || jcr->JobType == JT_VERIFY) { + jcr->acquired_resource_locks = false; + if (jcr->rstore) { + Dmsg1(000, "Rstore=%s\n", jcr->rstore->name()); /* * Let only one Restore/verify job run at a time regardless * of MaxConcurrentJobs. */ - if (jcr->store->NumConcurrentJobs == 0) { - jcr->store->NumConcurrentJobs = 1; + if (jcr->rstore->NumConcurrentJobs == 0) { + jcr->rstore->NumConcurrentJobs = 1; + Dmsg0(000, "Set rncj=1\n"); } else { + Dmsg1(000, "Fail rncj=%d\n", jcr->rstore->NumConcurrentJobs); set_jcr_job_status(jcr, JS_WaitStoreRes); return false; } - /* We are not doing a Restore or Verify */ - } else if (jcr->store->NumConcurrentJobs == 0 && - jcr->store->NumConcurrentJobs < jcr->store->MaxConcurrentJobs) { - /* Simple case, first job */ - jcr->store->NumConcurrentJobs = 1; - } else if (jcr->store->NumConcurrentJobs < jcr->store->MaxConcurrentJobs) { - jcr->store->NumConcurrentJobs++; - } else { - skip_this_jcr = true; + } + + if (jcr->wstore) { + if (jcr->wstore->NumConcurrentJobs == 0 && + jcr->wstore->NumConcurrentJobs < jcr->wstore->MaxConcurrentJobs) { + /* Simple case, first job */ + jcr->wstore->NumConcurrentJobs = 1; + Dmsg0(000, "Set wncj=1\n"); + } else if (jcr->wstore->NumConcurrentJobs < jcr->wstore->MaxConcurrentJobs) { + jcr->wstore->NumConcurrentJobs++; + Dmsg1(000, "Inc wncj=%d\n", jcr->wstore->NumConcurrentJobs); + } else if (jcr->rstore) { + jcr->rstore->NumConcurrentJobs = 0; /* back out rstore */ + Dmsg1(000, "Fail wncj=%d\n", jcr->wstore->NumConcurrentJobs); + skip_this_jcr = true; + } else { + Dmsg1(000, "Fail wncj=%d\n", jcr->wstore->NumConcurrentJobs); + skip_this_jcr = true; + } } if (skip_this_jcr) { set_jcr_job_status(jcr, JS_WaitStoreRes); @@ -679,7 +709,14 @@ static bool acquire_resources(JCR *jcr) jcr->client->NumConcurrentJobs++; } else { /* Back out previous locks */ - jcr->store->NumConcurrentJobs--; + if (jcr->wstore) { + jcr->wstore->NumConcurrentJobs--; + Dmsg1(000, "Dec wncj=%d\n", jcr->wstore->NumConcurrentJobs); + } + if (jcr->rstore) { + jcr->rstore->NumConcurrentJobs = 0; + Dmsg1(000, "Dec rncj=%d\n", jcr->rstore->NumConcurrentJobs); + } set_jcr_job_status(jcr, JS_WaitClientRes); return false; } @@ -687,12 +724,22 @@ static bool acquire_resources(JCR *jcr) jcr->job->NumConcurrentJobs++; } else { /* Back out previous locks */ - jcr->store->NumConcurrentJobs--; + if (jcr->wstore) { + jcr->wstore->NumConcurrentJobs--; + Dmsg1(000, "Dec wncj=%d\n", jcr->wstore->NumConcurrentJobs); + } + if (jcr->rstore) { + jcr->rstore->NumConcurrentJobs = 0; + Dmsg1(000, "Dec rncj=%d\n", jcr->rstore->NumConcurrentJobs); + } jcr->client->NumConcurrentJobs--; set_jcr_job_status(jcr, JS_WaitJobRes); return false; } /* Check actual device availability */ /* ***FIXME****/ + + + jcr->acquired_resource_locks = true; return true; } diff --git a/bacula/src/dird/migrate.c b/bacula/src/dird/migrate.c index 1a4059c1e9..defc5e504a 100644 --- a/bacula/src/dird/migrate.c +++ b/bacula/src/dird/migrate.c @@ -74,9 +74,9 @@ bool do_migration_init(JCR *jcr) } /* If pool storage specified, use it instead of job storage */ - copy_storage(jcr, jcr->pool->storage, _("Pool resource")); + copy_wstorage(jcr, jcr->pool->storage, _("Pool resource")); - if (!jcr->storage) { + if (!jcr->wstorage) { Jmsg(jcr, M_FATAL, 0, _("No Storage specification found in Job or Pool.\n")); return false; } @@ -171,7 +171,8 @@ bool do_migration(JCR *jcr) /* ***FIXME*** */ /* If pool storage specified, use it for restore */ - copy_storage(prev_jcr, pool->storage, _("Pool resource")); + copy_rstorage(prev_jcr, pool->storage, _("Pool resource")); + copy_rstorage(jcr, pool->storage, _("Pool resource")); /* If the original backup pool has a NextPool, make sure a * record exists in the database. @@ -191,7 +192,7 @@ bool do_migration(JCR *jcr) } /* If pool storage specified, use it instead of job storage for backup */ - copy_storage(jcr, jcr->pool->storage, _("Pool resource")); + copy_wstorage(jcr, jcr->pool->storage, _("Pool resource")); /* Print Job Start message */ Jmsg(jcr, M_INFO, 0, _("Start Migration JobId %s, Job=%s\n"), @@ -238,9 +239,9 @@ bool do_migration(JCR *jcr) * Now start a job with the Storage daemon */ Dmsg2(dbglevel, "Read store=%s, write store=%s\n", - ((STORE *)prev_jcr->storage->first())->hdr.name, - ((STORE *)jcr->storage->first())->hdr.name); - if (!start_storage_daemon_job(jcr, prev_jcr->storage, jcr->storage)) { + ((STORE *)jcr->rstorage->first())->name(), + ((STORE *)jcr->wstorage->first())->name()); + if (!start_storage_daemon_job(jcr, jcr->rstorage, jcr->wstorage)) { return false; } Dmsg0(150, "Storage daemon connection OK\n"); @@ -807,10 +808,10 @@ void migration_cleanup(JCR *jcr, int TermCode) edit_uint64(jcr->jr.JobId, ec8), jcr->jr.Job, level_to_str(jcr->JobLevel), jcr->since, - jcr->client->hdr.name, - jcr->fileset->hdr.name, jcr->FSCreateTime, - jcr->pool->hdr.name, jcr->pool_source, - jcr->store->hdr.name, jcr->storage_source, + jcr->client->name(), + jcr->fileset->name(), jcr->FSCreateTime, + jcr->pool->name(), jcr->pool_source, + jcr->wstore->name(), jcr->storage_source, sdt, edt, edit_utime(RunTime, elapsed, sizeof(elapsed)), diff --git a/bacula/src/dird/msgchan.c b/bacula/src/dird/msgchan.c index 5e0124975b..c19b505282 100644 --- a/bacula/src/dird/msgchan.c +++ b/bacula/src/dird/msgchan.c @@ -69,7 +69,13 @@ bool connect_to_storage_daemon(JCR *jcr, int retry_interval, if (jcr->store_bsock) { return true; /* already connected */ } - store = (STORE *)jcr->storage->first(); + + /* If there is a write storage use it */ + if (jcr->wstorage) { + store = (STORE *)jcr->wstorage->first(); + } else { + store = (STORE *)jcr->rstorage->first(); + } /* * Open message channel with the Storage daemon diff --git a/bacula/src/dird/newvol.c b/bacula/src/dird/newvol.c index 6a542caa4d..d022b65a51 100644 --- a/bacula/src/dird/newvol.c +++ b/bacula/src/dird/newvol.c @@ -57,7 +57,7 @@ bool newVolume(JCR *jcr, MEDIA_DBR *mr) memset(mr, 0, sizeof(MEDIA_DBR)); set_pool_dbr_defaults_in_media_dbr(mr, &pr); jcr->VolumeName[0] = 0; - bstrncpy(mr->MediaType, jcr->store->media_type, sizeof(mr->MediaType)); + bstrncpy(mr->MediaType, jcr->wstore->media_type, sizeof(mr->MediaType)); if (generate_job_event(jcr, "NewVolume") == 1 && jcr->VolumeName[0] && is_volume_name_legal(NULL, jcr->VolumeName)) { bstrncpy(mr->VolumeName, jcr->VolumeName, sizeof(mr->VolumeName)); diff --git a/bacula/src/dird/next_vol.c b/bacula/src/dird/next_vol.c index 129a8cbde0..82675a2246 100644 --- a/bacula/src/dird/next_vol.c +++ b/bacula/src/dird/next_vol.c @@ -43,7 +43,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, bool create) int retry = 0; bool ok; bool InChanger; - STORE *store = jcr->store; + STORE *store = jcr->wstore; bstrncpy(mr->MediaType, store->media_type, sizeof(mr->MediaType)); Dmsg2(100, "CatReq FindMedia: PoolId=%d, MediaType=%s\n", (int)mr->PoolId, mr->MediaType); diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index da56c4701c..55e9dad4a1 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -99,8 +99,15 @@ extern void apply_pool_overrides(JCR *jcr); extern JobId_t run_job(JCR *jcr); extern bool cancel_job(UAContext *ua, JCR *jcr); extern void init_jcr_job_record(JCR *jcr); -extern void copy_storage(JCR *jcr, alist *storage, const char *where); -extern void set_storage(JCR *jcr, STORE *store); +extern void copy_rwstorage(JCR *jcr, alist *storage, const char *where); +extern void set_rwstorage(JCR *jcr, STORE *store); +extern void free_rwstorage(JCR *jcr); +extern void copy_wstorage(JCR *jcr, alist *storage, const char *where); +extern void set_wstorage(JCR *jcr, STORE *store); +extern void free_wstorage(JCR *jcr); +extern void copy_rstorage(JCR *jcr, alist *storage, const char *where); +extern void set_rstorage(JCR *jcr, STORE *store); +extern void free_rstorage(JCR *jcr); extern bool setup_job(JCR *jcr); extern void create_clones(JCR *jcr); extern bool create_restore_bootstrap_file(JCR *jcr); diff --git a/bacula/src/dird/pythondir.c b/bacula/src/dird/pythondir.c index 9f5df846c0..d64bb23e3d 100644 --- a/bacula/src/dird/pythondir.c +++ b/bacula/src/dird/pythondir.c @@ -140,13 +140,25 @@ PyObject *job_getattr(PyObject *self, char *attrname) goto bail_out; } case 6: /* Pool */ - return Py_BuildValue(getvars[i].fmt, jcr->pool->hdr.name); + return Py_BuildValue(getvars[i].fmt, jcr->pool->name()); case 7: /* Storage */ - return Py_BuildValue(getvars[i].fmt, jcr->store->hdr.name); + if (jcr->wstore) { + return Py_BuildValue(getvars[i].fmt, jcr->wstore->name()); + } else if (jcr->rstore) { + return Py_BuildValue(getvars[i].fmt, jcr->rstore->name()); + } else { + goto bail_out; + } case 8: - return Py_BuildValue(getvars[i].fmt, jcr->catalog->hdr.name); + return Py_BuildValue(getvars[i].fmt, jcr->catalog->name()); case 9: /* MediaType */ - return Py_BuildValue(getvars[i].fmt, jcr->store->media_type); + if (jcr->wstore) { + return Py_BuildValue(getvars[i].fmt, jcr->wstore->media_type); + } else if (jcr->rstore) { + return Py_BuildValue(getvars[i].fmt, jcr->rstore->media_type); + } else { + goto bail_out; + } case 10: /* JobName */ return Py_BuildValue(getvars[i].fmt, jcr->Job); case 11: /* JobStatus */ diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index 90fdb42a63..49b412c5aa 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -56,6 +56,8 @@ bool do_restore(JCR *jcr) BSOCK *fd; JOB_DBR rjr; /* restore job record */ + free_wstorage(jcr); /* we don't write */ + memset(&rjr, 0, sizeof(rjr)); jcr->jr.JobLevel = L_FULL; /* Full restore */ if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) { @@ -95,7 +97,7 @@ bool do_restore(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr, jcr->storage, NULL)) { + if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) { restore_cleanup(jcr, JS_ErrorTerminated); return false; } @@ -129,10 +131,10 @@ bool do_restore(JCR *jcr) * then wait for File daemon to make connection * with Storage daemon. */ - if (jcr->store->SDDport == 0) { - jcr->store->SDDport = jcr->store->SDport; + if (jcr->rstore->SDDport == 0) { + jcr->rstore->SDDport = jcr->rstore->SDport; } - bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport); + bnet_fsend(fd, storaddr, jcr->rstore->address, jcr->rstore->SDDport); Dmsg1(6, "dird>filed: %s\n", fd->msg); if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) { restore_cleanup(jcr, JS_ErrorTerminated); @@ -191,6 +193,7 @@ bool do_restore(JCR *jcr) bool do_restore_init(JCR *jcr) { + free_wstorage(jcr); return true; } diff --git a/bacula/src/dird/scheduler.c b/bacula/src/dird/scheduler.c index ada34c437a..684e694520 100644 --- a/bacula/src/dird/scheduler.c +++ b/bacula/src/dird/scheduler.c @@ -205,7 +205,7 @@ again: jcr->run_diff_pool_override = true; } if (run->storage) { - set_storage(jcr, run->storage); /* override storage */ + set_rwstorage(jcr, run->storage); /* override storage */ } if (run->msgs) { jcr->messages = run->msgs; /* override messages */ diff --git a/bacula/src/dird/ua.h b/bacula/src/dird/ua.h index b06f62c7cb..e04315bf14 100644 --- a/bacula/src/dird/ua.h +++ b/bacula/src/dird/ua.h @@ -6,7 +6,7 @@ * Version $Id$ */ /* - Copyright (C) 2000-2005 Kern Sibbald + 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 diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index f2d2bf2f8d..90b44cce68 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -146,8 +146,8 @@ int do_a_command(UAContext *ua, const char *cmd) return 1; } - while (ua->jcr->storage->size()) { - ua->jcr->storage->remove(0); + while (ua->jcr->wstorage->size()) { + ua->jcr->wstorage->remove(0); } len = strlen(ua->argk[0]); @@ -672,10 +672,10 @@ static void do_storage_setdebug(UAContext *ua, STORE *store, int level, int trac BSOCK *sd; JCR *jcr = ua->jcr; - set_storage(jcr, store); + set_wstorage(jcr, store); /* Try connecting for up to 15 seconds */ bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d\n"), - store->hdr.name, store->address, store->SDport); + store->name(), store->address, store->SDport); if (!connect_to_storage_daemon(jcr, 1, 15, 0)) { bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); return; @@ -1319,7 +1319,7 @@ static void do_mount_cmd(UAContext *ua, const char *command) if (!store) { return; } - set_storage(jcr, store); + set_wstorage(jcr, store); drive = get_storage_drive(ua, store); Dmsg3(120, "Found storage, MediaType=%s DevName=%s drive=%d\n", diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 1452489736..86a5b02843 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -165,7 +165,7 @@ void update_slots(UAContext *ua) if (!store) { return; } - set_storage(ua->jcr, store); + set_wstorage(ua->jcr, store); drive = get_storage_drive(ua, store); scan = find_arg(ua, NT_("scan")) >= 0; @@ -317,7 +317,7 @@ static int do_label(UAContext *ua, const char *cmd, int relabel) if (!store) { return 1; } - set_storage(ua->jcr, store); + set_wstorage(ua->jcr, store); drive = get_storage_drive(ua, store); if (label_barcodes) { @@ -463,7 +463,7 @@ checkName: */ static void label_from_barcodes(UAContext *ua, int drive) { - STORE *store = ua->jcr->store; + STORE *store = ua->jcr->wstore; POOL_DBR pr; MEDIA_DBR mr, omr; vol_list_t *vl, *vol_list = NULL; @@ -633,7 +633,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, if (!(sd=open_sd_bsock(ua))) { return false; } - bstrncpy(dev_name, ua->jcr->store->dev_name(), sizeof(dev_name)); + bstrncpy(dev_name, ua->jcr->wstore->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); bash_spaces(mr->VolumeName); bash_spaces(mr->MediaType); @@ -672,7 +672,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, if (media_record_exists) { /* we update it */ mr->VolBytes = 1; mr->InChanger = 1; - mr->StorageId = ua->jcr->store->StorageId; + mr->StorageId = ua->jcr->wstore->StorageId; if (!db_update_media_record(ua->jcr, ua->db, mr)) { bsendmsg(ua, "%s", db_strerror(ua->db)); ok = false; @@ -681,7 +681,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, set_pool_dbr_defaults_in_media_dbr(mr, pr); mr->VolBytes = 1; /* flag indicating Volume labeled */ mr->InChanger = 1; - mr->StorageId = ua->jcr->store->StorageId; + mr->StorageId = ua->jcr->wstore->StorageId; mr->Enabled = 1; if (db_create_media_record(ua->jcr, ua->db, mr)) { bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d successfully created.\n"), @@ -704,11 +704,11 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, static BSOCK *open_sd_bsock(UAContext *ua) { - STORE *store = ua->jcr->store; + STORE *store = ua->jcr->wstore; if (!ua->jcr->store_bsock) { bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), - store->hdr.name, store->address, store->SDport); + store->name(), store->address, store->SDport); if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); return NULL; @@ -728,7 +728,7 @@ static void close_sd_bsock(UAContext *ua) static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive) { - STORE *store = ua->jcr->store; + STORE *store = ua->jcr->wstore; BSOCK *sd; char dev_name[MAX_NAME_LENGTH]; char *VolName = NULL; @@ -769,7 +769,7 @@ static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive) */ static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan) { - STORE *store = ua->jcr->store; + STORE *store = ua->jcr->wstore; char dev_name[MAX_NAME_LENGTH]; BSOCK *sd; vol_list_t *vl; @@ -882,7 +882,7 @@ static void free_vol_list(vol_list_t *vol_list) */ static int get_num_slots_from_SD(UAContext *ua) { - STORE *store = ua->jcr->store; + STORE *store = ua->jcr->wstore; char dev_name[MAX_NAME_LENGTH]; BSOCK *sd; int slots = 0; @@ -914,7 +914,7 @@ static int get_num_slots_from_SD(UAContext *ua) */ int get_num_drives_from_SD(UAContext *ua) { - STORE *store = ua->jcr->store; + STORE *store = ua->jcr->wstore; char dev_name[MAX_NAME_LENGTH]; BSOCK *sd; int drives = 0; diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index f53628e974..b0e261ba49 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -465,15 +465,15 @@ static bool list_nextvol(UAContext *ua, int ndays) memset(&pr, 0, sizeof(pr)); pr.PoolId = jcr->jr.PoolId; if (! db_get_pool_record(ua->jcr, ua->db, &pr)) { - strcpy(pr.Name, "*UnknownPool*"); + bstrncpy(pr.Name, "*UnknownPool*", sizeof(pr.Name)); } mr.PoolId = jcr->jr.PoolId; if (run->storage) { - jcr->store = run->storage; + jcr->wstore = run->storage; } else { - jcr->store = (STORE *)job->storage->first(); + jcr->wstore = (STORE *)job->storage->first(); } - mr.StorageId = jcr->store->StorageId; + mr.StorageId = jcr->wstore->StorageId; if (!find_next_volume_for_append(jcr, &mr, 1, false/*no create*/)) { bsendmsg(ua, _("Could not find next Volume for Job %s (%s, %s).\n"), job->hdr.name, pr.Name, level_to_str(run->level)); diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index f93bc7a342..24d0aba7b7 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -178,19 +178,19 @@ int restore_cmd(UAContext *ua, const char *cmd) Mmsg(ua->cmd, "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\"" " where=\"%s\" files=%d catalog=\"%s\"", - job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"", - jcr->RestoreBootstrap, rx.where, rx.selected_files, ua->catalog->hdr.name); + job->name(), rx.ClientName, rx.store?rx.store->name():"", + jcr->RestoreBootstrap, rx.where, rx.selected_files, ua->catalog->name()); } else { Mmsg(ua->cmd, "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\"" " files=%d catalog=\"%s\"", - job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"", - jcr->RestoreBootstrap, rx.selected_files, ua->catalog->hdr.name); + job->name(), rx.ClientName, rx.store?rx.store->name():"", + jcr->RestoreBootstrap, rx.selected_files, ua->catalog->name()); } if (find_arg(ua, NT_("yes")) > 0) { pm_strcat(ua->cmd, " yes"); /* pass it on to the run command */ } - Dmsg1(100, "Submitting: %s\n", ua->cmd); + Dmsg1(200, "Submitting: %s\n", ua->cmd); parse_ua_args(ua); run_cmd(ua, ua->cmd); free_rx(&rx); @@ -1007,7 +1007,7 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat if (rx->pool) { POOL_DBR pr; memset(&pr, 0, sizeof(pr)); - bstrncpy(pr.Name, rx->pool->hdr.name, sizeof(pr.Name)); + bstrncpy(pr.Name, rx->pool->name(), sizeof(pr.Name)); if (db_get_pool_record(ua->jcr, ua->db, &pr)) { bsnprintf(pool_select, sizeof(pool_select), "AND Media.PoolId=%s ", edit_int64(pr.PoolId, ed1)); @@ -1185,52 +1185,6 @@ static int fileset_handler(void *ctx, int num_fields, char **row) return 0; } -#ifdef xxxx_needed -/* - * Called here with each name to be added to the list. The name is - * added to the list if it is not already in the list. - * - * Used to make unique list of FileSets - */ -static int unique_name_list_handler(void *ctx, int num_fields, char **row) -{ - NAME_LIST *name = (NAME_LIST *)ctx; - - if (name->num_ids == MAX_ID_LIST_LEN) { - return 1; - } - if (name->num_ids == name->max_ids) { - if (name->max_ids == 0) { - name->max_ids = 1000; - name->name = (char **)bmalloc(sizeof(char *) * name->max_ids); - } else { - name->max_ids = (name->max_ids * 3) / 2; - name->name = (char **)brealloc(name->name, sizeof(char *) * name->max_ids); - } - } - for (int i=0; inum_ids; i++) { - if (strcmp(name->name[i], row[0]) == 0) { - return 0; /* already in list, return */ - } - } - /* Add new name to list */ - name->name[name->num_ids++] = bstrdup(row[0]); - return 0; -} - - -/* - * Print names in the list - */ -static void print_name_list(UAContext *ua, NAME_LIST *name_list) -{ - for (int i=0; i < name_list->num_ids; i++) { - bsendmsg(ua, "%s\n", name_list->name[i]); - } -} -#endif - - /* * Free names in the list */ @@ -1252,6 +1206,7 @@ void find_storage_resource(UAContext *ua, RESTORE_CTX &rx, char *Storage, char * STORE *store; if (rx.store) { + Dmsg1(200, "Already have store=%s\n", rx.store->name()); return; } /* @@ -1259,8 +1214,8 @@ void find_storage_resource(UAContext *ua, RESTORE_CTX &rx, char *Storage, char * */ LockRes(); foreach_res(store, R_STORAGE) { - if (strcmp(Storage, store->hdr.name) == 0) { - if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) { + if (strcmp(Storage, store->name()) == 0) { + if (acl_access_ok(ua, Storage_ACL, store->name())) { rx.store = store; } break; @@ -1274,14 +1229,15 @@ void find_storage_resource(UAContext *ua, RESTORE_CTX &rx, char *Storage, char * int i = find_arg_with_value(ua, "storage"); if (i > 0) { store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]); - if (store && !acl_access_ok(ua, Storage_ACL, store->hdr.name)) { + if (store && !acl_access_ok(ua, Storage_ACL, store->name())) { store = NULL; } } if (store && (store != rx.store)) { bsendmsg(ua, _("Warning default storage overridden by \"%s\" on command line.\n"), - store->hdr.name); + store->name()); rx.store = store; + Dmsg1(200, "Set store=%s\n", rx.store->name()); } return; } @@ -1291,10 +1247,11 @@ void find_storage_resource(UAContext *ua, RESTORE_CTX &rx, char *Storage, char * LockRes(); foreach_res(store, R_STORAGE) { if (strcmp(MediaType, store->media_type) == 0) { - if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) { + if (acl_access_ok(ua, Storage_ACL, store->name())) { rx.store = store; + Dmsg1(200, "Set store=%s\n", rx.store->name()); bsendmsg(ua, _("Storage \"%s\" not found, using Storage \"%s\" from MediaType \"%s\".\n"), - Storage, store->hdr.name, MediaType); + Storage, store->name(), MediaType); } UnlockRes(); return; @@ -1307,71 +1264,6 @@ void find_storage_resource(UAContext *ua, RESTORE_CTX &rx, char *Storage, char * /* Take command line arg, or ask user if none */ rx.store = get_storage_resource(ua, false /* don't use default */); + Dmsg1(200, "Set store=%s\n", rx.store->name()); } - - -#ifdef xxxx_needed -static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, RESTORE_CTX *rx) -{ - STORE *store; - - if (name_list->num_ids > 1) { - bsendmsg(ua, _("Warning, the JobIds that you selected refer to more than one MediaType.\n" - "Restore may not be possible. The MediaTypes used are:\n")); - print_name_list(ua, name_list); -// rx->store = select_storage_resource(ua); - return; - } - - if (name_list->num_ids == 0) { - bsendmsg(ua, _("No MediaType found for your JobIds.\n")); - rx->store = select_storage_resource(ua); - return; - } - if (rx->store) { - return; - } - /* - * We have a single MediaType, look it up in our Storage resource - */ - LockRes(); - foreach_res(store, R_STORAGE) { - if (strcmp(name_list->name[0], store->media_type) == 0) { - if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) { - rx->store = store; - } - break; - } - } - UnlockRes(); - - if (rx->store) { - /* Check if an explicit storage resource is given */ - store = NULL; - int i = find_arg_with_value(ua, "storage"); - if (i > 0) { - store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]); - if (store && !acl_access_ok(ua, Storage_ACL, store->hdr.name)) { - store = NULL; - } - } - if (store && (store != rx->store)) { - bsendmsg(ua, _("Warning default storage overridden by %s on command line.\n"), - store->hdr.name); - rx->store = store; - } - return; - } - - /* Take command line arg, or ask user if none */ - rx->store = get_storage_resource(ua, false /* don't use default */); - - if (!rx->store) { - bsendmsg(ua, _("\nWarning. Unable to find Storage resource for\n" - "MediaType \"%s\", needed by the Jobs you selected.\n" - "You will be allowed to select a Storage device later.\n"), - name_list->name[0]); - } -} -#endif diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index 334fe079c1..b55bc1590a 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -321,9 +321,9 @@ int run_cmd(UAContext *ua, const char *cmd) } if (!job) { return 0; - } else if (!acl_access_ok(ua, Job_ACL, job->hdr.name)) { + } else if (!acl_access_ok(ua, Job_ACL, job->name())) { bsendmsg(ua, _("No authorization. Job \"%s\".\n"), - job->hdr.name); + job->name()); return 0; } @@ -340,12 +340,12 @@ int run_cmd(UAContext *ua, const char *cmd) } if (!store) { return 1; - } else if (!acl_access_ok(ua, Storage_ACL, store->hdr.name)) { + } else if (!acl_access_ok(ua, Storage_ACL, store->name())) { bsendmsg(ua, _("No authorization. Storage \"%s\".\n"), - store->hdr.name); + store->name()); return 0; } - Dmsg1(800, "Using storage=%s\n", store->hdr.name); + Dmsg1(800, "Using storage=%s\n", store->name()); if (pool_name) { pool = (POOL *)GetResWithName(R_POOL, pool_name); @@ -360,12 +360,12 @@ int run_cmd(UAContext *ua, const char *cmd) } if (!pool) { return 0; - } else if (!acl_access_ok(ua, Pool_ACL, pool->hdr.name)) { + } else if (!acl_access_ok(ua, Pool_ACL, pool->name())) { bsendmsg(ua, _("No authorization. Pool \"%s\".\n"), - pool->hdr.name); + pool->name()); return 0; } - Dmsg1(800, "Using pool\n", pool->hdr.name); + Dmsg1(800, "Using pool\n", pool->name()); if (client_name) { client = (CLIENT *)GetResWithName(R_CLIENT, client_name); @@ -380,12 +380,12 @@ int run_cmd(UAContext *ua, const char *cmd) } if (!client) { return 0; - } else if (!acl_access_ok(ua, Client_ACL, client->hdr.name)) { + } else if (!acl_access_ok(ua, Client_ACL, client->name())) { bsendmsg(ua, _("No authorization. Client \"%s\".\n"), - client->hdr.name); + client->name()); return 0; } - Dmsg1(800, "Using client=%s\n", client->hdr.name); + Dmsg1(800, "Using client=%s\n", client->name()); if (fileset_name) { fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name); @@ -398,9 +398,9 @@ int run_cmd(UAContext *ua, const char *cmd) } if (!fileset) { return 0; - } else if (!acl_access_ok(ua, FileSet_ACL, fileset->hdr.name)) { + } else if (!acl_access_ok(ua, FileSet_ACL, fileset->name())) { bsendmsg(ua, _("No authorization. FileSet \"%s\".\n"), - fileset->hdr.name); + fileset->name()); return 0; } @@ -434,7 +434,7 @@ int run_cmd(UAContext *ua, const char *cmd) jcr->verify_job = verify_job; jcr->previous_job = previous_job; - set_storage(jcr, store); + set_rwstorage(jcr, store); jcr->client = client; jcr->fileset = fileset; jcr->pool = pool; @@ -539,10 +539,10 @@ try_again: "When: %s\n" "Priority: %d\n"), _("Admin"), - job->hdr.name, - jcr->fileset->hdr.name, - NPRT(jcr->client->hdr.name), - NPRT(jcr->store->hdr.name), + job->name(), + jcr->fileset->name(), + NPRT(jcr->client->name()), + NPRT(jcr->wstore->name()), bstrutime(dt, sizeof(dt), jcr->sched_time), jcr->JobPriority); jcr->JobLevel = L_FULL; @@ -560,18 +560,18 @@ try_again: "When: %s\n" "Priority: %d\n"), _("Backup"), - job->hdr.name, - jcr->fileset->hdr.name, + job->name(), + jcr->fileset->name(), level_to_str(jcr->JobLevel), - jcr->client->hdr.name, - jcr->store->hdr.name, - NPRT(jcr->pool->hdr.name), + jcr->client->name(), + jcr->wstore->name(), + NPRT(jcr->pool->name()), bstrutime(dt, sizeof(dt), jcr->sched_time), jcr->JobPriority); } else { /* JT_VERIFY */ const char *Name; if (jcr->verify_job) { - Name = jcr->verify_job->hdr.name; + Name = jcr->verify_job->name(); } else { Name = ""; } @@ -593,12 +593,12 @@ try_again: "When: %s\n" "Priority: %d\n"), _("Verify"), - job->hdr.name, - jcr->fileset->hdr.name, + job->name(), + jcr->fileset->name(), level_to_str(jcr->JobLevel), - jcr->client->hdr.name, - jcr->store->hdr.name, - NPRT(jcr->pool->hdr.name), + jcr->client->name(), + jcr->rstore->name(), + NPRT(jcr->pool->name()), Name, verify_list, bstrutime(dt, sizeof(dt), jcr->sched_time), @@ -630,15 +630,15 @@ try_again: "When: %s\n" "Catalog: %s\n" "Priority: %d\n"), - job->hdr.name, + job->name(), NPRT(jcr->RestoreBootstrap), jcr->where?jcr->where:NPRT(job->RestoreWhere), replace, - jcr->fileset->hdr.name, - jcr->client->hdr.name, - jcr->store->hdr.name, + jcr->fileset->name(), + jcr->client->name(), + jcr->rstore->name(), bstrutime(dt, sizeof(dt), jcr->sched_time), - jcr->catalog->hdr.name, + jcr->catalog->name(), jcr->JobPriority); } else { bsendmsg(ua, _("Run Restore job\n" @@ -652,15 +652,15 @@ try_again: "When: %s\n" "Catalog: %s\n" "Priority: %d\n"), - job->hdr.name, + job->name(), NPRT(jcr->RestoreBootstrap), jcr->where?jcr->where:NPRT(job->RestoreWhere), replace, - jcr->client->hdr.name, - jcr->store->hdr.name, + jcr->client->name(), + jcr->rstore->name(), jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1), bstrutime(dt, sizeof(dt), jcr->sched_time), - jcr->catalog->hdr.name, + jcr->catalog->name(), jcr->JobPriority); } break; @@ -676,14 +676,14 @@ try_again: "When: %s\n" "Catalog: %s\n" "Priority: %d\n"), - job->hdr.name, + job->name(), NPRT(jcr->RestoreBootstrap), - jcr->fileset->hdr.name, - jcr->client->hdr.name, - jcr->store->hdr.name, + jcr->fileset->name(), + jcr->client->name(), + jcr->wstore->name(), jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1), bstrutime(dt, sizeof(dt), jcr->sched_time), - jcr->catalog->hdr.name, + jcr->catalog->name(), jcr->JobPriority); break; default: @@ -785,7 +785,7 @@ try_again: /* Storage */ store = select_storage_resource(ua); if (store) { - set_storage(jcr, store); + set_rwstorage(jcr, store); goto try_again; } break; diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index 9ae31bd05e..169fbc45e6 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -828,7 +828,7 @@ STORE *get_storage_resource(UAContext *ua, bool use_default) bsendmsg(ua, _("JobId %s is not running.\n"), edit_int64(jobid, ed1)); return NULL; } - store = jcr->store; + store = jcr->wstore; free_jcr(jcr); break; @@ -842,7 +842,7 @@ STORE *get_storage_resource(UAContext *ua, bool use_default) bsendmsg(ua, _("Job \"%s\" is not running.\n"), ua->argv[i]); return NULL; } - store = jcr->store; + store = jcr->wstore; free_jcr(jcr); break; } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) { @@ -854,7 +854,7 @@ STORE *get_storage_resource(UAContext *ua, bool use_default) bsendmsg(ua, _("Job \"%s\" is not running.\n"), ua->argv[i]); return NULL; } - store = jcr->store; + store = jcr->wstore; free_jcr(jcr); break; } diff --git a/bacula/src/dird/ua_status.c b/bacula/src/dird/ua_status.c index 49ddebd316..6ea1e34de7 100644 --- a/bacula/src/dird/ua_status.c +++ b/bacula/src/dird/ua_status.c @@ -175,7 +175,7 @@ static void do_all_status(UAContext *ua) i = 0; foreach_res(store, R_STORAGE) { found = false; - if (!acl_access_ok(ua, Storage_ACL, store->hdr.name)) { + if (!acl_access_ok(ua, Storage_ACL, store->name())) { continue; } for (j=0; jhdr.name)) { + if (!acl_access_ok(ua, Client_ACL, client->name())) { continue; } for (j=0; jjcr, store); + set_wstorage(ua->jcr, store); /* Try connecting for up to 15 seconds */ bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d\n"), - store->hdr.name, store->address, store->SDport); + store->name(), store->address, store->SDport); if (!connect_to_storage_daemon(ua->jcr, 1, 15, 0)) { bsendmsg(ua, _("\nFailed to connect to Storage daemon %s.\n====\n"), - store->hdr.name); + store->name()); if (ua->jcr->store_bsock) { bnet_close(ua->jcr->store_bsock); ua->jcr->store_bsock = NULL; @@ -318,10 +318,10 @@ static void do_client_status(UAContext *ua, CLIENT *client) /* Try to connect for 15 seconds */ bsendmsg(ua, _("Connecting to Client %s at %s:%d\n"), - client->hdr.name, client->address, client->FDport); + client->name(), client->address, client->FDport); if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) { bsendmsg(ua, _("Failed to connect to Client %s.\n====\n"), - client->hdr.name); + client->name()); if (ua->jcr->file_bsock) { bnet_close(ua->jcr->file_bsock); ua->jcr->file_bsock = NULL; @@ -396,7 +396,7 @@ static void prt_runtime(UAContext *ua, sched_pkt *sp) } bsendmsg(ua, _("%-14s %-8s %3d %-18s %-18s %s\n"), level_ptr, job_type_to_str(sp->job->JobType), sp->priority, dt, - sp->job->hdr.name, mr.VolumeName); + sp->job->name(), mr.VolumeName); if (close_db) { db_close_database(jcr, jcr->db); } @@ -456,7 +456,7 @@ static void list_scheduled_jobs(UAContext *ua) /* Loop through all jobs */ LockRes(); foreach_res(job, R_JOB) { - if (!acl_access_ok(ua, Job_ACL, job->hdr.name) || !job->enabled) { + if (!acl_access_ok(ua, Job_ACL, job->name()) || !job->enabled) { continue; } for (run=NULL; (run = find_next_run(run, job, runtime, days)); ) { @@ -536,7 +536,7 @@ static void list_running_jobs(UAContext *ua) bsendmsg(ua, _(" JobId Level Name Status\n")); bsendmsg(ua, _("======================================================================\n")); foreach_jcr(jcr) { - if (jcr->JobId == 0 || !acl_access_ok(ua, Job_ACL, jcr->job->hdr.name)) { + if (jcr->JobId == 0 || !acl_access_ok(ua, Job_ACL, jcr->job->name())) { continue; } njobs++; @@ -570,13 +570,17 @@ static void list_running_jobs(UAContext *ua) break; case JS_WaitFD: emsg = (char *) get_pool_memory(PM_FNAME); - Mmsg(emsg, _("is waiting on Client %s"), jcr->client->hdr.name); + Mmsg(emsg, _("is waiting on Client %s"), jcr->client->name()); pool_mem = true; msg = emsg; break; case JS_WaitSD: emsg = (char *) get_pool_memory(PM_FNAME); - Mmsg(emsg, _("is waiting on Storage %s"), jcr->store->hdr.name); + if (jcr->wstore) { + Mmsg(emsg, _("is waiting on Storage %s"), jcr->wstore->name()); + } else { + Mmsg(emsg, _("is waiting on Storage %s"), jcr->rstore->name()); + } pool_mem = true; msg = emsg; break; @@ -630,7 +634,7 @@ static void list_running_jobs(UAContext *ua) pool_mem = true; } Mmsg(emsg, _("is waiting for Client %s to connect to Storage %s"), - jcr->client->hdr.name, jcr->store->hdr.name); + jcr->client->name(), jcr->wstore->name()); msg = emsg; break; } diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 84a2ba196c..a83c1b1cba 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -57,6 +57,8 @@ bool do_verify_init(JCR *jcr) JobId_t verify_jobid = 0; const char *Name; + free_wstorage(jcr); /* we don't write */ + memset(&jcr->previous_jr, 0, sizeof(jcr->previous_jr)); Dmsg1(9, "bdird: created client %s record\n", jcr->client->hdr.name); @@ -171,7 +173,7 @@ bool do_verify(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr, jcr->storage, NULL)) { + if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) { return false; } if (!bnet_fsend(jcr->store_bsock, "run")) { @@ -224,10 +226,10 @@ bool do_verify(JCR *jcr) /* * send Storage daemon address to the File daemon */ - if (jcr->store->SDDport == 0) { - jcr->store->SDDport = jcr->store->SDport; + if (jcr->rstore->SDDport == 0) { + jcr->rstore->SDDport = jcr->rstore->SDport; } - bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport); + bnet_fsend(fd, storaddr, jcr->rstore->address, jcr->rstore->SDDport); if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) { return false; } diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 5e2a69c828..20630005f0 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -114,13 +114,13 @@ private: pthread_mutex_t mutex; /* jcr mutex */ volatile int _use_count; /* use count */ public: - void inc_use_count(void) {P(mutex); _use_count++; V(mutex); }; - void dec_use_count(void) {P(mutex); _use_count--; V(mutex); }; + void lock() {P(mutex); }; + void unlock() {V(mutex); }; + void inc_use_count(void) {lock(); _use_count++; unlock(); }; + void dec_use_count(void) {lock(); _use_count--; unlock(); }; int use_count() { return _use_count; }; void init_mutex(void) {pthread_mutex_init(&mutex, NULL); }; void destroy_mutex(void) {pthread_mutex_destroy(&mutex); }; - void lock() {P(mutex); }; - void unlock() {V(mutex); }; bool is_job_canceled() {return job_canceled(this); }; /* Global part of JCR common to all daemons */ @@ -185,8 +185,10 @@ public: BSOCK *ua; /* User agent */ JOB *job; /* Job resource */ JOB *verify_job; /* Job resource of verify previous job */ - alist *storage; /* Storage possibilities */ - STORE *store; /* Storage daemon selected */ + alist *rstorage; /* Read storage possibilities */ + STORE *rstore; /* Selected read storage */ + alist *wstorage; /* Write storage possibilities */ + STORE *wstore; /* Selected write storage */ CLIENT *client; /* Client resource */ POOL *pool; /* Pool resource */ POOL *full_pool; /* Full backup pool resource */ -- 2.39.5