]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Fix listing performance problems in bat. Pointed out by
authorKern Sibbald <kern@sibbald.com>
Fri, 5 Oct 2007 16:56:55 +0000 (16:56 +0000)
committerKern Sibbald <kern@sibbald.com>
Fri, 5 Oct 2007 16:56:55 +0000 (16:56 +0000)
     Chris Howells.
kes  Remove old debug code.
kes  Fix bat code that tests for Win32. This should fix bug #968
kes  Query 5 list wrong Vol after migration. This fixes bug #960

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@5727 91ce42f0-d328-0410-95d8-f526ca767f89

15 files changed:
bacula/LICENSE
bacula/projects
bacula/src/dird/query.sql
bacula/src/filed/job.c
bacula/src/qt-console/bat.h
bacula/src/qt-console/pages.cpp
bacula/src/qt-console/restore/restore.cpp
bacula/src/qt-console/restore/restoretree.cpp
bacula/src/qt-console/restore/restoretree.h
bacula/src/stored/askdir.c
bacula/src/stored/dev.h
bacula/src/stored/reserve.c
bacula/src/tools/bsmtp.c
bacula/src/version.h
bacula/technotes-2.3

index fea736568ea08ea5089068a4667864b3a4f81592..83f25f9a71befc12fa70053d731ef90743ad3f0c 100644 (file)
@@ -10,21 +10,19 @@ The name Bacula is a registered trademark.
 ===================================
 
 License:
-For the most part, Bacula is licensed under the GPL version 2
-this code is listed under Copyright Free Software Foundation
-Europe e.V. What follows are the addition(s) to the GPL version
-2 license, for code that is copyrighted as noted above.
+For the most part, Bacula is licensed under the GPL version 2 this
+code is listed under Copyright Free Software Foundation Europe e.V.
+What follows is the addition(s) to the GPL version 2 license, that
+applys to code that is copyrighted by the Free Software Foundation
+Europe e.V.
 
 Linking: 
 As a special exception to the GPLv2, the Bacula Project gives
 permission to link the code of its release of Bacula with the OpenSSL
 project's "OpenSSL" library (or with modified versions of it that use
 the same license as the "OpenSSL" library), and distribute the linked
-executables. You must obey the GNU General Public License in all
-respects for all of the code used other than "OpenSSL". If you modify
-a particular file, you may extend this exception to your version of the file,
-but you are not obligated to do so. If you do not wish this exception
-to apply to your code, clearly indicate so in the file.
+executables.  You must obey the GNU General Public License in all
+respects for all of the code used other than "OpenSSL".
              
 ===================================
 
index 6b99f5fc6a5f38f63658549139c3214f03e3a0ea..55820d694657e2c0de750e06e059a36e76cdd197 100644 (file)
@@ -38,7 +38,7 @@ Item 25:  Archival (removal) of User Files to Tape
 Item  1:  Accurate restoration of renamed/deleted files
   Date:   28 November 2005
   Origin: Martin Simmons (martin at lispworks dot com)
