]> git.sur5r.net Git - bacula/bacula/commitdiff
New tools directory -- kes12Aug02
authorKern Sibbald <kern@sibbald.com>
Mon, 12 Aug 2002 21:07:38 +0000 (21:07 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 12 Aug 2002 21:07:38 +0000 (21:07 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@90 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/Makefile.in
bacula/autoconf/Make.common.in
bacula/autoconf/configure.in
bacula/configure
bacula/src/cats/Makefile.in
bacula/src/dird/Makefile.in
bacula/src/lib/Makefile.in
bacula/src/stored/Makefile.in
bacula/src/tools/dbcheck.c [new file with mode: 0644]

index 3f17dcc86d13de8d26c2d09f61f718780553d4da..6c3a64a7ac276ba8ef607b631df4a68ffd0bff47 100755 (executable)
@@ -17,7 +17,7 @@ dummy:
 
 subdirs = src doc src/lib src/findlib src/cats \
          @READLINE_SRC@ src/console src/dird src/filed \
-         src/stored @GNOME_DIR@
+         src/stored @GNOME_DIR@ src/tools
 
 FDsubdirs = src/lib src/findlib src/filed
 
index e2d86db61d37bb0f8da617fc7ced3571569d9814..c4967df87c3000e2001fb11d34848ccf42e55a43 100644 (file)
@@ -61,6 +61,7 @@ LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
 DINCLUDE = @DINCLUDE@
 DLIB = @DLIB@
+DB_LIBS = @DB_LIBS@
 
 # X Include directory
 #XINC = @X_CFLAGS@ @XPM_CFLAGS@
index d75ba911eb0c02dd4ebeb479dbaed088fe27bc12..00d71c2bfe9ca99062651e7772a83c5ce6ba85c2 100644 (file)
@@ -992,7 +992,7 @@ AC_DEFINE(FDLIBS)
 
 CFLAGS=${CFLAGS--O}
 LDFLAGS=${LDFLAGS--O}
-LIBS="${LIBS} ${SQL_LFLAGS}"
+DB_LIBS="${SQL_LFLAGS}"
 
 CPPFLAGS="$CPPFLAGS"
 AC_SUBST(DEBUG)
@@ -1003,6 +1003,7 @@ AC_SUBST(LDFLAGS)
 AC_SUBST(X_CFLAGS)
 AC_SUBST(LIBS)
 AC_SUBST(DLIB)
+AC_SUBST(DB_LIBS)
 AC_SUBST(X_LIBS)
 AC_SUBST(X_EXTRA_LIBS)
 
@@ -1212,6 +1213,7 @@ AC_OUTPUT([autoconf/Make.common \
           src/cats/make_bdb_tables \
           src/cats/drop_bdb_tables \
           src/findlib/Makefile \
+          src/tools/Makefile \
           $PFILES ],  
          [(echo "Doing make of dependencies"; make depend;) ]
 )
@@ -1250,6 +1252,7 @@ Configuration on `date`:
   Libraries:                 ${LIBS}
   Database found:            ${have_db}
   Database type:             ${db_name}
+  Database lib:              ${DB_LIBS}
 
   Job Output Email:          ${job_email}
   Traceback Email:           ${dump_email}
index 9a66191f0d589ce66927ec16c5a489252e410406..3728d59fd0495e1cf3660070c37343de996f455a 100755 (executable)
@@ -8861,7 +8861,7 @@ EOF
 
 CFLAGS=${CFLAGS--O}
 LDFLAGS=${LDFLAGS--O}
-LIBS="${LIBS} ${SQL_LFLAGS}"
+DB_LIBS="${SQL_LFLAGS}"
 
 CPPFLAGS="$CPPFLAGS"
 
@@ -8875,6 +8875,7 @@ CPPFLAGS="$CPPFLAGS"
 
 
 
+
 OBJLIST=
 
 
@@ -9186,6 +9187,7 @@ trap 'rm -fr `echo "autoconf/Make.common \
           src/cats/make_bdb_tables \
           src/cats/drop_bdb_tables \
           src/findlib/Makefile \
+          src/tools/Makefile \
           $PFILES  src/config.h:autoconf/config.h.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
 EOF
 cat >> $CONFIG_STATUS <<EOF
@@ -9341,6 +9343,7 @@ s%@FDLIBS@%$FDLIBS%g
 s%@DEBUG@%$DEBUG%g
 s%@DINCLUDE@%$DINCLUDE%g
 s%@DLIB@%$DLIB%g
+s%@DB_LIBS@%$DB_LIBS%g
 s%@OBJLIST@%$OBJLIST%g
 s%@hostname@%$hostname%g
 s%@TAPEDRIVE@%$TAPEDRIVE%g
@@ -9432,6 +9435,7 @@ CONFIG_FILES=\${CONFIG_FILES-"autoconf/Make.common \
           src/cats/make_bdb_tables \
           src/cats/drop_bdb_tables \
           src/findlib/Makefile \
+          src/tools/Makefile \
           $PFILES "}
 EOF
 cat >> $CONFIG_STATUS <<\EOF
@@ -9646,6 +9650,7 @@ Configuration on `date`:
   Libraries:                 ${LIBS}
   Database found:            ${have_db}
   Database type:             ${db_name}
+  Database lib:              ${DB_LIBS}
 
   Job Output Email:          ${job_email}
   Traceback Email:           ${dump_email}
index 3be938d7cf314713b7f18b3e10aaf5fa8ef89811..19bf536120f6bc733b288380c9be3b23fe0c2e2b 100644 (file)
@@ -48,7 +48,7 @@ libsql.a: $(LIBOBJS)
        $(RANLIB) $@
 
 cats: $(SVROBJS) ../findlib/libfind.a
-       $(CC) $(LDFLAGS) -L../findlib -L../lib -o $@ $(SVROBJS) $(LIBS) $(DLIB) -lfind -lbac
+       $(CC) $(LDFLAGS) -L../findlib -L../lib -o $@ $(SVROBJS) $(LIBS) $(DB_LIBS) -lfind -lbac
 
 Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
        cd $(topdir) \
index 8dcae47617d0a910aa6e1931c859b04641668851..f1fbcf3597356f18a62f7e5654b009d011b6b0c4 100644 (file)
@@ -66,7 +66,7 @@ all: Makefile bacula-dir
 
 bacula-dir:  $(SVROBJS) ../lib/libbac.a ../cats/libsql.a
        $(CXX) $(LDFLAGS) -L../lib -L../cats -o $@ $(SVROBJS) \
-             -lsql -lbac -lm $(LIBS) $(DLIB)
+             -lsql -lbac -lm $(LIBS) $(DLIB) $(DB_LIBS)
 
 Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
        cd $(topdir) \
index 62c6f4eec8da1ac9dd03743df7c7e236511a45e4..8abc0dcf98f0aafedc824c8ffc17b0b9bce62dae 100644 (file)
@@ -83,7 +83,7 @@ EXTRAOBJS = @OBJLIST@
        $(XDVI) -s 0 $<
 
 #-------------------------------------------------------------------------
-all: Makefile libbac.a smtp
+all: Makefile libbac.a
        @echo "==== Make of lib is good ===="
        @echo " "
 
@@ -96,9 +96,6 @@ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
        cd $(topdir) \
          && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
 
-smtp:  smtp.o
-       $(CXX) $(LDFLAGS) -L. -o $@ smtp.o $(LIBS) $(DLIB) -lbac -lm
-
 rwlock_test:  rwlock.o
        rm -f rwlock.o
        $(CXX) -DTEST_RWLOCK $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(GMP_INC) $(CFLAGS) rwlock.c
@@ -107,14 +104,12 @@ rwlock_test:  rwlock.o
        $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(GMP_INC) $(CFLAGS) rwlock.c
         
 install:
-       $(INSTALL_PROGRAM) smtp $(DESTDIR)/$(sbindir)/smtp
 
 uninstall:
-       (cd $(DESTDIR)$(sbindir); $(RMF) smtp)
 
 clean:
        $(RMF) *.a core a.out *.o *.bak *.tex *.pdf *~ *.intpro *.extpro 1 2 3
-       $(RMF) smtp rwlock_test
+       $(RMF) rwlock_test
 
 realclean: clean
        $(RMF) tags
index 6dac0c8b7b7cdf0cab984c12e3d3affd12a04ce4..cdef7ac8bee80e2fe5865bf9ed7d34d20f2e7d40 100644 (file)
@@ -84,7 +84,7 @@ bextract: ../findlib/libfind.a $(BEXTOBJS) ../lib/libbac.a
        $(CXX) $(LDFLAGS) -L../lib -L../findlib -o $@ $(BEXTOBJS) $(LIBS) $(DLIB) $(FDLIBS) -lbac -lfind -lm
 
 bscan: ../findlib/libfind.a $(SCNOBJS) ../cats/libsql.a
-       $(CXX) $(LDFLAGS) -L../lib -L../cats -L../findlib -o $@ $(SCNOBJS) -lsql $(LIBS) $(DLIB) $(FDLIBS) -lbac -lfind -lm
+       $(CXX) $(LDFLAGS) -L../lib -L../cats -L../findlib -o $@ $(SCNOBJS) -lsql $(LIBS) $(DB_LIBS) $(FDLIBS) -lbac -lfind -lm
 
 
 
diff --git a/bacula/src/tools/dbcheck.c b/bacula/src/tools/dbcheck.c
new file mode 100644 (file)
index 0000000..5c8496a
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ *
+ *  Program to check a Bacula database for consistency and to
+ *   make repairs 
+ *
+ *   Kern E. Sibbald, August 2002
+ *
+ *   Version $Id$
+ *
+ */
+/*
+   Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+
+   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.
+
+   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.
+
+ */
+
+#include "bacula.h"
+#include "cats/cats.h"
+
+typedef struct s_id_ctx {
+   uint32_t *Id;                     /* ids to be modified */
+   int num_ids;                      /* ids stored */
+   int max_ids;                      /* size of array */
+   int num_del;                      /* number deleted */
+   int tot_ids;                      /* total to process */
+} ID_LIST;
+
+typedef struct s_name_ctx {
+   char **name;                      /* list of names */
+   int num_ids;                      /* ids stored */
+   int max_ids;                      /* size of array */
+   int num_del;                      /* number deleted */
+   int tot_ids;                      /* total to process */
+} NAME_LIST;
+
+
+
+/* Global variables */
+static int fix = FALSE;
+static int interactive = FALSE;
+static int verbose = FALSE;
+static B_DB *db;
+static ID_LIST id_list;
+static NAME_LIST name_list;
+static char buf[2000];
+
+#define MAX_ID_LIST_LEN 1000000
+
+/* Forward referenced functions */
+static int make_id_list(char *query, ID_LIST *id_list);
+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 void eliminate_duplicate_filenames();
+static void eliminate_duplicate_paths();
+static void eliminate_orphaned_jobmedia_records();
+static void eliminate_orphaned_file_records();
+
+#ifdef xxxx
+static void prtit(void *ctx, char *msg)
+{
+   printf("%s", msg);
+}
+#endif
+
+static void usage()
+{
+   fprintf(stderr,
+"Usage: dbcheck [-d debug_level] <working-directory> <bacula-databse> <user> <password>\n"
+"       -dnn            set debug level to nn\n"
+"       -f              fix inconsistencies\n"
+"       -i              interactive mode\n"
+"       -?              print this message\n\n");
+   exit(1);
+}
+
+int main (int argc, char *argv[])
+{
+   int ch;
+   char *user, *password, *db_name;
+
+   my_name_is(argc, argv, "dbcheck");
+   init_msg(NULL, NULL);             /* setup message handler */
+
+   memset(&id_list, 0, sizeof(id_list));
+   memset(&name_list, 0, sizeof(name_list));
+
+
+   while ((ch = getopt(argc, argv, "d:fi?")) != -1) {
+      switch (ch) {
+         case 'd':                    /* debug level */
+           debug_level = atoi(optarg);
+           if (debug_level <= 0)
+              debug_level = 1; 
+           break;
+
+         case 'f':                    /* fix inconsistencies */
+           fix = TRUE;
+           break;
+
+         case 'i':                    /* interactive */
+           interactive = TRUE;
+           break;
+
+         case '?':
+        default:
+           usage();
+
+      }  
+   }
+   argc -= optind;
+   argv += optind;
+
+   if (argc > 4) {
+      Pmsg0(0, _("Wrong number of arguments.\n"));
+      usage();
+   }
+
+   if (argc < 1) {
+      Pmsg0(0, _("Working directory not supplied.\n"));
+      usage();
+   }
+
+   /* This is needed by SQLite to find the db */
+   working_directory = argv[0];
+   db_name = "bacula";
+   user = db_name;
+   password = "";
+
+   if (argc == 2) {
+      db_name = argv[1];
+      user = db_name;
+   } else if (argc == 3) {
+      db_name = argv[1];
+      user = argv[2];
+   } else if (argc == 4) {
+      db_name = argv[1];
+      user = argv[2];
+      password = argv[3];
+   }
+
+   /* Open database */
+   db = db_init_database(db_name, user, password);
+   if (!db_open_database(db)) {
+      Emsg1(M_FATAL, 0, "%s", db_strerror(db));
+   }
+
+   eliminate_duplicate_filenames();
+
+   eliminate_duplicate_paths();
+
+   eliminate_orphaned_jobmedia_records();
+
+   eliminate_orphaned_file_records();
+
+   db_close_database(db);
+
+   close_msg(NULL);
+   term_msg();
+   return 0;
+}
+  
+/*
+ * Called here with each id to be added to the list
+ */
+static int id_list_handler(void *ctx, int num_fields, char **row)
+{
+   ID_LIST *lst = (ID_LIST *)ctx;
+
+   if (lst->num_ids == MAX_ID_LIST_LEN) {  
+      return 1;
+   }
+   if (lst->num_ids == lst->max_ids) {
+      if (lst->max_ids == 0) {
+        lst->max_ids = 1000;
+        lst->Id = (uint32_t *)malloc(sizeof(uint32_t) * lst->max_ids);
+      } else {
+        lst->max_ids = (lst->max_ids * 3) / 2;
+        lst->Id = (uint32_t *)brealloc(lst->Id, sizeof(uint32_t) * lst->max_ids);
+      }
+   }
+   lst->Id[lst->num_ids++] = (uint32_t)strtod(row[0], NULL);
+   return 0;
+}
+
+/*
+ * Construct record id list
+ */
+static int make_id_list(char *query, ID_LIST *id_list)
+{
+   id_list->num_ids = 0;
+   id_list->num_del = 0;
+   id_list->tot_ids = 0;
+
+   if (!db_sql_query(db, query, id_list_handler, (void *)id_list)) {
+      printf("%s", db_strerror(db));
+      return 0;
+   }
+   return 1;
+}
+
+/*
+ * Delete all entries in the list 
+ */
+static int delete_id_list(char *query, ID_LIST *id_list)
+{ 
+   int i;
+
+   for (i=0; i < id_list->num_ids; i++) {
+      sprintf(buf, query, id_list->Id[i]);
+      db_sql_query(db, buf, NULL, NULL);
+   }
+   return 1;
+}
+
+/*
+ * Called here with each name to be added to the list
+ */
+static int 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 **)malloc(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);
+      }
+   }
+   name->name[name->num_ids++] = bstrdup(row[0]);
+   return 0;
+}
+
+
+/*
+ * Construct name list
+ */
+static int make_name_list(char *query, NAME_LIST *name_list)
+{
+   name_list->num_ids = 0;
+   name_list->num_del = 0;
+   name_list->tot_ids = 0;
+
+   if (!db_sql_query(db, query, name_list_handler, (void *)name_list)) {
+      printf("%s", db_strerror(db));
+      return 0;
+   }
+   return 1;
+}
+
+
+/*
+ * Print names in the list
+ */
+static void print_name_list(NAME_LIST *name_list)
+{ 
+   int i;
+
+   for (i=0; i < name_list->num_ids; i++) {
+      printf("%s\n", name_list->name[i]);
+   }
+}
+
+
+/*
+ * Free names in the list
+ */
+static void free_name_list(NAME_LIST *name_list)
+{ 
+   int i;
+
+   for (i=0; i < name_list->num_ids; i++) {
+      free(name_list->name[i]);
+   }
+   name_list->num_ids = 0;
+}
+
+static void eliminate_duplicate_filenames()
+{
+   char *query;
+
+   printf("Checking for duplicate Filename entries.\n");
+   
+   /* Make list of duplicated names */
+   query = "SELECT Name FROM Filename "
+           "GROUP BY Name HAVING COUNT(FilenameId) > 1";
+   if (!make_name_list(query, &name_list)) {
+      exit(1);
+   }
+   printf("Found %d duplicate Filename records.\n", name_list.num_ids);
+   if (verbose) {
+      print_name_list(&name_list);
+   }
+   if (fix) {
+      /* Loop through list of duplicate names */
+      for (int i=0; i<name_list.num_ids; i++) {
+        /* Get all the Ids of each name */
+         sprintf(buf, "SELECT FilenameId FROM Filename WHERE Name='%s'",
+           name_list.name[i]);
+        if (!make_id_list(buf, &id_list)) {
+           exit(1);
+        }
+        /* Force all records to use the first id then delete the other ids */
+        for (int j=1; j<id_list.num_ids; j++) {
+            sprintf(buf, "UPDATE File SET FilenameId=%u WHERE FilenameId=%u", 
+              id_list.Id[0], id_list.Id[j]);
+           db_sql_query(db, buf, NULL, NULL);
+            sprintf(buf, "DELETE FROM Filename WHERE FilenameId=%u", 
+              id_list.Id[j]);
+           db_sql_query(db, buf, NULL, NULL);
+        }
+      }
+   }
+   free_name_list(&name_list);
+}
+
+static void eliminate_duplicate_paths()
+{
+   char *query;
+
+   printf("Checking for duplicate Path entries.\n");
+   
+   /* Make list of duplicated names */
+   query = "SELECT Path FROM Path "
+           "GROUP BY Path HAVING COUNT(PathId) > 1";
+   if (!make_name_list(query, &name_list)) {
+      exit(1);
+   }
+   printf("Found %d duplicate Path records.\n", name_list.num_ids);
+   if (verbose) {
+      print_name_list(&name_list);
+   }
+   if (fix) {
+      /* Loop through list of duplicate names */
+      for (int i=0; i<name_list.num_ids; i++) {
+        /* Get all the Ids of each name */
+         sprintf(buf, "SELECT PathId FROM Path WHERE Path='%s'",
+           name_list.name[i]);
+        if (!make_id_list(buf, &id_list)) {
+           exit(1);
+        }
+        /* Force all records to use the first id then delete the other ids */
+        for (int j=1; j<id_list.num_ids; j++) {
+            sprintf(buf, "UPDATE File SET PathId=%u WHERE PathId=%u", 
+              id_list.Id[0], id_list.Id[j]);
+           db_sql_query(db, buf, NULL, NULL);
+            sprintf(buf, "DELETE FROM Path WHERE PathId=%u", 
+              id_list.Id[j]);
+           db_sql_query(db, buf, NULL, NULL);
+        }
+      }
+   }
+   free_name_list(&name_list);
+}
+
+static void eliminate_orphaned_jobmedia_records()
+{
+   char *query;
+
+   printf("Checking for orphaned JobMedia entries.\n");
+   query = "SELECT JobMedia.JobId,Job FROM JobMedia LEFT OUTER JOIN Job ON"
+           " (Job.JobId=JobMediaId) GROUP BY MediaId HAVING Job IS NULL";
+   if (!make_id_list(query, &id_list)) {
+      exit(1);
+   }
+   printf("Found %d orphaned JobMedia records.\n", id_list.num_ids);
+   
+   if (fix && id_list.num_ids > 0) {
+      printf("Deleting %d orphaned JobMedia records.\n", id_list.num_ids);
+      delete_id_list("DELETE FROM JobMedia WHERE JobMediaId=%u", &id_list);
+   }
+}
+
+static void eliminate_orphaned_file_records()
+{
+   char *query;
+
+   printf("Checking for orphaned File entries.\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)) {
+      exit(1);
+   }
+   printf("Found %d orphaned File records.\n", id_list.num_ids);
+   
+   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);
+   }
+}