General:
 01Jun07
+kes  Implement algorithm to handle only one appendable volume with
+     Prefer Mounted Volumes = no.
 kes  Fix a Bacula PostgreSQL bug dereferencing a NULL pointer      
      returned from a query.
 kes  Make volume lock recursive.
 
     int n;
     int32_t InChanger;
 
-    if (bnet_recv(dir) <= 0) {
+    if (dir->recv() <= 0) {
        Dmsg0(200, "getvolname error bnet_recv\n");
        Mmsg(jcr->errmsg, _("Network error on bnet_recv in req_vol_info.\n"));
        return false;
     P(vol_info_mutex);
     bstrncpy(dcr->VolCatInfo.VolCatName, dcr->VolumeName, sizeof(dcr->VolCatInfo.VolCatName));
     bash_spaces(dcr->VolCatInfo.VolCatName);
-    bnet_fsend(dir, Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName,
+    dir->fsend(Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName,
        writing==GET_VOL_INFO_FOR_WRITE?1:0);
     Dmsg1(100, ">dird: %s", dir->msg);
     unbash_spaces(dcr->VolCatInfo.VolCatName);
  * Returns: true  on success dcr->VolumeName is volume
  *                reserve_volume() called on Volume name
  *          false on failure dcr->VolumeName[0] == 0
+ *                also sets dcr->volume_in_use if at least one 
+ *                in use volume was found.
  *
  *          Volume information returned in dcr
  *
      */
     lock_reservations();
     P(vol_info_mutex);
+    dcr->volume_in_use = false;
     for (int vol_index=1;  vol_index < 20; vol_index++) {
        bash_spaces(dcr->media_type);
        bash_spaces(dcr->pool_name);
-       bnet_fsend(dir, Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type);
+       dir->fsend(Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type);
        unbash_spaces(dcr->media_type);
        unbash_spaces(dcr->pool_name);
        Dmsg1(100, ">dird: %s", dir->msg);
              break;
           } else {
              Dmsg1(100, "Volume %s is in use.\n", dcr->VolumeName);
+             dcr->volume_in_use = true;
              continue;
           }
        } else {
 
    bool reserved_device;              /* set if reserve done */
    bool any_volume;                   /* Any OK for dir_find_next... */
    bool attached_to_dev;              /* set when attached to dev */
+   bool volume_in_use;                /* set in dir_find_next_appendable_volume() */
    uint32_t VolFirstIndex;            /* First file index this Volume */
    uint32_t VolLastIndex;             /* Last file index this Volume */
    uint32_t FileIndex;                /* Current File Index */
 
 
    if (dev->vol == NULL) {
       Dmsg2(dbglvl, "JobId=%u vol_unused: no vol on %s\n", (int)dcr->jcr->JobId, dev->print_name());
-      debug_list_volumes("null return unreserve_volume");
+      debug_list_volumes("null vol cannot unreserve_volume");
       return false;
    }
 
    if (dev->is_busy()) {
       Dmsg2(dbglvl, "JobId=%u vol_unused: no vol on %s\n", (int)dcr->jcr->JobId, dev->print_name());
-      debug_list_volumes("dev busy return unreserve_volume");
+      debug_list_volumes("dev busy cannot unreserve_volume");
       return false;
    }
 
          rctx.device_name = device_name;
          stat = search_res_for_device(rctx); 
          if (stat == 1) {             /* found available device */
-            Dmsg2(dbglvl, "JobId=%u Suitable device found=%s\n", (int)rctx.jcr->JobId, 
+            Dmsg2(dbglvl, "JobId=%u available device found=%s\n", (int)rctx.jcr->JobId, 
                   device_name);
             ok = true;
             break;
             Dmsg1(dbglvl, "JobId=%u No next volume found\n", (int)rctx.jcr->JobId);
             rctx.have_volume = false;
             rctx.VolumeName[0] = 0;
-        }
+            /*
+             * If there is at least one volume that is valid and in use,
+             *   but we get here, check if we are running with prefers
+             *   non-mounted drives.  In that case, we have selected a
+             *   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) {
+               rctx.PreferMountedVols = true;
+               goto bail_out;
+            }
+         }
       }
       ok = reserve_device_for_append(dcr, rctx);
       if (ok) {
       }
    }
    if (!ok) {
-      rctx.have_volume = false;
-      free_dcr(dcr);
-      Dmsg1(dbglvl, "JobId=%u Not OK.\n", (int)rctx.jcr->JobId);
-      return 0;
+      goto bail_out;
    }
-   POOL_MEM dev_name;
    if (rctx.notify_dir) {
+      POOL_MEM dev_name;
       BSOCK *dir = rctx.jcr->dir_bsock;
       pm_strcpy(dev_name, rctx.device->hdr.name);
       bash_spaces(dev_name);
       ok = true;
    }
    return ok ? 1 : -1;
+
+bail_out:
+   rctx.have_volume = false;
+   free_dcr(dcr);
+   Dmsg1(dbglvl, "JobId=%u Not OK.\n", (int)rctx.jcr->JobId);
+   return 0;
 }
 
 /*
 
 
 General:
 01Jun07
+kes  Implement algorithm to handle only one appendable volume with
+     Prefer Mounted Volumes = no.
 kes  Fix a Bacula PostgreSQL bug dereferencing a NULL pointer      
      returned from a query.
 kes  Make volume lock recursive.