From: Kern Sibbald Date: Sat, 20 Dec 2003 18:40:14 +0000 (+0000) Subject: SQL updates + Vol read/write times X-Git-Tag: Release-7.0.0~9816 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6c7cb4fae48855844858efe9e43b003b47966a05;p=bacula%2Fbacula SQL updates + Vol read/write times git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@914 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/Makefile.in b/bacula/Makefile.in index 87e6eb80c2..b9e212a182 100755 --- a/bacula/Makefile.in +++ b/bacula/Makefile.in @@ -121,6 +121,7 @@ Makefiles: chmod 755 src/cats/make_test_tables src/cats/drop_test_tables chmod 755 src/cats/create_mysql_database chmod 755 src/cats/create_postgresql_database + chmod 755 src/cats/create_bacula_database chmod 755 src/cats/make_catalog_backup src/cats/delete_catalog_backup chmod 755 src/cats/update_mysql_tables chmod 755 src/cats/create_sqlite_database @@ -128,6 +129,7 @@ Makefiles: chomd 755 src/cats/update_bacula_tables chmod 755 src/cats/create_bdb_database chmod 755 src/cats/grant_mysql_privileges + chmod 755 src/cats/grant_sqlite_privileges chmod 755 src/cats/grant_postgresql_privileges chmod 755 src/cats/grant_bacula_privileges diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index f32184caef..7cf04e8243 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -1572,11 +1572,13 @@ AC_OUTPUT([autoconf/Make.common \ src/cats/drop_sqlite_tables \ src/cats/update_sqlite_tables \ src/cats/create_sqlite_database \ + src/cats/grant_sqlite_privileges \ src/cats/sqlite \ src/cats/mysql \ src/cats/create_bdb_database \ src/cats/make_bdb_tables \ src/cats/drop_bdb_tables \ + src/cats/create_bacula_database \ src/cats/make_bacula_tables \ src/cats/drop_bacula_tables \ src/cats/update_bacula_tables \ @@ -1604,6 +1606,7 @@ chmod 755 src/cats/update_sqlite_tables chmod 755 src/cats/make_bacula_tables src/cats/drop_bacula_tables chmod 755 src/cats/update_mysql_tables chmod 755 src/cats/update_bacula_tables src/cats/update_mysql_tables +chmod 755 src/cats/create_bacula_database chmod 755 src/cats/grant_bacula_privileges chmod 755 src/cats/create_sqlite_database chmod 755 src/cats/sqlite diff --git a/bacula/configure b/bacula/configure index 238b6f7288..c9370b4cc9 100755 --- a/bacula/configure +++ b/bacula/configure @@ -18032,7 +18032,7 @@ if test "x${subsysdir}" = "x${sbindir}" ; then exit 1 fi - ac_config_files="$ac_config_files autoconf/Make.common Makefile rescue/Makefile rescue/linux/Makefile rescue/freebsd/Makefile rescue/solaris/Makefile scripts/startmysql scripts/stopmysql scripts/btraceback scripts/startit scripts/stopit scripts/bconsole scripts/gconsole scripts/bacula scripts/fd scripts/Makefile scripts/logrotate scripts/bacula.desktop.gnome1 scripts/bacula.desktop.gnome2 scripts/mtx-changer doc/Makefile src/Makefile src/host.h src/console/Makefile src/console/bconsole.conf src/gnome-console/Makefile src/gnome-console/gnome-console.conf src/gnome2-console/Makefile src/gnome2-console/gnome-console.conf src/tconsole/Makefile src/dird/Makefile src/dird/bacula-dir.conf src/lib/Makefile src/stored/Makefile src/stored/bacula-sd.conf src/filed/Makefile src/filed/bacula-fd.conf src/filed/win32/Makefile src/cats/Makefile src/cats/make_catalog_backup src/cats/delete_catalog_backup src/cats/make_postgresql_tables src/cats/drop_postgresql_tables src/cats/create_postgresql_database src/cats/grant_postgresql_privileges src/cats/make_mysql_tables src/cats/drop_mysql_tables src/cats/update_mysql_tables src/cats/create_mysql_database src/cats/grant_mysql_privileges src/cats/make_sqlite_tables src/cats/drop_sqlite_tables src/cats/update_sqlite_tables src/cats/create_sqlite_database src/cats/sqlite src/cats/mysql src/cats/create_bdb_database src/cats/make_bdb_tables src/cats/drop_bdb_tables src/cats/make_bacula_tables src/cats/drop_bacula_tables src/cats/update_bacula_tables src/cats/grant_bacula_privileges src/findlib/Makefile src/tools/Makefile $PFILES" + ac_config_files="$ac_config_files autoconf/Make.common Makefile rescue/Makefile rescue/linux/Makefile rescue/freebsd/Makefile rescue/solaris/Makefile scripts/startmysql scripts/stopmysql scripts/btraceback scripts/startit scripts/stopit scripts/bconsole scripts/gconsole scripts/bacula scripts/fd scripts/Makefile scripts/logrotate scripts/bacula.desktop.gnome1 scripts/bacula.desktop.gnome2 scripts/mtx-changer doc/Makefile src/Makefile src/host.h src/console/Makefile src/console/bconsole.conf src/gnome-console/Makefile src/gnome-console/gnome-console.conf src/gnome2-console/Makefile src/gnome2-console/gnome-console.conf src/tconsole/Makefile src/dird/Makefile src/dird/bacula-dir.conf src/lib/Makefile src/stored/Makefile src/stored/bacula-sd.conf src/filed/Makefile src/filed/bacula-fd.conf src/filed/win32/Makefile src/cats/Makefile src/cats/make_catalog_backup src/cats/delete_catalog_backup src/cats/make_postgresql_tables src/cats/drop_postgresql_tables src/cats/create_postgresql_database src/cats/grant_postgresql_privileges src/cats/make_mysql_tables src/cats/drop_mysql_tables src/cats/update_mysql_tables src/cats/create_mysql_database src/cats/grant_mysql_privileges src/cats/make_sqlite_tables src/cats/drop_sqlite_tables src/cats/update_sqlite_tables src/cats/create_sqlite_database src/cats/grant_sqlite_privileges src/cats/sqlite src/cats/mysql src/cats/create_bdb_database src/cats/make_bdb_tables src/cats/drop_bdb_tables src/cats/create_bacula_database src/cats/make_bacula_tables src/cats/drop_bacula_tables src/cats/update_bacula_tables src/cats/grant_bacula_privileges src/findlib/Makefile src/tools/Makefile $PFILES" ac_config_commands="$ac_config_commands default" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -18615,11 +18615,13 @@ do "src/cats/drop_sqlite_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_sqlite_tables" ;; "src/cats/update_sqlite_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/update_sqlite_tables" ;; "src/cats/create_sqlite_database" ) CONFIG_FILES="$CONFIG_FILES src/cats/create_sqlite_database" ;; + "src/cats/grant_sqlite_privileges" ) CONFIG_FILES="$CONFIG_FILES src/cats/grant_sqlite_privileges" ;; "src/cats/sqlite" ) CONFIG_FILES="$CONFIG_FILES src/cats/sqlite" ;; "src/cats/mysql" ) CONFIG_FILES="$CONFIG_FILES src/cats/mysql" ;; "src/cats/create_bdb_database" ) CONFIG_FILES="$CONFIG_FILES src/cats/create_bdb_database" ;; "src/cats/make_bdb_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/make_bdb_tables" ;; "src/cats/drop_bdb_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_bdb_tables" ;; + "src/cats/create_bacula_database" ) CONFIG_FILES="$CONFIG_FILES src/cats/create_bacula_database" ;; "src/cats/make_bacula_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/make_bacula_tables" ;; "src/cats/drop_bacula_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_bacula_tables" ;; "src/cats/update_bacula_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/update_bacula_tables" ;; @@ -19410,6 +19412,7 @@ chmod 755 src/cats/update_sqlite_tables chmod 755 src/cats/make_bacula_tables src/cats/drop_bacula_tables chmod 755 src/cats/update_mysql_tables chmod 755 src/cats/update_bacula_tables src/cats/update_mysql_tables +chmod 755 src/cats/create_bacula_database chmod 755 src/cats/grant_bacula_privileges chmod 755 src/cats/create_sqlite_database chmod 755 src/cats/sqlite diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 7178c7621b..d25520787b 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -62,8 +62,8 @@ struct sqlite { typedef struct s_sql_field { char *name; /* name of column */ - uint32_t length; /* length */ - uint32_t max_length; /* max length */ + int length; /* length */ + int max_length; /* max length */ uint32_t type; /* type */ uint32_t flags; /* flags */ } SQL_FIELD; @@ -129,15 +129,18 @@ typedef struct s_db { #define sql_insert_id(x,y) sqlite_last_insert_rowid((x)->db) #define sql_field_seek(x, y) my_sqlite_field_seek((x), (y)) #define sql_fetch_field(x) my_sqlite_fetch_field(x) -#define sql_num_fields(x) (unsigned)((x)->ncolumn) +#define sql_num_fields(x) ((x)->ncolumn) #define SQL_ROW char** /* In cats/sqlite.c */ -extern int my_sqlite_query(B_DB *mdb, char *cmd); -extern SQL_ROW my_sqlite_fetch_row(B_DB *mdb); -extern void my_sqlite_free_table(B_DB *mdb); +void my_sqlite_free_table(B_DB *mdb); +SQL_ROW my_sqlite_fetch_row(B_DB *mdb); +int my_sqlite_query(B_DB *mdb, char *cmd); +void my_sqlite_field_seek(B_DB *mdb, int field); +SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb); + #else @@ -199,7 +202,7 @@ typedef struct s_db { #define sql_insert_id(x,y) mysql_insert_id((x)->db) #define sql_field_seek(x, y) mysql_field_seek((x)->result, (y)) #define sql_fetch_field(x) mysql_fetch_field((x)->result) -#define sql_num_fields(x) mysql_num_fields((x)->result) +#define sql_num_fields(x) (int)mysql_num_fields((x)->result) #define SQL_ROW MYSQL_ROW #define SQL_FIELD MYSQL_FIELD @@ -217,10 +220,10 @@ typedef struct s_db { typedef char **POSTGRESQL_ROW; typedef struct pg_field { - char *name; - unsigned int max_length; - unsigned int type; // 1 = number - unsigned int flags; // 1 == not null + char *name; + int max_length; + unsigned int type; // 1 = number + unsigned int flags; // 1 == not null } POSTGRESQL_FIELD; @@ -229,11 +232,11 @@ typedef struct pg_field { * used inside sql.c and associated database interface * subroutines. * - * P O S T G R E S Q L + * P O S T G R E S Q L */ typedef struct s_db { - BQUEUE bq; /* queue control */ - brwlock_t lock; /* transaction lock */ + BQUEUE bq; /* queue control */ + brwlock_t lock; /* transaction lock */ PGconn *db; PGresult *result; int status; @@ -247,32 +250,31 @@ typedef struct s_db { char *db_name; char *db_user; char *db_password; - char *db_address; /* host address */ - char *db_socket; /* socket for local access */ - int db_port; /* port of host address */ - int have_insert_id; /* do have insert_id() */ + char *db_address; /* host address */ + char *db_socket; /* socket for local access */ + int db_port; /* port of host address */ + int have_insert_id; /* do have insert_id() */ int connected; - POOLMEM *errmsg; /* nicely edited error message */ - POOLMEM *cmd; /* SQL command string */ + POOLMEM *errmsg; /* nicely edited error message */ + POOLMEM *cmd; /* SQL command string */ POOLMEM *cached_path; - int cached_path_len; /* length of cached path */ + int cached_path_len; /* length of cached path */ uint32_t cached_path_id; - int changes; /* changes made to db */ - POOLMEM *fname; /* Filename only */ - POOLMEM *path; /* Path only */ - POOLMEM *esc_name; /* Escaped file/path name */ - int fnl; /* file name length */ - int pnl; /* path name length */ + int changes; /* changes made to db */ + POOLMEM *fname; /* Filename only */ + POOLMEM *path; /* Path only */ + POOLMEM *esc_name; /* Escaped file/path name */ + int fnl; /* file name length */ + int pnl; /* path name length */ } B_DB; -POSTGRESQL_ROW my_postgresql_fetch_row (B_DB *mdb); -POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb); - -void my_postgresql_data_seek (B_DB *mdb, int row); -void my_postgresql_field_seek (B_DB *mdb, int row); -int my_postgresql_query (B_DB *mdb, char *query); -void my_postgresql_free_result(B_DB *mdb); -int my_postgresql_currval (B_DB *mdb, char *table_name); +void my_postgresql_free_result(B_DB *mdb); +POSTGRESQL_ROW my_postgresql_fetch_row(B_DB *mdb); +int my_postgresql_query (B_DB *mdb, char *query); +void my_postgresql_data_seek (B_DB *mdb, int row); +int my_postgresql_currval (B_DB *mdb, char *table_name); +void my_postgresql_field_seek (B_DB *mdb, int row); +POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb) /* "Generic" names for easier conversion */ @@ -288,7 +290,7 @@ int my_postgresql_currval (B_DB *mdb, char *table_name); #define sql_insert_id(x,y) my_postgresql_currval((x), (y)) #define sql_field_seek(x, y) my_postgresql_field_seek((x), (y)) #define sql_fetch_field(x) my_postgresql_fetch_field(x) -#define sql_num_fields(x) (unsigned) (x)->num_fields +#define sql_num_fields(x) ((x)->num_fields) #define SQL_ROW POSTGRESQL_ROW #define SQL_FIELD POSTGRESQL_FIELD @@ -360,7 +362,9 @@ typedef struct s_db { extern uint32_t bacula_db_version; -/* ***FIXME*** FileId_t should be uint64_t */ +/* ***FIXME*** FileId_t should *really* be uint64_t + * but at the current time, this breaks MySQL. + */ typedef uint32_t FileId_t; typedef uint32_t DBId_t; /* general DB id type */ typedef uint32_t JobId_t; @@ -515,13 +519,14 @@ struct MEDIA_DBR { uint64_t VolBytes; /* Number of bytes written */ uint64_t MaxVolBytes; /* Max bytes to write to Volume */ uint64_t VolCapacityBytes; /* capacity estimate */ + uint64_t VolReadTime; /* time spent reading volume */ + uint64_t VolWriteTime; /* time spent writing volume */ utime_t VolRetention; /* Volume retention in seconds */ utime_t VolUseDuration; /* time in secs volume can be used */ uint32_t MaxVolJobs; /* Max Jobs on Volume */ uint32_t MaxVolFiles; /* Max files on Volume */ int32_t Recycle; /* recycle yes/no */ int32_t Slot; /* slot in changer */ - int32_t Drive; /* drive in changer */ int32_t InChanger; /* Volume currently in changer */ char VolStatus[20]; /* Volume status */ /* Extra stuff not in DB */ @@ -569,7 +574,19 @@ struct FILESET_DBR { }; + #include "protos.h" #include "jcr.h" + +/* + * Some functions exported by sql.c for use withing the + * cats directory. + */ +void list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type); +void list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx); +int get_sql_record_max(JCR *jcr, B_DB *mdb); +int check_tables_version(JCR *jcr, B_DB *mdb); +void _db_unlock(char *file, int line, B_DB *mdb); +void _db_lock(char *file, int line, B_DB *mdb); #endif /* __SQL_H_ */ diff --git a/bacula/src/cats/make_mysql_tables.in b/bacula/src/cats/make_mysql_tables.in index 6db5652082..509dc097e3 100644 --- a/bacula/src/cats/make_mysql_tables.in +++ b/bacula/src/cats/make_mysql_tables.in @@ -114,9 +114,10 @@ CREATE TABLE Media ( MaxVolJobs INTEGER UNSIGNED NOT NULL DEFAULT 0, MaxVolFiles INTEGER UNSIGNED NOT NULL DEFAULT 0, MaxVolBytes BIGINT UNSIGNED NOT NULL DEFAULT 0, - Drive INTEGER NOT NULL DEFAULT 0, InChanger TINYINT NOT NULL DEFAULT 0, MediaAddressing TINYINT NOT NULL DEFAULT 0, + VolReadTime BIGINT UNSIGNED NOT NULL DEAULT 0, + VolWriteTime BIGINT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY(MediaId), INDEX (PoolId) ); diff --git a/bacula/src/cats/make_postgresql_tables.in b/bacula/src/cats/make_postgresql_tables.in index 337a74ff4e..12faa4a8cb 100644 --- a/bacula/src/cats/make_postgresql_tables.in +++ b/bacula/src/cats/make_postgresql_tables.in @@ -9,25 +9,25 @@ if $bindir/psql $* -f - <max_length + 2; j++) - send(ctx, "-"); - send(ctx, "+"); - } - send(ctx, "\n"); -} - -/* - * If full_list is set, we list vertically, otherwise, we - * list on one line horizontally. - */ -void -list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type) -{ - SQL_FIELD *field; - SQL_ROW row; - unsigned int i, col_len, max_len = 0; - char buf[2000], ewc[30]; - - if (mdb->result == NULL) { - send(ctx, _("No results to list.\n")); - return; - } - /* determine column display widths */ - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - col_len = strlen(field->name); - if (type == VERT_LIST) { - if (col_len > max_len) { - max_len = col_len; - } - } else { - if (IS_NUM(field->type) && field->max_length > 0) { /* fixup for commas */ - field->max_length += (field->max_length - 1) / 3; - } - if (col_len < field->max_length) { - col_len = field->max_length; - } - if (col_len < 4 && !IS_NOT_NULL(field->flags)) { - col_len = 4; /* 4 = length of the word "NULL" */ - } - field->max_length = col_len; /* reset column info */ - } - } - - if (type == VERT_LIST) { - goto vertical_list; - } - - list_dashes(mdb, send, ctx); - send(ctx, "|"); - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, field->name); - send(ctx, buf); - } - send(ctx, "\n"); - list_dashes(mdb, send, ctx); - - while ((row = sql_fetch_row(mdb)) != NULL) { - sql_field_seek(mdb, 0); - send(ctx, "|"); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - if (row[i] == NULL) { - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, "NULL"); - } else if (IS_NUM(field->type)) { - bsnprintf(buf, sizeof(buf), " %*s |", (int)field->max_length, - add_commas(row[i], ewc)); - } else { - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, row[i]); - } - send(ctx, buf); - } - send(ctx, "\n"); - } - list_dashes(mdb, send, ctx); - return; - -vertical_list: - - while ((row = sql_fetch_row(mdb)) != NULL) { - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - if (row[i] == NULL) { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL"); - } else if (IS_NUM(field->type)) { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, - add_commas(row[i], ewc)); - } else { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]); - } - send(ctx, buf); - } - send(ctx, "\n"); - } - return; -} - - #endif /* HAVE_MYSQL */ diff --git a/bacula/src/cats/postgresql.c b/bacula/src/cats/postgresql.c index 375be429fc..7d08fc5ddd 100644 --- a/bacula/src/cats/postgresql.c +++ b/bacula/src/cats/postgresql.c @@ -39,7 +39,7 @@ #ifdef HAVE_POSTGRESQL -#include "postgres_ext.h" /* needed for NAMEDATALEN */ +#include "postgres_ext.h" /* needed for NAMEDATALEN */ /* ----------------------------------------------------------------------- * @@ -93,14 +93,14 @@ db_init_database(JCR *jcr, char *db_name, char *db_user, char *db_password, } mdb->db_port = db_port; mdb->have_insert_id = TRUE; - mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */ + mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */ *mdb->errmsg = 0; - mdb->cmd = get_pool_memory(PM_EMSG); /* get command buffer */ + mdb->cmd = get_pool_memory(PM_EMSG); /* get command buffer */ mdb->cached_path = get_pool_memory(PM_FNAME); mdb->cached_path_id = 0; mdb->ref_count = 1; - mdb->fname = get_pool_memory(PM_FNAME); - mdb->path = get_pool_memory(PM_FNAME); + mdb->fname = get_pool_memory(PM_FNAME); + mdb->path = get_pool_memory(PM_FNAME); mdb->esc_name = get_pool_memory(PM_FNAME); qinsert(&db_list, &mdb->bq); /* put db in list */ V(mutex); @@ -134,8 +134,8 @@ db_open_database(JCR *jcr, B_DB *mdb) mdb->db = PQsetdbLogin( mdb->db_address, /* default = localhost */ (char *) mdb->db_port, /* default port */ - NULL, /* pg options */ - NULL, /* tty, ignored */ + NULL, /* pg options */ + NULL, /* tty, ignored */ mdb->db_name, /* database name */ mdb->db_user, /* login name */ mdb->db_password); /* password */ @@ -145,8 +145,8 @@ db_open_database(JCR *jcr, B_DB *mdb) mdb->db = PQsetdbLogin( mdb->db_address, /* default = localhost */ (char *) mdb->db_port, /* default port */ - NULL, /* pg options */ - NULL, /* tty, ignored */ + NULL, /* pg options */ + NULL, /* tty, ignored */ mdb->db_name, /* database name */ mdb->db_user, /* login name */ mdb->db_password); /* password */ @@ -160,7 +160,7 @@ db_open_database(JCR *jcr, B_DB *mdb) Mmsg2(&mdb->errmsg, _("Unable to connect to PostgreSQL server.\n" "Database=%s User=%s\n" "It is probably not running or your password is incorrect.\n"), - mdb->db_name, mdb->db_user); + mdb->db_name, mdb->db_user); V(mutex); return 0; } @@ -184,7 +184,7 @@ db_close_database(JCR *jcr, B_DB *mdb) if (mdb->ref_count == 0) { qdchain(&mdb->bq); if (mdb->connected && mdb->db) { - sql_close(mdb); + sql_close(mdb); } rwl_destroy(&mdb->lock); free_pool_memory(mdb->errmsg); @@ -194,19 +194,19 @@ db_close_database(JCR *jcr, B_DB *mdb) free_pool_memory(mdb->path); free_pool_memory(mdb->esc_name); if (mdb->db_name) { - free(mdb->db_name); + free(mdb->db_name); } if (mdb->db_user) { - free(mdb->db_user); + free(mdb->db_user); } if (mdb->db_password) { - free(mdb->db_password); + free(mdb->db_password); } if (mdb->db_address) { - free(mdb->db_address); + free(mdb->db_address); } if (mdb->db_socket) { - free(mdb->db_socket); + free(mdb->db_socket); } free(mdb); } @@ -262,17 +262,17 @@ int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void if (result_handler != NULL) { Dmsg0(50, "db_sql_query invoking handler\n"); if ((mdb->result = sql_store_result(mdb)) != NULL) { - int num_fields = sql_num_fields(mdb); + int num_fields = sql_num_fields(mdb); Dmsg0(50, "db_sql_query sql_store_result suceeded\n"); - while ((row = sql_fetch_row(mdb)) != NULL) { + while ((row = sql_fetch_row(mdb)) != NULL) { Dmsg0(50, "db_sql_query sql_fetch_row worked\n"); - if (result_handler(ctx, num_fields, row)) - break; - } + if (result_handler(ctx, num_fields, row)) + break; + } - sql_free_result(mdb); + sql_free_result(mdb); } } db_unlock(mdb); @@ -283,139 +283,20 @@ int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void } -static void -list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx) -{ - SQL_FIELD *field; - unsigned int i, j; - - sql_field_seek(mdb, 0); - send(ctx, "+"); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - for (j = 0; j < field->max_length + 2; j++) - send(ctx, "-"); - send(ctx, "+"); - } - send(ctx, "\n"); -} -/* - * If full_list is set, we list vertically, otherwise, we - * list on one line horizontally. - */ -void -list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type) +POSTGRESQL_ROW my_postgresql_fetch_row(B_DB *mdb) { - SQL_FIELD *field; - SQL_ROW row; - unsigned int i, col_len, max_len = 0; - char buf[2000], ewc[30]; - - Dmsg0(50, "list_result starts\n"); - if (mdb->result == NULL) { - send(ctx, _("No results to list.\n")); - return; - } - - Dmsg1(50, "list_result starts looking at %d fields\n", sql_num_fields(mdb)); - /* determine column display widths */ - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - Dmsg1(50, "list_result processing field %d\n", i); - field = sql_fetch_field(mdb); - col_len = strlen(field->name); - if (type == VERT_LIST) { - if (col_len > max_len) { - max_len = col_len; - } - } else { - if (IS_NUM(field->type) && field->max_length > 0) { /* fixup for commas */ - field->max_length += (field->max_length - 1) / 3; - } - if (col_len < field->max_length) { - col_len = field->max_length; - } - if (col_len < 4 && !IS_NOT_NULL(field->flags)) { - col_len = 4; /* 4 = length of the word "NULL" */ - } - field->max_length = col_len; /* reset column info */ - } - } - - Dmsg0(50, "list_result finished first loop\n"); - if (type == VERT_LIST) { - goto vertical_list; - } - - Dmsg1(50, "list_result starts second loop looking at %d fields\n", sql_num_fields(mdb)); - list_dashes(mdb, send, ctx); - send(ctx, "|"); - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - Dmsg1(50, "list_result looking at field %d\n", i); - field = sql_fetch_field(mdb); - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, field->name); - send(ctx, buf); - } - send(ctx, "\n"); - list_dashes(mdb, send, ctx); - - Dmsg1(50, "list_result starts third loop looking at %d fields\n", sql_num_fields(mdb)); - while ((row = sql_fetch_row(mdb)) != NULL) { - sql_field_seek(mdb, 0); - send(ctx, "|"); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - if (row[i] == NULL) { - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, "NULL"); - } else if (IS_NUM(field->type)) { - bsnprintf(buf, sizeof(buf), " %*s |", (int)field->max_length, - add_commas(row[i], ewc)); - } else { - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, row[i]); - } - send(ctx, buf); - } - send(ctx, "\n"); - } - list_dashes(mdb, send, ctx); - return; - -vertical_list: - - Dmsg1(50, "list_result starts vertical list at %d fields\n", sql_num_fields(mdb)); - while ((row = sql_fetch_row(mdb)) != NULL) { - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - if (row[i] == NULL) { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL"); - } else if (IS_NUM(field->type)) { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, - add_commas(row[i], ewc)); - } else { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]); - } - send(ctx, buf); - } - send(ctx, "\n"); - } - return; -} - -POSTGRESQL_ROW my_postgresql_fetch_row(B_DB *mdb) { - int j; + int j; POSTGRESQL_ROW row = NULL; // by default, return NULL - Dmsg0(50, "my_postgresql_fetch_row start\n"); + Dmsg0(50, "my_postgresql_fetch_row start\n"); if (mdb->row_number == -1 || mdb->row == NULL) { - Dmsg1(50, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields); + Dmsg1(50, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields); if (mdb->row != NULL) { - Dmsg0(50, "my_postgresql_fetch_row freeing space\n"); + Dmsg0(50, "my_postgresql_fetch_row freeing space\n"); free(mdb->row); mdb->row = NULL; } @@ -428,26 +309,27 @@ POSTGRESQL_ROW my_postgresql_fetch_row(B_DB *mdb) { // if still within the result set if (mdb->row_number < mdb->num_rows) { - Dmsg2(50, "my_postgresql_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); + Dmsg2(50, "my_postgresql_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); // get each value from this row for (j = 0; j < mdb->num_fields; j++) { mdb->row[j] = PQgetvalue(mdb->result, mdb->row_number, j); - Dmsg2(50, "my_postgresql_fetch_row field '%d' has value '%s'\n", j, mdb->row[j]); + Dmsg2(50, "my_postgresql_fetch_row field '%d' has value '%s'\n", j, mdb->row[j]); } // increment the row number for the next call mdb->row_number++; row = mdb->row; } else { - Dmsg2(50, "my_postgresql_fetch_row row number '%d' is NOT acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); + Dmsg2(50, "my_postgresql_fetch_row row number '%d' is NOT acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); } - Dmsg1(50, "my_postgresql_fetch_row finishes returning %x\n", row); + Dmsg1(50, "my_postgresql_fetch_row finishes returning %x\n", row); return row; } -POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb) { +POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb) +{ mdb->field.name = PQfname (mdb->result, mdb->field_number); // I am not sure this returns the max width of the result set @@ -457,12 +339,12 @@ POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb) { mdb->field.type = PQftype (mdb->result, mdb->field_number); // if (mdb->num_rows > 0) { -// Dmsg1(50, "asking for information on field '%d' type='%d' and IsNull=%d\n", -// mdb->field.flags = PQgetisnull(mdb->result, mdb->row_number, mdb->field_number); -// } +// Dmsg1(50, "asking for information on field '%d' type='%d' and IsNull=%d\n", +// mdb->field.flags = PQgetisnull(mdb->result, mdb->row_number, mdb->field_number); +// } mdb->field.flags = 0; - Dmsg4(50, "my_postgresql_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n", + Dmsg4(50, "my_postgresql_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n", mdb->field.name, mdb->field.max_length, mdb->field.type, mdb->field.flags); // increment this for the next time around @@ -471,49 +353,52 @@ POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb) { return &mdb->field; } -void my_postgresql_data_seek(B_DB *mdb, int row) { +void my_postgresql_data_seek(B_DB *mdb, int row) +{ // set the row number to be returned on the next call // to my_postgresql_fetch_row mdb->row_number = row; } -void my_postgresql_field_seek(B_DB *mdb, int field) { +void my_postgresql_field_seek(B_DB *mdb, int field) + { mdb->field_number = field; } int my_postgresql_query(B_DB *mdb, char *query) { - Dmsg0(50, "my_postgresql_query started\n"); + Dmsg0(50, "my_postgresql_query started\n"); // We are starting a new query. reset everything. - mdb->num_rows = -1; + mdb->num_rows = -1; mdb->row_number = -1; mdb->field_number = -1; - Dmsg1(50, "my_postgresql_query starts with '%s'\n", query); + Dmsg1(50, "my_postgresql_query starts with '%s'\n", query); mdb->result = PQexec(mdb->db, query); mdb->status = PQresultStatus(mdb->result); if (mdb->status == PGRES_TUPLES_OK || mdb->status == PGRES_COMMAND_OK) { - Dmsg1(50, "we have a result\n", query); + Dmsg1(50, "we have a result\n", query); // how many fields in the set? - mdb->num_fields = (unsigned int) PQnfields(mdb->result); - Dmsg1(50, "we have %d fields\n", mdb->num_fields); + mdb->num_fields = (int) PQnfields(mdb->result); + Dmsg1(50, "we have %d fields\n", mdb->num_fields); - mdb->num_rows = PQntuples(mdb->result); - Dmsg1(50, "we have %d rows\n", mdb->num_rows); + mdb->num_rows = PQntuples(mdb->result); + Dmsg1(50, "we have %d rows\n", mdb->num_rows); mdb->status = 0; } else { - Dmsg1(50, "we failed\n", query); + Dmsg1(50, "we failed\n", query); mdb->status = 1; } - Dmsg0(50, "my_postgresql_query finishing\n"); + Dmsg0(50, "my_postgresql_query finishing\n"); return mdb->status; } -void my_postgresql_free_result (B_DB *mdb) { +void my_postgresql_free_result (B_DB *mdb) +{ if (mdb->result) { PQclear(mdb->result); } @@ -524,7 +409,8 @@ void my_postgresql_free_result (B_DB *mdb) { } } -int my_postgresql_currval(B_DB *mdb, char *table_name) { +int my_postgresql_currval(B_DB *mdb, char *table_name) +{ // Obtain the current value of the sequence that // provides the serial value for primary key of the table. @@ -541,36 +427,36 @@ int my_postgresql_currval(B_DB *mdb, char *table_name) { // everything else can use the PostgreSQL formula. - char sequence[NAMEDATALEN-1]; - char query [NAMEDATALEN+50]; + char sequence[NAMEDATALEN-1]; + char query [NAMEDATALEN+50]; // POOLMEM *query; PGresult *result; - int id = 0; + int id = 0; - if (strcasecmp(table_name, "basefiles") == 0) { - bstrncpy(sequence, "basefiles_baseid", sizeof(sequence)); + if (strcasecmp(table_name, "basefiles") == 0) { + bstrncpy(sequence, "basefiles_baseid", sizeof(sequence)); } else { bstrncpy(sequence, table_name, sizeof(sequence)); - bstrncat(sequence, "_", sizeof(sequence)); + bstrncat(sequence, "_", sizeof(sequence)); bstrncat(sequence, table_name, sizeof(sequence)); - bstrncat(sequence, "id", sizeof(sequence)); + bstrncat(sequence, "id", sizeof(sequence)); } - bstrncat(sequence, "_seq", sizeof(sequence)); - bsnprintf(query, sizeof(query), "SELECT currval('%s')", sequence); + bstrncat(sequence, "_seq", sizeof(sequence)); + bsnprintf(query, sizeof(query), "SELECT currval('%s')", sequence); -// Mmsg(&query, "SELECT currval('%s')", sequence); - Dmsg1(50, "my_postgresql_currval invoked with '%s'\n", query); +// Mmsg(&query, "SELECT currval('%s')", sequence); + Dmsg1(50, "my_postgresql_currval invoked with '%s'\n", query); result = PQexec(mdb->db, query); - Dmsg0(50, "exec done"); + Dmsg0(50, "exec done"); if (PQresultStatus(result) == PGRES_TUPLES_OK) { - Dmsg0(50, "getting value"); + Dmsg0(50, "getting value"); id = atoi(PQgetvalue(result, 0, 0)); - Dmsg2(50, "got value '%s' which became %d\n", PQgetvalue(result, 0, 0), id); + Dmsg2(50, "got value '%s' which became %d\n", PQgetvalue(result, 0, 0), id); } else { - Mmsg1(&mdb->errmsg, _("error fetching currval: %s\n"), PQerrorMessage(mdb->db)); + Mmsg1(&mdb->errmsg, _("error fetching currval: %s\n"), PQerrorMessage(mdb->db)); } // free_pool_memory(query); diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index b19cc606bd..9570c06f16 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -1,4 +1,7 @@ /* + * + * Database routines that are exported by the cats library for + * use elsewhere in Bacula (mainly the Director). * * Version $Id$ */ @@ -32,19 +35,16 @@ /* sql.c */ B_DB *db_init_database(JCR *jcr, char *db_name, char *db_user, char *db_password, char *db_address, int db_port, char *db_socket); -int db_open_database(JCR *jcr, B_DB *db); +int db_open_database(JCR *jcr, B_DB *db); void db_close_database(JCR *jcr, B_DB *db); void db_escape_string(char *snew, char *old, int len); char *db_strerror(B_DB *mdb); -int get_sql_record_max(JCR *jcr, B_DB *mdb); -int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index); -int db_sql_query(B_DB *mdb, char *cmd, DB_RESULT_HANDLER *result_handler, void *ctx); -int check_tables_version(JCR *jcr, B_DB *mdb); -void _db_unlock(char *file, int line, B_DB *mdb); -void _db_lock(char *file, int line, B_DB *mdb); +int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index); +int db_sql_query(B_DB *mdb, char *cmd, DB_RESULT_HANDLER *result_handler, void *ctx); void db_start_transaction(JCR *jcr, B_DB *mdb); void db_end_transaction(JCR *jcr, B_DB *mdb); + /* create.c */ int db_create_file_attributes_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar); int db_create_job_record(JCR *jcr, B_DB *db, JOB_DBR *jr); diff --git a/bacula/src/cats/sql.c b/bacula/src/cats/sql.c index 16aebd1702..c71f92c27f 100644 --- a/bacula/src/cats/sql.c +++ b/bacula/src/cats/sql.c @@ -80,7 +80,7 @@ int check_tables_version(JCR *jcr, B_DB *mdb) db_sql_query(mdb, query, int_handler, (void *)&bacula_db_version); if (bacula_db_version != BDB_VERSION) { Mmsg(&mdb->errmsg, "Version error for database \"%s\". Wanted %d, got %d\n", - mdb->db_name, BDB_VERSION, bacula_db_version); + mdb->db_name, BDB_VERSION, bacula_db_version); Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); return 0; } @@ -219,11 +219,19 @@ int get_sql_record_max(JCR *jcr, B_DB *mdb) return stat; } +/* + * Return pre-edited error message + */ char *db_strerror(B_DB *mdb) { return mdb->errmsg; } +/* + * Lock database, this can be called multiple times by the same + * thread without blocking, but must be unlocked the number of + * times it was locked. + */ void _db_lock(char *file, int line, B_DB *mdb) { int errstat; @@ -233,6 +241,11 @@ void _db_lock(char *file, int line, B_DB *mdb) } } +/* + * Unlock the database. This can be called multiple times by the + * same thread up to the number of times that thread called + * db_lock()/ + */ void _db_unlock(char *file, int line, B_DB *mdb) { int errstat; @@ -337,4 +350,130 @@ void split_path_and_filename(JCR *jcr, B_DB *mdb, char *fname) Dmsg2(100, "sllit path=%s file=%s\n", mdb->path, mdb->fname); } +/* + * List dashs as part of header for listing SQL results in a table + */ +void +list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx) +{ + SQL_FIELD *field; + int i, j; + + sql_field_seek(mdb, 0); + send(ctx, "+"); + for (i = 0; i < sql_num_fields(mdb); i++) { + field = sql_fetch_field(mdb); + for (j = 0; j < field->max_length + 2; j++) { + send(ctx, "-"); + } + send(ctx, "+"); + } + send(ctx, "\n"); +} + +/* + * If full_list is set, we list vertically, otherwise, we + * list on one line horizontally. + */ +void +list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type) +{ + SQL_FIELD *field; + SQL_ROW row; + int i, col_len, max_len = 0; + char buf[2000], ewc[30]; + + Dmsg0(50, "list_result starts\n"); + if (mdb->result == NULL || sql_num_rows(mdb) == 0) { + send(ctx, _("No results to list.\n")); + return; + } + + Dmsg1(50, "list_result starts looking at %d fields\n", sql_num_fields(mdb)); + /* determine column display widths */ + sql_field_seek(mdb, 0); + for (i = 0; i < sql_num_fields(mdb); i++) { + Dmsg1(50, "list_result processing field %d\n", i); + field = sql_fetch_field(mdb); + col_len = strlen(field->name); + if (type == VERT_LIST) { + if (col_len > max_len) { + max_len = col_len; + } + } else { + if (IS_NUM(field->type) && field->max_length > 0) { /* fixup for commas */ + field->max_length += (field->max_length - 1) / 3; + } + if (col_len < field->max_length) { + col_len = field->max_length; + } + if (col_len < 4 && !IS_NOT_NULL(field->flags)) { + col_len = 4; /* 4 = length of the word "NULL" */ + } + field->max_length = col_len; /* reset column info */ + } + } + + Dmsg0(50, "list_result finished first loop\n"); + if (type == VERT_LIST) { + goto vertical_list; + } + + Dmsg1(50, "list_result starts second loop looking at %d fields\n", sql_num_fields(mdb)); + list_dashes(mdb, send, ctx); + send(ctx, "|"); + sql_field_seek(mdb, 0); + for (i = 0; i < sql_num_fields(mdb); i++) { + Dmsg1(50, "list_result looking at field %d\n", i); + field = sql_fetch_field(mdb); + bsnprintf(buf, sizeof(buf), " %-*s |", field->max_length, field->name); + send(ctx, buf); + } + send(ctx, "\n"); + list_dashes(mdb, send, ctx); + + Dmsg1(50, "list_result starts third loop looking at %d fields\n", sql_num_fields(mdb)); + while ((row = sql_fetch_row(mdb)) != NULL) { + sql_field_seek(mdb, 0); + send(ctx, "|"); + for (i = 0; i < sql_num_fields(mdb); i++) { + field = sql_fetch_field(mdb); + if (row[i] == NULL) { + bsnprintf(buf, sizeof(buf), " %-*s |", field->max_length, "NULL"); + } else if (IS_NUM(field->type)) { + bsnprintf(buf, sizeof(buf), " %*s |", field->max_length, + add_commas(row[i], ewc)); + } else { + bsnprintf(buf, sizeof(buf), " %-*s |", field->max_length, row[i]); + } + send(ctx, buf); + } + send(ctx, "\n"); + } + list_dashes(mdb, send, ctx); + return; + +vertical_list: + + Dmsg1(50, "list_result starts vertical list at %d fields\n", sql_num_fields(mdb)); + while ((row = sql_fetch_row(mdb)) != NULL) { + sql_field_seek(mdb, 0); + for (i = 0; i < sql_num_fields(mdb); i++) { + field = sql_fetch_field(mdb); + if (row[i] == NULL) { + bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL"); + } else if (IS_NUM(field->type)) { + bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, + add_commas(row[i], ewc)); + } else { + bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]); + } + send(ctx, buf); + } + send(ctx, "\n"); + } + return; +} + + #endif /* HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */ diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 52b9c6b6ff..d595a18909 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -231,7 +231,7 @@ int db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) { int stat; - char ed1[30], ed2[30], ed3[30], ed4[30], ed5[30]; + char ed1[30], ed2[30], ed3[30], ed4[30], ed5[30], ed6[50], ed7[50]; struct tm tm; db_lock(mdb); @@ -259,8 +259,8 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) Mmsg(&mdb->cmd, "INSERT INTO Media (VolumeName,MediaType,PoolId,MaxVolBytes,VolCapacityBytes," "Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," -"VolStatus,Slot,VolBytes,Drive,InChanger) " -"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%d)", +"VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime) " +"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s)", mr->VolumeName, mr->MediaType, mr->PoolId, edit_uint64(mr->MaxVolBytes,ed1), @@ -273,8 +273,10 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) mr->VolStatus, mr->Slot, edit_uint64(mr->VolBytes, ed5), - mr->Drive, - mr->InChanger); + mr->InChanger, + edit_uint64(mr->VolReadTime, ed6), + edit_uint64(mr->VolWriteTime, ed7)); + Dmsg1(500, "Create Volume: %s\n", mdb->cmd); if (!INSERT_DB(jcr, mdb, mdb->cmd)) { diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index 4f00fd88ec..c48e0940bd 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -119,7 +119,7 @@ db_update_job_start_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) * */ void edit_num_or_null(char *s, size_t n, uint32_t id) { - bsnprintf(s, n, id ? "%u" : "NULL", id); + bsnprintf(s, n, id ? "%u" : "NULL", id); } @@ -138,13 +138,13 @@ db_update_job_end_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) int stat; char ed1[30], ed2[30]; btime_t JobTDate; - char PoolId [50]; + char PoolId [50]; char FileSetId [50]; char ClientId [50]; /* some values are set to zero, which translates to NULL in SQL */ - edit_num_or_null(PoolId, sizeof(PoolId), jr->PoolId); + edit_num_or_null(PoolId, sizeof(PoolId), jr->PoolId); edit_num_or_null(FileSetId, sizeof(FileSetId), jr->FileSetId); edit_num_or_null(ClientId, sizeof(ClientId), jr->ClientId); @@ -260,7 +260,7 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) time_t ttime; struct tm tm; int stat; - char ed1[30], ed2[30]; + char ed1[30], ed2[30], ed3[30], ed4[30]; Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten); @@ -299,11 +299,16 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) Mmsg(&mdb->cmd, "UPDATE Media SET VolJobs=%u," "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u," "VolWrites=%u,MaxVolBytes=%s,LastWritten='%s',VolStatus='%s'," - "Slot=%d,Drive=%d,InChanger=%d WHERE VolumeName='%s'", + "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s " + " WHERE VolumeName='%s'", mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), mr->VolMounts, mr->VolErrors, mr->VolWrites, edit_uint64(mr->MaxVolBytes, ed2), dt, - mr->VolStatus, mr->Slot, mr->Drive, mr->InChanger, mr->VolumeName); + mr->VolStatus, mr->Slot, mr->InChanger, + edit_uint64(mr->VolReadTime, ed3), + edit_uint64(mr->VolWriteTime, ed4), + mr->VolumeName); + Dmsg1(400, "%s\n", mdb->cmd); diff --git a/bacula/src/cats/sqlite.c b/bacula/src/cats/sqlite.c index 754ae33855..92e7338ba2 100644 --- a/bacula/src/cats/sqlite.c +++ b/bacula/src/cats/sqlite.c @@ -329,7 +329,7 @@ SQL_ROW my_sqlite_fetch_row(B_DB *mdb) void my_sqlite_free_table(B_DB *mdb) { - unsigned int i; + int i; if (mdb->fields_defined) { for (i=0; i < sql_num_fields(mdb); i++) { @@ -344,7 +344,7 @@ void my_sqlite_free_table(B_DB *mdb) void my_sqlite_field_seek(B_DB *mdb, int field) { - unsigned int i, j; + int i, j; if (mdb->result == NULL) { return; } @@ -356,8 +356,8 @@ void my_sqlite_field_seek(B_DB *mdb, int field) mdb->fields[i]->name = mdb->result[i]; mdb->fields[i]->length = strlen(mdb->fields[i]->name); mdb->fields[i]->max_length = mdb->fields[i]->length; - for (j=1; j <= (unsigned)mdb->nrow; j++) { - uint32_t len; + for (j=1; j <= mdb->nrow; j++) { + int len; if (mdb->result[i + mdb->ncolumn *j]) { len = (uint32_t)strlen(mdb->result[i + mdb->ncolumn * j]); } else { @@ -372,8 +372,8 @@ void my_sqlite_field_seek(B_DB *mdb, int field) } mdb->fields_defined = TRUE; } - if (field > (int)sql_num_fields(mdb)) { - field = (int)sql_num_fields(mdb); + if (field > sql_num_fields(mdb)) { + field = sql_num_fields(mdb); } mdb->field = field; @@ -384,117 +384,6 @@ SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb) return mdb->fields[mdb->field++]; } -static void -list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx) -{ - SQL_FIELD *field; - unsigned int i, j; - - sql_field_seek(mdb, 0); - send(ctx, "+"); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - for (j = 0; j < field->max_length + 2; j++) - send(ctx, "-"); - send(ctx, "+"); - } - send(ctx, "\n"); -} - -/* - * If full_list is set, we list vertically, otherwise, we - * list on one line horizontally. - */ -void -list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type) -{ - SQL_FIELD *field; - SQL_ROW row; - unsigned int i, col_len, max_len = 0; - char buf[2000], ewc[30]; - - if (mdb->result == NULL || mdb->nrow == 0) { - send(ctx, _("No results to list.\n")); - return; - } - /* determine column display widths */ - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - col_len = strlen(field->name); - if (type == VERT_LIST) { - if (col_len > max_len) { - max_len = col_len; - } - } else { - if (IS_NUM(field->type) && field->max_length > 0) { /* fixup for commas */ - field->max_length += (field->max_length - 1) / 3; - } - if (col_len < field->max_length) { - col_len = field->max_length; - } - if (col_len < 4 && !IS_NOT_NULL(field->flags)) { - col_len = 4; /* 4 = length of the word "NULL" */ - } - field->max_length = col_len; /* reset column info */ - } - } - - if (type == VERT_LIST) { - goto vertical_list; - } - - list_dashes(mdb, send, ctx); - send(ctx, "|"); - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, field->name); - send(ctx, buf); - } - send(ctx, "\n"); - list_dashes(mdb, send, ctx); - - while ((row = sql_fetch_row(mdb)) != NULL) { - sql_field_seek(mdb, 0); - send(ctx, "|"); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - if (row[i] == NULL) { - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, "NULL"); - } else if (IS_NUM(field->type)) { - bsnprintf(buf, sizeof(buf), " %*s |", (int)field->max_length, - add_commas(row[i], ewc)); - } else { - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, row[i]); - } - send(ctx, buf); - } - send(ctx, "\n"); - } - list_dashes(mdb, send, ctx); - return; - -vertical_list: - - while ((row = sql_fetch_row(mdb)) != NULL) { - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - if (row[i] == NULL) { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL"); - } else if (IS_NUM(field->type)) { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, - add_commas(row[i], ewc)); - } else { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]); - } - send(ctx, buf); - } - send(ctx, "\n"); - } - return; -} #endif /* HAVE_SQLITE */ diff --git a/bacula/src/cats/update_mysql_tables.in b/bacula/src/cats/update_mysql_tables.in index f2934a36d0..7767308c52 100755 --- a/bacula/src/cats/update_mysql_tables.in +++ b/bacula/src/cats/update_mysql_tables.in @@ -11,9 +11,10 @@ bindir=@SQL_BINDIR@ if $bindir/mysql $* -f <MediaId = mr->MediaId; pm_strcpy(&jcr->VolumeName, mr->VolumeName); @@ -77,9 +78,11 @@ static int send_volume_info_to_storage_daemon(JCR *jcr, BSOCK *sd, MEDIA_DBR *mr edit_uint64(mr->MaxVolBytes, ed2), edit_uint64(mr->VolCapacityBytes, ed3), mr->VolStatus, mr->Slot, mr->MaxVolJobs, mr->MaxVolFiles, - mr->Drive, mr->InChanger); + mr->InChanger, + edit_uint64(mr->VolReadTime, ed4), + edit_uint64(mr->VolWriteTime, ed5)); unbash_spaces(mr->VolumeName); - Dmsg2(100, "Vol Info for %s: %s", jcr->Job, sd->msg); + Dmsg2(200, "Vol Info for %s: %s", jcr->Job, sd->msg); return stat; } @@ -179,7 +182,8 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) } else if (sscanf(bs->msg, Update_media, &Job, &sdmr.VolumeName, &sdmr.VolJobs, &sdmr.VolFiles, &sdmr.VolBlocks, &sdmr.VolBytes, &sdmr.VolMounts, &sdmr.VolErrors, &sdmr.VolWrites, &sdmr.MaxVolBytes, &sdmr.LastWritten, &sdmr.VolStatus, - &sdmr.Slot, &label, &sdmr.Drive, &sdmr.InChanger) == 16) { + &sdmr.Slot, &label, &sdmr.InChanger, &sdmr.VolReadTime, + &sdmr.VolWriteTime) == 17) { db_lock(jcr->db); Dmsg3(100, "Update media %s oldStat=%s newStat=%s\n", sdmr.VolumeName, @@ -204,17 +208,18 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) } Dmsg2(100, "Update media: BefVolJobs=%u After=%u\n", mr.VolJobs, sdmr.VolJobs); /* Copy updated values to original media record */ - mr.VolJobs = sdmr.VolJobs; - mr.VolFiles = sdmr.VolFiles; - mr.VolBlocks = sdmr.VolBlocks; - mr.VolBytes = sdmr.VolBytes; - mr.VolMounts = sdmr.VolMounts; - mr.VolErrors = sdmr.VolErrors; - mr.VolWrites = sdmr.VolWrites; - mr.LastWritten = sdmr.LastWritten; - mr.Slot = sdmr.Slot; - mr.Drive = sdmr.Drive; - mr.InChanger = sdmr.InChanger; + mr.VolJobs = sdmr.VolJobs; + mr.VolFiles = sdmr.VolFiles; + mr.VolBlocks = sdmr.VolBlocks; + mr.VolBytes = sdmr.VolBytes; + mr.VolMounts = sdmr.VolMounts; + mr.VolErrors = sdmr.VolErrors; + mr.VolWrites = sdmr.VolWrites; + mr.LastWritten = sdmr.LastWritten; + mr.Slot = sdmr.Slot; + mr.InChanger = sdmr.InChanger; + mr.VolReadTime = sdmr.VolReadTime; + mr.VolWriteTime = sdmr.VolWriteTime; bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus)); Dmsg2(100, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName); diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 1307a09751..027b3f75aa 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -35,7 +35,7 @@ static char Get_Vol_Info[] = "CatReq Job=%s GetVolInfo VolName=%s write=%d\n"; static char Update_media[] = "CatReq Job=%s UpdateMedia VolName=%s" " VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%s VolMounts=%u" " VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%d VolStatus=%s" - " Slot=%d relabel=%d Drive=%d InChanger=%d\n"; + " Slot=%d relabel=%d InChanger=%d VolReadTime=%s VolWriteTime=%s\n"; static char Create_job_media[] = "CatReq Job=%s CreateJobMedia" " FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u" " StartBlock=%u EndBlock=%u\n"; @@ -47,7 +47,9 @@ static char Job_status[] = "3012 Job %s jobstatus %d\n"; static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%u" " VolBlocks=%u VolBytes=%" lld " VolMounts=%u VolErrors=%u VolWrites=%u" " MaxVolBytes=%" lld " VolCapacityBytes=%" lld " VolStatus=%20s" - " Slot=%d MaxVolJobs=%u MaxVolFiles=%u Drive=%d InChanger=%d"; + " Slot=%d MaxVolJobs=%u MaxVolFiles=%u InChanger=%d" + " VolReadTime=%" lld " VolWriteTime=%" lld; + static char OK_create[] = "1000 OK CreateJobMedia\n"; @@ -75,6 +77,7 @@ static int do_get_volume_info(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; VOLUME_CAT_INFO vol; + int n; jcr->VolumeName[0] = 0; /* No volume */ if (bnet_recv(dir) <= 0) { @@ -83,16 +86,17 @@ static int do_get_volume_info(JCR *jcr) return 0; } memset(&vol, 0, sizeof(vol)); - if (sscanf(dir->msg, OK_media, vol.VolCatName, + Dmsg1(200, "Get vol info=%s\n", dir->msg); + n = sscanf(dir->msg, OK_media, vol.VolCatName, &vol.VolCatJobs, &vol.VolCatFiles, &vol.VolCatBlocks, &vol.VolCatBytes, &vol.VolCatMounts, &vol.VolCatErrors, &vol.VolCatWrites, &vol.VolCatMaxBytes, &vol.VolCatCapacityBytes, vol.VolCatStatus, &vol.Slot, &vol.VolCatMaxJobs, &vol.VolCatMaxFiles, - &vol.Drive, &vol.InChanger) != 16) { - - Dmsg1(200, "Bad response from Dir: %s\n", dir->msg); + &vol.InChanger, &vol.VolReadTime, &vol.VolWriteTime); + if (n != 17) { + Dmsg2(100, "Bad response from Dir fields=%d: %s\n", n, dir->msg); Mmsg(&jcr->errmsg, _("Error getting Volume info: %s\n"), dir->msg); return 0; } @@ -156,7 +160,7 @@ int dir_update_volume_info(JCR *jcr, DEVICE *dev, int label) { BSOCK *dir = jcr->dir_bsock; time_t EndTime = time(NULL); - char ed1[50], ed2[50]; + char ed1[50], ed2[50], ed3[50], ed4[50]; VOLUME_CAT_INFO *vol = &dev->VolCatInfo; if (vol->VolCatName[0] == 0) { @@ -184,8 +188,11 @@ int dir_update_volume_info(JCR *jcr, DEVICE *dev, int label) vol->VolCatBlocks, edit_uint64(vol->VolCatBytes, ed1), vol->VolCatMounts, vol->VolCatErrors, vol->VolCatWrites, edit_uint64(vol->VolCatMaxBytes, ed2), - EndTime, vol->VolCatStatus, vol->Slot, label, vol->Drive, - vol->InChanger); + EndTime, vol->VolCatStatus, vol->Slot, label, + vol->InChanger, + edit_uint64(vol->VolReadTime, ed3), + edit_uint64(vol->VolWriteTime, ed4) ); + Dmsg1(120, "update_volume_info(): %s", dir->msg); unbash_spaces(vol->VolCatName); diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 3f27bd8170..32d717f0ae 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -127,12 +127,13 @@ struct VOLUME_CAT_INFO { uint64_t VolCatRBytes; /* Number of bytes read */ uint32_t VolCatRecycles; /* Number of recycles this volume */ int32_t Slot; /* Slot in changer */ - int32_t Drive; /* Changer drive */ bool InChanger; /* Set if vol in current magazine */ uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */ uint32_t VolCatMaxFiles; /* Maximum files to write to volume */ uint64_t VolCatMaxBytes; /* Max bytes to write to volume */ uint64_t VolCatCapacityBytes; /* capacity estimate */ + uint64_t VolReadTime; /* time spent reading */ + uint64_t VolWriteTime; /* time spent writing this Volume */ char VolCatStatus[20]; /* Volume status */ char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */ }; diff --git a/bacula/src/version.h b/bacula/src/version.h index 3f0b5ba510..b821f338d5 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -2,8 +2,8 @@ #undef VERSION #define VERSION "1.33" #define VSTRING "1" -#define BDATE "18 Dec 2003" -#define LSMDATE "18Dec03" +#define BDATE "20 Dec 2003" +#define LSMDATE "20Dec03" /* Debug flags */ #undef DEBUG