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
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
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 \
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
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
"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" ;;
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
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;
#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
#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
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;
* 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;
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 */
#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
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;
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 */
};
+
#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_ */
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)
);
create table version
(
- versionid integer not null
+ versionid integer not null
);
INSERT INTO Version (VersionId) VALUES (7);
create table counters
(
- counter text not null,
- minvalue integer ,
- maxvalue integer ,
- currentvalue integer ,
- wrapcounter text not null,
+ counter text not null,
+ minvalue integer ,
+ maxvalue integer ,
+ currentvalue integer ,
+ wrapcounter text not null,
primary key (counter)
);
create table filename
(
- filenameid serial not null,
- name text not null,
+ filenameid serial not null,
+ name text not null,
primary key (filenameid)
);
create table path
(
- pathid serial not null,
- path text not null,
+ pathid serial not null,
+ path text not null,
primary key (pathid)
);
create table fileset
(
- filesetid serial not null,
- fileset text not null,
- md5 text not null,
- createtime timestamp without time zone not null,
+ filesetid serial not null,
+ fileset text not null,
+ md5 text not null,
+ createtime timestamp without time zone not null,
primary key (filesetid)
);
create table pool
(
- poolid serial not null,
- name text not null,
- numvols integer not null
- default 0,
- maxvols integer not null
- default 0,
- useonce smallint not null,
- usecatalog smallint not null,
- acceptanyvolume smallint
- default 0,
- volretention bigint not null,
- voluseduration bigint not null,
- maxvoljobs integer not null
- default 0,
- maxvolfiles integer not null
- default 0,
- maxvolbytes bigint not null,
- autoprune smallint not null
- default 0,
- recycle smallint
- default 0,
- pooltype text
- check (pooltype is null or (pooltype in ('Backup','Copy','Cloned','Archive','Migration'))),
- labelformat text not null,
- enabled smallint not null
- default 1,
- scratchpoolid integer ,
- recyclepoolid integer ,
+ poolid serial not null,
+ name text not null,
+ numvols integer not null
+ default 0,
+ maxvols integer not null
+ default 0,
+ useonce smallint not null,
+ usecatalog smallint not null,
+ acceptanyvolume smallint
+ default 0,
+ volretention bigint not null,
+ voluseduration bigint not null,
+ maxvoljobs integer not null
+ default 0,
+ maxvolfiles integer not null
+ default 0,
+ maxvolbytes bigint not null,
+ autoprune smallint not null
+ default 0,
+ recycle smallint
+ default 0,
+ pooltype text
+ check (pooltype is null or (pooltype in ('Backup','Copy','Cloned','Archive','Migration'))),
+ labelformat text not null,
+ enabled smallint not null
+ default 1,
+ scratchpoolid integer ,
+ recyclepoolid integer ,
primary key (poolid)
);
create table client
(
- clientid serial not null,
- name text not null,
- uname text not null,
- autoprune smallint
- default 0,
- fileretention bigint not null,
- jobretention bigint not null,
+ clientid serial not null,
+ name text not null,
+ uname text not null,
+ autoprune smallint
+ default 0,
+ fileretention bigint not null,
+ jobretention bigint not null,
primary key (clientid)
);
create table media
(
- mediaid serial not null,
- volumename text not null,
- slot integer not null
- default 0,
- poolid integer not null,
- mediatype text not null,
+ mediaid serial not null,
+ volumename text not null,
+ slot integer not null
+ default 0,
+ poolid integer not null,
+ mediatype text not null,
firstwritten timestamp without time zone not null
- default current_timestamp,
+ default current_timestamp,
lastwritten timestamp without time zone not null
- default current_timestamp,
- labeldate timestamp without time zone not null
+ default current_timestamp,
+ labeldate timestamp without time zone not null
default current_timestamp,
- voljobs integer not null
- default 0,
- volfiles integer not null
- default 0,
- volblocks integer not null
- default 0,
- volmounts integer not null
- default 0,
- volbytes bigint not null
- default 0,
- volerrors integer not null
- default 0,
- volwrites integer not null
- default 0,
- volcapacitybytes bigint not null,
- volstatus text not null
- check (volstatus in ('Full','Archive','Append','Recycle','Purged','Read-Only','Disabled','Error','Busy',
- 'Used','Cleaning')),
- recycle smallint not null
- default 0,
- volretention bigint not null
- default 0,
- voluseduration bigint not null
- default 0,
- maxvoljobs integer not null
- default 0,
- maxvolfiles integer not null
- default 0,
- maxvolbytes bigint not null
- default 0,
- drive integer not null
- default 0,
- inchanger smallint not null
- default 0,
- mediaaddressing smallint not null
- default 0,
+ voljobs integer not null
+ default 0,
+ volfiles integer not null
+ default 0,
+ volblocks integer not null
+ default 0,
+ volmounts integer not null
+ default 0,
+ volbytes bigint not null
+ default 0,
+ volerrors integer not null
+ default 0,
+ volwrites integer not null
+ default 0,
+ volcapacitybytes bigint not null,
+ volstatus text not null
+ check (volstatus in ('Full','Archive','Append','Recycle','Purged','Read-Only','Disabled','Error','Busy',
+ 'Used','Cleaning')),
+ recycle smallint not null
+ default 0,
+ volretention bigint not null
+ default 0,
+ voluseduration bigint not null
+ default 0,
+ maxvoljobs integer not null
+ default 0,
+ maxvolfiles integer not null
+ default 0,
+ maxvolbytes bigint not null
+ default 0,
+ inchanger smallint not null
+ default 0,
+ mediaaddressing smallint not null
+ default 0,
+ volreadtime bigint not null
+ default 0,
+ volwritetime bigint not null
+ default 0,
primary key (mediaid)
);
create table job
(
- jobid serial not null,
- job text not null,
- name text not null,
- type char(1) not null,
- level char(1) not null,
- clientid integer ,
- jobstatus char(1) not null,
- schedtime timestamp without time zone not null,
- starttime timestamp without time zone ,
- endtime timestamp without time zone ,
- jobtdate bigint not null,
- volsessionid integer not null
- default 0,
- volsessiontime integer not null
- default 0,
- jobfiles integer not null
+ jobid serial not null,
+ job text not null,
+ name text not null,
+ type char(1) not null,
+ level char(1) not null,
+ clientid integer ,
+ jobstatus char(1) not null,
+ schedtime timestamp without time zone not null,
+ starttime timestamp without time zone ,
+ endtime timestamp without time zone ,
+ jobtdate bigint not null,
+ volsessionid integer not null
+ default 0,
+ volsessiontime integer not null
+ default 0,
+ jobfiles integer not null
default 0,
- jobbytes bigint not null
- default 0,
- joberrors integer not null
- default 0,
- jobmissingfiles integer not null
- default 0,
- poolid integer ,
- filesetid integer ,
- purgedfiles smallint not null
- default 0,
- hasbase smallint not null
- default 0,
+ jobbytes bigint not null
+ default 0,
+ joberrors integer not null
+ default 0,
+ jobmissingfiles integer not null
+ default 0,
+ poolid integer ,
+ filesetid integer ,
+ purgedfiles smallint not null
+ default 0,
+ hasbase smallint not null
+ default 0,
primary key (jobid)
);
create table file
(
- fileid serial not null,
- fileindex integer not null
- default 0,
- jobid integer not null,
- pathid integer not null,
- filenameid bigint not null,
- markid integer not null
- default 0,
- lstat text not null,
- md5 text not null,
+ fileid serial not null,
+ fileindex integer not null
+ default 0,
+ jobid integer not null,
+ pathid integer not null,
+ filenameid bigint not null,
+ markid integer not null
+ default 0,
+ lstat text not null,
+ md5 text not null,
primary key (fileid)
);
create table jobmedia
(
- jobmediaid serial not null,
- jobid integer not null,
- mediaid integer not null,
- firstindex integer not null
- default 0,
- lastindex integer not null
- default 0,
- startfile integer not null
- default 0,
- endfile integer not null
- default 0,
- startblock integer not null
- default 0,
- endblock integer not null
- default 0,
- volindex integer not null
- default 0,
+ jobmediaid serial not null,
+ jobid integer not null,
+ mediaid integer not null,
+ firstindex integer not null
+ default 0,
+ lastindex integer not null
+ default 0,
+ startfile integer not null
+ default 0,
+ endfile integer not null
+ default 0,
+ startblock integer not null
+ default 0,
+ endblock integer not null
+ default 0,
+ volindex integer not null
+ default 0,
primary key (jobmediaid)
);
create table basefiles
(
- baseid serial not null,
- jobid integer not null,
- fileid integer not null,
- fileindex integer ,
- basejobid integer ,
+ baseid serial not null,
+ jobid integer not null,
+ fileid integer not null,
+ fileindex integer ,
+ basejobid integer ,
primary key (baseid)
);
create table unsavedfiles
(
- UnsavedId integer not null,
- jobid integer not null,
- pathid integer not null,
- filenameid integer not null,
+ UnsavedId integer not null,
+ jobid integer not null,
+ pathid integer not null,
+ filenameid integer not null,
primary key (UnsavedId)
);
MaxVolJobs INTEGER UNSIGNED DEFAULT 0,
MaxVolFiles INTEGER UNSIGNED DEFAULT 0,
MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
- Drive INTEGER DEFAULT 0,
InChanger TINYINT DEFAULT 0,
MediaAddressing TINYINT DEFAULT 0,
+ VolReadTime BIGINT UNSIGNED DEFAULT 0,
+ VolWriteTime BIGINT UNSIGNED DEFAULT 0,
PRIMARY KEY(MediaId)
);
}
-
-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) {
- 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 */
#ifdef HAVE_POSTGRESQL
-#include "postgres_ext.h" /* needed for NAMEDATALEN */
+#include "postgres_ext.h" /* needed for NAMEDATALEN */
/* -----------------------------------------------------------------------
*
}
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);
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 */
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 */
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;
}
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);
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);
}
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);
}
-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;
}
// 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
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
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);
}
}
}
-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.
// 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);
/*
+ *
+ * Database routines that are exported by the cats library for
+ * use elsewhere in Bacula (mainly the Director).
*
* Version $Id$
*/
/* 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);
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;
}
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;
}
}
+/*
+ * 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;
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 */
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);
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),
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)) {
*
*/
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);
}
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);
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);
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);
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++) {
void my_sqlite_field_seek(B_DB *mdb, int field)
{
- unsigned int i, j;
+ int i, j;
if (mdb->result == NULL) {
return;
}
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 {
}
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;
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 */
if $bindir/mysql $* -f <<END-OF-DATA
USE bacula;
-ALTER TABLE Media ADD COLUMN Drive INTEGER NOT NULL DEFAULT 0;
ALTER TABLE Media ADD COLUMN InChanger TINYINT NOT NULL DEFAULT 0;
ALTER TABLE Media ADD COLUMN MediaAddressing TINYINT NOT NULL DEFAULT 0;
+ALTER TABLE Media ADD COLUMN VolReadTime BIGINT UNSIGNED NOT NULL DEFAULT 0;
+ALTER TABLE Media ADD COLUMN VolWriteTime BIGINT UNSIGNED NOT NULL DEFAULT 0;
ALTER TABLE Pool ADD COLUMN Enabled TINYINT DEFAULT 1;
ALTER TABLE Pool ADD COLUMN ScratchPoolId INTEGER UNSIGNED DEFAULT 0 REFERENCES Pool;
MaxVolJobs INTEGER UNSIGNED DEFAULT 0,
MaxVolFiles INTEGER UNSIGNED DEFAULT 0,
MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
- Drive INTEGER DEFAULT 0,
InChanger TINYINT DEFAULT 0,
MediaAddressing TINYINT DEFAULT 0,
+ VolReadTime BIGINT UNSIGNED DEFAULT 0,
+ VolWriteTime BIGINT UNSIGNED DEFAULT 0,
PRIMARY KEY(MediaId)
);
VolMounts, VolBytes, VolErrors, VolWrites,
VolCapacityBytes, VolStatus, Recycle,
VolRetention, VolUseDuration, MaxVolJobs,
- MaxVolFiles, MaxVolBytes, 0, 0, 0
+ MaxVolFiles, MaxVolBytes, 0, 0, 0, 0
FROM Media;
MaxVolJobs INTEGER UNSIGNED DEFAULT 0,
MaxVolFiles INTEGER UNSIGNED DEFAULT 0,
MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
- Drive INTEGER DEFAULT 0,
InChanger TINYINT DEFAULT 0,
MediaAddressing TINYINT DEFAULT 0,
+ VolReadTime BIGINT UNSIGNED DEFAULT 0,
+ VolWriteTime BIGINT UNSIGNED DEFAULT 0,
PRIMARY KEY(MediaId)
);
VolMounts, VolBytes, VolErrors, VolWrites,
VolCapacityBytes, VolStatus, Recycle,
VolRetention, VolUseDuration, MaxVolJobs,
- MaxVolFiles, MaxVolBytes, Drive,
- InChanger, MediaAddressing)
+ MaxVolFiles, MaxVolBytes,
+ InChanger, MediaAddressing,
+ VolReadTime, VolWriteTime,
SELECT * FROM Media_backup;
DROP TABLE Media_backup;
static char Update_media[] = "CatReq Job=%127s UpdateMedia VolName=%s\
VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%" lld " VolMounts=%u\
VolErrors=%u VolWrites=%u MaxVolBytes=%" lld " EndTime=%d VolStatus=%10s\
- Slot=%d relabel=%d Drive=%d InChanger=%d\n";
+ Slot=%d relabel=%d InChanger=%d VolReadTime=%" lld " VolWriteTime=%" lld "\n";
static char Create_job_media[] = "CatReq Job=%127s CreateJobMedia \
FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u \
static char OK_media[] = "1000 OK VolName=%s VolJobs=%u VolFiles=%u"
" VolBlocks=%u VolBytes=%s VolMounts=%u VolErrors=%u VolWrites=%u"
" MaxVolBytes=%s VolCapacityBytes=%s VolStatus=%s Slot=%d"
- " MaxVolJobs=%u MaxVolFiles=%u Drive=%d InChanger=%d\n";
+ " MaxVolJobs=%u MaxVolFiles=%u InChanger=%d VolReadTime=%s"
+ " VolWriteTime=%s\n";
static char OK_create[] = "1000 OK CreateJobMedia\n";
static int send_volume_info_to_storage_daemon(JCR *jcr, BSOCK *sd, MEDIA_DBR *mr)
{
int stat;
- char ed1[50], ed2[50], ed3[50];
+ char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50];
jcr->MediaId = mr->MediaId;
pm_strcpy(&jcr->VolumeName, mr->VolumeName);
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;
}
} 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,
}
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);
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";
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";
{
BSOCK *dir = jcr->dir_bsock;
VOLUME_CAT_INFO vol;
+ int n;
jcr->VolumeName[0] = 0; /* No volume */
if (bnet_recv(dir) <= 0) {
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;
}
{
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) {
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);
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 */
};
#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