]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Generally clean up the manual tape loading code. The main
authorKern Sibbald <kern@sibbald.com>
Mon, 30 Jun 2008 12:56:49 +0000 (12:56 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 30 Jun 2008 12:56:49 +0000 (12:56 +0000)
     conceptial change is that when a volume is marked to be unloaded,
     its volume name is retained, and it is only marked as unloaded
     when either the autoloader says it is unloaded or another tape
     is read on that drive.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/branches/Branch-2.4@7263 91ce42f0-d328-0410-95d8-f526ca767f89

17 files changed:
bacula/src/dird/autoprune.c
bacula/src/dird/pythondir.c
bacula/src/filed/job.c
bacula/src/filed/pythonfd.c
bacula/src/lib/jcr.c
bacula/src/stored/acquire.c
bacula/src/stored/authenticate.c
bacula/src/stored/autochanger.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/label.c
bacula/src/stored/mount.c
bacula/src/stored/pythonsd.c
bacula/src/stored/reserve.c
bacula/src/stored/wait.c
bacula/src/version.h
bacula/technotes-2.3

index df4cb5542db2150b1a15cf77cc5269423a87f35a..38aab4f4a5b1d13a97020d7541bf19a850ba5a8f 100644 (file)
@@ -190,7 +190,7 @@ bool prune_volumes(JCR *jcr, bool InChanger, MEDIA_DBR *mr)
           */
          if (ok && lmr.PoolId == mr->PoolId) {
             Dmsg2(050, "Vol=%s MediaId=%d purged.\n", lmr.VolumeName, (int)lmr.MediaId);
-            mr = &lmr;                    /* struct copy */
+            memcpy(mr, &lmr, sizeof(lmr));
             break;                        /* got a volume */
          }
          /*
index c17606e2f4a6697b061aab4dd0e9b4f9a3013eca..60a2fe250337c2aedf3d2d5a120acb10e7044b45 100644 (file)
@@ -67,7 +67,7 @@ PyMethodDef JobMethods[] = {
 
 struct s_vars {
    const char *name;
-   char *fmt;
+   const char *fmt;
 };
 
 /* Read-only variables */
index d54a476b3d854e26b86c2e0dc694d841687ec52e..944d2f5547d0687edb0947a9b66f7559be219c5b 100644 (file)
@@ -1140,7 +1140,7 @@ static int bootstrap_cmd(JCR *jcr)
    }
 
    while (bnet_recv(dir) >= 0) {
-       Dmsg1(200, "filed<dird: bootstrap file %s\n", dir->msg);
+       Dmsg1(200, "filed<dird: bootstrap: %s", dir->msg);
        fputs(dir->msg, bs);
    }
    fclose(bs);
index 130f494e115e46ae02016c1fb31f5e344d371d9d..be6f185dd533b86b90faa8aa4df131337c50d1a2 100644 (file)
@@ -72,7 +72,7 @@ ssize_t my_python_read(BFILE *bfd, void *buf, size_t count);
 
 struct s_vars {
    const char *name;
-   char *fmt;
+   const char *fmt;
 };
 
 /* Read-only variables */
index 3032fc037e8699efbe6cc1282f0f6111e63daadf..3ce86e23f4bde13d7cff019a99ec51ba731fd413 100644 (file)
@@ -600,7 +600,7 @@ void set_jcr_job_status(JCR *jcr, int JobStatus)
     * For a set of errors, ... keep the current status
     *   so it isn't lost. For all others, set it.
     */
-   Dmsg2(100, "OnEntry JobStatus=%c set=%c\n", jcr->JobStatus, JobStatus);
+   Dmsg2(200, "OnEntry JobStatus=%c set=%c\n", jcr->JobStatus, JobStatus);
    switch (jcr->JobStatus) {
    case JS_ErrorTerminated:
    case JS_FatalError:
@@ -620,7 +620,7 @@ void set_jcr_job_status(JCR *jcr, int JobStatus)
    default:
       jcr->JobStatus = JobStatus;
    }
-   Dmsg2(100, "OnExit JobStatus=%c set=%c\n", jcr->JobStatus, JobStatus);
+   Dmsg2(200, "OnExit JobStatus=%c set=%c\n", jcr->JobStatus, JobStatus);
 }
 
 #ifdef TRACE_JCR_CHAIN
