]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/catreq.c
Fix bug #1943 no message storage on closed database connection.
[bacula/bacula] / bacula / src / dird / catreq.c
index 1f765da18b324d91a4c120f40bfa594e82c33bab..0cf0b6d92fb07e852dc4625046e30ad5461b5697 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2001-2010 Free Software Foundation Europe e.V.
+   Copyright (C) 2001-2012 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.
@@ -114,7 +114,6 @@ void catalog_request(JCR *jcr, BSOCK *bs)
    utime_t VolFirstWritten;
    utime_t VolLastWritten;
 
-   memset(&mr, 0, sizeof(mr));
    memset(&sdmr, 0, sizeof(sdmr));
    memset(&jm, 0, sizeof(jm));
    Dsm_check(100);      
@@ -141,7 +140,7 @@ void catalog_request(JCR *jcr, BSOCK *bs)
       ok = db_get_pool_record(jcr, jcr->db, &pr);
       if (ok) {
          mr.PoolId = pr.PoolId;
-         mr.StorageId = jcr->wstore->StorageId;
+         set_storageid_in_mr(jcr->wstore, &mr);
          mr.ScratchPoolId = pr.ScratchPoolId;
          ok = find_next_volume_for_append(jcr, &mr, index, fnv_create_vol, fnv_prune);
          Dmsg3(050, "find_media ok=%d idx=%d vol=%s\n", ok, index, mr.VolumeName);
@@ -201,7 +200,7 @@ void catalog_request(JCR *jcr, BSOCK *bs)
             send_volume_info_to_storage_daemon(jcr, bs, &mr);
          } else {
             /* Not suitable volume */
-            bs->fsend(_("1998 Volume \"%s\" status is %s, %s.\n"), mr.VolumeName,
+            bs->fsend(_("1998 Volume \"%s\" catalog status is %s, %s.\n"), mr.VolumeName,
                mr.VolStatus, reason);
          }
 
@@ -281,14 +280,14 @@ void catalog_request(JCR *jcr, BSOCK *bs)
        *   However, do so only if we are writing the tape, i.e.
        *   the number of VolWrites has increased.
        */
-      if (jcr->wstore && jcr->wstore->StorageId && sdmr.VolWrites > mr.VolWrites) {
+      if (jcr->wstore && sdmr.VolWrites > mr.VolWrites) {
          Dmsg2(050, "Update StorageId old=%d new=%d\n",
                mr.StorageId, jcr->wstore->StorageId);
-         if (jcr->wstore->StorageId == 0) {
-            Jmsg(jcr, M_ERROR, 0, _("Attempt to set StorageId to zero.\n"));
-         } else {
-            mr.StorageId = jcr->wstore->StorageId;
-         }
+         /* Update StorageId after write */
+         set_storageid_in_mr(jcr->wstore, &mr);
+      } else {
+         /* Nothing written, reset same StorageId */
+         set_storageid_in_mr(NULL, &mr);
       }
 
       /* Copy updated values to original media record */
@@ -357,6 +356,7 @@ void catalog_request(JCR *jcr, BSOCK *bs)
       Jmsg1(jcr, M_FATAL, 0, _("Invalid Catalog request: %s"), omsg);
       free_memory(omsg);
    }
+
    Dmsg1(400, ">CatReq response: %s", bs->msg);
    Dmsg1(400, "Leave catreq jcr 0x%x\n", jcr);
    return;
@@ -393,8 +393,9 @@ static void update_attribute(JCR *jcr, char *msg, int32_t msglen)
    skip_spaces(&p);
    skip_nonspaces(&p);                /* Job=nnn */
    skip_spaces(&p);
-   skip_nonspaces(&p);                /* FileAttributes */
+   skip_nonspaces(&p);                /* "FileAttributes" */
    p += 1;
+   /* The following "SD header" fields are serialized */
    unser_begin(p, 0);
    unser_uint32(VolSessionId);        /* VolSessionId */
    unser_uint32(VolSessionTime);      /* VolSessionTime */
@@ -403,9 +404,32 @@ static void update_attribute(JCR *jcr, char *msg, int32_t msglen)
    unser_uint32(reclen);              /* Record length */
    p += unser_length(p);              /* Raw record follows */
 
-   /*
+   /**
     * At this point p points to the raw record, which varies according
-    *  to what kind of a record (Stream) was sent
+    *  to what kind of a record (Stream) was sent.  Note, the integer
+    *  fields at the beginning of these "raw" records are in ASCII with
+    *  spaces between them so one can use scanf or manual scanning to
+    *  extract the fields.
+    *
+    * File Attributes
+    *   File_index
+    *   File type
+    *   Filename (full path)
+    *   Encoded attributes
+    *   Link name (if type==FT_LNK or FT_LNKSAVED)
+    *   Encoded extended-attributes (for Win32)
+    *   Delta sequence number (32 bit int)
+    *
+    * Restore Object
+    *   File_index
+    *   File_type
+    *   Object_index
+    *   Object_len (possibly compressed)
+    *   Object_full_len (not compressed)
+    *   Object_compression
+    *   Plugin_name
+    *   Object_name
+    *   Binary Object data
     */
 
    Dmsg1(400, "UpdCat msg=%s\n", msg);
@@ -416,7 +440,7 @@ static void update_attribute(JCR *jcr, char *msg, int32_t msglen)
       if (jcr->cached_attribute) {
          Dmsg2(400, "Cached attr. Stream=%d fname=%s\n", ar->Stream, ar->fname);
          if (!db_create_attributes_record(jcr, jcr->db, ar)) {
-            Jmsg1(jcr, M_FATAL, 0, _("Attribute create error%s"), db_strerror(jcr->db));
+            Jmsg1(jcr, M_FATAL, 0, _("Attribute create error: ERR=%s"), db_strerror(jcr->db));
          }
          jcr->cached_attribute = false;
       }
@@ -424,14 +448,26 @@ static void update_attribute(JCR *jcr, char *msg, int32_t msglen)
       jcr->attr = check_pool_memory_size(jcr->attr, msglen);
       memcpy(jcr->attr, msg, msglen);
       p = jcr->attr - msg + p;    /* point p into jcr->attr */
-      skip_nonspaces(&p);             /* skip FileIndex */
+      skip_nonspaces(&p);         /* skip FileIndex */
       skip_spaces(&p);
-      ar->FileType = str_to_int32(p);     /* TODO: choose between unserialize and str_to_int32 */
-      skip_nonspaces(&p);             /* skip FileType */
+      ar->FileType = str_to_int32(p); 
+      skip_nonspaces(&p);         /* skip FileType */
       skip_spaces(&p);
       fname = p;
       len = strlen(fname);        /* length before attributes */
       attr = &fname[len+1];
+      ar->DeltaSeq = 0;
+      if (ar->FileType == FT_REG) {
+         p = attr + strlen(attr) + 1;  /* point to link */
+         p = p + strlen(p) + 1;        /* point to extended attributes */
+         p = p + strlen(p) + 1;        /* point to delta sequence */
+         /*
+          * Older FDs don't have a delta sequence, so check if it is there 
+          */
+         if (p - jcr->attr < msglen) {
+            ar->DeltaSeq = str_to_int32(p); /* delta_seq */
+         }
+      }
 
       Dmsg2(400, "dird<stored: stream=%d %s\n", Stream, fname);
       Dmsg1(400, "dird<stored: attr=%s\n", attr);
@@ -449,52 +485,64 @@ static void update_attribute(JCR *jcr, char *msg, int32_t msglen)
       } else {
          ar->JobId = jcr->JobId;
       }