-  Status: Robert Nelson will implement this
+  Status: 
 
   What:   When restoring a fileset for a specified date (including "most
           recent"), Bacula should give you exactly the files and directories
index c9f27f9893d60df83fd114671d916b1596368c07..b18f10fd65df9c66b545ae9f74de9bdf56e50c0d 100644 (file)
@@ -56,8 +56,8 @@ SELECT DISTINCT Job.JobId as JobId,Client.Name as Client,
    JobFiles,JobBytes,VolumeName
  FROM Client,Job,JobMedia,Media,FileSet
  WHERE Client.Name='%1'
- AND Client.ClientId=Job.ClientId
- AND JobStatus='T' AND Job.FileSetId=FileSet.FileSetId
+ AND Client.ClientId=Job.ClientId AND Job.Type='B'
+ AND Job.JobStatus='T' AND Job.FileSetId=FileSet.FileSetId
  AND JobMedia.JobId=Job.JobId AND JobMedia.MediaId=Media.MediaId
  ORDER BY Job.StartTime;
 # 6
index d2f5097102cebd50951f933b29f917c71c0bd66e..03c971d8e8e6836282ba75ce4d3425d8b124f64b 100644 (file)
@@ -437,9 +437,6 @@ static int job_cmd(JCR *jcr)
    POOLMEM *sd_auth_key;
 
    sd_auth_key = get_memory(dir->msglen);
-   if (debug_level == 3) {
-      Dmsg1(000, "<dird: %s", dir->msg);
-   }
    if (sscanf(dir->msg, jobcmd,  &jcr->JobId, jcr->Job,
               &jcr->VolSessionId, &jcr->VolSessionTime,
               sd_auth_key) != 5) {
@@ -450,9 +447,6 @@ static int job_cmd(JCR *jcr)
       return 0;
    }
    jcr->sd_auth_key = bstrdup(sd_auth_key);
-   if (debug_level == 3) {
-      Dmsg1(000, "sd_auth_key=%s\n", jcr->sd_auth_key);
-   }
    free_pool_memory(sd_auth_key);
    Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
    return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
index 608b15cc603e465d33404b8491a3dd77aec4ebcb..650f6fec19b4286e2c2a8eca781c5e0837b6b96c 100644 (file)
@@ -48,5 +48,6 @@ extern MainWin *mainWin;
 extern QApplication *app;
 
 int bvsnprintf(char *str, int32_t size, const char *format, va_list ap);
+bool isWin32Path(QString &fullPath);
 
 #endif /* _BAT_H_ */
index 157ea5b253a27f740c531e512eb7c6d06bf2be88..59c5143e59ce7e3122734a99e77aa2c74ba9d85d 100644 (file)
 #include "pages.h"
 #include "bat.h"
 
+/* A global function */
+bool isWin32Path(QString &fullPath) 
+{
+   char *buf = fullPath.left(2).toUtf8().data();
+
+   return buf[1] == ':' && B_ISALPHA(buf[0]);
+}
+
+
 /*
  * dockPage
  * This function is intended to be called from within the Pages class to pull
index 26114225dbe0a8f5e360329d1ef3902d046836e5..73661b4e06a6856e0f8f56ae35e2ab689cacf462 100644 (file)
@@ -181,7 +181,6 @@ void restorePage::addDirectory(QString &newdirr)
 {
    QString newdir = newdirr;
    QString fullpath = m_cwd + newdirr;
-   QRegExp regex("^/[a-z]:/$");
    bool ok = true;
    bool windrive = false;
 
@@ -193,7 +192,7 @@ void restorePage::addDirectory(QString &newdirr)
    }
 
    /* add unix '/' directory first */
-   if (m_dirPaths.empty() && (regex.indexIn(fullpath,0) == -1)) {
+   if (m_dirPaths.empty() && !isWin32Path(fullpath)) {
       QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
       item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
       
@@ -206,12 +205,11 @@ void restorePage::addDirectory(QString &newdirr)
       m_dirTreeItems.insert(item, text);
    }
 
-   if (regex.indexIn(fullpath,0) == 0) {
+   if (isWin32Path(fullpath)) {
       /* this is a windows drive */
       if (mainWin->m_miscDebug) {
          Pmsg0(000, "Need to do windows \"letter\":/\n");
       }
-      fullpath.replace(0,1,"");
       windrive = true;
    }
  
@@ -316,10 +314,6 @@ void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
     */
    if (item->text(1).endsWith("/")) {
       QString fullpath = m_cwd + item->text(1);
-      /* check for fullpath = "/c:/" */
-      QRegExp regex("^/[a-z]:/");
-      if (regex.indexIn(fullpath,0) == 0)  /* remove leading '/' */
-         fullpath.replace(0,1,"");
       QTreeWidgetItem *item = m_dirPaths.value(fullpath);
       if (item) {
          directoryWidget->setCurrentItem(item);
index e1594a39b9bec92a936fff99a66bf28733108e50..0bec98106ee1cc68e76988d0ba08e190266313b4 100644 (file)
@@ -51,9 +51,6 @@ restoreTree::restoreTree()
    m_populated = false;
 
    dockPage();
-   m_winRegExpDrive.setPattern("^[a-zA-Z]:/$");
-   m_winRegExpPath.setPattern("^[a-zA-Z]:/");
-   m_slashregex.setPattern("/");
    m_debugCnt = 0;
    m_debugTrap = true;
 
@@ -259,8 +256,10 @@ void restoreTree::populateDirectoryTree()
             Pmsg1(000, "Done with query %i results\n", results.count());
          QStringList fieldlist;
          foreach(QString resultline, results) {
-            m_debugCnt += 1;
-            prBar2->setValue(m_debugCnt);
+            /* Update progress bar periodically */
+            if ((++m_debugCnt && 0x3FF) == 0) {
+               prBar2->setValue(m_debugCnt);
+            }
             fieldlist = resultline.split("\t");
             int fieldcnt = 0;
             QString field;
@@ -324,15 +323,14 @@ void restoreTree::setJobsCheckedList()
  */
 void restoreTree::parseDirectory(QString &dir_in)
 {
-   /* m_debugTrap is to only print debugs for a few occurances of calling parseDirectory
+   /* m_debugTrap is to only print debugs for a few occurennces of calling parseDirectory
     * instead of printing out what could potentially a whole bunch */
    if (m_debugCnt > 2)
       m_debugTrap = false;
-   /* Clean up the directory string remove some funny char after last '/' */
-   QRegExp rgx("[^/]$");
-   int lastslash = rgx.indexIn(dir_in);
-   if (lastslash != -1)
-      dir_in.replace(lastslash, dir_in.length()-lastslash, "");
+   /* Truncate everything after the last / */
+   if (dir_in.right(1) != "/") {
+      dir_in.truncate(dir_in.lastIndexOf("/") + 1);
+   }
    if ((mainWin->m_miscDebug) && (m_debugTrap))
       Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
 
@@ -344,7 +342,7 @@ void restoreTree::parseDirectory(QString &dir_in)
    /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/ 
     * if not added into tree, then try /etc/ and somedir/ if not added, then try
     * / and etc/ .  That should succeed, then add the ones that failed in reverse */
-   while (((index = m_slashregex.lastIndexIn(dir_in, -2)) != -1) && (!done)) {
+   while (((index = dir_in.lastIndexOf("/", -2)) != -1) && (!done)) {
       direct = path = dir_in;
       path.replace(index+1, dir_in.length()-index-1,"");
       direct.replace(0, index+1, "");
@@ -373,6 +371,7 @@ void restoreTree::parseDirectory(QString &dir_in)
    }
 }
 
+
 /*
  * Function called from fill directory when a directory is found to see if this
  * directory exists in the directory pane and then add it to the directory pane
@@ -392,7 +391,7 @@ bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
 
    if (!m_slashTrap) {
       /* add unix '/' directory first */
-      if (m_dirPaths.empty() && (m_winRegExpPath.indexIn(fullPath, 0) == -1)) {
+      if (m_dirPaths.empty() && isWin32Path(fullPath)) {
          m_slashTrap = true;
          QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
          QString text("/");
@@ -406,7 +405,7 @@ bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
          m_dirPaths.insert(text, item);
       }
       /* no need to check for windows drive if unix */
-      if (m_winRegExpDrive.indexIn(m_cwd, 0) == 0) {
+      if (isWin32Path(m_cwd)) {
          if (!m_dirPaths.contains(m_cwd)) {
             /* this is a windows drive add the base widget */
             QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
@@ -1280,7 +1279,7 @@ void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in
    bool done = false;
    QString fullPath = fullPath_in;
    QString direct, path;
-   while (((index = m_slashregex.lastIndexIn(fullPath, -2)) != -1) && (!done)) {
+   while (((index = fullPath.lastIndexOf("/", -2)) != -1) && (!done)) {
       direct = path = fullPath;
       path.replace(index+1, fullPath.length()-index-1, "");
       direct.replace(0, index+1, "");
@@ -1730,7 +1729,7 @@ int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
 {
    int qversion = 0;
    QString directory, fileName;
-   int index = m_slashregex.lastIndexIn(fullPath, -2);
+   int index = fullPath.lastIndexOf("/", -2);
    if (index != -1) {
       directory = fileName = fullPath;
       directory.replace(index+1, fullPath.length()-index-1, "");
@@ -1783,7 +1782,7 @@ int restoreTree::queryFileIndex(QString &fullPath, int jobId)
 {
    int qfileIndex = 0;
    QString directory, fileName;
-   int index = m_slashregex.lastIndexIn(fullPath, -2);
+   int index = fullPath.lastIndexOf("/", -2);
    if (index != -1) {
       directory = fileName = fullPath;
       directory.replace(index+1, fullPath.length()-index-1, "");
index be99c492e2dce2f7b0300a41d53b308f6296ca1a..1ad1f176ea00c2e9017b329c9375e516085a2afb 100644 (file)
@@ -102,7 +102,6 @@ private:
    bool m_dropdownChanged;
    QRegExp m_winRegExpDrive;
    QRegExp m_winRegExpPath;
-   QRegExp m_slashregex;
    bool m_slashTrap;
    QHash<QString, QTreeWidgetItem *> m_dirPaths;
    QString m_checkedJobs, m_prevJobCombo, m_prevClientCombo, m_prevFileSetCombo;
index 7f965e805f39a42fd9aa99f49b043a1eccf6c4b6..1141df69c40735c93141417f65e3af08916e4713 100644 (file)
@@ -179,7 +179,7 @@ static bool do_get_volume_info(DCR *dcr)
        return false;
     }
     memset(&vol, 0, sizeof(vol));
-    Dmsg2(100, "<dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg);
+    Dmsg1(100, "<dird %s", dir->msg);
     n = sscanf(dir->msg, OK_media, vol.VolCatName,
                &vol.VolCatJobs, &vol.VolCatFiles,
                &vol.VolCatBlocks, &vol.VolCatBytes,
@@ -191,8 +191,8 @@ static bool do_get_volume_info(DCR *dcr)
                &vol.EndFile, &vol.EndBlock, &vol.VolCatParts,
                &vol.LabelType, &vol.VolMediaId);
     if (n != 22) {
-       Dmsg4(100, "Bad response from Dir jid=%u fields=%d, len=%d: %s", 
-             (uint32_t)jcr->JobId, n, dir->msglen, dir->msg);
+       Dmsg3(100, "Bad response from Dir fields=%d, len=%d: %s", 
+             n, dir->msglen, dir->msg);
        Mmsg(jcr->errmsg, _("Error getting Volume info: %s"), dir->msg);
        return false;
     }
@@ -201,8 +201,8 @@ static bool do_get_volume_info(DCR *dcr)
     bstrncpy(dcr->VolumeName, vol.VolCatName, sizeof(dcr->VolumeName));
     dcr->VolCatInfo = vol;            /* structure assignment */
 
-    Dmsg3(100, "do_reqest_vol_info return true jid=%u slot=%d Volume=%s\n",
-          (uint32_t)jcr->JobId, vol.Slot, vol.VolCatName);
+    Dmsg2(100, "do_reqest_vol_info return true slot=%d Volume=%s\n",
+          vol.Slot, vol.VolCatName);
     return true;
 }
 
@@ -227,7 +227,7 @@ bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing)
     bash_spaces(dcr->VolCatInfo.VolCatName);
     dir->fsend(Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName,
        writing==GET_VOL_INFO_FOR_WRITE?1:0);
-    Dmsg2(100, ">dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg);
+    Dmsg1(100, ">dird %s", dir->msg);
     unbash_spaces(dcr->VolCatInfo.VolCatName);
     bool ok = do_get_volume_info(dcr);
     V(vol_info_mutex);
@@ -271,14 +271,14 @@ bool dir_find_next_appendable_volume(DCR *dcr)
        dir->fsend(Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type);
        unbash_spaces(dcr->media_type);
        unbash_spaces(dcr->pool_name);
-       Dmsg2(100, ">dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg);
+       Dmsg1(100, ">dird %s", dir->msg);
        bool ok = do_get_volume_info(dcr);
        if (ok) {
           if (!is_volume_in_use(dcr)) {
              found = true;
              break;
           } else {
-             Dmsg2(100, "jid=%u Volume %s is in use.\n", (uint32_t)jcr->JobId, dcr->VolumeName);
+             Dmsg1(100, "Volume %s is in use.\n", dcr->VolumeName);
              dcr->volume_in_use = true;
              continue;
           }
@@ -358,7 +358,7 @@ bool dir_update_volume_info(DCR *dcr, bool label)
       edit_int64(vol->VolWriteTime, ed4),
       edit_uint64(vol->VolFirstWritten, ed5),
       vol->VolCatParts);
-    Dmsg2(100, ">dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg);
+    Dmsg1(100, ">dird %s", dir->msg);
 
    /* Do not lock device here because it may be locked from label */
    if (!do_get_volume_info(dcr)) {
@@ -367,7 +367,7 @@ bool dir_update_volume_info(DCR *dcr, bool label)
          vol->VolCatName, jcr->errmsg);
       goto bail_out;
    }
-   Dmsg2(420, "get_volume_info() jid=%u: %s", (uint32_t)jcr->JobId, dir->msg);
+   Dmsg1(420, "get_volume_info() %s", dir->msg);
    /* Update dev Volume info in case something changed (e.g. expired) */
    dev->VolCatInfo = dcr->VolCatInfo;
    ok = true;
@@ -402,14 +402,14 @@ bool dir_create_jobmedia_record(DCR *dcr)
       dcr->StartBlock, dcr->EndBlock, 
       dcr->Copy, dcr->Stripe, 
       edit_uint64(dcr->VolMediaId, ed1));
-    Dmsg2(100, ">dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg);
+    Dmsg1(100, ">dird %s", dir->msg);
    if (bnet_recv(dir) <= 0) {
       Dmsg0(190, "create_jobmedia error bnet_recv\n");
       Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: ERR=%s\n"),
            dir->bstrerror());
       return false;
    }
-   Dmsg2(100, "<dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg);
+   Dmsg1(100, "<dird %s", dir->msg);
    if (strcmp(dir->msg, OK_create) != 0) {
       Dmsg1(130, "Bad response from Dir: %s\n", dir->msg);
       Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: %s\n"), dir->msg);
@@ -444,7 +444,7 @@ bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec)
    ser_uint32(rec->data_len);
    ser_bytes(rec->data, rec->data_len);
    dir->msglen = ser_length(dir->msg);
-   Dmsg2(1800, ">dird jid=%u: %s\n", (uint32_t)jcr->JobId, dir->msg);    /* Attributes */
+   Dmsg1(1800, ">dird %s\n", dir->msg);    /* Attributes */
    return dir->send();
 }
 
index f51f3ce1602fca6cb0b1b51b641069e2b10c166e..45cd39f6accce2cb9cd98f56f7a7f53d4acadb55 100644 (file)
@@ -473,8 +473,9 @@ public:
 class VOLRES { 
 public:
    dlink link;
-   char *vol_name;
-   DEVICE *dev;
+   char *vol_name;                    /* Volume name */
+   DEVICE *dev;                       /* Pointer to device to which we are attached */
+   bool released;                     /* set when the Volume can be released */
 };
 
 
index 70083683bce52a1e5ee811377d4ddae1238697e4..42b343418020c2ca25b991a93366b9f18d7ab38e 100644 (file)
@@ -210,11 +210,11 @@ 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\n", dev->can_read()?1:0,
-            dev->num_writers, dev->reserved_device);
+         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);
          sendit(msg.c_str(), len, arg);
       } else {
-         len = Mmsg(msg, "%s no dev\n", vol->vol_name);
+         len = Mmsg(msg, "%s no device. released=%d\n", vol->vol_name, vol->released);
          sendit(msg.c_str(), len, arg);
       }
    }
@@ -377,12 +377,16 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
             Dmsg3(dbglvl, "Volume busy could not swap vol=%s from dev=%s to %s\n", 
                VolumeName, vol->dev->print_name(), dev->print_name());
             vol = NULL;                /* device busy */
+            goto get_out;
          }
       }
    }
    dev->vol = vol;
 
 get_out:
+   if (vol) {
+      vol->released = false;
+   }
    debug_list_volumes("end new volume");
    unlock_volumes();
    return vol;
@@ -461,6 +465,7 @@ bool volume_unused(DCR *dcr)
     *  explicitly read in this drive. This allows the SD to remember
     *  where the tapes are or last were.
     */
+   dev->vol->released = true;
    if (dev->is_tape() || dev->is_autochanger()) {
       return true;
    } else {
@@ -512,7 +517,7 @@ void free_volume_list()
       if (vol->dev) {
          Dmsg2(dbglvl, "free vol_list Volume=%s dev=%s\n", vol->vol_name, vol->dev->print_name());
       } else {
-         Dmsg2(dbglvl, "free vol_list Volume=%s dev=%p\n", vol->vol_name, vol->dev);
+         Dmsg1(dbglvl, "free vol_list Volume=%s No dev\n", vol->vol_name);
       }
       free(vol->vol_name);
       vol->vol_name = NULL;
index 83b0e552dc9c55bc81b874420342ddc24f9ccef4..c1a3e22110955f39ae5b3f831dd614181805e715 100644 (file)
@@ -107,7 +107,7 @@ static char *cleanup_addr(char *addr, char *buf, int buf_len)
 {
    char *p, *q;
 
-   if ((p = strchr(from_addr, '<')) == NULL) {
+   if ((p = strchr(addr, '<')) == NULL) {
       snprintf(buf, buf_len, "<%s>", addr);
    } else {
       /* Copy <addr> */
index f1e59b8b66ceabb5160a9f6216aa52d759e7decc..502a19308990a1b26dff7d68028b865ec9d708d9 100644 (file)
@@ -4,8 +4,8 @@
 
 #undef  VERSION
 #define VERSION "2.3.6"
-#define BDATE   "30 September 2007"
-#define LSMDATE "30Sep07"
+#define BDATE   "05 October 2007"
+#define LSMDATE "05Oct07"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2007"       /* year for copyright messages in progs */
index af38df92f74e48ec9f8b1db45847aa5234f7ad9b..d8a943c0e2014888f08881240e801029597427d1 100644 (file)
@@ -1,10 +1,15 @@
               Technical notes on version 2.3
 
 General:
+05Oct07
+kes  Fix listing performance problems in bat. Pointed out by 
+     Chris Howells.
+kes  Remove old debug code.
+kes  Fix bat code that tests for Win32. This should fix bug #968
+kes  Query 5 list wrong Vol after migration. This fixes bug #960
 04Oct07
-ebl  Fix #969 where user can't change Replace option in
-     restore menu.
-30Sep07
+ebl  Fix #969 where user can't change Replace option in restore menu.
+5ASep07
 kes  Save jcr in thread specific data (tsd) for each thread.
 kes  Make Dmsg() print JobId as -%u.
 kes  Make Jmsg, Emsg, and others automatically pickup the jobid
@@ -57,7 +62,7 @@ kes  If Dir gets an error during inserting attributes, cancel SD.
      This reduces unnecessary error messages.
 24Sep07 
 kes  Correct search boolean for getting Volume info
-ebl  Cleanup batch code. Probably fixes bug #965.
+ebl  Cleanup batch insert code. Probably fixes bug #965.
 kes  Back out one small change to the reservation system (reserving a volume).
 kes  Rework how a Volume is mounted. It is now much more intelligent and
      will always attempt to use any mounted volume if possible and reduces