index 55489403b994e1d84657c9a7956355bba6c83d68..42f15bd7655cb48cf62840d6abf3693ea2d73da6 100644 (file)
@@ -70,6 +70,7 @@ bool acquire_device_for_read(DCR *dcr)
          dev->num_writers, jcr->JobId);
       goto get_out;
    }
+   dev->clear_unload();
 
    /* Find next Volume, if any */
    vol = jcr->VolList;
@@ -194,8 +195,10 @@ bool acquire_device_for_read(DCR *dcr)
 
 
    /* Volume info is always needed because of VolParts */
-   Dmsg0(200, "dir_get_volume_info\n");
+   Dmsg1(150, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
    if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
+      Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n", 
+         dcr->VolumeName, jcr->errmsg);
       Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
    }
    dev->set_load();                /* set to load volume */
@@ -236,7 +239,7 @@ bool acquire_device_for_read(DCR *dcr)
       switch (vol_label_status) {
       case VOL_OK:
          ok = true;
-         memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
+         dev->VolCatInfo = dcr->VolCatInfo;     /* structure assignment */
          break;                    /* got it */
       case VOL_IO_ERROR:
          /*
@@ -249,20 +252,20 @@ bool acquire_device_for_read(DCR *dcr)
          }
          goto default_path;
       case VOL_NAME_ERROR:
-         if (tape_initially_mounted) {
-            tape_initially_mounted = false;
-            goto default_path;
-         }
-         /* If polling and got a previous bad name, ignore it */
-         if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) {
+         if (dev->is_volume_to_unload()) {
             goto default_path;
-         } else {
-             bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName));
          }
+//       if (tape_initially_mounted) {
+            tape_initially_mounted = false;
+//          goto default_path;
+//       }
+         dev->set_unload();              /* force unload of unwanted tape */
          if (!unload_autochanger(dcr, -1)) {
             /* at least free the device so we can re-open with correct volume */
             dev->close();                                                          
          }
+         dev->set_load();
+         ASSERT(0);
          /* Fall through */
       default:
          Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
@@ -288,7 +291,6 @@ default_path:
             }
             /* Try closing and re-opening */
             dev->close();
-            dev->clear_unload();
             if (dev->open(dcr, OPEN_READ_ONLY) >= 0) {
                continue;
             }
@@ -308,6 +310,7 @@ default_path:
       } /* end switch */
       break;
    } /* end for loop */
+
    if (!ok) {
       Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s for reading.\n"),
             dev->print_name());
@@ -370,6 +373,8 @@ DCR *acquire_device_for_append(DCR *dcr)
       goto get_out;
    }
 
+   dev->clear_unload();
+
    /*
     * have_vol defines whether or not mount_next_write_volume should
     *   ask the Director again about what Volume to use.
index 49f6551fc54a719ea13dc57fcca3043620736c58..0d2d9390a56f8608a52cb3ca9b7fb702c6e91509 100644 (file)
@@ -60,13 +60,13 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
 
    if (rcode != R_DIRECTOR) {
       Dmsg1(dbglvl, "I only authenticate Directors, not %d\n", rcode);
-      Emsg1(M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode);
+      Jmsg1(jcr, M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode);
       return 0;
    }
    if (bs->msglen < 25 || bs->msglen > 500) {
       Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n",
             bs->who(), bs->msglen);
-      Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
+      Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
             bs->who(), bs->msglen);
       return 0;
    }
@@ -77,7 +77,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
       bs->msg[100] = 0;
       Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n",
             bs->who(), bs->msg);
-      Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
+      Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
             bs->who(), bs->msg);
       return 0;
    }
@@ -90,7 +90,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
    if (!director) {
       Dmsg2(dbglvl, "Connection from unknown Director %s at %s rejected.\n",
             dirname, bs->who());
-      Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
+      Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
             dirname, bs->who());
       free_pool_memory(dirname);
@@ -123,7 +123,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
    }
 
    if (!auth_success) {
-      Emsg0(M_FATAL, 0, _("Incorrect password given by Director.\n"
+      Jmsg0(jcr, M_FATAL, 0, _("Incorrect password given by Director.\n"
        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
       auth_success = false;
       goto auth_fatal;
@@ -131,7 +131,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
 
    /* Verify that the remote host is willing to meet our TLS requirements */
    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