-      /*
-       * Restore object */
-      if (ar->FileType == FT_RESTORE_FIRST) {
-         ROBJECT_DBR ro;
-         POOLMEM *attrEx = get_pool_memory(PM_MESSAGE);
-         char *p;
-         memset(&ro, 0, sizeof(ro));
-         ro.full_fname = fname;
-         ro.Stream = Stream;
-         ro.FileType = ar->FileType;
-         ro.FileIndex = FileIndex;
-         ro.JobId = ar->JobId;
-         p = ar->attr;                   /* point to attributes */
-         while (*p++ != 0)               /* skip attributes */
-            { }
-         while (*p++ != 0)               /* skip link */
-            { }
-         /* We have an object, so do a binary copy */
-         ro.object_len = msglen + jcr->attr - p;
-         attrEx = check_pool_memory_size(attrEx, ro.object_len + 1);
-         memcpy(attrEx, p, ro.object_len);  
-         ro.object = attrEx;
-         /* Add a EOS for those who attempt to print the object */
-         p = attrEx + ro.object_len;
-         *p = 0;
-         Dmsg7(000, "fname=%s stream=%d FT=%d FI=%d JobId=%d, obj_len=%d\nobj=\"%s\"\n",
-            ro.full_fname, ro.Stream, ro.FileType, ro.FileIndex, ro.JobId,
-            ro.object_len, attrEx);
-         /* Send it */
-         if (!db_create_restore_object_record(jcr, jcr->db, &ro)) {
-            Jmsg1(jcr, M_FATAL, 0, _("Restore object create error. %s"), db_strerror(jcr->db));
-         }
-         free_pool_memory(attrEx);
-      } else {
-         ar->Digest = NULL;
-         ar->DigestType = CRYPTO_DIGEST_NONE;
-         jcr->cached_attribute = true;
-      }
+      ar->Digest = NULL;
+      ar->DigestType = CRYPTO_DIGEST_NONE;
+      jcr->cached_attribute = true;
 
       Dmsg2(400, "dird<filed: stream=%d %s\n", Stream, fname);
       Dmsg1(400, "dird<filed: attr=%s\n", attr);
 
