]> git.sur5r.net Git - bacula/bacula/commitdiff
Doc updates + first cut Volume polling code
authorKern Sibbald <kern@sibbald.com>
Sat, 10 Jan 2004 13:32:42 +0000 (13:32 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 10 Jan 2004 13:32:42 +0000 (13:32 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@999 91ce42f0-d328-0410-95d8-f526ca767f89

21 files changed:
bacula/kernstodo
bacula/src/dird/backup.c
bacula/src/dird/msgchan.c
bacula/src/dird/restore.c
bacula/src/stored/askdir.c
bacula/src/stored/bcopy.c
bacula/src/stored/bextract.c
bacula/src/stored/block.c
bacula/src/stored/bls.c
bacula/src/stored/bscan.c
bacula/src/stored/btape.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/mount.c
bacula/src/stored/protos.h
bacula/src/stored/status.c
bacula/src/stored/stored_conf.c
bacula/src/stored/stored_conf.h
bacula/src/version.h

index e5f1dce9cec4178811b76a67ee98effaf9af4d53..2034f73c261f99877e2a22a9141d1433012f5464 100644 (file)
@@ -1,5 +1,5 @@
                  Kern's ToDo List
-                22 December 2003  
+                 09 January 2004
 
 Documentation to do: (any release a little bit at a time)
 - Document running a test version.
@@ -41,6 +41,7 @@ For 1.33 Testing/Documentation:
 - Add counter variable test.
 - Document ln -sf /usr/lib/libncurses.so /usr/lib/libtermcap.so
   and install the esound-devĀ  package for compiling Console on SuSE.
+  This should read 'Document LDFLAGS="-L/usr/lib/termcap" ... '
 - Add an example of using a FIFO in dirdconf.wml 
 - Add an item to the FAQ about running jobs in different timezones.
 - Add some examples of job editing codes.
@@ -55,19 +56,13 @@ For 1.33 Testing/Documentation:
 - Add subsections to the Disaster Recovery index section.
                 
 For 1.33
-- Look at code in recycle_oldes_purged_volume() recycle.c. Why not
-  let SQL do ORDER BY LastWritten ASC?
-- Look at find_next_volume() algorithm. Currently, it selects:
-    +---------+------------+---------------------+-----------+
-    | MediaId | VolumeName | LastWritten         | VolBytes  |
-    +---------+------------+---------------------+-----------+
-    |       3 | Test13     | 0000-00-00 00:00:00 |         1 |
-    |       4 | Test14     | 0000-00-00 00:00:00 |         1 |
-    |       1 | test11     | 2003-12-03 18:39:55 | 4,004,926 |
-    |       2 | test12     | 2004-01-04 15:25:56 | 2,078,691 |
-    +---------+------------+---------------------+-----------+
-  but perhaps it should fill already used Volumes first, and use
-  Append volumes before Purged, or Recycled, ...
+- Add level to estimate command.
+- Check time/dates printed during restore when using Win32 API.
+- Possibly remove the "|| ap == NULL" on lines 123 and 207 of lib/var.c,
+  which creates compile problems on alpha systems.
+  var.c:123: no match for `va_list & == long int'
+- Check "restore" 3 (JobId), then it asks for Storage resource. Does
+  it verify that the correct volume is chosen?
 - Volume "add"ed to Pool gets recycled in first use. VolBytes=0
 - Get rid of 0 dates in LastWritten, ...
 - Make Bacula "poll a drive".
@@ -116,6 +111,7 @@ For 1.33
   resources, like Level? If so, I think I'd make it an optional directive
   in Job, Client, and Pool, with precedence such that Job overrides Client
   which in turn overrides Pool.
+- Print a message when a job starts if the conf file is not current.
 - Finish work on conio.c
 - To pass Include 1 or two letter commands
   I Name           Include name - first record
@@ -1071,3 +1067,16 @@ Done: (see kernsdone for more)
     gnome-console is built, but the binary and .conf are not being installed.
 - Permit Bacula and apcupsd donations (not done for apcupsd).
 - Fix Ctl-C crashing the Console (readline?).
+- Look at code in recycle_oldes_purged_volume() recycle.c. Why not
+  let SQL do ORDER BY LastWritten ASC?
+- Look at find_next_volume() algorithm. Currently, it selects:
+    +---------+------------+---------------------+-----------+
+    | MediaId | VolumeName | LastWritten         | VolBytes  |
+    +---------+------------+---------------------+-----------+
+    |       3 | Test13     | 0000-00-00 00:00:00 |         1 |
+    |       4 | Test14     | 0000-00-00 00:00:00 |         1 |
+    |       1 | test11     | 2003-12-03 18:39:55 | 4,004,926 |
+    |       2 | test12     | 2004-01-04 15:25:56 | 2,078,691 |
+    +---------+------------+---------------------+-----------+
+  but perhaps it should fill already used Volumes first, and use
+  Append volumes before Purged, or Recycled, ...
index 2480afbcee82e2d5880feb7885ee3e3d111ca3a1..0fe51441a94e64faf09373ced7eb3c3460a8bcd2 100644 (file)
@@ -385,14 +385,18 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr
         msg_type = M_ERROR;          /* Generate error message */
         if (jcr->store_bsock) {
            bnet_sig(jcr->store_bsock, BNET_TERMINATE);
-           pthread_cancel(jcr->SD_msg_chan);
+           if (jcr->SD_msg_chan) {
+              pthread_cancel(jcr->SD_msg_chan);
+           }
         }
         break;
       case JS_Canceled:
          term_msg = _("Backup Canceled");
         if (jcr->store_bsock) {
            bnet_sig(jcr->store_bsock, BNET_TERMINATE);
-           pthread_cancel(jcr->SD_msg_chan);
+           if (jcr->SD_msg_chan) {
+              pthread_cancel(jcr->SD_msg_chan);
+           }
         }
         break;
       default:
index 1f3d42bb9c7772b9a42008579cfda1e4aac114c9..94b8c664f84fcae492d283aa9b83133f4c264678 100644 (file)
@@ -196,6 +196,7 @@ static void msg_thread_cleanup(void *arg)
    P(jcr->mutex);
    jcr->sd_msg_thread_done = true;
    pthread_cond_broadcast(&jcr->term_wait); /* wakeup any waiting threads */
+   jcr->SD_msg_chan = 0;
    V(jcr->mutex);
    free_jcr(jcr);                    /* release jcr */
 }
index 6dfb15ef140cd47dcdfc9b08f2a3a2aa2f357a09..47e6bd4db2c34206031ea43c9ac3a06dd15be1f6 100644 (file)
@@ -287,14 +287,18 @@ static void restore_cleanup(JCR *jcr, int TermCode)
       msg_type = M_ERROR;         /* Generate error message */
       if (jcr->store_bsock) {
         bnet_sig(jcr->store_bsock, BNET_TERMINATE);
-        pthread_cancel(jcr->SD_msg_chan);
+        if (jcr->SD_msg_chan) {
+           pthread_cancel(jcr->SD_msg_chan);
+        }
       }
       break;
    case JS_Canceled:
       term_msg = _("Restore Canceled");
       if (jcr->store_bsock) {
         bnet_sig(jcr->store_bsock, BNET_TERMINATE);
-        pthread_cancel(jcr->SD_msg_chan);
+        if (jcr->SD_msg_chan) {
+           pthread_cancel(jcr->SD_msg_chan);
+        }
       }
       break;
    default:
index 027b3f75aa6b6629d521e4560af94df718f1b1ef..81138f046550caf59467cd6e5cc135f0f76ff5c3 100644 (file)
@@ -54,7 +54,7 @@ static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%u"
 static char OK_create[] = "1000 OK CreateJobMedia\n";
 
 /* Forward referenced functions */
-static int wait_for_sysop(JCR *jcr, DEVICE *dev, int wait_sec);
+static int wait_for_sysop(JCR *jcr, DEVICE *dev);
 
 /*
  * Send current JobStatus to Director
@@ -159,7 +159,7 @@ int dir_find_next_appendable_volume(JCR *jcr)
 int dir_update_volume_info(JCR *jcr, DEVICE *dev, int label)
 {
    BSOCK *dir = jcr->dir_bsock;
-   time_t EndTime = time(NULL);
+   time_t LastWritten = time(NULL);
    char ed1[50], ed2[50], ed3[50], ed4[50];
    VOLUME_CAT_INFO *vol = &dev->VolCatInfo;
 
@@ -188,7 +188,7 @@ int dir_update_volume_info(JCR *jcr, DEVICE *dev, int label)
       vol->VolCatBlocks, edit_uint64(vol->VolCatBytes, ed1),
       vol->VolCatMounts, vol->VolCatErrors,
       vol->VolCatWrites, edit_uint64(vol->VolCatMaxBytes, ed2), 
-      EndTime, vol->VolCatStatus, vol->Slot, label,
+      LastWritten, vol->VolCatStatus, vol->Slot, label,
       vol->InChanger,
       edit_uint64(vol->VolReadTime, ed3), 
       edit_uint64(vol->VolWriteTime, ed4) );
@@ -262,8 +262,9 @@ int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec)
 }
 
 
+
 /*
- *   Request to mount next Volume, which Volume not specified
+ *   Request the sysop to create an appendable volume
  *
  *   Entered with device blocked.
  *   Leaves with device blocked.
@@ -280,37 +281,34 @@ int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec)
  *     actually be mounted. The calling routine must read it and
  *     verify the label.
  */
-int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev)
+int dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev)
 {
    int stat = 0, jstat;
-   /* ******FIXME******* put these on config variable */
-   int min_wait = 60 * 60;
-   int max_wait = 24 * 60 * 60;
-   int max_num_wait = 9;             /* 5 waits =~ 1 day, then 1 day at a time */
-
-   int wait_sec;
-   int num_wait = 0;
+   bool unmounted;
 
-   Dmsg0(130, "enter dir_ask_sysop_to_mount_next_volume\n");
+   Dmsg0(130, "enter dir_ask_sysop_to_create_appendable_volume\n");
    ASSERT(dev->dev_blocked);
-   wait_sec = min_wait;
    for ( ;; ) {
       if (job_canceled(jcr)) {
-         Mmsg(&dev->errmsg, _("Job %s canceled while waiting for mount on Storage Device \"%s\".\n"), 
+        Mmsg(&dev->errmsg,
+              _("Job %s canceled while waiting for mount on Storage Device \"%s\".\n"), 
              jcr->Job, jcr->dev_name);
          Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
         return 0;
       }
       if (dir_find_next_appendable_volume(jcr)) {    /* get suggested volume */
         jstat = JS_WaitMount;
+        unmounted = (dev->dev_blocked == BST_UNMOUNTED) ||
+                    (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
         /*
          * If we have a valid volume name and we are not
          *   removable media, return now, or if we have a
          *   Slot for an autochanger, otherwise wait
          *   for the operator to mount the media.
          */
-        if ((jcr->VolumeName[0] && !dev_cap(dev, CAP_REM) && dev_cap(dev, CAP_LABEL)) ||
-            (jcr->VolumeName[0] && jcr->VolCatInfo.Slot)) {
+        if (!unmounted && ((jcr->VolumeName[0] && !dev_cap(dev, CAP_REM) && 
+               dev_cap(dev, CAP_LABEL)) ||
+                (jcr->VolumeName[0] && jcr->VolCatInfo.Slot))) {
             Dmsg0(100, "Return 1 from mount without wait.\n");
            return 1;
         }
@@ -322,32 +320,33 @@ int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev)
                jcr->VolumeName, jcr->dev_name, jcr->Job);
       } else {
         jstat = JS_WaitMedia;
-        Jmsg(jcr, M_MOUNT, 0, _(
+        if (!dev->poll) {
+           Jmsg(jcr, M_MOUNT, 0, _(
 "Job %s waiting. Cannot find any appendable volumes.\n\
 Please use the \"label\"  command to create a new Volume for:\n\
     Storage:      %s\n\
     Media type:   %s\n\
     Pool:         %s\n"),
-             jcr->Job, 
-             jcr->dev_name, 
-             jcr->media_type,
-             jcr->pool_name);
+              jcr->Job, 
+              jcr->dev_name, 
+              jcr->media_type,
+              jcr->pool_name);
+        }
       }
 
       jcr->JobStatus = jstat;
       dir_send_job_status(jcr);
 
-      stat = wait_for_sysop(jcr, dev, wait_sec);
+      stat = wait_for_sysop(jcr, dev);
+      if (dev->poll) {
+         Dmsg1(200, "Poll timeout in create append vol on device %s\n", dev_name(dev));
+        continue;
+      }
 
       if (stat == ETIMEDOUT) {
-        wait_sec *= 2;               /* double wait time */
-        if (wait_sec > max_wait) {   /* but not longer than maxtime */
-           wait_sec = max_wait;
-        }
-        num_wait++;
-        if (num_wait >= max_num_wait) {
+        if (!double_dev_wait_time(dev)) {
             Mmsg(&dev->errmsg, _("Gave up waiting to mount Storage Device \"%s\" for Job %s\n"), 
-                jcr->dev_name, jcr->Job);
+              dev_name(dev), jcr->Job);
             Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
             Dmsg1(190, "Gave up waiting on device %s\n", dev_name(dev));
            return 0;                 /* exceeded maximum waits */
@@ -366,22 +365,30 @@ Please use the \"label\"  command to create a new Volume for:\n\
       }
       Dmsg1(190, "Someone woke me for device %s\n", dev_name(dev));
 
-      /* Restart wait counters */
-      wait_sec = min_wait;
-      num_wait = 0;
       /* If no VolumeName, and cannot get one, try again */
       if (jcr->VolumeName[0] == 0 && !job_canceled(jcr) &&
          !dir_find_next_appendable_volume(jcr)) {
         Jmsg(jcr, M_MOUNT, 0, _(
 "Someone woke me up, but I cannot find any appendable\n\
 volumes for Job=%s.\n"), jcr->Job);
+        /* Restart wait counters after user interaction */
+        init_dev_wait_timers(dev);
         continue;
       }       
+      unmounted = (dev->dev_blocked == BST_UNMOUNTED) ||
+                 (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
+      if (unmounted) {
+        continue;                    /* continue to wait */
+      }
+
+      /*
+       * Device mounted, we have a volume, break and return   
+       */
       break;
    }
    set_jcr_job_status(jcr, JS_Running);
    dir_send_job_status(jcr);
-   Dmsg0(130, "leave dir_ask_sysop_to_mount_next_volume\n");
+   Dmsg0(130, "leave dir_ask_sysop_to_mount_create_appendable_volume\n");
    return 1;
 }
 
@@ -400,47 +407,55 @@ volumes for Job=%s.\n"), jcr->Job);
 int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
 {
    int stat = 0;
-   /* ******FIXME******* put these on config variable */
-   int min_wait = 60 * 60;
-   int max_wait = 24 * 60 * 60;
-   int max_num_wait = 9;             /* 5 waits =~ 1 day, then 1 day at a time */
-   int wait_sec;
-   int num_wait = 0;
    char *msg;
 
-   Dmsg0(130, "enter dir_ask_sysop_to_mount_next_volume\n");
+   Dmsg0(130, "enter dir_ask_sysop_to_mount_volume\n");
    if (!jcr->VolumeName[0]) {
       Mmsg0(&dev->errmsg, _("Cannot request another volume: no volume name given.\n"));
       return 0;
    }
    ASSERT(dev->dev_blocked);
-   wait_sec = min_wait;
    for ( ;; ) {
       if (job_canceled(jcr)) {
          Mmsg(&dev->errmsg, _("Job %s canceled while waiting for mount on Storage Device \"%s\".\n"), 
              jcr->Job, jcr->dev_name);
         return 0;
       }
-      msg = _("Please mount");
-      Jmsg(jcr, M_MOUNT, 0, _("%s Volume \"%s\" on Storage Device \"%s\" for Job %s\n"),
-          msg, jcr->VolumeName, jcr->dev_name, jcr->Job);
-      Dmsg3(190, "Mount %s on %s for Job %s\n",
-           jcr->VolumeName, jcr->dev_name, jcr->Job);
+
+      /*
+       * If we have a valid volume name and we are not
+       *   removable media, return now, or if we have a
+       *   Slot for an autochanger, otherwise wait
+       *   for the operator to mount the media.
+       */
+      if ((jcr->VolumeName[0] && !dev_cap(dev, CAP_REM) && dev_cap(dev, CAP_LABEL)) ||
+         (jcr->VolumeName[0] && jcr->VolCatInfo.Slot)) {
+         Dmsg0(100, "Return 1 from mount without wait.\n");
+        return 1;
+      }
+
+      if (!dev->poll) {
+         msg = _("Please mount");
+         Jmsg(jcr, M_MOUNT, 0, _("%s Volume \"%s\" on Storage Device \"%s\" for Job %s\n"),
+             msg, jcr->VolumeName, jcr->dev_name, jcr->Job);
+         Dmsg3(190, "Mount %s on %s for Job %s\n",
+              jcr->VolumeName, jcr->dev_name, jcr->Job);
+      }
 
       jcr->JobStatus = JS_WaitMount;
       dir_send_job_status(jcr);
 
-      stat = wait_for_sysop(jcr, dev, wait_sec); /* wait on device */
+      stat = wait_for_sysop(jcr, dev);    /* wait on device */
+      if (dev->poll) {
+         Dmsg1(200, "Poll timeout in mount vol on device %s\n", dev_name(dev));
+         Dmsg1(200, "Blocked=%d\n", dev->dev_blocked);
+        return 1;
+      }
 
       if (stat == ETIMEDOUT) {
-        wait_sec *= 2;               /* double wait time */
-        if (wait_sec > max_wait) {   /* but not longer than maxtime */
-           wait_sec = max_wait;
-        }
-        num_wait++;
-        if (num_wait >= max_num_wait) {
+        if (!double_dev_wait_time(dev)) {
             Mmsg(&dev->errmsg, _("Gave up waiting to mount Storage Device \"%s\" for Job %s\n"), 
-                jcr->dev_name, jcr->Job);
+              dev_name(dev), jcr->Job);
             Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
             Dmsg1(190, "Gave up waiting on device %s\n", dev_name(dev));
            return 0;                 /* exceeded maximum waits */
@@ -458,59 +473,66 @@ int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
            strerror(stat));
       }
       Dmsg1(190, "Someone woke me for device %s\n", dev_name(dev));
-
-      /* Restart wait counters */
-      wait_sec = min_wait;
-      num_wait = 0;
       break;
    }
    set_jcr_job_status(jcr, JS_Running);
    dir_send_job_status(jcr);
-   Dmsg0(130, "leave dir_ask_sysop_to_mount_next_volume\n");
+   Dmsg0(130, "leave dir_ask_sysop_to_mount_volume\n");
    return 1;
 }
 
 /*
  * Wait for SysOp to mount a tape
  */
-static int wait_for_sysop(JCR *jcr, DEVICE *dev, int wait_sec)
+static int wait_for_sysop(JCR *jcr, DEVICE *dev)
 {
    struct timeval tv;
    struct timezone tz;
    struct timespec timeout;
-   int dev_blocked;
-   time_t start = time(NULL);
    time_t last_heartbeat = 0;
+   time_t first_start = time(NULL);
    int stat = 0;
    int add_wait;
+   bool unmounted;
    
+   P(dev->mutex);
+   unmounted = (dev->dev_blocked == BST_UNMOUNTED) ||
+               (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
+
+   dev->poll = false;
    /*
-    * Wait requested time (wait_sec).  However, we also wake up every
+    * Wait requested time (dev->rem_wait_sec). However, we also wake up every
     *   HB_TIME seconds and send a heartbeat to the FD and the Director
     *   to keep stateful firewalls from closing them down while waiting
     *   for the operator.
     */
-   add_wait = wait_sec;
+   add_wait = dev->rem_wait_sec;
    if (me->heartbeat_interval && add_wait > me->heartbeat_interval) {
       add_wait = me->heartbeat_interval;
    }
+   if (!unmounted && dev->vol_poll_interval && add_wait > dev->vol_poll_interval) {
+      add_wait = dev->vol_poll_interval;
+   }
    gettimeofday(&tv, &tz);
    timeout.tv_nsec = tv.tv_usec * 1000;
    timeout.tv_sec = tv.tv_sec + add_wait;
 
-   P(dev->mutex);
-   dev_blocked = dev->dev_blocked;
-   dev->dev_blocked = BST_WAITING_FOR_SYSOP; /* indicate waiting for mount */
+   if (!unmounted) {
+      dev->dev_prev_blocked = dev->dev_blocked;
+      dev->dev_blocked = BST_WAITING_FOR_SYSOP; /* indicate waiting for mount */
+   }
 
    for ( ; !job_canceled(jcr); ) {
-      time_t now;
+      time_t now, start;
 
       Dmsg3(100, "I'm going to sleep on device %s. HB=%d wait=%d\n", dev_name(dev),
-        (int)me->heartbeat_interval, wait_sec);
+        (int)me->heartbeat_interval, dev->wait_sec);
+      start = time(NULL);
       stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->mutex, &timeout);
       Dmsg1(100, "Wokeup from sleep on device stat=%d\n", stat);
 
       now = time(NULL);
+      dev->rem_wait_sec -= (now - start);
 
       /* Note, this always triggers the first time. We want that. */
       if (me->heartbeat_interval) {
@@ -527,19 +549,38 @@ static int wait_for_sysop(JCR *jcr, DEVICE *dev, int wait_sec)
         }
       }
 
-      if (dev->dev_blocked == BST_MOUNT) {   /* mount request ? */
-        stat = 0;
-        break;
-      }
+      /*
+       * Check if user unmounted the device while we were waiting
+       */
+      unmounted = (dev->dev_blocked == BST_UNMOUNTED) ||
+                  (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
 
       if (stat != ETIMEDOUT) {    /* we blocked the device */
         break;                    /* on error return */
       }
-      if (now - start >= wait_sec) {  /* on exceeding wait time return */
+      if (dev->rem_wait_sec <= 0) {  /* on exceeding wait time return */
          Dmsg0(100, "Exceed wait time.\n");
         break;
       }
-      add_wait = wait_sec - (now - start);
+      
+      if (!unmounted && dev->vol_poll_interval &&      
+         (now - first_start >= dev->vol_poll_interval)) {
+         Dmsg1(200, "In wait blocked=%d\n", dev->dev_blocked);
+        dev->poll = true;
+        break;
+      }
+      /*
+       * Check if user mounted the device while we were waiting
+       */
+      if (dev->dev_blocked == BST_MOUNT) {   /* mount request ? */
+        stat = 0;
+        break;
+      }
+
+      add_wait = dev->wait_sec - (now - start);
+      if (add_wait < 0) {
+        add_wait = 0;
+      }
       if (me->heartbeat_interval && add_wait > me->heartbeat_interval) {
         add_wait = me->heartbeat_interval;
       }
@@ -549,7 +590,9 @@ static int wait_for_sysop(JCR *jcr, DEVICE *dev, int wait_sec)
       Dmsg1(100, "Additional wait %d sec.\n", add_wait);
    }
 
-   dev->dev_blocked = dev_blocked;    /* restore entry state */
+   if (!unmounted) {
+      dev->dev_blocked = dev->dev_prev_blocked;    /* restore entry state */
+   }
    V(dev->mutex);
    return stat;
 }
index 9efa2a796503d7b98dee654daa37afe120b821fe..6255e65247374be8bff6a586496d8b06f305d299 100644 (file)
@@ -256,7 +256,7 @@ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw  writing) { return 1;}
 int    dir_find_next_appendable_volume(JCR *jcr) { return 1;}
 int    dir_update_volume_info(JCR *jcr, DEVICE *dev, int relabel) { return 1; }
 int    dir_create_jobmedia_record(JCR *jcr) { return 1; }
-int    dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
+int    dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev) { return 1; }
 int    dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
 int    dir_send_job_status(JCR *jcr) {return 1;}
 
index 1ac47c0700736eaea88c63f7ab05577f7f723e1f..950ff5bbb2a2385f3f6206e17627a7a8d1240c2b 100644 (file)
@@ -437,7 +437,7 @@ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw  writing) { return 1;}
 int    dir_find_next_appendable_volume(JCR *jcr) { return 1;}
 int    dir_update_volume_info(JCR *jcr, DEVICE *dev, int relabel) { return 1; }
 int    dir_create_jobmedia_record(JCR *jcr) { return 1; }
-int    dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
+int    dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev) { return 1; }
 int    dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
 int    dir_send_job_status(JCR *jcr) {return 1;}
 
index c74902de4b519e564ece3fe233cf05400bc132cc..585f89ca3446950db72827dc16dcde7f1cfefbc8 100644 (file)
@@ -412,6 +412,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       block->write_failed = true;
       if (weof_dev(dev, 1) != 0) {           /* end tape */
          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+        dev->VolCatInfo.VolCatErrors++;
       }
       /* Don't do update after second EOF or file count will be wrong */
       Dmsg0(100, "dir_update_volume_info\n");
@@ -419,6 +420,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       dir_update_volume_info(jcr, dev, 0);
       if (dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* write eof */
          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+        dev->VolCatInfo.VolCatErrors++;
       }
       dev->state |= (ST_EOF | ST_EOT | ST_WEOT);
       return 0;   
@@ -433,6 +435,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
         if (weof_dev(dev, 1) != 0) {            /* write eof */
             Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
            block->write_failed = true;
+           dev->VolCatInfo.VolCatErrors++;
            dev->state |= (ST_EOF | ST_EOT | ST_WEOT);
             Dmsg0(100, "dir_update_volume_info\n");
            dev->VolCatInfo.VolCatFiles = dev->file;
@@ -499,12 +502,14 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 
       block->write_failed = true;
       if (weof_dev(dev, 1) != 0) {        /* end the tape */
+        dev->VolCatInfo.VolCatErrors++;
          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
       }
       Dmsg0(100, "dir_update_volume_info\n");
       dev->VolCatInfo.VolCatFiles = dev->file;
       dir_update_volume_info(jcr, dev, 0);
       if (dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* end the tape */
+        dev->VolCatInfo.VolCatErrors++;
          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
       }
       dev->state |= (ST_EOF | ST_EOT | ST_WEOT);
index 350d7b79110f461c3b13eff6368c88fd2e3ffcf4..0525a4af7984103a6e726138880a5ad2b39d7d49 100644 (file)
@@ -400,7 +400,7 @@ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw  writing) { return 1;}
 int    dir_find_next_appendable_volume(JCR *jcr) { return 1;}
 int    dir_update_volume_info(JCR *jcr, DEVICE *dev, int relabel) { return 1; }
 int    dir_create_jobmedia_record(JCR *jcr) { return 1; }
-int    dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
+int    dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev) { return 1; }
 int    dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
 int    dir_send_job_status(JCR *jcr) {return 1;}
 
index d0d406c7a2582c4d230b636a2e8c854c91dc5344..4eaf150c39b6d6ca68ba402da3e115d790935443 100644 (file)
@@ -1114,7 +1114,7 @@ int       dir_get_volume_info(JCR *jcr, enum get_vol_info_rw  writing) { return 1;}
 int    dir_find_next_appendable_volume(JCR *jcr) { return 1;}
 int    dir_update_volume_info(JCR *jcr, DEVICE *dev, int relabel) { return 1; }
 int    dir_create_jobmedia_record(JCR *jcr) { return 1; }
-int    dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
+int    dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev) { return 1; }
 int    dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
 int    dir_send_job_status(JCR *jcr) {return 1;}
 
index 0b75970041b03bbd4c1da073ec96bc21b2638fd6..4c586c694abd199dcc26a5905acd8919ffa58723 100644 (file)
@@ -2245,7 +2245,7 @@ int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
    return 1;
 }
 
-int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev)
+int dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev)
 {
    /* Close device so user can use autochanger if desired */
    if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
index 2dc51f42b6e9c7ad8ba081de02b7d700ec57f2fe..0140d4211c33858bf770465ac611f2f1ad1175c1 100644 (file)
@@ -147,6 +147,11 @@ init_dev(DEVICE *dev, DEVRES *device)
    dev->max_rewind_wait = device->max_rewind_wait;
    dev->max_open_wait = device->max_open_wait;
    dev->max_open_vols = device->max_open_vols;
+   dev->vol_poll_interval = device->vol_poll_interval;
+   /* Sanity check */
+   if (dev->vol_poll_interval && dev->vol_poll_interval < 60) {
+      dev->vol_poll_interval = 60;
+   }
    dev->device = device;
 
    if (tape) {
@@ -1386,3 +1391,37 @@ JCR *next_attached_jcr(DEVICE *dev, JCR *jcr)
    }
    return jcr->next_dev;
 }
+
+/*
+ * This routine initializes the device wait timers
+ */
+void init_dev_wait_timers(DEVICE *dev)
+{
+   /* ******FIXME******* put these on config variables */
+   dev->min_wait = 60 * 60;
+   dev->max_wait = 24 * 60 * 60;
+   dev->max_num_wait = 9;             /* 5 waits =~ 1 day, then 1 day at a time */
+   dev->wait_sec = dev->min_wait;
+   dev->rem_wait_sec = dev->wait_sec;
+   dev->num_wait = 0;
+   dev->poll = false;
+   dev->BadVolName[0] = 0;
+}
+
+/*
+ * Returns: true if time doubled
+ *         false if max time expired
+ */
+bool double_dev_wait_time(DEVICE *dev)
+{
+   dev->wait_sec *= 2;              /* double wait time */
+   if (dev->wait_sec > dev->max_wait) {   /* but not longer than maxtime */
+      dev->wait_sec = dev->max_wait;
+   }
+   dev->num_wait++;
+   dev->rem_wait_sec = dev->wait_sec;
+   if (dev->num_wait >= dev->max_num_wait) {
+      return false;
+   }
+   return true;
+}
index 32d717f0ae0aec5bb2017716e801ae182f50b397..78d9d7b5148c8f774c2096669c67dbeebe8bdf19 100644 (file)
@@ -142,6 +142,7 @@ 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 */
 } bsteal_lock_t;
 
 struct DEVRES;                        /* Device resource defined in stored_conf.h */
@@ -157,6 +158,7 @@ public:
    pthread_cond_t wait_next_vol;      /* wait for tape to be mounted */
    pthread_t no_wait_id;              /* this thread must not wait */
    int dev_blocked;                   /* set if we must wait (i.e. change tape) */
+   int dev_prev_blocked;              /* previous blocked state */
    int num_waiting;                   /* number of threads waiting */
    int num_writers;                   /* number of writing threads */
    int use_count;                     /* usage count on this device */
@@ -180,12 +182,22 @@ public:
    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 */
+   utime_t  vol_poll_interval;        /* interval between polling Vol mount */
    DEVRES *device;                    /* pointer to Device Resource */
    btimer_id tid;                     /* timer id */
 
    VOLUME_CAT_INFO VolCatInfo;        /* Volume Catalog Information */
    VOLUME_LABEL VolHdr;               /* Actual volume label */
    
+   /* Device wait times ***FIXME*** look at durations */
+   char BadVolName[MAX_NAME_LENGTH];  /* Last wrong Volume mounted */
+   bool poll;                         /* set to poll Volume */
+   int min_wait;
+   int max_wait;
+   int max_num_wait;
+   int wait_sec;
+   int rem_wait_sec;
+   int num_wait;
 };
 
 
index eaacb8fcd4ed1e358e73423936df89303f289ed3..46ffd38ace86113d2eeb606a7ca8b148090e0b0f 100644 (file)
@@ -366,6 +366,7 @@ void _steal_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold,
    Dmsg4(100, "steal lock. old=%d new=%d from %s:%d\n", dev->dev_blocked, state,
       file, line);
    hold->dev_blocked = dev->dev_blocked;
+   hold->dev_prev_blocked = dev->dev_prev_blocked;
    hold->no_wait_id = dev->no_wait_id;
    dev->dev_blocked = state;
    dev->no_wait_id = pthread_self();
@@ -382,5 +383,6 @@ void _give_back_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *ho
       dev->dev_blocked, hold->dev_blocked, file, line);
    P(dev->mutex);
    dev->dev_blocked = hold->dev_blocked;
+   dev->dev_prev_blocked = hold->dev_prev_blocked;
    dev->no_wait_id = hold->no_wait_id;
 }
index ab506c3a58dc84350d5cc712113641870832c6e5..efc3343bcf0eed840dd431d283da19ae73bfa692 100644 (file)
@@ -599,7 +599,7 @@ static int unmount_cmd(JCR *jcr)
         P(dev->mutex);               /* Use P to avoid indefinite block */
         if (!(dev->state & ST_OPENED)) {
             Dmsg0(90, "Device already unmounted\n");
-            bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"), dev_name(dev));
+            bnet_fsend(dir, _("3901 Device \"%s\" is already unmounted.\n"), dev_name(dev));
 
         } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) {
             Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
@@ -608,18 +608,18 @@ static int unmount_cmd(JCR *jcr)
            offline_or_rewind_dev(dev);
            force_close_dev(dev);
            dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP;
-            bnet_fsend(dir, _("3001 Device %s unmounted.\n"), dev_name(dev));
+            bnet_fsend(dir, _("3001 Device \"%s\" unmounted.\n"), dev_name(dev));
 
         } else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
-            bnet_fsend(dir, _("3902 Device %s is busy in acquire.\n"), dev_name(dev));
+            bnet_fsend(dir, _("3902 Device \"%s\" is busy in acquire.\n"), dev_name(dev));
 
         } else if (dev->dev_blocked == BST_WRITING_LABEL) {
-            bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), dev_name(dev));
+            bnet_fsend(dir, _("3903 Device \"%s\" is being labeled.\n"), dev_name(dev));
 
         } else if (dev_state(dev, ST_READ) || dev->num_writers) {
            if (dev_state(dev, ST_READ)) {
                 Dmsg0(90, "Device in read mode\n");
-                bnet_fsend(dir, _("3904 Device %s is busy with 1 reader.\n"), dev_name(dev));
+                bnet_fsend(dir, _("3904 Device \"%s\" is busy reading.\n"), dev_name(dev));
            } else {
                 Dmsg1(90, "Device busy with %d writers\n", dev->num_writers);
                 bnet_fsend(dir, _("3905 Device %s is busy with %d writer(s).\n"),
@@ -789,7 +789,7 @@ static int readlabel_cmd(JCR *jcr)
         dev = jcr->device->dev;
 
         P(dev->mutex);               /* Use P to avoid indefinite block */
-        if (!(dev->state & ST_OPENED)) {
+        if (!dev_state(dev, ST_OPENED)) {
            if (open_dev(dev, NULL, READ_WRITE) < 0) {
                bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev));
            } else {
@@ -845,9 +845,9 @@ static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot)
    block = new_block(dev);
 
    /* Ensure that the device is open -- autoload_device() closes it */
-   for ( ; !(dev->state & ST_OPENED); ) {
+   for ( ; !dev_state(dev, ST_OPENED); ) {
       if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) {
-         bnet_fsend(dir, _("3910 Unable to open device %s. ERR=%s\n"), 
+         bnet_fsend(dir, _("3910 Unable to open device \"%s\". ERR=%s\n"), 
            dev_name(dev), strerror_dev(dev));
         goto bail_out;
       }
@@ -856,7 +856,7 @@ static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot)
    dev->state &= ~ST_LABEL;          /* force read of label */
    switch (read_dev_volume_label(jcr, dev, block)) {               
    case VOL_OK:
-      bnet_fsend(dir, _("3001 Volume=%s Slot=%d\n"), dev->VolHdr.VolName, Slot);
+      bnet_fsend(dir, _("3001 Volume=\"%s\" Slot=%d\n"), dev->VolHdr.VolName, Slot);
       Dmsg1(100, "Volume: %s\n", dev->VolHdr.VolName);
       break;
    default:
index de54ad968438cfad08af80bba4cf1fa5d4942790..0ba90a615f75db19fe8ae73dbd1627131b0b2a21 100644 (file)
 #include "bacula.h"                   /* pull in global headers */
 #include "stored.h"                   /* pull in Storage Deamon headers */
 
-/* Forward referenced routines */
-static void mark_volume_in_error(JCR *jcr, DEVICE *dev);
-
-
 /*
  * If release is set, we rewind the current volume, 
  * which we no longer want, and ask the user (console) 
@@ -54,13 +50,16 @@ int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release
 
    Dmsg0(100, "Enter mount_next_volume()\n");
 
+   init_dev_wait_timers(dev);
+
    /* 
     * Attempt to mount the next volume. If something non-fatal goes
     *  wrong, we come back here to re-try (new op messages, re-read
     *  Volume, ...)
     */
 mount_next_vol:
-   if (retry++ > 5) {
+   /* Ignore retry if this is poll request */
+   if (!dev->poll && retry++ > 8) {
       Jmsg(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"), 
           dev_name(dev));
       return 0;
@@ -82,9 +81,9 @@ mount_next_vol:
     *   in jcr->VolCatInfo
     */
    Dmsg0(100, "Before dir_find_next\n");
-   if (!dir_find_next_appendable_volume(jcr)) {
+   while (!dir_find_next_appendable_volume(jcr)) {
        Dmsg0(100, "not dir_find_next\n");
-       if (!dir_ask_sysop_to_mount_next_volume(jcr, dev)) {
+       if (!dir_ask_sysop_to_create_appendable_volume(jcr, dev)) {
         return 0;
        }
    }
@@ -123,7 +122,7 @@ mount_next_vol:
    Dmsg2(100, "Ask=%d autochanger=%d\n", ask, autochanger);
    release = true;                /* release next time if we "recurse" */
 
-   if (ask && !dir_ask_sysop_to_mount_next_volume(jcr, dev)) {
+   if (ask && !dir_ask_sysop_to_mount_volume(jcr, dev)) {
       Dmsg0(100, "Error return ask_sysop ...\n");
       return 0;             /* error return */
    }
@@ -179,6 +178,13 @@ read_volume:
       VOLUME_CAT_INFO VolCatInfo;
 
       Dmsg1(100, "Vol NAME Error Name=%s\n", jcr->VolumeName);
+      /* If polling and got a previous bad name, ignore it */
+      if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolName) == 0) {
+        ask = true;
+         Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n", 
+           jcr->VolumeName);
+        goto mount_next_vol;
+      }
       /* 
        * OK, we got a different volume mounted. First save the
        *  requested Volume info (jcr) structure, then query if
@@ -189,6 +195,7 @@ read_volume:
       /* Check if this is a valid Volume in the pool */
       pm_strcpy(&jcr->VolumeName, dev->VolHdr.VolName);                        
       if (!dir_get_volume_info(jcr, GET_VOL_INFO_FOR_WRITE)) {
+        bstrncpy(dev->BadVolName, dev->VolHdr.VolName, sizeof(dev->BadVolName));
          Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n"
               "    Current Volume \"%s\" not acceptable because:\n"
               "    %s"),
@@ -240,7 +247,11 @@ read_volume:
    case VOL_NO_MEDIA:
    default:
       /* Send error message */
-      Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);                         
+      if (!dev->poll) {
+         Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);                         
+      } else {
+         Dmsg1(200, "Msg suppressed by poll: %s\n", jcr->errmsg);
+      }
       ask = true;
       goto mount_next_vol;
    }
@@ -375,7 +386,10 @@ The number of files mismatch! Volume=%u Catalog=%u\n"),
    return 1; 
 }
 
-static void mark_volume_in_error(JCR *jcr, DEVICE *dev)
+/*
+ * Mark volume in error in catalog 
+ */
+void mark_volume_in_error(JCR *jcr, DEVICE *dev)
 {
    Jmsg(jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"),
        jcr->VolumeName);
index 3e1d1560e5722b21d88546fa91f136546167ac5e..10b4122db9d62abda71134ea33130c0b05f03303 100644 (file)
@@ -40,7 +40,7 @@ enum get_vol_info_rw {
 int     dir_get_volume_info(JCR *jcr, enum get_vol_info_rw);
 int     dir_find_next_appendable_volume(JCR *jcr);
 int     dir_update_volume_info(JCR *jcr, DEVICE *dev, int label);
-int     dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev);
+int     dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev);
 int     dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
 int     dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
 int     dir_send_job_status(JCR *jcr);
@@ -103,6 +103,8 @@ JCR     *next_attached_jcr(DEVICE *dev, JCR *jcr);
 int      dev_can_write(DEVICE *dev);
 int      offline_or_rewind_dev(DEVICE *dev);
 int      reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
+void     init_dev_wait_timers(DEVICE *dev);
+bool     double_dev_wait_time(DEVICE *dev);
 
 
 /* Get info about device */
@@ -115,15 +117,15 @@ int      dev_is_tape(DEVICE *dev);
 /* From device.c */
 int      open_device(DEVICE *dev);
 int      fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void _lock_device(char *file, int line, DEVICE *dev);
-void _unlock_device(char *file, int line, DEVICE *dev);
-void _block_device(char *file, int line, DEVICE *dev, int state);
-void _unblock_device(char *file, int line, DEVICE *dev);
-void _steal_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state);
-void _give_back_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
-void set_new_volume_parameters(JCR *jcr, DEVICE *dev);
-void set_new_file_parameters(JCR *jcr, DEVICE *dev); 
-int  device_is_unmounted(DEVICE *dev);
+void     _lock_device(char *file, int line, DEVICE *dev);
+void     _unlock_device(char *file, int line, DEVICE *dev);
+void     _block_device(char *file, int line, DEVICE *dev, int state);
+void     _unblock_device(char *file, int line, DEVICE *dev);
+void     _steal_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state);
+void     _give_back_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
+void     set_new_volume_parameters(JCR *jcr, DEVICE *dev);
+void     set_new_file_parameters(JCR *jcr, DEVICE *dev); 
+int      device_is_unmounted(DEVICE *dev);
 
 /* From dircmd.c */
 void     *connection_request(void *arg); 
@@ -161,6 +163,7 @@ bool     match_set_eof(BSR *bsr, DEV_RECORD *rec);
 int      mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release);
 int      mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
 void     release_volume(JCR *jcr, DEVICE *dev);
+void     mark_volume_in_error(JCR *jcr, DEVICE *dev);
 
 /* From autochanger.c */
 int      autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
@@ -178,13 +181,13 @@ void     free_vol_list(JCR *jcr);
 void     create_vol_list(JCR *jcr);
 
 /* From record.c */
-char   *FI_to_ascii(int fi);
-char   *stream_to_ascii(int stream, int fi);
-int     write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int     can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int     read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); 
+char    *FI_to_ascii(int fi);
+char    *stream_to_ascii(int stream, int fi);
+int      write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int      can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int      read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); 
 DEV_RECORD *new_record();
-void    free_record(DEV_RECORD *rec);
+void     free_record(DEV_RECORD *rec);
 
 /* From read_record.c */
 int read_records(JCR *jcr,  DEVICE *dev, 
index b9dbce14b688ca2a92ca79aad26144a068e93f09..a50611ddc66c5d90a73cbbd1f7e0d1b017ea126f 100644 (file)
@@ -76,17 +76,17 @@ int status_cmd(JCR *jcr)
     * List devices
     */
    LockRes();
-   for (device=NULL;  (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) {
+   foreach_res(device, R_DEVICE) {
       for (dev=device->dev; dev; dev=dev->next) {
-        if (dev->state & ST_OPENED) {
-           if (dev->state & ST_LABEL) {
-               bnet_fsend(user, _("Device %s is mounted with Volume \"%s\"\n"), 
+        if (dev_state(dev, ST_OPENED)) {
+           if (dev_state(dev, ST_LABEL)) {
+               bnet_fsend(user, _("Device \"%s\" is mounted with Volume \"%s\"\n"), 
                  dev_name(dev), dev->VolHdr.VolName);
            } else {
-               bnet_fsend(user, _("Device %s open but no Bacula volume is mounted.\n"), dev_name(dev));
+               bnet_fsend(user, _("Device \"%s\" open but no Bacula volume is mounted.\n"), dev_name(dev));
            }
            send_blocked_status(jcr, dev);
-           if (dev->state & ST_APPEND) {
+           if (dev_state(dev, ST_APPEND)) {
               bpb = dev->VolCatInfo.VolCatBlocks;
               if (bpb <= 0) {
                  bpb = 1;
@@ -116,7 +116,7 @@ int status_cmd(JCR *jcr)
               edit_uint64_with_commas(dev->block_num, b2));
 
         } else {
-            bnet_fsend(user, _("Device %s is not open.\n"), dev_name(dev));
+            bnet_fsend(user, _("Device \"%s\" is not open.\n"), dev_name(dev));
            send_blocked_status(jcr, dev);
         }
       }
@@ -132,7 +132,7 @@ int status_cmd(JCR *jcr)
            job_type_to_str(jcr->JobType), jcr->Job);
       }
       if (jcr->device) {
-         bnet_fsend(user, _("%s %s job %s using Volume \"%s\" on device %s\n"), 
+         bnet_fsend(user, _("%s %s job %s using Volume \"%s\" on device \"%s\"\n"), 
                   job_level_to_str(jcr->JobLevel),
                   job_type_to_str(jcr->JobType),
                   jcr->Job,
index 918dafba5ea7c289dc70b461e06703f616093208..f2006f339d6dea4db11409c12bbf588239417a9e 100644 (file)
@@ -105,6 +105,7 @@ static struct res_items dev_items[] = {
    {"maximumchangerwait",    store_pint,   ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
    {"maximumopenwait",       store_pint,   ITEM(res_dev.max_open_wait), 0, ITEM_DEFAULT, 5 * 60},
    {"maximumopenvolumes",    store_pint,   ITEM(res_dev.max_open_vols), 0, ITEM_DEFAULT, 1},
+   {"volumepollinterval",    store_time,   ITEM(res_dev.vol_poll_interval), 0, 0, 0},
    {"offlineonunmount",      store_yesno,  ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
    {"maximumrewindwait",     store_pint,   ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, 5 * 60},
    {"minimumblocksize",      store_pint,   ITEM(res_dev.min_block_size), 0, 0, 0},
index 7cf81d72d8e0a936c1631d07eb7923030c832ebe..7540e06215b44c7a8e67e9633d683e216df018a2 100644 (file)
@@ -83,6 +83,7 @@ struct DEVRES {
    uint32_t min_block_size;           /* min block size */
    uint32_t max_block_size;           /* max block size */
    uint32_t max_volume_jobs;          /* max jobs to put on one volume */
+   utime_t  vol_poll_interval;        /* interval between polling volume during mount */
    int64_t max_volume_files;          /* max files to put on one volume */
    int64_t max_volume_size;           /* max bytes to put on one volume */
    int64_t max_file_size;             /* max file size in bytes */
index b10fbc0fc4bc32df3b0dd3940de1d24dabc23459..8946634f62a4ed6f5bdbbee5667d2b5c1833d462 100644 (file)
@@ -2,8 +2,8 @@
 #undef  VERSION
 #define VERSION "1.33"
 #define VSTRING "1"
-#define BDATE   "06 Jan 2004"
-#define LSMDATE "06Jan04"
+#define BDATE   "10 Jan 2004"
+#define LSMDATE "10Jan04"
 
 /* Debug flags */
 #undef  DEBUG