]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/spool.c
update configure
[bacula/bacula] / bacula / src / stored / spool.c
index 9d6300ae6d249cbed4ff4d153f33d0dc047dbcef..f152ba13173caa9df23ac5649cd5ae89c16b149e 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2004-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2004-2011 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.
 
@@ -15,7 +15,7 @@
    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.
@@ -30,7 +30,6 @@
  *
  *      Kern Sibbald, March 2004
  *
- *  Version $Id$
  */
 
 #include "bacula.h"
@@ -219,8 +218,13 @@ static bool despool_data(DCR *dcr, bool commit)
    JCR *jcr = dcr->jcr;
    int stat;
    char ec1[50];
+   BSOCK *dir = jcr->dir_bsock;
 
    Dmsg0(100, "Despooling data\n");
+   if (jcr->dcr->job_spool_size == 0) {
+      Jmsg(jcr, M_WARNING, 0, _("Despooling zero bytes. Your disk is probably FULL!\n"));
+   }
+
    /*
     * Commit means that the job is done, so we commit, otherwise, we
     *  are despooling because of user spool size max or some error  
@@ -230,13 +234,13 @@ static bool despool_data(DCR *dcr, bool commit)
       Jmsg(jcr, M_INFO, 0, _("Committing spooled data to Volume \"%s\". Despooling %s bytes ...\n"),
          jcr->dcr->VolumeName,
          edit_uint64_with_commas(jcr->dcr->job_spool_size, ec1));
-      set_jcr_job_status(jcr, JS_DataCommitting);
+      jcr->setJobStatus(JS_DataCommitting);
    } else {
       Jmsg(jcr, M_INFO, 0, _("Writing spooled data to Volume. Despooling %s bytes ...\n"),
          edit_uint64_with_commas(jcr->dcr->job_spool_size, ec1));
-      set_jcr_job_status(jcr, JS_DataDespooling);
+      jcr->setJobStatus(JS_DataDespooling);
    }
-   set_jcr_job_status(jcr, JS_DataDespooling);
+   jcr->setJobStatus(JS_DataDespooling);
    dir_send_job_status(jcr);
    dcr->despool_wait = true;
    dcr->spooling = false;
@@ -276,7 +280,7 @@ static bool despool_data(DCR *dcr, bool commit)
 #endif
 
    /* Add run time, to get current wait time */
-   time_t despool_start = time(NULL) - jcr->run_time;
+   int32_t despool_start = time(NULL) - jcr->run_time;
 
    set_new_file_parameters(dcr);
 
@@ -298,25 +302,42 @@ static bool despool_data(DCR *dcr, bool commit)
                dcr->dev->print_name(), dcr->dev->bstrerror());
          Dmsg2(000, "Fatal append error on device %s: ERR=%s\n",
                dcr->dev->print_name(), dcr->dev->bstrerror());
+         /* Force in case Incomplete set */
+         jcr->forceJobStatus(JS_FatalError);
       }
       Dmsg3(800, "Write block ok=%d FI=%d LI=%d\n", ok, block->FirstIndex, block->LastIndex);
    }
 
+   /*
+    * If this Job is incomplete, we need to backup the FileIndex
+    *  to the last correctly saved file so that the JobMedia
+    *  LastIndex is correct.
+    */
+   if (jcr->is_JobStatus(JS_Incomplete)) {
+      dcr->VolLastIndex = dir->get_FileIndex();
+      Dmsg1(100, "======= Set FI=%ld\n", dir->get_FileIndex());
+   }
+
    if (!dir_create_jobmedia_record(dcr)) {
       Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
-         dcr->VolCatInfo.VolCatName, jcr->Job);
+         dcr->getVolCatName(), jcr->Job);
+      jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
    }
    /* Set new file/block parameters for current dcr */
    set_new_file_parameters(dcr);
 
-   /* Subtracting run_time give us elapsed time - wait_time since we started despooling */
-   time_t despool_elapsed = time(NULL) - despool_start - jcr->run_time;
+   /*
+    * Subtracting run_time give us elapsed time - wait_time since 
+    * we started despooling. Note, don't use time_t as it is 32 or 64
+    * bits depending on the OS and doesn't edit with %d
+    */
+   int32_t despool_elapsed = time(NULL) - despool_start - jcr->run_time;
 
    if (despool_elapsed <= 0) {
       despool_elapsed = 1;
    }
 
