]> git.sur5r.net Git - bacula/bacula/commitdiff
Massive cleanup of recycling code
authorKern Sibbald <kern@sibbald.com>
Thu, 18 Sep 2003 12:20:21 +0000 (12:20 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 18 Sep 2003 12:20:21 +0000 (12:20 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@706 91ce42f0-d328-0410-95d8-f526ca767f89

14 files changed:
bacula/ReleaseNotes
bacula/kernstodo
bacula/src/dird/catreq.c
bacula/src/dird/job.c
bacula/src/dird/next_vol.c
bacula/src/dird/protos.h
bacula/src/dird/recycle.c
bacula/src/dird/ua_cmds.c
bacula/src/lib/watchdog.c
bacula/src/stored/acquire.c
bacula/src/stored/dircmd.c
bacula/src/stored/job.c
bacula/src/stored/mount.c
bacula/src/version.h

index c12647cb8c727f1e7ac1ef4abdd3b3e70744c596..06950566b75577a35c82508a418d9354a96a80a8 100644 (file)
@@ -15,6 +15,8 @@ Major Changes this Release:
 - Implemented Include | and < in File daemon.
 - Implemented a new Include/Exclude syntax.
 - Lots of fixes with variable expansion and counter variables
+- Automatic labeling of tape Volumes is fixed.
+- Recycling has been completely restructured and should work.
 
 
 Other Changes this Release:
index 47d11af8bf3cade4b8b7a7048d220ebd61f897fd..e7acbe60c17c1d86bd91e58b0f328b28f8633452 100644 (file)
@@ -1,5 +1,5 @@
                  Kern's ToDo List
-                16 September 2003 
+                18 September 2003 
 
 Documentation to do: (any release a little bit at a time)
 - Document running a test version.
@@ -32,15 +32,16 @@ For 1.32 Testing/Documentation:
 - Add test of exclusion, test multiple Include {} statements.
                 
 For 1.32:
+- Add multiple character duration qualifiers.
 - Enhance "update slots" to include a "scan" feature
   scan 1; scan 1-5; scan 1,2,4 ...  to update the catalog 
 - Allow a slot or range of slots on the label barcodes command.
 - Don't print "Warning: Wrong Volume mounted ..." if mounting second volume.
 
 
-
-
 For 1.33
+- Do a complete audit of all pthreads_mutex, cond, ... to ensure that
+  any that are dynamically initialized are destroyed when no longer used.
 - Write a mini-readline with history and editing.
 - Look at how fuser works and /proc/PID/fd that is how Nic found the
   file descriptor leak in Bacula.
@@ -919,4 +920,5 @@ Done: (see kernsdone for more)
   a block and a record.
 - LabelFormat on tape volume apparently creates the db record but 
   never actually labels the volume.
+- Recycling a volume when two jobs are using it is going to break. Fixed.
 
index 4fd0e049a8dbf5171a2b57f6fa06223026a44845..05f7f1e8841f92caae7fc5c5e52a25a9423f3940 100644 (file)
@@ -82,7 +82,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
     */
    Dmsg1(200, "catreq %s", bs->msg);
    if (sscanf(bs->msg, Find_media, &Job, &index) == 2) {
-      ok = find_next_volume_for_append(jcr, &mr, TRUE /*create*/);
+      ok = find_next_volume_for_append(jcr, &mr, TRUE /*permit create new vol*/);
       /*
        * Send Find Media response to Storage daemon 
        */
@@ -112,14 +112,16 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
        */
       unbash_spaces(mr.VolumeName);
       if (db_get_media_record(jcr, jcr->db, &mr)) {
-        bool VolSuitable = false;
-         char *reason = "";           /* detailed reason for rejection */
+        char *reason = NULL;         /* detailed reason for rejection */
         jcr->MediaId = mr.MediaId;
          Dmsg1(120, "VolumeInfo MediaId=%d\n", jcr->MediaId);
         pm_strcpy(&jcr->VolumeName, mr.VolumeName);
-        if (!writing) {
-           VolSuitable = true;        /* accept anything for read */
-        } else {
+        /*                   
+         * If we are reading, accept any volume (reason == NULL)
+         * If we are writing, check if the Volume is valid 
+         *   for this job, and do a recycle if necessary
+         */ 
+        if (writing) {
            /* 
             * SD wants to write this Volume, so make
             *   sure it is suitable for this job, i.e.
@@ -128,63 +130,26 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
             */
            if (mr.PoolId != jcr->PoolId) {
                reason = "not in Pool";
-            } else if (strcmp(mr.VolStatus, "Append") != 0 &&
-                       strcmp(mr.VolStatus, "Recycle") != 0 &&
-                       strcmp(mr.VolStatus, "Purged") != 0) {
-               reason = "not Append, Purged or Recycle";
-               /* What we're trying to do here is see if the current volume is
-                * "recycleable" - ie. if we prune all expired jobs off it, is
-               * it now possible to reuse it for the job that it is currently
-               * needed for?
-               */
-              if ((mr.LastWritten + mr.VolRetention) < (utime_t)time(NULL)
-                    && mr.Recycle && jcr->pool->recycle_current_volume   
-                     && (strcmp(mr.VolStatus, "Full") == 0 ||
-                        strcmp(mr.VolStatus, "Used") == 0)) {
-                 /*
-                  * Attempt prune of current volume to see if we can
-                  * recycle it for use.
-                  */
-                 UAContext *ua;
-
-                 ua = new_ua_context(jcr);
-                 ok = prune_volume(ua, &mr);
-                 free_ua_context(ua);
-
-                 if (ok) {
-                    /* If fully purged, recycle current volume */
-                    if (recycle_volume(jcr, &mr)) {
-                        Jmsg(jcr, M_INFO, 0, "Recycled current "
-                              "volume \"%s\"\n", mr.VolumeName);
-                       VolSuitable = true;
-                    } else {
-                        reason = "not Append, Purged or Recycle (recycling of the "
-                           "current volume failed)";
-                    }
-                 } else {
-                     reason = "not Append, Purged or Recycle (cannot automatically "
-                        "recycle current volume, as it still contains "
-                        "unpruned data)";
-                 }
-              }
            } else if (strcmp(mr.MediaType, jcr->store->media_type) != 0) {
                reason = "not correct MediaType";
-           } else if (!jcr->pool->accept_any_volume) {
-               reason = "Volume not in sequence";
-            } else if (strcmp(mr.VolStatus, "Purged") == 0) {
-              if (recycle_volume(jcr, &mr)) {
-                  Jmsg(jcr, M_INFO, 0, "Recycled current "
-                       "volume \"%s\"\n", mr.VolumeName);
-                 VolSuitable = true;
-              } else {
-                  /* In principle this shouldn't happen */
-                  reason = "recycling of current volume failed";
-              }
            } else {
-              VolSuitable = true;
+             /* 
+              * ****FIXME*** 
+              *   This test (accept_any_volume) is turned off
+               *   because it doesn't properly check if the volume
+              *   really is out of sequence!
+              *
+              * } else if (!jcr->pool->accept_any_volume) {
+               *    reason = "Volume not in sequence";
+              */
+
+              /* 
+               * Now try recycling if necessary
+               */
+              is_volume_valid_or_recyclable(jcr, &mr, &reason);
            }
         }
-        if (VolSuitable) {
+        if (reason == NULL) {
            char ed1[50], ed2[50], ed3[50];
            /*
             * Send Find Media response to Storage daemon 
@@ -199,8 +164,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
             Dmsg2(100, "Vol Info for %s: %s", jcr->Job, bs->msg);
         } else { 
            /* Not suitable volume */
-            bnet_fsend(bs, "1998 Volume \"%s\" %s.\n",
-              mr.VolumeName, reason);
+            bnet_fsend(bs, "1998 Volume \"%s\" %s.\n", mr.VolumeName, reason);
         }
 
       } else {
@@ -210,7 +174,8 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
    
    /*
     * Request to update Media record. Comes typically at the end
-    *  of a Storage daemon Job Session
+    *  of a Storage daemon Job Session or when labeling/relabeling a
+    *  Volume.
     */
    } else if (sscanf(bs->msg, Update_media, &Job, &sdmr.VolumeName, &sdmr.VolJobs,
       &sdmr.VolFiles, &sdmr.VolBlocks, &sdmr.VolBytes, &sdmr.VolMounts, &sdmr.VolErrors,
@@ -252,47 +217,17 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
       mr.Slot = sdmr.Slot;
 
       /*     
-       * Update Media Record
+       * Apply expiration periods and limits, if not a label request,
+       *   and ignore status because if !label we won't use it.
        */
-
-      /* Check limits and expirations if "Append" and not a lable request */
-      if (strcmp(mr.VolStatus, "Append") == 0 && !label) {
-        /* First handle Max Volume Bytes */
-        if ((mr.MaxVolBytes > 0 && mr.VolBytes >= mr.MaxVolBytes)) {
-            Jmsg(jcr, M_INFO, 0, _("Max Volume bytes exceeded. "             
-                "Marking Volume \"%s\" as Full.\n"), mr.VolumeName);
-            strcpy(mr.VolStatus, "Full");
-
-        /* Now see if Volume should only be used once */
-        } else if (mr.VolBytes > 0 && jcr->pool->use_volume_once) {
-            Jmsg(jcr, M_INFO, 0, _("Volume used once. "             
-                "Marking Volume \"%s\" as Used.\n"), mr.VolumeName);
-            strcpy(mr.VolStatus, "Used");
-
-        /* Now see if Max Jobs written to volume */
-        } else if (mr.MaxVolJobs > 0 && mr.MaxVolJobs <= mr.VolJobs) {
-            Jmsg(jcr, M_INFO, 0, _("Max Volume jobs exceeded. "       
-                "Marking Volume \"%s\" as Used.\n"), mr.VolumeName);
-            strcpy(mr.VolStatus, "Used");
-
-        /* Now see if Max Files written to volume */
-        } else if (mr.MaxVolFiles > 0 && mr.MaxVolFiles <= mr.VolFiles) {
-            Jmsg(jcr, M_INFO, 0, _("Max Volume files exceeded. "       
-                "Marking Volume \"%s\" as Used.\n"), mr.VolumeName);
-            strcpy(mr.VolStatus, "Used");
-
-        /* Finally, check Use duration expiration */
-        } else if (mr.VolUseDuration > 0) {
-           utime_t now = time(NULL);
-           /* See if Vol Use has expired */
-           if (mr.VolUseDuration <= (now - mr.FirstWritten)) {
-               Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. "       
-                  "Marking Volume \"%s\"as Used.\n"), mr.VolumeName);
-               strcpy(mr.VolStatus, "Used");  /* yes, mark as used */
-           }
-        }
+      if (!label) {
+        has_volume_expired(jcr, &mr);
       }
+
       Dmsg2(200, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName);
+      /*
+       * Write the modified record to the DB
+       */
       if (db_update_media_record(jcr, jcr->db, &mr)) {
         bnet_fsend(bs, OK_update);
          Dmsg0(190, "send OK\n");
index 2878a9e6346c1a3e0a542561a945242c46288f9a..1827194306ef0319d7d2d2d3d833beba7da4e4a5 100644 (file)
@@ -381,6 +381,7 @@ void dird_free_jcr(JCR *jcr)
       free_pool_memory(jcr->client_uname);
       jcr->client_uname = NULL;
    }
+   pthread_cond_destroy(&jcr->term_wait);
    Dmsg0(200, "End dird free_jcr\n");
 }
 
index d16f042fb4e7d4d013e8c623988b6e2c8daffb1d..043fd1ac93ad646d07b9e53c5630432b3853a7bf 100644 (file)
@@ -96,19 +96,11 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int create)
            }
         }
       }
-      /* Check if use duration applies, then if it has expired */
       Dmsg2(100, "VolJobs=%d FirstWritten=%d\n", mr->VolJobs, mr->FirstWritten);
-      if (ok && mr->VolJobs > 0 && mr->VolUseDuration > 0 && 
-           strcmp(mr->VolStatus, "Append") == 0) {
-        utime_t now = time(NULL);
-        if (mr->VolUseDuration <= (now - mr->FirstWritten)) {
-           ok = FALSE;
-            Dmsg4(100, "Duration=%d now=%d start=%d now-start=%d\n",
-              (int)mr->VolUseDuration, (int)now, (int)mr->FirstWritten, 
-              (int)(now-mr->FirstWritten));
-            Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. "       
-               "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
-            strcpy(mr->VolStatus, "Used");  /* yes, mark as used */
+      if (ok) {
+        /* If we can use the volume, check if it is expired */
+        if (has_volume_expired(jcr, mr)) {
+           /* Need to update media */
            if (!db_update_media_record(jcr, jcr->db, mr)) {
                Jmsg(jcr, M_ERROR, 0, _("Catalog error updating volume \"%s\". ERR=%s"),
                    mr->VolumeName, db_strerror(jcr->db));
@@ -126,3 +118,136 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int create)
    db_unlock(jcr->db);
    return ok;
 }
+
+/*
+ * Check if any time limits or use limits have expired
+ *   if so, set the VolStatus appropriately.
+ */
+bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr)
+{
+   bool expired = false;
+   /*
+    * Check limits and expirations if "Append" and it has been used
+    * i.e. mr->VolJobs > 0
+    *
+    */
+   if (strcmp(mr->VolStatus, "Append") == 0 && mr->VolJobs > 0) {
+      /* First handle Max Volume Bytes */
+      if ((mr->MaxVolBytes > 0 && mr->VolBytes >= mr->MaxVolBytes)) {
+         Jmsg(jcr, M_INFO, 0, _("Max Volume bytes exceeded. "             
+             "Marking Volume \"%s\" as Full.\n"), mr->VolumeName);
+         bstrncpy(mr->VolStatus, "Full", sizeof(mr->VolStatus));
+        expired = true;
+
+      /* Now see if Volume should only be used once */
+      } else if (mr->VolBytes > 0 && jcr->pool->use_volume_once) {
+         Jmsg(jcr, M_INFO, 0, _("Volume used once. "             
+             "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
+         bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
+        expired = true;
+
+      /* Now see if Max Jobs written to volume */
+      } else if (mr->MaxVolJobs > 0 && mr->MaxVolJobs <= mr->VolJobs) {
+         Jmsg(jcr, M_INFO, 0, _("Max Volume jobs exceeded. "       
+             "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
+         bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
+        expired = true;
+
+      /* Now see if Max Files written to volume */
+      } else if (mr->MaxVolFiles > 0 && mr->MaxVolFiles <= mr->VolFiles) {
+         Jmsg(jcr, M_INFO, 0, _("Max Volume files exceeded. "       
+             "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
+         bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
+        expired = true;
+
+      /* Finally, check Use duration expiration */
+      } else if (mr->VolUseDuration > 0) {
+        utime_t now = time(NULL);
+        /* See if Vol Use has expired */
+        if (mr->VolUseDuration <= (now - mr->FirstWritten)) {
+            Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. "       
+               "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
+            bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
+           expired = true;
+        }
+      }
+   }
+   return expired;
+}
+
+/*
+ * Try hard to recycle the current volume
+ *
+ *  Returns: on failure - reason = NULL
+ *          on success - reason - pointer to reason
+ */
+bool is_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, char **reason)
+{
+   int ok;
+
+   *reason = NULL;
+
+   /*  Check if a duration or limit has expired */
+   has_volume_expired(jcr, mr);
+
+   /*
+    * Now see if we can use the volume as is
+    */
+   if (strcmp(mr->VolStatus, "Append") == 0 ||
+       strcmp(mr->VolStatus, "Recycle") == 0) {
+      return true;
+   }
+                                                                                       
+   /*
+    * Check if the Volume is alreay marked for recycling
+    */
+   if (strcmp(mr->VolStatus, "Purged") == 0) {
+      if (recycle_volume(jcr, mr)) {
+         Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName);
+        return true;
+      } else {
+         /* In principle this shouldn't happen */
+         *reason = "recycling of current volume failed";
+        return false;
+      }
+   }
+                                                                                       
+   /* At this point, the volume is not valid for writing */
+   *reason = "not Append, Purged or Recycle";
+                                                                                       
+   /*
+    * What we're trying to do here is see if the current volume is
+    * "recyclable" - ie. if we prune all expired jobs off it, is
+    * it now possible to reuse it for the job that it is currently
+    * needed for?
+    */
+   if ((mr->LastWritten + mr->VolRetention) < (utime_t)time(NULL)
+        && mr->Recycle && jcr->pool->recycle_current_volume
+         && (strcmp(mr->VolStatus, "Full") == 0 ||
+            strcmp(mr->VolStatus, "Used") == 0)) {
+      /*
+       * Attempt prune of current volume to see if we can
+       * recycle it for use.
+       */
+      UAContext *ua;
+                                                                                       
+      ua = new_ua_context(jcr);
+      ok = prune_volume(ua, mr);
+      free_ua_context(ua);
+                                                                                       
+      if (ok) {
+        /* If fully purged, recycle current volume */
+        if (recycle_volume(jcr, mr)) {
+            Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName);
+           return true;               /* Good volume */
+        } else {
+            *reason = "not Append, Purged or Recycle (recycling of the "
+               "current volume failed)";
+        }
+      } else {
+         *reason = "not Append, Purged or Recycle (cannot automatically "
+            "recycle current volume, as it still contains unpruned data)";
+      }
+   }
+   return *reason ? false : true;
+}
index e54713823d9115ecb57e6b9ee1030d8e642c1ffe..a4b48609dec3bebc46cb4fb83b121f3f49063c0a 100644 (file)
@@ -101,6 +101,8 @@ extern void wait_for_storage_daemon_termination(JCR *jcr);
 
 /* next_vol.c */
 int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int create);
+bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr);
+bool is_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, char **reason);
 
 /* newvol.c */
 int newVolume(JCR *jcr, MEDIA_DBR *mr);
index 591888121aacad6866bcb4d5556d0a3baaa43954..9e5b4fce0ecfca079200d8a270092e4f64beeb27 100644 (file)
@@ -114,7 +114,7 @@ int recycle_volume(JCR *jcr, MEDIA_DBR *mr)
 {
    bstrncpy(mr->VolStatus, "Recycle", sizeof(mr->VolStatus));
    mr->VolJobs = mr->VolFiles = mr->VolBlocks = mr->VolErrors = 0;
-   mr->VolBytes = 0;
+   mr->VolBytes = 1;
    mr->FirstWritten = mr->LastWritten = 0;
    return db_update_media_record(jcr, jcr->db, mr);
 }
index 1be992423343c2cfb096ca7c88b2726bd2e0baad..7acb0d12161b10f20675e2c27c4143f3a2317004 100644 (file)
@@ -821,12 +821,12 @@ static int update_volume(UAContext *ua)
       N_("Recycle"),                  /* 6 */
       NULL };
 
-   if (!select_media_dbr(ua, &mr)) {
-      return 0;
-   }
    for (int i=0; kw[i]; i++) {
       int j;
       if ((j=find_arg_with_value(ua, kw[i])) > 0) {
+        if (!select_media_dbr(ua, &mr)) {
+           return 0;
+        }
         switch (i) {
         case 0:
            update_volstatus(ua, ua->argv[j], &mr);
index 002207641faeb1d5418bb614f1b204c16c6943ff..93ba92cee1114bfa5cc5f836ce72b42974d8306b 100755 (executable)
@@ -75,8 +75,6 @@ int start_watchdog(void)
    watchdog_time = time(NULL);
    quit = FALSE;
    if ((stat = pthread_create(&wdid, NULL, btimer_thread, (void *)NULL)) != 0) {
-      pthread_mutex_destroy(&mutex);
-      pthread_cond_destroy(&timer);
       return stat;
    }
    return 0;
index 48fe3ecaa89f4aab39e83a3a2fa7e544de09a03b..940b0171f2ee86fa8830a101f295f5aa8507f66e 100644 (file)
@@ -161,10 +161,11 @@ get_out:
  *   multiple devices (for files), thus we have our own mutex 
  *   on top of the device mutex.
  */
-DEVICE * acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 {
    int release = 0;
-   int do_mount = 0;
+   bool recycle = false;
+   bool do_mount = false;
    DEVICE *rtn_dev = NULL;
 
    if (device_is_unmounted(dev)) {
@@ -218,8 +219,20 @@ DEVICE * acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
         }
         /* Wrong tape mounted, release it, then fall through to get correct one */
         release = 1;
-        do_mount = 1;
-      }
+        do_mount = true;
+      } else {
+        /*       
+         * At this point, the correct tape is already mounted, so 
+         *   we do not need to do mount_next_write_volume(), unless
+         *   we need to recycle the tape.
+         */
+          recycle = strcmp(jcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
+         if (recycle && dev->num_writers != 0) {
+             Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
+                  " because it is in use by another job."));
+            goto get_out;
+         }
+       }
    } else { 
       /* Not already in append mode, so mount the device */
       if (dev->state & ST_READ) {
@@ -227,10 +240,10 @@ DEVICE * acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
         goto get_out;
       } 
       ASSERT(dev->num_writers == 0);
-      do_mount = 1;
+      do_mount = true;
    }
 
-   if (do_mount) {
+   if (do_mount || recycle) {
       if (!mount_next_write_volume(jcr, dev, block, release)) {
          Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
            dev_name(dev));
@@ -239,16 +252,16 @@ DEVICE * acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
    }
 
    dev->num_writers++;
-   if (dev->num_writers > 1) {
-      Dmsg2(100, "Hey!!!! There are %d writers on device %s\n", dev->num_writers,
-        dev_name(dev));
-   }
    if (jcr->NumVolumes == 0) {
       jcr->NumVolumes = 1;
    }
    attach_jcr_to_device(dev, jcr);    /* attach jcr to device */
    rtn_dev = dev;                    /* return device */
 
+/*
+ * If we jump here, it is an error return because
+ *  rtn_dev will still be NULL
+ */
 get_out:
    P(dev->mutex); 
    unblock_device(dev);
index ec67d19976067ea31d1bda0e5169129e1f0f0945..91a6ac3c174e95ed1e6da0112aa501ba2e85f8b9 100644 (file)
@@ -387,7 +387,7 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
    case VOL_OK:
       if (!relabel) {
         bnet_fsend(dir, _(
-            "3911 Cannot label Volume because it is already labeled: %s\n"), 
+            "3911 Cannot label Volume because it is already labeled: \"%s\"\n"), 
             dev->VolHdr.VolName);
         break;
       }
@@ -520,7 +520,7 @@ static int mount_cmd(JCR *jcr)
                  dev->dev_name, dev->VolHdr.VolName);
            } else {
                bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
-                                 "Try unmounting and remounting the Volume.\n"),
+                                 "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
                          dev->dev_name);
            }
            break;
