]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/reserve.c
Tweak debug msgs
[bacula/bacula] / bacula / src / stored / reserve.c
index 249754148914b440e0586713e7750a032312e7d0..8d92efc5346fbac06e0395cdbc03f89f9ebb0c68 100644 (file)
@@ -53,7 +53,7 @@ static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
 static bool use_storage_cmd(JCR *jcr);
 static void queue_reserve_message(JCR *jcr);
 static void pop_reserve_messages(JCR *jcr);
-void switch_device(DCR *dcr, DEVICE *dev);
+//void switch_device(DCR *dcr, DEVICE *dev);
 
 /* Requests from the Director daemon */
 static char use_storage[]  = "use storage=%127s media_type=%127s "
@@ -178,10 +178,11 @@ static void debug_list_volumes(const char *imsg)
    lock_volumes();
    foreach_dlist(vol, vol_list) {
       if (vol->dev) {
-         Mmsg(msg, "List %s: %s rel=%d on device %s\n", imsg, 
-              vol->vol_name, vol->released, vol->dev->print_name());
+         Mmsg(msg, "List %s: %s in_use=%d on device %s\n", imsg, 
+              vol->vol_name, vol->is_in_use(), vol->dev->print_name());
       } else {
-         Mmsg(msg, "List %s: %s rel=%d no dev\n", imsg, vol->vol_name, vol->released);
+         Mmsg(msg, "List %s: %s in_use=%d no dev\n", imsg, vol->vol_name, 
+              vol->is_in_use());
       }
       Dmsg1(dbglvl, "%s", msg.c_str());
    }
@@ -216,11 +217,13 @@ void list_volumes(void sendit(const char *msg, int len, void *sarg), void *arg)
       if (dev) {
          len = Mmsg(msg, "%s on device %s\n", vol->vol_name, dev->print_name());
          sendit(msg.c_str(), len, arg);
-         len = Mmsg(msg, "    Reader=%d writers=%d reserved=%d released=%d\n", 
-            dev->can_read()?1:0, dev->num_writers, dev->reserved_device, vol->released);
+         len = Mmsg(msg, "    Reader=%d writers=%d devres=%d volinuse=%d\n", 
+            dev->can_read()?1:0, dev->num_writers, dev->num_reserved(),   
+            vol->is_in_use());
          sendit(msg.c_str(), len, arg);
       } else {
-         len = Mmsg(msg, "%s no device. released=%d\n", vol->vol_name, vol->released);
+         len = Mmsg(msg, "%s no device. volinuse= %d\n", vol->vol_name, 
+            vol->is_in_use());
          sendit(msg.c_str(), len, arg);
       }
    }
@@ -257,7 +260,6 @@ static void free_vol_item(VOLRES *vol)
    }
 }
 
