]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/spool.c
Implement .bvfs_versions command to display all file versions for a client
[bacula/bacula] / bacula / src / stored / spool.c
index 62426a0c34c13947a23327364ba5607e808869a4..07a2f7cf8ed26502ae275017e64b662c47558ff7 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2004-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2004-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.
@@ -30,7 +30,6 @@
  *
  *      Kern Sibbald, March 2004
  *
- *  Version $Id$
  */
 
 #include "bacula.h"
@@ -99,8 +98,6 @@ void list_spool_stats(void sendit(const char *msg, int len, void *sarg), void *a
    
       sendit(msg.c_str(), len, arg);
    }
-   len = Mmsg(msg, "====\n");
-   sendit(msg.c_str(), len, arg);
 }
 
 bool begin_data_spool(DCR *dcr)
@@ -223,6 +220,10 @@ static bool despool_data(DCR *dcr, bool commit)
    char ec1[50];
 
    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  
@@ -232,16 +233,24 @@ 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);
    } 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);
    }
+   set_jcr_job_status(jcr, JS_DataDespooling);
+   dir_send_job_status(jcr);
    dcr->despool_wait = true;
    dcr->spooling = false;
-   dcr->dev->r_dlock();
+   /*
+    * We work with device blocked, but not locked so that
+    *  other threads -- e.g. reservations can lock the device
+    *  structure.
+    */
+   dcr->dblock(BST_DESPOOLING);
    dcr->despool_wait = false;
    dcr->despooling = true;
-   dcr->dev_locked = true;
 
    /*
     * This is really quite kludgy and should be fixed some time.
@@ -270,7 +279,9 @@ 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);
 
    for ( ; ok; ) {
       if (job_canceled(jcr)) {
@@ -288,18 +299,31 @@ static bool despool_data(DCR *dcr, bool commit)
       if (!ok) {
          Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
                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());
       }
       Dmsg3(800, "Write block ok=%d FI=%d LI=%d\n", ok, block->FirstIndex, block->LastIndex);
    }
 
-   /* Subtracting run_time give us elapsed time - wait_time since we started despooling */
-   time_t despool_elapsed = time(NULL) - despool_start - jcr->run_time;
+   if (!dir_create_jobmedia_record(dcr)) {
+      Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
+         dcr->getVolCatName(), jcr->Job);
+   }
+   /* 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. 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(dcr->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));
 
@@ -333,11 +357,15 @@ static bool despool_data(DCR *dcr, bool commit)
    free(rdev);
    dcr->spooling = true;           /* turn on spooling again */
    dcr->despooling = false;
-   /* If doing a commit, leave the device locked -- unlocked in release_device() */
+   /*
+    * Note, if committing we leave the device blocked. It will be removed in
+    *  release_device();
+    */
    if (!commit) {
-      dcr->dev_locked = false;
-      dcr->dev->dunlock();
+      dcr->dev->dunblock();
    }
+   set_jcr_job_status(jcr, JS_Running);
+   dir_send_job_status(jcr);
    return ok;
 }
 
@@ -406,6 +434,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;
@@ -482,12 +513,15 @@ static bool write_spool_header(DCR *dcr)
               be.bstrerror());
       }
       if (stat != (ssize_t)sizeof(hdr)) {
+         Jmsg(dcr->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)
             boffset_t   pos = _lseeki64(dcr->spool_fd, (__int64)0, SEEK_CUR);
 #else
-            boffset_t   pos = lseek(dcr->spool_fd, (off_t)0, SEEK_CUR);
+            boffset_t   pos = lseek(dcr->spool_fd, 0, SEEK_CUR);
 #endif
             if (ftruncate(dcr->spool_fd, pos - stat) != 0) {
                berrno be;
@@ -529,7 +563,7 @@ static bool write_spool_data(DCR *dcr)
 #if defined(HAVE_WIN32)
             boffset_t   pos = _lseeki64(dcr->spool_fd, (__int64)0, SEEK_CUR);
 #else
-            boffset_t   pos = lseek(dcr->spool_fd, (off_t)0, SEEK_CUR);
+            boffset_t   pos = lseek(dcr->spool_fd, 0, SEEK_CUR);
 #endif
             if (ftruncate(dcr->spool_fd, pos - stat - sizeof(spool_hdr)) != 0) {
                berrno be;
@@ -596,11 +630,46 @@ static void update_attr_spool_size(ssize_t size)
    V(mutex);
 }
 
+static void make_unique_spool_filename(JCR *jcr, POOLMEM **name, int fd)
+{
+   Mmsg(name, "%s/%s.attr.%s.%d.spool", working_directory, my_name,
+      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);
+   free_pool_memory(name);
+   
+   if (jcr->dir_bsock->recv() <= 0) {
+      Jmsg(jcr, M_FATAL, 0, _("Network error on BlastAttributes.\n"));
+      return false;
+   }
+   
+   if (!bstrcmp(jcr->dir_bsock->msg, "1000 OK BlastAttr\n")) {
+      return false;
+   }
+   return true;
+}
+
 bool commit_attribute_spool(JCR *jcr)
 {
-   off_t size;
+   boffset_t size;
    char ec1[30];
+   char tbuf[100];
 
+   Dmsg1(100, "Commit attributes at %s\n", bstrftimes(tbuf, sizeof(tbuf),
+         (utime_t)time(NULL)));
    if (are_attributes_spooled(jcr)) {
       if (fseeko(jcr->dir_bsock->m_spool_fd, 0, SEEK_END) != 0) {
          berrno be;
@@ -621,9 +690,17 @@ bool commit_attribute_spool(JCR *jcr)
       }
       spool_stats.attr_size += size;
       V(mutex);
+      set_jcr_job_status(jcr, 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));
-      jcr->dir_bsock->despool(update_attr_spool_size, size);
+
+      if (!blast_attr_spool_file(jcr, size)) {
+         /* Can't read spool file from director side,
+          * send content over network.
+          */
+         jcr->dir_bsock->despool(update_attr_spool_size, size);
+      }
       return close_attr_spool_file(jcr, jcr->dir_bsock);
    }
    return true;
@@ -633,14 +710,7 @@ bail_out:
    return false;
 }
 
-static void make_unique_spool_filename(JCR *jcr, POOLMEM **name, int fd)
-{
-   Mmsg(name, "%s/%s.attr.%s.%d.spool", working_directory, my_name,
-      jcr->Job, fd);
-}
-
-
-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);
 
@@ -660,10 +730,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)));
    if (!bs->m_spool_fd) {
       return true;
    }