]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/bsr.c
Fix problem in BVFS with concurrent queries
[bacula/bacula] / bacula / src / dird / bsr.c
index 4e03daa5a257079118b3b929e9f2ddbc160b7ee4..63d85b8745f56624b5c940be1545318eda9faebe 100644 (file)
@@ -1,23 +1,12 @@
-/*
- *
- *   Bacula Director -- Bootstrap Record routines.
- *
- *      BSR (bootstrap record) handling routines split from
- *        ua_restore.c July MMIII
- *
- *     Kern Sibbald, July MMII
- *
- *   Version $Id$
- */
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-2010 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.
    This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
+   modify it under the terms of version three of the GNU Affero General Public
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
+   You should have received a copy of the GNU Affero General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of Kern Sibbald.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
+/*
+ *
+ *   Bacula Director -- Bootstrap Record routines.
+ *
+ *      BSR (bootstrap record) handling routines split from
+ *        ua_restore.c July MMIII
+ *
+ *     Kern Sibbald, July MMII
+ *
+ */
 
 #include "bacula.h"
 #include "dird.h"
 
 /* Forward referenced functions */
 static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd);
-void print_bsr(UAContext *ua, RBSR *bsr);
-
 
 /*
  * Create new FileIndex entry for BSR
@@ -137,21 +134,6 @@ static bool is_volume_selected(RBSR_FINDEX *fi,
 }
 
 
-
-static void print_findex(UAContext *ua, RBSR_FINDEX *fi)
-{
-   ua->send_msg("fi=0x%lx\n", fi);
-   for ( ; fi; fi=fi->next) {
-      if (fi->findex == fi->findex2) {
-         ua->send_msg("FileIndex=%d\n", fi->findex);
-         Dmsg1(1000, "FileIndex=%d\n", fi->findex);
-      } else {
-         ua->send_msg("FileIndex=%d-%d\n", fi->findex, fi->findex2);
-         Dmsg2(1000, "FileIndex=%d-%d\n", fi->findex, fi->findex2);
-      }
-   }
-}
-
 /* Create a new bootstrap record */
 RBSR *new_bsr()
 {
@@ -169,6 +151,9 @@ void free_bsr(RBSR *bsr)
       if (bsr->VolParams) {
          free(bsr->VolParams);
       }
+      if (bsr->fileregex) {
+         free(bsr->fileregex);
+      }
       next = bsr->next;
       free(bsr);
    }
@@ -190,6 +175,10 @@ bool complete_bsr(UAContext *ua, RBSR *bsr)
       }
       bsr->VolSessionId = jr.VolSessionId;
       bsr->VolSessionTime = jr.VolSessionTime;
