]> git.sur5r.net Git - bacula/bacula/commitdiff
Misc cleanup
authorKern Sibbald <kern@sibbald.com>
Wed, 20 Aug 2003 09:42:21 +0000 (09:42 +0000)
committerKern Sibbald <kern@sibbald.com>
Wed, 20 Aug 2003 09:42:21 +0000 (09:42 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@670 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/examples/backup-every-other-week.txt [new file with mode: 0644]
bacula/kernstodo
bacula/src/filed/job.c
bacula/src/lib/protos.h
bacula/src/lib/util.c
bacula/src/stored/block.c
bacula/src/stored/btape.c

diff --git a/bacula/examples/backup-every-other-week.txt b/bacula/examples/backup-every-other-week.txt
new file mode 100644 (file)
index 0000000..f2f9173
--- /dev/null
@@ -0,0 +1,92 @@
+
+From bacula-users-admin@lists.sourceforge.net Wed Aug 13 19:22:21 2003
+From: Robert L Mathews <lists@tigertech.com>
+To: <bacula-users@lists.sourceforge.net>
+Content-Type: text/plain; charset="US-ASCII"
+Message-Id: <20030813170422.E48403FC65F@fry.tigertech.net>
+Subject: [Bacula-users] Making Backups Run Every Other Week
+Sender: bacula-users-admin@lists.sourceforge.net
+Date: Wed, 13 Aug 2003 10:04:23 -0700
+
+In case anyone is interested, here's a tip I came up with.
+
+My backup policy is such that I need backups to run every other week. I 
+have two separate "offsite" tape pools, and a backup is made to each of 
+them on alternating weeks.
+
+Bacula's scheduler currently doesn't handle "every two weeks", and using 
+something like "the first and third weeks for backup A, and the second 
+and fourth weeks for backup B" means there will be no backup done on the 
+fifth week if the month contains one. Scheduling a backup for the fifth 
+week doesn't help; it means that the same backup would sometimes run 
+twice in a row, which ruins the alternating week scheme.
+
+I first thought of poking around the code to make the scheduler support 
+"every two weeks", and I someday may still do so. However, I found an 
+easier way to do this is in the meantime: with a RunBeforeJob line.
+
+What I do is schedule both jobs to run every single week. Then the job 
+that runs my "Offsite Backup A" has this line:
+
+  RunBeforeJob = "/etc/bacula/two_week_script 'July 6 2003'"
+
+And the job with my "Offsite Backup B" has this one:
+
+  RunBeforeJob = "/etc/bacula/two_week_script 'July 13 2003'"
+
+And two_week_script is the following Perl script:
+
+----------------
+
+#!/usr/bin/perl -w
+
+use strict;
+use constant SECONDS_IN_WEEK => 86400 * 7;
+use constant SECONDS_IN_TWO_WEEKS => SECONDS_IN_WEEK * 2;
+
+# Calculate the elapsed seconds since the starting date,
+# which must be in a format that /bin/date can understand
+# Note that this relies on the GNU "%s" date extension
+my $start_date = shift;
+$start_date = `/bin/date -d '$start_date' +'%s'`;
+chomp $start_date;
+my $time_since_start_date = time - $start_date;
+
+# Now take those seconds modulo the number of seconds in
+# two weeks. If we're in the second half of the two week
+# period, exit with an error to stop the Bacula job. If
+# we're in the first half, the script will terminate normally
+# and the Bacula job will run.
+if ($time_since_start_date % SECONDS_IN_TWO_WEEKS
+        >= SECONDS_IN_WEEK)
+{
+        exit 1;
+}
+
+----------------
+
+The result is that the script cancels the job that should not be run that 
+week, while allowing the other job to continue.
+
+This idea could be trivially changed to support running every three 
+weeks, every two months, every prime number of days, etc.
+
+Anyway, just a tip in case anyone else needs to schedule things in a way 
+that the scheduler doesn't currently support. It's pretty obvious that 
+this is the right way to do it now, but I puzzled over it for a little 
+while before coming up with this.
+
+-- 
+Robert L Mathews, Tiger Technologies
+
+
+
+-------------------------------------------------------
+This SF.Net email sponsored by: Free pre-built ASP.NET sites including
+Data Reports, E-commerce, Portals, and Forums are available now.
+Download today and enter to win an XBOX or Visual Studio .NET.
+http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
+_______________________________________________
+Bacula-users mailing list
+Bacula-users@lists.sourceforge.net
+https://lists.sourceforge.net/lists/listinfo/bacula-users
index 5eaee27ecb8a7ed725f176bd5f1a4e5a32b7e65f..f527d2a1498171037c5cd36e501cda0bf4f13cde 100644 (file)
@@ -27,6 +27,7 @@ Testing to do: (painful)
 - Figure out how to use ssh or stunnel to protect Bacula communications.
 
 For 1.32:
+- Edit the Client/Storage name into authentication failure messages.
 - Implement job in VerifyToCatalog
 - Implement migrate
 - Implement List Volume Job=xxx  or List scheduled volumes or Status Director 
@@ -797,4 +798,3 @@ Done: (see kernsdone for more)
 - Add user configurable timeout for connecting to SD.
 - Unsaved Flag in Job record (use JobMissingFiles).
 - Base Flag in Job record.
-
index 83984348944fee97c10e6e60fb1babfdd2bcc9fa..e23828c37fb4675251d336776ca025500900417c 100644 (file)
@@ -312,8 +312,8 @@ static int job_cmd(JCR *jcr)
              &jcr->VolSessionId, &jcr->VolSessionTime,
              sd_auth_key) != 5) {
       pm_strcpy(&jcr->errmsg, dir->msg);
-      bnet_fsend(dir, BADjob);
       Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
+      bnet_fsend(dir, BADjob);
       free_pool_memory(sd_auth_key);
       return 0;
    }
