/*
- Bacula® - The Network Backup Solution
-
- Copyright (C) 2002-2011 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.
- 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
- License as published by the Free Software Foundation and included
- in the file LICENSE.
-
- 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 Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of Kern Sibbald.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
+ Bacula(R) - The Network Backup Solution
+
+ Copyright (C) 2000-2016 Kern Sibbald
+
+ The original author of Bacula is Kern Sibbald, with contributions
+ from many others, a complete list can be found in the file AUTHORS.
+
+ You may use this file and others of this release according to the
+ license defined in the LICENSE file, which includes the Affero General
+ Public License, v3.0 ("AGPLv3") and some additional permissions and
+ terms pursuant to its AGPLv3 Section 7.
+
+ This notice must be preserved when any source code is
+ conveyed and/or propagated.
+
+ Bacula(R) is a registered trademark of Kern Sibbald.
*/
/*
*
#include "bacula.h"
#include "cats/cats.h"
-#include "cats/sql_glue.h"
#include "lib/runscript.h"
#include "dird/dird_conf.h"
extern bool parse_dir_config(CONFIG *config, const char *configfile, int exit_code);
-/* Dummy functions */
-int generate_daemon_event(JCR *jcr, const char *event)
- { return 1; }
-
typedef struct s_id_ctx {
int64_t *Id; /* ids to be modified */
int num_ids; /* ids stored */
int tot_ids; /* total to process */
} NAME_LIST;
-/* Global variables */
+/* Global variables */
+
static bool fix = false;
static bool batch = false;
-static B_DB *db;
+static BDB *db;
static ID_LIST id_list;
static NAME_LIST name_list;
static char buf[20000];
static bool quit = false;
static CONFIG *config;
+static const char *idx_tmp_name;
#define MAX_ID_LIST_LEN 10000000
-/* Forward referenced functions */
+/* Forward referenced functions */
static int make_id_list(const char *query, ID_LIST *id_list);
static int delete_id_list(const char *query, ID_LIST *id_list);
static int make_name_list(const char *query, NAME_LIST *name_list);
static bool yes_no(const char *prompt);
static bool check_idx(const char *col_name);
static bool create_tmp_idx(const char *idx_name, const char *table_name,
- const char *col_name);
+ const char *col_name);
static bool drop_tmp_idx(const char *idx_name, const char *table_name);
-#ifdef HAVE_MYSQL
static int check_idx_handler(void *ctx, int num_fields, char **row);
-#endif
-
-
-/* Global variables */
-static const char *idx_tmp_name;
static void usage()
{
fprintf(stderr,
-"Usage: dbcheck [-c config ] [-B] [-C catalog name] [-d debug_level] <working-directory> <bacula-database> <user> <password> [<dbhost>] [<dbport>]\n"
+PROG_COPYRIGHT
+"\n%sVersion: %s (%s)\n\n"
+"Usage: dbcheck [-c config ] [-B] [-C catalog name] [-d debug_level] <working-directory> <bacula-database> <user> <password> [<dbhost>] [<dbport>] [<dbport>] [<dbsslmode>] [<dbsslkey>] [<dbsslcert>] [<dbsslca>]\n"
" -b batch mode\n"
" -C catalog name in the director conf file\n"
" -c Director conf filename\n"
" -f fix inconsistencies\n"
" -t test if client library is thread-safe\n"
" -v verbose\n"
-" -? print this message\n\n");
+" -? print this message\n"
+"\n", 2002, "", VERSION, BDATE);
+
exit(1);
}
{
int ch;
const char *user, *password, *db_name, *dbhost;
+ const char *dbsslmode = NULL, *dbsslkey = NULL, *dbsslcert = NULL, *dbsslca = NULL;
+ const char *dbsslcapath = NULL, *dbsslcipher = NULL;
int dbport = 0;
bool print_catalog=false;
char *configfile = NULL;
lmgr_init_thread();
my_name_is(argc, argv, "dbcheck");
- init_msg(NULL, NULL); /* setup message handler */
+ 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, "bc:C:d:fvB?")) != -1) {
+ while ((ch = getopt(argc, argv, "bc:C:d:fvB?")) != -1) {
switch (ch) {
case 'B':
print_catalog = true; /* get catalog information from config */
break;
-
case 'b': /* batch */
batch = true;
break;
-
case 'C': /* CatalogName */
catalogname = optarg;
break;
-
case 'c': /* configfile */
configfile = optarg;
break;
-
case 'd': /* debug level */
if (*optarg == 't') {
dbg_timestamp = true;
}
}
break;
-
case 'f': /* fix inconsistencies */
fix = true;
break;
-
case 'v':
verbose++;
break;
-
case '?':
default:
usage();
if (argc > 0) {
Pmsg0(0, _("Warning skipping the additional parameters for working directory/dbname/user/password/host.\n"));
}
- config = new_config_parser();
+ config = New(CONFIG());
parse_dir_config(config, configfile, M_ERROR_TERM);
LockRes();
foreach_res(catalog, R_CATALOG) {
/* Print catalog information and exit (-B) */
if (print_catalog) {
- POOLMEM *buf = get_pool_memory(PM_MESSAGE);
- printf("%s\nworking_dir=%s\n", catalog->display(buf),
- working_directory);
- free_pool_memory(buf);
+
+ POOLMEM *catalog_details = get_pool_memory(PM_MESSAGE);
+ db = db_init_database(NULL, catalog->db_driver, catalog->db_name, catalog->db_user,
+ catalog->db_password, catalog->db_address,
+ catalog->db_port, catalog->db_socket,
+ catalog->db_ssl_mode,
+ catalog->db_ssl_key, catalog->db_ssl_cert,
+ catalog->db_ssl_ca,
+ catalog->db_ssl_capath, catalog->db_ssl_cipher,
+ catalog->mult_db_connections,
+ catalog->disable_batch_insert);
+ if (db) {
+ printf("%sdb_type=%s\nworking_dir=%s\n", catalog->display(catalog_details),
+ db_get_engine_name(db), working_directory);
+ db_close_database(NULL, db);
+ }
+ free_pool_memory(catalog_details);
exit(0);
}
dbhost = NULL;
}
dbport = catalog->db_port;
+ dbsslmode = catalog->db_ssl_mode;
+ dbsslkey = catalog->db_ssl_key;
+ dbsslcert = catalog->db_ssl_cert;
+ dbsslca = catalog->db_ssl_ca;
+ dbsslcapath = catalog->db_ssl_capath;
+ dbsslcipher = catalog->db_ssl_cipher;
}
} else {
- if (argc > 6) {
+ if (argc > 10) {
Pmsg0(0, _("Wrong number of arguments.\n"));
usage();
}
password = "";
dbhost = NULL;
- if (argc == 2) {
+ 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];
- } else if (argc == 5) {
- db_name = argv[1];
- user = argv[2];
- password = argv[3];
- dbhost = argv[4];
- } else if (argc == 6) {
- db_name = argv[1];
- user = argv[2];
- password = argv[3];
- dbhost = argv[4];
- errno = 0;
- dbport = strtol(argv[5], &endptr, 10);
- if (*endptr != '\0') {
- Pmsg0(0, _("Database port must be a numeric value.\n"));
- exit(1);
- } else if (errno == ERANGE) {
- Pmsg0(0, _("Database port must be a int value.\n"));
- exit(1);
- }
- }
+ if (argc >= 3) {
+ user = argv[2];
+ if (argc >= 4) {
+ password = argv[3];
+ if (argc >= 5) {
+ dbhost = argv[4];
+ if (argc >= 6) {
+ errno = 0;
+ dbport = strtol(argv[5], &endptr, 10);
+ if (*endptr != '\0') {
+ Pmsg0(0, _("Database port must be a numeric value.\n"));
+ exit(1);
+ } else if (errno == ERANGE) {
+ Pmsg0(0, _("Database port must be a int value.\n"));
+ exit(1);
+ }
+ if (argc >= 7) {
+ dbsslmode = argv[6];
+ if (argc >= 8) {
+ dbsslkey = argv[7];
+ dbsslcert = argv[8];
+ if (argc == 10) {
+ dbsslca = argv[9];
+ } /* if (argc == 10) */
+ } /* if (argc >= 8) */
+ } /* if (argc >= 7) */
+ } /* if (argc >= 6) */
+ } /* if (argc >= 5) */
+ } /* if (argc >= 4) */
+ } /* if (argc >= 3) */
+ } /* if (argc >= 2) */
}
/* Open database */
- db = db_init_database(NULL, NULL, db_name, user, password, dbhost, dbport, NULL, false, false);
- if (!db_open_database(NULL, db)) {
+ db = db_init_database(NULL, NULL, db_name, user, password, dbhost,
+ dbport, NULL, dbsslmode, dbsslkey, dbsslcert, dbsslca,
+ dbsslcapath, dbsslcipher, false, false);
+
+ if (!db || !db_open_database(NULL, db)) {
Emsg1(M_FATAL, 0, "%s", db_strerror(db));
return 1;
}
- /* drop temporary index idx_tmp_name if it already exists */
+ /* Drop temporary index idx_tmp_name if it already exists */
drop_tmp_idx("idxPIchk", "File");
if (batch) {
do_interactive_mode();
}
- /* drop temporary index idx_tmp_name */
+ /* Drop temporary index idx_tmp_name */
drop_tmp_idx("idxPIchk", "File");
- db_close_database(NULL, db);
+ if (db) db_close_database(NULL, db);
close_msg(NULL);
term_msg();
lmgr_cleanup_main();
return 0;
}
+void print_catalog_details(CAT *catalog, const char *working_dir)
+{
+ POOLMEM *catalog_details = get_pool_memory(PM_MESSAGE);
+
+ /*
+ * Instantiate a BDB class and see what db_type gets assigned to it.
+ */
+ db = db_init_database(NULL, catalog->db_driver, catalog->db_name, catalog->db_user,
+ catalog->db_password, catalog->db_address,
+ catalog->db_port, catalog->db_socket,
+ catalog->db_ssl_mode, catalog->db_ssl_key,
+ catalog->db_ssl_cert, catalog->db_ssl_ca,
+ catalog->db_ssl_capath, catalog->db_ssl_cipher,
+ catalog->mult_db_connections,
+ catalog->disable_batch_insert);
+ if (db) {
+ printf("%sdb_type=%s\nworking_dir=%s\n", catalog->display(catalog_details),
+ db_get_engine_name(db), working_directory);
+ db_close_database(NULL, db);
+ }
+ free_pool_memory(catalog_details);
+}
+
static void do_interactive_mode()
{
const char *cmd;
return 0;
}
-
static int print_jobmedia_handler(void *ctx, int num_fields, char **row)
{
printf(_("Orphaned JobMediaId=%s JobId=%s Volume=\"%s\"\n"),
return 0;
}
-
/*
* Called here with each id to be added to the list
*/
return 0;
}
-
/*
* Construct name list
*/
}
}
-
/*
* Free names in the list
*/
printf(_("Checking for duplicate Path entries.\n"));
/* Make list of duplicated names */
-
query = "SELECT Path, count(Path) as Count FROM Path "
"GROUP BY Path HAVING count(Path) > 1";
/* Loop through list of duplicate names */
for (int i=0; i<name_list.num_ids; i++) {
/* Get all the Ids of each name */
- db_escape_string(NULL, db, esc_name, name_list.name[i], strlen(name_list.name[i]));
+ db_escape_string(NULL, db, esc_name, name_list.name[i], strlen(name_list.name[i]));
bsnprintf(buf, sizeof(buf), "SELECT PathId FROM Path WHERE Path='%s'", esc_name);
if (verbose > 1) {
printf("%s\n", buf);
char ed1[50];
bsnprintf(buf, sizeof(buf),
"SELECT JobMedia.JobMediaId,JobMedia.JobId,Media.VolumeName FROM JobMedia,Media "
-"WHERE JobMedia.JobMediaId=%s AND Media.MediaId=JobMedia.MediaId",
+ "WHERE JobMedia.JobMediaId=%s AND Media.MediaId=JobMedia.MediaId",
edit_int64(id_list.Id[i], ed1));
if (!db_sql_query(db, buf, print_jobmedia_handler, NULL)) {
printf("%s\n", db_strerror(db));
char ed1[50];
bsnprintf(buf, sizeof(buf),
"SELECT File.FileId,File.JobId,Filename.Name FROM File,Filename "
-"WHERE File.FileId=%s AND File.FilenameId=Filename.FilenameId",
+ "WHERE File.FileId=%s AND File.FilenameId=Filename.FilenameId",
edit_int64(id_list.Id[i], ed1));
if (!db_sql_query(db, buf, print_file_handler, NULL)) {
printf("%s\n", db_strerror(db));
static void eliminate_orphaned_path_records()
{
+ db_int64_ctx lctx;
+ lctx.count=0;
+ db_sql_query(db, "SELECT 1 FROM Job WHERE HasCache=1 LIMIT 1",
+ db_int64_handler, &lctx);
+
+ if (lctx.count == 1) {
+ printf(_("Pruning orphaned Path entries isn't possible when using BVFS.\n"));
+ return;
+ }
+
idx_tmp_name = NULL;
- /* check the existence of the required "one column" index */
+ /* Check the existence of the required "one column" index */
if (!check_idx("PathId")) {
if (yes_no(_("Create temporary index? (yes/no): "))) {
- /* create temporary index PathId */
+ /* create temporary index PathId */
create_tmp_idx("idxPIchk", "File", "PathId");
}
}
exit(1);
}
}
- /* drop temporary index idx_tmp_name */
+ /* Drop temporary index idx_tmp_name */
drop_tmp_idx("idxPIchk", "File");
}
static void eliminate_orphaned_filename_records()
{
idx_tmp_name = NULL;
- /* check the existence of the required "one column" index */
+ /* Check the existence of the required "one column" index */
if (!check_idx("FilenameId") ) {
if (yes_no(_("Create temporary index? (yes/no): "))) {
- /* create temporary index FilenameId */
+ /* Create temporary index FilenameId */
create_tmp_idx("idxFIchk", "File", "FilenameId");
}
}
exit(1);
}
}
- /* drop temporary index idx_tmp_name */
+ /* Drop temporary index idx_tmp_name */
drop_tmp_idx("idxFIchk", "File");
}
}
}
-
static void eliminate_admin_records()
{
const char *query;
}
}
-
-
-
static void repair_bad_filenames()
{
const char *query;
}
db_sql_query(db, buf, NULL, NULL);
}
+ free_pool_memory(name);
}
}
}
/* Add trailing slash */
len = pm_strcat(&name, "/");
- db_escape_string(NULL, db, esc_name, name, len);
+ db_escape_string(NULL, db, esc_name, name, len);
bsnprintf(buf, sizeof(buf), "UPDATE Path SET Path='%s' WHERE PathId=%s",
esc_name, edit_int64(id_list.Id[i], ed1));
if (verbose > 1) {
}
db_sql_query(db, buf, NULL, NULL);
}
+ free_pool_memory(name);
}
}
-
/*
* Gen next input command from the terminal
*/
bool python_set_prog(JCR*, char const*) { return false; }
-
/*
* The code below to add indexes is needed only for MySQL, and
* that to improve the performance.
*/
-#ifdef HAVE_MYSQL
#define MAXIDX 100
typedef struct s_idx_list {
char *key_name;
*/
static int check_idx_handler(void *ctx, int num_fields, char **row)
{
- /* Table | Non_unique | Key_name | Seq_in_index | Column_name |...
+ /*
+ * Table | Non_unique | Key_name | Seq_in_index | Column_name |...
* File | 0 | PRIMARY | 1 | FileId |...
- */
+ */
char *name, *key_name, *col_name;
int i, len;
int found = false;
+
name = (char *)ctx;
key_name = row[2];
col_name = row[4];
break;
}
}
- /* if the new Key_name, add it to the list */
+ /* If the new Key_name, add it to the list */
if (!found) {
len = strlen(key_name) + 1;
idx_list[i].key_name = (char *)malloc(len);
}
return 0;
}
-#endif
/*
* Return TRUE if "one column" index over *col_name exists
*/
static bool check_idx(const char *col_name)
{
-#ifdef HAVE_MYSQL
int i;
int found = false;
+ const char *query = "SHOW INDEX FROM File";
+ if (db_get_type_index(db) != SQL_TYPE_MYSQL) {
+ return true;
+ }
+ /* Continue for MySQL */
memset(&idx_list, 0, sizeof(idx_list));
- const char *query = "SHOW INDEX FROM File";
if (!db_sql_query(db, query, check_idx_handler, (void *)col_name)) {
printf("%s\n", db_strerror(db));
}
-
- for(i = 0; (idx_list[i].key_name != NULL) && (i < MAXIDX) ; i++) {
- /* NOTE : if (idx_list[i].count_key > 1) then index idx_list[i].key_name is "multiple-column" index */
+ for (i = 0; (idx_list[i].key_name != NULL) && (i < MAXIDX) ; i++) {
+ /*
+ * NOTE : if (idx_list[i].count_key > 1) then index idx_list[i].key_name is "multiple-column" index
+ */
if ((idx_list[i].count_key == 1) && (idx_list[i].count_col == 1)) {
/* "one column" index over *col_name found */
found = true;
} else {
printf(_("Note. Index over the %s column not found, that can greatly slow down dbcheck.\n"), col_name);
}
-
return found;
-#else
- return true;
-#endif
}
/*
* Create temporary one-column index
*/
static bool create_tmp_idx(const char *idx_name, const char *table_name,
- const char *col_name)
+ const char *col_name)
{
idx_tmp_name = NULL;
printf(_("Create temporary index... This may take some time!\n"));