#
SVRSRCS = filed.c authenticate.c backup.c estimate.c \
- filed_conf.c job.c \
+ filed_conf.c heartbeat.c job.c \
restore.c status.c verify.c verify_vol.c
SVROBJS = filed.o authenticate.o backup.o estimate.o \
- filed_conf.o job.o \
+ filed_conf.o heartbeat.o job.o \
restore.o status.o verify.o verify_vol.o
# these are the objects that are changed by the .configure process
static int save_file(FF_PKT *ff_pkt, void *pkt);
-#define HB_TIME (20*60)
-/*
- * Listen on the SD socket for heartbeat signals.
- * Send heartbeats to the Director every HB_TIME
- * seconds.
- */
-static void *heartbeat_thread(void *arg)
-{
- int32_t n;
- JCR *jcr = (JCR *)arg;
- BSOCK *sd, *dir;
- time_t last_heartbeat = time(NULL);
- time_t now;
-
- pthread_detach(pthread_self());
-
- /* Get our own local copy */
- sd = dup_bsock(jcr->store_bsock);
- dir = dup_bsock(jcr->dir_bsock);
-
- jcr->duped_sd = sd;
-
- /* Hang reading the socket to the SD, and every time we get
- * a heartbeat, we simply send it on to the Director to
- * keep him alive.
- */
- for ( ; !is_bnet_stop(sd); ) {
- n = bnet_wait_data_intr(sd, 60);
- now = time(NULL);
- if (now-last_heartbeat >= HB_TIME) {
- bnet_sig(dir, BNET_HEARTBEAT);
- last_heartbeat = now;
- }
- if (n == 1) { /* input waiting */
- bnet_recv(sd); /* read it -- probably heartbeat */
- }
- }
- bnet_close(sd);
- bnet_close(dir);
- jcr->duped_sd = NULL;
- return NULL;
-}
-
-/* Startup the heartbeat thread -- see above */
-static void start_heartbeat_monitor(JCR *jcr)
-{
- jcr->duped_sd = NULL;
- pthread_create(&jcr->heartbeat_id, NULL, heartbeat_thread, (void *)jcr);
-}
-
-/* Terminate the heartbeat thread */
-static void stop_heartbeat_monitor(JCR *jcr)
-{
- while (jcr->duped_sd == NULL) {
- bmicrosleep(0, 50); /* avoid race */
- }
- jcr->duped_sd->timed_out = 1; /* set timed_out to terminate read */
- jcr->duped_sd->terminated = 1; /* set to terminate read */
-
- while (jcr->duped_sd) {
- pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL); /* make heartbeat thread go away */
- bmicrosleep(0, 20);
- }
-}
-
/*
* Find all the requested files and send them
* to the Storage daemon.
#endif
extern int win32_client; /* Are we running on Windows? */
+
+extern CLIENT *me; /* "Global" Client resource */
* 1. The generic lexical scanner in lib/lex.c and lib/lex.h
*
* 2. The generic config scanner in lib/parse_config.c and
- * lib/parse_config.h.
- * These files contain the parser code, some utility
- * routines, and the common store routines (name, int,
- * string).
+ * lib/parse_config.h.
+ * These files contain the parser code, some utility
+ * routines, and the common store routines (name, int,
+ * string).
*
* 3. The daemon specific file, which contains the Resource
- * definitions as well as any specific store routines
- * for the resource records.
+ * definitions as well as any specific store routines
+ * for the resource records.
*
* Kern Sibbald, September MM
*
{"fdport", store_pint, ITEM(res_client.FDport), 0, ITEM_DEFAULT, 9102},
{"fdaddress", store_str, ITEM(res_client.FDaddr), 0, 0, 0},
{"workingdirectory", store_dir, ITEM(res_client.working_directory), 0, ITEM_REQUIRED, 0},
- {"piddirectory", store_dir, ITEM(res_client.pid_directory), 0, ITEM_REQUIRED, 0},
- {"subsysdirectory", store_dir, ITEM(res_client.subsys_directory), 0, ITEM_REQUIRED, 0},
- {"requiressl", store_yesno, ITEM(res_client.require_ssl),1, ITEM_DEFAULT, 0},
- {"maximumconcurrentjobs", store_pint, ITEM(res_client.MaxConcurrentJobs), 0, ITEM_DEFAULT, 3},
+ {"piddirectory", store_dir, ITEM(res_client.pid_directory), 0, ITEM_REQUIRED, 0},
+ {"subsysdirectory", store_dir, ITEM(res_client.subsys_directory), 0, ITEM_REQUIRED, 0},
+ {"requiressl", store_yesno, ITEM(res_client.require_ssl), 1, ITEM_DEFAULT, 0},
+ {"maximumconcurrentjobs", store_pint, ITEM(res_client.MaxConcurrentJobs), 0, ITEM_DEFAULT, 5},
{"messages", store_res, ITEM(res_client.messages), R_MSGS, 0, 0},
+ {"heartbeatinterval", store_time, ITEM(res_client.heartbeat_interval), 0, ITEM_DEFAULT, 20*60},
{NULL, NULL, NULL, 0, 0, 0}
};
{"filedaemon", cli_items, R_CLIENT, NULL},
{"client", cli_items, R_CLIENT, NULL}, /* alias for filedaemon */
{"messages", msgs_items, R_MSGS, NULL},
- {NULL, NULL, 0, NULL}
+ {NULL, NULL, 0, NULL}
};
sendit(sock, "No record for %d %s\n", type, res_to_str(type));
return;
}
- if (type < 0) { /* no recursion */
+ if (type < 0) { /* no recursion */
type = - type;
recurse = 0;
}
switch (type) {
case R_DIRECTOR:
sendit(sock, "Director: name=%s password=%s\n", reshdr->name,
- res->res_dir.password);
- break;
+ res->res_dir.password);
+ break;
case R_CLIENT:
sendit(sock, "Client: name=%s FDport=%d\n", reshdr->name,
- res->res_client.FDport);
- break;
+ res->res_client.FDport);
+ break;
case R_MSGS:
sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
- if (res->res_msgs.mail_cmd)
+ if (res->res_msgs.mail_cmd)
sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
- if (res->res_msgs.operator_cmd)
+ if (res->res_msgs.operator_cmd)
sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
- break;
+ break;
default:
sendit(sock, "Unknown resource type %d\n", type);
}
switch (type) {
case R_DIRECTOR:
- if (res->res_dir.password) {
- free(res->res_dir.password);
- }
- if (res->res_dir.address) {
- free(res->res_dir.address);
- }
- break;
+ if (res->res_dir.password) {
+ free(res->res_dir.password);
+ }
+ if (res->res_dir.address) {
+ free(res->res_dir.address);
+ }
+ break;
case R_CLIENT:
- if (res->res_client.working_directory) {
- free(res->res_client.working_directory);
- }
- if (res->res_client.pid_directory) {
- free(res->res_client.pid_directory);
- }
- if (res->res_client.subsys_directory) {
- free(res->res_client.subsys_directory);
- }
- if (res->res_client.FDaddr) {
- free(res->res_client.FDaddr);
- }
- break;
+ if (res->res_client.working_directory) {
+ free(res->res_client.working_directory);
+ }
+ if (res->res_client.pid_directory) {
+ free(res->res_client.pid_directory);
+ }
+ if (res->res_client.subsys_directory) {
+ free(res->res_client.subsys_directory);
+ }
+ if (res->res_client.FDaddr) {
+ free(res->res_client.FDaddr);
+ }
+ break;
case R_MSGS:
- if (res->res_msgs.mail_cmd)
- free(res->res_msgs.mail_cmd);
- if (res->res_msgs.operator_cmd)
- free(res->res_msgs.operator_cmd);
- free_msgs_res((MSGS *)res); /* free message resource */
- res = NULL;
- break;
+ if (res->res_msgs.mail_cmd)
+ free(res->res_msgs.mail_cmd);
+ if (res->res_msgs.operator_cmd)
+ free(res->res_msgs.operator_cmd);
+ free_msgs_res((MSGS *)res); /* free message resource */
+ res = NULL;
+ break;
default:
printf("Unknown resource type %d\n", type);
}
*/
for (i=0; items[i].name; i++) {
if (items[i].flags & ITEM_REQUIRED) {
- if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
+ if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
Emsg2(M_ABORT, 0, _("%s item is required in %s resource, but not found.\n"),
- items[i].name, resources[rindex]);
- }
+ items[i].name, resources[rindex]);
+ }
}
}
*/
if (pass == 2) {
switch (type) {
- /* Resources not containing a resource */
- case R_MSGS:
- case R_DIRECTOR:
- break;
+ /* Resources not containing a resource */
+ case R_MSGS:
+ case R_DIRECTOR:
+ break;
- /* Resources containing another resource */
- case R_CLIENT:
- if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_dir.hdr.name)) == NULL) {
+ /* Resources containing another resource */
+ case R_CLIENT:
+ if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_dir.hdr.name)) == NULL) {
Emsg1(M_ABORT, 0, "Cannot find Client resource %s\n", res_all.res_dir.hdr.name);
- }
- res->res_client.messages = res_all.res_client.messages;
- break;
- default:
+ }
+ res->res_client.messages = res_all.res_client.messages;
+ break;
+ default:
Emsg1(M_ERROR, 0, _("Unknown resource type %d\n"), type);
- error = 1;
- break;
+ error = 1;
+ break;
}
/* Note, the resoure name was already saved during pass 1,
* so here, we can just release it.
*/
if (res_all.res_dir.hdr.name) {
- free(res_all.res_dir.hdr.name);
- res_all.res_dir.hdr.name = NULL;
+ free(res_all.res_dir.hdr.name);
+ res_all.res_dir.hdr.name = NULL;
}
if (res_all.res_dir.hdr.desc) {
- free(res_all.res_dir.hdr.desc);
- res_all.res_dir.hdr.desc = NULL;
+ free(res_all.res_dir.hdr.desc);
+ res_all.res_dir.hdr.desc = NULL;
}
return;
}
/* The following code is only executed on pass 1 */
switch (type) {
case R_DIRECTOR:
- size = sizeof(DIRRES);
- break;
+ size = sizeof(DIRRES);
+ break;
case R_CLIENT:
- size = sizeof(CLIENT);
- break;
+ size = sizeof(CLIENT);
+ break;
case R_MSGS:
- size = sizeof(MSGS);
- break;
+ size = sizeof(MSGS);
+ break;
default:
printf(_("Unknown resource type %d\n"), type);
- error = 1;
- size = 1;
- break;
+ error = 1;
+ size = 1;
+ break;
}
/* Common */
if (!error) {
res = (URES *)malloc(size);
memcpy(res, &res_all, size);
if (!resources[rindex].res_head) {
- resources[rindex].res_head = (RES *)res; /* store first entry */
+ resources[rindex].res_head = (RES *)res; /* store first entry */
} else {
- RES *next;
- /* Add new res to end of chain */
- for (next=resources[rindex].res_head; next->next; next=next->next)
- { }
- next->next = (RES *)res;
+ RES *next;
+ /* Add new res to end of chain */
+ for (next=resources[rindex].res_head; next->next; next=next->next)
+ { }
+ next->next = (RES *)res;
Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
- res->res_dir.hdr.name);
+ res->res_dir.hdr.name);
}
}
}
/*
* Resource codes -- they must be sequential for indexing
*/
-#define R_FIRST 1001
+#define R_FIRST 1001
-#define R_DIRECTOR 1001
-#define R_CLIENT 1002
-#define R_MSGS 1003
+#define R_DIRECTOR 1001
+#define R_CLIENT 1002
+#define R_MSGS 1003
-#define R_LAST R_MSGS
+#define R_LAST R_MSGS
/*
* Some resource attributes
*/
-#define R_NAME 1020
-#define R_ADDRESS 1021
-#define R_PASSWORD 1022
-#define R_TYPE 1023
+#define R_NAME 1020
+#define R_ADDRESS 1021
+#define R_PASSWORD 1022
+#define R_TYPE 1023
/* Definition of the contents of each Resource */
struct s_res_dir {
- RES hdr;
- char *password; /* Director password */
- char *address; /* Director address or zero */
- int enable_ssl; /* Use SSL for this Director */
+ RES hdr;
+ char *password; /* Director password */
+ char *address; /* Director address or zero */
+ int enable_ssl; /* Use SSL for this Director */
};
typedef struct s_res_dir DIRRES;
struct s_res_client {
- RES hdr;
- int FDport; /* where we listen for Directors */
- char *FDaddr; /* bind address */
+ RES hdr;
+ int FDport; /* where we listen for Directors */
+ char *FDaddr; /* bind address */
char *working_directory;
char *pid_directory;
char *subsys_directory;
- int require_ssl; /* Require SSL on all connections */
+ int require_ssl; /* Require SSL on all connections */
struct s_res_msgs *messages; /* daemon message handler */
int MaxConcurrentJobs;
+ utime_t heartbeat_interval; /* Interval to send heartbeats to Dir */
};
typedef struct s_res_client CLIENT;
* resource structure definitions.
*/
union u_res {
- struct s_res_dir res_dir;
- struct s_res_client res_client;
- struct s_res_msgs res_msgs;
+ struct s_res_dir res_dir;
+ struct s_res_client res_client;
+ struct s_res_msgs res_msgs;
RES hdr;
};
--- /dev/null
+/*
+ * Bacula File Daemon heartbeat routines
+ * Listens for heartbeats coming from the SD
+ * If configured, sends heartbeats to Dir
+ *
+ * Kern Sibbald, May MMIII
+ *
+ * Version $Id$
+ *
+ */
+/*
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "filed.h"
+
+/*
+ * Listen on the SD socket for heartbeat signals.
+ * Send heartbeats to the Director every HB_TIME
+ * seconds.
+ */
+static void *heartbeat_thread(void *arg)
+{
+ int32_t n;
+ JCR *jcr = (JCR *)arg;
+ BSOCK *sd, *dir;
+ time_t last_heartbeat = time(NULL);
+ time_t now;
+
+ pthread_detach(pthread_self());
+
+ /* Get our own local copy */
+ sd = dup_bsock(jcr->store_bsock);
+ dir = dup_bsock(jcr->dir_bsock);
+
+ jcr->duped_sd = sd;
+
+ /* Hang reading the socket to the SD, and every time we get
+ * a heartbeat, we simply send it on to the Director to
+ * keep him alive.
+ */
+ for ( ; !is_bnet_stop(sd); ) {
+ n = bnet_wait_data_intr(sd, 60);
+ if (me->heartbeat_interval) {
+ now = time(NULL);
+ if (now-last_heartbeat >= me->heartbeat_interval) {
+ bnet_sig(dir, BNET_HEARTBEAT);
+ last_heartbeat = now;
+ }
+ }
+ if (n == 1) { /* input waiting */
+ bnet_recv(sd); /* read it -- probably heartbeat from sd */
+ Dmsg1(000, "Got %d from SD\n", sd->msglen);
+ }
+ }
+ bnet_close(sd);
+ bnet_close(dir);
+ jcr->duped_sd = NULL;
+ return NULL;
+}
+
+/* Startup the heartbeat thread -- see above */
+void start_heartbeat_monitor(JCR *jcr)
+{
+ jcr->duped_sd = NULL;
+ pthread_create(&jcr->heartbeat_id, NULL, heartbeat_thread, (void *)jcr);
+}
+
+/* Terminate the heartbeat thread */
+void stop_heartbeat_monitor(JCR *jcr)
+{
+ /* Wait for heartbeat thread to start */
+ while (jcr->duped_sd == NULL) {
+ bmicrosleep(0, 50); /* avoid race */
+ }
+ jcr->duped_sd->timed_out = 1; /* set timed_out to terminate read */
+ jcr->duped_sd->terminated = 1; /* set to terminate read */
+
+ /* Wait for heartbeat thread to stop */
+ while (jcr->duped_sd) {
+ pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL); /* make heartbeat thread go away */
+ bmicrosleep(0, 20);
+ }
+}
extern int authenticate_storagedaemon(JCR *jcr);
extern int make_estimate(JCR *jcr);
+/* From heartbeat.c */
+void start_heartbeat_monitor(JCR *jcr);
+void stop_heartbeat_monitor(JCR *jcr);
return 1;
}
-#define HB_TIME (20*60) /* send a heatbeat once every 20 minutes while waiting */
-
+/*
+ * Wait for SysOp to mount a tape
+ */
static int wait_for_sysop(JCR *jcr, DEVICE *dev, int wait_sec)
{
struct timeval tv;
*/
gettimeofday(&tv, &tz);
timeout.tv_nsec = tv.tv_usec * 1000;
- timeout.tv_sec = tv.tv_sec + (wait_sec > HB_TIME ? HB_TIME: wait_sec);
+ if (me->heartbeat_interval) {
+ utime_t hb = me->heartbeat_interval;
+ timeout.tv_sec = tv.tv_sec + (wait_sec > hb ? hb : wait_sec);
+ } else {
+ timeout.tv_sec = tv.tv_sec + wait_sec;
+ }
P(dev->mutex);
dev_blocked = dev->dev_blocked;
for ( ; !job_canceled(jcr); ) {
int add_wait;
+ time_t now;
Dmsg1(190, "I'm going to sleep on device %s\n", dev->dev_name);
stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->mutex, &timeout);
+ now = time(NULL);
+
/* Note, this always triggers the first time. We want that. */
- time_t now = time(NULL);
- if (now - last_heartbeat >= HB_TIME) {
- /* send heartbeats */
- if (jcr->file_bsock) {
- bnet_sig(jcr->file_bsock, BNET_HEARTBEAT);
- }
- if (jcr->dir_bsock) {
- bnet_sig(jcr->dir_bsock, BNET_HEARTBEAT);
+ if (me->heartbeat_interval) {
+ if (now - last_heartbeat >= me->heartbeat_interval) {
+ /* send heartbeats */
+ if (jcr->file_bsock) {
+ bnet_sig(jcr->file_bsock, BNET_HEARTBEAT);
+ Dmsg0(000, "Send heartbeat to FD.\n");
+ }
+ if (jcr->dir_bsock) {
+ bnet_sig(jcr->dir_bsock, BNET_HEARTBEAT);
+ }
+ last_heartbeat = now;
}
- last_heartbeat = now;
}
/* Check if we blocked the device */
break;
}
add_wait = wait_sec - (now - start);
- if (add_wait > HB_TIME) {
- add_wait = HB_TIME;
+ if (me->heartbeat_interval && add_wait > me->heartbeat_interval) {
+ add_wait = me->heartbeat_interval;
}
} else { /* Oops someone else has it blocked now */
add_wait = 10; /* hang around until he releases it */
/* Global variables */
-static STORES *me;
+STORES *me;
+
+/* Local variables */
static DEVICE *dev = NULL;
static B_DB *db;
static JCR *bjcr; /* jcr for bscan */
#include "jcr.h"
#include "protos.h"
#ifdef HAVE_LIBZ
-#include <zlib.h> /* compression headers */
+#include <zlib.h> /* compression headers */
#else
#define uLongf uint32_t
#endif
#include "findlib/find.h"
-extern char errmsg[]; /* general error message */
+extern char errmsg[]; /* general error message */
+
+extern STORES *me; /* "Global" daemon resource */
#endif /* __STORED_H_ */
{"piddirectory", store_dir, ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0},
{"subsysdirectory", store_dir, ITEM(res_store.subsys_directory), 0, ITEM_REQUIRED, 0},
{"requiressl", store_yesno,ITEM(res_store.require_ssl), 1, ITEM_DEFAULT, 0},
- {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 3},
+ {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 5},
+ {"heartbeatinterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 20*60},
{NULL, NULL, 0, 0, 0, 0}
};
*/
-#define R_FIRST 3001
+#define R_FIRST 3001
-#define R_DIRECTOR 3001
-#define R_STORAGE 3002
-#define R_DEVICE 3003
-#define R_MSGS 3004
+#define R_DIRECTOR 3001
+#define R_STORAGE 3002
+#define R_DEVICE 3003
+#define R_MSGS 3004
-#define R_LAST R_MSGS
+#define R_LAST R_MSGS
-#define R_NAME 3020
-#define R_ADDRESS 3021
-#define R_PASSWORD 3022
-#define R_TYPE 3023
-#define R_BACKUP 3024
+#define R_NAME 3020
+#define R_ADDRESS 3021
+#define R_PASSWORD 3022
+#define R_TYPE 3023
+#define R_BACKUP 3024
/* Definition of the contents of each Resource */
struct s_res_dir {
- RES hdr;
+ RES hdr;
- char *password; /* Director password */
- char *address; /* Director IP address or zero */
- int enable_ssl; /* Use SSL with this Director */
+ char *password; /* Director password */
+ char *address; /* Director IP address or zero */
+ int enable_ssl; /* Use SSL with this Director */
};
typedef struct s_res_dir DIRRES;
/* Storage daemon "global" definitions */
struct s_res_store {
- RES hdr;
+ RES hdr;
- char *address; /* deprecated */
- char *SDaddr; /* bind address */
- int SDport; /* Where we listen for Directors */
+ char *address; /* deprecated */
+ char *SDaddr; /* bind address */
+ int SDport; /* Where we listen for Directors */
int SDDport; /* "Data" port where we listen for File daemons */
- char *working_directory; /* working directory for checkpoints */
+ char *working_directory; /* working directory for checkpoints */
char *pid_directory;
char *subsys_directory;
- int require_ssl; /* Require SSL on all connections */
+ int require_ssl; /* Require SSL on all connections */
uint32_t max_concurrent_jobs; /* maximum concurrent jobs to run */
struct s_res_msgs *messages; /* Daemon message handler */
+ utime_t heartbeat_interval; /* Interval to send hb to FD */
};
typedef struct s_res_store STORES;
/* Device specific definitions */
struct s_res_dev {
- RES hdr;
-
- char *media_type; /* User assigned media type */
- char *device_name; /* Archive device name */
- char *changer_name; /* Changer device name */
- char *changer_command; /* Changer command -- external program */
- int cap_bits; /* Capabilities of this device */
- uint32_t max_changer_wait; /* Changer timeout */
- uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
- uint32_t max_open_wait; /* maximum secs to wait for open */
- uint32_t max_open_vols; /* maximum simultaneous open volumes */
- uint32_t min_block_size; /* min block size */
- uint32_t max_block_size; /* max block size */
- uint32_t max_volume_jobs; /* max jobs to put on one volume */
- int64_t max_volume_files; /* max files to put on one volume */
- int64_t max_volume_size; /* max bytes to put on one volume */
- int64_t max_file_size; /* max file size in bytes */
- int64_t volume_capacity; /* advisory capacity */
- DEVICE *dev; /* Pointer to phyical dev -- set at runtime */
+ RES hdr;
+
+ char *media_type; /* User assigned media type */
+ char *device_name; /* Archive device name */
+ char *changer_name; /* Changer device name */
+ char *changer_command; /* Changer command -- external program */
+ int cap_bits; /* Capabilities of this device */
+ uint32_t max_changer_wait; /* Changer timeout */
+ uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
+ uint32_t max_open_wait; /* maximum secs to wait for open */
+ uint32_t max_open_vols; /* maximum simultaneous open volumes */
+ uint32_t min_block_size; /* min block size */
+ uint32_t max_block_size; /* max block size */
+ uint32_t max_volume_jobs; /* max jobs to put on one volume */
+ int64_t max_volume_files; /* max files to put on one volume */
+ int64_t max_volume_size; /* max bytes to put on one volume */
+ int64_t max_file_size; /* max file size in bytes */
+ int64_t volume_capacity; /* advisory capacity */
+ DEVICE *dev; /* Pointer to phyical dev -- set at runtime */
};
typedef struct s_res_dev DEVRES;
union u_res {
- struct s_res_dir res_dir;
- struct s_res_store res_store;
- struct s_res_dev res_dev;
- struct s_res_msgs res_msgs;
+ struct s_res_dir res_dir;
+ struct s_res_store res_store;
+ struct s_res_dev res_dev;
+ struct s_res_msgs res_msgs;
RES hdr;
};
typedef union u_res URES;