-      Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not" 
+      Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
            " advertise required TLS support.\n"));
       auth_success = false;
       goto auth_fatal;
@@ -139,7 +139,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
 
    /* Verify that we are willing to meet the remote host's requirements */
    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
-      Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
+      Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
       auth_success = false;
       goto auth_fatal;
    }
@@ -147,7 +147,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
       /* Engage TLS! Full Speed Ahead! */
       if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
-         Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
+         Jmsg0(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
          auth_success = false;
          goto auth_fatal;
       }
@@ -179,7 +179,7 @@ int authenticate_director(JCR *jcr)
    if (!authenticate(R_DIRECTOR, dir, jcr)) {
       dir->fsend("%s", Dir_sorry);
       Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who());
-      Emsg1(M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
+      Jmsg1(jcr, M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
       bmicrosleep(5, 0);
       return 0;
    }
index 6bb750d95ce7b4d3f8f38fcb555ae276821ed606..a8afe572c411b1d7b9146664c226b9955d11a83f 100644 (file)
@@ -377,7 +377,9 @@ bool unload_autochanger(DCR *dcr, int loaded)
       free_volume(dev);            /* Free any volume associated with this drive */
       free_pool_memory(changer);
    }
-   dev->clear_unload();
+   if (ok) {
+      dev->clear_unload();
+   }
    return ok;
 }
 
@@ -495,7 +497,9 @@ bool unload_dev(DCR *dcr, DEVICE *dev)
       Dmsg2(100, "Slot %d unloaded %s\n", dev->get_slot(), dev->print_name());
       dev->set_slot(0);           /* nothing loaded */
    }
-   dev->clear_unload();
+   if (ok) {
+      dev->clear_unload();
+   }
    unlock_changer(dcr);
 
    dev->dunlock();
index 7d11452cccadf9408db13cefbb7be23195085510..c6f90465089f2cfa13bc7602e927ea984b8d1fcf 100644 (file)
@@ -1829,6 +1829,16 @@ void DEVICE::clrerror(int func)
 #endif
 }
 
+/*
+ * Set to unload the current volume in the drive
+ */
+void DEVICE::set_unload()
+{
+   if (!m_unload && VolHdr.VolumeName[0] != 0) {
+       m_unload = true;
+       memcpy(UnloadVolName, VolHdr.VolumeName, sizeof(UnloadVolName));
+   }
+}
 
 /*
  * Clear volume header
@@ -2379,7 +2389,6 @@ void init_device_wait_timers(DCR *dcr)
    dev->rem_wait_sec = dev->wait_sec;
    dev->num_wait = 0;
    dev->poll = false;
-   dev->BadVolName[0] = 0;
 
    jcr->min_wait = 60 * 60;
    jcr->max_wait = 24 * 60 * 60;
index fbfa735b687ba7294f50a8dbe0a1fc76fe719600..ca2968fddbfa49e95b6a482b2b7d3eae40be7ddd 100644 (file)
@@ -279,9 +279,10 @@ public:
    char pool_name[MAX_NAME_LENGTH];   /* pool name */
    char pool_type[MAX_NAME_LENGTH];   /* pool type */
 
-   /* Device wait times ***FIXME*** look at durations */
-   char BadVolName[MAX_NAME_LENGTH];  /* Last wrong Volume mounted */
+   char UnloadVolName[MAX_NAME_LENGTH];  /* Last wrong Volume mounted */
    bool poll;                         /* set to poll Volume */
+
+   /* Device wait times ***FIXME*** look at durations */
    int min_wait;
    int max_wait;
    int max_num_wait;
@@ -363,7 +364,8 @@ public:
    void set_part_spooled(int val) { if (val) state |= ST_PART_SPOOLED; \
           else state &= ~ST_PART_SPOOLED;
    };