-
 /*
  * Put a new Volume entry in the Volume list. This
  *  effectively reserves the volume so that it will
@@ -274,7 +276,7 @@ static void free_vol_item(VOLRES *vol)
  *
  *  1. The Volume list entry must be attached to the drive (rather than 
  *       attached to a job as it currently is. I.e. the drive that "owns" 
- *       the volume (reserved, in use, mounted)
+ *       the volume (in use, mounted)
  *       must point to the volume (still to be maintained in a list).
  *
  *  2. The Volume is entered in the list when a drive is reserved.  
@@ -334,29 +336,29 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
     */
    if (dev->vol) {
       vol = dev->vol;
-      Dmsg4(dbglvl, "Vol attached=%s, newvol=%s release=%d on %s\n",
-         vol->vol_name, VolumeName, vol->released, dev->print_name());
+      Dmsg4(dbglvl, "Vol attached=%s, newvol=%s volinuse=%d on %s\n",
+         vol->vol_name, VolumeName, vol->is_in_use(), dev->print_name());
       /*
        * Make sure we don't remove the current volume we are inserting
        *  because it was probably inserted by another job, or it
-       *  is not being used and is marked as released.
+       *  is not being used and is marked as not reserved.
        */
       if (strcmp(vol->vol_name, VolumeName) == 0) {
-         Dmsg2(dbglvl, "=== set not released vol=%s dev=%s\n", VolumeName,
+         Dmsg2(dbglvl, "=== set reserved vol=%s dev=%s\n", VolumeName,
                vol->dev->print_name());
-         vol->released = false;         /* retake vol if released previously */
+         vol->set_in_use();             /* retake vol if released previously */
          dcr->reserved_volume = true;   /* reserved volume */
          goto get_out;                  /* Volume already on this device */
       } else {
-         /* Don't release a volume if it is in use */
-         if (!vol->released && !dcr->reserved_volume) { 
-            Dmsg1(dbglvl, "Cannot free vol=%s. It is not released.\n", vol->vol_name);
+         /* Don't release a volume if it was reserved by someone other than us */
+         if (vol->is_in_use() && !dcr->reserved_volume) { 
+            Dmsg1(dbglvl, "Cannot free vol=%s. It is reserved.\n", vol->vol_name);
             vol = NULL;                  /* vol in use */
             goto get_out;
          }
          Dmsg2(dbglvl, "reserve_vol free vol=%s at %p\n", vol->vol_name, vol->vol_name);
          free_volume(dev);
-         dcr->unload_device = true;     /* have to unload current volume */
+         dev->set_unload();             /* have to unload current volume */
          debug_list_volumes("reserve_vol free");
       }
    }
@@ -387,25 +389,37 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
       /* Check if we are trying to use the Volume on a different drive */
       if (dev != vol->dev) {
          /* Caller wants to switch Volume to another device */
-         if (!vol->dev->is_busy()) {
-            dcr->swap_dev = vol->dev;   /* remember to get this vol */
+         if (!vol->dev->is_busy() && !vol->is_swapping()) {
+            Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", 
+               VolumeName, vol->dev->print_name(), dev->print_name());
+            free_volume(dev);            /* free any volume attached to our drive */
+            vol->dev->set_unload();      /* unload our drive */
+            vol->set_swapping();         /* swap from other drive */
+            dev->swap_dev = vol->dev;    /* remember to get this vol */
+            vol->dev->set_load();        /* then reload on our drive */
+            vol->dev->vol = NULL;        /* remove volume from other drive */
+            vol->dev = dev;              /* point it at our drive */
+            dev->vol = vol;              /* point our drive at it */
             Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", 
                VolumeName, vol->dev->print_name(), dev->print_name());
          } else {
             Dmsg3(dbglvl, "==== Swap not possible Vol busy vol=%s from dev=%s to %s\n", 
                VolumeName, vol->dev->print_name(), dev->print_name());
-            vol = NULL;                 /* device busy */
+            vol = NULL;                  /* device busy */
             goto get_out;
          }
+      } else {
+         dev->vol = vol;
       }
+   } else {
+      dev->vol = vol;                    /* point to newly inserted volume */
    }