+      if (jr.JobFiles == 0) {      /* zero files is OK, not an error, but */
+         bsr->VolCount = 0;        /*   there are no volumes */
+         continue;
+      }
       if ((bsr->VolCount=db_get_job_volume_parameters(ua->jcr, ua->db, bsr->JobId,
            &(bsr->VolParams))) == 0) {
          ua->error_msg(_("Unable to get Job Volume Parameters. ERR=%s\n"), db_strerror(ua->db));
@@ -233,12 +222,8 @@ uint32_t write_bsr_file(UAContext *ua, RESTORE_CTX &rx)
 {
    FILE *fd;
    POOL_MEM fname(PM_MESSAGE);
-   POOL_MEM volmsg(PM_MESSAGE);
    uint32_t count = 0;;
    bool err;
-   char *p;
-   JobId_t JobId;
-   char Device[MAX_NAME_LENGTH];
 
    make_unique_restore_filename(ua, fname);
    fd = fopen(fname.c_str(), "w+b");
@@ -253,7 +238,7 @@ uint32_t write_bsr_file(UAContext *ua, RESTORE_CTX &rx)
    err = ferror(fd);
    fclose(fd);
    if (count == 0) {
-      ua->info_msg(_("No files found to restore/migrate. No bootstrap file written.\n"));
+      ua->info_msg(_("No files found to read. No bootstrap file written.\n"));
       goto bail_out;
    }
    if (err) {
@@ -262,9 +247,52 @@ uint32_t write_bsr_file(UAContext *ua, RESTORE_CTX &rx)
       goto bail_out;
    }
 
-
    ua->send_msg(_("Bootstrap records written to %s\n"), fname.c_str());
 
+   if (debug_level >= 10) {
+      print_bsr(ua, rx);
+   }
+
+bail_out:
+   return count;
+}
+
+static void display_vol_info(UAContext *ua, RESTORE_CTX &rx, JobId_t JobId)
+{
+   POOL_MEM volmsg(PM_MESSAGE);
+   char Device[MAX_NAME_LENGTH];
+   char online;
+   RBSR *bsr;
+
+   for (bsr=rx.bsr; bsr; bsr=bsr->next) {
+      if (JobId && JobId != bsr->JobId) {
+         continue;
+      }
+
+      for (int i=0; i < bsr->VolCount; i++) {
+         if (bsr->VolParams[i].VolumeName[0]) {
+            if (!get_storage_device(Device, bsr->VolParams[i].Storage)) {
+               Device[0] = 0;
+            }
+            if (bsr->VolParams[i].InChanger && bsr->VolParams[i].Slot) {
+               online = '*';
+            } else {
+               online = ' ';
+            }
+            Mmsg(volmsg, "%c%-25s %-25s %-25s", 
+                 online, bsr->VolParams[i].VolumeName,
+                 bsr->VolParams[i].Storage, Device);
+            add_prompt(ua, volmsg.c_str());
+         }
+      }
+   }
+}
+
+void display_bsr_info(UAContext *ua, RESTORE_CTX &rx)
+{
+   char *p;
+   JobId_t JobId;
+
    /* Tell the user what he will need to mount */
    ua->send_msg("\n");
    ua->send_msg(_("The job will require the following\n"
@@ -272,40 +300,13 @@ uint32_t write_bsr_file(UAContext *ua, RESTORE_CTX &rx)
                   "===========================================================================\n"));
    /* Create Unique list of Volumes using prompt list */
    start_prompt(ua, "");
-   if (*rx.JobIds) {
+   if (*rx.JobIds == 0) {
+      /* Print Volumes in any order */
+      display_vol_info(ua, rx, 0);
+   } else {
       /* Ensure that the volumes are printed in JobId order */
       for (p=rx.JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) {
-         for (RBSR *nbsr=rx.bsr; nbsr; nbsr=nbsr->next) {
-            if (JobId != nbsr->JobId) {
-               continue;
-            }
-            for (int i=0; i < nbsr->VolCount; i++) {
-               if (nbsr->VolParams[i].VolumeName[0]) {
-                  if (!get_storage_device(Device, nbsr->VolParams[i].Storage)) {
-                     Device[0] = 0;
-                  }
-                  Mmsg(volmsg, "%-25.25s %-25.25s %-25.25s", 
-                       nbsr->VolParams[i].VolumeName, 
-                       nbsr->VolParams[i].Storage, Device);
-                  add_prompt(ua, volmsg.c_str());
-               }
-            }
-         }
-      }
-   } else {
-      /* Print Volumes in any order */
-      for (RBSR *nbsr=rx.bsr; nbsr; nbsr=nbsr->next) {
-         for (int i=0; i < nbsr->VolCount; i++) {
-            if (nbsr->VolParams[i].VolumeName[0]) {
-               if (!get_storage_device(Device, nbsr->VolParams[i].Storage)) {
-                  Device[0] = 0;
-               }
-               Mmsg(volmsg, "%-25.25s %-25.25s %-25.25s", 
-                    nbsr->VolParams[i].VolumeName, 
-                    nbsr->VolParams[i].Storage, Device);
-               add_prompt(ua, volmsg.c_str());
-            }
-         }
+         display_vol_info(ua, rx, JobId);
       }
    }
    for (int i=0; i < ua->num_prompts; i++) {
@@ -314,15 +315,79 @@ uint32_t write_bsr_file(UAContext *ua, RESTORE_CTX &rx)
    }
    if (ua->num_prompts == 0) {
       ua->send_msg(_("No Volumes found to restore.\n"));
-      count = 0;
+   } else {
+      ua->send_msg(_("\nVolumes marked with \"*\" are online.\n"));
    }
    ua->num_prompts = 0;
    ua->send_msg("\n");
 
-bail_out:
-   return count;
+   return;
 }
 
+/*
+ * Write bsr data for a single bsr record
+ */
+static uint32_t write_bsr_item(RBSR *bsr, UAContext *ua, 
+                   RESTORE_CTX &rx, FILE *fd, bool &first, uint32_t &LastIndex)
+{
+   char ed1[50], ed2[50];
+   uint32_t count = 0;
+   uint32_t total_count = 0;
+   char device[MAX_NAME_LENGTH];
+
+   /*
+    * For a given volume, loop over all the JobMedia records.
+    *   VolCount is the number of JobMedia records.
+    */
+   for (int i=0; i < bsr->VolCount; i++) {
+      if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex,
+           bsr->VolParams[i].LastIndex)) {
+         bsr->VolParams[i].VolumeName[0] = 0;  /* zap VolumeName */
+         continue;
+      }
+      if (!rx.store) {
+         find_storage_resource(ua, rx, bsr->VolParams[i].Storage,
+                                       bsr->VolParams[i].MediaType);
+      }
+      fprintf(fd, "Storage=\"%s\"\n", bsr->VolParams[i].Storage);
+      fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName);
+      fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType);
+      if (bsr->fileregex) {
+         fprintf(fd, "FileRegex=%s\n", bsr->fileregex);
+      }
+      if (get_storage_device(device, bsr->VolParams[i].Storage)) {
+         fprintf(fd, "Device=\"%s\"\n", device);
+      }
+      if (bsr->VolParams[i].Slot > 0) {
+         fprintf(fd, "Slot=%d\n", bsr->VolParams[i].Slot);
+      }
+      fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
+      fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
+      fprintf(fd, "VolAddr=%s-%s\n", edit_uint64(bsr->VolParams[i].StartAddr, ed1),
+              edit_uint64(bsr->VolParams[i].EndAddr, ed2));
+//    Dmsg2(100, "bsr VolParam FI=%u LI=%u\n",
+//      bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex);
+
+      count = write_findex(bsr->fi, bsr->VolParams[i].FirstIndex,
+                           bsr->VolParams[i].LastIndex, fd);
+      if (count) {
+         fprintf(fd, "Count=%u\n", count);
+      }
+      total_count += count;
+      /* If the same file is present on two tapes or in two files
+       *   on a tape, it is a continuation, and should not be treated
+       *   twice in the totals.
+       */
+      if (!first && LastIndex == bsr->VolParams[i].FirstIndex) {
+         total_count--;
+      }
+      first = false;
+      LastIndex = bsr->VolParams[i].LastIndex;
+   }
+   return total_count;
+}
+
+
 /*
  * Here we actually write out the details of the bsr file.
  *  Note, there is one bsr for each JobId, but the bsr may
@@ -333,155 +398,31 @@ bail_out:
  */
 static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd)
 {
-   uint32_t count = 0;
-   uint32_t total_count = 0;
-   uint32_t LastIndex = 0;
    bool first = true;
+   uint32_t LastIndex = 0;
+   uint32_t total_count = 0;
    char *p;
    JobId_t JobId;
-   char device[MAX_NAME_LENGTH];
    RBSR *bsr;
    if (*rx.JobIds == 0) {
       for (bsr=rx.bsr; bsr; bsr=bsr->next) {
-         /*
-          * For a given volume, loop over all the JobMedia records.
-          *   VolCount is the number of JobMedia records.
-          */
-         for (int i=0; i < bsr->VolCount; i++) {
-            if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex,
-                 bsr->VolParams[i].LastIndex)) {
-               bsr->VolParams[i].VolumeName[0] = 0;  /* zap VolumeName */
-               continue;
-            }
-            if (!rx.store) {
-               find_storage_resource(ua, rx, bsr->VolParams[i].Storage,
-                                             bsr->VolParams[i].MediaType);
-            }
-            fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName);
-            fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType);
-            if (get_storage_device(device, bsr->VolParams[i].Storage)) {
-               fprintf(fd, "Device=\"%s\"\n", device);
-            }
-            if (bsr->VolParams[i].Slot > 0) {
-               fprintf(fd, "Slot=%d\n", bsr->VolParams[i].Slot);
-            }
-            fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
-            fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
-            if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) {
-               fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile);
-            } else {
-               fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
-                       bsr->VolParams[i].EndFile);
-            }
-            if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) {
-               fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock);
-            } else {
-               fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
-                       bsr->VolParams[i].EndBlock);
-            }
-   //       Dmsg2(100, "bsr VolParam FI=%u LI=%u\n",
-   //          bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex);
-
-            count = write_findex(bsr->fi, bsr->VolParams[i].FirstIndex,
-                                 bsr->VolParams[i].LastIndex, fd);
-            if (count) {
-               fprintf(fd, "Count=%u\n", count);
-            }
-            total_count += count;
-            /* If the same file is present on two tapes or in two files
-             *   on a tape, it is a continuation, and should not be treated
-             *   twice in the totals.
-             */
-            if (!first && LastIndex == bsr->VolParams[i].FirstIndex) {
-               total_count--;
-            }
-            first = false;
-            LastIndex = bsr->VolParams[i].LastIndex;
-         }
+         total_count += write_bsr_item(bsr, ua, rx, fd, first, LastIndex);
       }
       return total_count;
    }
    for (p=rx.JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) {
       for (bsr=rx.bsr; bsr; bsr=bsr->next) {
-         if (JobId != bsr->JobId) {
-            continue;
-         }
-         /*
-          * For a given volume, loop over all the JobMedia records.
-          *   VolCount is the number of JobMedia records.
-          */
-         for (int i=0; i < bsr->VolCount; i++) {
-            if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex,
-                 bsr->VolParams[i].LastIndex)) {
-               bsr->VolParams[i].VolumeName[0] = 0;  /* zap VolumeName */
-               continue;
-            }
-            if (!rx.store) {
-               find_storage_resource(ua, rx, bsr->VolParams[i].Storage,
-                                             bsr->VolParams[i].MediaType);
-            }
-            fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName);
-            fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType);
-            if (get_storage_device(device, bsr->VolParams[i].Storage)) {
-               fprintf(fd, "Device=\"%s\"\n", device);
-            }
-            if (bsr->VolParams[i].Slot > 0) {
-               fprintf(fd, "Slot=%d\n", bsr->VolParams[i].Slot);
-            }
-            fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
-            fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
-            if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) {
-               fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile);
-            } else {
-               fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
-                       bsr->VolParams[i].EndFile);
-            }
-            if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) {
-               fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock);
-            } else {
-               fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
-                       bsr->VolParams[i].EndBlock);
-            }
-   //       Dmsg2(100, "bsr VolParam FI=%u LI=%u\n",
-   //          bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex);
-
-            count = write_findex(bsr->fi, bsr->VolParams[i].FirstIndex,
-                                 bsr->VolParams[i].LastIndex, fd);
-            if (count) {
-               fprintf(fd, "Count=%u\n", count);
-            }
-            total_count += count;
-            /* If the same file is present on two tapes or in two files
-             *   on a tape, it is a continuation, and should not be treated
-             *   twice in the totals.
-             */
-            if (!first && LastIndex == bsr->VolParams[i].FirstIndex) {
-               total_count--;
-            }
-            first = false;
-            LastIndex = bsr->VolParams[i].LastIndex;
+         if (JobId == bsr->JobId) {
+            total_count += write_bsr_item(bsr, ua, rx, fd, first, LastIndex);
          }
       }
    }
    return total_count;
 }
 