+   } else if (Stream == STREAM_RESTORE_OBJECT) {
+      ROBJECT_DBR ro;
+
+      memset(&ro, 0, sizeof(ro));
+      ro.Stream = Stream;
+      ro.FileIndex = FileIndex;
+      if (jcr->mig_jcr) {
+         ro.JobId = jcr->mig_jcr->JobId;
+      } else {
+         ro.JobId = jcr->JobId;
+      }
+
+      Dmsg1(100, "Robj=%s\n", p);
+      
+      skip_nonspaces(&p);                  /* skip FileIndex */
+      skip_spaces(&p);
+      ro.FileType = str_to_int32(p);        /* FileType */
+      skip_nonspaces(&p);
+      skip_spaces(&p);
+      ro.object_index = str_to_int32(p);    /* Object Index */
+      skip_nonspaces(&p);
+      skip_spaces(&p);
+      ro.object_len = str_to_int32(p);      /* object length possibly compressed */
+      skip_nonspaces(&p);                  
+      skip_spaces(&p);
+      ro.object_full_len = str_to_int32(p); /* uncompressed object length */
+      skip_nonspaces(&p);
+      skip_spaces(&p);
+      ro.object_compression = str_to_int32(p); /* compression */
+      skip_nonspaces(&p);
+      skip_spaces(&p);
+
+      ro.plugin_name = p;                      /* point to plugin name */
+      len = strlen(ro.plugin_name);
+      ro.object_name = &ro.plugin_name[len+1]; /* point to object name */
+      len = strlen(ro.object_name);
+      ro.object = &ro.object_name[len+1];      /* point to object */
+      ro.object[ro.object_len] = 0;            /* add zero for those who attempt printing */
+      Dmsg7(100, "oname=%s stream=%d FT=%d FI=%d JobId=%d, obj_len=%d\nobj=\"%s\"\n",
+         ro.object_name, ro.Stream, ro.FileType, ro.FileIndex, ro.JobId,
+         ro.object_len, ro.object);
+      /* Send it */
+      if (!db_create_restore_object_record(jcr, jcr->db, &ro)) {
+         Jmsg1(jcr, M_FATAL, 0, _("Restore object create error. %s"), db_strerror(jcr->db));
+      }
+
    } else if (crypto_digest_stream_type(Stream) != CRYPTO_DIGEST_NONE) {
       fname = p;
       if (ar->FileIndex != FileIndex) {
-         Jmsg(jcr, M_WARNING, 0, _("Got %s but not same File as attributes\n"), stream_to_ascii(Stream));
+         Jmsg3(jcr, M_WARNING, 0, _("%s not same File=%d as attributes=%d\n"), 
+            stream_to_ascii(Stream), FileIndex, ar->FileIndex);
       } else {
          /* Update digest in catalog */
          char digestbuf[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
@@ -587,8 +635,7 @@ bool despool_attributes_from_file(JCR *jcr, const char *file)
    bool ret=false;
    int32_t pktsiz;
    size_t nbytes;
-   ssize_t last = 0, size = 0;
-   int count = 0;
+   ssize_t size = 0;
    int32_t msglen;                    /* message length */
    POOLMEM *msg = get_pool_memory(PM_MESSAGE);
    FILE *spool_fd=NULL;
@@ -626,9 +673,6 @@ bool despool_attributes_from_file(JCR *jcr, const char *file)
             goto bail_out;
          }
          size += nbytes;
-         if ((++count & 0x3F) == 0) {
-            last = size;
-         }
       }
       if (!jcr->is_job_canceled()) {
          update_attribute(jcr, msg, msglen);