@@ -541,7 +541,7 @@ static int mount_cmd(JCR *jcr)
                     dev->dev_name, dev->VolHdr.VolName);
               } else {
                   bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"   
-                                 "Try unmounting and remounting the Volume.\n"),
+                                 "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
                             dev->dev_name);
               }
            } else {
@@ -560,7 +560,7 @@ static int mount_cmd(JCR *jcr)
                     dev->dev_name, dev->VolHdr.VolName);
               } else {
                   bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
-                                    "Try unmounting and remounting the Volume.\n"),
+                                    "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
                             dev->dev_name);
               }
            }
index 3a8d3a211249a8dd468f2574c90b2610cf760f4f..37f732732b471936044e83cf46c872fb9dcbcd8b 100644 (file)
@@ -376,6 +376,6 @@ void stored_free_jcr(JCR *jcr)
    if (jcr->next_dev && jcr->prev_dev) {
       Emsg0(M_FATAL, 0, _("In free_jcr(), but still attached to device!!!!\n"));
    }
-                     
+   pthread_cond_destroy(&jcr->job_start_wait);
    return;
 }
index 0e2bcb6a9a6355ec2034261f1b3432a1cad09ac8..4d45f4e384c0466f9b9871766cf0e9acf1b8de12 100644 (file)
  *
  * This routine returns a 0 only if it is REALLY
  *  impossible to get the requested Volume.
