]> git.sur5r.net Git - bacula/bacula/commitdiff
Watchdog updates
authorKern Sibbald <kern@sibbald.com>
Thu, 12 Dec 2002 10:50:33 +0000 (10:50 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 12 Dec 2002 10:50:33 +0000 (10:50 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@236 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/ChangeLog
bacula/kernstodo
bacula/src/dird/sql_cmds.c
bacula/src/lib/bpipe.c
bacula/src/lib/bpipe.h
bacula/src/lib/lib.h
bacula/src/lib/protos.h
bacula/src/lib/watchdog.c
bacula/src/stored/btape.c
bacula/src/stored/butil.c
bacula/src/version.h

index f702b670e9a7ebad871fd3505cd111d56138ebb0..393173bc346daf6a5ed48a5b4948bfd86af21d92 100644 (file)
@@ -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.
index 3dab6db3736de3bebf3ac689b1ca8ee747fe4f95..8747fd4b3b808f383cb4e5452c4e2e18dfb7141b 100644 (file)
@@ -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();
 
index c1bf44d086f7b157074742d76ad8f2d97f00a4a4..7dd223fd8796c834e5263c46daa61acbe67e25cc 100644 (file)
@@ -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";
 
index 8c415d65e1872db92cf7bd78d3c341e39f8cc57c..dd3827edb64f55c06fb59299674ecb57bc6d4d1f 100644 (file)
@@ -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;
 }
index d01f1823d521f9405ab2e6668263c04dc086e026..d41365f9238f81b01e48254b1ec971b1d29db4ad 100644 (file)
  */
 
 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;
-
index 3562e605bc2f64ce35295fe01b2d90e372ba14e2..b36100dc03109066539d0d781ecda9129da35015 100644 (file)
@@ -46,6 +46,7 @@
 #endif
 #include "md5.h"
 #include "tree.h"
+#include "watchdog.h"
 #include "bpipe.h"
 
 #include "protos.h"
index d996455aec74c6d4f3bb3d82497f42c3185ec416..b06e01b645965d067dd2122030aa2a127e569d5a 100644 (file)
  */
 
 /* 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);
index b53b60fae6e0537f824054f5adcb0eb5d1a7405d..52ea23dc73add0665068f31a87afdcabe30abee9 100755 (executable)
@@ -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);
+}
index bb8e3c51b830ad30c6d2eacdc21ffa83d5fcf7ee..bd4050508672448375fe2da2e5d66698b8a6166b 100644 (file)
@@ -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; 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 */
@@ -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);
 }
 
 
index a0892aa84530273953aa94ab6ff80e1f6e41b2dd..5b114b1f7ceb9904763dc61b7d3d085315f2304e 100644 (file)
@@ -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;
index 90d59c97bc2e4b8389f03c3e22133f12a42e5610..c9a4bd5c2537e0b016934e5696007fabcb90cb80 100644 (file)
@@ -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