-void print_bsr(UAContext *ua, RBSR *bsr)
+void print_bsr(UAContext *ua, RESTORE_CTX &rx)
 {
-   for ( ; bsr; bsr=bsr->next) {
-      for (int i=0; i < bsr->VolCount; i++) {
-         ua->send_msg("Volume=\"%s\"\n", bsr->VolParams[i].VolumeName);
-         ua->send_msg("MediaType\"%s\"\n", bsr->VolParams[i].MediaType);
-         ua->send_msg("VolSessionId=%u\n", bsr->VolSessionId);
-         ua->send_msg("VolSessionTime=%u\n", bsr->VolSessionTime);
-         ua->send_msg("VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
-                  bsr->VolParams[i].EndFile);
-         ua->send_msg("VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
-                  bsr->VolParams[i].EndBlock);
-         print_findex(ua, bsr->fi);
-      }
-      print_bsr(ua, bsr->next);
-   }
+   write_bsr(ua, rx, stdout);
 }
 
 
@@ -491,6 +432,7 @@ void print_bsr(UAContext *ua, RBSR *bsr)
  * Add a FileIndex to the list of BootStrap records.
  *  Here we are only dealing with JobId's and the FileIndexes
  *  associated with those JobIds.
+ * We expect that JobId, FileIndex are sorted ascending.
  */
 void add_findex(RBSR *bsr, uint32_t JobId, int32_t findex)
 {
@@ -615,8 +557,15 @@ void add_findex_all(RBSR *bsr, uint32_t JobId)
          /* Add new JobId at end of chain */
          for (nbsr=bsr; nbsr->next; nbsr=nbsr->next)
             {  }
+
          nbsr->next = new_bsr();
          nbsr->next->JobId = JobId;
+
+         /* If we use regexp to restore, set it for each jobid */
+         if (bsr->fileregex) { 
+            nbsr->next->fileregex = bstrdup(bsr->fileregex);
+         }
+
          nbsr->next->fi = new_findex();
          nbsr->next->fi->findex = 1;
          nbsr->next->fi->findex2 = INT32_MAX;