+ *
+ *    *****FIXME****** handle "Recycle" volume ******
  */
 int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release)
 {
-   int recycle, ask, retry = 0, autochanger;
+   int retry = 0, autochanger;
+   bool ask, recycle;
 
    Dmsg0(100, "Enter mount_next_volume()\n");
 
@@ -60,11 +63,12 @@ mount_next_vol:
       Jmsg(jcr, M_FATAL, 0, _("Job canceled.\n"));
       return 0;
    }
-   recycle = ask = autochanger = 0;
+   autochanger = 0;
+   recycle = ask = false;
    if (release) {
       Dmsg0(100, "mount_next_volume release=1\n");
       release_volume(jcr, dev);
-      ask = 1;                       /* ask operator to mount tape */
+      ask = true;                    /* ask operator to mount tape */
    }
 
    /* 
@@ -107,7 +111,7 @@ mount_next_vol:
        *   we will err, recurse and ask the operator the next time.
        */
       if (autochanger || (!release && dev_is_tape(dev) && dev_cap(dev, CAP_AUTOMOUNT))) {
-         ask = 0;                     /* don't ask SYSOP this time */
+         ask = false;                 /* don't ask SYSOP this time */
       }
 
       release = 1;                    /* release next time if we "recurse" */
@@ -149,6 +153,8 @@ read_volume:
       } else {
         vol_label_status = read_dev_volume_label(jcr, dev, block);
       }
