From e0ccfdebe72875815e48f3588865fe5764ef0feb Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Thu, 12 Dec 2002 10:50:33 +0000 Subject: [PATCH] Watchdog updates git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@236 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/ChangeLog | 4 + bacula/kernstodo | 13 ++- bacula/src/dird/sql_cmds.c | 2 +- bacula/src/lib/bpipe.c | 6 ++ bacula/src/lib/bpipe.h | 4 +- bacula/src/lib/lib.h | 1 + bacula/src/lib/protos.h | 190 +++++++++++++++++++------------------ bacula/src/lib/watchdog.c | 104 ++++++++++++++++---- bacula/src/stored/btape.c | 98 +++++++++++++++++-- bacula/src/stored/butil.c | 4 + bacula/src/version.h | 4 +- 11 files changed, 303 insertions(+), 127 deletions(-) diff --git a/bacula/ChangeLog b/bacula/ChangeLog index f702b670e9..393173bc34 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -36,6 +36,10 @@ Changes submitted this submission: - Improved error messages in smtp. ============================================================================= +2002-12-12 Version 1.27d +- This is a minor update that fixes a segmentation fault in btape + as well as reduces non-important error messages in bscan. + 2002-11-29 Version 1.27c - Yet another silly error duplicating a column name in the SQLite make tables. No code change, just a make file. diff --git a/bacula/kernstodo b/bacula/kernstodo index 3dab6db373..8747fd4b3b 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 5 December 2002 + 11 December 2002 Documentation to do: (a little bit at a time) - Document running a test version. @@ -11,10 +11,10 @@ Testing to do: (painful) - that console command line options work - blocksize recognition code. - Test new BSR code (mostly done). +- Test watchdog child timer code. For 1.28 release: -- Add count output to restore. - Need a verbose mode in restore, perhaps to bsr. - Should we dump a SOS when starting a new tape? - bscan without -v is too quiet -- perhaps show jobs. @@ -22,8 +22,6 @@ For 1.28 release: - Print some statistics when get EOF on device in bscan -- feedback to let user know it is working. - Add code to reject whole blocks if not wanted on restore. -- Add watchdog timeout for child processes start_child_timer() - end_child_timer(); - Figure out how to allow multiple simultaneous file Volumes on a single device. @@ -33,12 +31,15 @@ For 1.28 release: - Make sure the MaxVolFiles is fully implemented in SD - Flush all the daemon messages at the end of every job. - Check if both CatalogFiles and UseCatalog are set to SD. -- Check if we can bump Bacula FD priorty in Win2000 +- Check if we can increase Bacula FD priorty in Win2000 - Make bcopy read through bad tape records. - Need return status on read_cb() from read_records(). Need multiple records -- one per Job, maybe a JCR or some other structure with a block and a record. +- Look at hierarchial storage for Bacula. +- Implement Bacula plugins -- design API + - Work more on how to to a Bacula restore beginning with just a Bacula tape and a boot floppy (bare metal recovery). - Try bare metal Windows restore @@ -622,4 +623,6 @@ Done: (see kernsdone for more) - Replace popen() and pclose() -- fail safe and timeout, no SIG dep. - Add code to put VolFile in bsr for restore command. - Volumes can be listed multiple times in Restore volume list. +- Add watchdog timeout for child processes start_child_timer() + end_child_timer(); diff --git a/bacula/src/dird/sql_cmds.c b/bacula/src/dird/sql_cmds.c index c1bf44d086..7dd223fd87 100644 --- a/bacula/src/dird/sql_cmds.c +++ b/bacula/src/dird/sql_cmds.c @@ -198,7 +198,7 @@ char *uar_inc = "WHERE Job.JobTDate>%s AND Job.ClientId=%u " "AND JobMedia.JobId=Job.JobId " "AND JobMedia.MediaId=Media.MediaId " - "AND Job.Level='I' AND JobStatus='T' " + "AND Job.Level IN ('I', 'D') AND JobStatus='T' " "AND Job.FileSetId=%u " "GROUP BY Job.JobId"; diff --git a/bacula/src/lib/bpipe.c b/bacula/src/lib/bpipe.c index 8c415d65e1..dd3827edb6 100644 --- a/bacula/src/lib/bpipe.c +++ b/bacula/src/lib/bpipe.c @@ -108,6 +108,9 @@ BPIPE *open_bpipe(char *prog, int wait, char *mode) } bpipe->worker_stime = time(NULL); bpipe->wait = wait; + if (wait > 0) { + bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait); + } return bpipe; } @@ -167,6 +170,9 @@ int close_bpipe(BPIPE *bpipe) if (WIFEXITED(chldstatus)) { stat = WEXITSTATUS(chldstatus); } + if (bpipe->timer_id) { + stop_child_timer(bpipe->timer_id); + } free(bpipe); return stat; } diff --git a/bacula/src/lib/bpipe.h b/bacula/src/lib/bpipe.h index d01f1823d5..d41365f923 100644 --- a/bacula/src/lib/bpipe.h +++ b/bacula/src/lib/bpipe.h @@ -25,10 +25,10 @@ */ typedef struct s_bpipe { - int worker_pid; + pid_t worker_pid; time_t worker_stime; int wait; + btimer_id timer_id; FILE *rfd; FILE *wfd; } BPIPE; - diff --git a/bacula/src/lib/lib.h b/bacula/src/lib/lib.h index 3562e605bc..b36100dc03 100644 --- a/bacula/src/lib/lib.h +++ b/bacula/src/lib/lib.h @@ -46,6 +46,7 @@ #endif #include "md5.h" #include "tree.h" +#include "watchdog.h" #include "bpipe.h" #include "protos.h" diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index d996455aec..b06e01b645 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -24,133 +24,135 @@ */ /* 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); diff --git a/bacula/src/lib/watchdog.c b/bacula/src/lib/watchdog.c index b53b60fae6..52ea23dc73 100755 --- a/bacula/src/lib/watchdog.c +++ b/bacula/src/lib/watchdog.c @@ -38,12 +38,13 @@ time_t watchdog_time; /* this has granularity of SLEEP_TIME */ #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; /* @@ -80,7 +81,7 @@ int start_watchdog(void) 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; @@ -98,18 +99,14 @@ int stop_watchdog(void) { 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; } @@ -117,24 +114,22 @@ int stop_watchdog(void) /* * 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"); @@ -191,12 +186,89 @@ static void *watchdog_thread(void *arg) 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); +} diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index bb8e3c51b8..bd40505086 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -539,10 +539,89 @@ plus the header exceeds the block size (by default about 64K\n"); */ 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; idata[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 */ @@ -566,10 +645,12 @@ We should be in file 3. I am at file %d. This is %s\n\n", 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\ @@ -590,9 +671,12 @@ block in the first file.\n\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); } diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index a0892aa845..5b114b1f7c 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -174,6 +174,10 @@ static void my_free_jcr(JCR *jcr) free_pool_memory(jcr->fileset_name); jcr->fileset_name = NULL; } + if (jcr->fileset_md5) { + free_pool_memory(jcr->fileset_md5); + jcr->fileset_md5 = NULL; + } if (jcr->dev_name) { free_pool_memory(jcr->dev_name); jcr->dev_name = NULL; diff --git a/bacula/src/version.h b/bacula/src/version.h index 90d59c97bc..c9a4bd5c25 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #define VERSION "1.28" #define VSTRING "1" -#define DATE "9 December 2002" -#define LSMDATE "09Dec02" +#define DATE "12 December 2002" +#define LSMDATE "12Dec02" /* Debug flags */ #define DEBUG 1 -- 2.39.5