diff --git a/src/dird/job.c b/src/dird/job.c index 5045471a13c..6485e481b90 100644 --- a/src/dird/job.c +++ b/src/dird/job.c @@ -1501,6 +1501,7 @@ void dird_free_jcr(JCR *jcr) free_and_null_pool_memory(jcr->res.catalog_source); free_and_null_pool_memory(jcr->FDSecureEraseCmd); free_and_null_pool_memory(jcr->SDSecureEraseCmd); + free_and_null_pool_memory(jcr->vf_jobids); /* * Delete lists setup to hold storage pointers diff --git a/src/dird/ua_run.c b/src/dird/ua_run.c index da60af8a132..a53b7de9f88 100644 --- a/src/dird/ua_run.c +++ b/src/dird/ua_run.c @@ -977,9 +977,18 @@ static bool reset_restore_context(UAContext *ua, JCR *jcr, RUN_CTX &rc) } if (rc.jid) { - /* Note, this is also MigrateJobId and a VerifyJobId */ - jcr->RestoreJobId = str_to_int64(rc.jid); - rc.jid = 0; + if (jcr->is_JobType(JT_BACKUP) && jcr->is_JobLevel(L_VIRTUAL_FULL)) { + if (!jcr->vf_jobids) { + jcr->vf_jobids = get_pool_memory(PM_MESSAGE); + } + pm_strcpy(jcr->vf_jobids, rc.jid); + } else { + /* + * Note, this is also MigrateJobId and a VerifyJobId + */ + jcr->RestoreJobId = str_to_int64(rc.jid); + } + rc.jid = NULL; } if (rc.backup_format) { diff --git a/src/dird/vbackup.c b/src/dird/vbackup.c index 3f7e2b541cb..12ca58a40ea 100644 --- a/src/dird/vbackup.c +++ b/src/dird/vbackup.c @@ -3,7 +3,7 @@ Copyright (C) 2008-2012 Free Software Foundation Europe e.V. Copyright (C) 2011-2012 Planets Communications B.V. - Copyright (C) 2013-2013 Bareos GmbH & Co. KG + Copyright (C) 2013-2016 Bareos GmbH & Co. KG This program is Free Software; you can redistribute it and/or modify it under the terms of version three of the GNU Affero General Public @@ -43,8 +43,7 @@ static const int dbglevel = 10; static bool create_bootstrap_file(JCR *jcr, char *jobids); /* - * Called here before the job is run to do the job - * specific setup. + * Called here before the job is run to do the job specific setup. */ bool do_native_vbackup_init(JCR *jcr) { @@ -67,16 +66,19 @@ bool do_native_vbackup_init(JCR *jcr) Jmsg(jcr, M_FATAL, 0, _("Could not get or create a Pool record.\n")); return false; } + /* * Note, at this point, pool is the pool for this job. We - * transfer it to rpool (read pool), and a bit later, - * pool will be changed to point to the write pool, - * which comes from pool->NextPool. + * transfer it to rpool (read pool), and a bit later, + * pool will be changed to point to the write pool, + * which comes from pool->NextPool. */ jcr->res.rpool = jcr->res.pool; /* save read pool */ pm_strcpy(jcr->res.rpool_source, jcr->res.pool_source); - /* If pool storage specified, use it for restore */ + /* + * If pool storage specified, use it for restore + */ copy_rstorage(jcr, jcr->res.pool->storage, _("Pool resource")); Dmsg2(dbglevel, "Read pool=%s (From %s)\n", jcr->res.rpool->name(), jcr->res.rpool_source); @@ -116,8 +118,8 @@ bool do_native_vbackup_init(JCR *jcr) /* * If the original backup pool has a NextPool, make sure a - * record exists in the database. Note, in this case, we - * will be migrating from pool to pool->NextPool. + * record exists in the database. Note, in this case, we + * will be migrating from pool to pool->NextPool. */ if (jcr->res.next_pool) { jcr->jr.PoolId = get_or_create_pool_record(jcr, jcr->res.next_pool->name()); @@ -140,18 +142,17 @@ bool do_native_vbackup_init(JCR *jcr) } /* - * Do a virtual backup, which consolidates all previous backups into - * a sort of synthetic Full. + * Do a virtual backup, which consolidates all previous backups into a sort of synthetic Full. * - * Returns: false on failure - * true on success + * Returns: false on failure + * true on success */ bool do_native_vbackup(JCR *jcr) { - char ed1[100]; - BSOCK *sd; char *p; - db_list_ctx jobids; + BSOCK *sd; + char *jobids; + char ed1[100]; if (!jcr->res.rstorage) { Jmsg(jcr, M_FATAL, 0, _("No storage for reading given.\n")); @@ -165,8 +166,8 @@ bool do_native_vbackup(JCR *jcr) Dmsg2(100, "rstorage=%p wstorage=%p\n", jcr->res.rstorage, jcr->res.wstorage); Dmsg2(100, "Read store=%s, write store=%s\n", - ((STORERES *)jcr->res.rstorage->first())->name(), - ((STORERES *)jcr->res.wstorage->first())->name()); + ((STORERES *)jcr->res.rstorage->first())->name(), + ((STORERES *)jcr->res.wstorage->first())->name()); /* * Print Job Start message @@ -178,24 +179,38 @@ bool do_native_vbackup(JCR *jcr) _("This Job is not an Accurate backup so is not equivalent to a Full backup.\n")); } - db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, &jobids); - Dmsg1(10, "Accurate jobids=%s\n", jobids.list); - if (jobids.count == 0) { - Jmsg(jcr, M_FATAL, 0, _("No previous Jobs found.\n")); - return false; + /* + * See if we already got a list of jobids to use. + */ + if (jcr->vf_jobids) { + Dmsg1(10, "Accurate jobids=%s\n", jcr->vf_jobids); + jobids = bstrdup(jcr->vf_jobids); + } else { + db_list_ctx jobids_ctx; + + db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, &jobids_ctx); + Dmsg1(10, "Accurate jobids=%s\n", jobids_ctx.list); + if (jobids_ctx.count == 0) { + Jmsg(jcr, M_FATAL, 0, _("No previous Jobs found.\n")); + return false; + } + + jobids = bstrdup(jobids_ctx.list); } + Jmsg(jcr, M_INFO, 0, _("Consolidating JobIds %s\n"), jobids); + /* * Now we find the last job that ran and store it's info in * the previous_jr record. We will set our times to the * values from that job so that anything changed after that * time will be picked up on the next backup. */ - p = strrchr(jobids.list, ','); /* find last jobid */ + p = strrchr(jobids, ','); /* find last jobid */ if (p != NULL) { p++; } else { - p = jobids.list; + p = jobids; } memset(&jcr->previous_jr, 0, sizeof(jcr->previous_jr)); @@ -204,20 +219,19 @@ bool do_native_vbackup(JCR *jcr) if (!db_get_job_record(jcr, jcr->db, &jcr->previous_jr)) { Jmsg(jcr, M_FATAL, 0, _("Error getting Job record for previous Job: ERR=%s"), - db_strerror(jcr->db)); - return false; + db_strerror(jcr->db)); + goto bail_out; } - if (!create_bootstrap_file(jcr, jobids.list)) { + if (!create_bootstrap_file(jcr, jobids)) { Jmsg(jcr, M_FATAL, 0, _("Could not get or create the FileSet record.\n")); - return false; + goto bail_out; } /* * Open a message channel connection with the Storage * daemon. This is to let him know that our client * will be contacting him for a backup session. - * */ Dmsg0(110, "Open connection with storage daemon\n"); jcr->setJobStatus(JS_WaitSD); @@ -226,7 +240,7 @@ bool do_native_vbackup(JCR *jcr) * Start conversation with Storage daemon */ if (!connect_to_storage_daemon(jcr, 10, me->SDConnectTimeout, true)) { - return false; + goto bail_out; } sd = jcr->store_bsock; @@ -234,7 +248,7 @@ bool do_native_vbackup(JCR *jcr) * Now start a job with the Storage daemon */ if (!start_storage_daemon_job(jcr, jcr->res.rstorage, jcr->res.wstorage, /* send_bsr */ true)) { - return false; + goto bail_out; } Dmsg0(100, "Storage daemon connection OK\n"); @@ -258,7 +272,7 @@ bool do_native_vbackup(JCR *jcr) */ if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) { Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); - return false; + goto bail_out; } /* @@ -272,14 +286,14 @@ bool do_native_vbackup(JCR *jcr) * the same time. */ if (!sd->fsend("run")) { - return false; + goto bail_out; } /* * Now start a Storage daemon message thread */ if (!start_storage_daemon_message_thread(jcr)) { - return false; + goto bail_out; } jcr->setJobStatus(JS_Running); @@ -292,11 +306,16 @@ bool do_native_vbackup(JCR *jcr) jcr->setJobStatus(jcr->SDJobStatus); db_write_batch_file_records(jcr); /* used by bulk batch file insert */ if (!jcr->is_JobStatus(JS_Terminated)) { - return false; + goto bail_out; } native_vbackup_cleanup(jcr, jcr->JobStatus); + free(jobids); return true; + +bail_out: + free(jobids); + return false; } /* diff --git a/src/dird/verify.c b/src/dird/verify.c index fef06dd0067..5257866a669 100644 --- a/src/dird/verify.c +++ b/src/dird/verify.c @@ -139,8 +139,8 @@ bool do_verify(JCR *jcr) /* * See if user supplied a jobid= as run argument or from menu */ - if (jcr->RestoreJobId) { - verify_jobid = jcr->RestoreJobId; + if (jcr->VerifyJobId) { + verify_jobid = jcr->VerifyJobId; Dmsg1(100, "Supplied jobid=%d\n", verify_jobid); } else { diff --git a/src/include/jcr.h b/src/include/jcr.h index 3e22d823a49..e12a6d00d79 100644 --- a/src/include/jcr.h +++ b/src/include/jcr.h @@ -439,8 +439,6 @@ class JCR { uint32_t SDJobFiles; /* Number of files written, this job */ uint64_t SDJobBytes; /* Number of bytes processed this job */ uint32_t SDErrors; /* Number of non-fatal errors */ - POOLMEM *FDSecureEraseCmd; /* Report: Secure Erase Command */ - POOLMEM *SDSecureEraseCmd; /* Report: Secure Erase Command */ volatile int32_t SDJobStatus; /* Storage Job Status */ volatile int32_t FDJobStatus; /* File daemon Job Status */ uint32_t DumpLevel; /* Dump level when doing a NDMP backup */ @@ -448,7 +446,6 @@ class JCR { uint32_t MediaId; /* DB record IDs associated with this job */ uint32_t FileIndex; /* Last FileIndex processed */ utime_t MaxRunSchedTime; /* Max run time in seconds from Initial Scheduled time */ - POOLMEM *fname; /* Name to put into catalog */ JOB_DBR jr; /* Job DB record for current job */ JOB_DBR previous_jr; /* Previous job database record */ JCR *mig_jcr; /* JCR for migration/copy job */ @@ -456,10 +453,15 @@ class JCR { char since[MAX_TIME_LENGTH]; /* Since time */ char PrevJob[MAX_NAME_LENGTH]; /* Previous job name assiciated with since time */ union { - JobId_t RestoreJobId; /* Restore id specified by UA */ - JobId_t MigrateJobId; /* Migration id specified by UA */ + JobId_t RestoreJobId; /* Restore JobId specified by UA */ + JobId_t MigrateJobId; /* Migration JobId specified by UA */ + JobId_t VerifyJobId; /* Verify JobId specified by UA */ }; + POOLMEM *fname; /* Name to put into catalog */ POOLMEM *client_uname; /* Client uname */ + POOLMEM *FDSecureEraseCmd; /* Report: Secure Erase Command */ + POOLMEM *SDSecureEraseCmd; /* Report: Secure Erase Command */ + POOLMEM *vf_jobids; /* JobIds to use for Virtual Full */ uint32_t replace; /* Replace option */ int32_t NumVols; /* Number of Volume used in pool */ int32_t reschedule_count; /* Number of times rescheduled */