From 59b310539e83184635c0a1a91b0872df8bb64647 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 15 Nov 2003 20:25:58 +0000 Subject: [PATCH] Fix Vol info update + add Drive and InChanger to Media rec git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@807 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 7 + bacula/scripts/bacula.in | 77 ++++---- bacula/src/baconfig.h | 2 +- bacula/src/cats/cats.h | 330 ++++++++++++++++---------------- bacula/src/cats/sql_list.c | 8 +- bacula/src/dird/catreq.c | 76 ++++---- bacula/src/dird/ua_output.c | 4 +- bacula/src/lib/alist.h | 4 +- bacula/src/lib/bnet.c | 49 ++++- bacula/src/lib/jcr.c | 3 +- bacula/src/lib/signal.c | 5 +- bacula/src/lib/watchdog.c | 3 + bacula/src/stored/acquire.c | 43 +++-- bacula/src/stored/askdir.c | 75 ++++---- bacula/src/stored/autochanger.c | 13 +- bacula/src/stored/bcopy.c | 2 +- bacula/src/stored/bextract.c | 2 +- bacula/src/stored/block.c | 17 +- bacula/src/stored/bls.c | 2 +- bacula/src/stored/bscan.c | 2 +- bacula/src/stored/btape.c | 2 +- bacula/src/stored/dev.c | 2 +- bacula/src/stored/dev.h | 2 + bacula/src/stored/device.c | 14 +- bacula/src/stored/dircmd.c | 24 +-- bacula/src/stored/label.c | 23 +-- bacula/src/stored/match_bsr.c | 2 +- bacula/src/stored/mount.c | 39 ++-- bacula/src/stored/protos.h | 192 +++++++++---------- bacula/src/stored/stored.c | 101 ++++++---- bacula/src/tools/.cvsignore | 1 + bacula/src/tools/Makefile.in | 4 +- bacula/src/tools/bsmtp.c | 2 +- bacula/src/version.h | 4 +- 34 files changed, 632 insertions(+), 504 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 61ac538623..2dd8c85eb8 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -47,6 +47,13 @@ For 1.33 Testing/Documentation: For 1.33 +- do a "messages" before the first prompt in Console +- Add a date and time stamp at the beginning of every line in the + Job report (Volker Sauer). +- Client does not show busy during Estimate command. +- Volume problems occurs if you have valid volume, written, then it is + truncated. You get 12-Nov-2003 11:48 rufus-sd: kernsave.2003-11-12_11.48.09 Warning: mount.c:228 Volume on /tmp is not a Bacula labeled Volume, because: + block.c:640 Read zero bytes on device /tmp. - Implement Console mtx commands. - Look at 2Gb limit for SQLite. - Implement 3 Pools for a Job: diff --git a/bacula/scripts/bacula.in b/bacula/scripts/bacula.in index 2952141c86..1fbd1a98ee 100755 --- a/bacula/scripts/bacula.in +++ b/bacula/scripts/bacula.in @@ -182,63 +182,64 @@ failure() { case "$1" in start) [ -x ${BACBIN}/bacula-sd ] && { - echo "Starting the Storage daemon" - OPTIONS='' - if [ "${SD_USER}" != '' ]; then - OPTIONS="${OPTIONS} -u ${SD_USER}" - fi + echo "Starting the Storage daemon" + OPTIONS='' + if [ "${SD_USER}" != '' ]; then + OPTIONS="${OPTIONS} -u ${SD_USER}" + fi - if [ "${SD_GROUP}" != '' ]; then - OPTIONS="${OPTIONS} -g ${SD_GROUP}" - fi + if [ "${SD_GROUP}" != '' ]; then + OPTIONS="${OPTIONS} -g ${SD_GROUP}" + fi - ${BACBIN}/bacula-sd $2 ${OPTIONS} -v -c ${BACCFG}/bacula-sd.conf + ${BACBIN}/bacula-sd $2 ${OPTIONS} -v -c ${BACCFG}/bacula-sd.conf } [ -x ${BACBIN}/bacula-fd ] && { - echo "Starting the File daemon" - OPTIONS='' - if [ "${FD_USER}" != '' ]; then - OPTIONS="${OPTIONS} -u ${FD_USER}" - fi + echo "Starting the File daemon" + OPTIONS='' + if [ "${FD_USER}" != '' ]; then + OPTIONS="${OPTIONS} -u ${FD_USER}" + fi - if [ "${FD_GROUP}" != '' ]; then - OPTIONS="${OPTIONS} -g ${FD_GROUP}" - fi + if [ "${FD_GROUP}" != '' ]; then + OPTIONS="${OPTIONS} -g ${FD_GROUP}" + fi - ${BACBIN}/bacula-fd $2 ${OPTIONS} -v -c ${BACCFG}/bacula-fd.conf + ${BACBIN}/bacula-fd $2 ${OPTIONS} -v -c ${BACCFG}/bacula-fd.conf } [ -x ${BACBIN}/bacula-dir ] && { - sleep 2 - echo "Starting the Director daemon" - OPTIONS='' - if [ "${DIR_USER}" != '' ]; then - OPTIONS="${OPTIONS} -u ${DIR_USER}" - fi - - if [ "${DIR_GROUP}" != '' ]; then - OPTIONS="${OPTIONS} -g ${DIR_GROUP}" - fi - - ${BACBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACCFG}/bacula-dir.conf + sleep 2 + echo "Starting the Director daemon" + OPTIONS='' + if [ "${DIR_USER}" != '' ]; then + OPTIONS="${OPTIONS} -u ${DIR_USER}" + fi + + if [ "${DIR_GROUP}" != '' ]; then + OPTIONS="${OPTIONS} -g ${DIR_GROUP}" + fi + + ${BACBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACCFG}/bacula-dir.conf } ;; stop) - [ -x ${BACBIN}/bacula-sd ] && { - echo "Stopping the Storage daemon" - killproc ${BACBIN}/bacula-sd ${SD_PORT} + # Stop the FD first so that SD will fail jobs and update catalog + [ -x ${BACBIN}/bacula-fd ] && { + echo "Stopping the File daemon" + killproc ${BACBIN}/bacula-fd ${FD_PORT} } - [ -x ${BACBIN}/bacula-fd ] && { - echo "Stopping the File daemon" - killproc ${BACBIN}/bacula-fd ${FD_PORT} + [ -x ${BACBIN}/bacula-sd ] && { + echo "Stopping the Storage daemon" + killproc ${BACBIN}/bacula-sd ${SD_PORT} } [ -x ${BACBIN}/bacula-dir ] && { - echo "Stopping the Director daemon" - killproc ${BACBIN}/bacula-dir ${DIR_PORT} + echo "Stopping the Director daemon" + killproc ${BACBIN}/bacula-dir ${DIR_PORT} } echo ;; diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index 123f0128ef..b9c6cd9719 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -434,7 +434,7 @@ extern int thr_setconcurrency(int); #ifdef HAVE_DARWIN_OS /* Apparently someone forgot to wrap getdomainname as a C function */ -extern "C" int getdomainname(char *name, size_t len); +extern "C" int getdomainname(char *name, int len); /* Darwin lib fnmatch() doesn't work, so use our own */ #undef HAVE_FNMATCH diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index f4746db3c8..62eedfc3a1 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -57,70 +57,70 @@ struct sqlite { char dummy; }; -#define IS_NUM(x) ((x) == 1) -#define IS_NOT_NULL(x) ((x) == 1) +#define IS_NUM(x) ((x) == 1) +#define IS_NOT_NULL(x) ((x) == 1) typedef struct s_sql_field { - char *name; /* name of column */ - uint32_t length; /* length */ - uint32_t max_length; /* max length */ - uint32_t type; /* type */ - uint32_t flags; /* flags */ + char *name; /* name of column */ + uint32_t length; /* length */ + uint32_t max_length; /* max length */ + uint32_t type; /* type */ + uint32_t flags; /* flags */ } SQL_FIELD; /* * This is the "real" definition that should only be * used inside sql.c and associated database interface * subroutines. - * S Q L I T E + * S Q L I T E */ typedef struct s_db { - BQUEUE bq; /* queue control */ - brwlock_t lock; /* transaction lock */ + BQUEUE bq; /* queue control */ + brwlock_t lock; /* transaction lock */ struct sqlite *db; char **result; - int nrow; /* nrow returned from sqlite */ - int ncolumn; /* ncolum returned from sqlite */ - int num_rows; /* used by code */ - int row; /* seek row */ - int have_insert_id; /* do not have insert id */ - int fields_defined; /* set when fields defined */ - int field; /* seek field */ - SQL_FIELD **fields; /* defined fields */ + int nrow; /* nrow returned from sqlite */ + int ncolumn; /* ncolum returned from sqlite */ + int num_rows; /* used by code */ + int row; /* seek row */ + int have_insert_id; /* do not have insert id */ + int fields_defined; /* set when fields defined */ + int field; /* seek field */ + SQL_FIELD **fields; /* defined fields */ int ref_count; char *db_name; char *db_user; - char *db_address; /* host name address */ - char *db_socket; /* socket for local access */ + char *db_address; /* host name address */ + char *db_socket; /* socket for local access */ char *db_password; - int db_port; /* port for host name address */ + int db_port; /* port for host name address */ int connected; - char *sqlite_errmsg; /* error message returned by sqlite */ - POOLMEM *errmsg; /* nicely edited error message */ - POOLMEM *cmd; /* SQL command string */ - POOLMEM *cached_path; /* cached path name */ - int cached_path_len; /* length of cached path */ - uint32_t cached_path_id; /* cached path id */ - int transaction; /* transaction started */ - int changes; /* changes during transaction */ - 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 */ + char *sqlite_errmsg; /* error message returned by sqlite */ + POOLMEM *errmsg; /* nicely edited error message */ + POOLMEM *cmd; /* SQL command string */ + POOLMEM *cached_path; /* cached path name */ + int cached_path_len; /* length of cached path */ + uint32_t cached_path_id; /* cached path id */ + int transaction; /* transaction started */ + int changes; /* changes during transaction */ + 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; /* * "Generic" names for easier conversion * - * S Q L I T E + * S Q L I T E */ #define sql_store_result(x) x->result #define sql_free_result(x) my_sqlite_free_table(x) #define sql_fetch_row(x) my_sqlite_fetch_row(x) #define sql_query(x, y) my_sqlite_query(x, y) -#define sql_close(x) sqlite_close((x)->db) +#define sql_close(x) sqlite_close((x)->db) #define sql_strerror(x) (x)->sqlite_errmsg?(x)->sqlite_errmsg:"unknown" #define sql_num_rows(x) (x)->nrow #define sql_data_seek(x, i) (x)->row = i @@ -129,7 +129,7 @@ typedef struct s_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_ROW char** +#define SQL_ROW char** @@ -151,11 +151,11 @@ extern void my_sqlite_free_table(B_DB *mdb); * used inside sql.c and associated database interface * subroutines. * - * M Y S Q L + * M Y 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 */ MYSQL mysql; MYSQL *db; MYSQL_RES *result; @@ -164,22 +164,22 @@ 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; @@ -188,7 +188,7 @@ typedef struct s_db { #define sql_free_result(x) mysql_free_result((x)->result) #define sql_fetch_row(x) mysql_fetch_row((x)->result) #define sql_query(x, y) mysql_query((x)->db, y) -#define sql_close(x) mysql_close((x)->db) +#define sql_close(x) mysql_close((x)->db) #define sql_strerror(x) mysql_error((x)->db) #define sql_num_rows(x) mysql_num_rows((x)->result) #define sql_data_seek(x, i) mysql_data_seek((x)->result, i) @@ -197,8 +197,8 @@ typedef struct s_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_ROW MYSQL_ROW -#define SQL_FIELD MYSQL_FIELD +#define SQL_ROW MYSQL_ROW +#define SQL_FIELD MYSQL_FIELD #else /* USE BACULA DB routines */ @@ -207,17 +207,17 @@ typedef struct s_db { /* Change this each time there is some incompatible * file format change!!!! */ -#define BDB_VERSION 12 /* file version number */ +#define BDB_VERSION 12 /* file version number */ struct s_control { - int bdb_version; /* Version number */ - uint32_t JobId; /* next Job Id */ - uint32_t PoolId; /* next Pool Id */ - uint32_t MediaId; /* next Media Id */ - uint32_t JobMediaId; /* next JobMedia Id */ - uint32_t ClientId; /* next Client Id */ - uint32_t FileSetId; /* nest FileSet Id */ - time_t time; /* time file written */ + int bdb_version; /* Version number */ + uint32_t JobId; /* next Job Id */ + uint32_t PoolId; /* next Pool Id */ + uint32_t MediaId; /* next Media Id */ + uint32_t JobMediaId; /* next JobMedia Id */ + uint32_t ClientId; /* next Client Id */ + uint32_t FileSetId; /* nest FileSet Id */ + time_t time; /* time file written */ }; @@ -225,23 +225,23 @@ struct s_control { * Bacula internal DB */ typedef struct s_db { - BQUEUE bq; /* queue control */ -/* pthread_mutex_t mutex; */ /* single thread lock */ - brwlock_t lock; /* transaction lock */ - int ref_count; /* number of times opened */ - struct s_control control; /* control file structure */ - int cfd; /* control file device */ - FILE *jobfd; /* Jobs records file descriptor */ - FILE *poolfd; /* Pool records fd */ - FILE *mediafd; /* Media records fd */ - FILE *jobmediafd; /* JobMedia records fd */ - FILE *clientfd; /* Client records fd */ - FILE *filesetfd; /* FileSet records fd */ - char *db_name; /* name of database */ - POOLMEM *errmsg; /* nicely edited error message */ - POOLMEM *cmd; /* Command string */ + BQUEUE bq; /* queue control */ +/* pthread_mutex_t mutex; */ /* single thread lock */ + brwlock_t lock; /* transaction lock */ + int ref_count; /* number of times opened */ + struct s_control control; /* control file structure */ + int cfd; /* control file device */ + FILE *jobfd; /* Jobs records file descriptor */ + FILE *poolfd; /* Pool records fd */ + FILE *mediafd; /* Media records fd */ + FILE *jobmediafd; /* JobMedia records fd */ + FILE *clientfd; /* Client records fd */ + FILE *filesetfd; /* FileSet records fd */ + char *db_name; /* name of database */ + POOLMEM *errmsg; /* nicely edited error message */ + POOLMEM *cmd; /* 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; } B_DB; @@ -255,12 +255,12 @@ typedef struct s_db { #define DELETE_DB(jcr, db, cmd) DeleteDB(__FILE__, __LINE__, jcr, db, cmd) -#else /* not __SQL_C */ +#else /* not __SQL_C */ /* This is a "dummy" definition for use outside of sql.c */ -typedef struct s_db { - int dummy; /* for SunOS compiler */ +typedef struct s_db { + int dummy; /* for SunOS compiler */ } B_DB; #endif /* __SQL_C */ @@ -269,7 +269,7 @@ extern uint32_t bacula_db_version; /* ***FIXME*** FileId_t should be uint64_t */ typedef uint32_t FileId_t; -typedef uint32_t DBId_t; /* general DB id type */ +typedef uint32_t DBId_t; /* general DB id type */ typedef uint32_t JobId_t; #define faddr_t long @@ -283,18 +283,18 @@ typedef uint32_t JobId_t; /* Job record */ struct JOB_DBR { JobId_t JobId; - char Job[MAX_NAME_LENGTH]; /* Job unique name */ - char Name[MAX_NAME_LENGTH]; /* Job base name */ - int Type; /* actually char(1) */ - int Level; /* actually char(1) */ - int JobStatus; /* actually char(1) */ - uint32_t ClientId; /* Id of client */ - uint32_t PoolId; /* Id of pool */ - uint32_t FileSetId; /* Id of FileSet */ - time_t SchedTime; /* Time job scheduled */ - time_t StartTime; /* Job start time */ - time_t EndTime; /* Job termination time */ - utime_t JobTDate; /* Backup time/date in seconds */ + char Job[MAX_NAME_LENGTH]; /* Job unique name */ + char Name[MAX_NAME_LENGTH]; /* Job base name */ + int Type; /* actually char(1) */ + int Level; /* actually char(1) */ + int JobStatus; /* actually char(1) */ + uint32_t ClientId; /* Id of client */ + uint32_t PoolId; /* Id of pool */ + uint32_t FileSetId; /* Id of FileSet */ + time_t SchedTime; /* Time job scheduled */ + time_t StartTime; /* Job start time */ + time_t EndTime; /* Job termination time */ + utime_t JobTDate; /* Backup time/date in seconds */ uint32_t VolSessionId; uint32_t VolSessionTime; uint32_t JobFiles; @@ -305,8 +305,8 @@ struct JOB_DBR { /* Note, FirstIndex, LastIndex, Start/End File and Block * are only used in the JobMedia record. */ - uint32_t FirstIndex; /* First index this Volume */ - uint32_t LastIndex; /* Last index this Volume */ + uint32_t FirstIndex; /* First index this Volume */ + uint32_t LastIndex; /* Last index this Volume */ uint32_t StartFile; uint32_t EndFile; uint32_t StartBlock; @@ -324,28 +324,28 @@ struct JOB_DBR { */ /* JobMedia record */ struct JOBMEDIA_DBR { - uint32_t JobMediaId; /* record id */ - JobId_t JobId; /* JobId */ - uint32_t MediaId; /* MediaId */ - uint32_t FirstIndex; /* First index this Volume */ - uint32_t LastIndex; /* Last index this Volume */ - uint32_t StartFile; /* File for start of data */ - uint32_t EndFile; /* End file on Volume */ - uint32_t StartBlock; /* start block on tape */ - uint32_t EndBlock; /* last block */ + uint32_t JobMediaId; /* record id */ + JobId_t JobId; /* JobId */ + uint32_t MediaId; /* MediaId */ + uint32_t FirstIndex; /* First index this Volume */ + uint32_t LastIndex; /* Last index this Volume */ + uint32_t StartFile; /* File for start of data */ + uint32_t EndFile; /* End file on Volume */ + uint32_t StartBlock; /* start block on tape */ + uint32_t EndBlock; /* last block */ }; /* Volume Parameter structure */ struct VOL_PARAMS { char VolumeName[MAX_NAME_LENGTH]; /* Volume name */ - uint32_t VolIndex; /* Volume seqence no. */ - uint32_t FirstIndex; /* First index this Volume */ - uint32_t LastIndex; /* Last index this Volume */ - uint32_t StartFile; /* File for start of data */ - uint32_t EndFile; /* End file on Volume */ - uint32_t StartBlock; /* start block on tape */ - uint32_t EndBlock; /* last block */ + uint32_t VolIndex; /* Volume seqence no. */ + uint32_t FirstIndex; /* First index this Volume */ + uint32_t LastIndex; /* Last index this Volume */ + uint32_t StartFile; /* File for start of data */ + uint32_t EndFile; /* End file on Volume */ + uint32_t StartBlock; /* start block on tape */ + uint32_t EndBlock; /* last block */ }; @@ -354,9 +354,9 @@ struct VOL_PARAMS { * records (e.g. pathname, filename, fileattributes). */ struct ATTR_DBR { - char *fname; /* full path & filename */ - char *link; /* link if any */ - char *attr; /* attributes statp */ + char *fname; /* full path & filename */ + char *link; /* link if any */ + char *attr; /* attributes statp */ uint32_t FileIndex; uint32_t Stream; JobId_t JobId; @@ -378,26 +378,26 @@ struct FILE_DBR { char LStat[256]; /* int Status; */ char SIG[50]; - int SigType; /* NO_SIG/MD5_SIG/SHA1_SIG */ + int SigType; /* NO_SIG/MD5_SIG/SHA1_SIG */ }; /* Pool record -- same format as database */ struct POOL_DBR { uint32_t PoolId; - char Name[MAX_NAME_LENGTH]; /* Pool name */ - uint32_t NumVols; /* total number of volumes */ - uint32_t MaxVols; /* max allowed volumes */ - int UseOnce; /* set to use once only */ - int UseCatalog; /* set to use catalog */ - int AcceptAnyVolume; /* set to accept any volume sequence */ - int AutoPrune; /* set to prune automatically */ - int Recycle; /* default Vol recycle flag */ - utime_t VolRetention; /* retention period 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 */ - uint64_t MaxVolBytes; /* Max bytes on Volume */ - char PoolType[MAX_NAME_LENGTH]; + char Name[MAX_NAME_LENGTH]; /* Pool name */ + uint32_t NumVols; /* total number of volumes */ + uint32_t MaxVols; /* max allowed volumes */ + int32_t UseOnce; /* set to use once only */ + int32_t UseCatalog; /* set to use catalog */ + int32_t AcceptAnyVolume; /* set to accept any volume sequence */ + int32_t AutoPrune; /* set to prune automatically */ + int32_t Recycle; /* default Vol recycle flag */ + utime_t VolRetention; /* retention period 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 */ + uint64_t MaxVolBytes; /* Max bytes on Volume */ + char PoolType[MAX_NAME_LENGTH]; char LabelFormat[MAX_NAME_LENGTH]; /* Extra stuff not in DB */ faddr_t rec_addr; @@ -405,34 +405,36 @@ struct POOL_DBR { /* Media record -- same as the database */ struct MEDIA_DBR { - uint32_t MediaId; /* Unique volume id */ + uint32_t MediaId; /* Unique volume id */ char VolumeName[MAX_NAME_LENGTH]; /* Volume name */ char MediaType[MAX_NAME_LENGTH]; /* Media type */ - uint32_t PoolId; /* Pool id */ - time_t FirstWritten; /* Time Volume first written */ - time_t LastWritten; /* Time Volume last written */ - time_t LabelDate; /* Date/Time Volume labeled */ - uint32_t VolJobs; /* number of jobs on this medium */ - uint32_t VolFiles; /* Number of files */ - uint32_t VolBlocks; /* Number of blocks */ - uint32_t VolMounts; /* Number of times mounted */ - uint32_t VolErrors; /* Number of read/write errors */ - uint32_t VolWrites; /* Number of writes */ - uint32_t VolReads; /* Number of reads */ - uint64_t VolBytes; /* Number of bytes written */ - uint64_t MaxVolBytes; /* Max bytes to write to Volume */ - uint64_t VolCapacityBytes; /* capacity estimate */ - 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 */ - int Recycle; /* recycle yes/no */ - int32_t Slot; /* slot in changer */ - char VolStatus[20]; /* Volume status */ + uint32_t PoolId; /* Pool id */ + time_t FirstWritten; /* Time Volume first written */ + time_t LastWritten; /* Time Volume last written */ + time_t LabelDate; /* Date/Time Volume labeled */ + uint32_t VolJobs; /* number of jobs on this medium */ + uint32_t VolFiles; /* Number of files */ + uint32_t VolBlocks; /* Number of blocks */ + uint32_t VolMounts; /* Number of times mounted */ + uint32_t VolErrors; /* Number of read/write errors */ + uint32_t VolWrites; /* Number of writes */ + uint32_t VolReads; /* Number of reads */ + uint64_t VolBytes; /* Number of bytes written */ + uint64_t MaxVolBytes; /* Max bytes to write to Volume */ + uint64_t VolCapacityBytes; /* capacity estimate */ + 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 */ - faddr_t rec_addr; /* found record address */ + faddr_t rec_addr; /* found record address */ /* Since the database returns times as strings, this is how we pass - * them back. + * them back. */ char cFirstWritten[MAX_TIME_LENGTH]; /* FirstWritten returned from DB */ char cLastWritten[MAX_TIME_LENGTH]; /* LastWritten returned from DB */ @@ -441,12 +443,12 @@ struct MEDIA_DBR { /* Client record -- same as the database */ struct CLIENT_DBR { - uint32_t ClientId; /* Unique Client id */ + uint32_t ClientId; /* Unique Client id */ int AutoPrune; utime_t FileRetention; utime_t JobRetention; - char Name[MAX_NAME_LENGTH]; /* Client name */ - char Uname[256]; /* Uname for client */ + char Name[MAX_NAME_LENGTH]; /* Client name */ + char Uname[256]; /* Uname for client */ }; /* Counter record as in database */ @@ -461,16 +463,16 @@ struct COUNTER_DBR { /* FileSet record -- same as the database */ struct FILESET_DBR { - uint32_t FileSetId; /* Unique FileSet id */ + uint32_t FileSetId; /* Unique FileSet id */ char FileSet[MAX_NAME_LENGTH]; /* FileSet name */ - char MD5[50]; /* MD5 signature of include/exclude */ - time_t CreateTime; /* date created */ + char MD5[50]; /* MD5 signature of include/exclude */ + time_t CreateTime; /* date created */ /* * This is where we return CreateTime */ char cCreateTime[MAX_TIME_LENGTH]; /* CreateTime as returned from DB */ /* Not in DB but returned by db_create_fileset() */ - bool created; /* set when record newly created */ + bool created; /* set when record newly created */ }; diff --git a/bacula/src/cats/sql_list.c b/bacula/src/cats/sql_list.c index c74a41a4bd..8637c5c7b4 100644 --- a/bacula/src/cats/sql_list.c +++ b/bacula/src/cats/sql_list.c @@ -151,12 +151,12 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, } } else { if (mdbr->VolumeName[0] != 0) { - Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,MediaType,VolStatus," - "VolBytes,LastWritten,VolRetention,Recycle,Slot " + Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolStatus," + "VolBytes,VolFiles,VolRetention,Recycle,Slot,MediaType,LastWritten " "FROM Media WHERE Media.VolumeName='%s'", mdbr->VolumeName); } else { - Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,MediaType,VolStatus," - "VolBytes,LastWritten,VolRetention,Recycle,Slot " + Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolStatus," + "VolBytes,VolFiles,VolRetention,Recycle,Slot,MediaType,LastWritten " "FROM Media WHERE Media.PoolId=%u ORDER BY MediaId", mdbr->PoolId); } } diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index db060bedef..b8b7ebd525 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -47,7 +47,7 @@ static char Get_Vol_Info[] = "CatReq Job=%127s GetVolInfo VolName=%127s write=%d 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\n"; + Slot=%d relabel=%d Drive=%d InChanger=%d\n"; static char Create_job_media[] = "CatReq Job=%127s CreateJobMedia \ FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u \ @@ -55,15 +55,33 @@ static char Create_job_media[] = "CatReq Job=%127s CreateJobMedia \ /* Responses sent to Storage daemon */ -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\n"; +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"; -static char OK_update[] = "1000 OK UpdateMedia\n"; +static char OK_create[] = "1000 OK CreateJobMedia\n"; -/* static char FileAttributes[] = "UpdCat Job=%127s FileAttributes "; */ +static int send_volume_info_to_storage_daemon(JCR *jcr, BSOCK *sd, MEDIA_DBR *mr) +{ + int stat; + char ed1[50], ed2[50], ed3[50]; + + jcr->MediaId = mr->MediaId; + pm_strcpy(&jcr->VolumeName, mr->VolumeName); + bash_spaces(mr->VolumeName); + stat = bnet_fsend(sd, OK_media, mr->VolumeName, mr->VolJobs, + mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), + mr->VolMounts, mr->VolErrors, mr->VolWrites, + edit_uint64(mr->MaxVolBytes, ed2), + edit_uint64(mr->VolCapacityBytes, ed3), + mr->VolStatus, mr->Slot, mr->MaxVolJobs, mr->MaxVolFiles, + mr->Drive, mr->InChanger); + unbash_spaces(mr->VolumeName); + Dmsg2(100, "Vol Info for %s: %s", jcr->Job, sd->msg); + return stat; +} void catalog_request(JCR *jcr, BSOCK *bs, char *msg) { @@ -87,17 +105,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) * Send Find Media response to Storage daemon */ if (ok) { - char ed1[50], ed2[50], ed3[50]; - jcr->MediaId = mr.MediaId; - pm_strcpy(&jcr->VolumeName, mr.VolumeName); - bash_spaces(mr.VolumeName); - bnet_fsend(bs, OK_media, mr.VolumeName, mr.VolJobs, - mr.VolFiles, mr.VolBlocks, edit_uint64(mr.VolBytes, ed1), - mr.VolMounts, mr.VolErrors, mr.VolWrites, - edit_uint64(mr.MaxVolBytes, ed2), - edit_uint64(mr.VolCapacityBytes, ed3), - mr.VolStatus, mr.Slot, mr.MaxVolJobs, mr.MaxVolFiles); - Dmsg2(100, "Find media for %s: %s", jcr->Job, bs->msg); + send_volume_info_to_storage_daemon(jcr, bs, &mr); } else { bnet_fsend(bs, "1901 No Media.\n"); } @@ -113,9 +121,6 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) unbash_spaces(mr.VolumeName); if (db_get_media_record(jcr, jcr->db, &mr)) { char *reason = NULL; /* detailed reason for rejection */ - jcr->MediaId = mr.MediaId; - Dmsg1(120, "VolumeInfo MediaId=%d\n", jcr->MediaId); - pm_strcpy(&jcr->VolumeName, mr.VolumeName); /* * If we are reading, accept any volume (reason == NULL) * If we are writing, check if the Volume is valid @@ -151,18 +156,10 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) } } if (reason == NULL) { - char ed1[50], ed2[50], ed3[50]; /* * Send Find Media response to Storage daemon */ - bash_spaces(mr.VolumeName); - bnet_fsend(bs, OK_media, mr.VolumeName, mr.VolJobs, - mr.VolFiles, mr.VolBlocks, edit_uint64(mr.VolBytes, ed1), - mr.VolMounts, mr.VolErrors, mr.VolWrites, - edit_uint64(mr.MaxVolBytes, ed2), - edit_uint64(mr.VolCapacityBytes, ed3), - mr.VolStatus, mr.Slot, mr.MaxVolJobs, mr.MaxVolFiles); - Dmsg2(100, "Vol Info for %s: %s", jcr->Job, bs->msg); + send_volume_info_to_storage_daemon(jcr, bs, &mr); } else { /* Not suitable volume */ bnet_fsend(bs, "1998 Volume \"%s\" status is %s, %s.\n", mr.VolumeName, @@ -182,7 +179,7 @@ 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) == 14) { + &sdmr.Slot, &label, &sdmr.Drive, &sdmr.InChanger) == 16) { db_lock(jcr->db); Dmsg3(400, "Update media %s oldStat=%s newStat=%s\n", sdmr.VolumeName, @@ -215,23 +212,26 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) mr.VolErrors = sdmr.VolErrors; mr.VolWrites = sdmr.VolWrites; mr.LastWritten = sdmr.LastWritten; + mr.Slot = sdmr.Slot; + mr.Drive = sdmr.Drive; + mr.InChanger = sdmr.InChanger; bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus)); - mr.Slot = sdmr.Slot; Dmsg2(200, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName); /* - * Write the modified record to the DB + * Check if it has expired, and if not update the DB. Note, if + * Volume has expired, has_volume_expired() will update the DB. */ - if (db_update_media_record(jcr, jcr->db, &mr)) { - bnet_fsend(bs, OK_update); - Dmsg0(190, "send OK\n"); + if (has_volume_expired(jcr, &mr)) { + send_volume_info_to_storage_daemon(jcr, bs, &mr); + } else if (db_update_media_record(jcr, jcr->db, &mr)) { + send_volume_info_to_storage_daemon(jcr, bs, &mr); } else { Jmsg(jcr, M_ERROR, 0, _("Catalog error updating Media record. %s"), db_strerror(jcr->db)); bnet_fsend(bs, "1992 Update Media error\n"); Dmsg0(190, "send error\n"); } - has_volume_expired(jcr, &mr); /* if expired, change Media record */ db_unlock(jcr->db); /* @@ -251,7 +251,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) bnet_fsend(bs, "1991 Update JobMedia error\n"); } else { Dmsg0(100, "JobMedia record created\n"); - bnet_fsend(bs, OK_update); + bnet_fsend(bs, OK_create); } } else { diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index 05cee1db59..31a91f36ac 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -304,7 +304,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) /* List MEDIA or VOLUMES */ } else if (strcasecmp(ua->argk[i], _("media")) == 0 || strcasecmp(ua->argk[i], _("volumes")) == 0) { - int done = FALSE; + bool done = false; for (j=i+1; jargc; j++) { if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) { bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); @@ -320,7 +320,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) n = db_get_job_volume_names(ua->jcr, ua->db, jobid, &VolumeName); bsendmsg(ua, _("Jobid %d used %d Volume(s): %s\n"), jobid, n, VolumeName); free_pool_memory(VolumeName); - done = TRUE; + done = true; } /* if no job or jobid keyword found, then we list all media */ if (!done) { diff --git a/bacula/src/lib/alist.h b/bacula/src/lib/alist.h index 03ab5e3e91..8b6755405b 100644 --- a/bacula/src/lib/alist.h +++ b/bacula/src/lib/alist.h @@ -20,6 +20,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Kern Sibbald, June MMIII + */ /* @@ -52,7 +54,7 @@ inline void * alist::operator [](int index) const { return items[index]; } -/* +/* * This allows us to do explicit initialization, * allowing us to mix C++ classes inside malloc'ed * C structures. Define before called in constructor. diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 0e04ffa224..c319f7c2cc 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -61,6 +61,7 @@ static int32_t read_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes) errno = 0; nread = read(bsock->fd, ptr, nleft); if (bsock->timed_out || bsock->terminated) { + Dmsg1(000, "timed_out = %d\n", bsock->timed_out); return nread; } } while (nread == -1 && (errno == EINTR || errno == EAGAIN)); @@ -474,6 +475,50 @@ bnet_wait_data_intr(BSOCK *bsock, int sec) } } +#ifndef NETDB_INTERNAL +#define NETDB_INTERNAL -1 /* See errno. */ +#endif +#ifndef NETDB_SUCCESS +#define NETDB_SUCCESS 0 /* No problem. */ +#endif +#ifndef HOST_NOT_FOUND +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */ +#endif +#ifndef TRY_AGAIN +#define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */ +#endif +#ifndef NO_RECOVERY +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */ +#endif +#ifndef NO_DATA +#define NO_DATA 4 /* Valid name, no data record of requested type. */ +#endif + +extern int h_errno; /* On error has one of the above */ + +/* + * Get human readable error for gethostbyname() + */ +static char *gethost_strerror() +{ + switch (h_errno) { + case NETDB_INTERNAL: + return strerror(errno); + case NETDB_SUCCESS: + return "No problem."; + case HOST_NOT_FOUND: + return "Authoritative answer Host not found."; + case TRY_AGAIN: + return "Non-authoritative Host not found, or ServerFail."; + case NO_RECOVERY: + return "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP."; + case NO_DATA: + return "Valid name, no data record of resquested type."; + default: + return "Unknown error."; + } +} + static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -497,7 +542,7 @@ static uint32_t *bget_host_ip(JCR *jcr, char *host) P(ip_mutex); if ((hp = gethostbyname(host)) == NULL) { Jmsg2(jcr, M_ERROR, 0, "gethostbyname() for %s failed: ERR=%s\n", - host, strerror(errno)); + host, gethost_strerror()); V(ip_mutex); return NULL; } @@ -512,7 +557,7 @@ Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length); i++; } i++; - addr_list = (uint32_t *) malloc(sizeof(uint32_t) * i); + addr_list = (uint32_t *)malloc(sizeof(uint32_t) * i); i = 0; for (p = hp->h_addr_list; *p != 0; p++) { addr_list[i++] = (*(struct in_addr **)p)->s_addr; diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index ad80a10cef..ee884d1634 100755 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -189,7 +189,7 @@ void free_jcr(JCR *jcr) P(mutex); jcr->use_count--; /* decrement use count */ - Dmsg2(200, "Dec jcr 0x%x use_count=%d\n", jcr, jcr->use_count); + Dmsg3(200, "Dec jcr 0x%x use_count=%d jobid=%d\n", jcr, jcr->use_count, jcr->JobId); if (jcr->use_count > 0) { /* if in use */ V(mutex); Dmsg2(200, "jcr 0x%x use_count=%d\n", jcr, jcr->use_count); @@ -198,6 +198,7 @@ void free_jcr(JCR *jcr) remove_jcr(jcr); V(mutex); + Dmsg1(200, "End job=%d\n", jcr->JobId); if (jcr->daemon_free_jcr) { jcr->daemon_free_jcr(jcr); /* call daemon free routine */ } diff --git a/bacula/src/lib/signal.c b/bacula/src/lib/signal.c index aea28d9453..4561f4664c 100644 --- a/bacula/src/lib/signal.c +++ b/bacula/src/lib/signal.c @@ -65,6 +65,7 @@ static void signal_handler(int sig) if (already_dead) { _exit(1); } + Dmsg1(200, "sig=%d\n", sig); /* Ignore certain signals */ if (sig == SIGCHLD || sig == SIGUSR2) { return; @@ -138,7 +139,7 @@ static void signal_handler(int sig) waitpid(pid, NULL, 0); /* wait for child to produce dump */ fprintf(stderr, "Traceback complete, attempting cleanup ...\n"); Dmsg0(500, "Done waitpid\n"); - exit_handler(1); /* clean up if possible */ + exit_handler(sig); /* clean up if possible */ Dmsg0(500, "Done exit_handler\n"); } else { Dmsg0(500, "Doing sleep\n"); @@ -148,7 +149,7 @@ static void signal_handler(int sig) } #endif - exit_handler(1); + exit_handler(sig); } /* diff --git a/bacula/src/lib/watchdog.c b/bacula/src/lib/watchdog.c index 93ba92cee1..14fda2273b 100755 --- a/bacula/src/lib/watchdog.c +++ b/bacula/src/lib/watchdog.c @@ -133,6 +133,7 @@ static void *btimer_thread(void *arg) if (fd) { timer_start = fd->timer_start; if (timer_start && (watchdog_time - timer_start) > fd->timeout) { + fd->timer_start = 0; /* turn off timer */ fd->timed_out = TRUE; Jmsg(jcr, M_ERROR, 0, _( "Watchdog sending kill after %d secs to thread stalled reading Storage daemon.\n"), @@ -144,6 +145,7 @@ static void *btimer_thread(void *arg) if (fd) { timer_start = fd->timer_start; if (timer_start && (watchdog_time - timer_start) > fd->timeout) { + fd->timer_start = 0; /* turn off timer */ fd->timed_out = TRUE; Jmsg(jcr, M_ERROR, 0, _( "Watchdog sending kill after %d secs to thread stalled reading File daemon.\n"), @@ -155,6 +157,7 @@ static void *btimer_thread(void *arg) if (fd) { timer_start = fd->timer_start; if (timer_start && (watchdog_time - timer_start) > fd->timeout) { + fd->timer_start = 0; /* turn off timer */ fd->timed_out = TRUE; Jmsg(jcr, M_ERROR, 0, _( "Watchdog sending kill after %d secs to thread stalled reading Director.\n"), diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 44e00b6bd7..85e1aef4aa 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -53,17 +53,18 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) block_device(dev, BST_DOING_ACQUIRE); unlock_device(dev); - tape_previously_mounted = (dev->state & ST_READ) || (dev->state & ST_APPEND); + tape_previously_mounted = dev_state(dev, ST_READ) || dev_state(dev, ST_APPEND); - if (dev->state & ST_READ || dev->num_writers > 0) { - Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy. Job canceled.\n"), dev_name(dev)); + if (dev_state(dev, ST_READ) || dev->num_writers > 0) { + Jmsg2(jcr, M_FATAL, 0, _("Device %s is busy. Job %d canceled.\n"), + dev_name(dev), jcr->JobId); goto get_out; } /* Find next Volume, if any */ vol = jcr->VolList; if (!vol) { - Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job canceled.\n")); + Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId); goto get_out; } jcr->CurVolume++; @@ -74,7 +75,7 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) for (i=0; i<5; i++) { if (job_canceled(jcr)) { - Mmsg0(&dev->errmsg, _("Job canceled.\n")); + Mmsg1(&dev->errmsg, _("Job %d canceled.\n"), jcr->JobId); goto get_out; /* error return */ } /* @@ -178,7 +179,7 @@ DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) Dmsg1(190, "acquire_append device is %s\n", dev_is_tape(dev)?"tape":"disk"); - if (dev->state & ST_APPEND) { + if (dev_state(dev, ST_APPEND)) { /* * Device already in append mode * @@ -198,7 +199,7 @@ DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) for ( ; d; d=d->next) { open_vols++; } - if (dev->state & ST_FILE && dev->max_open_vols > open_vols) { + if (dev_state(dev, ST_FILE) && dev->max_open_vols > open_vols) { d = init_dev(NULL, (DEVRES *)dev->device); /* init new device */ d->prev = dev; /* chain in new device */ d->next = dev->next; @@ -235,7 +236,7 @@ DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) } } else { /* Not already in append mode, so mount the device */ - if (dev->state & ST_READ) { + if (dev_state(dev, ST_READ)) { Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev)); goto get_out; } @@ -245,8 +246,11 @@ DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (do_mount || recycle) { if (!mount_next_write_volume(jcr, dev, block, release)) { - Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"), - dev_name(dev)); + if (!job_canceled(jcr)) { + /* Reduce "noise" -- don't print if job canceled */ + Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"), + dev_name(dev)); + } goto get_out; } } @@ -279,7 +283,7 @@ int release_device(JCR *jcr, DEVICE *dev) { lock_device(dev); Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk"); - if (dev->state & ST_READ) { + if (dev_state(dev, ST_READ)) { dev->state &= ~ST_READ; /* clear read bit */ if (!dev_is_tape(dev) || !dev_cap(dev, CAP_ALWAYSOPEN)) { offline_or_rewind_dev(dev); @@ -288,11 +292,12 @@ int release_device(JCR *jcr, DEVICE *dev) /******FIXME**** send read volume usage statistics to director */ } else if (dev->num_writers > 0) { + ASSERT(dev_state(dev, ST_APPEND)); dev->num_writers--; Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers); if (dev->num_writers == 0) { /* If we are the only writer, write EOF after job */ - if (dev->state & ST_LABEL) { + if (dev_state(dev, ST_LABEL)) { Dmsg0(100, "dir_create_jobmedia_record. Release\n"); if (!dir_create_jobmedia_record(jcr)) { Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), @@ -301,34 +306,32 @@ int release_device(JCR *jcr, DEVICE *dev) if (dev_can_write(dev)) { weof_dev(dev, 1); } - dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */ dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */ /* Note! do volume update before close, which zaps VolCatInfo */ - Dmsg0(200, "dir_update_vol_info. Release0\n"); - dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* send Volume info to Director */ + Dmsg0(100, "dir_update_vol_info. Release0\n"); + dir_update_volume_info(jcr, dev, 0); /* send Volume info to Director */ } if (!dev_is_tape(dev) || !dev_cap(dev, CAP_ALWAYSOPEN)) { offline_or_rewind_dev(dev); close_dev(dev); } - } else if (dev->state & ST_LABEL) { + } else if (dev_state(dev, ST_LABEL)) { Dmsg0(100, "dir_create_jobmedia_record. Release\n"); if (!dir_create_jobmedia_record(jcr)) { Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), jcr->VolCatInfo.VolCatName, jcr->Job); } - Dmsg0(200, "dir_update_vol_info. Release1\n"); - dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */ + Dmsg0(100, "dir_update_vol_info. Release1\n"); dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */ - dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* send Volume info to Director */ + dir_update_volume_info(jcr, dev, 0); /* send Volume info to Director */ } } else { Jmsg2(jcr, M_ERROR, 0, _("BAD ERROR: release_device %s, Volume \"%s\" not in use.\n"), dev_name(dev), NPRT(jcr->VolumeName)); } detach_jcr_from_device(dev, jcr); - if (dev->prev && !(dev->state & ST_READ) && dev->num_writers == 0) { + if (dev->prev && !dev_state(dev, ST_READ) && dev->num_writers == 0) { P(mutex); unlock_device(dev); dev->prev->next = dev->next; /* dechain */ diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 392640505c..c89a91e213 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -32,24 +32,24 @@ /* Requests sent to the Director */ static char Find_media[] = "CatReq Job=%s FindMedia=%d\n"; 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\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 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"; +static char Create_job_media[] = "CatReq Job=%s CreateJobMedia" + " FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u" + " StartBlock=%u EndBlock=%u\n"; static char FileAttributes[] = "UpdCat Job=%s FileAttributes "; static char Job_status[] = "3012 Job %s jobstatus %d\n"; /* Responses received from the Director */ -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\n"; -static char OK_update[] = "1000 OK UpdateMedia\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"; + +static char OK_create[] = "1000 OK CreateJobMedia\n"; /* Forward referenced functions */ static int wait_for_sysop(JCR *jcr, DEVICE *dev, int wait_sec); @@ -67,8 +67,11 @@ int dir_send_job_status(JCR *jcr) * dir_get_volume_info() * and * dir_find_next_appendable_volume() + * + * Returns: 1 on success and vol info in jcr->VolCatInfo + * 0 on failure */ -static int do_request_volume_info(JCR *jcr) +static int do_get_volume_info(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; VOLUME_CAT_INFO vol; @@ -86,10 +89,11 @@ static int do_request_volume_info(JCR *jcr) &vol.VolCatMounts, &vol.VolCatErrors, &vol.VolCatWrites, &vol.VolCatMaxBytes, &vol.VolCatCapacityBytes, vol.VolCatStatus, - &vol.Slot, &vol.VolCatMaxJobs, &vol.VolCatMaxFiles) != 14) { + &vol.Slot, &vol.VolCatMaxJobs, &vol.VolCatMaxFiles, + &vol.Drive, &vol.InChanger) != 16) { Dmsg1(200, "Bad response from Dir: %s\n", dir->msg); - Mmsg(&jcr->errmsg, _("Error scanning Dir response: %s\n"), dir->msg); + Mmsg(&jcr->errmsg, _("Error getting Volume info: %s\n"), dir->msg); return 0; } unbash_spaces(vol.VolCatName); @@ -121,7 +125,7 @@ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw writing) bash_spaces(jcr->VolCatInfo.VolCatName); bnet_fsend(dir, Get_Vol_Info, jcr->Job, jcr->VolCatInfo.VolCatName, writing==GET_VOL_INFO_FOR_WRITE?1:0); - return do_request_volume_info(jcr); + return do_get_volume_info(jcr); } @@ -140,7 +144,7 @@ int dir_find_next_appendable_volume(JCR *jcr) Dmsg0(200, "dir_find_next_appendable_volume\n"); bnet_fsend(dir, Find_media, jcr->Job, 1); - return do_request_volume_info(jcr); + return do_get_volume_info(jcr); } @@ -148,16 +152,28 @@ int dir_find_next_appendable_volume(JCR *jcr) * After writing a Volume, send the updated statistics * back to the director. */ -int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int label) +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]; + VOLUME_CAT_INFO *vol = &dev->VolCatInfo; if (vol->VolCatName[0] == 0) { Jmsg0(jcr, M_ERROR, 0, _("NULL Volume name. This shouldn't happen!!!\n")); return 0; } + if (dev_state(dev, ST_READ)) { + Jmsg0(jcr, M_ERROR, 0, _("Attempt to update_volume_info in read mode!!!\n")); + return 0; + } + if (!dev_state(dev, ST_LABEL)) { + Jmsg0(jcr, M_ERROR, 0, _("Attempt to update_volume_info on non-labeled Volume!!!\n")); + return 0; + } + + dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */ + Dmsg1(100, "Update cat VolFiles=%d\n", dev->file); /* Just labeled or relabeled the tape */ if (label) { bstrncpy(vol->VolCatStatus, "Append", sizeof(vol->VolCatStatus)); @@ -169,22 +185,17 @@ int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, 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); + EndTime, vol->VolCatStatus, vol->Slot, label, vol->Drive, + vol->InChanger); Dmsg1(120, "update_volume_data(): %s", dir->msg); unbash_spaces(vol->VolCatName); - if (bnet_recv(dir) <= 0) { - Dmsg0(190, "updateVolCatInfo error bnet_recv\n"); - Jmsg(jcr, M_ERROR, 0, _("Error updating Volume info Vol=\"%s\": ERR=%s\n"), - vol->VolCatName, bnet_strerror(dir)); - return 0; - } - Dmsg1(120, "Updatevol: %s", dir->msg); - if (strcmp(dir->msg, OK_update) != 0) { - Dmsg1(130, "Bad response from Dir: %s\n", dir->msg); - Jmsg(jcr, M_ERROR, 0, _("Error updating Volume info Vol=\"%s\": %s\n"), - vol->VolCatName, dir->msg); + + if (!do_get_volume_info(jcr)) { + Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg); return 0; } + /* Update dev Volume info in case something changed (e.g. expired) */ + memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(dev->VolCatInfo)); return 1; } @@ -212,7 +223,7 @@ int dir_create_jobmedia_record(JCR *jcr) return 0; } Dmsg1(120, "Create_jobmedia: %s", dir->msg); - if (strcmp(dir->msg, OK_update) != 0) { + if (strcmp(dir->msg, OK_create) != 0) { Dmsg1(130, "Bad response from Dir: %s\n", dir->msg); Jmsg(jcr, M_ERROR, 0, _("Error creating JobMedia record: %s\n"), dir->msg); return 0; diff --git a/bacula/src/stored/autochanger.c b/bacula/src/stored/autochanger.c index a6a19870c9..f9f269d1f4 100644 --- a/bacula/src/stored/autochanger.c +++ b/bacula/src/stored/autochanger.c @@ -128,14 +128,19 @@ int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir) return rtn_stat; } -void invalidate_slot_in_catalog(JCR *jcr) +/* + * The Volume is not in the correct slot, so mark this + * Volume as not being in the Changer. + */ +void invalid_slot_in_catalog(JCR *jcr, DEVICE *dev) { Jmsg(jcr, M_ERROR, 0, _("Autochanger Volume \"%s\" not found in slot %d.\n" " Setting slot to zero in catalog.\n"), jcr->VolCatInfo.VolCatName, jcr->VolCatInfo.Slot); - jcr->VolCatInfo.Slot = 0; /* invalidate slot */ - Dmsg0(200, "update vol info in mount\n"); - dir_update_volume_info(jcr, &jcr->VolCatInfo, 1); /* set slot */ + jcr->VolCatInfo.InChanger = false; + dev->VolCatInfo.InChanger = false; + Dmsg0(100, "update vol info in mount\n"); + dir_update_volume_info(jcr, dev, 1); /* set new status */ } /* diff --git a/bacula/src/stored/bcopy.c b/bacula/src/stored/bcopy.c index fc9452c16a..9efa2a7965 100644 --- a/bacula/src/stored/bcopy.c +++ b/bacula/src/stored/bcopy.c @@ -254,7 +254,7 @@ static int record_cb(JCR *in_jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec /* Dummies to replace askdir.c */ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw writing) { return 1;} int dir_find_next_appendable_volume(JCR *jcr) { return 1;} -int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; } +int dir_update_volume_info(JCR *jcr, DEVICE *dev, int relabel) { return 1; } int dir_create_jobmedia_record(JCR *jcr) { return 1; } int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; } int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;} diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 3b8d4794fd..1ac47c0700 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -435,7 +435,7 @@ static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) /* Dummies to replace askdir.c */ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw writing) { return 1;} int dir_find_next_appendable_volume(JCR *jcr) { return 1;} -int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; } +int dir_update_volume_info(JCR *jcr, DEVICE *dev, int relabel) { return 1; } int dir_create_jobmedia_record(JCR *jcr) { return 1; } int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; } int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;} diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index e815e3cd8b..cecb013f57 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -411,13 +411,16 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) edit_uint64(max_cap, ed1), dev->dev_name); block->write_failed = true; weof_dev(dev, 1); /* end the tape */ + /* Don't do update after second EOF or file count will be wrong */ + Dmsg0(100, "dir_update_volume_info\n"); + dir_update_volume_info(jcr, dev, 0); weof_dev(dev, 1); dev->state |= (ST_EOF | ST_EOT | ST_WEOT); return 0; } /* Limit maximum File size on volume to user specified value */ - if (dev->state & ST_TAPE) { + if (dev_state(dev, ST_TAPE)) { if ((dev->max_file_size > 0) && (dev->file_addr+block->binbuf) >= dev->max_file_size) { @@ -426,10 +429,14 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); block->write_failed = true; dev->state |= (ST_EOF | ST_EOT | ST_WEOT); + Dmsg0(100, "dir_update_volume_info\n"); + dir_update_volume_info(jcr, dev, 0); return 0; } /* Do bookkeeping to handle EOF just written */ + Dmsg0(100, "dir_update_volume_info\n"); + dir_update_volume_info(jcr, dev, 0); if (!dir_create_jobmedia_record(jcr)) { Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), jcr->VolCatInfo.VolCatName, jcr->Job); @@ -443,7 +450,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (mjcr->JobId == 0) { continue; /* ignore console */ } - mjcr->NewFile = true; + mjcr->NewFile = true; /* set reminder to do set_new_file_params */ } set_new_file_parameters(jcr, dev); } @@ -485,6 +492,8 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) block->write_failed = true; weof_dev(dev,1); + Dmsg0(100, "dir_update_volume_info\n"); + dir_update_volume_info(jcr, dev, 0); if (weof_dev(dev, 1) != 0) { /* end the tape */ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } @@ -552,7 +561,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) block->BlockNumber++; /* Update jcr values */ - if (dev->state & ST_TAPE) { + if (dev_state(dev, ST_TAPE)) { jcr->EndBlock = dev->EndBlock; jcr->EndFile = dev->EndFile; } else { @@ -621,7 +630,7 @@ reread: dev->VolCatInfo.VolCatErrors++; } } while (stat == -1 && (errno == EINTR || errno == EIO) && retry++ < 11); -// Dmsg1(000, "read stat = %d\n", stat); +// Dmsg1(100, "read stat = %d\n", stat); if (stat < 0) { Dmsg1(90, "Read device got: ERR=%s\n", strerror(errno)); clrerror_dev(dev, -1); diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index 6d26549f71..350d7b7911 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -398,7 +398,7 @@ static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sess /* Dummies to replace askdir.c */ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw writing) { return 1;} int dir_find_next_appendable_volume(JCR *jcr) { return 1;} -int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; } +int dir_update_volume_info(JCR *jcr, DEVICE *dev, int relabel) { return 1; } int dir_create_jobmedia_record(JCR *jcr) { return 1; } int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; } int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;} diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 56f311f6be..1983252465 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -1111,7 +1111,7 @@ static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId) /* Dummies to replace askdir.c */ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw writing) { return 1;} int dir_find_next_appendable_volume(JCR *jcr) { return 1;} -int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; } +int dir_update_volume_info(JCR *jcr, DEVICE *dev, int relabel) { return 1; } int dir_create_jobmedia_record(JCR *jcr) { return 1; } int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; } int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;} diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 445fd46678..39df9d4911 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -1788,7 +1788,7 @@ get_cmd(char *prompt) /* Dummies to replace askdir.c */ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw writing) { return 1;} -int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; } +int dir_update_volume_info(JCR *jcr, DEVICE *dev, int relabel) { return 1; } int dir_create_jobmedia_record(JCR *jcr) { return 1; } int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;} int dir_send_job_status(JCR *jcr) {return 1;} diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 997020c89c..f8e2f395eb 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -1012,7 +1012,7 @@ weof_dev(DEVICE *dev, int num) return -1; } - if (!(dev->state & ST_TAPE)) { + if (!(dev_state(dev, ST_TAPE))) { return 0; } dev->state &= ~(ST_EOT | ST_EOF); /* remove EOF/EOT flags */ diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 797fa441b6..53969ba5aa 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -125,6 +125,8 @@ 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 */ diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index 4fd675c138..0fad7a420f 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -106,13 +106,11 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) return 0; } - strcpy(dev->VolCatInfo.VolCatStatus, "Full"); - Dmsg2(200, "Call update_vol_info Stat=%s Vol=%s\n", + bstrncpy(dev->VolCatInfo.VolCatStatus, "Full", sizeof(dev->VolCatInfo.VolCatStatus)); + Dmsg2(100, "Call update_vol_info Stat=%s Vol=%s\n", dev->VolCatInfo.VolCatStatus, dev->VolCatInfo.VolCatName); - dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */ - /* *****FIXME**** this needs to be done elsewhere */ dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */ - if (!dir_update_volume_info(jcr, &dev->VolCatInfo, 0)) { /* send Volume info to Director */ + if (!dir_update_volume_info(jcr, dev, 0)) { /* send Volume info to Director */ P(dev->mutex); unblock_device(dev); return 0; /* device locked */ @@ -201,7 +199,7 @@ void set_new_volume_parameters(JCR *jcr, DEVICE *dev) Jmsg1(jcr, M_ERROR, 0, "%s", jcr->errmsg); } /* Set new start/end positions */ - if (dev->state & ST_TAPE) { + if (dev_state(dev, ST_TAPE)) { jcr->StartBlock = dev->block_num; jcr->StartFile = dev->file; } else { @@ -217,14 +215,14 @@ void set_new_volume_parameters(JCR *jcr, DEVICE *dev) } /* - * We are now in a new file, so reset the Volume parameters + * We are now in a new Volume file, so reset the Volume parameters * concerning this job. The global changes were made earlier * in the dev structure. */ void set_new_file_parameters(JCR *jcr, DEVICE *dev) { /* Set new start/end positions */ - if (dev->state & ST_TAPE) { + if (dev_state(dev, ST_TAPE)) { jcr->StartBlock = dev->block_num; jcr->StartFile = dev->file; } else { diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 4e456d84e5..cceb5cac51 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -322,8 +322,8 @@ static int do_label(JCR *jcr, int relabel) dev->dev_blocked == BST_WAITING_FOR_SYSOP || dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) { label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel); - } else if (dev->state & ST_READ || dev->num_writers) { - if (dev->state & ST_READ) { + } else if (dev_state(dev, ST_READ) || dev->num_writers) { + if (dev_state(dev, ST_READ)) { bnet_fsend(dir, _("3911 Device %s is busy with 1 reader.\n"), dev_name(dev)); } else { @@ -519,7 +519,7 @@ static int mount_cmd(JCR *jcr) Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n"); dev->dev_blocked = BST_MOUNT; } - if (dev->state & ST_LABEL) { + if (dev_state(dev, ST_LABEL)) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), dev->dev_name, dev->VolHdr.VolName); } else { @@ -540,8 +540,8 @@ static int mount_cmd(JCR *jcr) break; case BST_NOT_BLOCKED: - if (dev->state & ST_OPENED) { - if (dev->state & ST_LABEL) { + if (dev_state(dev, ST_OPENED)) { + if (dev_state(dev, ST_LABEL)) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), dev->dev_name, dev->VolHdr.VolName); } else { @@ -560,7 +560,7 @@ static int mount_cmd(JCR *jcr) break; } read_label(jcr, dev); - if (dev->state & ST_LABEL) { + if (dev_state(dev, ST_LABEL)) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), dev->dev_name, dev->VolHdr.VolName); } else { @@ -638,8 +638,8 @@ static int unmount_cmd(JCR *jcr) bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), dev_name(dev)); - } else if (dev->state & ST_READ || dev->num_writers) { - if (dev->state & ST_READ) { + } else if (dev_state(dev, ST_READ) || dev->num_writers) { + if (dev_state(dev, ST_READ)) { Dmsg0(90, "Device in read mode\n"); bnet_fsend(dir, _("3904 Device %s is busy with 1 reader.\n"), dev_name(dev)); @@ -729,8 +729,8 @@ static int release_cmd(JCR *jcr) bnet_fsend(dir, _("3914 Device %s is being labeled.\n"), dev_name(dev)); - } else if (dev->state & ST_READ || dev->num_writers) { - if (dev->state & ST_READ) { + } else if (dev_state(dev, ST_READ) || dev->num_writers) { + if (dev_state(dev, ST_READ)) { Dmsg0(90, "Device in read mode\n"); bnet_fsend(dir, _("3915 Device %s is busy with 1 reader.\n"), dev_name(dev)); @@ -806,8 +806,8 @@ static int autochanger_cmd(JCR *jcr) dev->dev_blocked == BST_WAITING_FOR_SYSOP || dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) { autochanger_list(jcr, dev, dir); - } else if (dev->state & ST_READ || dev->num_writers) { - if (dev->state & ST_READ) { + } else if (dev_state(dev, ST_READ) || dev->num_writers) { + if (dev_state(dev, ST_READ)) { bnet_fsend(dir, _("3901 Device %s is busy with 1 reader.\n"), dev_name(dev)); } else { diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index c62a4e69d7..a92b259ccb 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -65,7 +65,7 @@ int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) Dmsg3(100, "Enter read_volume_label device=%s vol=%s dev_Vol=%s\n", dev_name(dev), VolName, dev->VolHdr.VolName); - if (dev->state & ST_LABEL) { /* did we already read label? */ + if (dev_state(dev, ST_LABEL)) { /* did we already read label? */ /* Compare Volume Names allow special wild card */ if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolName, VolName) != 0) { Mmsg(&jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"), @@ -131,6 +131,17 @@ because:\n %s"), dev_name(dev), strerror_dev(dev)); return jcr->label_status = VOL_VERSION_ERROR; } + /* We are looking for either an unused Bacula tape (PRE_LABEL) or + * a Bacula volume label (VOL_LABEL) + */ + if (dev->VolHdr.LabelType != PRE_LABEL && dev->VolHdr.LabelType != VOL_LABEL) { + Mmsg(&jcr->errmsg, _("Volume on %s has bad Bacula label type: %x\n"), + dev_name(dev), dev->VolHdr.LabelType); + return jcr->label_status = VOL_LABEL_ERROR; + } + + dev->state |= ST_LABEL; /* set has Bacula label */ + /* Compare Volume Names */ Dmsg2(30, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolName); if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolName, VolName) != 0) { @@ -147,16 +158,6 @@ because:\n %s"), dev_name(dev), strerror_dev(dev)); } Dmsg1(30, "Copy vol_name=%s\n", dev->VolHdr.VolName); - /* We are looking for either an unused Bacula tape (PRE_LABEL) or - * a Bacula volume label (VOL_LABEL) - */ - if (dev->VolHdr.LabelType != PRE_LABEL && dev->VolHdr.LabelType != VOL_LABEL) { - Mmsg(&jcr->errmsg, _("Volume on %s has bad Bacula label type: %x\n"), - dev_name(dev), dev->VolHdr.LabelType); - return jcr->label_status = VOL_LABEL_ERROR; - } - - dev->state |= ST_LABEL; /* set has Bacula label */ if (debug_level >= 10) { dump_volume_label(dev); } diff --git a/bacula/src/stored/match_bsr.c b/bacula/src/stored/match_bsr.c index 1098527c6b..79a5d78bcc 100755 --- a/bacula/src/stored/match_bsr.c +++ b/bacula/src/stored/match_bsr.c @@ -446,7 +446,7 @@ static int match_volfile(BSR *bsr, BSR_VOLFILE *volfile, DEV_RECORD *rec, bool d if (!(rec->state & REC_ISTAPE)) { return 1; /* All File records OK for this match */ } -// Dmsg3(000, "match_volfile: sfile=%d efile=%d recfile=%d\n", +// Dmsg3(100, "match_volfile: sfile=%d efile=%d recfile=%d\n", // volfile->sfile, volfile->efile, rec->File); if (volfile->sfile <= rec->File && volfile->efile >= rec->File) { return 1; diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 46368bb8be..891cddf761 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -59,7 +59,7 @@ mount_next_vol: return 0; } if (job_canceled(jcr)) { - Jmsg(jcr, M_FATAL, 0, _("Job canceled.\n")); + Jmsg(jcr, M_FATAL, 0, _("Job %d canceled.\n"), jcr->JobId); return 0; } autochanger = 0; @@ -72,6 +72,7 @@ mount_next_vol: /* * Get Director's idea of what tape we should have mounted. + * in jcr->VolCatInfo */ Dmsg0(100, "Before dir_find_next\n"); if (!dir_find_next_appendable_volume(jcr)) { @@ -124,7 +125,7 @@ mount_next_vol: Dmsg1(100, "want vol=%s\n", jcr->VolumeName); /* Open device */ - if (!(dev->state & ST_OPENED)) { + if (!(dev_state(dev, ST_OPENED))) { int mode; if (dev_cap(dev, CAP_STREAM)) { mode = OPEN_WRITE_ONLY; @@ -153,6 +154,7 @@ read_volume: } else { vol_label_status = read_dev_volume_label(jcr, dev, block); } + Dmsg2(100, "dirVol=%s dirStat=%s\n", jcr->VolumeName, jcr->VolCatInfo.VolCatStatus); /* @@ -199,22 +201,28 @@ read_volume: case VOL_IO_ERROR: /* * If permitted, we label the device, make sure we can do - * it by checking that the VolCatBytes is zero => not labeled. + * it by checking that the VolCatBytes is zero => not labeled, + * once the Volume is labeled we don't want to label another + * blank tape with the same name. For disk, we go ahead and + * label it anyway, because the OS insures that there is only + * one Volume with that name. * As noted above, at this point jcr->VolCatInfo has what * the Director wants and dev->VolCatInfo has info on the * previous tape (or nothing). */ - if (dev_cap(dev, CAP_LABEL) && jcr->VolCatInfo.VolCatBytes == 0) { + if (dev_cap(dev, CAP_LABEL) && (jcr->VolCatInfo.VolCatBytes == 0 || + (!dev_is_tape(dev) && strcmp(jcr->VolCatInfo.VolCatStatus, + "Recycle") == 0))) { Dmsg0(100, "Create volume label\n"); if (!write_volume_label_to_dev(jcr, (DEVRES *)dev->device, jcr->VolumeName, jcr->pool_name)) { Dmsg0(100, "!write_vol_label\n"); goto mount_next_vol; } - Dmsg0(200, "dir_update_vol_info. Set Append\n"); + Dmsg0(100, "dir_update_vol_info. Set Append\n"); /* Copy Director's info into the device info */ memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(dev->VolCatInfo)); - dir_update_volume_info(jcr, &dev->VolCatInfo, 1); /* indicate tape labeled */ + dir_update_volume_info(jcr, dev, 1); /* indicate tape labeled */ Jmsg(jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"), jcr->VolumeName, dev_name(dev)); goto read_volume; /* read label we just wrote */ @@ -224,8 +232,7 @@ read_volume: default: mount_error: /* Send error message */ - Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); - Dmsg0(100, "Default\n"); + Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg); ask = true; /* was - goto ask_again; */ goto mount_next_vol; @@ -297,9 +304,9 @@ mount_error: dev->VolCatInfo.VolCatWrites = 1; dev->VolCatInfo.VolCatReads = 1; } - Dmsg0(200, "dir_update_vol_info. Set Append\n"); + Dmsg0(100, "dir_update_vol_info. Set Append\n"); bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus)); - dir_update_volume_info(jcr, &dev->VolCatInfo, 1); /* indicate doing relabel */ + dir_update_volume_info(jcr, dev, 1); /* indicate doing relabel */ if (recycle) { Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\" on device %s, all previous data lost.\n"), jcr->VolumeName, dev_name(dev)); @@ -323,8 +330,8 @@ mount_error: Jmsg(jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"), jcr->VolumeName); bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus)); - Dmsg0(200, "dir_update_vol_info. Set Error.\n"); - dir_update_volume_info(jcr, &dev->VolCatInfo, 0); + Dmsg0(100, "dir_update_vol_info. Set Error.\n"); + dir_update_volume_info(jcr, dev, 0); goto mount_next_vol; } /* *****FIXME**** we should do some checking for files too */ @@ -341,14 +348,14 @@ mount_error: The number of files mismatch! Volume=%u Catalog=%u\n"), dev_file(dev), dev->VolCatInfo.VolCatFiles); bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus)); - Dmsg0(200, "dir_update_vol_info. Set Error.\n"); - dir_update_volume_info(jcr, &dev->VolCatInfo, 0); + Dmsg0(100, "dir_update_vol_info. Set Error.\n"); + dir_update_volume_info(jcr, dev, 0); goto mount_next_vol; } } dev->VolCatInfo.VolCatMounts++; /* Update mounts */ - Dmsg1(200, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts); - dir_update_volume_info(jcr, &dev->VolCatInfo, 0); + Dmsg1(100, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts); + dir_update_volume_info(jcr, dev, 0); /* Return an empty block */ empty_block(block); /* we used it for reading so set for write */ } diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index e84cfc1f15..3e1d1560e5 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,93 +28,93 @@ uint32_t new_VolSessionId(); /* From acquire.c */ -DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int release_device(JCR *jcr, DEVICE *dev); +DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int release_device(JCR *jcr, DEVICE *dev); /* From askdir.c */ enum get_vol_info_rw { GET_VOL_INFO_FOR_WRITE, GET_VOL_INFO_FOR_READ }; -int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw); -int dir_find_next_appendable_volume(JCR *jcr); -int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int label); -int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev); -int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev); -int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec); -int dir_send_job_status(JCR *jcr); -int dir_create_jobmedia_record(JCR *jcr); +int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw); +int dir_find_next_appendable_volume(JCR *jcr); +int dir_update_volume_info(JCR *jcr, DEVICE *dev, int label); +int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev); +int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev); +int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec); +int dir_send_job_status(JCR *jcr); +int dir_create_jobmedia_record(JCR *jcr); /* authenticate.c */ -int authenticate_director(JCR *jcr); -int authenticate_filed(JCR *jcr); +int authenticate_director(JCR *jcr); +int authenticate_filed(JCR *jcr); /* From block.c */ -void dump_block(DEV_BLOCK *b, char *msg); +void dump_block(DEV_BLOCK *b, char *msg); DEV_BLOCK *new_block(DEVICE *dev); -void init_block_write(DEV_BLOCK *block); -void empty_block(DEV_BLOCK *block); -void free_block(DEV_BLOCK *block); -int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); +void init_block_write(DEV_BLOCK *block); +void empty_block(DEV_BLOCK *block); +void free_block(DEV_BLOCK *block); +int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); #define CHECK_BLOCK_NUMBERS true #define NO_BLOCK_NUMBER_CHECK false -int read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); -int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); +int read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); +int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); /* From butil.c -- utilities for SD tool programs */ -void print_ls_output(char *fname, char *link, int type, struct stat *statp); +void print_ls_output(char *fname, char *link, int type, struct stat *statp); JCR *setup_jcr(char *name, char *device, BSR *bsr, char *VolumeName); DEVICE *setup_to_access_device(JCR *jcr, int read_access); -void display_tape_error_status(JCR *jcr, DEVICE *dev); +void display_tape_error_status(JCR *jcr, DEVICE *dev); DEVRES *find_device_res(char *device_name, int read_access); /* From dev.c */ -DEVICE *init_dev(DEVICE *dev, DEVRES *device); -int open_dev(DEVICE *dev, char *VolName, int mode); -void close_dev(DEVICE *dev); -void force_close_dev(DEVICE *dev); -int truncate_dev(DEVICE *dev); -void term_dev(DEVICE *dev); -char * strerror_dev(DEVICE *dev); -void clrerror_dev(DEVICE *dev, int func); -int update_pos_dev(DEVICE *dev); -int rewind_dev(DEVICE *dev); -int load_dev(DEVICE *dev); -int offline_dev(DEVICE *dev); -int flush_dev(DEVICE *dev); -int weof_dev(DEVICE *dev, int num); -int write_block(DEVICE *dev); -int write_dev(DEVICE *dev, char *buf, size_t len); -int read_dev(DEVICE *dev, char *buf, size_t len); -int status_dev(DEVICE *dev, uint32_t *status); -int eod_dev(DEVICE *dev); -int fsf_dev(DEVICE *dev, int num); -int fsr_dev(DEVICE *dev, int num); -int bsf_dev(DEVICE *dev, int num); -int bsr_dev(DEVICE *dev, int num); -void attach_jcr_to_device(DEVICE *dev, JCR *jcr); -void detach_jcr_from_device(DEVICE *dev, JCR *jcr); -JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); -int dev_can_write(DEVICE *dev); -int offline_or_rewind_dev(DEVICE *dev); -int reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); +DEVICE *init_dev(DEVICE *dev, DEVRES *device); +int open_dev(DEVICE *dev, char *VolName, int mode); +void close_dev(DEVICE *dev); +void force_close_dev(DEVICE *dev); +int truncate_dev(DEVICE *dev); +void term_dev(DEVICE *dev); +char * strerror_dev(DEVICE *dev); +void clrerror_dev(DEVICE *dev, int func); +int update_pos_dev(DEVICE *dev); +int rewind_dev(DEVICE *dev); +int load_dev(DEVICE *dev); +int offline_dev(DEVICE *dev); +int flush_dev(DEVICE *dev); +int weof_dev(DEVICE *dev, int num); +int write_block(DEVICE *dev); +int write_dev(DEVICE *dev, char *buf, size_t len); +int read_dev(DEVICE *dev, char *buf, size_t len); +int status_dev(DEVICE *dev, uint32_t *status); +int eod_dev(DEVICE *dev); +int fsf_dev(DEVICE *dev, int num); +int fsr_dev(DEVICE *dev, int num); +int bsf_dev(DEVICE *dev, int num); +int bsr_dev(DEVICE *dev, int num); +void attach_jcr_to_device(DEVICE *dev, JCR *jcr); +void detach_jcr_from_device(DEVICE *dev, JCR *jcr); +JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); +int dev_can_write(DEVICE *dev); +int offline_or_rewind_dev(DEVICE *dev); +int reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); /* Get info about device */ -char * dev_name(DEVICE *dev); -char * dev_vol_name(DEVICE *dev); +char * dev_name(DEVICE *dev); +char * dev_vol_name(DEVICE *dev); uint32_t dev_block(DEVICE *dev); uint32_t dev_file(DEVICE *dev); -int dev_is_tape(DEVICE *dev); +int dev_is_tape(DEVICE *dev); /* From device.c */ -int open_device(DEVICE *dev); -int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int open_device(DEVICE *dev); +int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); void _lock_device(char *file, int line, DEVICE *dev); void _unlock_device(char *file, int line, DEVICE *dev); void _block_device(char *file, int line, DEVICE *dev, int state); @@ -126,65 +126,65 @@ void set_new_file_parameters(JCR *jcr, DEVICE *dev); int device_is_unmounted(DEVICE *dev); /* From dircmd.c */ -void *connection_request(void *arg); +void *connection_request(void *arg); /* From fd_cmds.c */ -void run_job(JCR *jcr); +void run_job(JCR *jcr); /* From job.c */ -void stored_free_jcr(JCR *jcr); -void connection_from_filed(void *arg); -void handle_filed_connection(BSOCK *fd, char *job_name); +void stored_free_jcr(JCR *jcr); +void connection_from_filed(void *arg); +void handle_filed_connection(BSOCK *fd, char *job_name); /* From label.c */ -int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void create_session_label(JCR *jcr, DEV_RECORD *rec, int label); -void create_volume_label(DEVICE *dev, char *VolName, char *PoolName); -int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName); -int write_session_label(JCR *jcr, DEV_BLOCK *block, int label); -int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void dump_volume_label(DEVICE *dev); -void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); -int unser_volume_label(DEVICE *dev, DEV_RECORD *rec); -int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); +int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void create_session_label(JCR *jcr, DEV_RECORD *rec, int label); +void create_volume_label(DEVICE *dev, char *VolName, char *PoolName); +int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName); +int write_session_label(JCR *jcr, DEV_BLOCK *block, int label); +int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void dump_volume_label(DEVICE *dev); +void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); +int unser_volume_label(DEVICE *dev, DEV_RECORD *rec); +int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); /* From match_bsr.c */ -int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, - SESSION_LABEL *sesrec); -int match_bsr_block(BSR *bsr, DEV_BLOCK *block); -void position_bsr_block(BSR *bsr, DEV_BLOCK *block); -BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); -bool match_set_eof(BSR *bsr, DEV_RECORD *rec); +int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, + SESSION_LABEL *sesrec); +int match_bsr_block(BSR *bsr, DEV_BLOCK *block); +void position_bsr_block(BSR *bsr, DEV_BLOCK *block); +BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); +bool match_set_eof(BSR *bsr, DEV_RECORD *rec); /* From mount.c */ -int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release); -int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void release_volume(JCR *jcr, DEVICE *dev); +int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release); +int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void release_volume(JCR *jcr, DEVICE *dev); /* From autochanger.c */ -int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir); -int autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir); -void invalidate_slot_in_catalog(JCR *jcr); +int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir); +int autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir); +void invalidate_slot_in_catalog(JCR *jcr, DEVICE *dev); /* From parse_bsr.c */ -extern BSR *parse_bsr(JCR *jcr, char *lf); -void dump_bsr(BSR *bsr, bool recurse); -extern void free_bsr(BSR *bsr); -extern VOL_LIST *new_vol(); -extern int add_vol(JCR *jcr, VOL_LIST *vol); -extern void free_vol_list(JCR *jcr); -extern void create_vol_list(JCR *jcr); +BSR *parse_bsr(JCR *jcr, char *lf); +void dump_bsr(BSR *bsr, bool recurse); +void free_bsr(BSR *bsr); +VOL_LIST *new_vol(); +int add_vol(JCR *jcr, VOL_LIST *vol); +void free_vol_list(JCR *jcr); +void create_vol_list(JCR *jcr); /* From record.c */ char *FI_to_ascii(int fi); char *stream_to_ascii(int stream, int fi); -int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); +int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); DEV_RECORD *new_record(); -void free_record(DEV_RECORD *rec); +void free_record(DEV_RECORD *rec); /* From read_record.c */ int read_records(JCR *jcr, DEVICE *dev, diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index 826b7fbd18..96ba176f97 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -107,48 +107,48 @@ int main (int argc, char *argv[]) while ((ch = getopt(argc, argv, "c:d:fg:stu:v?")) != -1) { switch (ch) { - case 'c': /* configuration file */ - if (configfile != NULL) { - free(configfile); - } - configfile = bstrdup(optarg); - break; - - case 'd': /* debug level */ - debug_level = atoi(optarg); - if (debug_level <= 0) { - debug_level = 1; - } - break; + case 'c': /* configuration file */ + if (configfile != NULL) { + free(configfile); + } + configfile = bstrdup(optarg); + break; - case 'f': /* run in foreground */ - foreground = TRUE; - break; + case 'd': /* debug level */ + debug_level = atoi(optarg); + if (debug_level <= 0) { + debug_level = 1; + } + break; - case 'g': /* set group id */ - gid = optarg; - break; + case 'f': /* run in foreground */ + foreground = TRUE; + break; - case 's': /* no signals */ - no_signals = TRUE; - break; + case 'g': /* set group id */ + gid = optarg; + break; - case 't': - test_config = TRUE; - break; + case 's': /* no signals */ + no_signals = TRUE; + break; - case 'u': /* set uid */ - uid = optarg; - break; + case 't': + test_config = TRUE; + break; - case 'v': /* verbose */ - verbose++; - break; + case 'u': /* set uid */ + uid = optarg; + break; - case '?': - default: - usage(); + case 'v': /* verbose */ + verbose++; + break; + case '?': + default: + usage(); + break; } } argc -= optind; @@ -335,16 +335,47 @@ void terminate_stored(int sig) { static int in_here = FALSE; DEVRES *device; + JCR *jcr; if (in_here) { /* prevent loops */ exit(1); } in_here = TRUE; + if (sig == SIGTERM) { /* normal shutdown request? */ + /* + * This is a normal shutdown request. We wiffle through + * all open jobs canceling them and trying to wake + * them up so that they will report back the correct + * volume status. + */ + lock_jcr_chain(); + for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) { + BSOCK *fd; + free_locked_jcr(jcr); + if (jcr->JobId == 0) { + continue; /* ignore console */ + } + set_jcr_job_status(jcr, JS_Canceled); + fd = jcr->file_bsock; + if (fd) { + fd->timed_out = TRUE; + Dmsg1(100, "killing JobId=%d\n", jcr->JobId); + pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL); + if (jcr->device && jcr->device->dev && jcr->device->dev->dev_blocked) { + pthread_cond_signal(&jcr->device->dev->wait_next_vol); + } + bmicrosleep(0, 50000); + } + } + unlock_jcr_chain(); + bmicrosleep(0, 500000); /* give them 1/2 sec to clean up */ + } + delete_pid_file(me->pid_directory, "bacula-sd", me->SDport); stop_watchdog(); - Dmsg0(200, "In terminate_stored()\n"); + Dmsg1(200, "In terminate_stored() sig=%d\n", sig); LockRes(); for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) { diff --git a/bacula/src/tools/.cvsignore b/bacula/src/tools/.cvsignore index 28a8201264..e0747ab695 100644 --- a/bacula/src/tools/.cvsignore +++ b/bacula/src/tools/.cvsignore @@ -3,4 +3,5 @@ testls Makefile dbcheck smtp +bsmtp testfind diff --git a/bacula/src/tools/Makefile.in b/bacula/src/tools/Makefile.in index 9f735b05f2..c820dfa35f 100644 --- a/bacula/src/tools/Makefile.in +++ b/bacula/src/tools/Makefile.in @@ -36,7 +36,7 @@ EXTRAOBJS = @OBJLIST@ .c.o: $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $< #------------------------------------------------------------------------- -all: Makefile bsmtp dbcheck testfind testls +all: Makefile bsmtp dbcheck testfind testls hammer @echo "==== Make of tools is good ====" @echo " " @@ -54,8 +54,6 @@ testls: ../findlib/libfind.a ../lib/libbac.a testls.o $(CXX) -g $(LDFLAGS) -L. -L../lib -L../findlib -o $@ testls.o \ $(LIBS) $(DLIB) -lfind -lbac -lm - - Makefile: $(srcdir)/Makefile.in $(topdir)/config.status cd $(topdir) \ && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status diff --git a/bacula/src/tools/bsmtp.c b/bacula/src/tools/bsmtp.c index f851582e58..87f761c3de 100644 --- a/bacula/src/tools/bsmtp.c +++ b/bacula/src/tools/bsmtp.c @@ -102,7 +102,7 @@ static void usage() { fprintf(stderr, "\n" -"Usage: smtp [-f from] [-h mailhost] [-s subject] [-c copy] [recepient ...]\n" +"Usage: bsmtp [-f from] [-h mailhost] [-s subject] [-c copy] [recepient ...]\n" " -c set the Cc: field\n" " -dnn set debug level to nn\n" " -f set the From: field\n" diff --git a/bacula/src/version.h b/bacula/src/version.h index e81d5e77d6..66d98188d1 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 "10 Nov 2003" -#define LSMDATE "10Nov03" +#define BDATE "14 Nov 2003" +#define LSMDATE "14Nov03" /* Debug flags */ #undef DEBUG -- 2.39.5