-   Jmsg(dcr->jcr, M_INFO, 0, _("Despooling elapsed time = %02d:%02d:%02d, Transfer rate = %s bytes/second\n"),
+   Jmsg(jcr, M_INFO, 0, _("Despooling elapsed time = %02d:%02d:%02d, Transfer rate = %s Bytes/second\n"),
          despool_elapsed / 3600, despool_elapsed % 3600 / 60, despool_elapsed % 60,
          edit_uint64_with_suffix(jcr->dcr->job_spool_size / despool_elapsed, ec1));
 
@@ -325,7 +346,7 @@ static bool despool_data(DCR *dcr, bool commit)
    lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */
    if (ftruncate(rdcr->spool_fd, 0) != 0) {
       berrno be;
-      Jmsg(dcr->jcr, M_ERROR, 0, _("Ftruncate spool file failed: ERR=%s\n"),
+      Jmsg(jcr, M_ERROR, 0, _("Ftruncate spool file failed: ERR=%s\n"),
          be.bstrerror());
       /* Note, try continuing despite ftruncate problem */
    }
@@ -350,19 +371,14 @@ static bool despool_data(DCR *dcr, bool commit)
    free(rdev);
    dcr->spooling = true;           /* turn on spooling again */
    dcr->despooling = false;
-
-   /* 
-    * We are done, so unblock the device, but if we have done a 
-    *  commit, leave it locked so that the job cleanup does not
-    *  need to wait to release the device (no re-acquire of the lock).
+   /*
+    * Note, if committing we leave the device blocked. It will be removed in
+    *  release_device();
     */
-   dcr->dlock();
-   unblock_device(dcr->dev);
-   /* If doing a commit, leave the device locked -- unlocked in release_device() */
    if (!commit) {
-      dcr->dunlock();
+      dcr->dev->dunblock();
    }
-   set_jcr_job_status(jcr, JS_Running);
+   jcr->setJobStatus(JS_Running);
    dir_send_job_status(jcr);
    return ok;
 }
@@ -380,6 +396,7 @@ static int read_block_from_spool_file(DCR *dcr)
    ssize_t stat;
    spool_hdr hdr;
    DEV_BLOCK *block = dcr->block;
+   JCR *jcr = dcr->jcr;
 
    rlen = sizeof(hdr);
    stat = read(dcr->spool_fd, (char *)&hdr, (size_t)rlen);
@@ -393,20 +410,23 @@ static int read_block_from_spool_file(DCR *dcr)
               be.bstrerror());
       } else {
          Pmsg2(000, _("Spool read error. Wanted %u bytes, got %d\n"), rlen, stat);
-         Jmsg2(dcr->jcr, M_FATAL, 0, _("Spool header read error. Wanted %u bytes, got %d\n"), rlen, stat);
+         Jmsg2(jcr, M_FATAL, 0, _("Spool header read error. Wanted %u bytes, got %d\n"), rlen, stat);
       }
+      jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
       return RB_ERROR;
    }
    rlen = hdr.len;
    if (rlen > block->buf_len) {
       Pmsg2(000, _("Spool block too big. Max %u bytes, got %u\n"), block->buf_len, rlen);
-      Jmsg2(dcr->jcr, M_FATAL, 0, _("Spool block too big. Max %u bytes, got %u\n"), block->buf_len, rlen);
+      Jmsg2(jcr, M_FATAL, 0, _("Spool block too big. Max %u bytes, got %u\n"), block->buf_len, rlen);
+      jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
       return RB_ERROR;
    }
    stat = read(dcr->spool_fd, (char *)block->buf, (size_t)rlen);
    if (stat != (ssize_t)rlen) {
       Pmsg2(000, _("Spool data read error. Wanted %u bytes, got %d\n"), rlen, stat);
       Jmsg2(dcr->jcr, M_FATAL, 0, _("Spool data read error. Wanted %u bytes, got %d\n"), rlen, stat);
+      jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
       return RB_ERROR;
    }
    /* Setup write pointers */
@@ -432,6 +452,9 @@ bool write_block_to_spool_file(DCR *dcr)
    bool despool = false;
    DEV_BLOCK *block = dcr->block;
 