@@ -943,7 +943,7 @@ static int send_bootstrap_file(JCR *jcr)
       set_jcr_job_status(jcr, JS_ErrorTerminated);
       return 0;
    }
-   strcpy(sd->msg, bootstrap); 
+   pm_strcpy(&sd->msg, bootstrap);  
    sd->msglen = strlen(sd->msg);
    bnet_send(sd);
    while (fgets(buf, sizeof(buf), bs)) {
index 413c3b6494845a85bc5aed7bf7f7b171be00d172..15d561dad170df5e250dfdaf5896a464fd23ec6e 100644 (file)
@@ -177,8 +177,8 @@ char *           encode_time             (time_t time, char *buf);
 char *           encode_mode             (mode_t mode, char *buf);
 int              do_shell_expansion      (char *name, int name_len);
 void             jobstatus_to_ascii      (int JobStatus, char *msg, int maxlen);
-void             pm_strcat               (POOLMEM **pm, char *str);
-void             pm_strcpy               (POOLMEM **pm, char *str);
+int              pm_strcat               (POOLMEM **pm, char *str);
+int              pm_strcpy               (POOLMEM **pm, char *str);
 int              run_program             (char *prog, int wait, POOLMEM *results);
 char *           job_type_to_str         (int type);
 char *           job_status_to_str       (int stat);
index 71518c3b81a8353016f8edda03b50280c90eb7ca..59bb7ad69c8492e8131913c850b3f78aeef1f642 100644 (file)
@@ -112,25 +112,27 @@ char *encode_time(time_t time, char *buf)
 /*
  * Concatenate a string (str) onto a pool memory buffer pm
  */
-void pm_strcat(POOLMEM **pm, char *str)
+in pm_strcat(POOLMEM **pm, char *str)
 {
    int pmlen = strlen(*pm);
    int len = strlen(str) + 1;
 
    *pm = check_pool_memory_size(*pm, pmlen + len);
    memcpy(*pm+pmlen, str, len);
+   return pmlen + len - 1;
 }
 
 
 /*
  * Copy a string (str) into a pool memory buffer pm
  */
-void pm_strcpy(POOLMEM **pm, char *str)
+int pm_strcpy(POOLMEM **pm, char *str)
 {
    int len = strlen(str) + 1;
 
    *pm = check_pool_memory_size(*pm, len);
    memcpy(*pm, str, len);
+   return len - 1;
 }
 
 
index ca96d6d3943c1fff30a146b59636a78e5b68bf3e..ef24940c48a977f979c7373cff2356426e6955aa 100644 (file)
@@ -314,7 +314,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
    ssize_t stat = 0;
    uint32_t wlen;                    /* length to write */
    int hit_max1, hit_max2;
-   int ok;
+   bool ok;
 
 #ifdef NO_TAPE_WRITE_TEST
    empty_block(block);
@@ -396,7 +396,8 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 
    dev->VolCatInfo.VolCatWrites++;
    Dmsg1(300, "Write block of %u bytes\n", wlen);      
-   if ((uint32_t)(stat=write(dev->fd, block->buf, (size_t)wlen)) != wlen) {
+   stat = write(dev->fd, block->buf, (size_t)wlen);
+   if (stat != (ssize_t)wlen) {
       /* We should check for errno == ENOSPC, BUT many 
        * devices simply report EIO when the volume is full.
        * With a little more thought we may be able to check
@@ -412,11 +413,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
          * systems (FreeBSD like), do the clrerror() only after
          * the weof_dev() call.
          */
-#ifndef MTIOCERRSTAT
         clrerror_dev(dev, -1);
-#else
-        dev->dev_errno = errno;      /* save errno */
-#endif
         if (dev->dev_errno == 0) {
            dev->dev_errno = ENOSPC;        /* out of space */
         }
@@ -428,18 +425,16 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
            dev->dev_name, wlen, stat);
       }  
 
-      Dmsg4(10, "=== Write error. size=%u rtn=%d  errno=%d: ERR=%s\n", 
-        wlen, stat, dev->dev_errno, strerror(dev->dev_errno));
+      Dmsg6(100, "=== Write error. size=%u rtn=%d dev_blk=%d blk_blk=%d errno=%d: ERR=%s\n", 
+        wlen, stat, dev->block_num, block->BlockNumber, dev->dev_errno, strerror(dev->dev_errno));
 
       block->write_failed = true;
-      weof_dev(dev, 1);              /* end the tape */
-      weof_dev(dev, 1);              /* write second eof */
-#ifdef MTIOCERRSTAT
-      clrerror_dev(dev, -1);
-#endif
+      if (weof_dev(dev, 2) != 0) {        /* end the tape */
+         Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+      }
       dev->state |= (ST_EOF | ST_EOT | ST_WEOT);
        
-      ok = TRUE;
+      ok = true;
 #define CHECK_LAST_BLOCK
 #ifdef CHECK_LAST_BLOCK
       /* 
@@ -452,12 +447,12 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 
         /* Now back up over what we wrote and read the last block */
         if (bsf_dev(dev, 1) != 0 || bsf_dev(dev, 1) != 0) {
-           ok = FALSE;
+           ok = false;
             Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
         }
         /* Backspace over record */
         if (ok && bsr_dev(dev, 1) != 0) {
-           ok = FALSE;
+           ok = false;
             Jmsg(jcr, M_ERROR, 0, _("Backspace record at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
            /*
             *  On FreeBSD systems, if the user got here, it is likely that his/her
index eed019ac31af464fdcece01eaf0df51f28e5e104..91e42c47760a44fd0beae21f65c77bf988ec9f13 100644 (file)
@@ -69,6 +69,7 @@ static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
 static void scan_blocks();
 static void set_volume_name(char *VolName, int volnum);
 static void rawfill_cmd();
+static void bfill_cmd();
 
 
 /* Static variables */
@@ -136,37 +137,37 @@ int main(int argc, char *argv[])
 
    while ((ch = getopt(argc, argv, "b:c:d:sv?")) != -1) {
       switch (ch) {
-         case 'b':                    /* bootstrap file */
-           bsr = parse_bsr(NULL, optarg);
-//         dump_bsr(bsr);
-           break;
+      case 'b':                    /* bootstrap file */
+        bsr = parse_bsr(NULL, optarg);
+//      dump_bsr(bsr);
+        break;
 
-         case 'c':                    /* specify config file */
-           if (configfile != NULL) {
-              free(configfile);
-           }
-           configfile = bstrdup(optarg);
-           break;
+      case 'c':                    /* specify config file */
+        if (configfile != NULL) {
+           free(configfile);
+        }
+        configfile = bstrdup(optarg);
+        break;
 
-         case 'd':                    /* set debug level */
-           debug_level = atoi(optarg);
-           if (debug_level <= 0) {
-              debug_level = 1; 
-           }
-           break;
+      case 'd':                    /* set debug level */
+        debug_level = atoi(optarg);
+        if (debug_level <= 0) {
+           debug_level = 1; 
+        }
+        break;
 
-         case 's':
-           signals = FALSE;
-           break;
+      case 's':
+        signals = FALSE;
+        break;
 
-         case 'v':
-           verbose++;
-           break;
+      case 'v':
+        verbose++;
+        break;
 
-         case '?':
-        default:
-           helpcmd();
-           exit(0);
+      case '?':
+      default:
+        helpcmd();
+        exit(0);
 
       }  
    }
@@ -1020,14 +1021,14 @@ static void scan_blocks()
       blocks++;
       tot_blocks++;
       bytes += block->block_len;
-      Dmsg5(100, "Blk=%u blen=%u bVer=%d SessId=%u SessTim=%u\n",
-        block->BlockNumber, block->block_len, block->BlockVer,
+      Dmsg6(100, "Blk_blk=%u dev_blk=%u blen=%u bVer=%d SessId=%u SessTim=%u\n",
+        block->BlockNumber, dev->block_num, block->block_len, block->BlockVer,
         block->VolSessionId, block->VolSessionTime);
       if (verbose == 1) {
         DEV_RECORD *rec = new_record();
         read_record_from_block(block, rec);
-         Pmsg7(-1, "Block: %u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n",
-             block->BlockNumber, block->block_len,
+         Pmsg8(-1, "Blk_block: %u dev_blk=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n",
+             block->BlockNumber, dev->block_num, block->block_len,
              FI_to_ascii(rec->FileIndex), rec->VolSessionId, rec->VolSessionTime,
              stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len);
         rec->remainder = 0;
@@ -1148,7 +1149,8 @@ This may take a long time -- hours! ...\n\n");
     */
    jcr->VolFirstIndex = 0;
    time(&jcr->run_time);             /* start counting time for rates */
-   Pmsg0(-1, "Begin writing records to first tape ...\n");
+   Pmsg0(-1, "Begin writing Bacula records to first tape ...\n");
+   Pmsg1(-1, "Block num = %d\n", dev->block_num);
    for (file_index = 0; ok && !job_canceled(jcr); ) {
       rec.VolSessionId = jcr->VolSessionId;
       rec.VolSessionTime = jcr->VolSessionTime;
@@ -1177,7 +1179,7 @@ This may take a long time -- hours! ...\n\n");
 
         /* Write block to tape */
         if (!flush_block(block, 1)) {
-           return;
+           break;
         }
 
         /* Every 5000 blocks (approx 322MB) report where we are.
@@ -1189,7 +1191,8 @@ This may take a long time -- hours! ...\n\n");
               now = 1;
            }
            kbs = (double)dev->VolCatInfo.VolCatBytes / (1000.0 * (double)now);
-            Pmsg3(-1, "Wrote block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
+            Pmsg4(-1, "Wrote block=%u, blk_num=%d VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
+              dev->block_num,
               edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), (float)kbs);
         }
         /* Every 15000 blocks (approx 1GB) write an EOF.
@@ -1248,10 +1251,11 @@ This may take a long time -- hours! ...\n\n");
 
    free_block(block);
    free_memory(rec.data);
-   Pmsg0(-1, _("\n\nDone filling tape. Now beginning re-read of tape ...\n"));
 
    dump_block(last_block, _("Last block written to tape.\n"));
 
+   Pmsg0(-1, _("\n\nDone filling tape. Now beginning re-read of tape ...\n"));
+
    unfillcmd();
 }
 
@@ -1476,7 +1480,6 @@ static int flush_block(DEV_BLOCK *block, int dump)
    this_file = dev->file;
    this_block_num = dev->block_num;
    if (!write_block_to_dev(jcr, dev, block)) {
-      Pmsg0(000, strerror_dev(dev));           
       Pmsg3(000, "Block not written: FileIndex=%u Block=%u Size=%u\n", 
         (unsigned)file_index, block->BlockNumber, block->block_len);
       Pmsg2(000, "last_block_num=%u this_block_num=%d\n", last_block_num,
@@ -1561,10 +1564,11 @@ static void qfillcmd()
    memset(rec->data, i & 0xFF, i);
    rec->data_len = i;
    rewindcmd();
-   Pmsg1(0, "Begin writing %d blocks to tape ...\n", count);
+   Pmsg1(0, "Begin writing %d Bacula blocks to tape ...\n", count);
    for (i=0; i < count; i++) {
       if (i % 100 == 0) {
          printf("+");
+        fflush(stdout);
       }
       if (!write_record_to_block(block, rec)) {
          Pmsg0(0, _("Error writing record to block.\n")); 
@@ -1589,6 +1593,9 @@ bail_out:
 
 }
 
+/*
+ * Fill a tape using raw write() command
+ */
 static void rawfill_cmd()
 {
    DEV_BLOCK *block;
@@ -1608,13 +1615,14 @@ static void rawfill_cmd()
       return;
    }
    p = (uint32_t *)block->buf;
-   Pmsg1(0, "Begin writing blocks of %u bytes.\n", block->buf_len);
+   Pmsg1(0, "Begin writing raw blocks of %u bytes.\n", block->buf_len);
    for ( ;; ) {
       *p = block_num;
       stat = write(dev->fd, block->buf, block->buf_len);
       if (stat == (int)block->buf_len) {
         if ((block_num++ % 100) == 0) {
             printf("+");
+           fflush(stdout);
         }
         continue;
       }
@@ -1622,17 +1630,60 @@ static void rawfill_cmd()
    }
    my_errno = errno;
    printf("\n");
-   weofcmd();
    printf("Write failed at block %u. stat=%d ERR=%s\n", block_num, stat,
       strerror(my_errno));
+   weofcmd();
    free_block(block);
+}
 
+
+/*
+ * Fill a tape using raw write() command
+ */
+static void bfill_cmd()
+{
+   DEV_BLOCK *block;
+   uint32_t block_num = 0;
+   uint32_t *p;
+   int my_errno;
+   int fd;
+
+   block = new_block(dev);
+   fd = open("/dev/urandom", O_RDONLY);
+   if (fd) {
+      read(fd, block->buf, block->buf_len);
+   } else {
+      Pmsg0(0, "Cannot open /dev/urandom.\n");
+      free_block(block);
+      return;
+   }
+   p = (uint32_t *)block->buf;
+   Pmsg1(0, "Begin writing Bacula blocks of %u bytes.\n", block->buf_len);
+   for ( ;; ) {
+      *p = block_num;
+      block->binbuf = block->buf_len;
+      block->bufp = block->buf + block->binbuf;
+      if (!write_block_to_dev(jcr, dev, block)) {
+        break;
+      }
+      if ((block_num++ % 100) == 0) {
+         printf("+");
+        fflush(stdout);
+      }
+   }
+   my_errno = errno;
+   printf("\n");
+   printf("Write failed at block %u.\n", block_num);     
+   weofcmd();
+   free_block(block);
 }
 
+
 struct cmdstruct { char *key; void (*func)(); char *help; }; 
 static struct cmdstruct commands[] = {
  {"bsf",        bsfcmd,       "backspace file"},
  {"bsr",        bsrcmd,       "backspace record"},
+ {"bfill",      bfill_cmd,    "fill tape using Bacula writes"},
  {"cap",        capcmd,       "list device capabilities"},
  {"clear",      clearcmd,     "clear tape errors"},
  {"eod",        eodcmd,       "go to end of Bacula data for append"},