From 4804ae852c70d399a195ffd92a6116dcd51936bf Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Tue, 28 Oct 2008 22:54:13 +0000 Subject: [PATCH] kes Fix bug #1046 VolumeToCatalog incorrectly reports mounted filesystems as missing on the Volume. kes Rewrite the set_jcr_job_status() code to include job status priorities so that more important status changes occur but lower priority status changes will not overwrite something more serious. This could possibly cause reporting incorrect status reporting in some cases. More testing is needed to ensure I have the right priorities. This vastly simplifies the previous contorted logic. Verify Diff status should now be correctly reported, whereas it was previously lost. kes Reduce some debug output. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@7928 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/patches/2.4.3-migrate-log.patch | 57 ++++++++++++++++++++++++++ bacula/patches/2.4.3-migrate.patch | 53 ++++++++++++++++++++++++ bacula/patches/2.4.3-prune.patch | 57 ++++++++++++++++++++++++++ bacula/src/cats/cats.h | 1 + bacula/src/cats/sql_get.c | 24 ++++++++++- bacula/src/dird/migrate.c | 28 ++++++++----- bacula/src/dird/protos.h | 2 +- bacula/src/dird/verify.c | 52 ++++++++++------------- bacula/src/lib/jcr.c | 55 ++++++++++++++++--------- bacula/src/stored/block.c | 2 +- bacula/src/stored/fd_cmds.c | 3 +- bacula/src/stored/spool.c | 2 + bacula/src/stored/vol_mgr.c | 8 ++-- bacula/technotes-2.5 | 12 ++++++ 14 files changed, 287 insertions(+), 69 deletions(-) create mode 100644 bacula/patches/2.4.3-migrate-log.patch create mode 100644 bacula/patches/2.4.3-migrate.patch create mode 100644 bacula/patches/2.4.3-prune.patch diff --git a/bacula/patches/2.4.3-migrate-log.patch b/bacula/patches/2.4.3-migrate-log.patch new file mode 100644 index 0000000000..a35f8159da --- /dev/null +++ b/bacula/patches/2.4.3-migrate-log.patch @@ -0,0 +1,57 @@ +Index: src/dird/migrate.c +=================================================================== +--- src/dird/migrate.c (revision 7926) ++++ src/dird/migrate.c (working copy) +@@ -402,14 +402,6 @@ + } + + migration_cleanup(jcr, jcr->JobStatus); +- if (mig_jcr) { +- char jobid[50]; +- UAContext *ua = new_ua_context(jcr); +- edit_uint64(jcr->previous_jr.JobId, jobid); +- /* Purge all old file records, but leave Job record */ +- purge_files_from_jobs(ua, jobid); +- free_ua_context(ua); +- } + return true; + } + +@@ -1087,11 +1079,26 @@ + edit_uint64(mig_jcr->jr.JobId, ec2)); + db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL); + +- /* Now mark the previous job as migrated if it terminated normally */ +- if (jcr->JobStatus == JS_Terminated) { ++ /* ++ * If we terminated a migration normally: ++ * - mark the previous job as migrated ++ * - move any Log records to the new JobId ++ * - Purge the File records from the previous job ++ */ ++ if (jcr->JobType == JT_MIGRATE && jcr->JobStatus == JS_Terminated) { ++ char old_jobid[50], new_jobid[50]; + Mmsg(query, "UPDATE Job SET Type='%c' WHERE JobId=%s", +- (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, ec1)); ++ (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, new_jobid)); + db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL); ++ UAContext *ua = new_ua_context(jcr); ++ /* Move JobLog to new JobId */ ++ Mmsg(query, "UPDATE Log SET JobId=%s WHERE JobId=%s", ++ new_jobid, ++ edit_uint64(jcr->previous_jr.JobId, old_jobid)); ++ db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL); ++ /* Purge all old file records, but leave Job record */ ++ purge_files_from_jobs(ua, old_jobid); ++ free_ua_context(ua); + } + + if (!db_get_job_record(jcr, jcr->db, &jcr->jr)) { +@@ -1100,7 +1107,6 @@ + set_jcr_job_status(jcr, JS_ErrorTerminated); + } + +- + update_bootstrap_file(mig_jcr); + + if (!db_get_job_volume_names(mig_jcr, mig_jcr->db, mig_jcr->jr.JobId, &mig_jcr->VolumeName)) { diff --git a/bacula/patches/2.4.3-migrate.patch b/bacula/patches/2.4.3-migrate.patch new file mode 100644 index 0000000000..138c09c9d1 --- /dev/null +++ b/bacula/patches/2.4.3-migrate.patch @@ -0,0 +1,53 @@ + + This patch should prevent migration jobs from attempting to migrate + jobs that failed. Apply it to Bacula 2.4.3 (possibly earlier versions) + with: + + cd + patch -p0 <2.4.3-migrate.patch + ./configure + make + ... + make install + + +Index: src/dird/migrate.c +=================================================================== +--- src/dird/migrate.c (revision 7757) ++++ src/dird/migrate.c (working copy) +@@ -377,7 +377,7 @@ + * to avoid two threads from using the BSOCK structure at + * the same time. + */ +- if (!bnet_fsend(sd, "run")) { ++ if (!sd->fsend("run")) { + return false; + } + +@@ -520,6 +520,7 @@ + "SELECT DISTINCT Job.JobId,Job.StartTime FROM Job,Pool,Client" + " WHERE Client.Name='%s' AND Pool.Name='%s' AND Job.PoolId=Pool.PoolId" + " AND Job.ClientId=Client.ClientId AND Job.Type='B'" ++ " AND Job.JobStatus = 'T'" + " ORDER by Job.StartTime"; + + /* Get Volume names in Pool */ +@@ -533,9 +534,9 @@ + "SELECT DISTINCT Job.JobId,Job.StartTime FROM Media,JobMedia,Job" + " WHERE Media.VolumeName='%s' AND Media.MediaId=JobMedia.MediaId" + " AND JobMedia.JobId=Job.JobId AND Job.Type='B'" ++ " AND Job.JobStatus = 'T' AND Media.Enabled=1" + " ORDER by Job.StartTime"; + +- + const char *sql_smallest_vol = + "SELECT Media.MediaId FROM Media,Pool,JobMedia WHERE" + " Media.MediaId in (SELECT DISTINCT MediaId from JobMedia) AND" +@@ -570,7 +571,6 @@ + const char *sql_job_bytes = + "SELECT SUM(JobBytes) FROM Job WHERE JobId IN (%s)"; + +- + /* Get Media Ids in Pool */ + const char *sql_mediaids = + "SELECT MediaId FROM Media,Pool WHERE" diff --git a/bacula/patches/2.4.3-prune.patch b/bacula/patches/2.4.3-prune.patch new file mode 100644 index 0000000000..7af00a7bec --- /dev/null +++ b/bacula/patches/2.4.3-prune.patch @@ -0,0 +1,57 @@ + + This patch should fix the bug reported on the bacula-users list where + a retention period of 100 years does immediate prunning. + Apply it to 2.4.3 (or earlier versions) with: + + cd + patch -p0 <2.4.3-prune.patch + ./configure + make + ... + make install + +Index: src/dird/ua_prune.c +=================================================================== +--- src/dird/ua_prune.c (revision 7757) ++++ src/dird/ua_prune.c (working copy) +@@ -202,7 +202,7 @@ + now = (utime_t)time(NULL); + + /* Select Jobs -- for counting */ +- Mmsg(query, count_select_job, edit_uint64(now - period, ed1), ++ Mmsg(query, count_select_job, edit_int64(now - period, ed1), + edit_int64(cr.ClientId, ed2)); + Dmsg3(050, "select now=%u period=%u sql=%s\n", (uint32_t)now, + (uint32_t)period, query.c_str()); +@@ -230,7 +230,7 @@ + del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); + + /* Now process same set but making a delete list */ +- Mmsg(query, select_job, edit_uint64(now - period, ed1), ++ Mmsg(query, select_job, edit_int64(now - period, ed1), + edit_int64(cr.ClientId, ed2)); + db_sql_query(ua->db, query.c_str(), file_delete_handler, (void *)&del); + +@@ -318,7 +318,7 @@ + * Select all files that are older than the JobRetention period + * and stuff them into the "DeletionCandidates" table. + */ +- edit_uint64(now - period, ed1); ++ edit_int64(now - period, ed1); + Mmsg(query, insert_delcand, (char)JobType, ed1, + edit_int64(cr.ClientId, ed2)); + if (!db_sql_query(ua->db, query.c_str(), NULL, (void *)NULL)) { +@@ -443,10 +443,10 @@ + edit_int64(mr->MediaId, ed1); + period = mr->VolRetention; + now = (utime_t)time(NULL); +- edit_uint64(now-period, ed2); ++ edit_int64(now-period, ed2); + Mmsg(query, sel_JobMedia, ed1, ed2); +- Dmsg3(250, "Now=%d period=%d now-period=%d\n", (int)now, (int)period, +- (int)(now-period)); ++ Dmsg3(250, "Now=%d period=%d now-period=%s\n", (int)now, (int)period, ++ ed2); + + Dmsg1(050, "Query=%s\n", query.c_str()); + if (!db_sql_query(ua->db, query.c_str(), file_delete_handler, (void *)del)) { diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 63e6b08a53..e8e1d40c82 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -822,6 +822,7 @@ struct JOB_DBR { /* Extra stuff not in DB */ int limit; /* limit records to display */ faddr_t rec_addr; + uint32_t FileIndex; /* added during Verify */ }; /* Job Media information used to create the media records diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index a50fb336aa..82602d5eef 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -97,6 +97,18 @@ int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, * Note in this routine, we do not use Jmsg because it may be * called to get attributes of a non-existent file, which is * "normal" if a new file is found during Verify. + * + * The following is a bit of a kludge: because we always backup a + * directory entry, we can end up with two copies of the directory + * in the backup. One is when we encounter the directory and find + * we cannot recurse into it, and the other is when we find an + * explicit mention of the directory. This can also happen if the + * use includes the directory twice. In this case, Verify + * VolumeToCatalog fails because we have two copies in the catalog, + * and only the first one is marked (twice). So, when calling from Verify, + * jr is not NULL and we know jr->FileIndex is the fileindex + * of the version of the directory/file we actually want and do + * a more explicit SQL search. */ static int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) @@ -115,6 +127,15 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) edit_int64(fdbr->FilenameId, ed2), edit_int64(jr->ClientId,ed3)); + } else if (jr != NULL) { + /* Called from Verify so jr->FileIndex is valid */ + Mmsg(mdb->cmd, +"SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%s AND File.PathId=%s AND " +"File.FilenameId=%s AND FileIndex=%u", + edit_int64(fdbr->JobId, ed1), + edit_int64(fdbr->PathId, ed2), + edit_int64(fdbr->FilenameId,ed3), + jr->FileIndex); } else { Mmsg(mdb->cmd, "SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%s AND File.PathId=%s AND " @@ -123,7 +144,7 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) edit_int64(fdbr->PathId, ed2), edit_int64(fdbr->FilenameId,ed3)); } - Dmsg3(050, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n", + Dmsg3(450, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n", fdbr->JobId, fdbr->FilenameId, fdbr->PathId); Dmsg1(100, "Query=%s\n", mdb->cmd); @@ -134,6 +155,7 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) if (mdb->num_rows > 1) { Mmsg1(mdb->errmsg, _("get_file_record want 1 got rows=%d\n"), mdb->num_rows); + Dmsg1(000, "=== Problem! %s", mdb->errmsg); } if (mdb->num_rows >= 1) { if ((row = sql_fetch_row(mdb)) == NULL) { diff --git a/bacula/src/dird/migrate.c b/bacula/src/dird/migrate.c index b6ea75f76f..bf20d4ba03 100644 --- a/bacula/src/dird/migrate.c +++ b/bacula/src/dird/migrate.c @@ -406,14 +406,7 @@ bool do_migration(JCR *jcr) } migration_cleanup(jcr, jcr->JobStatus); - if (jcr->get_JobType() == JT_MIGRATE && mig_jcr) { - char jobid[50]; - UAContext *ua = new_ua_context(jcr); - edit_uint64(jcr->previous_jr.JobId, jobid); - /* Purge all old file records, but leave Job record */ - purge_files_from_jobs(ua, jobid); - free_ua_context(ua); - } + return true; } @@ -1137,11 +1130,26 @@ void migration_cleanup(JCR *jcr, int TermCode) edit_uint64(mig_jcr->jr.JobId, ec2)); db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL); - /* Now mark the previous job as migrated if it terminated normally */ + /* + * If we terminated a migration normally: + * - mark the previous job as migrated + * - move any Log records to the new JobId + * - Purge the File records from the previous job + */ if (jcr->get_JobType() == JT_MIGRATE && jcr->JobStatus == JS_Terminated) { + char old_jobid[50], new_jobid[50]; Mmsg(query, "UPDATE Job SET Type='%c' WHERE JobId=%s", - (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, ec1)); + (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, new_jobid)); + db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL); + UAContext *ua = new_ua_context(jcr); + /* Move JobLog to new JobId */ + Mmsg(query, "UPDATE Log SET JobId=%s WHERE JobId=%s", + new_jobid, + edit_uint64(jcr->previous_jr.JobId, old_jobid)); db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL); + /* Purge all old file records, but leave Job record */ + purge_files_from_jobs(ua, old_jobid); + free_ua_context(ua); } if (!db_get_job_record(jcr, jcr->db, &jcr->jr)) { diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 84677d62bb..06c8660ee7 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -97,7 +97,7 @@ extern bool send_exclude_list(JCR *jcr); extern bool send_bootstrap_file(JCR *jcr, BSOCK *sock); extern bool send_level_command(JCR *jcr); extern int get_attributes_and_put_in_catalog(JCR *jcr); -extern int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId); +extern void get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId); extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname, char *link, char *attr, int stream); extern void get_level_since_time(JCR *jcr, char *since, int since_len); diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 50828f40bd..3f1e57b521 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -383,12 +383,6 @@ void verify_cleanup(JCR *jcr, int TermCode) TermCode = JS_ErrorTerminated; } - /* If no files were expected, there can be no error */ - if (jcr->get_JobLevel() == L_VERIFY_VOLUME_TO_CATALOG && - jcr->ExpectedFiles == 0) { - TermCode = JS_Terminated; - } - JobId = jcr->jr.JobId; update_job_end(jcr, TermCode); @@ -510,14 +504,13 @@ void verify_cleanup(JCR *jcr, int TermCode) /* * This routine is called only during a Verify */ -int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) +void get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) { BSOCK *fd; int n, len; FILE_DBR fdbr; struct stat statf; /* file stat */ struct stat statc; /* catalog stat */ - int stat = JS_Terminated; char buf[MAXSTRING]; POOLMEM *fname = get_pool_memory(PM_MESSAGE); int do_Digest = CRYPTO_DIGEST_NONE; @@ -545,7 +538,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) char Opts_Digest[MAXSTRING]; /* Verify Opts or MD5/SHA1 digest */ if (job_canceled(jcr)) { - return false; + return; } fname = check_pool_memory_size(fname, fd->msglen); jcr->fname = check_pool_memory_size(jcr->fname, fd->msglen); @@ -554,7 +547,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) fname)) != 3) { Jmsg3(jcr, M_FATAL, 0, _("birdmsglen, fd->msg); - return false; + return; } /* * We read the Options or Signature into fname @@ -582,6 +575,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) Dmsg2(400, "file_index=%d attr=%s\n", file_index, attr); jcr->JobFiles++; jcr->FileIndex = file_index; /* remember attribute file_index */ + jcr->previous_jr.FileIndex = file_index; decode_stat(attr, &statf, &LinkFIf); /* decode file stat packet */ do_Digest = CRYPTO_DIGEST_NONE; jcr->fn_printed = false; @@ -598,7 +592,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) &jcr->previous_jr, &fdbr)) { Jmsg(jcr, M_INFO, 0, _("New file: %s\n"), jcr->fname); Dmsg1(020, _("File not in catalog: %s\n"), jcr->fname); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); continue; } else { /* @@ -624,7 +618,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) Jmsg(jcr, M_INFO, 0, _(" st_ino differ. Cat: %s File: %s\n"), edit_uint64((uint64_t)statc.st_ino, ed1), edit_uint64((uint64_t)statf.st_ino, ed2)); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } break; case 'p': /* permissions bits */ @@ -632,7 +626,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) prt_fname(jcr); Jmsg(jcr, M_INFO, 0, _(" st_mode differ. Cat: %x File: %x\n"), (uint32_t)statc.st_mode, (uint32_t)statf.st_mode); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } break; case 'n': /* number of links */ @@ -640,7 +634,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) prt_fname(jcr); Jmsg(jcr, M_INFO, 0, _(" st_nlink differ. Cat: %d File: %d\n"), (uint32_t)statc.st_nlink, (uint32_t)statf.st_nlink); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } break; case 'u': /* user id */ @@ -648,7 +642,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) prt_fname(jcr); Jmsg(jcr, M_INFO, 0, _(" st_uid differ. Cat: %u File: %u\n"), (uint32_t)statc.st_uid, (uint32_t)statf.st_uid); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } break; case 'g': /* group id */ @@ -656,7 +650,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) prt_fname(jcr); Jmsg(jcr, M_INFO, 0, _(" st_gid differ. Cat: %u File: %u\n"), (uint32_t)statc.st_gid, (uint32_t)statf.st_gid); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } break; case 's': /* size */ @@ -665,28 +659,28 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) Jmsg(jcr, M_INFO, 0, _(" st_size differ. Cat: %s File: %s\n"), edit_uint64((uint64_t)statc.st_size, ed1), edit_uint64((uint64_t)statf.st_size, ed2)); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } break; case 'a': /* access time */ if (statc.st_atime != statf.st_atime) { prt_fname(jcr); Jmsg(jcr, M_INFO, 0, _(" st_atime differs\n")); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } break; case 'm': if (statc.st_mtime != statf.st_mtime) { prt_fname(jcr); Jmsg(jcr, M_INFO, 0, _(" st_mtime differs\n")); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } break; case 'c': /* ctime */ if (statc.st_ctime != statf.st_ctime) { prt_fname(jcr); Jmsg(jcr, M_INFO, 0, _(" st_ctime differs\n")); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } break; case 'd': /* file size decrease */ @@ -695,7 +689,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) Jmsg(jcr, M_INFO, 0, _(" st_size decrease. Cat: %s File: %s\n"), edit_uint64((uint64_t)statc.st_size, ed1), edit_uint64((uint64_t)statf.st_size, ed2)); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } break; case '5': /* compare MD5 */ @@ -724,7 +718,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) if (jcr->FileIndex != (uint32_t)file_index) { Jmsg2(jcr, M_FATAL, 0, _("MD5/SHA1 index %d not same as attributes %d\n"), file_index, jcr->FileIndex); - return false; + return; } if (do_Digest != CRYPTO_DIGEST_NONE) { db_escape_string(jcr, jcr->db, buf, Opts_Digest, strlen(Opts_Digest)); @@ -732,7 +726,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) prt_fname(jcr); Jmsg(jcr, M_INFO, 0, _(" %s differs. File=%s Cat=%s\n"), stream_to_ascii(stream), buf, fdbr.Digest); - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } do_Digest = CRYPTO_DIGEST_NONE; } @@ -743,7 +737,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) berrno be; Jmsg2(jcr, M_FATAL, 0, _("bdirddb, buf, missing_handler, (void *)jcr); if (jcr->fn_printed) { - stat = JS_Differences; + set_jcr_job_status(jcr, JS_Differences); } free_pool_memory(fname); - if (!job_canceled(jcr)) { - jcr->JobStatus = stat; - } - return stat == JS_Terminated; } /* @@ -782,8 +772,8 @@ static int missing_handler(void *ctx, int num_fields, char **row) return 1; } if (!jcr->fn_printed) { - Qmsg(jcr, M_INFO, 0, _("\nThe following files are in the Catalog but not on %s:\n"), - jcr->get_JobLevel() == L_VERIFY_VOLUME_TO_CATALOG ? "the Volume(s)" : "disk"); + Qmsg(jcr, M_WARNING, 0, _("The following files are in the Catalog but not on %s:\n"), + jcr->get_JobLevel() == L_VERIFY_VOLUME_TO_CATALOG ? "the Volume(s)" : "disk"); jcr->fn_printed = true; } Qmsg(jcr, M_INFO, 0, " %s%s\n", row[0]?row[0]:"", row[1]?row[1]:""); diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index e7acb12a15..4b8b9d110a 100644 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -714,10 +714,38 @@ JCR *get_jcr_by_full_name(char *Job) return jcr; } +/* + * Priority runs from 0 (lowest) to 10 (highest) + */ +static int get_status_priority(int JobStatus) +{ + int priority = 0; + switch (JobStatus) { + case JS_ErrorTerminated: + case JS_FatalError: + priority = 10; + break; + case JS_Canceled: + priority = 9; + break; + case JS_Error: + priority = 8; + break; + case JS_Differences: + priority = 7; + break; + } + return priority; +} + void set_jcr_job_status(JCR *jcr, int JobStatus) { bool set_waittime = false; int oldJobStatus = jcr->JobStatus; + int priority, old_priority; + + priority = get_status_priority(JobStatus); + old_priority = get_status_priority(oldJobStatus); Dmsg2(800, "set_jcr_job_status(%s, %c)\n", jcr->Job, JobStatus); /* if wait state is new, we keep current time for watchdog MaxWaitTime */ @@ -742,26 +770,15 @@ void set_jcr_job_status(JCR *jcr, int JobStatus) */ Dmsg3(300, "jid=%u OnEntry JobStatus=%c set=%c\n", (uint32_t)jcr->JobId, jcr->JobStatus, JobStatus); - switch (jcr->JobStatus) { - case JS_ErrorTerminated: - case JS_FatalError: - case JS_Canceled: - break; - case JS_Error: - case JS_Differences: - switch (JobStatus) { - case JS_ErrorTerminated: - case JS_FatalError: - case JS_Canceled: - /* Override more minor status */ - jcr->JobStatus = JobStatus; - break; - default: - break; - } + if (priority >= old_priority) { + jcr->JobStatus = JobStatus; /* replace with new priority */ + } /* - * For a set of Wait situation, keep old time. + * If we were previously waiting and are not any more + * we want to update the wait_time variable, which is + * the start of waiting. */ + switch (oldJobStatus) { case JS_WaitFD: case JS_WaitSD: case JS_WaitMedia: @@ -773,9 +790,7 @@ void set_jcr_job_status(JCR *jcr, int JobStatus) case JS_WaitPriority: set_waittime = false; /* keep old time */ default: - jcr->JobStatus = JobStatus; if (set_waittime) { - /* set it before JobStatus */ Dmsg0(800, "Setting wait_time\n"); jcr->wait_time = time(NULL); } diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 156b0fa834..a173b8eb47 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -422,7 +422,7 @@ bool write_block_to_dev(DCR *dcr) if (dev->at_weot()) { Dmsg0(100, "return write_block_to_dev with ST_WEOT\n"); dev->dev_errno = ENOSPC; - Jmsg(jcr, M_FATAL, 0, _("Cannot write block. Device at EOM.\n")); + Jmsg0(jcr, M_FATAL, 0, _("Cannot write block. Device at EOM.\n")); return false; } if (!dev->can_append()) { diff --git a/bacula/src/stored/fd_cmds.c b/bacula/src/stored/fd_cmds.c index 7cd070e6c5..558df83f3a 100644 --- a/bacula/src/stored/fd_cmds.c +++ b/bacula/src/stored/fd_cmds.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2007 Free Software Foundation Europe e.V. + Copyright (C) 2000-2008 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. @@ -212,7 +212,6 @@ static bool append_end_session(JCR *jcr) fd->fsend(NOT_opened); return false; } - set_jcr_job_status(jcr, JS_Terminated); return fd->fsend(OK_end); } diff --git a/bacula/src/stored/spool.c b/bacula/src/stored/spool.c index 01f6e2323b..bbd2f8601f 100644 --- a/bacula/src/stored/spool.c +++ b/bacula/src/stored/spool.c @@ -296,6 +296,8 @@ static bool despool_data(DCR *dcr, bool commit) if (!ok) { Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"), dcr->dev->print_name(), dcr->dev->bstrerror()); + Dmsg2(000, "Fatal append error on device %s: ERR=%s\n", + dcr->dev->print_name(), dcr->dev->bstrerror()); } Dmsg3(800, "Write block ok=%d FI=%d LI=%d\n", ok, block->FirstIndex, block->LastIndex); } diff --git a/bacula/src/stored/vol_mgr.c b/bacula/src/stored/vol_mgr.c index a3c7dc15b0..0d5584d8c1 100644 --- a/bacula/src/stored/vol_mgr.c +++ b/bacula/src/stored/vol_mgr.c @@ -158,9 +158,9 @@ void add_read_volume(JCR *jcr, const char *VolumeName) vol = (VOLRES *)read_vol_list->binary_insert(nvol, read_compare); if (vol != nvol) { free_vol_item(nvol); - Dmsg2(1, "read_vol=%s JobId=%d already in list.\n", VolumeName, jcr->JobId); + Dmsg2(dbglvl, "read_vol=%s JobId=%d already in list.\n", VolumeName, jcr->JobId); } else { - Dmsg2(1, "add read_vol=%s JobId=%d\n", VolumeName, jcr->JobId); + Dmsg2(dbglvl, "add read_vol=%s JobId=%d\n", VolumeName, jcr->JobId); } unlock_read_volumes(); } @@ -176,7 +176,9 @@ void remove_read_volume(JCR *jcr, const char *VolumeName) vol.set_jobid(jcr->JobId); fvol = (VOLRES *)read_vol_list->binary_search(&vol, read_compare); free(vol.vol_name); - Dmsg3(1, "remove_read_vol=%s JobId=%d found=%d\n", VolumeName, jcr->JobId, fvol!=NULL); + if (fvol) { + Dmsg3(dbglvl, "remove_read_vol=%s JobId=%d found=%d\n", VolumeName, jcr->JobId, fvol!=NULL); + } debug_list_volumes("remove_read_volume"); if (fvol) { read_vol_list->remove(fvol); diff --git a/bacula/technotes-2.5 b/bacula/technotes-2.5 index 93cd89bd92..a053d8de56 100644 --- a/bacula/technotes-2.5 +++ b/bacula/technotes-2.5 @@ -11,6 +11,18 @@ mixed priorities General: 28Oct08 +kes Fix bug #1046 VolumeToCatalog incorrectly reports mounted + filesystems as missing on the Volume. +kes Rewrite the set_jcr_job_status() code to include job status + priorities so that more important status changes occur but + lower priority status changes will not overwrite something + more serious. This could possibly cause reporting incorrect status + reporting in some cases. More testing is needed to ensure + I have the right priorities. This vastly simplifies the previous + contorted logic. + Verify Diff status should now be correctly reported, whereas it + was previously lost. +kes Reduce some debug output. kes Apply Joao's patch to SQLite tables to make chars work. 27Oct08 ebl Fix #1175 About update slots that don't reset InChanger flag when -- 2.39.2