+   if (job_canceled(dcr->jcr)) {
+      return false;
+   }
    ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf)));
    if (block->binbuf <= WRITE_BLKHDR_LENGTH) {  /* Does block have data in it? */
       return true;
@@ -494,6 +517,7 @@ static bool write_spool_header(DCR *dcr)
    spool_hdr hdr;
    ssize_t stat;
    DEV_BLOCK *block = dcr->block;
+   JCR *jcr = dcr->jcr;
 
    hdr.FirstIndex = block->FirstIndex;
    hdr.LastIndex = block->LastIndex;
@@ -504,10 +528,14 @@ static bool write_spool_header(DCR *dcr)
       stat = write(dcr->spool_fd, (char*)&hdr, sizeof(hdr));
       if (stat == -1) {
          berrno be;
-         Jmsg(dcr->jcr, M_FATAL, 0, _("Error writing header to spool file. ERR=%s\n"),
+         Jmsg(jcr, M_FATAL, 0, _("Error writing header to spool file. ERR=%s\n"),
               be.bstrerror());
+         jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
       }
       if (stat != (ssize_t)sizeof(hdr)) {
+         Jmsg(jcr, M_ERROR, 0, _("Error writing header to spool file."
+              " Disk probably full. Attempting recovery. Wanted to write=%d got=%d\n"),
+              (int)stat, (int)sizeof(hdr));
          /* If we wrote something, truncate it, then despool */
          if (stat != -1) {
 #if defined(HAVE_WIN32)
@@ -523,14 +551,16 @@ static bool write_spool_header(DCR *dcr)
             }
          }
          if (!despool_data(dcr, false)) {
-            Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error."));
+            Jmsg(jcr, M_FATAL, 0, _("Fatal despooling error."));
+            jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
             return false;
          }
          continue;                    /* try again */
       }
       return true;
    }
-   Jmsg(dcr->jcr, M_FATAL, 0, _("Retrying after header spooling error failed.\n"));
+   Jmsg(jcr, M_FATAL, 0, _("Retrying after header spooling error failed.\n"));
+   jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
    return false;
 }
 