-   void set_unload() { m_unload = true; };
+   bool is_volume_to_unload() const { \
+      return m_unload && strcmp(VolHdr.VolumeName, UnloadVolName) == 0; };
    void set_load() { m_load = true; };
    void inc_reserved() { m_num_reserved++; }
    void set_mounted(int val) { if (val) state |= ST_MOUNTED; \
@@ -380,13 +382,14 @@ public:
    void clear_media() { state &= ~ST_MEDIA; };
    void clear_short_block() { state &= ~ST_SHORT; };
    void clear_freespace_ok() { state &= ~ST_FREESPACE_OK; };
-   void clear_unload() { m_unload = false; };
+   void clear_unload() { m_unload = false; UnloadVolName[0] = 0; };
    void clear_load() { m_load = false; };
    char *bstrerror(void) { return errmsg; };
    char *print_errmsg() { return errmsg; };
    int32_t get_slot() const { return m_slot; };
 
 
+   void set_unload();            /* in dev.c */
    void clear_volhdr();          /* in dev.c */
    void close();                 /* in dev.c */
    void close_part(DCR *dcr);    /* in dev.c */
@@ -533,6 +536,7 @@ public:
    void mark_volume_in_error();
    void mark_volume_not_inchanger();
    int try_autolabel(bool opened);
+   bool find_a_volume();
    bool is_suitable_volume_mounted();
    bool is_eod_valid();
    int check_volume_label(bool &ask, bool &autochanger);
index d5c981bbd674d1a926c270003b36442284c87a9a..da90a41fb0f626e900ed8c820377319f102afb03 100644 (file)
@@ -168,6 +168,10 @@ int read_dev_volume_label(DCR *dcr)
    }
    free_record(record);               /* finished reading Volume record */
 
+   if (!dev->is_volume_to_unload()) {
+      dev->clear_unload();
+   }
+
    if (!ok) {
       if (forge_on || jcr->ignore_label_errors) {
          dev->set_labeled();         /* set has Bacula label */
@@ -212,15 +216,6 @@ int read_dev_volume_label(DCR *dcr)
    }
 
    dev->set_labeled();               /* set has Bacula label */
-   Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName);
-   Dmsg2(100, "=== dcr->dev=%p dev=%p\n", dcr->dev, dev);
-   if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) {
-      Mmsg2(jcr->errmsg, _("Could not reserve volume %s on %s\n"),
-           dev->VolHdr.VolumeName, dev->print_name());
-      stat = VOL_NAME_ERROR;
-      goto bail_out;
-   }
-   Dmsg2(100, "=== dcr->dev=%p dev=%p\n", dcr->dev, dev);
 
    /* Compare Volume Names */
    Dmsg2(130, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolumeName);
@@ -237,10 +232,9 @@ int read_dev_volume_label(DCR *dcr)
       }
       Dmsg0(150, "return VOL_NAME_ERROR\n");
       stat = VOL_NAME_ERROR;
-      volume_unused(dcr);             /* mark volume "released" */
       goto bail_out;
    }
-   Dmsg1(130, "Copy vol_name=%s\n", dev->VolHdr.VolumeName);
+
 
    if (debug_level >= 10) {
       dump_volume_label(dev);
@@ -253,11 +247,19 @@ int read_dev_volume_label(DCR *dcr)
          stat = read_ansi_ibm_label(dcr);            
          /* If we want a label and didn't find it, return error */
          if (stat != VOL_OK) {
-            volume_unused(dcr);       /* mark volume "released" */
             goto bail_out;
          }
       }
    }
+
+   Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName);
+   if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) {
+      Mmsg2(jcr->errmsg, _("Could not reserve volume %s on %s\n"),
+           dev->VolHdr.VolumeName, dev->print_name());
+      stat = VOL_NAME_ERROR;
+      goto bail_out;
+   }
+
    empty_block(block);
    return VOL_OK;
 
index e4f7cf7ada012f5b9c3887a86a012c98375eee63..b6f0f02e6f0fb51c52528fd15912cf60d113e49a 100644 (file)
@@ -96,6 +96,7 @@ mount_next_vol:
          goto no_lock_bail_out;
       }
       lock_volumes();