-   dev->vol = vol;
 
 get_out:
    if (vol) {
-      Dmsg2(dbglvl, "=== set not released. vol=%s dev=%s\n", vol->vol_name,
+      Dmsg2(dbglvl, "=== set in_use. vol=%s dev=%s\n", vol->vol_name,
             vol->dev->print_name());
-      vol->released = false;
+      vol->set_in_use();
       dcr->reserved_volume = true;
    }
    debug_list_volumes("end new volume");
@@ -417,6 +431,7 @@ get_out:
  * Switch from current device to given device  
  *   (not yet used) 
  */
+#ifdef xxx
 void switch_device(DCR *dcr, DEVICE *dev)
 {
    DCR save_dcr;
@@ -436,11 +451,11 @@ void switch_device(DCR *dcr, DEVICE *dev)
    bstrncpy(dcr->pool_type, save_dcr.pool_type, sizeof(dcr->pool_type));
    bstrncpy(dcr->dev_name, dev->dev_name, sizeof(dcr->dev_name));
 
-   dev->reserved_device++;
-   dcr->reserved_device = true;
+// dcr->set_reserved();
 
    dev->dunlock();
 }
+#endif
 
 /*
  * Search for a Volume name in the Volume list.
@@ -448,43 +463,56 @@ void switch_device(DCR *dcr, DEVICE *dev)
  *  Returns: VOLRES entry on success
  *           NULL if the Volume is not in the list
  */
-VOLRES *find_volume(DCR *dcr)
+VOLRES *find_volume(const char *VolumeName) 
 {
    VOLRES vol, *fvol;
    /* Do not lock reservations here */
    lock_volumes();
-   vol.vol_name = bstrdup(dcr->VolumeName);
+   vol.vol_name = bstrdup(VolumeName);
    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
    free(vol.vol_name);
-   Dmsg2(dbglvl, "find_vol=%s found=%d\n", dcr->VolumeName, fvol!=NULL);
+   Dmsg2(dbglvl, "find_vol=%s found=%d\n", VolumeName, fvol!=NULL);
    debug_list_volumes("find_volume");
    unlock_volumes();
    return fvol;
 }
 
+void DCR::set_reserved()
+{
+   m_reserved = true;
+   Dmsg2(dbglvl, "Inc reserve=%d dev=%s\n", dev->num_reserved(), dev->print_name());
+   dev->inc_reserved();
+}
+
+void DCR::clear_reserved()
+{
+   if (m_reserved) {
+      m_reserved = false;
+      dev->dec_reserved();
+      Dmsg2(dbglvl, "Dec reserve=%d dev=%s\n", dev->num_reserved(), dev->print_name());
+   }
+}
+
 /* 
  * Remove any reservation from a drive and tell the system
  *  that the volume is unused at least by us.
  */
-void unreserve_device(DCR *dcr)
+void DCR::unreserve_device()
 {
-   DEVICE *dev = dcr->dev;
    lock_volumes();
-   if (dcr->reserved_device) {
-      dcr->reserved_device = false;
-      dcr->reserved_volume = false;
-      dev->reserved_device--;
-      Dmsg2(dbglvl, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
+   if (is_reserved()) {
+      clear_reserved();
+      reserved_volume = false;
       /* If we set read mode in reserving, remove it */
       if (dev->can_read()) {
          dev->clear_read();
       }
       if (dev->num_writers < 0) {
-         Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
+         Jmsg1(jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
          dev->num_writers = 0;
       }
-      if (dev->reserved_device == 0 && dev->num_writers == 0) {
-         volume_unused(dcr);
+      if (dev->num_reserved() == 0 && dev->num_writers == 0) {
+         volume_unused(this);
       }
    }
    unlock_volumes();
@@ -494,7 +522,7 @@ void unreserve_device(DCR *dcr)
  * Free a Volume from the Volume list if it is no longer used
  *   Note, for tape drives we want to remember where the Volume
  *   was when last used, so rather than free the volume entry,
- *   we simply mark it "released" so when the drive is really
+ *   we simply mark it "not reserved" so when the drive is really
  *   needed for another volume, we can reuse it.
  *
  *  Returns: true if the Volume found and "removed" from the list
@@ -504,11 +532,16 @@ bool volume_unused(DCR *dcr)
 {
    DEVICE *dev = dcr->dev;
 
-   if (dev->vol == NULL) {
+   if (!dev->vol) {
       Dmsg1(dbglvl, "vol_unused: no vol on %s\n", dev->print_name());
       debug_list_volumes("null vol cannot unreserve_volume");
       return false;
    }
+   if (dev->vol->is_swapping()) {
+      Dmsg1(dbglvl, "vol_unused: vol being swapped on %s\n", dev->print_name());
+      debug_list_volumes("swapping vol cannot unreserve_volume");
+      return false;
+   }
 
 #ifdef xxx
    if (dev->is_busy()) {
@@ -518,7 +551,7 @@ bool volume_unused(DCR *dcr)
    }
 #endif
 #ifdef xxx
-   if (dev->num_writers > 0 || dev->reserved_device > 0) {
+   if (dev->num_writers > 0 || dev->num_reserved() > 0) {
       ASSERT(0);
    }
 #endif
@@ -529,11 +562,9 @@ bool volume_unused(DCR *dcr)
     *  explicitly read in this drive. This allows the SD to remember
     *  where the tapes are or last were.
     */
-   Dmsg3(dbglvl, "=== mark released vol=%s num_writers=%d dev_reserved=%d\n",
-      dev->vol->vol_name, dev->num_writers, dev->reserved_device);
-   dev->vol->released = true;
-   Dmsg2(dbglvl, "=== set released. Vol=%s dev=%s\n", dev->vol->vol_name,
-         dev->print_name());
+   Dmsg4(dbglvl, "=== set not reserved vol=%s num_writers=%d dev_reserved=%d dev=%s\n",
+      dev->vol->vol_name, dev->num_writers, dev->num_reserved(), dev->print_name());
+   dev->vol->clear_in_use();
    if (dev->is_tape() || dev->is_autochanger()) {
       return true;
    } else {
@@ -599,34 +630,35 @@ void free_volume_list()
    unlock_volumes();
 }
 
-bool is_volume_in_use(DCR *dcr)
+bool DCR::can_i_use_volume()
 {
-   bool rtn = false;
+   bool rtn = true;
    VOLRES *vol;
 
    lock_volumes();
-   vol = find_volume(dcr);
+   vol = find_volume(VolumeName);
    if (!vol) {
-      Dmsg1(dbglvl, "Vol=%s not in use.\n", dcr->VolumeName);
+      Dmsg1(dbglvl, "Vol=%s not in use.\n", VolumeName);
       goto get_out;                   /* vol not in list */
    }
    ASSERT(vol->dev != NULL);
 
-   if (dcr->dev == vol->dev) {        /* same device OK */
-      Dmsg1(dbglvl, "Vol=%s on same dev.\n", dcr->VolumeName);
+   if (dev == vol->dev) {        /* same device OK */
+      Dmsg1(dbglvl, "Vol=%s on same dev.\n", VolumeName);
       goto get_out;
    } else {
-      Dmsg3(dbglvl, "Vol=%s on %s we have %s\n", dcr->VolumeName,
-            vol->dev->print_name(), dcr->dev->print_name());
+      Dmsg3(dbglvl, "Vol=%s on %s we have %s\n", VolumeName,
+            vol->dev->print_name(), dev->print_name());
    }
+   /* ***FIXME*** check this ... */
    if (!vol->dev->is_busy()) {
-      Dmsg2(dbglvl, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
+      Dmsg2(dbglvl, "Vol=%s dev=%s not busy.\n", VolumeName, vol->dev->print_name());
       goto get_out;
    } else {
-      Dmsg2(dbglvl, "Vol=%s dev=%s busy.\n", dcr->VolumeName, vol->dev->print_name());
+      Dmsg2(dbglvl, "Vol=%s dev=%s busy.\n", VolumeName, vol->dev->print_name());
    }
-   Dmsg2(dbglvl, "Vol=%s in use by %s.\n", dcr->VolumeName, vol->dev->print_name());
-   rtn = true;
+   Dmsg2(dbglvl, "Vol=%s in use by %s.\n", VolumeName, vol->dev->print_name());
+   rtn = false;
 
 get_out:
    unlock_volumes();
@@ -759,9 +791,6 @@ static bool use_storage_cmd(JCR *jcr)
             rctx.PreferMountedVols = false;                
             rctx.exact_match = false;
             rctx.autochanger_only = true;
-            Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
-               rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
-               rctx.autochanger_only, rctx.any_drive);
             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
                break;
             }
@@ -774,9 +803,6 @@ static bool use_storage_cmd(JCR *jcr)
                rctx.try_low_use_drive = false;
             }
             rctx.autochanger_only = false;
-            Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
-               rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
-               rctx.autochanger_only, rctx.any_drive);
             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
                break;
             }
@@ -789,25 +815,16 @@ static bool use_storage_cmd(JCR *jcr)
          rctx.PreferMountedVols = true;
          rctx.exact_match = true;
          rctx.autochanger_only = false;
-         Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
-            rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
-            rctx.autochanger_only, rctx.any_drive);
          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
             break;
          }
          /* Look for any mounted drive */
          rctx.exact_match = false;
-         Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
-            rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
-            rctx.autochanger_only, rctx.any_drive);
          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
             break;
          }
          /* Try any drive */
          rctx.any_drive = true;
-         Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
-            rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
-            rctx.autochanger_only, rctx.any_drive);
          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
             break;
          }
@@ -900,9 +917,9 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
    } else {
       dirstore = jcr->read_store;
    }
