From bd5b4259358d810021114c79d9248ef57e52325c Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 11 Nov 2002 11:07:03 +0000 Subject: [PATCH] Fix VolJobs + enhance dbcheck git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@190 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 5 +- bacula/src/stored/acquire.c | 2 + bacula/src/stored/mount.c | 4 +- bacula/src/tools/dbcheck.c | 171 ++++++++++++++++++++++++++++++++---- bacula/src/version.h | 4 +- 5 files changed, 162 insertions(+), 24 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 4d40527a8e..94ce1d7c13 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -15,6 +15,9 @@ Test: - blocksize recognition code. For 1.27 release: +- Implement VolumeUsePeriod (maximum duration/period) a volume can be used). + Possibly VolumeUseTimes (VolumeMaxJobs) This permits a volume to be + recycled even if it is not full. - Implement FileOptions. - Need return status on read_cb() from read_records(). Need multiple records -- one per Job, maybe a JCR or some other structure with @@ -68,6 +71,7 @@ After 1.27 - Fix db_get_fileset in cats/sql_get.c for multiple records. - Fix start/end blocks for File devices - Add new code to scheduler.c and run_conf.c + schedule options (1-sat, 2-sat, ...). - Fix catalog filename truncation in sql_get and sql_create. Use only a single filename split routine. - Add command to reset VolFiles to a larger value (don't allow @@ -567,4 +571,3 @@ Done: (see kernsdone for more) - that Bacula won't write on tape where tape/catalog files differ. - Document how to recycle a tape in 7 days even if the backup takes a long time. - Document tape cycling - diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 6cf7940624..2c799d64e8 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -224,6 +224,7 @@ int release_device(JCR *jcr, DEVICE *dev) Dmsg0(100, "dir_create_jobmedia_record. Release\n"); dir_create_jobmedia_record(jcr); dev->VolCatInfo.VolCatFiles++; /* increment number of files */ + dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */ /* Note! do volume update before close, which zaps VolCatInfo */ Dmsg0(100, "dir_update_vol_info. Release\n"); dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* send Volume info to Director */ @@ -238,6 +239,7 @@ int release_device(JCR *jcr, DEVICE *dev) Dmsg0(100, "dir_create_jobmedia_record. Release\n"); dir_create_jobmedia_record(jcr); Dmsg0(100, "dir_update_vol_info. Release\n"); + dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */ dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* send Volume info to Director */ } } else { diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 4594c72d12..e32579ad0c 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -261,6 +261,7 @@ mount_error: } /* Recreate a correct volume label and return it in the block */ write_volume_label_to_block(jcr, dev, block); + /* Set or reset Volume statistics */ dev->VolCatInfo.VolCatJobs = 1; dev->VolCatInfo.VolCatFiles = 1; dev->VolCatInfo.VolCatErrors = 0; @@ -323,9 +324,8 @@ The number of files mismatch! Volume=%d Catalog=%d\n"), goto mount_next_vol; } } - /* Update Volume Info -- will be written at end of Job */ dev->VolCatInfo.VolCatMounts++; /* Update mounts */ - dev->VolCatInfo.VolCatJobs++; + dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* Return an empty block */ empty_block(block); /* we used it for reading so set for write */ } diff --git a/bacula/src/tools/dbcheck.c b/bacula/src/tools/dbcheck.c index eafcc748bc..2b0754b573 100644 --- a/bacula/src/tools/dbcheck.c +++ b/bacula/src/tools/dbcheck.c @@ -51,7 +51,7 @@ typedef struct s_name_ctx { /* Global variables */ static int fix = FALSE; -static int interactive = FALSE; +static int batch = FALSE; static int verbose = FALSE; static B_DB *db; static ID_LIST id_list; @@ -66,10 +66,14 @@ static int delete_id_list(char *query, ID_LIST *id_list); static int make_name_list(char *query, NAME_LIST *name_list); static void print_name_list(NAME_LIST *name_list); static void free_name_list(NAME_LIST *name_list); +static char *get_cmd(char *prompt); static void eliminate_duplicate_filenames(); static void eliminate_duplicate_paths(); static void eliminate_orphaned_jobmedia_records(); static void eliminate_orphaned_file_records(); +static void eliminate_orphaned_path_records(); +static void eliminate_orphaned_filename_records(); +static void do_interactive_mode(); #ifdef xxxx static void prtit(void *ctx, char *msg) @@ -82,9 +86,10 @@ static void usage() { fprintf(stderr, "Usage: dbcheck [-d debug_level] \n" +" -b batch mode\n" " -dnn set debug level to nn\n" " -f fix inconsistencies\n" -" -i interactive mode\n" +" -v verbose\n" " -? print this message\n\n"); exit(1); } @@ -101,8 +106,12 @@ int main (int argc, char *argv[]) memset(&name_list, 0, sizeof(name_list)); - while ((ch = getopt(argc, argv, "d:fi?")) != -1) { + while ((ch = getopt(argc, argv, "d:fiv?")) != -1) { switch (ch) { + case 'b': /* batch */ + batch = TRUE; + break; + case 'd': /* debug level */ debug_level = atoi(optarg); if (debug_level <= 0) @@ -113,8 +122,8 @@ int main (int argc, char *argv[]) fix = TRUE; break; - case 'i': /* interactive */ - interactive = TRUE; + case 'v': + verbose++; break; case '?': @@ -160,20 +169,89 @@ int main (int argc, char *argv[]) Emsg1(M_FATAL, 0, "%s", db_strerror(db)); } - eliminate_duplicate_filenames(); - - eliminate_duplicate_paths(); - - eliminate_orphaned_jobmedia_records(); - - eliminate_orphaned_file_records(); + if (batch) { + eliminate_duplicate_filenames(); + eliminate_duplicate_paths(); + eliminate_orphaned_jobmedia_records(); + eliminate_orphaned_file_records(); + eliminate_orphaned_path_records(); + eliminate_orphaned_filename_records(); + } else { + do_interactive_mode(); + } db_close_database(db); - close_msg(NULL); term_msg(); return 0; } + +static void do_interactive_mode() +{ + int quit = FALSE; + char *cmd; + + printf("Hello, this is the database check/correct program.\n\ +Please select the fuction you want to perform.\n"); + + while (!quit) { + printf(_("\n\ + 1) Toggle modify database flag\n\ + 2) Toggle verbose flag\n\ + 3) Eliminate duplicate Filename records\n\ + 4) Eliminate duplicate Path records\n\ + 5) Eliminate orphaned Jobmedia records\n\ + 6) Eliminate orphaned File records\n\ + 7) Eliminate orphaned Path records\n\ + 8) Eliminate orphaned Filename records\n\ + 9) All (3-8)\n\ +10) Quit\n\n")); + + cmd = get_cmd(_("Select function number: ")); + if (cmd) { + int item = atoi(cmd); + switch (item) { + case 1: + fix = !fix; + printf(_("Database will %sbe modified.\n"), fix?"":_("not ")); + break; + case 2: + verbose = verbose?0:1; + printf(_("Verbose is %s\n"), verbose?_("On"):_("Off")); + break; + case 3: + eliminate_duplicate_filenames(); + break; + case 4: + eliminate_duplicate_paths(); + break; + case 5: + eliminate_orphaned_jobmedia_records(); + break; + case 6: + eliminate_orphaned_file_records(); + break; + case 7: + eliminate_orphaned_path_records(); + break; + case 8: + eliminate_orphaned_filename_records(); + break; + case 9: + eliminate_duplicate_filenames(); + eliminate_duplicate_paths(); + eliminate_orphaned_jobmedia_records(); + eliminate_orphaned_file_records(); + eliminate_orphaned_path_records(); + eliminate_orphaned_filename_records(); + break; + case 10: + quit = 1; + break; + } + } + } +} /* * Called here with each id to be added to the list @@ -223,6 +301,9 @@ static int delete_id_list(char *query, ID_LIST *id_list) for (i=0; i < id_list->num_ids; i++) { sprintf(buf, query, id_list->Id[i]); + if (verbose) { + printf("Deleting: %s\n", buf); + } db_sql_query(db, buf, NULL, NULL); } return 1; @@ -302,8 +383,8 @@ static void eliminate_duplicate_filenames() printf("Checking for duplicate Filename entries.\n"); /* Make list of duplicated names */ - query = "SELECT Name FROM Filename " - "GROUP BY Name HAVING COUNT(FilenameId) > 1"; + query = "SELECT Name FROM (SELECT COUNT(Name) as Count,Name from Filename " + "GROUP BY Name) WHERE Count > 1"; if (!make_name_list(query, &name_list)) { exit(1); } @@ -341,8 +422,8 @@ static void eliminate_duplicate_paths() printf("Checking for duplicate Path entries.\n"); /* Make list of duplicated names */ - query = "SELECT Path FROM Path " - "GROUP BY Path HAVING COUNT(PathId) > 1"; + query = "SELECT Path FROM (SELECT COUNT(Path) AS Count,Path FROM Path " + "GROUP BY Path) WHERE Count > 1"; if (!make_name_list(query, &name_list)) { exit(1); } @@ -395,7 +476,7 @@ static void eliminate_orphaned_file_records() { char *query; - printf("Checking for orphaned File entries.\n"); + printf("Checking for orphaned File entries. This takes some time!\n"); query = "SELECT FileId,Job FROM File LEFT OUTER JOIN Job ON" " (Job.JobId=File.JobId) GROUP BY FileId HAVING Job IS NULL"; if (!make_id_list(query, &id_list)) { @@ -405,6 +486,58 @@ static void eliminate_orphaned_file_records() if (fix && id_list.num_ids > 0) { printf("Deleting %d orphaned File records.\n", id_list.num_ids); - delete_id_list("DELETE FROM File WHERE FileIdId=%u", &id_list); + delete_id_list("DELETE FROM File WHERE FileId=%u", &id_list); } } + +static void eliminate_orphaned_path_records() +{ + char *query; + + printf("Checking for orphaned Path entries. This may take some time!\n"); + query = "SELECT Path.PathId,File.JobId FROM Path LEFT OUTER JOIN File ON" + " (File.PathId=Path.PathId) GROUP BY Path.PathId HAVING File.JobId IS NULL"; + if (!make_id_list(query, &id_list)) { + exit(1); + } + printf("Found %d orphaned Path records.\n", id_list.num_ids); + + if (fix && id_list.num_ids > 0) { + printf("Deleting %d orphaned Path records.\n", id_list.num_ids); + delete_id_list("DELETE FROM Path WHERE PathId=%u", &id_list); + } +} + +static void eliminate_orphaned_filename_records() +{ + char *query; + + printf("Checking for orphaned Filename entries. This may take some time!\n"); + query = "SELECT Filename.FilenameId,File.JobId FROM Filename " + "LEFT OUTER JOIN File ON (File.FilenameId=Filename.FilenameId) " + "GROUP BY Filename.FilenameId HAVING File.JobId IS NULL"; + if (!make_id_list(query, &id_list)) { + exit(1); + } + printf("Found %d orphaned Filename records.\n", id_list.num_ids); + + if (fix && id_list.num_ids > 0) { + printf("Deleting %d orphaned Filename records.\n", id_list.num_ids); + delete_id_list("DELETE FROM Filename WHERE FilenameId=%u", &id_list); + } +} + +/* + * Gen next input command from the terminal + */ +static char *get_cmd(char *prompt) +{ + static char cmd[1000]; + + printf("%s", prompt); + if (fgets(cmd, sizeof(cmd), stdin) == NULL) + return NULL; + printf("\n"); + strip_trailing_junk(cmd); + return cmd; +} diff --git a/bacula/src/version.h b/bacula/src/version.h index 1b1094e6d0..ba9b1abcff 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #define VERSION "1.27" #define VSTRING "1" -#define DATE "08 November 2002" -#define LSMDATE "08Nov02" +#define DATE "10 November 2002" +#define LSMDATE "10Nov02" /* Debug flags */ #define DEBUG 1 -- 2.39.5