*/
/* 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);
/* bmisc.c */
-char *bstrncpy (char *dest, const char *src, int maxlen);
-char *bstrncat (char *dest, const char *src, int maxlen);
-void *b_malloc (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 (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, size_t size, const char *format, ...);
-int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
-int pool_sprintf (char *pool_buf, char *fmt, ...);
-void create_pid_file (char *dir, char *progname, int port);
-int delete_pid_file (char *dir, char *progname, int port);
+void *brealloc (void *buf, size_t size);
+void *bcalloc (size_t size1, size_t size2);
+int bsnprintf (char *str, size_t size, const char *format, ...);
+int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
+int pool_sprintf (char *pool_buf, char *fmt, ...);
+void create_pid_file (char *dir, char *progname, int port);
+int delete_pid_file (char *dir, char *progname, int port);
/* bnet.c */
-int32_t bnet_recv (BSOCK *bsock);
-int bnet_send (BSOCK *bsock);
-int bnet_fsend (BSOCK *bs, char *fmt, ...);
-int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
-int bnet_sig (BSOCK *bs, int sig);
-BSOCK * bnet_connect (void *jcr, int retry_interval,
- int max_retry_time, char *name, char *host, char *service,
- int port, int verbose);
-int bnet_wait_data (BSOCK *bsock, int sec);
-void bnet_close (BSOCK *bsock);
-BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port);
-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_despool (BSOCK *bsock);
-int is_bnet_stop (BSOCK *bsock);
-int is_bnet_error (BSOCK *bsock);
+int32_t bnet_recv (BSOCK *bsock);
+int bnet_send (BSOCK *bsock);
+int bnet_fsend (BSOCK *bs, char *fmt, ...);
+int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
+int bnet_sig (BSOCK *bs, int sig);
+BSOCK * bnet_connect (void *jcr, int retry_interval,
+ int max_retry_time, char *name, char *host, char *service,
+ int port, int verbose);
+int bnet_wait_data (BSOCK *bsock, int sec);
+void bnet_close (BSOCK *bsock);
+BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port);
+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_despool (BSOCK *bsock);
+int is_bnet_stop (BSOCK *bsock);
+int is_bnet_error (BSOCK *bsock);
/* cram-md5.c */
int cram_md5_get_auth(BSOCK *bs, char *password);
int cram_md5_auth(BSOCK *bs, char *password);
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);
+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);
/* 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);
-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);
+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[], char *name);
-void init_msg (void *jcr, MSGS *msg);
-void term_msg (void);
-void close_msg (void *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 (void *jcr, int type, int level, char *fmt, ...);
-void dispatch_message (void *jcr, int type, int level, char *buf);
-void init_console_msg (char *wd);
-void free_msgs_res (MSGS *msgs);
-int open_spool_file (void *jcr, BSOCK *bs);
-int close_spool_file (void *vjcr, BSOCK *bs);
+void my_name_is (int argc, char *argv[], char *name);
+void init_msg (void *jcr, MSGS *msg);
+void term_msg (void);
+void close_msg (void *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 (void *jcr, int type, int level, char *fmt, ...);
+void dispatch_message (void *jcr, int type, int level, char *buf);
+void init_console_msg (char *wd);
+void free_msgs_res (MSGS *msgs);
+int open_spool_file (void *jcr, BSOCK *bs);
+int close_spool_file (void *vjcr, BSOCK *bs);
/* 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_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_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);
/* 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);
/* util.c */
-void lcase (char *str);
-void bash_spaces (char *str);
-void unbash_spaces (char *str);
-void strip_trailing_junk (char *str);
-void strip_trailing_slashes (char *dir);
-int skip_spaces (char **msg);
-int skip_nonspaces (char **msg);
-int fstrsch (char *a, char *b);
-char * encode_time (time_t time, char *buf);
-char * encode_mode (mode_t mode, char *buf);
-int do_shell_expansion (char *name);
-int is_buf_zero (char *buf, int len);
-void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
-void pm_strcat (POOLMEM **pm, char *str);
-void pm_strcpy (POOLMEM **pm, 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 makeSessionKey (char *key, char *seed, int mode);
-BPIPE * open_bpipe(char *prog, int wait, char *mode);
-int close_wpipe(BPIPE *bpipe);
-int close_bpipe(BPIPE *bpipe);
+void lcase (char *str);
+void bash_spaces (char *str);
+void unbash_spaces (char *str);
+void strip_trailing_junk (char *str);
+void strip_trailing_slashes (char *dir);
+int skip_spaces (char **msg);
+int skip_nonspaces (char **msg);
+int fstrsch (char *a, char *b);
+char * encode_time (time_t time, char *buf);
+char * encode_mode (mode_t mode, char *buf);
+int do_shell_expansion (char *name);
+int is_buf_zero (char *buf, int len);
+void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
+void pm_strcat (POOLMEM **pm, char *str);
+void pm_strcpy (POOLMEM **pm, 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 makeSessionKey (char *key, char *seed, int mode);
+BPIPE * open_bpipe(char *prog, int wait, char *mode);
+int close_wpipe(BPIPE *bpipe);
+int close_bpipe(BPIPE *bpipe);
/* watchdog.c */
int start_watchdog(void);
int stop_watchdog(void);
+void stop_child_timer(btimer_id wid);
+btimer_t *start_child_timer(pid_t pid, uint32_t wait);
#define SLEEP_TIME 30 /* examine things every 30 seconds */
/* Forward referenced functions */
-static void *watchdog_thread(void *arg);
+static void *btimer_thread(void *arg);
/* Static globals */
static pthread_mutex_t mutex;
static pthread_cond_t timer;
static int quit;
+static btimer_t *child_chain = NULL;
/*
return stat;
}
quit = FALSE;
- if ((stat = pthread_create(&wdid, NULL, watchdog_thread, (void *)NULL)) != 0) {
+ if ((stat = pthread_create(&wdid, NULL, btimer_thread, (void *)NULL)) != 0) {
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&timer);
return stat;
{
int stat;
- if ((stat = pthread_mutex_lock(&mutex)) != 0) {
- return stat;
- }
+ P(mutex);
quit = TRUE;
if ((stat = pthread_cond_signal(&timer)) != 0) {
- pthread_mutex_unlock(&mutex);
- return stat;
- }
- if ((stat = pthread_mutex_unlock(&mutex)) != 0) {
+ V(mutex);
return stat;
}
+ V(mutex);
return 0;
}
/*
* This is the actual watchdog thread.
*/
-static void *watchdog_thread(void *arg)
+static void *btimer_thread(void *arg)
{
struct timespec timeout;
int stat;
JCR *jcr;
BSOCK *fd;
+ btimer_t *wid;
Dmsg0(200, "Start watchdog thread\n");
pthread_detach(pthread_self());
- if ((stat = pthread_mutex_lock(&mutex)) != 0) {
- return NULL;
- }
-
+ P(mutex);
for ( ;!quit; ) {
struct timeval tv;
struct timezone tz;
- time_t timer_start;
+ time_t timer_start, now;
Dmsg0(200, "Top of for loop\n");
timeout.tv_sec = tv.tv_sec + SLEEP_TIME;
Dmsg1(200, "pthread_cond_timedwait sec=%d\n", timeout.tv_sec);
+ /* Note, this unlocks mutex during the sleep */
stat = pthread_cond_timedwait(&timer, &mutex, &timeout);
Dmsg1(200, "pthread_cond_timedwait stat=%d\n", stat);
+
+ now = time(NULL);
+
+ /* Walk child chain killing off any process overdue */
+ for (wid = child_chain; wid; wid=wid->next) {
+ int killed = FALSE;
+ /* First ask him politely to go away */
+ if (!wid->killed && now > (wid->start_time + wid->wait)) {
+// Dmsg1(000, "Watchdog sigterm pid=%d\n", wid->pid);
+ kill(wid->pid, SIGTERM);
+ killed = TRUE;
+ }
+ /* If we asked somone to die, wait 3 seconds and slam him */
+ if (killed) {
+ btimer_t *wid1;
+ sleep(3);
+ for (wid1 = child_chain; wid1; wid1=wid1->next) {
+ if (!wid1->killed && now > (wid1->start_time + wid1->wait)) {
+ kill(wid1->pid, SIGKILL);
+// Dmsg1(000, "Watchdog killed pid=%d\n", wid->pid);
+ wid1->killed = TRUE;
+ }
+ }
+ }
+ }
} /* end of big for loop */
- pthread_mutex_unlock(&mutex); /* for good form */
+ V(mutex);
Dmsg0(200, "End watchdog\n");
return NULL;
}
+
+/*
+ * Start a timer on a child process of pid, kill it after wait seconds.
+ * NOTE! Granularity is SLEEP_TIME (i.e. 30 seconds)
+ *
+ * Returns: btimer_id (pointer to btimer_t struct) on success
+ * NULL on failure
+ */
+btimer_id start_child_timer(pid_t pid, uint32_t wait)
+{
+ btimer_id wid = (btimer_id)malloc(sizeof(btimer_t));
+
+ P(mutex);
+ /* Chain it into child_chain as the first item */
+ wid->prev = NULL;
+ wid->next = child_chain;
+ if (child_chain) {
+ child_chain->prev = wid;
+ }
+ child_chain = wid;
+ wid->start_time = time(NULL);
+ wid->wait = wait;
+ wid->pid = pid;
+ wid->killed = FALSE;
+ Dmsg2(200, "Start child timer 0x%x for %d secs.\n", wid, wait);
+ V(mutex);
+ return wid;
+}
+
+/*
+ * Stop child timer
+ */
+void stop_child_timer(btimer_id wid)
+{
+ if (wid == NULL) {
+ Emsg0(M_ABORT, 0, _("NULL btimer_id.\n"));
+ }
+ P(mutex);
+ /* Remove wid from child_chain */
+ if (!wid->prev) { /* if no prev */
+ child_chain = wid->next; /* set new head */
+ } else {
+ wid->prev->next = wid->next; /* update prev */
+ }
+ if (wid->next) {
+ wid->next->prev = wid->prev; /* unlink it */
+ }
+ V(mutex);
+ Dmsg2(200, "Stop child timer 0x%x for %d secs.\n", wid, wid->wait);
+ free(wid);
+}
*/
static void testcmd()
{
- Pmsg0(0, "Append files test.\n\n\
-I'm going to write one record in file 0,\n\
- two records in file 1,\n\
- and three records in file 2\n\n");
+ DEV_BLOCK *block;
+ DEV_RECORD *rec;
+ int len;
+
+ Pmsg0(0, "\nWrite, backup, and re-read test.\n\n"
+"I'm going to write three records and two eof's\n"
+"then backup over the eof's and re-read the last record.\n\n");
+ rewindcmd();
+ block = new_block(dev);
+ rec = new_record();
+ rec->data = check_pool_memory_size(rec->data, block->buf_len);
+ len = rec->data_len = block->buf_len-100;
+ memset(rec->data, 1, rec->data_len);
+ if (!write_record_to_block(block, rec)) {
+ Pmsg0(0, "Error writing record to block.\n");
+ goto bail_out;
+ }
+ if (!write_block_to_dev(jcr, dev, block)) {
+ Pmsg0(0, "Error writing block to device.\n");
+ goto bail_out;
+ } else {
+ Pmsg1(0, "Wrote one record of %d bytes.\n", rec->data_len);
+ }
+ memset(rec->data, 2, rec->data_len);
+ if (!write_record_to_block(block, rec)) {
+ Pmsg0(0, "Error writing record to block.\n");
+ goto bail_out;
+ }
+ if (!write_block_to_dev(jcr, dev, block)) {
+ Pmsg0(0, "Error writing block to device.\n");
+ goto bail_out;
+ } else {
+ Pmsg1(0, "Wrote one record of %d bytes.\n", rec->data_len);
+ }
+ memset(rec->data, 3, rec->data_len);
+ if (!write_record_to_block(block, rec)) {
+ Pmsg0(0, "Error writing record to block.\n");
+ goto bail_out;
+ }
+ if (!write_block_to_dev(jcr, dev, block)) {
+ Pmsg0(0, "Error writing block to device.\n");
+ goto bail_out;
+ } else {
+ Pmsg1(0, "Wrote one record of %d bytes.\n", rec->data_len);
+ }
+ weofcmd();
+ weofcmd();
+ if (bsf_dev(dev, 1) != 0) {
+ Pmsg1(0, "Back space file failed! ERR=%s\n", strerror(dev->dev_errno));
+ goto bail_out;
+ }
+ if (bsf_dev(dev, 1) != 0) {
+ Pmsg1(0, "Back space file failed! ERR=%s\n", strerror(dev->dev_errno));
+ goto bail_out;
+ }
+ Pmsg0(0, "Backspaced over two EOFs OK.\n");
+ if (bsr_dev(dev, 1) != 0) {
+ Pmsg1(0, "Back space record failed! ERR=%s\n", strerror(dev->dev_errno));
+ goto bail_out;
+ }
+ Pmsg0(0, "Backspace record OK.\n");
+ if (!read_block_from_dev(dev, block)) {
+ Pmsg1(0, "Read block failed! ERR=%s\n", strerror(dev->dev_errno));
+ goto bail_out;
+ }
+ memset(rec->data, 0, rec->data_len);
+ if (!read_record_from_block(block, rec)) {
+ Pmsg1(0, "Read block failed! ERR=%s\n", strerror(dev->dev_errno));
+ goto bail_out;
+ }
+ for (int i=0; i<len; i++) {
+ if (rec->data[i] != 3) {
+ Pmsg0(0, "Bad data in record. Test failed!\n");
+ goto bail_out;
+ }
+ }
+ Pmsg0(0, "Test succeeded!\n\n");
+
+
+ Pmsg0(0, "\nAppend files test.\n\n"
+"I'm going to write one record in file 0,\n"
+" two records in file 1,\n"
+" and three records in file 2\n\n");
rewindcmd();
wrcmd();
weofcmd(); /* end file 0 */
weofcmd();
// weofcmd();
rewindcmd();
+ Pmsg0(0, "Done writing, scanning results ...\n\n");
scancmd();
Pmsg0(0, "End Append to the tape test.\n\
The above scan should have four files of:\n\
-One record, two records, three records, and one record respectively.\n\n");
+One record, two records, three records, and one record \n\
+respectively each with 64,512 bytes.\n\n");
Pmsg0(0, "Append block test.\n\
wrcmd();
weofcmd();
rewindcmd();
- Pmsg0(0, "Done writing, scanning results\n");
+ Pmsg0(0, "Done writing, scanning results ...\n\n");
scancmd();
- Pmsg0(0, "The above should have one file of two blocks.\n");
+ Pmsg0(0, "The above should have one file of two blocks 64,512 bytes each.\n");
+bail_out:
+ free_record(rec);
+ free_block(block);
}