@@ -538,14 +568,16 @@ static bool write_spool_data(DCR *dcr)
 {
    ssize_t stat;
    DEV_BLOCK *block = dcr->block;
+   JCR *jcr = dcr->jcr;
 
    /* Write data */
    for (int retry=0; retry<=1; retry++) {
       stat = write(dcr->spool_fd, block->buf, (size_t)block->binbuf);
       if (stat == -1) {
          berrno be;
-         Jmsg(dcr->jcr, M_FATAL, 0, _("Error writing data to spool file. ERR=%s\n"),
+         Jmsg(jcr, M_FATAL, 0, _("Error writing data to spool file. ERR=%s\n"),
               be.bstrerror());
+         jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
       }
       if (stat != (ssize_t)block->binbuf) {
          /*
@@ -565,7 +597,8 @@ static bool write_spool_data(DCR *dcr)
             }
          }
          if (!despool_data(dcr, false)) {
-            Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error."));
+            Jmsg(jcr, M_FATAL, 0, _("Fatal despooling error."));
+            jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
             return false;
          }
          if (!write_spool_header(dcr)) {
@@ -575,7 +608,8 @@ static bool write_spool_data(DCR *dcr)
       }
       return true;
    }
-   Jmsg(dcr->jcr, M_FATAL, 0, _("Retrying after data spooling error failed.\n"));
+   Jmsg(jcr, M_FATAL, 0, _("Retrying after data spooling error failed.\n"));
+   jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
    return false;
 }
 
@@ -628,18 +662,24 @@ static void make_unique_spool_filename(JCR *jcr, POOLMEM **name, int fd)
       jcr->Job, fd);
 }
 
+/*
+ * Tell Director where to find the attributes spool file 
+ *  Note, if we are not on the same machine, the Director will
+ *  return an error, and the higher level routine will transmit
+ *  the data record by record -- using bsock->despool().
+ */
 static bool blast_attr_spool_file(JCR *jcr, boffset_t size)
 {
    /* send full spool file name */
    POOLMEM *name  = get_pool_memory(PM_MESSAGE);
    make_unique_spool_filename(jcr, &name, jcr->dir_bsock->m_fd);
    bash_spaces(name);
-   jcr->dir_bsock->fsend("BlastAttr Job=%s File=%s\n",
-                         jcr->Job, name);
+   jcr->dir_bsock->fsend("BlastAttr Job=%s File=%s\n", jcr->Job, name);
    free_pool_memory(name);
    
    if (jcr->dir_bsock->recv() <= 0) {
       Jmsg(jcr, M_FATAL, 0, _("Network error on BlastAttributes.\n"));
+      jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
       return false;
    }
    
@@ -651,24 +691,44 @@ static bool blast_attr_spool_file(JCR *jcr, boffset_t size)
 
 bool commit_attribute_spool(JCR *jcr)
 {
-   boffset_t size;
+   boffset_t size, data_end;
    char ec1[30];
    char tbuf[100];
+   BSOCK *dir;
 
    Dmsg1(100, "Commit attributes at %s\n", bstrftimes(tbuf, sizeof(tbuf),
-         ( utime_t)time(NULL)));
+         (utime_t)time(NULL)));
    if (are_attributes_spooled(jcr)) {
-      if (fseeko(jcr->dir_bsock->m_spool_fd, 0, SEEK_END) != 0) {
+      dir = jcr->dir_bsock;
+      if (fseeko(dir->m_spool_fd, 0, SEEK_END) != 0) {
          berrno be;
          Jmsg(jcr, M_FATAL, 0, _("Fseek on attributes file failed: ERR=%s\n"),
               be.bstrerror());
+         jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
          goto bail_out;
       }
-      size = ftello(jcr->dir_bsock->m_spool_fd);
+      size = ftello(dir->m_spool_fd);
+      if (jcr->is_JobStatus(JS_Incomplete)) {
+         data_end = dir->get_data_end();
+         /* Check and truncate to last valid data_end if necssary */
+         if (size > data_end) {
+            if (ftruncate(fileno(dir->m_spool_fd), data_end) != 0) {
+               berrno be;
+               Jmsg(jcr, M_FATAL, 0, _("Truncate on attributes file failed: ERR=%s\n"),
+                    be.bstrerror());
+               jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
+               goto bail_out;
+            }
+            Dmsg2(100, "=== Attrib spool truncated from %lld to %lld\n", 
+                  size, data_end);
+            size = data_end;
+         }
+      }
       if (size < 0) {
          berrno be;
          Jmsg(jcr, M_FATAL, 0, _("Fseek on attributes file failed: ERR=%s\n"),
               be.bstrerror());
+         jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
          goto bail_out;
       }
       P(mutex);
@@ -677,7 +737,7 @@ bool commit_attribute_spool(JCR *jcr)
       }
       spool_stats.attr_size += size;
       V(mutex);
-      set_jcr_job_status(jcr, JS_AttrDespooling);
+      jcr->setJobStatus(JS_AttrDespooling);
       dir_send_job_status(jcr);
       Jmsg(jcr, M_INFO, 0, _("Sending spooled attrs to the Director. Despooling %s bytes ...\n"),
             edit_uint64_with_commas(size, ec1));
@@ -686,18 +746,18 @@ bool commit_attribute_spool(JCR *jcr)
          /* Can't read spool file from director side,
           * send content over network.
           */
-         jcr->dir_bsock->despool(update_attr_spool_size, size);
+         dir->despool(update_attr_spool_size, size);
       }
-      return close_attr_spool_file(jcr, jcr->dir_bsock);
+      return close_attr_spool_file(jcr, dir);
    }
    return true;
 
 bail_out:
-   close_attr_spool_file(jcr, jcr->dir_bsock);
+   close_attr_spool_file(jcr, dir);
    return false;
 }
 
-bool open_attr_spool_file(JCR *jcr, BSOCK *bs)
+static bool open_attr_spool_file(JCR *jcr, BSOCK *bs)
 {
    POOLMEM *name  = get_pool_memory(PM_MESSAGE);
 
@@ -707,6 +767,7 @@ bool open_attr_spool_file(JCR *jcr, BSOCK *bs)
       berrno be;
       Jmsg(jcr, M_FATAL, 0, _("fopen attr spool file %s failed: ERR=%s\n"), name,
            be.bstrerror());
+      jcr->forceJobStatus(JS_FatalError);  /* override any Incomplete */
       free_pool_memory(name);
       return false;
    }
@@ -717,14 +778,14 @@ bool open_attr_spool_file(JCR *jcr, BSOCK *bs)
    return true;
 }
 
-bool close_attr_spool_file(JCR *jcr, BSOCK *bs)
+static bool close_attr_spool_file(JCR *jcr, BSOCK *bs)
 {
    POOLMEM *name;
 
    char tbuf[100];
 
    Dmsg1(100, "Close attr spool file at %s\n", bstrftimes(tbuf, sizeof(tbuf),
-         ( utime_t)time(NULL)));
+         (utime_t)time(NULL)));
    if (!bs->m_spool_fd) {
       return true;
    }