Kern's ToDo List
- 08 February 2006
+ 17 February 2006
Major development:
Project Developer
directive).
For 1.39:
+- Keep same dcr when switching device ...
+- Job retention period in a Pool (and hence Volume). The job would
+ then be migrated.
- Detect resource deadlock in Migrate when same job wants to read
and write the same device.
- Make hardlink code at line 240 of find_one.c use binary search.
even defined).
- Make sure Maximum Volumes is respected in Pools when adding
Volumes (e.g. when pulling a Scratch volume).
-
General:
Changes to 1.39.5
+20Feb06
+- Note!!! Your database must be updated, or you must create
+ a new database. I have not yet incremented the database level.
+- Add Location table.
+- Add LocationId, DeviceId, and MediaTypeId to Media record.
+18Feb06
+- Implement create/get mac record in database for adding extended
+ Migration data to the job record.
+- Add new MAC table to update/make database scripts.
+- Return Storage name used when getting VolumeNames for a job.
+- Change bsr file keyword Storage to Device, which is more accurate.
+- Ensure that Mac records are pruned/purged.
+- Tweak SD tools to deal with changing media type.
+- Integrate more dev.c subroutines as methods (e.g. strerror, bsr, ...)
+- Pass pointer to dcr pointer to acquire_device_for_read() so
+ that the subroutine can switch devices, and hence dcrs.
+- Modify the multiple MediaType read code to re-use the same
+ dcr when switching devices. This makes the code much more
+ robust.
+- Integrate patch from Karl Hakimian that reads JobIds, FileIndexes
+ from a table for restore.
+- Add Storage name to VolParams, but it really should be Device.
14Feb06
- Add disk-changer to scripts directory + configure/Makefile
- Eliminate PoolId from jcr -- it is in jcr->jr.PoolId
--- /dev/null
+--- dvd+rw-tools-6.1.old/growisofs.c 2006-01-26 22:16:54.000000000 +0100
++++ dvd+rw-tools-6.1/growisofs.c 2006-02-15 00:00:44.000000000 +0100
+@@ -355,12 +355,17 @@
+ * - Treat only x73xx OPC errors as fatal;
+ * - Fix typo in -speed scaling code;
+ * - permit tracksize to be not divisible by 32KB in DAO mode;
++ * 6.1.1: (by Nicolas Boichat, Bacula project)
++ * - Allow session to cross 4GB boundary regardless of medium type
++ * (don't need to have a DL media)
++ * - Add a -F option (used instead of -M or -Z), which displays next_session
++ * offset and capacity (free space = next_session - capacity).
+ */
+ #define PRINT_VERSION(cmd) do { \
+ char *s=strrchr((cmd),'/'); \
+ s ? s++ : (s=(cmd)); \
+ printf ("* %.*sgrowisofs by <appro@fy.chalmers.se>,"\
+- " version 6.1,\n",(int)(s-(cmd)),(cmd)); \
++ " version 6.1.1,\n",(int)(s-(cmd)),(cmd)); \
+ } while (0)
+ \f
+ #define _LARGEFILE_SOURCE
+@@ -2329,6 +2334,18 @@
+ else in_device = argv[++i];
+ dev_found = 'Z';
+ }
++ else if (argv[i][1] == 'F')
++ { if (len > 2) in_device = argv[i]+2;
++ else in_device = argv[++i];
++ dev_found = 'F';
++ dry_run = 1; /* NEVER write anything with -F */
++ }
++ else if (!strncmp(opt,"-free-space",11))
++ { if (len > 11) in_device = opt+11;
++ else in_device = argv[++i];
++ dev_found = 'F';
++ dry_run = 1; /* NEVER write anything with -F */
++ }
+ else if (!strcmp(opt,"-poor-man"))
+ { if (poor_man<0) poor_man = 1;
+ continue;
+@@ -2542,7 +2559,9 @@
+ fprintf (stderr," you most likely want to use -Z option.\n"),
+ exit (FATAL_START(errno));
+
+- if (dev_found == 'M')
++ if ((dev_found == 'M') ||
++ ((dev_found == 'F') && !(mmc_profile&0x10000)) && (saved_descriptors[0].type[0] || saved_descriptors[0].type[1] || saved_descriptors[0].type[2]))
++ /* -F : The medium is not blank, there is a fs on it (the_buffer[0,1 or 2] != 0), so compute next_session. */
+ { if (memcmp (saved_descriptors[0].type,"\1CD001",6))
+ fprintf (stderr,":-( %s doesn't look like isofs...\n",
+ in_device), exit(FATAL_START(EMEDIUMTYPE));
+@@ -2565,7 +2584,7 @@
+ exit(FATAL_START(EINVAL));
+ }
+ else if (next_session > (0x200000-0x5000)) /* 4GB/2K-40MB/2K */
+- if ((mmc_profile&0xFFFF)!=0x2B || !no_4gb_check)
++ if (!no_4gb_check)
+ fprintf (stderr,":-( next session would cross 4GB "
+ "boundary, aborting...\n"),
+ exit (FATAL_START(ENOSPC));
+@@ -2608,7 +2627,7 @@
+ exit (FATAL_START(EINVAL));
+
+ if (imgfd<0)
+- { if (mkisofs_argc==1)
++ { if ((mkisofs_argc==1) && (dev_found != 'F'))
+ fprintf (stderr,"%s: no mkisofs options specified, "
+ "aborting...\n",argv[0]),
+ exit (FATAL_START(EINVAL));
+@@ -2880,6 +2899,15 @@
+ }
+ }
+
++ if (dev_found == 'F') {
++ off64_t capacity = 0;
++ printf("next_session=%lld\n", next_session*CD_BLOCK);
++ if (ioctl_handle!=INVALID_HANDLE)
++ capacity = get_capacity (ioctl_handle);
++ printf("capacity=%lld\n", capacity);
++ exit(0);
++ }
++
+ if (imgfd>=0)
+ { quiet--;
+ if (builtin_dd (imgfd,out_fd,next_session*CD_BLOCK) < 0)
uint32_t JobErrors;
uint32_t JobMissingFiles;
uint64_t JobBytes;
+ int PurgedFiles;
+ int HasBase;
/* Note, FirstIndex, LastIndex, Start/End File and Block
* are only used in the JobMedia record.
faddr_t rec_addr;
};
+/*
+ * Suplementary record for Migration, archive, copy jobs
+ */
+/* MAC record */
+struct MAC_DBR {
+ JobId_t JobId; /* Id of this job */
+ JobId_t OriginalJobId; /* Id of job migrated, copied or archived */
+ /*
+ * The following are the actual values for this job. This
+ * is needed because the values in the corresponding Job
+ * record were set to the values of the original backup job.
+ */
+ int JobType; /* Actual job type */
+ int JobLevel; /* Actual job level */
+ time_t SchedTime; /* Actual time job scheduled */
+ time_t StartTime; /* Actual Job start time */
+ time_t EndTime; /* Actual Job termination time */
+ utime_t JobTDate; /* Actual Backup time/date in seconds */
+
+ char cSchedTime[MAX_TIME_LENGTH];
+ char cStartTime[MAX_TIME_LENGTH];
+ char cEndTime[MAX_TIME_LENGTH];
+
+};
+
+
+
/* Job Media information used to create the media records
* for each Volume used for the job.
*/
struct VOL_PARAMS {
char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
char MediaType[MAX_NAME_LENGTH]; /* Media Type */
+ char Storage[MAX_NAME_LENGTH]; /* Storage name */
uint32_t VolIndex; /* Volume seqence no. */
uint32_t FirstIndex; /* First index this Volume */
uint32_t LastIndex; /* Last index this Volume */
uint32_t EndFile; /* End file on Volume */
uint32_t StartBlock; /* start block on tape */
uint32_t EndBlock; /* last block */
+ int32_t Slot; /* Slot */
// uint32_t Copy; /* identical copy */
// uint32_t Stripe; /* RAIT strip number */
};
INDEX (Name(128))
);
+CREATE TABLE MAC (
+ JobId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ OriginalJobId INTEGER UNSIGNED NOT NULL,
+ JobType BINARY(1) NOT NULL,
+ JobLevel BINARY(1) NOT NULL,
+ SchedTime DATETIME NOT NULL,
+ StartTime DATETIME NOT NULL,
+ EndTime DATETIME NOT NULL,
+ JobTDate BIGINT UNSIGNED NOT NULL,
+ PRIMARY KEY(JobId)
+ );
+
+
#
CREATE TABLE FileSet (
FileSetId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
Slot INTEGER NOT NULL DEFAULT 0,
PoolId INTEGER UNSIGNED NOT NULL REFERENCES Pool,
MediaType TINYBLOB NOT NULL,
+ MediaTypeId INTEGER UNSIGNED NOT NULL REFERENCES MediaType,
LabelType TINYINT NOT NULL DEFAULT 0,
FirstWritten DATETIME NOT NULL,
LastWritten DATETIME NOT NULL,
MaxVolBytes BIGINT UNSIGNED NOT NULL DEFAULT 0,
InChanger TINYINT NOT NULL DEFAULT 0,
StorageId INTEGER UNSIGNED NOT NULL REFERENCES Storage,
+ DeviceId INTEGER UNSIGNED NOT NULL REFERENCES Device,
MediaAddressing TINYINT NOT NULL DEFAULT 0,
VolReadTime BIGINT UNSIGNED NOT NULL DEFAULT 0,
VolWriteTime BIGINT UNSIGNED NOT NULL DEFAULT 0,
EndFile INTEGER UNSIGNED NOT NULL DEFAULT 0,
EndBlock INTEGER UNSIGNED NOT NULL DEFAULT 0,
+ LocationId INTEGER UNSIGNED NOT NULL REFERENCES Location,
PRIMARY KEY(MediaId),
INDEX (PoolId)
);
CREATE INDEX job_name_idx on job (name);
+CREATE TABLE MAC (
+ JobId serial not null,
+ OriginalJobId serial not null,
+ JobType char(1) not null,
+ JobLevel char(1) not null,
+ schedtime timestamp without time zone not null,
+ starttime timestamp without time zone,
+ endtime timestamp without time zone,
+ jobtdate bigint not null,
+ primary key (jobid)
+);
+
+
CREATE TABLE fileset
(
filesetid serial not null,
slot integer not null default 0,
poolid integer not null,
mediatype text not null,
+ mediatypeid integer not null,
labeltype integer not null default 0,
firstwritten timestamp without time zone,
lastwritten timestamp without time zone,
maxvolbytes bigint not null default 0,
inchanger smallint not null default 0,
StorageId integer default 0,
+ DeviceId integer default 0,
mediaaddressing smallint not null default 0,
volreadtime bigint not null default 0,
volwritetime bigint not null default 0,
endfile integer not null default 0,
endblock bigint not null default 0,
+ LocationId integer default 0,
primary key (mediaid)
);
CREATE INDEX inx6 ON Job (Name);
+CREATE TABLE MAC (
+ JobId INTEGER,
+ OriginalJobId INTEGER,
+ JobType CHAR NOT NULL,
+ JobLevel CHAR NOT NULL,
+ SchedTime DATETIME NOT NULL,
+ StartTime DATETIME DEFAULT 0,
+ EndTime DATETIME DEFAULT 0,
+ JobTDate BIGINT UNSIGNED DEFAULT 0,
+ PRIMARY KEY(JobId)
+ );
+
+
CREATE TABLE FileSet (
FileSetId INTEGER,
FileSet VARCHAR(128) NOT NULL,
Slot INTEGER DEFAULT 0,
PoolId INTEGER UNSIGNED REFERENCES Pool NOT NULL,
MediaType VARCHAR(128) NOT NULL,
+ MediaTypeId INTEGER UNSIGNED REFERENCES MediaType NOT NULL,
LabelType TINYINT DEFAULT 0,
FirstWritten DATETIME DEFAULT 0,
LastWritten DATETIME DEFAULT 0,
MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
InChanger TINYINT DEFAULT 0,
StorageId INTEGER UNSIGNED REFERENCES Storage,
+ DeviceId INTEGER UNSIGNED REFERENCES Device,
MediaAddressing TINYINT DEFAULT 0,
VolReadTime BIGINT UNSIGNED DEFAULT 0,
VolWriteTime BIGINT UNSIGNED DEFAULT 0,
EndFile INTEGER UNSIGNED DEFAULT 0,
EndBlock INTEGER UNSIGNED DEFAULT 0,
+ LocationId INTEGER UNSIGNED REFERENCES Location,
PRIMARY KEY(MediaId)
);
PRAGMA default_synchronous = OFF;
PRAGMA default_cache_size = 10000;
-PRAGMA synchronous = NORMAL;
END-OF-DATA
CREATE INDEX inx6 ON Job (Name);
+CREATE TABLE MAC (
+ JobId INTEGER,
+ OriginalJobId INTEGER,
+ JobType CHAR NOT NULL,
+ JobLevel CHAR NOT NULL,
+ SchedTime DATETIME NOT NULL,
+ StartTime DATETIME DEFAULT 0,
+ EndTime DATETIME DEFAULT 0,
+ JobTDate BIGINT UNSIGNED DEFAULT 0,
+ PRIMARY KEY(JobId)
+ );
+
+
CREATE TABLE FileSet (
FileSetId INTEGER,
FileSet VARCHAR(128) NOT NULL,
Slot INTEGER DEFAULT 0,
PoolId INTEGER UNSIGNED REFERENCES Pool NOT NULL,
MediaType VARCHAR(128) NOT NULL,
+ MediaTypeId INTEGER UNSIGNED REFERENCES MediaType NOT NULL,
LabelType TINYINT DEFAULT 0,
FirstWritten DATETIME DEFAULT 0,
LastWritten DATETIME DEFAULT 0,
MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
InChanger TINYINT DEFAULT 0,
StorageId INTEGER UNSIGNED REFERENCES Storage,
+ DeviceId INTEGER UNSIGNED REFERENCES Device,
MediaAddressing TINYINT DEFAULT 0,
VolReadTime BIGINT UNSIGNED DEFAULT 0,
VolWriteTime BIGINT UNSIGNED DEFAULT 0,
EndFile INTEGER UNSIGNED DEFAULT 0,
EndBlock INTEGER UNSIGNED DEFAULT 0,
+ LocationId INTEGER UNSIGNED REFERENCES Location,
PRIMARY KEY(MediaId)
);
/* create.c */
int db_create_file_attributes_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
-int db_create_job_record(JCR *jcr, B_DB *db, JOB_DBR *jr);
+bool db_create_job_record(JCR *jcr, B_DB *db, JOB_DBR *jr);
+bool db_create_mac_record(JCR *jcr, B_DB *db, MAC_DBR *mr);
int db_create_media_record(JCR *jcr, B_DB *db, MEDIA_DBR *media_dbr);
int db_create_client_record(JCR *jcr, B_DB *db, CLIENT_DBR *cr);
bool db_create_fileset_record(JCR *jcr, B_DB *db, FILESET_DBR *fsr);
/* get.c */
bool db_get_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pdbr);
int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr);
-int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr);
+bool db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr);
+bool db_get_mac_record(JCR *jcr, B_DB *mdb, MAC_DBR *mr);
int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames);
int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr);
int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr);
/* Create a new record for the Job
- * Returns: 0 on failure
- * 1 on success
+ * Returns: false on failure
+ * true on success
*/
-int
+bool
db_create_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
{
char dt[MAX_TIME_LENGTH];
time_t stime;
struct tm tm;
- int stat;
+ bool ok;
utime_t JobTDate;
char ed1[30];
Mmsg2(&mdb->errmsg, _("Create DB Job record %s failed. ERR=%s\n"),
mdb->cmd, sql_strerror(mdb));
jr->JobId = 0;
- stat = 0;
+ ok = false;
} else {
jr->JobId = sql_insert_id(mdb, N_("Job"));
- stat = 1;
+ ok = true;
}
db_unlock(mdb);
- return stat;
+ return ok;
+}
+
+/* Create a new migration, archive, copy
+ * Returns: false on failure
+ * true on success
+ */
+bool
+db_create_mac_record(JCR *jcr, B_DB *mdb, MAC_DBR *mr)
+{
+ char schedt[MAX_TIME_LENGTH], sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
+ time_t stime;
+ struct tm tm;
+ bool ok;
+ utime_t JobTDate;
+ char ed1[30], ed2[30];
+
+ db_lock(mdb);
+
+ stime = mr->SchedTime;
+ ASSERT(stime != 0);
+
+ localtime_r(&stime, &tm);
+ strftime(schedt, sizeof(schedt), "%Y-%m-%d %T", &tm);
+ JobTDate = (utime_t)stime;
+ localtime_r(&mr->StartTime, &tm);
+ strftime(sdt, sizeof(sdt), "%Y-%m-%d %T", &tm);
+ localtime_r(&mr->EndTime, &tm);
+ strftime(edt, sizeof(edt), "%Y-%m-%d %T", &tm);
+
+ /* Must create it */
+ Mmsg(mdb->cmd,
+"INSERT INTO MAC (OriginaJobId,JobType,JobLevel,SchedTime,"
+"StartTime,EndTime,JobTDate) VALUES "
+"('%s','%c','%c','%s','%s','%s',%s)",
+ edit_int64(mr->OriginalJobId, ed1),
+ (char)(mr->JobType), (char)(mr->JobLevel),
+ schedt, sdt, edt, edit_uint64(JobTDate, ed2));
+
+ if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
+ Mmsg2(&mdb->errmsg, _("Create DB MAC record %s failed. ERR=%s\n"),
+ mdb->cmd, sql_strerror(mdb));
+ mr->JobId = 0;
+ ok = false;
+ } else {
+ mr->JobId = sql_insert_id(mdb, N_("Job"));
+ ok = true;
+ }
+ db_unlock(mdb);
+ return ok;
}
+
/* Create a JobMedia record for medium used this job
* Returns: false on failure
* true on success
/* Must create it */
Mmsg(mdb->cmd,
-"INSERT INTO Media (VolumeName,MediaType,PoolId,MaxVolBytes,VolCapacityBytes,"
-"Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
+"INSERT INTO Media (VolumeName,MediaType,MediaTypeId,PoolId,MaxVolBytes,"
+"VolCapacityBytes,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
"VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime,VolParts,"
-"EndFile,EndBlock,LabelType,StorageId) "
-"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0,%d,%s)",
+"EndFile,EndBlock,LabelType,StorageId,DeviceId,LocationId) "
+"VALUES ('%s','%s',0,%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0,%d,%s,0,0)",
mr->VolumeName,
mr->MediaType, mr->PoolId,
edit_uint64(mr->MaxVolBytes,ed1),
*/
/*
- Copyright (C) 2000-2005 Kern Sibbald
+ Copyright (C) 2000-2006 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
/*
* Get Job record for given JobId or Job name
- * Returns: 0 on failure
- * 1 on success
+ * Returns: false on failure
+ * true on success
*/
-int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
+bool db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
{
SQL_ROW row;
char ed1[50];
if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
db_unlock(mdb);
- return 0; /* failed */
+ return false; /* failed */
}
if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(mdb->errmsg, _("No Job found for JobId %s\n"), edit_int64(jr->JobId, ed1));
sql_free_result(mdb);
db_unlock(mdb);
- return 0; /* failed */
+ return false; /* failed */
}
jr->VolSessionId = str_to_uint64(row[0]);
bstrncpy(jr->Name, row[13]!=NULL?row[13]:"", sizeof(jr->Name));
sql_free_result(mdb);
+ db_unlock(mdb);
+ return true;
+}
+
+/*
+ * Get MAC record for given JobId
+ * Returns: false on failure
+ * true on success
+ */
+bool db_get_mac_record(JCR *jcr, B_DB *mdb, MAC_DBR *mr)
+{
+ SQL_ROW row;
+ char ed1[50];
+
+ db_lock(mdb);
+ Mmsg(mdb->cmd, "SELECT OriginalJobId,JobType,JobLevel,"
+"SchedTime,StartTime,EndTime,JobTDate"
+"FROM MAC WHERE JobId=%s",
+ edit_int64(mr->JobId, ed1));
+
+ if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
+ db_unlock(mdb);
+ return 0; /* failed */
+ }
+ if ((row = sql_fetch_row(mdb)) == NULL) {
+ Mmsg1(mdb->errmsg, _("No MAC record found for JobId %s\n"), ed1);
+ sql_free_result(mdb);
+ db_unlock(mdb);
+ return false; /* failed */
+ }
+
+ mr->OriginalJobId = str_to_int64(row[0]);
+ mr->JobType = (int)*row[1];
+ mr->JobLevel = (int)*row[2];
+ bstrncpy(mr->cSchedTime, row[3]!=NULL?row[3]:"", sizeof(mr->cSchedTime));
+ bstrncpy(mr->cStartTime, row[4]!=NULL?row[4]:"", sizeof(mr->cStartTime));
+ bstrncpy(mr->cEndTime, row[5]!=NULL?row[5]:"", sizeof(mr->cEndTime));
+ mr->JobTDate = str_to_int64(row[6]);
+ sql_free_result(mdb);
+
db_unlock(mdb);
return 1;
}
+
/*
* Find VolumeNames for a given JobId
* Returns: 0 on error or no Volumes found
db_lock(mdb);
Mmsg(mdb->cmd,
"SELECT VolumeName,MediaType,FirstIndex,LastIndex,StartFile,"
-"JobMedia.EndFile,StartBlock,JobMedia.EndBlock,Copy,Stripe"
+"JobMedia.EndFile,StartBlock,JobMedia.EndBlock,Copy,Stripe,"
+"Slot,StorageId"
" FROM JobMedia,Media WHERE JobMedia.JobId=%s"
" AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
edit_int64(JobId, ed1));
Dmsg1(130, "VolNam=%s\n", mdb->cmd);
if (QUERY_DB(jcr, mdb, mdb->cmd)) {
mdb->num_rows = sql_num_rows(mdb);
- Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
+ Dmsg1(200, "Num rows=%d\n", mdb->num_rows);
if (mdb->num_rows <= 0) {
Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
stat = 0;
} else {
stat = mdb->num_rows;
+ DBId_t *SId;
if (stat > 0) {
*VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
+ SId = (DBId_t *)malloc(stat * sizeof(DBId_t));
}
for (i=0; i < stat; i++) {
if ((row = sql_fetch_row(mdb)) == NULL) {
stat = 0;
break;
} else {
+ DBId_t StorageId;
bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
Vols[i].FirstIndex = str_to_uint64(row[2]);
Vols[i].EndBlock = str_to_uint64(row[7]);
// Vols[i].Copy = str_to_uint64(row[8]);
// Vols[i].Stripe = str_to_uint64(row[9]);
+ Vols[i].Slot = str_to_uint64(row[10]);
+ StorageId = str_to_uint64(row[11]);
+ Vols[i].Storage[0] = 0;
+ SId[i] = StorageId;
+ }
+ }
+ for (i=0; i < stat; i++) {
+ if (SId[i] != 0) {
+ Mmsg(mdb->cmd, "SELECT Name from Storage WHERE StorageId=%s",
+ edit_int64(SId[i], ed1));
+ if (QUERY_DB(jcr, mdb, mdb->cmd)) {
+ if ((row = sql_fetch_row(mdb)) != NULL) {
+ bstrncpy(Vols[i].Storage, row[0], MAX_NAME_LENGTH);
+ }
+ }
}
}
}
#!/bin/sh
#
-# Shell script to update MySQL tables from version 1.36 to 1.38
+# Shell script to update MySQL tables from version 1.38 to 1.39
#
echo " "
-echo "This script will update a Bacula MySQL database from version 8 to 9"
+echo "This script will update a Bacula MySQL database from version 9 to 9"
echo "Depending on the size of your database,"
echo "this script may take several minutes to run."
echo " "
if $bindir/mysql $* -f <<END-OF-DATA
USE bacula;
-ALTER TABLE Media ADD COLUMN LabelType INTEGER UNSIGNED NOT NULL DEFAULT 0;
-ALTER TABLE Media ADD COLUMN StorageId INTEGER UNSIGNED DEFAULT 0 REFERENCES Storage;
-ALTER TABLE Media ADD COLUMN VolParts INTEGER UNSIGNED NOT NULL DEFAULT 0;
-
-ALTER TABLE Pool ADD COLUMN LabelType INTEGER UNSIGNED NOT NULL DEFAULT 0;
-ALTER TABLE Pool ADD COLUMN NextPoolId INTEGER UNSIGNED DEFAULT 0 REFERENCES Pool;
-ALTER TABLE Pool ADD COLUMN MigrationHighBytes BIGINT UNSIGNED DEFAULT 0;
-ALTER TABLE Pool ADD COLUMN MigrationLowBytes BIGINT UNSIGNED DEFAULT 0;
-ALTER TABLE Pool ADD COLUMN MigrationTime BIGINT UNSIGNED DEFAULT 0;
-
-ALTER TABLE JobMedia ADD COLUMN Copy INTEGER UNSIGNED NOT NULL DEFAULT 0;
-ALTER TABLE JobMedia ADD COLUMN Stripe INTEGER UNSIGNED NOT NULL DEFAULT 0;
-
-
-CREATE TABLE MediaType (
- MediaTypeId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- MediaType VARCHAR(128) NOT NULL,
- ReadOnly TINYINT DEFAULT 0,
- PRIMARY KEY(MediaTypeId)
+ALTER TABLE Media ADD COLUMN MediaTypeId INTEGER UNSIGNED DEFAULT 0 REFERENCES MediaType;
+ALTER TABLE Media ADD COLUMN DeviceId INTEGER UNSIGNED DEFAULT 0 REFERENCES Device;
+ALTER TABLE Media ADD COLUMN LocationId INTEGER UNSIGNED DEFAULT 0 REFERENCES Location;
+
+
+CREATE TABLE MAC (
+ JobId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ OriginalJobId INTEGER UNSIGNED NOT NULL,
+ JobType BINARY(1) NOT NULL,
+ JobLevel BINARY(1) NOT NULL,
+ SchedTime DATETIME NOT NULL,
+ StartTime DATETIME NOT NULL,
+ EndTime DATETIME NOT NULL,
+ JobTDate BIGINT UNSIGNED NOT NULL,
+ PRIMARY KEY(JobId)
);
-CREATE TABLE Storage (
- StorageId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- Name VARCHAR(128) NOT NULL,
- AutoChanger TINYINT DEFAULT 0,
- PRIMARY KEY(StorageId)
+CREATE TABLE Location (
+ LocationId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ Location TINYBLOB NOT NULL,
+ PRIMARY KEY(LocationId)
);
-CREATE TABLE Device (
- DeviceId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- Name VARCHAR(128) NOT NULL,
- MediaTypeId INTEGER UNSIGNED NOT NULL REFERENCES MediaType,
- StorageId INTEGER UNSIGNED REFERENCES Storage,
- DevMounts INTEGER UNSIGNED DEFAULT 0,
- DevReadBytes BIGINT UNSIGNED DEFAULT 0,
- DevWriteBytes BIGINT UNSIGNED DEFAULT 0,
- DevReadBytesSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- DevWriteBytesSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- DevReadTime BIGINT UNSIGNED DEFAULT 0,
- DevWriteTime BIGINT UNSIGNED DEFAULT 0,
- DevReadTimeSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- DevWriteTimeSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- CleaningDate DATETIME DEFAULT 0,
- CleaningPeriod BIGINT UNSIGNED DEFAULT 0,
- PRIMARY KEY(DeviceId)
- );
-
-CREATE TABLE Status (
- JobStatus CHAR(1) BINARY NOT NULL,
- JobStatusLong BLOB,
- PRIMARY KEY (JobStatus)
- );
-
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('C', 'Created, not yet running'),
- ('R', 'Running'),
- ('B', 'Blocked'),
- ('T', 'Completed successfully'),
- ('E', 'Terminated with errors'),
- ('e', 'Non-fatal error'),
- ('f', 'Fatal error'),
- ('D', 'Verify found differences'),
- ('A', 'Canceled by user'),
- ('F', 'Waiting for Client'),
- ('S', 'Waiting for Storage daemon'),
- ('m', 'Waiting for new media'),
- ('M', 'Waiting for media mount'),
- ('s', 'Waiting for storage resource'),
- ('j', 'Waiting for job resource'),
- ('c', 'Waiting for client resource'),
- ('d', 'Waiting on maximum jobs'),
- ('t', 'Waiting on start time'),
- ('p', 'Waiting on higher priority jobs');
-
DELETE FROM Version;
INSERT INTO Version (VersionId) VALUES (9);
#!/bin/sh
#
-# Shell script to update PostgreSQL tables from version 1.36 to 1.38
+# Shell script to update PostgreSQL tables from version 1.38 to 1.39
#
echo " "
-echo "This script will update a Bacula PostgreSQL database from version 8 to 9"
+echo "This script will update a Bacula PostgreSQL database from version 9 to 9"
echo "Depending on the size of your database,"
echo "this script may take several minutes to run."
echo " "
if $bindir/psql -f - -d bacula $* <<END-OF-DATA
-ALTER TABLE media ADD COLUMN labeltype integer;
-UPDATE media SET labeltype=0;
-ALTER TABLE media ALTER COLUMN labeltype SET NOT NULL;
-ALTER TABLE media ADD COLUMN StorageId integer;
-UPDATE media SET StorageId=0;
-
-ALTER TABLE pool ADD COLUMN labeltype integer;
-UPDATE pool set labeltype=0;
-ALTER TABLE pool ALTER COLUMN labeltype SET NOT NULL;
-ALTER TABLE pool ADD COLUMN NextPoolId integer;
-UPDATE pool SET NextPoolId=0;
-ALTER TABLE pool ADD COLUMN MigrationHighBytes BIGINT;
-UPDATE pool SET MigrationHighBytes=0;
-ALTER TABLE pool ADD COLUMN MigrationLowBytes BIGINT;
-UPDATE pool SET MigrationLowBytes=0;
-ALTER TABLE pool ADD COLUMN MigrationTime BIGINT;
-UPDATE pool SET MigrationTime=0;
-
-
-ALTER TABLE jobmedia ADD COLUMN Copy integer;
-UPDATE jobmedia SET Copy=0;
-ALTER TABLE jobmedia ADD COLUMN Stripe integer;
-UPDATE jobmedia SET Stripe=0;
-
-
-ALTER TABLE media ADD COLUMN volparts integer;
-UPDATE media SET volparts=0;
-ALTER TABLE media ALTER COLUMN volparts SET NOT NULL;
-
-CREATE TABLE MediaType (
- MediaTypeId SERIAL,
- MediaType TEXT NOT NULL,
- ReadOnly INTEGER DEFAULT 0,
- PRIMARY KEY(MediaTypeId)
+ALTER TABLE media ADD COLUMN DeviceId integer;
+UPDATE media SET DeviceId=0;
+ALTER TABLE media ADD COLUMN MediaTypeId integer;
+UPDATE media SET MediaTypeId=0;
+ALTER TABLE media ADD COLUMN LocationId integer;
+UPDATE media SET LocationId=0;
+
+
+CREATE TABLE MAC (
+ JobId serial not null,
+ OriginalJobId serial not null,
+ JobType char(1) not null,
+ JobLevel char(1) not null,
+ SchedTime timestamp without time zone not null,
+ StartTime timestamp without time zone,
+ EndTime timestamp without time zone,
+ JobTDate bigint not null,
+ primary key (JobId)
+);
+
+CREATE TABLE Location (
+ LocationId SERIAL,
+ Location TEXT NOT NULL,
+ PRIMARY KEY(LocationId)
);
-CREATE TABLE Device (
- DeviceId SERIAL,
- Name TEXT NOT NULL,
- MediaTypeId INTEGER NOT NULL,
- StorageId INTEGER,
- DevMounts INTEGER NOT NULL DEFAULT 0,
- DevReadBytes BIGINT NOT NULL DEFAULT 0,
- DevWriteBytes BIGINT NOT NULL DEFAULT 0,
- DevReadBytesSinceCleaning BIGINT NOT NULL DEFAULT 0,
- DevWriteBytesSinceCleaning BIGINT NOT NULL DEFAULT 0,
- DevReadTime BIGINT NOT NULL DEFAULT 0,
- DevWriteTime BIGINT NOT NULL DEFAULT 0,
- DevReadTimeSinceCleaning BIGINT NOT NULL DEFAULT 0,
- DevWriteTimeSinceCleaning BIGINT DEFAULT 0,
- CleaningDate TIMESTAMP WITHOUT TIME ZONE,
- CleaningPeriod BIGINT NOT NULL DEFAULT 0,
- PRIMARY KEY(DeviceId)
- );
-
-CREATE TABLE Storage (
- StorageId SERIAL,
- Name TEXT NOT NULL,
- AutoChanger INTEGER DEFAULT 0,
- PRIMARY KEY(StorageId)
- );
-
-CREATE TABLE Status (
- JobStatus CHAR(1) NOT NULL,
- JobStatusLong TEXT,
- PRIMARY KEY (JobStatus)
- );
-
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('C', 'Created, not yet running');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('R', 'Running');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('B', 'Blocked');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('T', 'Completed successfully');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('E', 'Terminated with errors');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('e', 'Non-fatal error');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('f', 'Fatal error');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('D', 'Verify found differences');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('A', 'Canceled by user');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('F', 'Waiting for Client');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('S', 'Waiting for Storage daemon');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('m', 'Waiting for new media');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('M', 'Waiting for media mount');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('s', 'Waiting for storage resource');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('j', 'Waiting for job resource');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('c', 'Waiting for client resource');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('d', 'Waiting on maximum jobs');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('t', 'Waiting on start time');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('p', 'Waiting on higher priority jobs');
-
-DELETE FROM version;
INSERT INTO version (versionId) VALUES (9);
vacuum;
#!/bin/sh
#
-# shell script to update SQLite from version 1.36 to 1.38
+# shell script to update SQLite from version 1.38 to 1.39
#
echo " "
-echo "This script will update a Bacula SQLite database from version 8 to 9"
+echo "This script will update a Bacula SQLite database from version 9 to 9"
echo "Depending on the size of your database,"
echo "this script may take several minutes to run."
echo " "
${bindir}/${sqlite} $* bacula.db <<END-OF-DATA
BEGIN TRANSACTION;
+
CREATE TEMPORARY TABLE Media_backup (
MediaId INTEGER UNSIGNED AUTOINCREMENT,
VolumeName VARCHAR(128) NOT NULL,
Slot INTEGER DEFAULT 0,
PoolId INTEGER UNSIGNED REFERENCES Pool NOT NULL,
MediaType VARCHAR(128) NOT NULL,
+ MediaTypeId INTEGER UNSIGNED REFERENCES MediaType NOT NULL,
LabelType TINYINT DEFAULT 0,
FirstWritten DATETIME DEFAULT 0,
LastWritten DATETIME DEFAULT 0,
MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
InChanger TINYINT DEFAULT 0,
StorageId INTEGER UNSIGNED REFERENCES Storage,
+ DeviceId INTEGER UNSIGNED REFERENCES Device,
MediaAddressing TINYINT DEFAULT 0,
VolReadTime BIGINT UNSIGNED DEFAULT 0,
VolWriteTime BIGINT UNSIGNED DEFAULT 0,
EndFile INTEGER UNSIGNED DEFAULT 0,
EndBlock INTEGER UNSIGNED DEFAULT 0,
+ LocationId INTEGER UNSIGNED REFERENCES Location,
PRIMARY KEY(MediaId)
);
INSERT INTO Media_backup SELECT
MediaId, VolumeName, Slot, PoolId,
- MediaType, 0, FirstWritten, LastWritten,
+ MediaType, LabelType, 0, FirstWritten, LastWritten,
LabelDate, VolJobs, VolFiles, VolBlocks,
- VolMounts, VolBytes, 0, VolErrors, VolWrites,
+ VolMounts, VolBytes, VolParts, VolErrors, VolWrites,
VolCapacityBytes, VolStatus, Recycle,
VolRetention, VolUseDuration, MaxVolJobs,
- MaxVolFiles, MaxVolBytes, InChanger, 0, MediaAddressing,
- VolReadTime, VolWriteTime, EndFile, EndBlock
+ MaxVolFiles, MaxVolBytes, InChanger,
+ StorageId, 0, MediaAddressing,
+ VolReadTime, VolWriteTime, EndFile, EndBlock, 0
FROM Media;
Slot INTEGER DEFAULT 0,
PoolId INTEGER UNSIGNED REFERENCES Pool NOT NULL,
MediaType VARCHAR(128) NOT NULL,
+ MediaTypeId INTEGER UNSIGNED REFERENCES MediaType NOT NULL,
LabelType TINYINT DEFAULT 0,
FirstWritten DATETIME DEFAULT 0,
LastWritten DATETIME DEFAULT 0,
MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
InChanger TINYINT DEFAULT 0,
StorageId INTEGER UNSIGNED REFERENCES Storage,
+ DeviceId INTEGER UNSIGNED REFERENCES Device,
MediaAddressing TINYINT DEFAULT 0,
VolReadTime BIGINT UNSIGNED DEFAULT 0,
VolWriteTime BIGINT UNSIGNED DEFAULT 0,
EndFile INTEGER UNSIGNED DEFAULT 0,
EndBlock INTEGER UNSIGNED DEFAULT 0,
+ LocationId INTEGER UNSIGNED REFERENCES Location,
PRIMARY KEY(MediaId)
);
INSERT INTO Media (
MediaId, VolumeName, Slot, PoolId,
- MediaType, LabelType, FirstWritten, LastWritten,
+ MediaType, MediaTypeId, LabelType, FirstWritten, LastWritten,
LabelDate, VolJobs, VolFiles, VolBlocks,
VolMounts, VolBytes, VolParts, VolErrors, VolWrites,
VolCapacityBytes, VolStatus, Recycle,
VolRetention, VolUseDuration, MaxVolJobs,
MaxVolFiles, MaxVolBytes,
- InChanger, StorageId, MediaAddressing,
+ InChanger, StorageId, DeviceId, MediaAddressing,
VolReadTime, VolWriteTime,
- EndFile, EndBlock)
+ EndFile, EndBlock, LocationId)
SELECT * FROM Media_backup;
DROP TABLE Media_backup;
CREATE INDEX inx8 ON Media (PoolId);
-CREATE TEMPORARY TABLE JobMedia_backup (
- JobMediaId INTEGER,
- JobId INTEGER UNSIGNED REFERENCES Job NOT NULL,
- MediaId INTEGER UNSIGNED REFERENCES Media NOT NULL,
- FirstIndex INTEGER UNSIGNED NOT NULL,
- LastIndex INTEGER UNSIGNED NOT NULL,
- StartFile INTEGER UNSIGNED DEFAULT 0,
- EndFile INTEGER UNSIGNED DEFAULT 0,
- StartBlock INTEGER UNSIGNED DEFAULT 0,
- EndBlock INTEGER UNSIGNED DEFAULT 0,
- VolIndex INTEGER UNSIGNED DEFAULT 0,
- Copy INTEGER UNSIGNED DEFAULT 0,
- Stripe INTEGER UNSIGNED DEFAULT 0,
- PRIMARY KEY(JobMediaId)
- );
-
-INSERT INTO JobMedia_backup SELECT
- JobMediaId, JobId, MediaId,
- FirstIndex, LastIndex, StartFile,
- EndFile, StartBlock, EndBlock,
- VolIndex, 0, 0
- FROM JobMedia;
-
-DROP TABLE JobMedia;
-
-CREATE TABLE JobMedia (
- JobMediaId INTEGER,
- JobId INTEGER UNSIGNED REFERENCES Job NOT NULL,
- MediaId INTEGER UNSIGNED REFERENCES Media NOT NULL,
- FirstIndex INTEGER UNSIGNED NOT NULL,
- LastIndex INTEGER UNSIGNED NOT NULL,
- StartFile INTEGER UNSIGNED DEFAULT 0,
- EndFile INTEGER UNSIGNED DEFAULT 0,
- StartBlock INTEGER UNSIGNED DEFAULT 0,
- EndBlock INTEGER UNSIGNED DEFAULT 0,
- VolIndex INTEGER UNSIGNED DEFAULT 0,
- Copy INTEGER UNSIGNED DEFAULT 0,
- Stripe INTEGER UNSIGNED DEFAULT 0,
- PRIMARY KEY(JobMediaId)
- );
-
-INSERT INTO JobMedia (
- JobMediaId, JobId, MediaId,
- FirstIndex, LastIndex, StartFile,
- EndFile, StartBlock, EndBlock,
- VolIndex, Copy, Stripe)
- SELECT * FROM JobMedia_backup;
-
-DROP TABLE JobMedia_backup;
-
-CREATE TEMPORARY TABLE Pool_backup (
- PoolId INTEGER,
- Name VARCHAR(128) NOT NULL,
- NumVols INTEGER UNSIGNED DEFAULT 0,
- MaxVols INTEGER UNSIGNED DEFAULT 0,
- UseOnce TINYINT DEFAULT 0,
- UseCatalog TINYINT DEFAULT 1,
- AcceptAnyVolume TINYINT DEFAULT 0,
- VolRetention BIGINT UNSIGNED DEFAULT 0,
- VolUseDuration BIGINT UNSIGNED DEFAULT 0,
- MaxVolJobs INTEGER UNSIGNED DEFAULT 0,
- MaxVolFiles INTEGER UNSIGNED DEFAULT 0,
- MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
- AutoPrune TINYINT DEFAULT 0,
- Recycle TINYINT DEFAULT 0,
- PoolType VARCHAR(20) NOT NULL,
- LabelType TINYINT DEFAULT 0,
- LabelFormat VARCHAR(128) NOT NULL,
- Enabled TINYINT DEFAULT 1,
- ScratchPoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- RecyclePoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- NextPoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- MigrationHighBytes BIGINT UNSIGNED DEFAULT 0,
- MigrationLowBytes BIGINT UNSIGNED DEFAULT 0,
- MigrationTime BIGINT UNSIGNED DEFAULT 0,
- UNIQUE (Name),
- PRIMARY KEY (PoolId)
- );
-
-INSERT INTO Pool_backup SELECT
- PoolId, Name, NumVols, MaxVols,
- UseOnce, UseCatalog, AcceptAnyVolume,
- VolRetention, VolUseDuration, MaxVolJobs,
- MaxVolFiles, MaxVolBytes, AutoPrune,
- Recycle, PoolType, 0, LabelFormat,
- Enabled, ScratchPoolId, RecyclePoolId,
- 0, 0, 0, 0
- FROM Pool;
-
-DROP TABLE Pool;
-
-CREATE TABLE Pool (
- PoolId INTEGER,
- Name VARCHAR(128) NOT NULL,
- NumVols INTEGER UNSIGNED DEFAULT 0,
- MaxVols INTEGER UNSIGNED DEFAULT 0,
- UseOnce TINYINT DEFAULT 0,
- UseCatalog TINYINT DEFAULT 1,
- AcceptAnyVolume TINYINT DEFAULT 0,
- VolRetention BIGINT UNSIGNED DEFAULT 0,
- VolUseDuration BIGINT UNSIGNED DEFAULT 0,
- MaxVolJobs INTEGER UNSIGNED DEFAULT 0,
- MaxVolFiles INTEGER UNSIGNED DEFAULT 0,
- MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
- AutoPrune TINYINT DEFAULT 0,
- Recycle TINYINT DEFAULT 0,
- PoolType VARCHAR(20) NOT NULL,
- LabelType TINYINT DEFAULT 0,
- LabelFormat VARCHAR(128) NOT NULL,
- Enabled TINYINT DEFAULT 1,
- ScratchPoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- RecyclePoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- NextPoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- MigrationHighBytes BIGINT UNSIGNED DEFAULT 0,
- MigrationLowBytes BIGINT UNSIGNED DEFAULT 0,
- MigrationTime BIGINT UNSIGNED DEFAULT 0,
- UNIQUE (Name),
- PRIMARY KEY (PoolId)
+CREATE TABLE MAC (
+ JobId INTEGER,
+ OriginalJobId INTEGER,
+ JobType CHAR NOT NULL,
+ JobLevel CHAR NOT NULL,
+ SchedTime DATETIME NOT NULL,
+ StartTime DATETIME DEFAULT 0,
+ EndTime DATETIME DEFAULT 0,
+ JobTDate BIGINT UNSIGNED DEFAULT 0,
+ PRIMARY KEY(JobId)
);
-INSERT INTO Pool (
- PoolId, Name, NumVols, MaxVols,
- UseOnce, UseCatalog, AcceptAnyVolume,
- VolRetention, VolUseDuration, MaxVolJobs,
- MaxVolFiles, MaxVolBytes, AutoPrune,
- Recycle, PoolType, LabelType, LabelFormat,
- Enabled, ScratchPoolId, RecyclePoolId,
- NextPoolId, MigrationHighBytes,
- MigrationLowBytes, MigrationTime )
- SELECT * FROM Pool_backup;
-
-DROP TABLE Pool_backup;
-
-CREATE TABLE MediaType (
- MediaTypeId INTEGER,
- MediaType VARCHAR(128) NOT NULL,
- ReadOnly TINYINT DEFAULT 0,
- PRIMARY KEY(MediaTypeId)
- );
-
-CREATE TABLE Storage (
- StorageId INTEGER,
- Name VARCHAR(128) NOT NULL,
- AutoChanger TINYINT DEFAULT 0,
- PRIMARY KEY(StorageId)
- );
-
-CREATE TABLE Device (
- DeviceId INTEGER,
- Name VARCHAR(128) NOT NULL,
- MediaTypeId INTEGER UNSIGNED REFERENCES MediaType NOT NULL,
- StorageId INTEGER UNSIGNED REFERENCES Storage,
- DevMounts INTEGER UNSIGNED DEFAULT 0,
- DevReadBytes BIGINT UNSIGNED DEFAULT 0,
- DevWriteBytes BIGINT UNSIGNED DEFAULT 0,
- DevReadBytesSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- DevWriteBytesSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- DevReadTime BIGINT UNSIGNED DEFAULT 0,
- DevWriteTime BIGINT UNSIGNED DEFAULT 0,
- DevReadTimeSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- DevWriteTimeSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- CleaningDate DATETIME DEFAULT 0,
- CleaningPeriod BIGINT UNSIGNED DEFAULT 0,
- PRIMARY KEY(DeviceId)
- );
-
-
-CREATE TABLE Status (
- JobStatus CHAR(1) NOT NULL,
- JobStatusLong BLOB,
- PRIMARY KEY (JobStatus)
+CREATE TABLE Location (
+ LocationId INTEGER,
+ Location VARCHAR(128) NOT NULL,
+ PRIMARY KEY(LocationId)
);
-
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('C', 'Created, not yet running');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('R', 'Running');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('B', 'Blocked');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('T', 'Completed successfully');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('E', 'Terminated with errors');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('e', 'Non-fatal error');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('f', 'Fatal error');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('D', 'Verify found differences');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('A', 'Canceled by user');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('F', 'Waiting for Client');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('S', 'Waiting for Storage daemon');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('m', 'Waiting for new media');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('M', 'Waiting for media mount');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('s', 'Waiting for storage resource');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('j', 'Waiting for job resource');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('c', 'Waiting for client resource');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('d', 'Waiting on maximum jobs');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('t', 'Waiting on start time');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('p', 'Waiting on higher priority jobs');
-
+
DELETE FROM Version;
INSERT INTO Version (VersionId) VALUES (9);
#!/bin/sh
#
-# shell script to update SQLite from version 1.36 to 1.38
+# shell script to update SQLite from version 1.38 to 1.39
#
echo " "
-echo "This script will update a Bacula SQLite database from version 8 to 9"
+echo "This script will update a Bacula SQLite database from version 9 to 9"
echo "Depending on the size of your database,"
echo "this script may take several minutes to run."
echo " "
${bindir}/${sqlite} $* bacula.db <<END-OF-DATA
BEGIN TRANSACTION;
+
CREATE TEMPORARY TABLE Media_backup (
MediaId INTEGER UNSIGNED AUTOINCREMENT,
VolumeName VARCHAR(128) NOT NULL,
Slot INTEGER DEFAULT 0,
PoolId INTEGER UNSIGNED REFERENCES Pool NOT NULL,
MediaType VARCHAR(128) NOT NULL,
+ MediaTypeId INTEGER UNSIGNED REFERENCES MediaType NOT NULL,
LabelType TINYINT DEFAULT 0,
FirstWritten DATETIME DEFAULT 0,
LastWritten DATETIME DEFAULT 0,
MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
InChanger TINYINT DEFAULT 0,
StorageId INTEGER UNSIGNED REFERENCES Storage,
+ DeviceId INTEGER UNSIGNED REFERENCES Device,
MediaAddressing TINYINT DEFAULT 0,
VolReadTime BIGINT UNSIGNED DEFAULT 0,
VolWriteTime BIGINT UNSIGNED DEFAULT 0,
EndFile INTEGER UNSIGNED DEFAULT 0,
EndBlock INTEGER UNSIGNED DEFAULT 0,
+ LocationId INTEGER UNSIGNED REFERENCES Location,
PRIMARY KEY(MediaId)
);
INSERT INTO Media_backup SELECT
MediaId, VolumeName, Slot, PoolId,
- MediaType, 0, FirstWritten, LastWritten,
+ MediaType, LabelType, 0, FirstWritten, LastWritten,
LabelDate, VolJobs, VolFiles, VolBlocks,
- VolMounts, VolBytes, 0, VolErrors, VolWrites,
+ VolMounts, VolBytes, VolParts, VolErrors, VolWrites,
VolCapacityBytes, VolStatus, Recycle,
VolRetention, VolUseDuration, MaxVolJobs,
- MaxVolFiles, MaxVolBytes, InChanger, 0, MediaAddressing,
- VolReadTime, VolWriteTime, EndFile, EndBlock
+ MaxVolFiles, MaxVolBytes, InChanger,
+ StorageId, 0, MediaAddressing,
+ VolReadTime, VolWriteTime, EndFile, EndBlock, 0
FROM Media;
Slot INTEGER DEFAULT 0,
PoolId INTEGER UNSIGNED REFERENCES Pool NOT NULL,
MediaType VARCHAR(128) NOT NULL,
+ MediaTypeId INTEGER UNSIGNED REFERENCES MediaType NOT NULL,
LabelType TINYINT DEFAULT 0,
FirstWritten DATETIME DEFAULT 0,
LastWritten DATETIME DEFAULT 0,
MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
InChanger TINYINT DEFAULT 0,
StorageId INTEGER UNSIGNED REFERENCES Storage,
+ DeviceId INTEGER UNSIGNED REFERENCES Device,
MediaAddressing TINYINT DEFAULT 0,
VolReadTime BIGINT UNSIGNED DEFAULT 0,
VolWriteTime BIGINT UNSIGNED DEFAULT 0,
EndFile INTEGER UNSIGNED DEFAULT 0,
EndBlock INTEGER UNSIGNED DEFAULT 0,
+ LocationId INTEGER UNSIGNED REFERENCES Location,
PRIMARY KEY(MediaId)
);
INSERT INTO Media (
MediaId, VolumeName, Slot, PoolId,
- MediaType, LabelType, FirstWritten, LastWritten,
+ MediaType, MediaTypeId, LabelType, FirstWritten, LastWritten,
LabelDate, VolJobs, VolFiles, VolBlocks,
VolMounts, VolBytes, VolParts, VolErrors, VolWrites,
VolCapacityBytes, VolStatus, Recycle,
VolRetention, VolUseDuration, MaxVolJobs,
MaxVolFiles, MaxVolBytes,
- InChanger, StorageId, MediaAddressing,
+ InChanger, StorageId, DeviceId, MediaAddressing,
VolReadTime, VolWriteTime,
- EndFile, EndBlock)
+ EndFile, EndBlock, LocationId)
SELECT * FROM Media_backup;
DROP TABLE Media_backup;
CREATE INDEX inx8 ON Media (PoolId);
-CREATE TEMPORARY TABLE JobMedia_backup (
- JobMediaId INTEGER,
- JobId INTEGER UNSIGNED REFERENCES Job NOT NULL,
- MediaId INTEGER UNSIGNED REFERENCES Media NOT NULL,
- FirstIndex INTEGER UNSIGNED NOT NULL,
- LastIndex INTEGER UNSIGNED NOT NULL,
- StartFile INTEGER UNSIGNED DEFAULT 0,
- EndFile INTEGER UNSIGNED DEFAULT 0,
- StartBlock INTEGER UNSIGNED DEFAULT 0,
- EndBlock INTEGER UNSIGNED DEFAULT 0,
- VolIndex INTEGER UNSIGNED DEFAULT 0,
- Copy INTEGER UNSIGNED DEFAULT 0,
- Stripe INTEGER UNSIGNED DEFAULT 0,
- PRIMARY KEY(JobMediaId)
- );
-
-INSERT INTO JobMedia_backup SELECT
- JobMediaId, JobId, MediaId,
- FirstIndex, LastIndex, StartFile,
- EndFile, StartBlock, EndBlock,
- VolIndex, 0, 0
- FROM JobMedia;
-
-DROP TABLE JobMedia;
-
-CREATE TABLE JobMedia (
- JobMediaId INTEGER,
- JobId INTEGER UNSIGNED REFERENCES Job NOT NULL,
- MediaId INTEGER UNSIGNED REFERENCES Media NOT NULL,
- FirstIndex INTEGER UNSIGNED NOT NULL,
- LastIndex INTEGER UNSIGNED NOT NULL,
- StartFile INTEGER UNSIGNED DEFAULT 0,
- EndFile INTEGER UNSIGNED DEFAULT 0,
- StartBlock INTEGER UNSIGNED DEFAULT 0,
- EndBlock INTEGER UNSIGNED DEFAULT 0,
- VolIndex INTEGER UNSIGNED DEFAULT 0,
- Copy INTEGER UNSIGNED DEFAULT 0,
- Stripe INTEGER UNSIGNED DEFAULT 0,
- PRIMARY KEY(JobMediaId)
- );
-
-INSERT INTO JobMedia (
- JobMediaId, JobId, MediaId,
- FirstIndex, LastIndex, StartFile,
- EndFile, StartBlock, EndBlock,
- VolIndex, Copy, Stripe)
- SELECT * FROM JobMedia_backup;
-
-DROP TABLE JobMedia_backup;
-
-CREATE TEMPORARY TABLE Pool_backup (
- PoolId INTEGER,
- Name VARCHAR(128) NOT NULL,
- NumVols INTEGER UNSIGNED DEFAULT 0,
- MaxVols INTEGER UNSIGNED DEFAULT 0,
- UseOnce TINYINT DEFAULT 0,
- UseCatalog TINYINT DEFAULT 1,
- AcceptAnyVolume TINYINT DEFAULT 0,
- VolRetention BIGINT UNSIGNED DEFAULT 0,
- VolUseDuration BIGINT UNSIGNED DEFAULT 0,
- MaxVolJobs INTEGER UNSIGNED DEFAULT 0,
- MaxVolFiles INTEGER UNSIGNED DEFAULT 0,
- MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
- AutoPrune TINYINT DEFAULT 0,
- Recycle TINYINT DEFAULT 0,
- PoolType VARCHAR(20) NOT NULL,
- LabelType TINYINT DEFAULT 0,
- LabelFormat VARCHAR(128) NOT NULL,
- Enabled TINYINT DEFAULT 1,
- ScratchPoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- RecyclePoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- NextPoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- MigrationHighBytes BIGINT UNSIGNED DEFAULT 0,
- MigrationLowBytes BIGINT UNSIGNED DEFAULT 0,
- MigrationTime BIGINT UNSIGNED DEFAULT 0,
- UNIQUE (Name),
- PRIMARY KEY (PoolId)
- );
-
-INSERT INTO Pool_backup SELECT
- PoolId, Name, NumVols, MaxVols,
- UseOnce, UseCatalog, AcceptAnyVolume,
- VolRetention, VolUseDuration, MaxVolJobs,
- MaxVolFiles, MaxVolBytes, AutoPrune,
- Recycle, PoolType, 0, LabelFormat,
- Enabled, ScratchPoolId, RecyclePoolId,
- 0, 0, 0, 0
- FROM Pool;
-
-DROP TABLE Pool;
-
-CREATE TABLE Pool (
- PoolId INTEGER,
- Name VARCHAR(128) NOT NULL,
- NumVols INTEGER UNSIGNED DEFAULT 0,
- MaxVols INTEGER UNSIGNED DEFAULT 0,
- UseOnce TINYINT DEFAULT 0,
- UseCatalog TINYINT DEFAULT 1,
- AcceptAnyVolume TINYINT DEFAULT 0,
- VolRetention BIGINT UNSIGNED DEFAULT 0,
- VolUseDuration BIGINT UNSIGNED DEFAULT 0,
- MaxVolJobs INTEGER UNSIGNED DEFAULT 0,
- MaxVolFiles INTEGER UNSIGNED DEFAULT 0,
- MaxVolBytes BIGINT UNSIGNED DEFAULT 0,
- AutoPrune TINYINT DEFAULT 0,
- Recycle TINYINT DEFAULT 0,
- PoolType VARCHAR(20) NOT NULL,
- LabelType TINYINT DEFAULT 0,
- LabelFormat VARCHAR(128) NOT NULL,
- Enabled TINYINT DEFAULT 1,
- ScratchPoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- RecyclePoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- NextPoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
- MigrationHighBytes BIGINT UNSIGNED DEFAULT 0,
- MigrationLowBytes BIGINT UNSIGNED DEFAULT 0,
- MigrationTime BIGINT UNSIGNED DEFAULT 0,
- UNIQUE (Name),
- PRIMARY KEY (PoolId)
+CREATE TABLE MAC (
+ JobId INTEGER,
+ OriginalJobId INTEGER,
+ JobType CHAR NOT NULL,
+ JobLevel CHAR NOT NULL,
+ SchedTime DATETIME NOT NULL,
+ StartTime DATETIME DEFAULT 0,
+ EndTime DATETIME DEFAULT 0,
+ JobTDate BIGINT UNSIGNED DEFAULT 0,
+ PRIMARY KEY(JobId)
);
-INSERT INTO Pool (
- PoolId, Name, NumVols, MaxVols,
- UseOnce, UseCatalog, AcceptAnyVolume,
- VolRetention, VolUseDuration, MaxVolJobs,
- MaxVolFiles, MaxVolBytes, AutoPrune,
- Recycle, PoolType, LabelType, LabelFormat,
- Enabled, ScratchPoolId, RecyclePoolId,
- NextPoolId, MigrationHighBytes,
- MigrationLowBytes, MigrationTime )
- SELECT * FROM Pool_backup;
-
-DROP TABLE Pool_backup;
-
-CREATE TABLE MediaType (
- MediaTypeId INTEGER,
- MediaType VARCHAR(128) NOT NULL,
- ReadOnly TINYINT DEFAULT 0,
- PRIMARY KEY(MediaTypeId)
- );
-
-CREATE TABLE Storage (
- StorageId INTEGER,
- Name VARCHAR(128) NOT NULL,
- AutoChanger TINYINT DEFAULT 0,
- PRIMARY KEY(StorageId)
- );
-
-CREATE TABLE Device (
- DeviceId INTEGER,
- Name VARCHAR(128) NOT NULL,
- MediaTypeId INTEGER UNSIGNED REFERENCES MediaType NOT NULL,
- StorageId INTEGER UNSIGNED REFERENCES Storage,
- DevMounts INTEGER UNSIGNED DEFAULT 0,
- DevReadBytes BIGINT UNSIGNED DEFAULT 0,
- DevWriteBytes BIGINT UNSIGNED DEFAULT 0,
- DevReadBytesSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- DevWriteBytesSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- DevReadTime BIGINT UNSIGNED DEFAULT 0,
- DevWriteTime BIGINT UNSIGNED DEFAULT 0,
- DevReadTimeSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- DevWriteTimeSinceCleaning BIGINT UNSIGNED DEFAULT 0,
- CleaningDate DATETIME DEFAULT 0,
- CleaningPeriod BIGINT UNSIGNED DEFAULT 0,
- PRIMARY KEY(DeviceId)
- );
-
-
-CREATE TABLE Status (
- JobStatus CHAR(1) NOT NULL,
- JobStatusLong BLOB,
- PRIMARY KEY (JobStatus)
+CREATE TABLE Location (
+ LocationId INTEGER,
+ Location VARCHAR(128) NOT NULL,
+ PRIMARY KEY(LocationId)
);
-
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('C', 'Created, not yet running');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('R', 'Running');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('B', 'Blocked');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('T', 'Completed successfully');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('E', 'Terminated with errors');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('e', 'Non-fatal error');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('f', 'Fatal error');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('D', 'Verify found differences');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('A', 'Canceled by user');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('F', 'Waiting for Client');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('S', 'Waiting for Storage daemon');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('m', 'Waiting for new media');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('M', 'Waiting for media mount');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('s', 'Waiting for storage resource');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('j', 'Waiting for job resource');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('c', 'Waiting for client resource');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('d', 'Waiting on maximum jobs');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('t', 'Waiting on start time');
-INSERT INTO Status (JobStatus,JobStatusLong) VALUES
- ('p', 'Waiting on higher priority jobs');
-
+
DELETE FROM Version;
INSERT INTO Version (VersionId) VALUES (9);
*/
/*
- Copyright (C) 2002-2005 Kern Sibbald
+ Copyright (C) 2002-2006 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
}
}
+/*
+ * Get storage device name from Storage resource
+ */
+static bool get_storage_device(char *device, char *storage)
+{
+ STORE *store;
+ if (storage[0] == 0) {
+ return false;
+ }
+ store = (STORE *)GetResWithName(R_STORAGE, storage);
+ if (!store) {
+ return false;
+ }
+ DEVICE *dev = (DEVICE *)(store->device->first());
+ if (!dev) {
+ return false;
+ }
+ bstrncpy(device, dev->hdr.name, MAX_NAME_LENGTH);
+ return true;
+}
+
/*
* Our data structures were not designed completely
* correctly, so the file indexes cover the full
bool first = true;
char *p;
JobId_t JobId;
+ char device[MAX_NAME_LENGTH];
RBSR *bsr;
if (*rx.JobIds == 0) {
for (bsr=rx.bsr; bsr; bsr=bsr->next) {
}
fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName);
fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType);
+ if (get_storage_device(device, bsr->VolParams[i].Storage)) {
+ fprintf(fd, "Device=\"%s\"\n", device);
+ }
+ if (bsr->VolParams[i].Slot > 0) {
+ fprintf(fd, "Slot=%d\n", bsr->VolParams[i].Slot);
+ }
fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) {
}
fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName);
fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType);
+ if (get_storage_device(device, bsr->VolParams[i].Storage)) {
+ fprintf(fd, "Device=\"%s\"\n", device);
+ }
+ if (bsr->VolParams[i].Slot > 0) {
+ fprintf(fd, "Slot=%d\n", bsr->VolParams[i].Slot);
+ }
fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) {
return false;
}
+ /*
+ * Target jcr is the new Job that corresponds to the original
+ * target job. It "runs" at the same time as the current
+ * migration job and becomes a new backup job that replaces
+ * the original backup job. Most operations on the current
+ * migration jcr are also done on the target jcr.
+ */
tjcr = jcr->target_jcr = new_jcr(sizeof(JCR), dird_free_jcr);
memcpy(&tjcr->target_jr, &jcr->target_jr, sizeof(tjcr->target_jr));
- set_jcr_defaults(tjcr, tjob);
+ /* Turn the tjcr into a "real" job */
+ set_jcr_defaults(tjcr, tjob);
if (!setup_job(tjcr)) {
return false;
}
return false;
}
+ /* Check Migration time and High/Low water marks */
+ /* ***FIXME*** */
+
/* If pool storage specified, use it for restore */
copy_storage(tjcr, pool->storage);
const char *upd_Purged = "UPDATE Job Set PurgedFiles=1 WHERE JobId=%s";
const char *cnt_DelCand = "SELECT count(*) FROM DelCandidates";
const char *del_Job = "DELETE FROM Job WHERE JobId=%s";
+const char *del_MAC = "DELETE FROM MAC WHERE JobId=%s";
const char *del_JobMedia = "DELETE FROM JobMedia WHERE JobId=%s";
const char *cnt_JobMedia = "SELECT count(*) FROM JobMedia WHERE MediaId=%s";
const char *sel_JobMedia = "SELECT JobId FROM JobMedia WHERE MediaId=%s";
"GROUP BY File.FileIndex ";
#endif
+/* Query to get list of files from table -- presuably built by an external program */
+const char *uar_jobid_fileindex_from_table =
+ "SELECT JobId, FileIndex from %s";
Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(JobId, ed1));
db_sql_query(ua->db, query, NULL, (void *)NULL);
- Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(JobId, ed1));
+ Mmsg(query, "DELETE FROM MAC WHERE JobId=%s", ed1);
db_sql_query(ua->db, query, NULL, (void *)NULL);
- Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(JobId, ed1));
+ Mmsg(query, "DELETE FROM File WHERE JobId=%s", ed1);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", ed1);
db_sql_query(ua->db, query, NULL, (void *)NULL);
free_pool_memory(query);
bsendmsg(ua, _("Job %s and associated records deleted from the catalog.\n"), edit_int64(JobId, ed1));
db_sql_query(ua->db, query, NULL, (void *)NULL);
Dmsg1(050, "Delete Job sql=%s\n", query);
+ Mmsg(query, "DELETE FROM MAC WHERE JobId=%s", ed1);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Dmsg1(050, "Delete MAC sql=%s\n", query);
+
Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", ed1);
db_sql_query(ua->db, query, NULL, (void *)NULL);
Dmsg1(050, "Delete JobMedia sql=%s\n", query);
db_sql_query(ua->db, query, NULL, (void *)NULL);
Mmsg(query, "DELETE FROM Job WHERE JobId=%s", ed1);
db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Mmsg(query, "DELETE FROM MAC WHERE JobId=%s", ed1);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", ed1);
db_sql_query(ua->db, query, NULL, (void *)NULL);
Dmsg1(050, "Del sql=%s\n", query);
extern char *uar_jobid_fileindex, *uar_dif, *uar_sel_all_temp;
extern char *uar_count_files, *uar_jobids_fileindex;
extern char *uar_jobid_fileindex_from_dir;
+extern char *uar_jobid_fileindex_from_table;
static int get_client_name(UAContext *ua, RESTORE_CTX *rx);
static int get_date(UAContext *ua, char *date, int date_len);
static int count_handler(void *ctx, int num_fields, char **row);
+static bool insert_table_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *table);
/*
* Restore files
free_name_list(&rx->name_list);
}
+static bool has_value(UAContext *ua, int i)
+{
+ if (!ua->argv[i]) {
+ bsendmsg(ua, _("Missing value for keyword: %s\n"), ua->argk[i]);
+ return false;
+ }
+ return true;
+}
+
static int get_client_name(UAContext *ua, RESTORE_CTX *rx)
{
/* If no client name specified yet, get it now */
/* try command line argument */
int i = find_arg_with_value(ua, N_("client"));
if (i >= 0) {
+ if (!has_value(ua, i)) {
+ return 0;
+ }
bstrncpy(rx->ClientName, ua->argv[i], sizeof(rx->ClientName));
return 1;
}
return 1;
}
-static bool has_value(UAContext *ua, int i)
-{
- if (!ua->argv[i]) {
- bsendmsg(ua, _("Missing value for keyword: %s\n"), ua->argk[i]);
- return false;
- }
- return true;
-}
/*
* The first step in the restore process is for the user to
}
fclose(ffd);
break;
+ case '?':
+ p++;
+ insert_table_into_findex_list(ua, rx, p);
+ break;
default:
if (dir) {
insert_dir_into_findex_list(ua, rx, ua->cmd, date);
return true;
}
+/*
+ * Get the JobId and FileIndexes of all files in the specified table
+ */
+static bool insert_table_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *table)
+{
+ char ed1[50];
+
+ strip_trailing_junk(table);
+ Mmsg(rx->query, uar_jobid_fileindex_from_table, table);
+
+ rx->found = false;
+ /* Find and insert jobid and File Index */
+ if (!db_sql_query(ua->db, rx->query, jobid_fileindex_handler, (void *)rx)) {
+ bsendmsg(ua, _("Query failed: %s. ERR=%s\n"),
+ rx->query, db_strerror(ua->db));
+ }
+ if (!rx->found) {
+ bsendmsg(ua, _("No table found: %s\n"), table);
+ return true;
+ }
+ /*
+ * Find the MediaTypes for this JobId and add to the name_list
+ */
+ Mmsg(rx->query, uar_mediatype, edit_int64(rx->JobId, ed1));
+ if (!db_sql_query(ua->db, rx->query, unique_name_list_handler, (void *)&rx->name_list)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ return false;
+ }
+ return true;
+}
static void split_path_and_filename(RESTORE_CTX *rx, char *name)
{
dummy:
# bacula-sd
-SVRSRCS = stored.c ansi_label.c \
- autochanger.c acquire.c append.c \
- askdir.c authenticate.c \
- block.c butil.c dev.c \
- device.c dircmd.c dvd.c ebcdic.c fd_cmds.c job.c \
- label.c mac.c match_bsr.c mount.c parse_bsr.c \
- pythonsd.c read.c read_record.c record.c \
- reserve.c scan.c \
- spool.c status.c stored_conf.c wait.c
-SVROBJS = stored.o ansi_label.o \
+SDOBJS = stored.o ansi_label.o \
autochanger.o acquire.o append.o \
askdir.o authenticate.o \
block.o butil.o dev.o \
spool.o status.o stored_conf.o wait.o
# btape
-TAPESRCS = btape.c block.c butil.c dev.c device.c label.c \
- ansi_label.c dvd.c ebcdic.c \
- acquire.c mount.c record.c read_record.c \
- stored_conf.c match_bsr.c parse_bsr.c spool.c
TAPEOBJS = btape.o block.o butil.o dev.o device.o label.o \
ansi_label.o dvd.o ebcdic.o \
autochanger.o acquire.o mount.o record.o read_record.o \
+ reserve.o \
stored_conf.o match_bsr.o parse_bsr.o scan.o spool.o wait.o
# bls
BLSOBJS = bls.o block.o butil.o device.o dev.o label.o match_bsr.o \
ansi_label.o dvd.o ebcdic.o \
autochanger.o acquire.o mount.o parse_bsr.o record.o \
- read_record.o scan.o stored_conf.o spool.o wait.o
+ read_record.o reserve.o scan.o stored_conf.o spool.o wait.o
# bextract
BEXTOBJS = bextract.o block.o device.o dev.o label.o record.o \
ansi_label.o dvd.o ebcdic.o \
autochanger.o acquire.o mount.o match_bsr.o parse_bsr.o butil.o \
- pythonsd.o \
- read_record.o scan.o stored_conf.o spool.o wait.o
+ pythonsd.o read_record.o reserve.o \
+ scan.o stored_conf.o spool.o wait.o
# bscan
SCNOBJS = bscan.o block.o device.o dev.o label.o \
ansi_label.o dvd.o ebcdic.o \
autochanger.o acquire.o mount.o record.o match_bsr.o parse_bsr.o \
- butil.o read_record.o scan.o stored_conf.o spool.o wait.o
+ butil.o read_record.o scan.o reserve.o stored_conf.o spool.o wait.o
# bcopy
COPYOBJS = bcopy.o block.o device.o dev.o label.o \
ansi_label.o dvd.o ebcdic.o \
autochanger.o acquire.o mount.o record.o match_bsr.o parse_bsr.o \
- butil.o read_record.o scan.o stored_conf.o spool.o wait.o
+ butil.o read_record.o reserve.o \
+ scan.o stored_conf.o spool.o wait.o
@echo "===== Make of stored is good ===="
@echo " "
-bacula-sd: $(SVROBJS) ../lib/libbac.a
- $(CXX) $(WLDFLAGS) $(LDFLAGS) -L../lib -o $@ $(SVROBJS) $(FDLIBS) \
+bacula-sd: $(SDOBJS) ../lib/libbac.a
+ $(CXX) $(WLDFLAGS) $(LDFLAGS) -L../lib -o $@ $(SDOBJS) $(FDLIBS) \
-lbac -lm $(PYTHON_LIBS) $(DLIB) $(LIBS) $(WRAPLIBS) \
$(GETTEXT_LIBS) $(OPENSSL_LIBS)
-static-bacula-sd: $(SVROBJS) ../lib/libbac.a
- $(CXX) $(WLDFLAGS) $(LDFLAGS) -static -L../lib -o $@ $(SVROBJS) $(FDLIBS) \
+static-bacula-sd: $(SDOBJS) ../lib/libbac.a
+ $(CXX) $(WLDFLAGS) $(LDFLAGS) -static -L../lib -o $@ $(SDOBJS) $(FDLIBS) \
-lbac -lm $(PYTHON_LIBS) $(DLIB) $(LIBS) $(WRAPLIBS) \
$(GETTEXT_LIBS) $(OPENSSL_LIBS)
strip $@
#include "bacula.h" /* pull in global headers */
#include "stored.h" /* pull in Storage Deamon headers */
+/* Forward referenced functions */
+static void detach_dcr_from_dev(DCR *dcr);
+
/*********************************************************************
* Acquire device for reading.
* Returns: NULL if failed for any reason
* dcr if successful
*/
-DCR *acquire_device_for_read(DCR *dcr)
+bool acquire_device_for_read(DCR *dcr)
{
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
- bool vol_ok = false;
+ bool ok = false;
bool tape_previously_mounted;
bool tape_initially_mounted;
VOL_LIST *vol;
bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
dcr->VolCatInfo.Slot = vol->Slot;
- Dmsg4(100, "===== Vol=%s MT=%s Slt=%d Dev-MT=%s\n", dcr->VolumeName,
- dcr->media_type, vol->Slot, dev->device->media_type);
-
- if (strcmp(dcr->media_type, dev->device->media_type) != 0) {
- Dmsg2(000, "Wrong MT have=%s want=%s\n", dev->device->media_type,
- dcr->media_type);
- Dmsg1(000, "New storage=%s\n", vol->storage);
+
+ /*
+ * If the MediaType requested for this volume is not the
+ * same as the current drive, we attempt to find the same
+ * device that was used to write the orginal volume. If
+ * found, we switch to using that device.
+ */
+ Dmsg2(100, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
+ if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
+ RCTX rctx;
+ DIRSTORE *store;
+ int stat;
+ memset(&rctx, 0, sizeof(RCTX));
+ rctx.jcr = jcr;
+ jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
+ rctx.any_drive = true;
+ rctx.device_name = vol->device;
+ store = new DIRSTORE;
+ memset(store, 0, sizeof(DIRSTORE));
+ store->name[0] = 0; /* No dir name */
+ bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
+ bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
+ bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
+ store->append = false;
+ rctx.store = store;
+
+ /*
+ * Note, if search_for_device() succeeds, we get a new_dcr,
+ * which we do not use except for the dev info.
+ */
+ stat = search_res_for_device(rctx);
+ release_msgs(jcr); /* release queued messages */
+ if (stat == 1) {
+ DCR *new_dcr = jcr->read_dcr;
+ dev->unblock();
+ detach_dcr_from_dev(dcr); /* release old device */
+ /* Copy important info from the new dcr */
+ dev = dcr->dev = new_dcr->dev;
+ jcr->read_dcr = dcr;
+ dcr->device = new_dcr->device;
+ dcr->max_job_spool_size = dcr->device->max_job_spool_size;
+ if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
+ dev->attached_dcrs->append(dcr); /* attach dcr to device */
+ }
+ new_dcr->VolumeName[0] = 0;
+ free_dcr(new_dcr);
+ dev->block(BST_DOING_ACQUIRE);
+ Jmsg(jcr, M_INFO, 0, _("Media Type change. New device %s chosen.\n"),
+ dev->print_name());
+ bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
+ bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
+ dcr->VolCatInfo.Slot = vol->Slot;
+ bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
+ bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
+ } else if (stat == 0) { /* device busy */
+ Dmsg1(000, "Device %s is busy.\n", vol->device);
+ } else {
+ /* error */
+ Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
+ vol->VolumeName);
+ goto get_out;
+ }
}
init_device_wait_timers(dcr);
if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
if (dev->dev_errno == EIO) { /* no tape loaded */
Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
- dev->print_name(), dcr->VolumeName, strerror_dev(dev));
+ dev->print_name(), dcr->VolumeName, dev->bstrerror());
goto default_path;
}
Jmsg3(jcr, M_FATAL, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
- dev->print_name(), dcr->VolumeName, strerror_dev(dev));
+ dev->print_name(), dcr->VolumeName, dev->bstrerror());
goto get_out;
}
Dmsg1(100, "opened dev %s OK\n", dev->print_name());
vol_label_status = read_dev_volume_label(dcr);
switch (vol_label_status) {
case VOL_OK:
- vol_ok = true;
+ ok = true;
memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
break; /* got it */
case VOL_IO_ERROR:
} /* end switch */
break;
} /* end for loop */
- if (!vol_ok) {
+ if (!ok) {
Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
dev->print_name());
goto get_out;
}
V(dev->mutex);
dev->unblock();
- if (!vol_ok) {
- dcr = NULL;
- }
- return dcr;
+ return ok;
}
}
#endif
-/*
- * Free up all aspects of the given dcr -- i.e. dechain it,
- * release allocated memory, zap pointers, ...
- */
-void free_dcr(DCR *dcr)
+static void detach_dcr_from_dev(DCR *dcr)
{
- JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
if (dcr->reserved_device) {
+ dcr->reserved_device = false;
lock_device(dev);
dev->reserved_device--;
Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
}
/* Detach this dcr only if the dev is initialized */
- if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
- dev->attached_dcrs->remove(dcr); /* detach dcr from device */
+ if (dcr->dev->fd != 0 && dcr->jcr && dcr->jcr->JobType != JT_SYSTEM) {
+ dcr->dev->attached_dcrs->remove(dcr); /* detach dcr from device */
// remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
}
+ free_unused_volume(dcr); /* free unused vols attached to this dcr */
+ pthread_cond_broadcast(&dcr->dev->wait_next_vol);
+ pthread_cond_broadcast(&wait_device_release);
+}
+
+/*
+ * Free up all aspects of the given dcr -- i.e. dechain it,
+ * release allocated memory, zap pointers, ...
+ */
+void free_dcr(DCR *dcr)
+{
+
+ detach_dcr_from_dev(dcr);
+
if (dcr->block) {
free_block(dcr->block);
}
if (dcr->jcr) {
dcr->jcr->dcr = NULL;
}
- free_unused_volume(dcr); /* free unused vols attached to this dcr */
free(dcr);
- pthread_cond_broadcast(&dev->wait_next_vol);
- pthread_cond_broadcast(&wait_device_release);
}
*/
if (!write_session_label(dcr, SOS_LABEL)) {
Jmsg1(jcr, M_FATAL, 0, _("Write session label failed. ERR=%s\n"),
- strerror_dev(dev));
+ dev->bstrerror());
set_jcr_job_status(jcr, JS_ErrorTerminated);
ok = false;
}
rec.remainder);
if (!write_block_to_device(dcr)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
ok = false;
break;
}
if (ok || dev->can_write()) {
if (!write_session_label(dcr, EOS_LABEL)) {
Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
- strerror_dev(dev));
+ dev->bstrerror());
set_jcr_job_status(jcr, JS_ErrorTerminated);
ok = false;
}
/* Flush out final partial block of this session */
if (!write_block_to_device(dcr)) {
Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
ok = false;
}
free_jcr(in_jcr);
free_jcr(out_jcr);
- term_dev(in_dev);
- term_dev(out_dev);
+ in_dev->term();
+ out_dev->term();
return 0;
}
rec->remainder);
if (!write_block_to_device(out_jcr->dcr)) {
Dmsg2(90, "Got write_block_to_dev error on device %s: ERR=%s\n",
- out_dev->print_name(), strerror_dev(out_dev));
+ out_dev->print_name(), out_dev->bstrerror());
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
- strerror_dev(out_dev));
+ out_dev->bstrerror());
}
}
if (!write_block_to_device(out_jcr->dcr)) {
Dmsg2(90, "Got write_block_to_dev error on device %s: ERR=%s\n",
- out_dev->print_name(), strerror_dev(out_dev));
+ out_dev->print_name(), out_dev->bstrerror());
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
- strerror_dev(out_dev));
+ out_dev->bstrerror());
}
break;
case EOM_LABEL:
rec->remainder);
if (!write_block_to_device(out_jcr->dcr)) {
Dmsg2(90, "Got write_block_to_dev error on device %s: ERR=%s\n",
- out_dev->print_name(), strerror_dev(out_dev));
+ out_dev->print_name(), out_dev->bstrerror());
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
- strerror_dev(out_dev));
+ out_dev->bstrerror());
break;
}
}
bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; }
bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
bool dir_send_job_status(JCR *jcr) {return 1;}
-VOLRES *new_volume(DCR *dcr, const char *VolumeName) { return NULL; }
-bool free_volume(DEVICE *dev) { return true; }
-void free_unused_volume(DCR *dcr) { }
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
release_device(dcr);
free_attr(attr);
free_jcr(jcr);
- term_dev(dev);
+ dev->term();
printf(_("%u files restored.\n"), num_files);
return;
bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; }
bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
bool dir_send_job_status(JCR *jcr) {return 1;}
-VOLRES *new_volume(DCR *dcr, const char *VolumeName) { return NULL; }
-bool free_volume(DEVICE *dev) { return true; }
-void free_unused_volume(DCR *dcr) { }
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
if (weof_dev(dev, 1) != 0) { /* write eof */
Dmsg0(190, "WEOF error in max file size.\n");
Jmsg(jcr, M_FATAL, 0, _("Unable to write EOF. ERR=%s\n"),
- strerror_dev(dev));
+ dev->bstrerror());
terminate_writing_volume(dcr);
dev->dev_errno = ENOSPC;
return false;
be.strerror(dev->dev_errno));
}
/* Backspace over record */
- if (ok && !bsr_dev(dev, 1)) {
+ if (ok && !dev->bsr(1)) {
berrno be;
ok = false;
Jmsg(jcr, M_ERROR, 0, _("Backspace record at EOT failed. ERR=%s\n"),
* rewind(), but if we do that, higher levels in cleaning up, will
* most likely write the EOS record over the beginning of the
* tape. The rewind *is* done later in mount.c when another
- * tape is requested. Note, the clrerror_dev() call in bsr_dev()
+ * tape is requested. Note, the clrerror_dev() call in bsr()
* calls ioctl(MTCERRSTAT), which *should* fix the problem.
*/
}
if (dvd_open_next_part(dcr) < 0) {
Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
dev->dev_errno = EIO;
return false;
}
(dev->part < dev->num_parts)) {
if (dvd_open_next_part(dcr) < 0) {
Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
dev->dev_errno = EIO;
return false;
}
/* Attempt to reposition to re-read the block */
if (dev->is_tape()) {
Dmsg0(200, "BSR for reread; block too big for buffer.\n");
- if (!bsr_dev(dev, 1)) {
- Jmsg(jcr, M_ERROR, 0, "%s", strerror_dev(dev));
+ if (!dev->bsr(1)) {
+ Jmsg(jcr, M_ERROR, 0, "%s", dev->bstrerror());
block->read_len = 0;
return false;
}
free_record(rec);
free_block(block);
free_jcr(jcr);
- term_dev(dev);
+ dev->term();
}
bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
bool dir_send_job_status(JCR *jcr) {return 1;}
int generate_job_event(JCR *jcr, const char *event) { return 1; }
-VOLRES *new_volume(DCR *dcr, const char *VolumeName) { return NULL; }
-bool free_volume(DEVICE *dev) { return true; }
-void free_unused_volume(DCR *dcr) { }
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
}
free_jcr(bjcr);
- term_dev(dev);
+ dev->term();
return 0;
}
bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
bool dir_send_job_status(JCR *jcr) {return 1;}
int generate_job_event(JCR *jcr, const char *event) { return 1; }
-VOLRES *new_volume(DCR *dcr, const char *VolumeName) { return NULL; }
-bool free_volume(DEVICE *dev) { return true; }
-void free_unused_volume(DCR *dcr) { }
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
{
VOL_LIST *next;
char VolumeName[MAX_NAME_LENGTH];
char MediaType[MAX_NAME_LENGTH];
- char storage[MAX_NAME_LENGTH]; /* ***FIXME*** use alist here */
+ char device[MAX_NAME_LENGTH]; /* ***FIXME*** use alist here */
int Slot;
uint32_t start_file;
};
BSR_VOLUME *next;
char VolumeName[MAX_NAME_LENGTH];
char MediaType[MAX_NAME_LENGTH];
- char storage[MAX_NAME_LENGTH]; /* ***FIXME*** use alist here */
+ char device[MAX_NAME_LENGTH]; /* ***FIXME*** use alist here */
int32_t Slot; /* Slot */
};
jcr = NULL;
if (dev) {
- term_dev(dev);
+ dev->term();
}
if (debug_level > 10)
if (!dev->is_open()) {
if (!first_open_device(dcr)) {
- Pmsg1(0, _("Device open failed. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Device open failed. ERR=%s\n"), dev->bstrerror());
}
}
dev->rewind(dcr);
Pmsg0(0, _("Volume label read correctly.\n"));
break;
case VOL_IO_ERROR:
- Pmsg1(0, _("I/O error on device: ERR=%s"), strerror_dev(dev));
+ Pmsg1(0, _("I/O error on device: ERR=%s"), dev->bstrerror());
break;
case VOL_NAME_ERROR:
Pmsg0(0, _("Volume name error\n"));
break;
case VOL_CREATE_ERROR:
- Pmsg1(0, _("Error creating label. ERR=%s"), strerror_dev(dev));
+ Pmsg1(0, _("Error creating label. ERR=%s"), dev->bstrerror());
break;
case VOL_VERSION_ERROR:
Pmsg0(0, _("Volume version error.\n"));
{
if (!load_dev(dev)) {
- Pmsg1(0, _("Bad status from load. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from load. ERR=%s\n"), dev->bstrerror());
} else
Pmsg1(0, _("Loaded %s\n"), dev->print_name());
}
static void rewindcmd()
{
if (!dev->rewind(dcr)) {
- Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror());
clrerror_dev(dev, -1);
} else {
Pmsg1(0, _("Rewound %s\n"), dev->print_name());
}
if ((stat = weof_dev(dev, num)) < 0) {
- Pmsg2(0, _("Bad status from weof %d. ERR=%s\n"), stat, strerror_dev(dev));
+ Pmsg2(0, _("Bad status from weof %d. ERR=%s\n"), stat, dev->bstrerror());
return;
} else {
if (num==1) {
static void eomcmd()
{
if (!dev->eod()) {
- Pmsg1(0, "%s", strerror_dev(dev));
+ Pmsg1(0, "%s", dev->bstrerror());
return;
} else {
Pmsg0(0, _("Moved to end of medium.\n"));
}
if (!dev->bsf(num)) {
- Pmsg1(0, _("Bad status from bsf. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from bsf. ERR=%s\n"), dev->bstrerror());
} else {
Pmsg2(0, _("Backspaced %d file%s.\n"), num, num==1?"":"s");
}
if (num <= 0) {
num = 1;
}
- if (!bsr_dev(dev, num)) {
- Pmsg1(0, _("Bad status from bsr. ERR=%s\n"), strerror_dev(dev));
+ if (!dev->bsr(num)) {
+ Pmsg1(0, _("Bad status from bsr. ERR=%s\n"), dev->bstrerror());
} else {
Pmsg2(0, _("Backspaced %d record%s.\n"), num, num==1?"":"s");
}
weofcmd();
}
if (!dev->bsf(1)) {
- Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Backspace file failed! ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
if (dev_cap(dev, CAP_TWOEOF)) {
if (!dev->bsf(1)) {
- Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Backspace file failed! ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
}
Pmsg0(0, _("Backspaced over EOF OK.\n"));
- if (!bsr_dev(dev, 1)) {
- Pmsg1(0, _("Backspace record failed! ERR=%s\n"), strerror_dev(dev));
+ if (!dev->bsr(1)) {
+ Pmsg1(0, _("Backspace record failed! ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
Pmsg0(0, _("Backspace record OK.\n"));
block = dcr->block;
rec = new_record();
if (!dev->rewind(dcr)) {
- Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
rec->data = check_pool_memory_size(rec->data, block->buf_len);
weofcmd();
}
if (!dev->rewind(dcr)) {
- Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror());
goto bail_out;
} else {
Pmsg0(0, _("Rewind OK.\n"));
empty_block(block);
rec = new_record();
if (!dev->rewind(dcr)) {
- Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
rec->data = check_pool_memory_size(rec->data, block->buf_len);
weofcmd();
}
if (!dev->rewind(dcr)) {
- Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror());
goto bail_out;
} else {
Pmsg0(0, _("Rewind OK.\n"));
continue;
}
Pmsg2(-1, _("Reposition to file:block %d:%d\n"), file, blk);
- if (!reposition_dev(dev, file, blk)) {
+ if (!dev->reposition(file, blk)) {
Pmsg0(0, _("Reposition error.\n"));
goto bail_out;
}
*/
bmicrosleep(sleep_time, 0);
if (!dev->rewind(dcr) || weof_dev(dev,1) < 0) {
- Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror());
clrerror_dev(dev, -1);
Pmsg0(-1, _("\nThe test failed, probably because you need to put\n"
"a longer sleep time in the mtx-script in the load) case.\n"
}
if ((status = weof_dev(dev, 1)) < 0) {
- Pmsg2(0, _("Bad status from weof %d. ERR=%s\n"), status, strerror_dev(dev));
+ Pmsg2(0, _("Bad status from weof %d. ERR=%s\n"), status, dev->bstrerror());
goto bail_out;
} else {
Pmsg1(0, _("Wrote EOF to %s\n"), dev->print_name());
rewindcmd();
Pmsg0(0, _("Now forward spacing 1 file.\n"));
if (!dev->fsf(1)) {
- Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
Pmsg2(-1, _("We should be in file 1. I am at file %d. %s\n"),
Pmsg0(0, _("Now forward spacing 2 files.\n"));
if (!dev->fsf(2)) {
- Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
Pmsg2(-1, _("We should be in file 3. I am at file %d. %s\n"),
rewindcmd();
Pmsg0(0, _("Now forward spacing 4 files.\n"));
if (!dev->fsf(4)) {
- Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
Pmsg2(-1, _("We should be in file 4. I am at file %d. %s\n"),
Pmsg0(-1, "\n");
Pmsg0(0, _("Now forward spacing 1 more file.\n"));
if (!dev->fsf(1)) {
- Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), dev->bstrerror());
}
Pmsg2(-1, _("We should be in file 5. I am at file %d. %s\n"),
dev->file, dev->file == 5 ? _("This is correct!") : _("This is NOT correct!!!!"));
num = 1;
}
if (!dev->fsf(num)) {
- Pmsg1(0, _("Bad status from fsf. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from fsf. ERR=%s\n"), dev->bstrerror());
return;
}
if (num == 1) {
num = 1;
}
if (!dev->fsr(num)) {
- Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), dev->bstrerror());
return;
}
if (num == 1) {
clrerror_dev(dev, -1);
Mmsg2(dev->errmsg, _("read error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
- Pmsg2(0, _("Bad status from read %d. ERR=%s\n"), stat, strerror_dev(dev));
+ Pmsg2(0, _("Bad status from read %d. ERR=%s\n"), stat, dev->bstrerror());
if (blocks > 0) {
if (blocks==1) {
printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file);
tot_files = dev->file;
for (;;) {
if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
- Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev));
+ Dmsg1(100, "!read_block(): ERR=%s\n", dev->bstrerror());
if (dev->state & ST_EOT) {
if (blocks > 0) {
if (blocks==1) {
printf(_("Short block read.\n"));
continue;
}
- printf(_("Error reading block. ERR=%s\n"), strerror_dev(dev));
+ printf(_("Error reading block. ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
if (block->block_len != block_size) {
{
int debug = debug_level;
debug_level = 30;
- Pmsg2(0, _("Device status: %u. ERR=%s\n"), status_dev(dev), strerror_dev(dev));
+ Pmsg2(0, _("Device status: %u. ERR=%s\n"), status_dev(dev), dev->bstrerror());
#ifdef xxxx
dump_volume_label(dev);
#endif
if (!write_session_label(dcr, SOS_LABEL)) {
set_jcr_job_status(jcr, JS_ErrorTerminated);
Jmsg1(jcr, M_FATAL, 0, _("Write session label failed. ERR=%s\n"),
- strerror_dev(dev));
+ dev->bstrerror());
ok = false;
}
Pmsg0(-1, _("Wrote Start of Session label.\n"));
set_jcr_job_status(jcr, JS_ErrorTerminated);
}
if (!write_session_label(dcr, EOS_LABEL)) {
- Pmsg1(000, _("Error writting end session label. ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(000, _("Error writting end session label. ERR=%s\n"), dev->bstrerror());
ok = false;
}
/* Write out final block of this session */
read_records(dcr, quickie_cb, my_mount_next_read_volume);
Pmsg4(-1, _("Reposition from %u:%u to %u:%u\n"), dev->file, dev->block_num,
last_file, last_block_num);
- if (!reposition_dev(dev, last_file, last_block_num)) {
- Pmsg1(-1, _("Reposition error. ERR=%s\n"), strerror_dev(dev));
+ if (!dev->reposition(last_file, last_block_num)) {
+ Pmsg1(-1, _("Reposition error. ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
Pmsg1(-1, _("Reading block %u.\n"), last_block_num);
if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
- Pmsg1(-1, _("Error reading block: ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
if (compare_blocks(last_block, block)) {
* on the previous tape.
*/
Pmsg2(-1, _("Reposition from %u:%u to 0:1\n"), dev->file, dev->block_num);
- if (!reposition_dev(dev, 0, 1)) {
- Pmsg1(-1, _("Reposition error. ERR=%s\n"), strerror_dev(dev));
+ if (!dev->reposition(0, 1)) {
+ Pmsg1(-1, _("Reposition error. ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
Pmsg1(-1, _("Reading block %d.\n"), dev->block_num);
if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
- Pmsg1(-1, _("Error reading block: ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
if (compare_blocks(first_block, block)) {
/* Now find and compare the last block */
Pmsg4(-1, _("Reposition from %u:%u to %u:%u\n"), dev->file, dev->block_num,
last_file, last_block_num);
- if (!reposition_dev(dev, last_file, last_block_num)) {
- Pmsg1(-1, _("Reposition error. ERR=%s\n"), strerror_dev(dev));
+ if (!dev->reposition(last_file, last_block_num)) {
+ Pmsg1(-1, _("Reposition error. ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
Pmsg1(-1, _("Reading block %d.\n"), dev->block_num);
if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
- Pmsg1(-1, _("Error reading block: ERR=%s\n"), strerror_dev(dev));
+ Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
if (compare_blocks(last_block, block)) {
} else {
/* Full test in progress */
if (!fixup_device_block_write_error(jcr->dcr)) {
- Pmsg1(000, _("Cannot fixup device error. %s\n"), strerror_dev(dev));
+ Pmsg1(000, _("Cannot fixup device error. %s\n"), dev->bstrerror());
ok = false;
unlock_device(dev);
return 0;
bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
dcr->VolCatInfo.Slot = volnum;
}
-
-VOLRES *new_volume(DCR *dcr, const char *VolumeName) { return NULL; }
-bool free_volume(DEVICE *dev) { return true; }
-void free_unused_volume(DCR *dcr) { }
pm_strcpy(jcr->fileset_md5, "Dummy.fileset.md5");
init_autochangers();
+ init_volume_list();
dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
if (!dcr) {
dev = (DEVICE *)malloc(sizeof(DEVICE));
memset(dev, 0, sizeof(DEVICE));
- dev->state = ST_MALLOC;
/* Copy user supplied device parameters from Resource */
dev->dev_name = get_memory(strlen(device->device_name)+1);
dev->prt_name = get_memory(strlen(device->device_name) + strlen(device->hdr.name) + 20);
/* We edit "Resource-name" (physical-name) */
Mmsg(dev->prt_name, "\"%s\" (%s)", device->hdr.name, device->device_name);
+ Dmsg1(400, "Allocate dev=%s\n", dev->print_name());
dev->capabilities = device->cap_bits;
dev->min_block_size = device->min_block_size;
dev->max_block_size = device->max_block_size;
if (dev->vol_poll_interval && dev->vol_poll_interval < 60) {
dev->vol_poll_interval = 60;
}
+ /* Link the dev and device structures together */
dev->device = device;
+ device->dev = dev;
if (dev->is_fifo()) {
dev->capabilities |= CAP_STREAM; /* set stream device */
* Returns: false on failure
* true on success
*/
-bool
-bsr_dev(DEVICE *dev, int num)
+bool DEVICE::bsr(int num)
{
struct mtop mt_com;
int stat;
- if (dev->fd < 0) {
- dev->dev_errno = EBADF;
- Mmsg0(dev->errmsg, _("Bad call to bsr_dev. Device not open\n"));
- Emsg0(M_FATAL, 0, dev->errmsg);
+ if (fd < 0) {
+ dev_errno = EBADF;
+ Mmsg0(errmsg, _("Bad call to bsr_dev. Device not open\n"));
+ Emsg0(M_FATAL, 0, errmsg);
return false;
}
- if (!dev->is_tape()) {
+ if (!is_tape()) {
return false;
}
- if (!dev->has_cap(CAP_BSR)) {
- Mmsg1(dev->errmsg, _("ioctl MTBSR not permitted on %s.\n"), dev->print_name());
+ if (!has_cap(CAP_BSR)) {
+ Mmsg1(errmsg, _("ioctl MTBSR not permitted on %s.\n"), print_name());
return false;
}
Dmsg0(29, "bsr_dev\n");
- dev->block_num -= num;
- dev->state &= ~(ST_EOF|ST_EOT|ST_EOF);
+ block_num -= num;
+ state &= ~(ST_EOF|ST_EOT|ST_EOF);
mt_com.mt_op = MTBSR;
mt_com.mt_count = num;
- stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
+ stat = ioctl(fd, MTIOCTOP, (char *)&mt_com);
if (stat < 0) {
berrno be;
- clrerror_dev(dev, MTBSR);
- Mmsg2(dev->errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"),
- dev->print_name(), be.strerror());
+ clrerror_dev(this, MTBSR);
+ Mmsg2(errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"),
+ print_name(), be.strerror());
}
- update_pos_dev(dev);
+ update_pos_dev(this);
return stat == 0;
}
* Returns: false on failure
* true on success
*/
-bool
-reposition_dev(DEVICE *dev, uint32_t file, uint32_t block)
+bool DEVICE::reposition(uint32_t rfile, uint32_t rblock)
{
- if (dev->fd < 0) {
- dev->dev_errno = EBADF;
- Mmsg0(dev->errmsg, _("Bad call to reposition_dev. Device not open\n"));
- Emsg0(M_FATAL, 0, dev->errmsg);
+ if (fd < 0) {
+ dev_errno = EBADF;
+ Mmsg0(errmsg, _("Bad call to reposition. Device not open\n"));
+ Emsg0(M_FATAL, 0, errmsg);
return false;
}
- if (!dev->is_tape()) {
- off_t pos = (((off_t)file)<<32) + (off_t)block;
+ if (!is_tape()) {
+ off_t pos = (((off_t)rfile)<<32) + (off_t)rblock;
Dmsg1(100, "===== lseek_dev to %d\n", (int)pos);
- if (lseek_dev(dev, pos, SEEK_SET) == (off_t)-1) {
+ if (lseek_dev(this, pos, SEEK_SET) == (off_t)-1) {
berrno be;
- dev->dev_errno = errno;
- Mmsg2(dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
- dev->print_name(), be.strerror());
+ dev_errno = errno;
+ Mmsg2(errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
+ print_name(), be.strerror());
return false;
}
- dev->file = file;
- dev->block_num = block;
- dev->file_addr = pos;
+ file = rfile;
+ block_num = rblock;
+ file_addr = pos;
return true;
}
- Dmsg4(100, "reposition_dev from %u:%u to %u:%u\n",
- dev->file, dev->block_num, file, block);
- if (file < dev->file) {
+ Dmsg4(100, "reposition from %u:%u to %u:%u\n",
+ file, block_num, rfile, rblock);
+ if (rfile < file) {
Dmsg0(100, "Rewind\n");
- if (!dev->rewind(NULL)) {
+ if (!rewind(NULL)) {
return false;
}
}
- if (file > dev->file) {
- Dmsg1(100, "fsf %d\n", file-dev->file);
- if (!dev->fsf(file-dev->file)) {
- Dmsg1(100, "fsf failed! ERR=%s\n", strerror_dev(dev));
+ if (rfile > file) {
+ Dmsg1(100, "fsf %d\n", rfile-file);
+ if (!fsf(rfile-file)) {
+ Dmsg1(100, "fsf failed! ERR=%s\n", bstrerror());
return false;
}
- Dmsg2(100, "wanted_file=%d at_file=%d\n", file, dev->file);
+ Dmsg2(100, "wanted_file=%d at_file=%d\n", rfile, file);
}
- if (block < dev->block_num) {
- Dmsg2(100, "wanted_blk=%d at_blk=%d\n", block, dev->block_num);
+ if (rblock < block_num) {
+ Dmsg2(100, "wanted_blk=%d at_blk=%d\n", rblock, block_num);
Dmsg0(100, "bsf 1\n");
- dev->bsf(1);
+ bsf(1);
Dmsg0(100, "fsf_dev 1\n");
- dev->fsf(1);
- Dmsg2(100, "wanted_blk=%d at_blk=%d\n", block, dev->block_num);
+ fsf(1);
+ Dmsg2(100, "wanted_blk=%d at_blk=%d\n", rblock, block_num);
}
- if (dev->has_cap(CAP_POSITIONBLOCKS) && block > dev->block_num) {
+ if (has_cap(CAP_POSITIONBLOCKS) && rblock > block_num) {
/* Ignore errors as Bacula can read to the correct block */
- Dmsg1(100, "fsr %d\n", block-dev->block_num);
- return dev->fsr(block-dev->block_num);
+ Dmsg1(100, "fsr %d\n", rblock-block_num);
+ return fsr(rblock-block_num);
}
return true;
}
return stat;
}
-/*
- * Return string message with last error in English
- * Be careful not to call this routine from within dev.c
- * while editing an Mmsg() or you will end up in a recursive
- * loop creating a Segmentation Violation.
- */
-char *
-strerror_dev(DEVICE *dev)
-{
- return dev->errmsg;
-}
-
/*
* If implemented in system, clear the tape
#endif
}
-/*
- * Flush buffer contents
- * No longer used.
- */
-int flush_dev(DEVICE *dev)
-{
- return 1;
-}
-
/*
* Close the device
*/
/*
* Free memory allocated for the device
*/
-void
-term_dev(DEVICE *dev)
+void DEVICE::term(void)
{
- if (!dev) {
- dev->dev_errno = EBADF;
- Mmsg0(dev->errmsg, _("Bad call to term_dev. Device not open\n"));
- Emsg0(M_FATAL, 0, dev->errmsg);
- return;
- }
- Dmsg1(29, "term_dev: %s\n", dev->print_name());
- dev->close();
- if (dev->dev_name) {
- free_memory(dev->dev_name);
- dev->dev_name = NULL;
- }
- if (dev->prt_name) {
- free_memory(dev->prt_name);
- dev->prt_name = NULL;
- }
- if (dev->errmsg) {
- free_pool_memory(dev->errmsg);
- dev->errmsg = NULL;
- }
- pthread_mutex_destroy(&dev->mutex);
- pthread_cond_destroy(&dev->wait);
- pthread_cond_destroy(&dev->wait_next_vol);
- pthread_mutex_destroy(&dev->spool_mutex);
- rwl_destroy(&dev->lock);
- if (dev->attached_dcrs) {
- delete dev->attached_dcrs;
- dev->attached_dcrs = NULL;
- }
- if (dev->state & ST_MALLOC) {
- free((char *)dev);
- }
+ Dmsg1(900, "term dev: %s\n", print_name());
+ close();
+ if (dev_name) {
+ free_memory(dev_name);
+ dev_name = NULL;
+ }
+ if (prt_name) {
+ free_memory(prt_name);
+ prt_name = NULL;
+ }
+ if (errmsg) {
+ free_pool_memory(errmsg);
+ errmsg = NULL;
+ }
+ pthread_mutex_destroy(&mutex);
+ pthread_cond_destroy(&wait);
+ pthread_cond_destroy(&wait_next_vol);
+ pthread_mutex_destroy(&spool_mutex);
+ rwl_destroy(&lock);
+ if (attached_dcrs) {
+ delete attached_dcrs;
+ attached_dcrs = NULL;
+ }
+ if (device) {
+ device->dev = NULL;
+ }
+ free((char *)this);
}
/*
void clear_mounted() { state &= ~ST_MOUNTED; };
void clear_media() { state &= ~ST_MEDIA; };
void clear_short_block() { state &= ~ST_SHORT; };
- void clear_freespace_ok() { state &= ~ST_FREESPACE_OK; }
+ void clear_freespace_ok() { state &= ~ST_FREESPACE_OK; };
+ char *bstrerror(void) { return errmsg; };
void block(int why); /* in dev.c */
void unblock(); /* in dev.c */
void close(); /* in dev.c */
bool truncate(DCR *dcr); /* in dev.c */
int open(DCR *dcr, int mode); /* in dev.c */
+ void term(void); /* in dev.c */
bool rewind(DCR *dcr); /* in dev.c */
bool mount(int timeout); /* in dev.c */
bool unmount(int timeout); /* in dev.c */
bool eod(); /* in dev.c */
bool fsr(int num); /* in dev.c */
bool fsf(int num); /* in dev.c */
+ bool bsr(int num); /* in dev.c */
bool scan_dir_for_volume(DCR *dcr); /* in scan.c */
+ bool reposition(uint32_t rfile, uint32_t rblock); /* in dev.c */
void set_blocked(int block) { dev_blocked = block; };
int get_blocked() const { return dev_blocked; };
* (when there is no DVD, or when the one inserted is a wrong one) */
if (!dev->poll && !dev->is_dvd() && !dev->is_removable()) {
Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
Pmsg2(000, _("Unable to open archive %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
}
return false;
}
case VOL_IO_ERROR:
case VOL_NO_LABEL:
if (!write_new_volume_label_to_dev(dcr, newname, poolname)) {
- bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), strerror_dev(dev));
+ bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), dev->bstrerror());
break;
}
bstrncpy(dcr->VolumeName, newname, sizeof(dcr->VolumeName));
newname, dev->print_name());
break;
case VOL_NO_MEDIA:
- bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), strerror_dev(dev));
+ bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), dev->bstrerror());
break;
default:
bnet_fsend(dir, _("3913 Cannot label Volume. "
/* We freed the device, so reopen it and wake any waiting threads */
if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
- strerror_dev(dev));
+ dev->bstrerror());
if (dev->dev_blocked == BST_UNMOUNTED) {
/* We blocked the device, so unblock it */
Dmsg0(100, "Unmounted. Unblocking device\n");
} else if (dev->is_tape()) {
if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
- strerror_dev(dev));
+ dev->bstrerror());
break;
}
read_label(dcr);
bnet_fsend(dir, _("3002 Device %s is mounted.\n"),
dev->print_name());
} else {
- bnet_fsend(dir, _("3907 %s"), strerror_dev(dev));
+ bnet_fsend(dir, _("3907 %s"), dev->bstrerror());
}
} else { /* must be file */
bnet_fsend(dir, _("3906 File device %s is always mounted.\n"),
update the part number. */
if (ok && (dvd_open_next_part(dcr) < 0)) {
Jmsg2(jcr, M_FATAL, 0, _("Unable to write part %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
dev->dev_errno = EIO;
ok = false;
}
if (!dev->rewind(dcr)) {
Mmsg(jcr->errmsg, _("Couldn't rewind device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
Dmsg1(30, "return VOL_NO_MEDIA: %s", jcr->errmsg);
return VOL_NO_MEDIA;
}
if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula "
"labeled Volume, because: ERR=%s"), NPRT(VolName),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
Dmsg1(30, "%s", jcr->errmsg);
} else if (!read_record_from_block(block, record)) {
Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n"));
Dmsg1(30, "%s", jcr->errmsg);
} else if (!unser_volume_label(dev, record)) {
Mmsg(jcr->errmsg, _("Could not unserialize Volume label: ERR=%s\n"),
- strerror_dev(dev));
+ dev->bstrerror());
Dmsg1(30, "%s", jcr->errmsg);
} else if (strcmp(dev->VolHdr.Id, BaculaId) != 0 &&
strcmp(dev->VolHdr.Id, OldBaculaId) != 0) {
if (!dev->rewind(dcr)) {
free_volume(dev);
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
- Dmsg2(30, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), strerror_dev(dev));
+ Dmsg2(30, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), dev->bstrerror());
if (!forge_on) {
goto bail_out;
}
/* Temporarily mark in append state to enable writing */
dev->set_append();
if (!write_record_to_block(dcr->block, dcr->rec)) {
- Dmsg2(30, "Bad Label write on %s: ERR=%s\n", dev->print_name(), strerror_dev(dev));
+ Dmsg2(30, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->bstrerror());
goto bail_out;
} else {
Dmsg2(30, "Wrote label of %d bytes to %s\n", dcr->rec->data_len, dev->print_name());
Dmsg0(99, "Call write_block_to_dev()\n");
if (!write_block_to_dev(dcr)) {
- Dmsg2(30, "Bad Label write on %s: ERR=%s\n", dev->print_name(), strerror_dev(dev));
+ Dmsg2(30, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->bstrerror());
goto bail_out;
}
Dmsg0(99, " Wrote block to device\n");
if (!dev_cap(dev, CAP_STREAM)) {
if (!dev->rewind(dcr)) {
Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
}
if (recycle) {
if (!dev->truncate(dcr)) {
Jmsg2(jcr, M_WARNING, 0, _("Truncate error on device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
}
}
Dmsg1(200, "Attempt to write to device fd=%d.\n", dev->fd);
if (!write_block_to_dev(dcr)) {
Jmsg2(jcr, M_ERROR, 0, _("Unable to write device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
Dmsg0(200, "===ERROR write block to dev\n");
return false;
}
/* Flush out final partial block of this session */
if (!write_block_to_device(jcr->dcr)) {
Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
ok = false;
}
if (!write_block_to_device(jcr->dcr)) {
DEVICE *dev = jcr->dcr->dev;
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
return false;
}
}
dcr->VolumeName);
if (!dev->eod()) {
Jmsg(jcr, M_ERROR, 0, _("Unable to position to end of data on device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
+ dev->print_name(), dev->bstrerror());
mark_volume_in_error(dcr);
goto mount_next_vol;
}
static BSR *store_vol(LEX *lc, BSR *bsr);
static BSR *store_mediatype(LEX *lc, BSR *bsr);
-static BSR *store_storage(LEX *lc, BSR *bsr);
+static BSR *store_device(LEX *lc, BSR *bsr);
static BSR *store_client(LEX *lc, BSR *bsr);
static BSR *store_job(LEX *lc, BSR *bsr);
static BSR *store_jobid(LEX *lc, BSR *bsr);
{"exclude", store_exclude},
{"volfile", store_volfile},
{"volblock", store_volblock},
- {"stream", store_stream},
- {"slot", store_slot},
- {"storage", store_storage},
+ {"stream", store_stream},
+ {"slot", store_slot},
+ {"device", store_device},
{NULL, NULL}
};
return bsr;
}
-/* Shove the Storage name in each Volume in the current bsr */
-static BSR *store_storage(LEX *lc, BSR *bsr)
+/* Shove the Device name in each Volume in the current bsr */
+static BSR *store_device(LEX *lc, BSR *bsr)
{
int token;
return NULL;
}
if (!bsr->volume) {
- Emsg1(M_ERROR,0, _("Storage %s in bsr at inappropriate place.\n"),
+ Emsg1(M_ERROR,0, _("Device \"%s\" in bsr at inappropriate place.\n"),
lc->str);
return bsr;
}
BSR_VOLUME *bv;
for (bv=bsr->volume; bv; bv=bv->next) {
- bstrncpy(bv->storage, lc->str, sizeof(bv->storage));
+ bstrncpy(bv->device, lc->str, sizeof(bv->device));
}
return bsr;
}
if (volume) {
Pmsg1(-1, _("VolumeName : %s\n"), volume->VolumeName);
Pmsg1(-1, _(" MediaType : %s\n"), volume->MediaType);
- Pmsg1(-1, _(" Storage : %s\n"), volume->storage);
+ Pmsg1(-1, _(" Device : %s\n"), volume->device);
Pmsg1(-1, _(" Slot : %d\n"), volume->Slot);
dump_volume(volume->next);
}
vol = new_restore_volume();
bstrncpy(vol->VolumeName, bsrvol->VolumeName, sizeof(vol->VolumeName));
bstrncpy(vol->MediaType, bsrvol->MediaType, sizeof(vol->MediaType));
- bstrncpy(vol->storage, bsrvol->storage, sizeof(vol->storage));
+ bstrncpy(vol->device, bsrvol->device, sizeof(vol->device));
vol->Slot = bsrvol->Slot;
vol->start_file = sfile;
if (add_restore_volume(jcr, vol)) {
/* From acquire.c */
DCR *acquire_device_for_append(DCR *dcr);
-DCR *acquire_device_for_read(DCR *dcr);
+bool acquire_device_for_read(DCR *dcr);
bool release_device(DCR *dcr);
DCR *new_dcr(JCR *jcr, DEVICE *dev);
void free_dcr(DCR *dcr);
bool eod_dev(DEVICE *dev);
bool fsf_dev(DEVICE *dev, int num);
bool bsf_dev(DEVICE *dev, int num);
-bool 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);
-bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
void init_device_wait_timers(DCR *dcr);
void init_jcr_device_wait_timers(JCR *jcr);
bool double_dev_wait_time(DEVICE *dev);
bool is_volume_in_use(DCR *dcr);
void send_drive_reserve_messages(JCR *jcr, BSOCK *user);
bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx);
+int search_res_for_device(RCTX &rctx);
+void release_msgs(JCR *jcr);
/* From spool.c */
/* Send end of data to FD */
bnet_sig(fd, BNET_EOD);
- if (!release_device(dcr)) {
+ if (!release_device(jcr->read_dcr)) {
ok = false;
}
break;
}
jcr->mount_next_volume = false;
+ /*
+ * The Device can change at the end of a tape, so refresh it
+ * from the dcr.
+ */
+ dev = dcr->dev;
/*
* We just have a new tape up, now read the label (first record)
* and pass it off to the callback routine, then continue
Dmsg4(300, "Try_Reposition from (file:block) %u:%u to %u:%u\n",
dev->file, dev->block_num, bsr->volfile->sfile,
bsr->volblock->sblock);
- reposition_dev(dev, bsr->volfile->sfile, bsr->volblock->sblock);
+ dev->reposition(bsr->volfile->sfile, bsr->volblock->sblock);
rec->Block = 0;
}
return false;
bsr->volfile->sfile, bsr->volblock->sblock);
Dmsg2(300, "Forward spacing to file:block %u:%u.\n",
bsr->volfile->sfile, bsr->volblock->sblock);
- reposition_dev(dev, bsr->volfile->sfile, bsr->volblock->sblock);
+ dev->reposition(bsr->volfile->sfile, bsr->volblock->sblock);
}
}
return bsr;
/* Forward referenced functions */
static int can_reserve_drive(DCR *dcr, RCTX &rctx);
-static int search_res_for_device(RCTX &rctx);
static int reserve_device(RCTX &rctx);
static bool reserve_device_for_read(DCR *dcr);
static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
static bool use_storage_cmd(JCR *jcr);
static void queue_reserve_message(JCR *jcr);
-static void release_msgs(JCR *jcr);
/* Requests from the Director daemon */
static char use_storage[] = "use storage=%127s media_type=%127s "
void free_unused_volume(DCR *dcr)
{
VOLRES *vol;
+
P(vol_list_lock);
for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
if (vol->dcr == dcr && (vol->dev == NULL ||
*/
if (ok) {
bool first = true; /* print wait message once */
+ rctx.notify_dir = true;
for ( ; !job_canceled(jcr); ) {
P(search_lock); /* only one thread at a time */
while ((msg = (char *)msgs->pop())) {
return ok;
}
-static void release_msgs(JCR *jcr)
+void release_msgs(JCR *jcr)
{
alist *msgs = jcr->reserve_msgs;
char *msg;
+ if (!msgs) {
+ return;
+ }
P(search_lock);
while ((msg = (char *)msgs->pop())) {
free(msg);
* Search for a particular storage device with particular storage
* characteristics (MediaType).
*/
-static int search_res_for_device(RCTX &rctx)
+int search_res_for_device(RCTX &rctx)
{
AUTOCHANGER *changer;
BSOCK *dir = rctx.jcr->dir_bsock;
Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
rctx.jcr->read_dcr->dev->reserved_device);
}
- pm_strcpy(dev_name, rctx.device->hdr.name);
- bash_spaces(dev_name);
- ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
- Dmsg1(100, ">dird changer: %s", dir->msg);
+ if (rctx.notify_dir) {
+ pm_strcpy(dev_name, rctx.device->hdr.name);
+ bash_spaces(dev_name);
+ ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
+ Dmsg1(100, ">dird changer: %s", dir->msg);
+ } else {
+ ok = true;
+ }
return ok ? 1 : -1;
}
}
if (stat != 1) {
return stat;
}
- Dmsg1(220, "Got: %s", dir->msg);
- bash_spaces(rctx.device_name);
- ok = bnet_fsend(dir, OK_device, rctx.device_name);
- Dmsg1(100, ">dird dev: %s", dir->msg);
+ if (rctx.notify_dir) {
+ bash_spaces(rctx.device_name);
+ ok = bnet_fsend(dir, OK_device, rctx.device_name);
+ Dmsg1(100, ">dird dev: %s", dir->msg);
+ } else {
+ ok = true;
+ }
return ok ? 1 : -1;
}
}
bool have_volume; /* Have DIR suggested vol name */
bool suitable_device; /* at least one device is suitable */
bool autochanger_only; /* look at autochangers only */
+ bool notify_dir; /* Notify DIR about device */
char VolumeName[MAX_NAME_LENGTH]; /* Vol name suggested by DIR */
};
ok = write_block_to_device(dcr);
if (!ok) {
Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
- dcr->dev->print_name(), strerror_dev(dcr->dev));
+ dcr->dev->print_name(), dcr->dev->bstrerror());
}
Dmsg3(800, "Write block ok=%d FI=%d LI=%d\n", ok, block->FirstIndex, block->LastIndex);
}
foreach_res(device, R_DEVICE) {
Dmsg1(90, "calling init_dev %s\n", device->device_name);
- device->dev = dev = init_dev(NULL, device);
+ dev = init_dev(NULL, device);
Dmsg1(10, "SD init done %s\n", device->device_name);
if (!dev) {
Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"), device->device_name);
Dmsg1(10, "Term device %s\n", device->device_name);
if (device->dev) {
free_volume(device->dev);
- term_dev(device->dev);
+ device->dev->term();
+ device->dev = NULL;
} else {
Dmsg1(10, "No dev structure %s\n", device->device_name);
}
#undef VERSION
#define VERSION "1.39.5"
-#define BDATE "14 February 2006"
-#define LSMDATE "14Feb06"
+#define BDATE "20 February 2006"
+#define LSMDATE "20Feb06"
/* Debug flags */
#undef DEBUG