+      Dmsg1(150, "Continue after dir_ask_sysop_to_mount. must_load=%d\n", dev->must_load());
    }
    if (job_canceled(jcr)) {
       Jmsg(jcr, M_FATAL, 0, _("Job %d canceled.\n"), jcr->JobId);
@@ -108,34 +109,10 @@ mount_next_vol:
    }
    do_swapping(true /*writing*/);
 
-   if (!is_suitable_volume_mounted()) {
-      bool have_vol = false;
-      /* Do we have a candidate volume? */
-      if (dev->vol) {
-         bstrncpy(VolumeName, dev->vol->vol_name, sizeof(VolumeName));
-         have_vol = dir_get_volume_info(this, GET_VOL_INFO_FOR_WRITE);
-      }
-      /*
-       * Get Director's idea of what tape we should have mounted.
-       *    in dcr->VolCatInfo
-       */
-      if (!have_vol) {
-         Dmsg0(200, "Before dir_find_next_appendable_volume.\n");
-         while (!dir_find_next_appendable_volume(dcr)) {
-            Dmsg0(200, "not dir_find_next\n");
-            if (job_canceled(jcr)) {
-               goto bail_out;
-            }
-            unlock_volumes();
-            if (!dir_ask_sysop_to_create_appendable_volume(dcr)) {
-               goto no_lock_bail_out;
-             }
-             lock_volumes();
-             Dmsg0(200, "Again dir_find_next_append...\n");
-         }
-         goto mount_next_vol;   
-      }
+   if (retry < 2 && !find_a_volume()) {
+      goto no_lock_bail_out;
    }
+
    if (job_canceled(jcr)) {
       goto bail_out;
    }
@@ -169,21 +146,21 @@ mount_next_vol:
     *   we will fail, recurse and ask the operator the next time.
     */
    if (!dev->must_unload() && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) {
-      Dmsg0(150, "(1)Ask=0\n");
+      Dmsg0(250, "(1)Ask=0\n");
       ask = false;                 /* don't ask SYSOP this time */
    }
    /* Don't ask if not removable */
    if (!dev->is_removable()) {
-      Dmsg0(150, "(2)Ask=0\n");
+      Dmsg0(250, "(2)Ask=0\n");
       ask = false;
    }
-   Dmsg2(150, "Ask=%d autochanger=%d\n", ask, autochanger);
+   Dmsg2(250, "Ask=%d autochanger=%d\n", ask, autochanger);
 
    if (ask) {
       unlock_volumes();
       if (!dir_ask_sysop_to_mount_volume(dcr, ST_APPEND)) {
          Dmsg0(150, "Error return ask_sysop ...\n");
-         goto no_lock_bail_out;  /* error return */
+         goto no_lock_bail_out;
       }
       lock_volumes();
    }
@@ -229,30 +206,22 @@ mount_next_vol:
       if (try_autolabel(false) == try_read_vol) {
          break;                       /* created a new volume label */
       }
+      Dmsg0(50, "set_unload\n");
       dev->set_unload();              /* force ask sysop */
       ask = true;
+      Dmsg0(150, "goto mount_next_vol\n");
       goto mount_next_vol;
-#ifdef xxx
-      /* If DVD, ignore the error, very often you cannot open the device
-       * (when there is no DVD, or when the one inserted is a wrong one) */
-      if (dev->poll || dev->is_dvd()) {
-         goto mount_next_vol;
-      } else {
-         Jmsg2(jcr, M_ERROR, 0, _("Could not open device %s: ERR=%s\n"),
-            dev->print_name(), dev->print_errmsg());
-         goto bail_out;
-      }
-#endif 
    }
 
    /*
     * Now check the volume label to make sure we have the right tape mounted
     */
 read_volume:
-
    switch (check_volume_label(ask, autochanger)) {
    case check_next_vol:
+      Dmsg0(50, "set_unload\n");
       dev->set_unload();                 /* want a different Volume */
+      Dmsg0(150, "goto mount_next_vol\n");
       goto mount_next_vol;
    case check_read_vol:
       goto read_volume;
@@ -298,6 +267,7 @@ read_volume:
          goto mount_next_vol;
       }
       if (!is_eod_valid()) {
+         Dmsg0(150, "goto mount_next_vol\n");
          goto mount_next_vol;
       }
 
