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:
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
;;
#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
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
#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**
* 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;
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;
#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)
#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 */
/* 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 */
};
* 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;
#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 */
/* ***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
/* 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;
/* 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;
*/
/* 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 */
};
* 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;
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;
/* 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 */
/* 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 */
/* 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 */
};
}
} 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);
}
}
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 \
/* 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)
{
* 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");
}
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
}
}
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,
} 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,
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);
/*
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 {
/* 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; j<ua->argc; j++) {
if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) {
bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH);
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) {
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
+ Kern Sibbald, June MMIII
+
*/
/*
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.
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));
}
}
+#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;
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;
}
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;
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);
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 */
}
if (already_dead) {
_exit(1);
}
+ Dmsg1(200, "sig=%d\n", sig);
/* Ignore certain signals */
if (sig == SIGCHLD || sig == SIGUSR2) {
return;
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");
}
#endif
- exit_handler(1);
+ exit_handler(sig);
}
/*
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"),
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"),
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"),
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++;
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 */
}
/*
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
*
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;
}
} 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;
}
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;
}
}
{
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);
/******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"),
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 */
/* 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);
* 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;
&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);
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);
}
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);
}
* 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));
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;
}
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;
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 */
}
/*
/* 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;}
/* 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;}
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) {
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);
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);
}
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);
}
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 {
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);
/* 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;}
/* 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;}
/* 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;}
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 */
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 */
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 */
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 {
}
/*
- * 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 {
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 {
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 {
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 {
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 {
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));
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));
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 {
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"),
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) {
}
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);
}
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;
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;
/*
* 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)) {
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;
} else {
vol_label_status = read_dev_volume_label(jcr, dev, block);
}
+
Dmsg2(100, "dirVol=%s dirStat=%s\n", jcr->VolumeName,
jcr->VolCatInfo.VolCatStatus);
/*
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 */
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;
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));
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 */
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 */
}
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);
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,
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;
{
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)); ) {
Makefile
dbcheck
smtp
+bsmtp
testfind
.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 " "
$(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
{
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"
#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