- Optimized bootstrap.
For 1.37:
+- Linux Sony LIB-D81, AIT-3 library works.
+- If Bacula does not find the right tape in the Autochanger,
+ then mark the tape in error and move on rather than asking
+ for operator intervention.
- Device resource needs the "name" of the SD.
- Add and option to see if the file size changed
during backup.
CREATE INDEX inx8 ON Media (PoolId);
CREATE TABLE MediaType (
- MediaTypeId INTERGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ MediaTypeId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
MediaType VARCHAR(128) NOT NULL,
ReadOnly TINYINT DEFAULT 0,
PRIMARY KEY(MediaTypeId)
);
+CREATE TABLE Storage (
+ StorageId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ Name VARCHAR(128) NOT NULL,
+ AutoChanger TINYINT DEFAULT 0,
+ PRIMARY KEY(StorageId)
+ );
+
CREATE TABLE Device (
DeviceId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
Name VARCHAR(128) NOT NULL,
PRIMARY KEY(DeviceId)
);
-CREATE TABLE Storage (
- StorageId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- Name VARCHAR(128) NOT NULL,
- AutoChanger TINYINT DEFAULT 0,
- PRIMARY KEY(StorageId)
- );
CREATE TABLE Pool (
PoolId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY(MediaTypeId)
);
+CREATE TABLE Storage (
+ StorageId SERIAL,
+ Name TEXT NOT NULL,
+ AutoChanger INTEGER DEFAULT 0,
+ PRIMARY KEY(StorageId)
+ );
+
CREATE TABLE Device (
DeviceId SERIAL,
Name TEXT NOT NULL,
PRIMARY KEY(DeviceId)
);
-CREATE TABLE Storage (
- StorageId SERIAL,
- Name TEXT NOT NULL,
- AutoChanger INTEGER DEFAULT 0,
- PRIMARY KEY(StorageId)
- );
CREATE TABLE pool
(
CREATE INDEX inx8 ON Media (PoolId);
CREATE TABLE MediaType (
- MediaTypeId INTERGER,
+ 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,
PRIMARY KEY(DeviceId)
);
-CREATE TABLE Storage (
- StorageId INTEGER,
- Name VARCHAR(128) NOT NULL,
- AutoChanger TINYINT DEFAULT 0,
- PRIMARY KEY(StorageId)
- );
-
CREATE TABLE Pool (
PoolId INTEGER,
CREATE INDEX inx8 ON Media (PoolId);
CREATE TABLE MediaType (
- MediaTypeId INTERGER,
+ 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,
PRIMARY KEY(DeviceId)
);
-CREATE TABLE Storage (
- StorageId INTEGER,
- Name VARCHAR(128) NOT NULL,
- AutoChanger TINYINT DEFAULT 0,
- PRIMARY KEY(StorageId)
- );
-
CREATE TABLE Pool (
PoolId INTEGER,
PRIMARY KEY(MediaTypeId)
);
+CREATE TABLE Storage (
+ StorageId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ Name VARCHAR(128) NOT NULL,
+ AutoChanger TINYINT DEFAULT 0,
+ PRIMARY KEY(StorageId)
+ );
+
CREATE TABLE Device (
DeviceId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
Name VARCHAR(128) NOT NULL,
PRIMARY KEY(DeviceId)
);
-CREATE TABLE Storage (
- StorageId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- Name VARCHAR(128) NOT NULL,
- AutoChanger TINYINT DEFAULT 0,
- PRIMARY KEY(StorageId)
- );
-
END-OF-DATA
then
echo "Update of Bacula MySQL tables succeeded."
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,
PRIMARY KEY(DeviceId)
);
-CREATE TABLE Storage (
- StorageId INTEGER,
- Name VARCHAR(128) NOT NULL,
- AutoChanger TINYINT DEFAULT 0,
- PRIMARY KEY(StorageId)
- );
-
COMMIT;
END-OF-DATA
DROP TABLE Pool_backup;
CREATE TABLE MediaType (
- MediaTypeId INTERGER,
+ 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,
PRIMARY KEY(DeviceId)
);
-CREATE TABLE Storage (
- StorageId INTEGER,
- Name VARCHAR(128) NOT NULL,
- AutoChanger TINYINT DEFAULT 0,
- PRIMARY KEY(StorageId)
- );
COMMIT;
#include "ua.h"
-/* Forward referenced functions */
-static void admin_cleanup(JCR *jcr, int TermCode);
-
-/* External functions */
+bool do_admin_init(JCR *jcr)
+{
+ return true;
+}
/*
- * Returns: 0 on failure
- * 1 on success
+ * Returns: false on failure
+ * true on success
*/
-int do_admin(JCR *jcr)
+bool do_admin(JCR *jcr)
{
jcr->jr.JobId = jcr->JobId;
set_jcr_job_status(jcr, JS_Running);
admin_cleanup(jcr, JS_Terminated);
- return 0;
+ return true;
}
+
/*
* Release resources allocated during backup.
*/
-static void admin_cleanup(JCR *jcr, int TermCode)
+void admin_cleanup(JCR *jcr, int TermCode)
{
char sdt[50], edt[50];
char term_code[100];
static char EndJob[] = "2800 End Job TermCode=%d JobFiles=%u "
"ReadBytes=%lld JobBytes=%lld Errors=%u\n";
-
-/* Forward referenced functions */
-static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr);
-
-/* External functions */
-
-/*
- * Do a backup of the specified FileSet
- *
- * Returns: 0 on failure
- * 1 on success
+/*
+ * Called here before the job is run to do the job
+ * specific setup.
*/
-int do_backup(JCR *jcr)
+bool do_backup_init(JCR *jcr)
{
- char since[MAXSTRING];
- int stat;
- BSOCK *fd;
- POOL_DBR pr;
FILESET_DBR fsr;
- STORE *store;
-
- since[0] = 0;
-
- if (!get_or_create_fileset_record(jcr, &fsr)) {
- goto bail_out;
- }
-
- get_level_since_time(jcr, since, sizeof(since));
-
+ POOL_DBR pr;
/*
* Get the Pool record -- first apply any level defined pools
*/
memset(&pr, 0, sizeof(pr));
bstrncpy(pr.Name, jcr->pool->hdr.name, sizeof(pr.Name));
- while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
+ if (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
/* Try to create the pool */
if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
db_strerror(jcr->db));
- goto bail_out;
+ return false;
} else {
Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
+ if (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
+ Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
+ db_strerror(jcr->db));
+ return false;
+ }
}
}
jcr->PoolId = pr.PoolId; /****FIXME**** this can go away */
jcr->jr.PoolId = pr.PoolId;
+ jcr->since[0] = 0;
+
+ if (!get_or_create_fileset_record(jcr, &fsr)) {
+ return false;
+ }
+ bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
+
+ get_level_since_time(jcr, jcr->since, sizeof(jcr->since));
+
+ return true;
+}
+
+/*
+ * Do a backup of the specified FileSet
+ *
+ * Returns: false on failure
+ * true on success
+ */
+bool do_backup(JCR *jcr)
+{
+ int stat;
+ BSOCK *fd;
+ STORE *store;
+
/* Print Job Start message */
Jmsg(jcr, M_INFO, 0, _("Start Backup JobId %u, Job=%s\n"),
Dmsg2(100, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel);
if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
- goto bail_out;
+ return false;
}
/*
* Start conversation with Storage daemon
*/
if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
- goto bail_out;
+ return false;
}
/*
* Now start a job with the Storage daemon
*/
if (!start_storage_daemon_job(jcr, jcr->storage, SD_APPEND)) {
- goto bail_out;
+ return false;
}
/*
* Now start a Storage daemon message thread
*/
if (!start_storage_daemon_message_thread(jcr)) {
- goto bail_out;
+ return false;
}
Dmsg0(150, "Storage daemon connection OK\n");
set_jcr_job_status(jcr, JS_WaitFD);
if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
- goto bail_out;
+ return false;
}
set_jcr_job_status(jcr, JS_Running);
fd = jcr->file_bsock;
if (!send_include_list(jcr)) {
- goto bail_out;
+ return false;
}
if (!send_exclude_list(jcr)) {
- goto bail_out;
+ return false;
}
if (!send_level_command(jcr)) {
- goto bail_out;
+ return false;
}
/*
bnet_fsend(fd, storaddr, store->address, store->SDDport,
store->enable_ssl);
if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
- goto bail_out;
+ return false;
}
if (!send_run_before_and_after_commands(jcr)) {
- goto bail_out;
+ return false;
}
/* Send backup command */
bnet_fsend(fd, backupcmd);
if (!response(jcr, fd, OKbackup, "backup", DISPLAY_ERROR)) {
- goto bail_out;
+ return false;
}
/* Pickup Job termination data */
stat = wait_for_job_termination(jcr);
- backup_cleanup(jcr, stat, since, &fsr);
- return 1;
-
-bail_out:
- backup_cleanup(jcr, JS_ErrorTerminated, since, &fsr);
- return 0;
+ backup_cleanup(jcr, stat);
+ return stat == JS_Terminated;
}
+
/*
* Here we wait for the File daemon to signal termination,
* then we wait for the Storage daemon. When both
/*
* Release resources allocated during backup.
*/
-static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr)
+void backup_cleanup(JCR *jcr, int TermCode)
{
char sdt[50], edt[50];
char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], compress[50];
edt,
jcr->jr.JobId,
jcr->jr.Job,
- level_to_str(jcr->JobLevel), since,
+ level_to_str(jcr->JobLevel), jcr->since,
jcr->client->hdr.name,
- jcr->fileset->hdr.name, fsr->cCreateTime,
+ jcr->fileset->hdr.name, jcr->FSCreateTime,
jcr->pool->hdr.name,
jcr->store->hdr.name,
sdt,
JCR *wait_for_next_job(char *runjob);
void term_scheduler();
void term_ua_server();
-int do_backup(JCR *jcr);
-void backup_cleanup(void);
void start_UA_server(dlist *addrs);
void init_job_server(int max_workers);
void term_job_server();
case R_DEVICE:
dev = &res->res_dev;
sendit(sock, "Device: name=%s ok=%d num_writers=%d num_waiting=%d\n"
-" use_cnt=%d open=%d append=%d read=%d labeled=%d\n"
+" use_cnt=%d open=%d append=%d read=%d labeled=%d offline=%d autochgr=%d\n"
" volname=%s MediaType=%s\n",
dev->hdr.name, dev->found, dev->num_writers, dev->num_waiting,
dev->use_count, dev->open, dev->append, dev->read, dev->labeled,
+ dev->offline, dev->autochanger,
dev->VolumeName, dev->MediaType);
break;
case R_STORAGE:
bool append; /* in append mode */
bool read;
bool labeled;
+ bool autochanger;
+ bool offline;
char VolumeName[MAX_NAME_LENGTH];
char MediaType[MAX_NAME_LENGTH];
};
/* Imported subroutines */
extern void term_scheduler();
extern void term_ua_server();
-extern int do_backup(JCR *jcr);
-extern bool do_mac(JCR *jcr);
-extern int do_admin(JCR *jcr);
-extern int do_restore(JCR *jcr);
-extern bool do_verify(JCR *jcr);
/* Imported variables */
extern time_t watchdog_time;
jcr->fname = get_pool_memory(PM_FNAME);
}
+ /* Now, do pre-run stuff, like setting job level (Inc/diff, ...) */
+ switch (jcr->JobType) {
+ case JT_BACKUP:
+ if (!do_backup_init(jcr)) {
+ backup_cleanup(jcr, JS_ErrorTerminated);
+ }
+ break;
+ case JT_VERIFY:
+ if (!do_verify_init(jcr)) {
+ verify_cleanup(jcr, JS_ErrorTerminated);
+ }
+ break;
+ case JT_RESTORE:
+ if (!do_restore_init(jcr)) {
+ restore_cleanup(jcr, JS_ErrorTerminated);
+ }
+ break;
+ case JT_ADMIN:
+ if (!do_admin_init(jcr)) {
+ admin_cleanup(jcr, JS_ErrorTerminated);
+ }
+ break;
+ case JT_MIGRATION:
+ case JT_COPY:
+ case JT_ARCHIVE:
+ if (!do_mac_init(jcr)) { /* migration, archive, copy */
+ mac_cleanup(jcr, JS_ErrorTerminated);
+ }
+ break;
+ default:
+ Pmsg1(0, "Unimplemented job type: %d\n", jcr->JobType);
+ set_jcr_job_status(jcr, JS_ErrorTerminated);
+ break;
+ }
+ if (job_canceled(jcr)) {
+ goto bail_out;
+ }
+
Dmsg0(200, "Add jrc to work queue\n");
/* Queue the job to be run */
return JobId;
bail_out:
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ if (jcr->fname) {
+ free_memory(jcr->fname);
+ jcr->fname = NULL;
+ }
V(jcr->mutex);
return JobId;
}
switch (jcr->JobType) {
case JT_BACKUP:
- do_backup(jcr);
- if (jcr->JobStatus == JS_Terminated) {
+ if (do_backup(jcr)) {
do_autoprune(jcr);
+ } else {
+ backup_cleanup(jcr, JS_ErrorTerminated);
}
break;
case JT_VERIFY:
- do_verify(jcr);
- if (jcr->JobStatus == JS_Terminated) {
+ if (do_verify(jcr)) {
do_autoprune(jcr);
+ } else {
+ verify_cleanup(jcr, JS_ErrorTerminated);
}
break;
case JT_RESTORE:
- do_restore(jcr);
- if (jcr->JobStatus == JS_Terminated) {
+ if (do_restore(jcr)) {
do_autoprune(jcr);
+ } else {
+ restore_cleanup(jcr, JS_ErrorTerminated);
}
break;
case JT_ADMIN:
- do_admin(jcr);
- if (jcr->JobStatus == JS_Terminated) {
+ if (do_admin(jcr)) {
do_autoprune(jcr);
+ } else {
+ admin_cleanup(jcr, JS_ErrorTerminated);
}
break;
case JT_MIGRATION:
case JT_COPY:
case JT_ARCHIVE:
- do_mac(jcr); /* migration, archive, copy */
- if (jcr->JobStatus == JS_Terminated) {
+ if (do_mac(jcr)) { /* migration, archive, copy */
do_autoprune(jcr);
+ } else {
+ mac_cleanup(jcr, JS_ErrorTerminated);
}
break;
default:
#include "dird.h"
#include "ua.h"
-/* Forward referenced functions */
-static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr,
- const char *Type);
-
-/* External functions */
-
-/*
- * Do a Migration, Archive, or Copy of a previous job
- *
- * Returns: false on failure
- * true on success
+/*
+ * Called here before the job is run to do the job
+ * specific setup.
*/
-bool do_mac(JCR *jcr)
+bool do_mac_init(JCR *jcr)
{
- char since[MAXSTRING];
- int stat;
+ FILESET_DBR fsr;
POOL_DBR pr;
JOB_DBR jr;
- FILESET_DBR fsr;
JobId_t input_jobid;
char *Name;
- const char *Type;
-
- switch(jcr->JobType) {
- case JT_MIGRATION:
- Type = "Migration";
- break;
- case JT_ARCHIVE:
- Type = "Archive";
- break;
- case JT_COPY:
- Type = "Copy";
- break;
- default:
- Type = "Unknown";
- break;
- }
if (!get_or_create_fileset_record(jcr, &fsr)) {
- goto bail_out;
+ return false;
}
+ bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
/*
* Find JobId of last job that ran.
if (!db_find_last_jobid(jcr, jcr->db, Name, &jr)) {
Jmsg(jcr, M_FATAL, 0, _(
"Unable to find JobId of previous Job for this client.\n"));
- goto bail_out;
+ return false;
}
input_jobid = jr.JobId;
jcr->JobLevel = jr.JobLevel;
if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
db_strerror(jcr->db));
- goto bail_out;
+ return false;
} else {
Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
}
}
jcr->PoolId = pr.PoolId; /****FIXME**** this can go away */
jcr->jr.PoolId = pr.PoolId;
+ jcr->needs_sd = true;
+ return true;
+}
+
+/*
+ * Do a Migration, Archive, or Copy of a previous job
+ *
+ * Returns: false on failure
+ * true on success
+ */
+bool do_mac(JCR *jcr)
+{
+ int stat;
+ const char *Type;
+
+ switch(jcr->JobType) {
+ case JT_MIGRATION:
+ Type = "Migration";
+ break;
+ case JT_ARCHIVE:
+ Type = "Archive";
+ break;
+ case JT_COPY:
+ Type = "Copy";
+ break;
+ default:
+ Type = "Unknown";
+ break;
+ }
/* Print Job Start message */
Dmsg2(100, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel);
if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
- goto bail_out;
+ return false;
}
/*
* Start conversation with Storage daemon
*/
if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
- goto bail_out;
+ return false;
}
/*
* Now start a job with the Storage daemon
*/
if (!start_storage_daemon_job(jcr, jcr->storage, SD_APPEND)) {
- goto bail_out;
+ return false;
}
/*
* Now start a Storage daemon message thread
*/
if (!start_storage_daemon_message_thread(jcr)) {
- goto bail_out;
+ return false;
}
Dmsg0(150, "Storage daemon connection OK\n");
} else {
stat = jcr->SDJobStatus;
}
- mac_cleanup(jcr, stat, since, &fsr, Type);
- return true;
-
-bail_out:
- mac_cleanup(jcr, JS_ErrorTerminated, since, &fsr, Type);
- return false;
+ mac_cleanup(jcr, stat);
+ return jcr->JobStatus == JS_Terminated;
}
/*
* Release resources allocated during backup.
*/
-static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr,
- const char *Type)
+void mac_cleanup(JCR *jcr, int TermCode)
{
char sdt[50], edt[50];
char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], compress[50];
MEDIA_DBR mr;
double kbps, compression;
utime_t RunTime;
+ const char *Type;
+
+ switch(jcr->JobType) {
+ case JT_MIGRATION:
+ Type = "Migration";
+ break;
+ case JT_ARCHIVE:
+ Type = "Archive";
+ break;
+ case JT_COPY:
+ Type = "Copy";
+ break;
+ default:
+ Type = "Unknown";
+ break;
+ }
Dmsg2(100, "Enter mac_cleanup %d %c\n", TermCode, TermCode);
dequeue_messages(jcr); /* display any queued messages */
edt,
jcr->jr.JobId,
jcr->jr.Job,
- level_to_str(jcr->JobLevel), since,
+ level_to_str(jcr->JobLevel), jcr->since,
jcr->client->hdr.name,
- jcr->fileset->hdr.name, fsr->cCreateTime,
+ jcr->fileset->hdr.name, jcr->FSCreateTime,
jcr->pool->hdr.name,
sdt,
edt,
static char OKjob[] = "3000 OK Job SDid=%d SDtime=%d Authorization=%100s\n";
static char OK_device[] = "3000 OK use device\n";
static char OK_query[] = "3001 OK query append=%d read=%d num_writers=%d "
- "num_waiting=%d open=%d use_count=%d labeled=%d "
+ "num_waiting=%d open=%d use_count=%d labeled=%d offline=%d autochanger=%d "
"media_type=%127s volume_name=%127s";
/* Storage Daemon requests */
{
POOL_MEM device_name, media_type, volume_name;
int dev_open, dev_append, dev_read, dev_labeled;
+ int dev_offline, dev_autochanger;
BSOCK *sd;
if (!connect_to_storage_daemon(jcr, 5, 30, 0)) {
return false;
Dmsg1(400, "<stored: %s", sd->msg);
if (sscanf(sd->msg, OK_query, &dev_append, &dev_read,
&dev->num_writers, &dev->num_waiting, &dev_open,
- &dev->use_count, &dev_labeled, media_type.c_str(),
- volume_name.c_str()) != 9) {
+ &dev->use_count, &dev_labeled, &dev_offline,
+ &dev_autochanger, media_type.c_str(),
+ volume_name.c_str()) != 11) {
return false;
}
unbash_spaces(media_type);
dev->append = dev_append;
dev->read = dev_read;
dev->labeled = dev_labeled;
+ dev->offline = dev_offline;
+ dev->autochanger = dev_autochanger;
dev->found = true;
} else {
return false;
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
*/
+/* admin.c */
+extern bool do_admin_init(JCR *jcr);
+extern bool do_admin(JCR *jcr);
+extern void admin_cleanup(JCR *jcr, int TermCode);
+
+
/* authenticate.c */
extern bool authenticate_storage_daemon(JCR *jcr, STORE *store);
extern int authenticate_file_daemon(JCR *jcr);
/* backup.c */
extern int wait_for_job_termination(JCR *jcr);
+extern bool do_backup_init(JCR *jcr);
+extern bool do_backup(JCR *jcr);
+extern void backup_cleanup(JCR *jcr, int TermCode);
/* bsr.c */
RBSR *new_bsr();
/* fd_cmds.c */
extern int connect_to_file_daemon(JCR *jcr, int retry_interval,
- int max_retry_time, int verbose);
+ int max_retry_time, int verbose);
extern int send_include_list(JCR *jcr);
extern int send_exclude_list(JCR *jcr);
extern int send_bootstrap_file(JCR *jcr);
extern int get_attributes_and_put_in_catalog(JCR *jcr);
extern int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId);
extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname,
- char *link, char *attr, int stream);
+ char *link, char *attr, int stream);
extern void get_level_since_time(JCR *jcr, char *since, int since_len);
extern int send_run_before_and_after_commands(JCR *jcr);
extern void copy_storage(JCR *new_jcr, JCR *old_jcr);
extern void set_storage(JCR *jcr, STORE *store);
+/* mac.c */
+extern bool do_mac(JCR *jcr);
+extern bool do_mac_init(JCR *jcr);
+extern void mac_cleanup(JCR *jcr, int TermCode);
+
+
/* mountreq.c */
extern void mount_request(JCR *jcr, BSOCK *bs, char *buf);
/* msgchan.c */
extern bool connect_to_storage_daemon(JCR *jcr, int retry_interval,
- int max_retry_time, int verbose);
+ int max_retry_time, int verbose);
extern int start_storage_daemon_job(JCR *jcr, alist *store, int append);
extern int start_storage_daemon_message_thread(JCR *jcr);
extern int bget_dirmsg(BSOCK *bs);
/* newvol.c */
bool newVolume(JCR *jcr, MEDIA_DBR *mr);
+/* restore.c */
+extern bool do_restore(JCR *jcr);
+extern bool do_restore_init(JCR *jcr);
+extern void restore_cleanup(JCR *jcr, int TermCode);
+
+
/* ua_acl.c */
bool acl_access_ok(UAContext *ua, int acl, char *item);
bool acl_access_ok(UAContext *ua, int acl, char *item, int len);
void free_ua_context(UAContext *ua);
/* ua_select.c */
-STORE *select_storage_resource(UAContext *ua);
-JOB *select_job_resource(UAContext *ua);
-JOB *select_restore_job_resource(UAContext *ua);
-CLIENT *select_client_resource(UAContext *ua);
+STORE *select_storage_resource(UAContext *ua);
+JOB *select_job_resource(UAContext *ua);
+JOB *select_restore_job_resource(UAContext *ua);
+CLIENT *select_client_resource(UAContext *ua);
FILESET *select_fileset_resource(UAContext *ua);
-int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
-int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
-bool select_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
-
-void start_prompt(UAContext *ua, const char *msg);
-void add_prompt(UAContext *ua, const char *prompt);
-int do_prompt(UAContext *ua, const char *automsg, const char *msg, char *prompt, int max_prompt);
+int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
+bool select_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+
+void start_prompt(UAContext *ua, const char *msg);
+void add_prompt(UAContext *ua, const char *prompt);
+int do_prompt(UAContext *ua, const char *automsg, const char *msg, char *prompt, int max_prompt);
CAT *get_catalog_resource(UAContext *ua);
STORE *get_storage_resource(UAContext *ua, int use_default);
-int get_media_type(UAContext *ua, char *MediaType, int max_media);
-bool get_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+int get_media_type(UAContext *ua, char *MediaType, int max_media);
+bool get_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
POOL *get_pool_resource(UAContext *ua);
POOL *select_pool_resource(UAContext *ua);
CLIENT *get_client_resource(UAContext *ua);
-int get_job_dbr(UAContext *ua, JOB_DBR *jr);
+int get_job_dbr(UAContext *ua, JOB_DBR *jr);
int find_arg_keyword(UAContext *ua, const char **list);
int find_arg(UAContext *ua, const char *keyword);
/* ua_run.c */
extern int run_cmd(UAContext *ua, const char *cmd);
+
+/* verify.c */
+extern bool do_verify(JCR *jcr);
+extern bool do_verify_init(JCR *jcr);
+extern void verify_cleanup(JCR *jcr, int TermCode);
static char OKstore[] = "2000 OK storage\n";
static char OKsession[] = "2000 OK session\n";
-/* Forward referenced functions */
-static void restore_cleanup(JCR *jcr, int status);
-
-/* External functions */
-
/*
* Do a restore of the specified files
*
* Returns: 0 on failure
* 1 on success
*/
-int do_restore(JCR *jcr)
+bool do_restore(JCR *jcr)
{
BSOCK *fd;
JOB_DBR rjr; /* restore job record */
if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
Dmsg0(20, "Updated job start record\n");
Jmsg2(jcr, M_FATAL, 0, _("Cannot get job record id=%d %s"), rjr.JobId,
db_strerror(jcr->db));
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
/*
Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume names for restore Job %d. %s"),
rjr.JobId, db_strerror(jcr->db));
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
Dmsg1(20, "Got job Volume Names: %s\n", jcr->VolumeName);
}
*/
if (!start_storage_daemon_job(jcr, jcr->storage, SD_READ)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
/*
* Now start a Storage daemon message thread
*/
if (!start_storage_daemon_message_thread(jcr)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
Dmsg0(50, "Storage daemon connection OK\n");
set_jcr_job_status(jcr, JS_WaitFD);
if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
fd = jcr->file_bsock;
if (!send_include_list(jcr)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
if (!send_exclude_list(jcr)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
/*
Dmsg1(6, "dird>filed: %s\n", fd->msg);
if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
/*
*/
if (!send_bootstrap_file(jcr)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
/*
rjr.EndBlock);
if (!response(jcr, fd, OKsession, "Session", DISPLAY_ERROR)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
}
if (!send_run_before_and_after_commands(jcr)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
/* Send restore command */
if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
/* Wait for Job Termination */
int stat = wait_for_job_termination(jcr);
restore_cleanup(jcr, stat);
- return 1;
+ return true;
+}
+
+bool do_restore_init(JCR *jcr)
+{
+ return true;
}
/*
* Release resources allocated during restore.
*
*/
-static void restore_cleanup(JCR *jcr, int TermCode)
+void restore_cleanup(JCR *jcr, int TermCode)
{
char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
char ec1[30], ec2[30], ec3[30];
/* Commands sent to File daemon */
static char verifycmd[] = "verify level=%s\n";
static char storaddr[] = "storage address=%s port=%d ssl=0\n";
-static char sessioncmd[] = "session %s %ld %ld %ld %ld %ld %ld\n";
/* Responses received from File daemon */
static char OKverify[] = "2000 OK verify\n";
static char OKstore[] = "2000 OK storage\n";
-static char OKsession[] = "2000 OK session\n";
/* Forward referenced functions */
-static void verify_cleanup(JCR *jcr, int TermCode);
static void prt_fname(JCR *jcr);
static int missing_handler(void *ctx, int num_fields, char **row);
-/*
- * Do a verification of the specified files against the Catlaog
- *
- * Returns: false on failure
- * true on success
+
+/*
+ * Called here before the job is run to do the job
+ * specific setup.
*/
-bool do_verify(JCR *jcr)
+bool do_verify_init(JCR *jcr)
{
- const char *level, *Name;
- BSOCK *fd;
- JOB_DBR jr, verify_jr;
+ JOB_DBR jr;
JobId_t verify_jobid = 0;
- int stat;
+ const char *Name;
- memset(&verify_jr, 0, sizeof(verify_jr));
- if (!jcr->verify_jr) {
- jcr->verify_jr = &verify_jr;
- }
+ memset(&jcr->target_jr, 0, sizeof(jcr->target_jr));
Dmsg1(9, "bdird: created client %s record\n", jcr->client->hdr.name);
Jmsg(jcr, M_FATAL, 0, _(
"Unable to find JobId of previous Job for this client.\n"));
}
- goto bail_out;
+ return false;
}
verify_jobid = jr.JobId;
Dmsg1(100, "Last full jobid=%d\n", verify_jobid);
}
-
- if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
- Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
- goto bail_out;
- }
-
- /* Print Job Start message */
- Jmsg(jcr, M_INFO, 0, _("Start Verify JobId=%d Level=%s Job=%s\n"),
- jcr->JobId, level_to_str(jcr->JobLevel), jcr->Job);
-
/*
* Now get the job record for the previous backup that interests
* us. We use the verify_jobid that we found above.
if (jcr->JobLevel == L_VERIFY_CATALOG ||
jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG ||
jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) {
- verify_jr.JobId = verify_jobid;
- if (!db_get_job_record(jcr, jcr->db, &verify_jr)) {
+ jcr->target_jr.JobId = verify_jobid;
+ if (!db_get_job_record(jcr, jcr->db, &jcr->target_jr)) {
Jmsg(jcr, M_FATAL, 0, _("Could not get job record for previous Job. ERR=%s"),
db_strerror(jcr->db));
- goto bail_out;
+ return false;
}
- if (verify_jr.JobStatus != 'T') {
+ if (jcr->target_jr.JobStatus != 'T') {
Jmsg(jcr, M_FATAL, 0, _("Last Job %d did not terminate normally. JobStatus=%c\n"),
- verify_jobid, verify_jr.JobStatus);
- goto bail_out;
+ verify_jobid, jcr->target_jr.JobStatus);
+ return false;
}
Jmsg(jcr, M_INFO, 0, _("Verifying against JobId=%d Job=%s\n"),
- verify_jr.JobId, verify_jr.Job);
+ jcr->target_jr.JobId, jcr->target_jr.Job);
}
/*
if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) {
RBSR *bsr = new_bsr();
UAContext *ua;
- bsr->JobId = verify_jr.JobId;
+ bsr->JobId = jcr->target_jr.JobId;
ua = new_ua_context(jcr);
complete_bsr(ua, bsr);
bsr->fi = new_findex();
bsr->fi->findex = 1;
- bsr->fi->findex2 = verify_jr.JobFiles;
+ bsr->fi->findex2 = jcr->target_jr.JobFiles;
jcr->ExpectedFiles = write_bsr_file(ua, bsr);
if (jcr->ExpectedFiles == 0) {
free_ua_context(ua);
free_bsr(bsr);
- goto bail_out;
+ return false;
}
free_ua_context(ua);
free_bsr(bsr);
Mmsg(fname, "%s/restore.bsr", working_directory);
jcr->RestoreBootstrap = bstrdup(fname);
free_pool_memory(fname);
+ jcr->needs_sd = true;
+
+ } else {
+ jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */
+ }
+
+ if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG && jcr->verify_job) {
+ jcr->fileset = jcr->verify_job->fileset;
+ }
+ Dmsg2(100, "ClientId=%u JobLevel=%c\n", jcr->target_jr.ClientId, jcr->JobLevel);
+ return true;
+}
+
+
+/*
+ * Do a verification of the specified files against the Catlaog
+ *
+ * Returns: false on failure
+ * true on success
+ */
+bool do_verify(JCR *jcr)
+{
+ const char *level;
+ BSOCK *fd;
+ int stat;
+
+ if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
+ Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
+ return false;
+ }
+ /* Print Job Start message */
+ Jmsg(jcr, M_INFO, 0, _("Start Verify JobId=%d Level=%s Job=%s\n"),
+ jcr->JobId, level_to_str(jcr->JobLevel), jcr->Job);
+
+ if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) {
/*
* Start conversation with Storage daemon
*/
set_jcr_job_status(jcr, JS_Blocked);
if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
- goto bail_out;
+ return false;
}
/*
* Now start a job with the Storage daemon
*/
if (!start_storage_daemon_job(jcr, jcr->storage, SD_READ)) {
- goto bail_out;
+ return false;
}
/*
* Now start a Storage daemon message thread
*/
if (!start_storage_daemon_message_thread(jcr)) {
- goto bail_out;
+ return false;
}
Dmsg0(50, "Storage daemon connection OK\n");
- } else {
- jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */
}
-
- if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG && jcr->verify_job) {
- jcr->fileset = jcr->verify_job->fileset;
- }
- Dmsg2(100, "ClientId=%u JobLevel=%c\n", verify_jr.ClientId, jcr->JobLevel);
-
/*
* OK, now connect to the File daemon
* and ask him for the files.
*/
set_jcr_job_status(jcr, JS_Blocked);
if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
- goto bail_out;
+ return false;
}
set_jcr_job_status(jcr, JS_Running);
Dmsg0(30, ">filed: Send include list\n");
if (!send_include_list(jcr)) {
- goto bail_out;
+ return false;
}
Dmsg0(30, ">filed: Send exclude list\n");
if (!send_exclude_list(jcr)) {
- goto bail_out;
+ return false;
}
/*
}
bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport);
if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
- goto bail_out;
+ return false;
}
/*
* Send the bootstrap file -- what Volumes/files to restore
*/
if (!send_bootstrap_file(jcr)) {
- goto bail_out;
+ return false;
}
- /*
- * The following code is deprecated
- */
if (!jcr->RestoreBootstrap) {
- /*
- * Pass the VolSessionId, VolSessionTime, Start and
- * end File and Blocks on the session command.
- */
- bnet_fsend(fd, sessioncmd,
- jcr->VolumeName,
- jr.VolSessionId, jr.VolSessionTime,
- jr.StartFile, jr.EndFile, jr.StartBlock,
- jr.EndBlock);
- if (!response(jcr, fd, OKsession, "Session", DISPLAY_ERROR)) {
- goto bail_out;
- }
+ Jmsg0(jcr, M_FATAL, 0, _("Deprecated feature ... use bootstrap.\n"));
+ return false;
}
+
level = "volume";
break;
case L_VERIFY_DATA:
default:
Jmsg2(jcr, M_FATAL, 0, _("Unimplemented Verify level %d(%c)\n"), jcr->JobLevel,
jcr->JobLevel);
- goto bail_out;
+ return false;
}
if (!send_run_before_and_after_commands(jcr)) {
- goto bail_out;
+ return false;
}
/*
*/
bnet_fsend(fd, verifycmd, level);
if (!response(jcr, fd, OKverify, "Verify", DISPLAY_ERROR)) {
- goto bail_out;
+ return false;
}
/*
Dmsg0(10, "Verify level=catalog\n");
jcr->sd_msg_thread_done = true; /* no SD msg thread, so it is done */
jcr->SDJobStatus = JS_Terminated;
- get_attributes_and_compare_to_catalog(jcr, verify_jobid);
+ get_attributes_and_compare_to_catalog(jcr, jcr->target_jr.JobId);
break;
case L_VERIFY_VOLUME_TO_CATALOG:
Dmsg0(10, "Verify level=volume\n");
- get_attributes_and_compare_to_catalog(jcr, verify_jobid);
+ get_attributes_and_compare_to_catalog(jcr, jcr->target_jr.JobId);
break;
case L_VERIFY_DISK_TO_CATALOG:
Dmsg0(10, "Verify level=disk_to_catalog\n");
jcr->sd_msg_thread_done = true; /* no SD msg thread, so it is done */
jcr->SDJobStatus = JS_Terminated;
- get_attributes_and_compare_to_catalog(jcr, verify_jobid);
+ get_attributes_and_compare_to_catalog(jcr, jcr->target_jr.JobId);
break;
case L_VERIFY_INIT:
default:
Jmsg1(jcr, M_FATAL, 0, _("Unimplemented verify level %d\n"), jcr->JobLevel);
- goto bail_out;
+ return false;
}
stat = wait_for_job_termination(jcr);
verify_cleanup(jcr, stat);
return true;
-
-bail_out:
- verify_cleanup(jcr, JS_ErrorTerminated);
- return false;
}
+
/*
* Release resources allocated during backup.
*
*/
-static void verify_cleanup(JCR *jcr, int TermCode)
+void verify_cleanup(JCR *jcr, int TermCode)
{
char sdt[50], edt[50];
char ec1[30], ec2[30];
jcr->fileset->hdr.name,
level_to_str(jcr->JobLevel),
jcr->client->hdr.name,
- jcr->verify_jr->JobId,
+ jcr->target_jr.JobId,
Name,
sdt,
edt,
jcr->fileset->hdr.name,
level_to_str(jcr->JobLevel),
jcr->client->hdr.name,
- jcr->verify_jr->JobId,
+ jcr->target_jr.JobId,
Name,
sdt,
edt,
term_msg);
}
Dmsg0(100, "Leave verify_cleanup()\n");
- if (jcr->fname) {
- free_memory(jcr->fname);
- jcr->fname = NULL;
- }
}
/*
fname)) != 3) {
Jmsg3(jcr, M_FATAL, 0, _("bird<filed: bad attributes, expected 3 fields got %d\n"
" mslen=%d msg=%s\n"), len, fd->msglen, fd->msg);
- goto bail_out;
+ return false;
}
/*
* We read the Options or Signature into fname
*/
fdbr.FileId = 0;
if (!db_get_file_attributes_record(jcr, jcr->db, jcr->fname,
- jcr->verify_jr, &fdbr)) {
+ &jcr->target_jr, &fdbr)) {
Jmsg(jcr, M_INFO, 0, _("New file: %s\n"), jcr->fname);
Dmsg1(020, _("File not in catalog: %s\n"), jcr->fname);
stat = JS_Differences;
if (jcr->FileIndex != (uint32_t)file_index) {
Jmsg2(jcr, M_FATAL, 0, _("MD5/SHA1 index %d not same as attributes %d\n"),
file_index, jcr->FileIndex);
- goto bail_out;
+ return false;
}
if (do_SIG) {
db_escape_string(buf, Opts_SIG, strlen(Opts_SIG));
berrno be;
Jmsg2(jcr, M_FATAL, 0, _("bdird<filed: bad attributes from filed n=%d : %s\n"),
n, be.strerror());
- goto bail_out;
+ return false;
}
/* Now find all the files that are missing -- i.e. all files in
}
free_pool_memory(fname);
set_jcr_job_status(jcr, stat);
- return 1;
-
-bail_out:
- free_pool_memory(fname);
- set_jcr_job_status(jcr, JS_ErrorTerminated);
- return 0;
+ return stat == JS_Terminated;
}
/*
POOLMEM *fname; /* name to put into catalog */
POOLMEM *stime; /* start time for incremental/differential */
JOB_DBR jr; /* Job DB record for current job */
- JOB_DBR *verify_jr; /* Pointer to target job */
+ JOB_DBR target_jr; /* target job */
+ char FSCreateTime[MAX_TIME_LENGTH]; /* FileSet CreateTime as returned from DB */
+ char since[MAX_TIME_LENGTH]; /* since time */
uint32_t RestoreJobId; /* Id specified by UA */
POOLMEM *client_uname; /* client uname */
int replace; /* Replace option */
- int saveMaxConcurrentJobs; /* save for restore jobs */
int NumVols; /* Number of Volume used in pool */
int reschedule_count; /* Number of times rescheduled */
bool spool_data; /* Spool data in SD */
bool term_wait_inited; /* Set when cond var inited */
bool fn_printed; /* printed filename */
bool write_part_after_job; /* Write part after job in SD */
+ bool needs_sd; /* set if SD needed by Job */
#endif /* DIRECTOR_DAEMON */
#define ST_NEXTVOL (1<<13) /* Start writing on next volume */
#define ST_SHORT (1<<14) /* Short block read */
#define ST_MOUNTED (1<<15) /* the device is mounted to the mount point */
+#define ST_OFFLINE (1<<16) /* set offline by operator */
/* dev_blocked states (mutually exclusive) */
enum {
int is_fifo() const;
int is_dvd() const;
int is_open() const;
+ int is_offline() const;
int is_labeled() const;
int is_busy() const; /* either reading or writing */
int at_eof() const;
void set_eot();
void set_append();
void set_read();
+ void set_offline();
void clear_append();
void clear_read();
void clear_label();
+ void clear_offline();
};
/* Note, these return int not bool! */
inline int DEVICE::is_fifo() const { return state & ST_FIFO; }
inline int DEVICE::is_dvd() const { return state & ST_DVD; }
inline int DEVICE::is_open() const { return state & ST_OPENED; }
+inline int DEVICE::is_offline() const { return state & ST_OFFLINE; }
inline int DEVICE::is_labeled() const { return state & ST_LABEL; }
inline int DEVICE::is_busy() const { return state & ST_READ || num_writers; }
inline int DEVICE::at_eof() const { return state & ST_EOF; }
inline int DEVICE::can_read() const { return state & ST_READ; }
inline void DEVICE::set_append() { state |= ST_APPEND; }
inline void DEVICE::set_read() { state |= ST_READ; }
+inline void DEVICE::set_offline() { state |= ST_OFFLINE; }
inline void DEVICE::clear_append() { state &= ~ST_APPEND; }
inline void DEVICE::clear_read() { state &= ~ST_READ; }
inline void DEVICE::clear_label() { state &= ~ST_LABEL; }
+inline void DEVICE::clear_offline() { state &= ~ST_OFFLINE; }
inline const char *DEVICE::strerror() const { return errmsg; }
inline const char *DEVICE::archive_name() const { return dev_name; }
static char BAD_use[] = "3913 Bad use command: %s\n";
static char BAD_job[] = "3915 Bad Job command: %s\n";
static char OK_query[] = "3001 OK query append=%d read=%d num_writers=%d "
- "num_waiting=%d open=%d use_count=%d labeled=%d "
+ "num_waiting=%d open=%d use_count=%d labeled=%d offline=%d autochanger=%d "
"media_type=%s volume_name=%s";
static char BAD_query[] = "3917 Bad query command: %s\n";
return bnet_fsend(dir, OK_query, dev->can_append()!=0,
dev->can_read()!=0, dev->num_writers, dev->num_waiting,
dev->is_open()!=0, dev->use_count, dev->is_labeled()!=0,
+ dev->is_offline()!=0, device->changer_res!=NULL,
MediaType.c_str(), VolumeName.c_str());
}
}
sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
sendit(sock, " max_spool_size=%" lld " max_job_spool_size=%" lld "\n",
res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
+ if (res->res_dev.changer_res) {
+ sendit(sock, " changer=%p\n", res->res_dev.changer_res);
+ }
bstrncpy(buf, " ", sizeof(buf));
if (res->res_dev.cap_bits & CAP_EOF) {
bstrncat(buf, "CAP_EOF ", sizeof(buf));
break;
case R_AUTOCHANGER:
DEVRES *dev;
- sendit(sock, "Changer: name=%s Changer_devname=%s Changer_cmd=%s\n",
+ sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n",
res->res_changer.hdr.name,
res->res_changer.changer_name, res->res_changer.changer_command);
foreach_alist(dev, res->res_changer.device) {
}
/* we must explicitly copy the device alist pointer */
res->res_changer.device = res_all.res_changer.device;
+ /*
+ * Now update each device in this resource to point back
+ * to the changer resource.
+ */
foreach_alist(dev, res->res_changer.device) {
dev->changer_res = (AUTOCHANGER *)&res->res_changer;
}
- if ((errstat = pthread_mutex_init(&dev->changer_res->changer_mutex, NULL)) != 0) {
+ if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) {
berrno be;
Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"),
be.strerror(errstat));
/* */
#undef VERSION
#define VERSION "1.37.4"
-#define BDATE "26 February 2005"
-#define LSMDATE "26Feb05"
+#define BDATE "28 February 2005"
+#define LSMDATE "28Feb05"
/* Debug flags */
#undef DEBUG