@@ -324,6 +294,45 @@ no_lock_bail_out:
    return false;
 }
 
+/*
+ * This routine is meant to be called once the first pass
+ *   to ensure that we have a candidate volume to mount.
+ *   Otherwise, we ask the sysop to created one.
+ */
+bool DCR::find_a_volume()  
+{
+   DCR *dcr = this;
+   if (!is_suitable_volume_mounted()) {
+      bool have_vol = false;
+      /* Do we have a candidate volume? */
+      if (dev->vol) {
+         bstrncpy(VolumeName, dev->vol->vol_name, sizeof(VolumeName));
+         have_vol = dir_get_volume_info(this, GET_VOL_INFO_FOR_WRITE);
+      }
+      /*
+       * Get Director's idea of what tape we should have mounted.
+       *    in dcr->VolCatInfo
+       */
+      if (!have_vol) {
+         Dmsg0(200, "Before dir_find_next_appendable_volume.\n");
+         while (!dir_find_next_appendable_volume(dcr)) {
+            Dmsg0(200, "not dir_find_next\n");
+            if (job_canceled(jcr)) {
+               unlock_volumes();
+               return false;
+            }
+            unlock_volumes();
+            if (!dir_ask_sysop_to_create_appendable_volume(dcr)) {
+               return false;
+             }
+             lock_volumes();
+             Dmsg0(150, "Again dir_find_next_append...\n");
+         }
+      }
+   }
+   return true;
+}
+
 int DCR::check_volume_label(bool &ask, bool &autochanger)
 {
    int vol_label_status;
@@ -357,6 +366,12 @@ int DCR::check_volume_label(bool &ask, bool &autochanger)
       VOLUME_CAT_INFO dcrVolCatInfo, devVolCatInfo;
       char saveVolumeName[MAX_NAME_LENGTH];
 
+      Dmsg1(150, "Vol NAME Error Name=%s\n", VolumeName);
+      if (dev->is_volume_to_unload()) {
+         ask = true;
+         goto check_next_volume;
+      }
+
       /* If not removable, Volume is broken */
       if (!dev->is_removable()) {
          Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
@@ -365,13 +380,6 @@ int DCR::check_volume_label(bool &ask, bool &autochanger)
          goto check_next_volume;
       }
 
-      Dmsg1(150, "Vol NAME Error Name=%s\n", VolumeName);
-      /* If polling and got a previous bad name, ignore it */
-      if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) {
-         ask = true;
-         Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n", VolumeName);
-         goto check_next_volume;
-      }
       /*
        * OK, we got a different volume mounted. First save the
        *  requested Volume info (dcr) structure, then query if
@@ -398,7 +406,7 @@ int DCR::check_volume_label(bool &ask, bool &autochanger)
             mark_volume_not_inchanger();
          }
          dev->VolCatInfo = devVolCatInfo;    /* structure assignment */
-         bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName));
+         dev->set_unload();                  /* unload this volume */
          Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n"
               "    Current Volume \"%s\" not acceptable because:\n"
               "    %s"),
@@ -416,6 +424,13 @@ int DCR::check_volume_label(bool &ask, bool &autochanger)
        */
       Dmsg1(150, "Got new Volume name=%s\n", VolumeName);
       dev->VolCatInfo = VolCatInfo;   /* structure assignment */
+      Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName);
+      if (reserve_volume(this, dev->VolHdr.VolumeName) == NULL) {
+         Jmsg2(jcr, M_WARNING, 0, _("Could not reserve volume %s on %s\n"),
+            dev->VolHdr.VolumeName, dev->print_name());
+         ask = true;
+         goto check_next_volume;
+      }
       break;                /* got a Volume */
    /*
     * At this point, we assume we have a blank tape mounted.
@@ -483,9 +498,8 @@ bool DCR::is_suitable_volume_mounted()
 void DCR::do_swapping(bool is_writing)
 {
    if (dev->must_unload()) {
-      Dmsg1(100, "swapping: unloading %s\n", dev->print_name());
+      Dmsg1(100, "must_unload release %s\n", dev->print_name());
       release_volume();
-      dev->clear_unload();
    }
    /*
     * See if we are asked to swap the Volume from another device
@@ -509,7 +523,7 @@ void DCR::do_swapping(bool is_writing)
       dev->swap_dev = NULL;
    }
    if (dev->must_load()) {
-      Dmsg1(100, "swapping: must load %s\n", dev->print_name());
+      Dmsg1(100, "Must load %s\n", dev->print_name());
       if (autoload_device(this, is_writing, NULL) > 0) {
          dev->clear_load();
       }
@@ -653,6 +667,7 @@ void DCR::mark_volume_in_error()
    Dmsg0(150, "dir_update_vol_info. Set Error.\n");
    dir_update_volume_info(this, false, false);
    volume_unused(this);
+   Dmsg0(50, "set_unload\n");
    dev->set_unload();                 /* must get a new volume */
 }
 