-   Dmsg4(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
-      rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
-      rctx.autochanger_only);
+   Dmsg5(dbglvl, "Start find_suit_dev PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
+         rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
+         rctx.autochanger_only, rctx.any_drive);
 
    /* 
     * If the appropriate conditions of this if are met, namely that
@@ -1016,7 +1033,7 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
       debug_list_volumes("=== After free temp table\n");
    }
    if (ok) {
-      Dmsg1(dbglvl, "Usable dev found. Vol=%s from in-use vols list\n", rctx.VolumeName);
+      Dmsg1(dbglvl, "OK dev found. Vol=%s from in-use vols list\n", rctx.VolumeName);
       return true;
    }
 
@@ -1048,7 +1065,9 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
       }
    }
    if (ok) {
-      Dmsg1(dbglvl, "Usable dev found. Vol=%s\n", rctx.VolumeName);
+      Dmsg1(dbglvl, "OK dev found. Vol=%s\n", rctx.VolumeName);
+   } else {
+      Dmsg0(dbglvl, "Leave find_suit_dev: no dev found.\n");
    }
    return ok;
 }
@@ -1078,10 +1097,10 @@ int search_res_for_device(RCTX &rctx)
             /* Debug code */
             if (rctx.store->append == SD_APPEND) {
                Dmsg2(dbglvl, "Device %s reserved=%d for append.\n", 
-                  rctx.device->hdr.name, rctx.jcr->dcr->dev->reserved_device);
+                  rctx.device->hdr.name, rctx.jcr->dcr->dev->num_reserved());
             } else {
                Dmsg2(dbglvl, "Device %s reserved=%d for read.\n", 
-                  rctx.device->hdr.name, rctx.jcr->read_dcr->dev->reserved_device);
+                  rctx.device->hdr.name, rctx.jcr->read_dcr->dev->num_reserved());
             }
             return stat;
          }