+      Dmsg2(100, "dirVol=%s dirStat=%s\n", jcr->VolumeName,
+        jcr->VolCatInfo.VolCatStatus);
       /*
        * At this point, dev->VolCatInfo has what is in the drive, if anything,
        *         and   jcr->VolCatInfo has what the Director wants.
@@ -157,9 +163,7 @@ read_volume:
       case VOL_OK:
          Dmsg1(100, "Vol OK name=%s\n", jcr->VolumeName);
         memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(jcr->VolCatInfo));
-         if (strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0) {
-           recycle = 1;
-        }
+         recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
         break;                    /* got a Volume */
       case VOL_NAME_ERROR:
         VOLUME_CAT_INFO VolCatInfo;
@@ -171,7 +175,7 @@ read_volume:
          *  this volume is really OK. If not, put back the desired
          *  volume name and continue.
          */
-        memcpy(&VolCatInfo, &jcr->VolCatInfo, sizeof(jcr->VolCatInfo));
+        memcpy(&VolCatInfo, &jcr->VolCatInfo, sizeof(VolCatInfo));
         /* 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)) {
@@ -186,9 +190,7 @@ read_volume:
         }
          Dmsg1(100, "want new name=%s\n", jcr->VolumeName);
         memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(dev->VolCatInfo));
-         if (strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0) {
-           recycle = 1;
-        }
+         recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
         break;                /* got a Volume */
       /*
        * At this point, we assume we have a blank tape mounted.
@@ -198,8 +200,11 @@ read_volume:
         /* 
          * If permitted, we label the device, make sure we can do
          *   it by checking that the VolCatBytes is zero => not labeled. 
+         * As noted above, at this point jcr->VolCatInfo has what
+         *   the Director wants and dev->VolCatInfo has info on the
+         *   previous tape (or nothing).
          */