@@ -691,7 +706,6 @@ void DCR::release_volume()
    dev->block_num = dev->file = 0;
    dev->EndBlock = dev->EndFile = 0;
    memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
-// memset(&VolCatInfo, 0, sizeof(VolCatInfo));
    dev->clear_volhdr();
    /* Force re-read of label */
    dev->clear_labeled();
@@ -708,7 +722,8 @@ void DCR::release_volume()
    if (dev->is_open()) {
       dev->offline_or_rewind();
    }
-   dev->set_unload();
+// Dmsg0(50, "set_unload\n");
+// dev->set_unload();
    Dmsg0(190, "release_volume\n");
 }
 
index 9bcfc1b8f40e6c067110be682f28465009772831..1db1aa5423addbcbf5101b678efd67b6c55c9ea0 100644 (file)
@@ -59,7 +59,7 @@ PyMethodDef JobMethods[] = {
 
 struct s_vars {
    const char *name;
-   char *fmt;
+   const char *fmt;
 };
 
 static struct s_vars getvars[] = {
index 175062fc14f3fb3f492ccc30f2d1226448e96e84..929ba8e86a4ece2e2c480c01affa7fa2ad0f1f1a 100644 (file)
@@ -349,7 +349,6 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
          }
          Dmsg3(dbglvl, "jid=%u reserve_vol free vol=%s at %p\n", jid(), vol->vol_name, vol->vol_name);
          free_volume(dev);
-//       volume_unused(dcr);
          dev->set_unload();             /* have to unload current volume */
          debug_list_volumes("reserve_vol free");
       }
@@ -390,7 +389,6 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
             Dmsg4(dbglvl, "==== jid=%u Swap vol=%s from dev=%s to %s\n", jid(),
                VolumeName, vol->dev->print_name(), dev->print_name());
             free_volume(dev);            /* free any volume attached to our drive */
-//          volume_unused(dcr);
             dev->set_unload();           /* Unload any volume that is on our drive */
             dcr->dev = vol->dev;         /* temp point to other dev */
             slot = get_autochanger_loaded_slot(dcr);  /* get slot on other drive */
index 53fa5eba0f73a7658390238a7cbfca87fd7fa32d..b443fd335fd291ca171689cd46738b64174efa61 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
index 4d29dc13dc448883126d893e45e53ed61a7a59e0..02f67816baa617d288a694096c072d34bf034d1d 100644 (file)
@@ -4,8 +4,8 @@
 
 #undef  VERSION
 #define VERSION "2.4.1"
-#define BDATE   "26 June 2008"
-#define LSMDATE "26Jun08"
+#define BDATE   "30 June 2008"
+#define LSMDATE "30Jun08"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2008 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2008"       /* year for copyright messages in progs */
index a379e5efd45e8cd51d043a6b59e493308f96592c..0c9738126271916189ad1d2df8c4e326d76aa744 100644 (file)
@@ -1,6 +1,12 @@
               Technical notes on version 2.2
 
 General:
+27Jun08
+kes  Generally clean up the manual tape loading code. The main
+     conceptial change is that when a volume is marked to be unloaded,
+     its volume name is retained, and it is only marked as unloaded
+     when either the autoloader says it is unloaded or another tape
+     is read on that drive.
 26Jun08
 kes  Fix a recycling problem with two autochangers reported in bug
      #1106. This may also (unlikely) fix a second recycling bug as