@@ -1101,10 +1120,10 @@ int search_res_for_device(RCTX &rctx)
             /* Debug code */
             if (rctx.store->append == SD_APPEND) {
                Dmsg2(dbglvl, "Device %s reserved=%d for append.\n", 
-                  rctx.device->hdr.name, rctx.jcr->dcr->dev->reserved_device);
+                  rctx.device->hdr.name, rctx.jcr->dcr->dev->num_reserved());
             } else {
                Dmsg2(dbglvl, "Device %s reserved=%d for read.\n", 
-                  rctx.device->hdr.name, rctx.jcr->read_dcr->dev->reserved_device);
+                  rctx.device->hdr.name, rctx.jcr->read_dcr->dev->num_reserved());
             }
             return stat;
          }
@@ -1172,7 +1191,7 @@ static int reserve_device(RCTX &rctx)
 
       rctx.jcr->dcr = dcr;
       Dmsg5(dbglvl, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
-               dcr->dev->reserved_device,
+               dcr->dev->num_reserved(),
                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
       Dmsg3(dbglvl, "Vol=%s num_writers=%d, have_vol=%d\n", 
          rctx.VolumeName, dcr->dev->num_writers, rctx.have_volume);
@@ -1202,10 +1221,10 @@ static int reserve_device(RCTX &rctx)
              *   non-used drive and our one and only volume is mounted
              *   elsewhere, so we bail out and retry using that drive.
              */
-            if (dcr->volume_in_use && !rctx.PreferMountedVols) {
+            if (dcr->found_in_use() && !rctx.PreferMountedVols) {
                rctx.PreferMountedVols = true;
                if (dcr->VolumeName[0]) {
-                  unreserve_device(dcr);
+                  dcr->unreserve_device();
                }
                goto bail_out;
             }
@@ -1222,7 +1241,7 @@ static int reserve_device(RCTX &rctx)
              */
             if (dcr->dev->num_writers != 0) {
                if (dcr->VolumeName[0]) {
-                  unreserve_device(dcr);
+                  dcr->unreserve_device();
                }
                goto bail_out;
             }
@@ -1233,7 +1252,7 @@ static int reserve_device(RCTX &rctx)
       if (ok) {
          rctx.jcr->read_dcr = dcr;
          Dmsg5(dbglvl, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
-               dcr->dev->reserved_device,
+               dcr->dev->num_reserved(),
                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
       }
    }
@@ -1287,7 +1306,7 @@ static bool reserve_device_for_read(DCR *dcr)
    if (dev->is_busy()) {
       Dmsg4(dbglvl, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", 
          dev->print_name(),
-         dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
+         dev->state & ST_READ?1:0, dev->num_writers, dev->num_reserved());
       Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
             jcr->JobId, dev->print_name());
       queue_reserve_message(jcr);
@@ -1297,9 +1316,7 @@ static bool reserve_device_for_read(DCR *dcr)
    dev->clear_append();
    dev->set_read();
    ok = true;
-   dev->reserved_device++;
-   Dmsg3(dbglvl, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, dev->print_name(), dev);
-   dcr->reserved_device = true;
+   dcr->set_reserved();
 
 bail_out:
    dev->dunlock();
@@ -1358,10 +1375,7 @@ static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
       goto bail_out;
    }
 
-   dev->reserved_device++;
-   Dmsg3(dbglvl, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, 
-      dev->print_name(), dev);
-   dcr->reserved_device = true;
+   dcr->set_reserved();
    ok = true;
 
 bail_out:
@@ -1385,7 +1399,7 @@ static int is_pool_ok(DCR *dcr)
       Mmsg(jcr->errmsg, _(
 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"), 
             (uint32_t)jcr->JobId, dcr->pool_name, dev->pool_name,
-            dev->reserved_device, dev->print_name());
+            dev->num_reserved(), dev->print_name());
       queue_reserve_message(jcr);
       Dmsg2(dbglvl, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
          dev->pool_name, dcr->pool_name);
@@ -1398,12 +1412,16 @@ static bool is_max_jobs_ok(DCR *dcr)
    DEVICE *dev = dcr->dev;
    JCR *jcr = dcr->jcr;
 
-   Dmsg4(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Vol=%s\n",
+   Dmsg5(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Status=%s Vol=%s\n",
          dcr->VolCatInfo.VolCatMaxJobs,
-         dcr->VolCatInfo.VolCatJobs, dev->reserved_device,
+         dcr->VolCatInfo.VolCatJobs, dev->num_reserved(),
+         dcr->VolCatInfo.VolCatStatus,
          dcr->VolumeName);
+   if (strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0) {
+      return true;
+   }
    if (dcr->VolCatInfo.VolCatMaxJobs > 0 && dcr->VolCatInfo.VolCatMaxJobs <=
-        (dcr->VolCatInfo.VolCatJobs + dev->reserved_device)) {
+        (dcr->VolCatInfo.VolCatJobs + dev->num_reserved())) {
       /* Max Job Vols depassed or already reserved */
       Mmsg(jcr->errmsg, _("3610 JobId=%u Volume max jobs exceeded on drive %s.\n"), 
             (uint32_t)jcr->JobId, dev->print_name());
@@ -1449,13 +1467,13 @@ static int can_reserve_drive(DCR *dcr, RCTX &rctx)
       /* If he wants a free drive, but this one is busy, no go */
       if (!rctx.PreferMountedVols && dev->is_busy()) {
          /* Save least used drive */
-         if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
-            rctx.num_writers = dev->num_writers + dev->reserved_device;
+         if ((dev->num_writers + dev->num_reserved()) < rctx.num_writers) {
+            rctx.num_writers = dev->num_writers + dev->num_reserved();
             rctx.low_use_drive = dev;
             Dmsg2(dbglvl, "set low use drive=%s num_writers=%d\n", 
                dev->print_name(), rctx.num_writers);
          } else {
-            Dmsg1(dbglvl, "not low use num_writers=%d\n", dev->num_writers+dev->reserved_device);
+            Dmsg1(dbglvl, "not low use num_writers=%d\n", dev->num_writers+dev->num_reserved());
          }
          Dmsg0(dbglvl, "failed: !prefMnt && busy.\n");
          Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"), 
@@ -1496,7 +1514,7 @@ static int can_reserve_drive(DCR *dcr, RCTX &rctx)
                   dev->VolHdr.VolumeName, dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
             return 0;
          }
-         if (is_volume_in_use(dcr)) {
+         if (!dcr->can_i_use_volume()) {
             return 0;              /* fail if volume on another drive */
          }
       }
@@ -1517,7 +1535,7 @@ static int can_reserve_drive(DCR *dcr, RCTX &rctx)
     */
    if (dev->num_writers == 0) {
       /* Now check if there are any reservations on the drive */
-      if (dev->reserved_device) {           
+      if (dev->num_reserved()) {           
          return is_pool_ok(dcr);
       } else if (dev->can_append()) {
          if (is_pool_ok(dcr)) {
@@ -1525,6 +1543,7 @@ static int can_reserve_drive(DCR *dcr, RCTX &rctx)
          } else {
             /* Changing pool, unload old tape if any in drive */
             Dmsg0(dbglvl, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
+            /* ***FIXME*** use set_unload() */
             unload_autochanger(dcr, 0);
          }
       }