-        if (dev_cap(dev, CAP_LABEL) && dev->VolCatInfo.VolCatBytes == 0) {
+        if (dev_cap(dev, CAP_LABEL) && jcr->VolCatInfo.VolCatBytes == 0) {
             Dmsg0(100, "Create volume label\n");
            if (!write_volume_label_to_dev(jcr, (DEVRES *)dev->device, jcr->VolumeName,
                   jcr->pool_name)) {
@@ -207,6 +212,7 @@ read_volume:
               goto mount_next_vol;
            }
             Dmsg0(200, "dir_update_vol_info. Set Append\n");
+            /* Copy Director's info into the device info */
            memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(dev->VolCatInfo));
            dir_update_volume_info(jcr, &dev->VolCatInfo, 1);  /* indicate tape labeled */
             Jmsg(jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"),
@@ -220,14 +226,14 @@ mount_error:
         /* Send error message */
          Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);                         
          Dmsg0(100, "Default\n");
-        ask = 1;
+        ask = true;
         goto ask_again;
       }
       break;
    }
 
    /* 
-    * See if we have a fresh tape or tape with data.
+    * See if we have a fresh tape or tape with data.
     *
     * Note, if the LabelType is PRE_LABEL, it was labeled
     *  but never written. If so, rewrite the label but set as
@@ -277,7 +283,7 @@ mount_error:
       /* Set or reset Volume statistics */
       dev->VolCatInfo.VolCatJobs = 0;
       dev->VolCatInfo.VolCatFiles = 0;
