R_MSGS,
R_COUNTER,
R_CONSOLE,
- R_JOBDEFS
+ R_JOBDEFS,
+ R_FIRST = R_DIRECTOR,
+ R_LAST = R_JOBDEFS /* keep this updated */
};
-#define R_FIRST R_DIRECTOR
-#define R_LAST R_JOBDEFS
/*
* Some resource attributes
*/
-#define R_NAME 1020
-#define R_ADDRESS 1021
-#define R_PASSWORD 1022
-#define R_TYPE 1023
-#define R_BACKUP 1024
+enum {
+ R_NAME = 1020,
+ R_ADDRESS,
+ R_PASSWORD,
+ R_TYPE,
+ R_BACKUP
+};
/* Used for certain KeyWord tables */
-struct s_kw {
+struct s_kw {
char *name;
- int token;
+ int token;
};
/* Job Level keyword structure */
struct s_jl {
- char *level_name; /* level keyword */
- int level; /* level */
- int job_type; /* JobType permitting this level */
+ char *level_name; /* level keyword */
+ int level; /* level */
+ int job_type; /* JobType permitting this level */
};
/* Job Type keyword structure */
struct RUN;
/*
- * Director Resource
+ * Director Resource
*
*/
struct DIRRES {
- RES hdr;
- int DIRport; /* where we listen -- UA port server port */
- char *DIRaddr; /* bind address */
- char *password; /* Password for UA access */
- int enable_ssl; /* Use SSL for UA */
- char *query_file; /* SQL query file */
- char *working_directory; /* WorkingDirectory */
- char *pid_directory; /* PidDirectory */
- char *subsys_directory; /* SubsysDirectory */
- int require_ssl; /* Require SSL for all connections */
- MSGS *messages; /* Daemon message handler */
- uint32_t MaxConcurrentJobs; /* Max concurrent jobs for whole director */
- utime_t FDConnectTimeout; /* timeout for connect in seconds */
- utime_t SDConnectTimeout; /* timeout in seconds */
+ RES hdr;
+ int DIRport; /* where we listen -- UA port server port */
+ char *DIRaddr; /* bind address */
+ char *password; /* Password for UA access */
+ int enable_ssl; /* Use SSL for UA */
+ char *query_file; /* SQL query file */
+ char *working_directory; /* WorkingDirectory */
+ char *pid_directory; /* PidDirectory */
+ char *subsys_directory; /* SubsysDirectory */
+ int require_ssl; /* Require SSL for all connections */
+ MSGS *messages; /* Daemon message handler */
+ uint32_t MaxConcurrentJobs; /* Max concurrent jobs for whole director */
+ utime_t FDConnectTimeout; /* timeout for connect in seconds */
+ utime_t SDConnectTimeout; /* timeout in seconds */
};
Command_ACL,
FileSet_ACL,
Catalog_ACL,
- Num_ACL /* keep last */
+ Num_ACL /* keep last */
};
/*
* Console Resource
*/
struct CONRES {
- RES hdr;
- char *password; /* UA server password */
- int enable_ssl; /* Use SSL */
- alist *ACL_lists[Num_ACL]; /* pointers to ACLs */
+ RES hdr;
+ char *password; /* UA server password */
+ int enable_ssl; /* Use SSL */
+ alist *ACL_lists[Num_ACL]; /* pointers to ACLs */
};
*
*/
struct CAT {
- RES hdr;
+ RES hdr;
- int db_port; /* Port -- not yet implemented */
- char *db_address; /* host name for remote access */
- char *db_socket; /* Socket for local access */
+ int db_port; /* Port -- not yet implemented */
+ char *db_address; /* host name for remote access */
+ char *db_socket; /* Socket for local access */
char *db_password;
char *db_user;
char *db_name;
*
*/
struct CLIENT {
- RES hdr;
+ RES hdr;
- int FDport; /* Where File daemon listens */
- int AutoPrune; /* Do automatic pruning? */
- utime_t FileRetention; /* file retention period in seconds */
- utime_t JobRetention; /* job retention period in seconds */
+ int FDport; /* Where File daemon listens */
+ int AutoPrune; /* Do automatic pruning? */
+ utime_t FileRetention; /* file retention period in seconds */
+ utime_t JobRetention; /* job retention period in seconds */
char *address;
char *password;
- CAT *catalog; /* Catalog resource */
- uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
- uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
- int enable_ssl; /* Use SSL */
+ CAT *catalog; /* Catalog resource */
+ uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
+ uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
+ int enable_ssl; /* Use SSL */
};
/*
*
*/
struct STORE {
- RES hdr;
+ RES hdr;
- int SDport; /* port where Directors connect */
- int SDDport; /* data port for File daemon */
+ int SDport; /* port where Directors connect */
+ int SDDport; /* data port for File daemon */
char *address;
char *password;
char *media_type;
char *dev_name;
- int autochanger; /* set if autochanger */
- uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
- uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
- int enable_ssl; /* Use SSL */
+ int autochanger; /* set if autochanger */
+ uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
+ uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
+ int enable_ssl; /* Use SSL */
};
* Job Resource
*/
struct JOB {
- RES hdr;
-
- int JobType; /* job type (backup, verify, restore */
- int level; /* default backup/verify level */
- int Priority; /* Job priority */
- int RestoreJobId; /* What -- JobId to restore */
- char *RestoreWhere; /* Where on disk to restore -- directory */
- char *RestoreBootstrap; /* Bootstrap file */
- char *RunBeforeJob; /* Run program before Job */
- char *RunAfterJob; /* Run program after Job */
- char *RunAfterFailedJob; /* Run program after Job that errs */
- char *ClientRunBeforeJob; /* Run client program before Job */
- char *ClientRunAfterJob; /* Run client program after Job */
- char *WriteBootstrap; /* Where to write bootstrap Job updates */
- int replace; /* How (overwrite, ..) */
- utime_t MaxRunTime; /* max run time in seconds */
- utime_t MaxWaitTime; /* max blocking time in seconds */
- utime_t MaxStartDelay; /* max start delay in seconds */
- int PrefixLinks; /* prefix soft links with Where path */
- int PruneJobs; /* Force pruning of Jobs */
- int PruneFiles; /* Force pruning of Files */
- int PruneVolumes; /* Force pruning of Volumes */
- int SpoolAttributes; /* Set to spool attributes in SD */
- int spool_data; /* Set to spool data in SD */
- uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
- int RescheduleOnError; /* Set to reschedule on error */
- int RescheduleTimes; /* Number of times to reschedule job */
- utime_t RescheduleInterval; /* Reschedule interval */
- utime_t JobRetention; /* job retention period in seconds */
+ RES hdr;
+
+ int JobType; /* job type (backup, verify, restore */
+ int level; /* default backup/verify level */
+ int Priority; /* Job priority */
+ int RestoreJobId; /* What -- JobId to restore */
+ char *RestoreWhere; /* Where on disk to restore -- directory */
+ char *RestoreBootstrap; /* Bootstrap file */
+ char *RunBeforeJob; /* Run program before Job */
+ char *RunAfterJob; /* Run program after Job */
+ char *RunAfterFailedJob; /* Run program after Job that errs */
+ char *ClientRunBeforeJob; /* Run client program before Job */
+ char *ClientRunAfterJob; /* Run client program after Job */
+ char *WriteBootstrap; /* Where to write bootstrap Job updates */
+ int replace; /* How (overwrite, ..) */
+ utime_t MaxRunTime; /* max run time in seconds */
+ utime_t MaxWaitTime; /* max blocking time in seconds */
+ utime_t MaxStartDelay; /* max start delay in seconds */
+ int PrefixLinks; /* prefix soft links with Where path */
+ int PruneJobs; /* Force pruning of Jobs */
+ int PruneFiles; /* Force pruning of Files */
+ int PruneVolumes; /* Force pruning of Volumes */
+ int SpoolAttributes; /* Set to spool attributes in SD */
+ int spool_data; /* Set to spool data in SD */
+ uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
+ int RescheduleOnError; /* Set to reschedule on error */
+ int RescheduleTimes; /* Number of times to reschedule job */
+ utime_t RescheduleInterval; /* Reschedule interval */
+ utime_t JobRetention; /* job retention period in seconds */
- MSGS *messages; /* How and where to send messages */
- SCHED *schedule; /* When -- Automatic schedule */
- CLIENT *client; /* Who to backup */
- FILESET *fileset; /* What to backup -- Fileset */
- STORE *storage; /* Where is device -- Storage daemon */
- POOL *pool; /* Where is media -- Media Pool */
- POOL *full_pool; /* Pool for Full backups */
- POOL *inc_pool; /* Pool for Incremental backups */
- POOL *dif_pool; /* Pool for Differental backups */
- JOB *verify_job; /* Job name to verify */
- JOB *jobdefs; /* Job defaults */
- uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
+ MSGS *messages; /* How and where to send messages */
+ SCHED *schedule; /* When -- Automatic schedule */
+ CLIENT *client; /* Who to backup */
+ FILESET *fileset; /* What to backup -- Fileset */
+ STORE *storage; /* Where is device -- Storage daemon */
+ POOL *pool; /* Where is media -- Media Pool */
+ POOL *full_pool; /* Pool for Full backups */
+ POOL *inc_pool; /* Pool for Incremental backups */
+ POOL *dif_pool; /* Pool for Differental backups */
+ JOB *verify_job; /* Job name to verify */
+ JOB *jobdefs; /* Job defaults */
+ uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
};
#define MAX_FOPTS 30
/* File options structure */
struct FOPTS {
- char opts[MAX_FOPTS]; /* options string */
- alist match; /* match string(s) */
- alist base_list; /* list of base names */
+ char opts[MAX_FOPTS]; /* options string */
+ alist match; /* match string(s) */
+ alist base_list; /* list of base names */
};
/* This is either an include item or an exclude item */
struct INCEXE {
- FOPTS *current_opts; /* points to current options structure */
- FOPTS **opts_list; /* options list */
- int num_opts; /* number of options items */
- alist name_list; /* filename list -- holds char * */
+ FOPTS *current_opts; /* points to current options structure */
+ FOPTS **opts_list; /* options list */
+ int num_opts; /* number of options items */
+ alist name_list; /* filename list -- holds char * */
};
/*
*
*/
struct FILESET {
- RES hdr;
+ RES hdr;
- int new_include; /* Set if new include used */
- INCEXE **include_items; /* array of incexe structures */
- int num_includes; /* number in array */
+ int new_include; /* Set if new include used */
+ INCEXE **include_items; /* array of incexe structures */
+ int num_includes; /* number in array */
INCEXE **exclude_items;
int num_excludes;
- int have_MD5; /* set if MD5 initialized */
- struct MD5Context md5c; /* MD5 of include/exclude */
- char MD5[30]; /* base 64 representation of MD5 */
+ int have_MD5; /* set if MD5 initialized */
+ struct MD5Context md5c; /* MD5 of include/exclude */
+ char MD5[30]; /* base 64 representation of MD5 */
};
*
*/
struct SCHED {
- RES hdr;
+ RES hdr;
RUN *run;
};
* Counter Resource
*/
struct COUNTER {
- RES hdr;
-
- int32_t MinValue; /* Minimum value */
- int32_t MaxValue; /* Maximum value */
- int32_t CurrentValue; /* Current value */
- COUNTER *WrapCounter; /* Wrap counter name */
- CAT *Catalog; /* Where to store */
- bool created; /* Created in DB */
+ RES hdr;
+
+ int32_t MinValue; /* Minimum value */
+ int32_t MaxValue; /* Maximum value */
+ int32_t CurrentValue; /* Current value */
+ COUNTER *WrapCounter; /* Wrap counter name */
+ CAT *Catalog; /* Where to store */
+ bool created; /* Created in DB */
};
/*
*
*/
struct POOL {
- RES hdr;
-
- char *pool_type; /* Pool type */
- char *label_format; /* Label format string */
- char *cleaning_prefix; /* Cleaning label prefix */
- int use_catalog; /* maintain catalog for media */
- int catalog_files; /* maintain file entries in catalog */
- int use_volume_once; /* write on volume only once */
- int accept_any_volume; /* accept any volume */
- int purge_oldest_volume; /* purge oldest volume */
- int recycle_oldest_volume; /* attempt to recycle oldest volume */
- int recycle_current_volume; /* attempt recycle of current volume */
- uint32_t max_volumes; /* max number of volumes */
- utime_t VolRetention; /* volume retention period in seconds */
- utime_t VolUseDuration; /* duration volume can be used */
- uint32_t MaxVolJobs; /* Maximum jobs on the Volume */
- uint32_t MaxVolFiles; /* Maximum files on the Volume */
- uint64_t MaxVolBytes; /* Maximum bytes on the Volume */
- int AutoPrune; /* default for pool auto prune */
- int Recycle; /* default for media recycle yes/no */
+ RES hdr;
+
+ char *pool_type; /* Pool type */
+ char *label_format; /* Label format string */
+ char *cleaning_prefix; /* Cleaning label prefix */
+ int use_catalog; /* maintain catalog for media */
+ int catalog_files; /* maintain file entries in catalog */
+ int use_volume_once; /* write on volume only once */
+ int accept_any_volume; /* accept any volume */
+ int purge_oldest_volume; /* purge oldest volume */
+ int recycle_oldest_volume; /* attempt to recycle oldest volume */
+ int recycle_current_volume; /* attempt recycle of current volume */
+ uint32_t max_volumes; /* max number of volumes */
+ utime_t VolRetention; /* volume retention period in seconds */
+ utime_t VolUseDuration; /* duration volume can be used */
+ uint32_t MaxVolJobs; /* Maximum jobs on the Volume */
+ uint32_t MaxVolFiles; /* Maximum files on the Volume */
+ uint64_t MaxVolBytes; /* Maximum bytes on the Volume */
+ int AutoPrune; /* default for pool auto prune */
+ int Recycle; /* default for media recycle yes/no */
};
CONRES res_con;
CLIENT res_client;
STORE res_store;
- CAT res_cat;
- JOB res_job;
+ CAT res_cat;
+ JOB res_job;
FILESET res_fs;
SCHED res_sch;
POOL res_pool;
MSGS res_msgs;
COUNTER res_counter;
- RES hdr;
+ RES hdr;
};
/* Run structure contained in Schedule Resource */
struct RUN {
- RUN *next; /* points to next run record */
- int level; /* level override */
- int Priority; /* priority override */
+ RUN *next; /* points to next run record */
+ int level; /* level override */
+ int Priority; /* priority override */
int job_type;
- bool spool_data; /* Data spooling override */
- bool spool_data_set; /* Data spooling override given */
- POOL *pool; /* Pool override */
- POOL *full_pool; /* Pool override */
- POOL *inc_pool; /* Pool override */
- POOL *dif_pool; /* Pool override */
- STORE *storage; /* Storage override */
- MSGS *msgs; /* Messages override */
+ bool spool_data; /* Data spooling override */
+ bool spool_data_set; /* Data spooling override given */
+ POOL *pool; /* Pool override */
+ POOL *full_pool; /* Pool override */
+ POOL *inc_pool; /* Pool override */
+ POOL *dif_pool; /* Pool override */
+ STORE *storage; /* Storage override */
+ MSGS *msgs; /* Messages override */
char *since;
int level_no;
- int minute; /* minute to run job */
- time_t last_run; /* last time run */
- time_t next_run; /* next time to run */
+ int minute; /* minute to run job */
+ time_t last_run; /* last time run */
+ time_t next_run; /* next time to run */
char hour[nbytes_for_bits(24)]; /* bit set for each hour */
char mday[nbytes_for_bits(31)]; /* bit set for each day of month */
char month[nbytes_for_bits(12)]; /* bit set for each month */
*/
struct BSOCK {
- uint64_t read_seqno; /* read sequence number */
- uint32_t in_msg_no; /* input message number */
- uint32_t out_msg_no; /* output message number */
- int fd; /* socket file descriptor */
- int32_t msglen; /* message length */
- int b_errno; /* bsock errno */
- int port; /* desired port */
- volatile bool errors: 1; /* set if errors on socket */
+ uint64_t read_seqno; /* read sequence number */
+ uint32_t in_msg_no; /* input message number */
+ uint32_t out_msg_no; /* output message number */
+ int fd; /* socket file descriptor */
+ int32_t msglen; /* message length */
+ int b_errno; /* bsock errno */
+ int port; /* desired port */
+ volatile bool errors: 1; /* set if errors on socket */
volatile bool suppress_error_msgs: 1; /* set to suppress error messages */
- volatile bool timed_out: 1; /* timed out in read/write */
+ volatile bool timed_out: 1; /* timed out in read/write */
volatile bool terminated: 1; /* set when BNET_TERMINATE arrives */
- bool duped: 1; /* set if duped BSOCK */
- bool spool: 1; /* set for spooling */
+ bool duped: 1; /* set if duped BSOCK */
+ bool spool: 1; /* set for spooling */
volatile time_t timer_start; /* time started read/write */
- volatile time_t timeout; /* timeout BSOCK after this interval */
- POOLMEM *msg; /* message pool buffer */
- char *who; /* Name of daemon to which we are talking */
- char *host; /* Host name/IP */
- POOLMEM *errmsg; /* edited error message (to be implemented) */
- RES *res; /* Resource to which we are connected */
- BSOCK *next; /* next BSOCK if duped */
- FILE *spool_fd; /* spooling file */
- JCR *jcr; /* jcr or NULL for error msgs */
+ volatile time_t timeout; /* timeout BSOCK after this interval */
+ POOLMEM *msg; /* message pool buffer */
+ char *who; /* Name of daemon to which we are talking */
+ char *host; /* Host name/IP */
+ POOLMEM *errmsg; /* edited error message (to be implemented) */
+ RES *res; /* Resource to which we are connected */
+ BSOCK *next; /* next BSOCK if duped */
+ FILE *spool_fd; /* spooling file */
+ JCR *jcr; /* jcr or NULL for error msgs */
struct sockaddr_in client_addr; /* client's IP address */
-};
+};
/* Signal definitions for use in bnet_sig() */
enum {
- BNET_EOD = -1, /* End of data stream, new data may follow */
- BNET_EOD_POLL = -2, /* End of data and poll all in one */
- BNET_STATUS = -3, /* Send full status */
- BNET_TERMINATE = -4, /* Conversation terminated, doing close() */
+ BNET_EOD = -1, /* End of data stream, new data may follow */
+ BNET_EOD_POLL = -2, /* End of data and poll all in one */
+ BNET_STATUS = -3, /* Send full status */
+ BNET_TERMINATE = -4, /* Conversation terminated, doing close() */
BNET_POLL = -5, /* Poll request, I'm hanging on a read */
- BNET_HEARTBEAT = -6, /* Heartbeat Response requested */
- BNET_HB_RESPONSE = -7, /* Only response permited to HB */
- BNET_PROMPT = -8, /* Prompt for UA */
- BNET_BTIME = -9, /* Send UTC btime */
- BNET_BREAK = -10 /* Stop current command -- ctl-c */
+ BNET_HEARTBEAT = -6, /* Heartbeat Response requested */
+ BNET_HB_RESPONSE = -7, /* Only response permited to HB */
+ BNET_PROMPT = -8, /* Prompt for UA */
+ BNET_BTIME = -9, /* Send UTC btime */
+ BNET_BREAK = -10 /* Stop current command -- ctl-c */
};
-#define BNET_SETBUF_READ 1 /* Arg for bnet_set_buffer_size */
-#define BNET_SETBUF_WRITE 2 /* Arg for bnet_set_buffer_size */
+#define BNET_SETBUF_READ 1 /* Arg for bnet_set_buffer_size */
+#define BNET_SETBUF_WRITE 2 /* Arg for bnet_set_buffer_size */
/* Return status from bnet_recv() */
#define BNET_SIGNAL -1
#define BNET_ERROR -3
/* SSL enabling values */
-#define BNET_SSL_NONE 0 /* cannot do SSL */
-#define BNET_SSL_OK 1 /* can do, but not required on my end */
-#define BNET_SSL_REQUIRED 2 /* SSL is required */
+#define BNET_SSL_NONE 0 /* cannot do SSL */
+#define BNET_SSL_OK 1 /* can do, but not required on my end */
+#define BNET_SSL_REQUIRED 2 /* SSL is required */
/*
* This is the structure of the in memory BPKT
*/
typedef struct s_bpkt {
- char *id; /* String identifier or name of field */
- uint8_t type; /* field type */
- uint32_t len; /* field length for string, name, bytes */
- void *value; /* pointer to value */
+ char *id; /* String identifier or name of field */
+ uint8_t type; /* field type */
+ uint32_t len; /* field length for string, name, bytes */
+ void *value; /* pointer to value */
} BPKT;
/*
* These are the data types that can be sent.
* For all values other than string, the storage space
* is assumed to be allocated in the receiving packet.
- * For BP_STRING if the *value is non-zero, it is a
+ * For BP_STRING if the *value is non-zero, it is a
* pointer to a POOLMEM buffer, and the Memory Pool
* routines will be used to assure that the length is
* adequate. NOTE!!! This pointer will be changed
* does). If the pointer is NULL, a POOLMEM
* buffer will be allocated.
*/
-#define BP_EOF 0 /* end of file */
-#define BP_CHAR 1 /* Character */
-#define BP_INT32 1 /* 32 bit integer */
-#define BP_UINT32 3 /* Unsigned 32 bit integer */
-#define BP_INT64 4 /* 64 bit integer */
-#define BP_STRING 5 /* string */
-#define BP_NAME 6 /* Name string -- limited length */
-#define BP_BYTES 7 /* Binary bytes */
-#define BP_FLOAT32 8 /* 32 bit floating point */
-#define BP_FLOAT64 9 /* 64 bit floating point */
+#define BP_EOF 0 /* end of file */
+#define BP_CHAR 1 /* Character */
+#define BP_INT32 1 /* 32 bit integer */
+#define BP_UINT32 3 /* Unsigned 32 bit integer */
+#define BP_INT64 4 /* 64 bit integer */
+#define BP_STRING 5 /* string */
+#define BP_NAME 6 /* Name string -- limited length */
+#define BP_BYTES 7 /* Binary bytes */
+#define BP_FLOAT32 8 /* 32 bit floating point */
+#define BP_FLOAT64 9 /* 64 bit floating point */
}
}
-static void make_unique_spool_filename(JCR *jcr, POOLMEM **name, int fd)
-{
- Mmsg(name, "%s/%s.spool.%s.%d", working_directory, my_name,
- jcr->Job, fd);
-}
-
-int open_spool_file(JCR *jcr, BSOCK *bs)
-{
- POOLMEM *name = get_pool_memory(PM_MESSAGE);
-
- make_unique_spool_filename(jcr, &name, bs->fd);
- bs->spool_fd = fopen(mp_chr(name), "w+");
- if (!bs->spool_fd) {
- Jmsg(jcr, M_ERROR, 0, "fopen spool file %s failed: ERR=%s\n", name, strerror(errno));
- free_pool_memory(name);
- return 0;
- }
- free_pool_memory(name);
- return 1;
-}
-
-int close_spool_file(JCR *jcr, BSOCK *bs)
-{
- POOLMEM *name = get_pool_memory(PM_MESSAGE);
-
- make_unique_spool_filename(jcr, &name, bs->fd);
- fclose(bs->spool_fd);
- unlink(mp_chr(name));
- free_pool_memory(name);
- bs->spool_fd = NULL;
- bs->spool = 0;
- return 1;
-}
/*
* Create a unique filename for the mail command
struct JCR;
/* attr.c */
-ATTR *new_attr();
-void free_attr(ATTR *attr);
-int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr);
-void build_attr_output_fnames(JCR *jcr, ATTR *attr);
-void print_ls_output(JCR *jcr, ATTR *attr);
+ATTR *new_attr();
+void free_attr(ATTR *attr);
+int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr);
+void build_attr_output_fnames(JCR *jcr, ATTR *attr);
+void print_ls_output(JCR *jcr, ATTR *attr);
/* base64.c */
-void base64_init (void);
-int to_base64 (intmax_t value, char *where);
-int from_base64 (intmax_t *value, char *where);
-int bin_to_base64 (char *buf, char *bin, int len);
+void base64_init (void);
+int to_base64 (intmax_t value, char *where);
+int from_base64 (intmax_t *value, char *where);
+int bin_to_base64 (char *buf, char *bin, int len);
/* bsys.c */
-char *bstrncpy (char *dest, const char *src, int maxlen);
-char *bstrncat (char *dest, const char *src, int maxlen);
-void *b_malloc (const char *file, int line, size_t size);
+char *bstrncpy (char *dest, const char *src, int maxlen);
+char *bstrncat (char *dest, const char *src, int maxlen);
+void *b_malloc (const char *file, int line, size_t size);
#ifndef DEBUG
-void *bmalloc (size_t size);
+void *bmalloc (size_t size);
#endif
-void *brealloc (void *buf, size_t size);
-void *bcalloc (size_t size1, size_t size2);
-int bsnprintf (char *str, int32_t size, const char *format, ...);
-int bvsnprintf (char *str, int32_t size, const char *format, va_list ap);
-int pool_sprintf (char *pool_buf, const char *fmt, ...);
-void create_pid_file (char *dir, const char *progname, int port);
-int delete_pid_file (char *dir, const char *progname, int port);
-void drop (char *uid, char *gid);
-int bmicrosleep (time_t sec, long usec);
-char *bfgets (char *s, int size, FILE *fd);
-void make_unique_filename (POOLMEM **name, int Id, char *what);
+void *brealloc (void *buf, size_t size);
+void *bcalloc (size_t size1, size_t size2);
+int bsnprintf (char *str, int32_t size, const char *format, ...);
+int bvsnprintf (char *str, int32_t size, const char *format, va_list ap);
+int pool_sprintf (char *pool_buf, const char *fmt, ...);
+void create_pid_file (char *dir, const char *progname, int port);
+int delete_pid_file (char *dir, const char *progname, int port);
+void drop (char *uid, char *gid);
+int bmicrosleep (time_t sec, long usec);
+char *bfgets (char *s, int size, FILE *fd);
+void make_unique_filename (POOLMEM **name, int Id, char *what);
#ifndef HAVE_STRTOLL
-long long int strtoll (const char *ptr, char **endptr, int base);
+long long int strtoll (const char *ptr, char **endptr, int base);
#endif
void read_state_file(char *dir, const char *progname, int port);
/* bnet.c */
-int32_t bnet_recv (BSOCK *bsock);
-int bnet_send (BSOCK *bsock);
-int bnet_fsend (BSOCK *bs, const char *fmt, ...);
-int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
-int bnet_sig (BSOCK *bs, int sig);
-int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
-int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need);
-BSOCK * bnet_connect (JCR *jcr, int retry_interval,
- int max_retry_time, const char *name, char *host, char *service,
- int port, int verbose);
-void bnet_close (BSOCK *bsock);
-BSOCK * init_bsock (JCR *jcr, int sockfd, const char *who, char *ip,
- int port, struct sockaddr_in *client_addr);
-BSOCK * dup_bsock (BSOCK *bsock);
-void term_bsock (BSOCK *bsock);
-char * bnet_strerror (BSOCK *bsock);
-char * bnet_sig_to_ascii (BSOCK *bsock);
-int bnet_wait_data (BSOCK *bsock, int sec);
-int bnet_wait_data_intr (BSOCK *bsock, int sec);
-int bnet_despool_to_bsock (BSOCK *bsock);
-int is_bnet_stop (BSOCK *bsock);
-int is_bnet_error (BSOCK *bsock);
-void bnet_suppress_error_messages(BSOCK *bsock, int flag);
+int32_t bnet_recv (BSOCK *bsock);
+int bnet_send (BSOCK *bsock);
+int bnet_fsend (BSOCK *bs, const char *fmt, ...);
+int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
+int bnet_sig (BSOCK *bs, int sig);
+int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
+int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need);
+BSOCK * bnet_connect (JCR *jcr, int retry_interval,
+ int max_retry_time, const char *name, char *host, char *service,
+ int port, int verbose);
+void bnet_close (BSOCK *bsock);
+BSOCK * init_bsock (JCR *jcr, int sockfd, const char *who, char *ip,
+ int port, struct sockaddr_in *client_addr);
+BSOCK * dup_bsock (BSOCK *bsock);
+void term_bsock (BSOCK *bsock);
+char * bnet_strerror (BSOCK *bsock);
+char * bnet_sig_to_ascii (BSOCK *bsock);
+int bnet_wait_data (BSOCK *bsock, int sec);
+int bnet_wait_data_intr (BSOCK *bsock, int sec);
+int bnet_despool_to_bsock (BSOCK *bsock);
+int is_bnet_stop (BSOCK *bsock);
+int is_bnet_error (BSOCK *bsock);
+void bnet_suppress_error_messages(BSOCK *bsock, int flag);
/* bget_msg.c */
-int bget_msg(BSOCK *sock);
+int bget_msg(BSOCK *sock);
/* bpipe.c */
-BPIPE * open_bpipe(char *prog, int wait, const char *mode);
-int close_wpipe(BPIPE *bpipe);
-int close_bpipe(BPIPE *bpipe);
+BPIPE * open_bpipe(char *prog, int wait, const char *mode);
+int close_wpipe(BPIPE *bpipe);
+int close_bpipe(BPIPE *bpipe);
/* cram-md5.c */
int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need);
int cram_md5_auth(BSOCK *bs, char *password, int ssl_need);
void hmac_md5(uint8_t* text, int text_len, uint8_t* key,
- int key_len, uint8_t *hmac);
+ int key_len, uint8_t *hmac);
/* crc32.c */
uint32_t bcrc32(uint8_t *buf, int len);
/* daemon.c */
-void daemon_start ();
+void daemon_start ();
/* edit.c */
-uint64_t str_to_uint64(char *str);
-int64_t str_to_int64(char *str);
-char * edit_uint64_with_commas (uint64_t val, char *buf);
-char * add_commas (char *val, char *buf);
-char * edit_uint64 (uint64_t val, char *buf);
-int duration_to_utime (char *str, utime_t *value);
-int size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
-char *edit_utime (utime_t val, char *buf);
-int is_a_number (const char *num);
-int is_an_integer (const char *n);
-bool is_name_valid (char *name, POOLMEM **msg);
+uint64_t str_to_uint64(char *str);
+int64_t str_to_int64(char *str);
+char * edit_uint64_with_commas (uint64_t val, char *buf);
+char * add_commas (char *val, char *buf);
+char * edit_uint64 (uint64_t val, char *buf);
+int duration_to_utime (char *str, utime_t *value);
+int size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
+char *edit_utime (utime_t val, char *buf);
+int is_a_number (const char *num);
+int is_an_integer (const char *n);
+bool is_name_valid (char *name, POOLMEM **msg);
/* jcr.c (most definitions are in src/jcr.h) */
void init_last_jobs_list();
/* lex.c */
-LEX * lex_close_file (LEX *lf);
-LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
-int lex_get_char (LEX *lf);
-void lex_unget_char (LEX *lf);
-const char * lex_tok_to_str (int token);
-int lex_get_token (LEX *lf, int expect);
+LEX * lex_close_file (LEX *lf);
+LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
+int lex_get_char (LEX *lf);
+void lex_unget_char (LEX *lf);
+const char * lex_tok_to_str (int token);
+int lex_get_token (LEX *lf, int expect);
/* message.c */
-void my_name_is (int argc, char *argv[], const char *name);
-void init_msg (JCR *jcr, MSGS *msg);
-void term_msg (void);
-void close_msg (JCR *jcr);
-void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
-void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
-void Jmsg (JCR *jcr, int type, int level, const char *fmt, ...);
-void dispatch_message (JCR *jcr, int type, int level, char *buf);
-void init_console_msg (char *wd);
-void free_msgs_res (MSGS *msgs);
-int open_spool_file (JCR *jcr, BSOCK *bs);
-int close_spool_file (JCR *jcr, BSOCK *bs);
-void dequeue_messages (JCR *jcr);
-void set_trace (int trace_flag);
+void my_name_is (int argc, char *argv[], const char *name);
+void init_msg (JCR *jcr, MSGS *msg);
+void term_msg (void);
+void close_msg (JCR *jcr);
+void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
+void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
+void Jmsg (JCR *jcr, int type, int level, const char *fmt, ...);
+void dispatch_message (JCR *jcr, int type, int level, char *buf);
+void init_console_msg (char *wd);
+void free_msgs_res (MSGS *msgs);
+void dequeue_messages (JCR *jcr);
+void set_trace (int trace_flag);
/* bnet_server.c */
-void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq,
- void *handle_client_request(void *bsock));
-void bnet_stop_thread_server(pthread_t tid);
-void bnet_server (int port, void handle_client_request(BSOCK *bsock));
-int net_connect (int port);
-BSOCK * bnet_bind (int port);
-BSOCK * bnet_accept (BSOCK *bsock, char *who);
+void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq,
+ void *handle_client_request(void *bsock));
+void bnet_stop_thread_server(pthread_t tid);
+void bnet_server (int port, void handle_client_request(BSOCK *bsock));
+int net_connect (int port);
+BSOCK * bnet_bind (int port);
+BSOCK * bnet_accept (BSOCK *bsock, char *who);
/* idcache.c */
char *getuser(uid_t uid);
/* signal.c */
-void init_signals (void terminate(int sig));
-void init_stack_dump (void);
+void init_signals (void terminate(int sig));
+void init_stack_dump (void);
/* scan.c */
-void strip_trailing_junk (char *str);
-void strip_trailing_slashes (char *dir);
-bool skip_spaces (char **msg);
-bool skip_nonspaces (char **msg);
-int fstrsch (char *a, char *b);
-int parse_args(POOLMEM *cmd, POOLMEM **args, int *argc,
- char **argk, char **argv, int max_args);
-char *next_arg(char **s);
+void strip_trailing_junk (char *str);
+void strip_trailing_slashes (char *dir);
+bool skip_spaces (char **msg);
+bool skip_nonspaces (char **msg);
+int fstrsch (char *a, char *b);
+int parse_args(POOLMEM *cmd, POOLMEM **args, int *argc,
+ char **argk, char **argv, int max_args);
+char *next_arg(char **s);
/* util.c */
-int is_buf_zero (char *buf, int len);
-void lcase (char *str);
-void bash_spaces (char *str);
-void unbash_spaces (char *str);
-char * encode_time (time_t time, char *buf);
-char * encode_mode (mode_t mode, char *buf);
-int do_shell_expansion (char *name, int name_len);
-void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
-int pm_strcat (POOLMEM **pm, const char *str);
-int pm_strcpy (POOLMEM **pm, const char *str);
-int run_program (char *prog, int wait, POOLMEM *results);
-char * job_type_to_str (int type);
-char * job_status_to_str (int stat);
-char * job_level_to_str (int level);
-void make_session_key (char *key, char *seed, int mode);
-POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to);
-void set_working_directory(char *wd);
+int is_buf_zero (char *buf, int len);
+void lcase (char *str);
+void bash_spaces (char *str);
+void unbash_spaces (char *str);
+char * encode_time (time_t time, char *buf);
+char * encode_mode (mode_t mode, char *buf);
+int do_shell_expansion (char *name, int name_len);
+void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
+int pm_strcat (POOLMEM **pm, const char *str);
+int pm_strcpy (POOLMEM **pm, const char *str);
+int run_program (char *prog, int wait, POOLMEM *results);
+char * job_type_to_str (int type);
+char * job_status_to_str (int stat);
+char * job_level_to_str (int level);
+void make_session_key (char *key, char *seed, int mode);
+POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to);
+void set_working_directory(char *wd);
/* watchdog.c */
dcr->block = new_block(dev);
dcr->record = new_record();
dcr->spool_fd = -1;
+ dcr->max_spool_size = dev->device->max_spool_size;
return dcr;
}
*/
for ( ; !(dev->state & ST_OPENED); ) {
Dmsg1(120, "bstored: open vol=%s\n", jcr->VolumeName);
- if (open_dev(dev, dcr->VolumeName, READ_ONLY) < 0) {
+ if (open_dev(dev, dcr->VolumeName, OPEN_READ_ONLY) < 0) {
Jmsg(jcr, M_FATAL, 0, _("Open device %s volume %s failed, ERR=%s\n"),
dev_name(dev), dcr->VolumeName, strerror_dev(dev));
goto get_out;
stream == STREAM_UNIX_ATTRIBUTES_EX || stream == STREAM_SHA1_SIGNATURE) {
if (!jcr->no_attributes) {
if (are_attributes_spooled(jcr)) {
- jcr->dir_bsock->spool = 1;
+ jcr->dir_bsock->spool = true;
}
Dmsg0(200, "Send attributes.\n");
if (!dir_update_file_attributes(jcr, &rec)) {
+ jcr->dir_bsock->spool = false;
Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
bnet_strerror(jcr->dir_bsock));
ok = false;
- jcr->dir_bsock->spool = 0;
break;
}
- jcr->dir_bsock->spool = 0;
+ jcr->dir_bsock->spool = false;
}
}
}
}
/* For we must now acquire the device for writing */
lock_device(out_dev);
- if (open_dev(out_dev, out_jcr->VolumeName, READ_WRITE) < 0) {
+ if (open_dev(out_dev, out_jcr->VolumeName, OPEN_READ_WRITE) < 0) {
Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
unlock_device(out_dev);
exit(1);
return stat;
}
- lock_device(dev);
+ if (!dcr->dev_locked) {
+ lock_device(dev);
+ }
/*
* If a new volume has been mounted since our last write
Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
jcr->VolCatInfo.VolCatName, jcr->Job);
set_new_volume_parameters(jcr, dev);
- unlock_device(dev);
- return 0;
+ stat = 0;
+ goto bail_out;
}
if (dcr->NewVol) {
/* Note, setting a new volume also handles any pending new file */
stat = fixup_device_block_write_error(jcr, dev, block);
}
- unlock_device(dev);
+bail_out:
+ if (!dcr->dev_locked) {
+ unlock_device(dev);
+ }
return stat;
}
lock_device(dev);
if (!(dev->state & ST_OPENED)) {
Dmsg1(200, "Opening device %s\n", jcr->VolumeName);
- if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) {
+ if (open_dev(dev, jcr->VolumeName, OPEN_READ_WRITE) < 0) {
Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
unlock_device(dev);
free_block(block);
*
* dev.c -- low level operations on device (storage device)
*
- * Kern Sibbald
+ * Kern Sibbald, MM
*
* NOTE!!!! None of these routines are reentrant. You must
* use lock_device() and unlock_device() at a higher level,
* to include ST_EOT, which is ephimeral, and ST_WEOT, which is
* persistent. Lots of routines clear ST_EOT, but ST_WEOT is
* cleared only when the problem goes away. Now when ST_WEOT
- * is set all calls to write_dev() are handled as usual. However,
- * in write_block() instead of attempting to write the block to
- * the physical device, it is chained into a list of blocks written
- * after the EOT condition. In addition, all threads are blocked
- * from writing on the tape by calling lock(), and thread other
+ * is set all calls to write_block_to_device() call the fix_up
+ * routine. In addition, all threads are blocked
+ * from writing on the tape by calling lock_dev(), and thread other
* than the first thread to hit the EOT will block on a condition
* variable. The first thread to hit the EOT will continue to
* be able to read and write the tape (he sort of tunnels through
- * the locking mechanism -- see lock() for details).
+ * the locking mechanism -- see lock_dev() for details).
*
* Now presumably somewhere higher in the chain of command
* (device.c), someone will notice the EOT condition and
dev->max_open_wait = device->max_open_wait;
dev->max_open_vols = device->max_open_vols;
dev->vol_poll_interval = device->vol_poll_interval;
+ dev->max_spool_size = device->max_spool_size;
/* Sanity check */
if (dev->vol_poll_interval && dev->vol_poll_interval < 60) {
dev->vol_poll_interval = 60;
Mmsg1(&dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
+ if ((errstat = pthread_mutex_init(&dev->spool_mutex, NULL)) != 0) {
+ dev->dev_errno = errstat;
+ Mmsg1(&dev->errmsg, _("Unable to init mutex: ERR=%s\n"), strerror(errstat));
+ Emsg0(M_FATAL, 0, dev->errmsg);
+ }
dev->fd = -1;
dev->attached_dcrs = new dlist(dcr, &dcr->dev_link);
Dmsg2(29, "init_dev: tape=%d dev_name=%s\n", dev_is_tape(dev), dev->dev_name);
pthread_mutex_destroy(&dev->mutex);
pthread_cond_destroy(&dev->wait);
pthread_cond_destroy(&dev->wait_next_vol);
+ pthread_mutex_destroy(&dev->spool_mutex);
if (dev->attached_dcrs) {
delete dev->attached_dcrs;
dev->attached_dcrs = NULL;
#define give_back_device_lock(d, p) _give_back_device_lock(__FILE__, __LINE__, (d), (p))
/* Arguments to open_dev() */
-#define READ_WRITE 0
-#define READ_ONLY 1
-#define OPEN_READ_WRITE 0
-#define OPEN_READ_ONLY 1
-#define OPEN_WRITE_ONLY 2
+enum {
+ OPEN_READ_WRITE = 0,
+ OPEN_READ_ONLY,
+ OPEN_WRITE_ONLY
+};
/* Generic status bits returned from status_dev() */
#define BMT_TAPE (1<<0) /* is tape device */
#define ST_SHORT (1<<13) /* Short block read */
/* dev_blocked states (mutually exclusive) */
-#define BST_NOT_BLOCKED 0 /* not blocked */
-#define BST_UNMOUNTED 1 /* User unmounted device */
-#define BST_WAITING_FOR_SYSOP 2 /* Waiting for operator to mount tape */
-#define BST_DOING_ACQUIRE 3 /* Opening/validating/moving tape */
-#define BST_WRITING_LABEL 4 /* Labeling a tape */
-#define BST_UNMOUNTED_WAITING_FOR_SYSOP 5 /* Closed by user during mount request */
-#define BST_MOUNT 6 /* Mount request */
+enum {
+ BST_NOT_BLOCKED = 0, /* not blocked */
+ BST_UNMOUNTED, /* User unmounted device */
+ BST_WAITING_FOR_SYSOP, /* Waiting for operator to mount tape */
+ BST_DOING_ACQUIRE, /* Opening/validating/moving tape */
+ BST_WRITING_LABEL, /* Labeling a tape */
+ BST_UNMOUNTED_WAITING_FOR_SYSOP, /* Closed by user during mount request */
+ BST_MOUNT /* Mount request */
+};
/* Volume Catalog Information structure definition */
struct VOLUME_CAT_INFO {
typedef struct s_steal_lock {
- pthread_t no_wait_id; /* id of no wait thread */
- int dev_blocked; /* state */
- int dev_prev_blocked; /* previous blocked state */
+ pthread_t no_wait_id; /* id of no wait thread */
+ int dev_blocked; /* state */
+ int dev_prev_blocked; /* previous blocked state */
} bsteal_lock_t;
struct DEVRES; /* Device resource defined in stored_conf.h */
JCR *attached_jcrs; /* attached JCR list */
dlist *attached_dcrs; /* attached DCR list */
pthread_mutex_t mutex; /* access control */
+ pthread_mutex_t spool_mutex; /* mutex for updating spool_size */
pthread_cond_t wait; /* thread wait variable */
pthread_cond_t wait_next_vol; /* wait for tape to be mounted */
pthread_t no_wait_id; /* this thread must not wait */
uint64_t max_volume_size; /* max bytes to put on one volume */
uint64_t max_file_size; /* max file size to put in one file on volume */
uint64_t volume_capacity; /* advisory capacity */
+ uint64_t max_spool_size; /* maximum spool file size */
+ uint64_t spool_size; /* curren spool size */
uint32_t max_rewind_wait; /* max secs to allow for rewind */
uint32_t max_open_wait; /* max secs to allow for open */
uint32_t max_open_vols; /* max simultaneous open volumes */
DEV_RECORD *record; /* pointer to record */
bool spool_data; /* set to spool data */
bool spooling; /* set when actually spooling */
+ bool dev_locked; /* set if dev already locked */
int spool_fd; /* fd if spooling */
bool NewVol; /* set if new Volume mounted */
bool WroteVol; /* set if Volume written */
uint32_t StartFile; /* Start write file */
uint32_t StartBlock; /* Start write block */
uint32_t EndBlock; /* Ending block written */
+ uint64_t spool_size; /* Current spool size */
+ uint64_t max_spool_size; /* Max job spool size */
char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */
};
/* Ensure that the device is open -- autoload_device() closes it */
for ( ; !(dev->state & ST_OPENED); ) {
- if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) {
+ if (open_dev(dev, jcr->VolumeName, OPEN_READ_WRITE) < 0) {
bnet_fsend(dir, _("3910 Unable to open device %s. ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
goto bail_out;
case BST_UNMOUNTED_WAITING_FOR_SYSOP:
case BST_UNMOUNTED:
/* We freed the device, so reopen it and wake any waiting threads */
- if (open_dev(dev, NULL, READ_WRITE) < 0) {
+ if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
strerror_dev(dev));
break;
bnet_fsend(dir, _("3906 cannot mount non-tape.\n"));
break;
}
- if (open_dev(dev, NULL, READ_WRITE) < 0) {
+ if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
strerror_dev(dev));
break;
/* Ensure that the device is open -- autoload_device() closes it */
for ( ; !dev_state(dev, ST_OPENED); ) {
- if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) {
+ if (open_dev(dev, jcr->VolumeName, OPEN_READ_WRITE) < 0) {
bnet_fsend(dir, _("3910 Unable to open device \"%s\". ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
goto bail_out;
int mount_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block));
/* From spool.c */
-int begin_data_spool(JCR *jcr);
-int discard_data_spool(JCR *jcr);
-int commit_data_spool(JCR *jcr);
-bool are_attributes_spooled(JCR *jcr);
-int begin_attribute_spool(JCR *jcr);
-int discard_attribute_spool(JCR *jcr);
-int commit_attribute_spool(JCR *jcr);
-bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block);
+bool begin_data_spool (JCR *jcr);
+bool discard_data_spool (JCR *jcr);
+bool commit_data_spool (JCR *jcr);
+bool are_attributes_spooled (JCR *jcr);
+bool begin_attribute_spool (JCR *jcr);
+bool discard_attribute_spool (JCR *jcr);
+bool commit_attribute_spool (JCR *jcr);
+bool write_block_to_spool_file (DCR *dcr, DEV_BLOCK *block);
+bool open_spool_file (JCR *jcr, BSOCK *bs);
+bool close_spool_file (JCR *jcr, BSOCK *bs);
RB_OK
};
-int begin_data_spool(JCR *jcr)
+bool begin_data_spool(JCR *jcr)
{
- int stat = 1;
+ bool stat = true;
if (jcr->spool_data) {
Dmsg0(100, "Turning on data spooling\n");
jcr->dcr->spool_data = true;
return stat;
}
-int discard_data_spool(JCR *jcr)
+bool discard_data_spool(JCR *jcr)
{
if (jcr->dcr->spooling) {
Dmsg0(100, "Data spooling discarded\n");
return close_data_spool_file(jcr);
}
- return 1;
+ return true;
}
-int commit_data_spool(JCR *jcr)
+bool commit_data_spool(JCR *jcr)
{
bool stat;
if (jcr->dcr->spooling) {
if (!stat) {
Dmsg1(000, "Bad return from despool WroteVol=%d\n", jcr->dcr->WroteVol);
close_data_spool_file(jcr);
- return 0;
+ return false;
}
return close_data_spool_file(jcr);
}
- return 1;
+ return true;
}
static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name)
{
- Mmsg(name, "%s/%s.data.spool.%s.%s", working_directory, my_name,
- jcr->Job, jcr->device->hdr.name);
+ char *dir;
+ if (jcr->dcr->dev->device->spool_directory) {
+ dir = jcr->dcr->dev->device->spool_directory;
+ } else {
+ dir = working_directory;
+ }
+ Mmsg(name, "%s/%s.data.spool.%s.%s", dir, my_name, jcr->Job, jcr->device->hdr.name);
}
{
DEVICE *rdev;
DCR *rdcr;
- dcr->spooling = false;
bool ok = true;
DEV_BLOCK *block;
JCR *jcr = dcr->jcr;
int stat;
-// lock_device(dcr->dev);
+ dcr->spooling = false;
+ lock_device(dcr->dev);
+ dcr->dev_locked = true;
Dmsg0(100, "Despooling data\n");
/* Set up a dev structure to read */
rdev = (DEVICE *)malloc(sizeof(DEVICE));
strcpy(rdev->dev_name, "spool");
rdev->errmsg = get_pool_memory(PM_EMSG);
*rdev->errmsg = 0;
+ rdev->device = dcr->dev->device;
rdcr = new_dcr(NULL, rdev);
rdcr->spool_fd = dcr->spool_fd;
rdcr->jcr = jcr; /* set a valid jcr */
Dmsg1(000, "Bad return from ftruncate. ERR=%s\n", strerror(errno));
ok = false;
}
+
+ P(dcr->dev->spool_mutex);
+ dcr->dev->spool_size -= dcr->spool_size;
+ dcr->spool_size = 0; /* zap size in input dcr */
+ V(dcr->dev->spool_mutex);
+
free_memory(rdev->dev_name);
free_pool_memory(rdev->errmsg);
free(rdev);
rdcr->jcr = NULL;
free_dcr(rdcr);
-// unlock_device(dcr->dev);
+ unlock_device(dcr->dev);
+ dcr->dev_locked = false;
return ok;
}
bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block)
{
ssize_t stat = 0;
- uint32_t wlen; /* length to write */
+ uint32_t wlen, hlen; /* length to write */
int retry = 0;
spool_hdr hdr;
+ bool despool = false;
ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf)));
-
+ hlen = sizeof(hdr);
+ wlen = block->binbuf;
+ P(dcr->dev->spool_mutex);
+ dcr->spool_size += hlen + wlen;
+ dcr->dev->spool_size += hlen + wlen;
+ if ((dcr->max_spool_size > 0 && dcr->spool_size >= dcr->max_spool_size) ||
+ (dcr->dev->spool_size > 0 && dcr->dev->spool_size >= dcr->dev->max_spool_size)) {
+ despool = true;
+ }
+ V(dcr->dev->spool_mutex);
+ if (despool) {
+ if (!despool_data(dcr)) {
+ return false;
+ }
+ P(dcr->dev->spool_mutex);
+ dcr->spool_size += hlen + wlen;
+ dcr->dev->spool_size += hlen + wlen;
+ V(dcr->dev->spool_mutex);
+ }
if (block->binbuf <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */
Dmsg0(100, "return write_block_to_dev no data to write\n");
return true;
hdr.FirstIndex = block->FirstIndex;
hdr.LastIndex = block->LastIndex;
hdr.len = block->binbuf;
- wlen = sizeof(hdr);
write_hdr_again:
- stat = write(dcr->spool_fd, (char*)&hdr, (size_t)wlen);
- if (stat != (ssize_t)wlen) {
+ stat = write(dcr->spool_fd, (char*)&hdr, (size_t)hlen);
+ if (stat != (ssize_t)hlen) {
if (!despool_data(dcr)) {
return false;
}
}
- wlen = block->binbuf;
Dmsg2(300, "Wrote block FI=%d LI=%d\n", block->FirstIndex, block->LastIndex);
write_again:
stat = write(dcr->spool_fd, block->buf, (size_t)wlen);
goto write_again;
}
+
empty_block(block);
return true;
}
-
bool are_attributes_spooled(JCR *jcr)
{
return jcr->spool_attributes && jcr->dir_bsock->spool_fd;
}
-int begin_attribute_spool(JCR *jcr)
+/*
+ * Create spool file for attributes.
+ * This is done by "attaching" to the bsock, and when
+ * it is called, the output is written to a file.
+ * The actual spooling is turned on and off in
+ * append.c only during writing of the attributes.
+ */
+bool begin_attribute_spool(JCR *jcr)
{
if (!jcr->no_attributes && jcr->spool_attributes) {
return open_spool_file(jcr, jcr->dir_bsock);
}
- return 1;
+ return true;
}
-int discard_attribute_spool(JCR *jcr)
+bool discard_attribute_spool(JCR *jcr)
{
if (are_attributes_spooled(jcr)) {
return close_spool_file(jcr, jcr->dir_bsock);
}
- return 1;
+ return true;
}
-int commit_attribute_spool(JCR *jcr)
+bool commit_attribute_spool(JCR *jcr)
{
if (are_attributes_spooled(jcr)) {
bnet_despool_to_bsock(jcr->dir_bsock);
return close_spool_file(jcr, jcr->dir_bsock);
}
- return 1;
+ return true;
+}
+
+static void make_unique_spool_filename(JCR *jcr, POOLMEM **name, int fd)
+{
+ Mmsg(name, "%s/%s.spool.%s.%d", working_directory, my_name,
+ jcr->Job, fd);
+}
+
+bool open_spool_file(JCR *jcr, BSOCK *bs)
+{
+ POOLMEM *name = get_pool_memory(PM_MESSAGE);
+
+ make_unique_spool_filename(jcr, &name, bs->fd);
+ bs->spool_fd = fopen(mp_chr(name), "w+");
+ if (!bs->spool_fd) {
+ Jmsg(jcr, M_ERROR, 0, "fopen spool file %s failed: ERR=%s\n", name, strerror(errno));
+ free_pool_memory(name);
+ return false;
+ }
+ free_pool_memory(name);
+ return true;
+}
+
+bool close_spool_file(JCR *jcr, BSOCK *bs)
+{
+ POOLMEM *name = get_pool_memory(PM_MESSAGE);
+
+ make_unique_spool_filename(jcr, &name, bs->fd);
+ fclose(bs->spool_fd);
+ unlink(mp_chr(name));
+ free_pool_memory(name);
+ bs->spool_fd = NULL;
+ bs->spool = false;
+ return true;
}
{"maximumvolumesize", store_size, ITEM(res_dev.max_volume_size), 0, 0, 0},
{"maximumfilesize", store_size, ITEM(res_dev.max_file_size), 0, ITEM_DEFAULT, 1000000000},
{"volumecapacity", store_size, ITEM(res_dev.volume_capacity), 0, 0, 0},
+ {"spooldirectory", store_dir, ITEM(res_dev.spool_directory), 0, 0, 0},
+ {"maximumspoolsize", store_size, ITEM(res_dev.max_spool_size), 0, 0, 0},
+ {"maximumjobspoolsize", store_size, ITEM(res_dev.max_job_spool_size), 0, 0, 0},
{NULL, NULL, 0, 0, 0, 0}
};
{"storage", store_items, R_STORAGE, NULL},
{"device", dev_items, R_DEVICE, NULL},
{"messages", msgs_items, R_MSGS, NULL},
- {NULL, NULL, 0, NULL}
+ {NULL, NULL, 0, NULL}
};
return;
}
sendit(sock, "dump_resource type=%d\n", type);
- if (type < 0) { /* no recursion */
+ if (type < 0) { /* no recursion */
type = - type;
recurse = 0;
}
break;
case R_STORAGE:
sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
- res->res_store.hdr.name, NPRT(res->res_store.SDaddr),
- res->res_store.SDport, res->res_store.SDDport,
- edit_utime(res->res_store.heartbeat_interval, buf));
+ res->res_store.hdr.name, NPRT(res->res_store.SDaddr),
+ res->res_store.SDport, res->res_store.SDDport,
+ edit_utime(res->res_store.heartbeat_interval, buf));
break;
case R_DEVICE:
sendit(sock, "Device: name=%s MediaType=%s Device=%s\n",
- res->res_dev.hdr.name,
- res->res_dev.media_type, res->res_dev.device_name);
+ res->res_dev.hdr.name,
+ res->res_dev.media_type, res->res_dev.device_name);
sendit(sock, " rew_wait=%d min_bs=%d max_bs=%d\n",
- res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
- res->res_dev.max_block_size);
+ res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
+ res->res_dev.max_block_size);
sendit(sock, " max_jobs=%d max_files=%" lld " max_size=%" lld "\n",
- res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
- res->res_dev.max_volume_size);
+ res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
+ res->res_dev.max_volume_size);
sendit(sock, " max_file_size=%" lld " capacity=%" lld "\n",
- res->res_dev.max_file_size, res->res_dev.volume_capacity);
+ res->res_dev.max_file_size, res->res_dev.volume_capacity);
+ sendit(sock, " spool_directory=%s\n", 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);
strcpy(buf, " ");
if (res->res_dev.cap_bits & CAP_EOF) {
bstrncat(buf, "CAP_EOF ", sizeof(buf));
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_STORAGE:
- if (res->res_store.address) { /* ***FIXME*** deprecated */
- free(res->res_store.address);
- }
- if (res->res_store.SDaddr) {
- free(res->res_store.SDaddr);
- }
- if (res->res_store.working_directory) {
- free(res->res_store.working_directory);
- }
- if (res->res_store.pid_directory) {
- free(res->res_store.pid_directory);
- }
- if (res->res_store.subsys_directory) {
- free(res->res_store.subsys_directory);
- }
- break;
+ if (res->res_store.address) { /* ***FIXME*** deprecated */
+ free(res->res_store.address);
+ }
+ if (res->res_store.SDaddr) {
+ free(res->res_store.SDaddr);
+ }
+ if (res->res_store.working_directory) {
+ free(res->res_store.working_directory);
+ }
+ if (res->res_store.pid_directory) {
+ free(res->res_store.pid_directory);
+ }
+ if (res->res_store.subsys_directory) {
+ free(res->res_store.subsys_directory);
+ }
+ break;
case R_DEVICE:
- if (res->res_dev.media_type) {
- free(res->res_dev.media_type);
- }
- if (res->res_dev.device_name) {
- free(res->res_dev.device_name);
- }
- if (res->res_dev.changer_name) {
- free(res->res_dev.changer_name);
- }
- if (res->res_dev.changer_command) {
- free(res->res_dev.changer_command);
- }
- break;
+ if (res->res_dev.media_type) {
+ free(res->res_dev.media_type);
+ }
+ if (res->res_dev.device_name) {
+ free(res->res_dev.device_name);
+ }
+ if (res->res_dev.changer_name) {
+ free(res->res_dev.changer_name);
+ }
+ if (res->res_dev.changer_command) {
+ free(res->res_dev.changer_command);
+ }
+ if (res->res_dev.spool_directory) {
+ free(res->res_dev.spool_directory);
+ }
+ 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:
Dmsg1(0, "Unknown resource type %d\n", type);
- break;
+ break;
}
/* Common stuff again -- free the resource, recurse to next one */
if (res) {
*/
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 this triggers, take a look at lib/parse_conf.h */
if (i >= MAX_RES_ITEMS) {
*/
if (pass == 2) {
switch (type) {
- /* Resources not containing a resource */
- case R_DIRECTOR:
- case R_DEVICE:
- case R_MSGS:
- break;
-
- /* Resources containing a resource */
- case R_STORAGE:
- if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
+ /* Resources not containing a resource */
+ case R_DIRECTOR:
+ case R_DEVICE:
+ case R_MSGS:
+ break;
+
+ /* Resources containing a resource */
+ case R_STORAGE:
+ if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
Emsg1(M_ABORT, 0, "Cannot find Storage resource %s\n", res_all.res_dir.hdr.name);
- }
- res->res_store.messages = res_all.res_store.messages;
- break;
- default:
+ }
+ res->res_store.messages = res_all.res_store.messages;
+ break;
+ default:
printf("Unknown resource type %d\n", type);
- error = 1;
- break;
+ error = 1;
+ break;
}
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_STORAGE:
- size = sizeof(STORES);
- break;
+ size = sizeof(STORES);
+ break;
case R_DEVICE:
- size = sizeof(DEVRES);
- break;
+ size = sizeof(DEVRES);
+ 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) {
- if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
- Emsg2(M_ERROR_TERM, 0,
+ RES *next;
+ /* Add new res to end of chain */
+ for (next=resources[rindex].res_head; next->next; next=next->next) {
+ if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
+ Emsg2(M_ERROR_TERM, 0,
_("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
- resources[rindex].name, res->res_dir.hdr.name);
- }
- }
- next->next = (RES *)res;
+ resources[rindex].name, res->res_dir.hdr.name);
+ }
+ }
+ 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);
}
}
}
*/
-#define R_FIRST 3001
-
-#define R_DIRECTOR 3001
-#define R_STORAGE 3002
-#define R_DEVICE 3003
-#define R_MSGS 3004
-
-#define R_LAST R_MSGS
-
+enum {
+ R_DIRECTOR = 3001,
+ R_STORAGE,
+ R_DEVICE,
+ R_MSGS,
+ R_FIRST = R_DIRECTOR,
+ R_LAST = R_MSGS /* keep this updated */
+};
-#define R_NAME 3020
-#define R_ADDRESS 3021
-#define R_PASSWORD 3022
-#define R_TYPE 3023
-#define R_BACKUP 3024
+enum {
+ R_NAME = 3020,
+ R_ADDRESS,
+ R_PASSWORD,
+ R_TYPE,
+ R_BACKUP
+};
/* Definition of the contents of each Resource */
struct DIRRES {
char *device_name; /* Archive device name */
char *changer_name; /* Changer device name */
char *changer_command; /* Changer command -- external program */
+ char *spool_directory; /* Spool file directory */
uint32_t cap_bits; /* Capabilities of this device */
uint32_t max_changer_wait; /* Changer timeout */
uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
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 */
+ int64_t max_spool_size; /* Max spool size for all jobs */
+ int64_t max_job_spool_size; /* Max spool size for any single job */
DEVICE *dev; /* Pointer to phyical dev -- set at runtime */
};
#undef VERSION
#define VERSION "1.33.4"
#define VSTRING "1"
-#define BDATE "09 Mar 2004"
-#define LSMDATE "09Mar04"
+#define BDATE "10 Mar 2004"
+#define LSMDATE "10Mar04"
/* Debug flags */
#undef DEBUG