From 0c7ee334ba6500b957240d4a5c7c0416ffd00a69 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 30 Dec 2015 19:19:27 +0100 Subject: [PATCH] Integrate patch into latest version, which fixes bug #1882 --- bacula/src/cats/bdb.h | 1 + bacula/src/cats/protos.h | 2 ++ bacula/src/cats/sql_find.c | 65 ++++++++++++++++++++++++++++++++++---- bacula/src/dird/fd_cmds.c | 35 ++++++++++++++------ 4 files changed, 88 insertions(+), 15 deletions(-) diff --git a/bacula/src/cats/bdb.h b/bacula/src/cats/bdb.h index 717f0dab90..87b260be03 100644 --- a/bacula/src/cats/bdb.h +++ b/bacula/src/cats/bdb.h @@ -119,6 +119,7 @@ public: int bdb_delete_snapshot_record(JCR *jcr, SNAPSHOT_DBR *sr); /* sql_find.c */ + bool bdb_find_last_job_end_time(JCR *jcr, JOB_DBR *jr, POOLMEM **etime, char *job); bool bdb_find_last_job_start_time(JCR *jcr, JOB_DBR *jr, POOLMEM **stime, char *job, int JobLevel); bool bdb_find_job_start_time(JCR *jcr, JOB_DBR *jr, POOLMEM **stime, char *job); bool bdb_find_last_jobid(JCR *jcr, const char *Name, JOB_DBR *jr); diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index 5a6a726c95..61c9119c18 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -163,6 +163,8 @@ void bdb_free_restoreobject_record(JCR *jcr, ROBJECT_DBR *rr); /* sql_find.c */ +#define db_find_last_job_end_time(jcr, mdb, jr, etime, job) \ + mdb->bdb_find_last_job_end_time(jcr, jr, etime, job) #define db_find_last_job_start_time(jcr, mdb, jr, stime, job, JobLevel) \ mdb->bdb_find_last_job_start_time(jcr, jr, stime, job, JobLevel) #define db_find_job_start_time(jcr, mdb, jr, stime, job) \ diff --git a/bacula/src/cats/sql_find.c b/bacula/src/cats/sql_find.c index 16c8c3e770..0a0878cd21 100644 --- a/bacula/src/cats/sql_find.c +++ b/bacula/src/cats/sql_find.c @@ -41,6 +41,58 @@ * ----------------------------------------------------------------------- */ +/* + * Find the most recent successful real end time for a job given. + * + * RealEndTime is returned in etime + * Job name is returned in job (MAX_NAME_LENGTH) + * + * Returns: false on failure + * true on success, jr is unchanged, but etime and job are set + */ +bool BDB::bdb_find_last_job_end_time(JCR *jcr, JOB_DBR *jr, POOLMEM **etime, + char *job) +{ + SQL_ROW row; + char ed1[50], ed2[50]; + char esc_name[MAX_ESCAPE_NAME_LENGTH]; + + bdb_lock(); + bdb_escape_string(jcr, esc_name, jr->Name, strlen(jr->Name)); + pm_strcpy(etime, "0000-00-00 00:00:00"); /* default */ + job[0] = 0; + + Mmsg(cmd, + "SELECT RealEndTime, Job FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " + "Level IN ('%c','%c','%c') AND Name='%s' AND ClientId=%s AND FileSetId=%s " + "ORDER BY RealEndTime DESC LIMIT 1", jr->JobType, + L_FULL, L_DIFFERENTIAL, L_INCREMENTAL, esc_name, + edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); + + if (!QueryDB(jcr, cmd)) { + Mmsg2(&errmsg, _("Query error for end time request: ERR=%s\nCMD=%s\n"), + sql_strerror(), cmd); + goto bail_out; + } + if ((row = sql_fetch_row()) == NULL) { + sql_free_result(); + Mmsg(errmsg, _("No prior backup Job record found.\n")); + goto bail_out; + } + Dmsg1(100, "Got end time: %s\n", row[0]); + pm_strcpy(etime, row[0]); + bstrncpy(job, row[1], MAX_NAME_LENGTH); + + sql_free_result(); + bdb_unlock(); + return true; + +bail_out: + bdb_unlock(); + return false; +} + + /* * Find job start time if JobId specified, otherwise * find last Job start time Incremental and Differential saves. @@ -48,8 +100,8 @@ * StartTime is returned in stime * Job name is returned in job (MAX_NAME_LENGTH) * - * Returns: 0 on failure - * 1 on success, jr is unchanged, but stime and job are set + * Returns: false on failure + * true on success, jr is unchanged, but stime and job are set */ bool BDB::bdb_find_job_start_time(JCR *jcr, JOB_DBR *jr, POOLMEM **stime, char *job) { @@ -208,10 +260,11 @@ bool BDB::bdb_find_failed_job_since(JCR *jcr, JOB_DBR *jr, POOLMEM *stime, int & /* Differential is since last Full backup */ Mmsg(cmd, -"SELECT Level FROM Job WHERE JobStatus NOT IN ('T','W') AND " -"Type='%c' AND Level IN ('%c','%c') AND Name='%s' AND ClientId=%s " -"AND FileSetId=%s AND StartTime>'%s' " -"ORDER BY StartTime DESC LIMIT 1", + "SELECT Level FROM Job WHERE JobStatus IN ('%c','%c', '%c', '%c') AND " + "Type='%c' AND Level IN ('%c','%c') AND Name='%s' AND ClientId=%s " + "AND FileSetId=%s AND StartTime>'%s' " + "ORDER BY StartTime DESC LIMIT 1", + JS_Canceled, JS_ErrorTerminated, JS_Error, JS_FatalError, jr->JobType, L_FULL, L_DIFFERENTIAL, esc_name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2), stime); diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index 52d4d7fd51..84e198de8b 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -257,16 +257,33 @@ void get_level_since_time(JCR *jcr, char *since, int since_len) jcr->setJobLevel(jcr->jr.JobLevel = L_DIFFERENTIAL); } else { if (jcr->job->rerun_failed_levels) { - if (db_find_failed_job_since(jcr, jcr->db, &jcr->jr, - jcr->stime, JobLevel)) { - Jmsg(jcr, M_INFO, 0, _("Prior failed job found in catalog. Upgrading to %s.\n"), - level_to_str(JobLevel)); - bsnprintf(since, since_len, _(" (upgraded from %s)"), - level_to_str(jcr->getJobLevel())); - jcr->setJobLevel(jcr->jr.JobLevel = JobLevel); - jcr->jr.JobId = jcr->JobId; - break; + + POOLMEM *etime = get_pool_memory(PM_MESSAGE); + + /* Get the end time of our most recent successfull backup for this job */ + /* This will be used to see if there have been any failures since then */ + if (db_find_last_job_end_time(jcr, jcr->db, &jcr->jr, &etime, prev_job)) { + + /* See if there are any failed Differential/Full backups since the completion */ + /* of our last successful backup for this job */ + if (db_find_failed_job_since(jcr, jcr->db, &jcr->jr, + etime, JobLevel)) { + /* If our job is an Incremental and we have a failed job then upgrade. */ + /* If our job is a Differential and the failed job is a Full then upgrade. */ + /* Otherwise there is no reason to upgrade. */ + if ((jcr->getJobLevel() == L_INCREMENTAL) || + ((jcr->getJobLevel() == L_DIFFERENTIAL) && (JobLevel == L_FULL))) { + Jmsg(jcr, M_INFO, 0, _("Prior failed job found in catalog. Upgrading to %s.\n"), + level_to_str(JobLevel)); + bsnprintf(since, since_len, _(" (upgraded from %s)"), + level_to_str(jcr->getJobLevel())); + jcr->setJobLevel(jcr->jr.JobLevel = JobLevel); + jcr->jr.JobId = jcr->JobId; + break; + } + } } + free_pool_memory(etime); } bstrncpy(since, _(", since="), since_len); bstrncat(since, jcr->stime, since_len); -- 2.39.2