-      dev->VolCatInfo.VolCatBytes = 0;
+      dev->VolCatInfo.VolCatBytes = 1;
       dev->VolCatInfo.VolCatErrors = 0;
       dev->VolCatInfo.VolCatBlocks = 0;
       dev->VolCatInfo.VolCatRBytes = 0;
@@ -291,6 +297,7 @@ mount_error:
         dev->VolCatInfo.VolCatReads = 1;
       }
       Dmsg0(200, "dir_update_vol_info. Set Append\n");
+      bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus));
       dir_update_volume_info(jcr, &dev->VolCatInfo, 1);  /* indicate doing relabel */
       if (recycle) {
          Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\" on device %s, all previous data lost.\n"),
@@ -314,7 +321,7 @@ mount_error:
            dev_name(dev), strerror_dev(dev));
          Jmsg(jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"),
            jcr->VolumeName);
-         strcpy(dev->VolCatInfo.VolCatStatus, "Error");
+         bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus));
          Dmsg0(200, "dir_update_vol_info. Set Error.\n");
         dir_update_volume_info(jcr, &dev->VolCatInfo, 0);
         goto mount_next_vol;
@@ -332,7 +339,7 @@ mount_error:
             Jmsg(jcr, M_ERROR, 0, _("I canot write on this volume because:\n\
 The number of files mismatch! Volume=%u Catalog=%u\n"), 
                 dev_file(dev), dev->VolCatInfo.VolCatFiles);
-            strcpy(dev->VolCatInfo.VolCatStatus, "Error");
+            bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus));
             Dmsg0(200, "dir_update_vol_info. Set Error.\n");
            dir_update_volume_info(jcr, &dev->VolCatInfo, 0);
            goto mount_next_vol;
index f3d18549351fcd645013e3564815792e0b108a4f..4c1c968022f79119eb0ab4a76070725d5b6b674c 100644 (file)
@@ -2,8 +2,8 @@
 #undef  VERSION
 #define VERSION "1.32"
 #define VSTRING "1"
-#define BDATE   "16 Sep 2003"
-#define LSMDATE "16Sep03"
+#define BDATE   "18 Sep 2003"
+#define LSMDATE "18Sep03"
 
 /* Debug flags */
 #undef  DEBUG