]> git.sur5r.net Git - bacula/bacula/commitdiff
Add delta sequence to batch mode, accurate query and file daemon ff_pkt
authorEric Bollengier <eric@eb.homelinux.org>
Thu, 18 Nov 2010 13:30:23 +0000 (14:30 +0100)
committerEric Bollengier <eric@eb.homelinux.org>
Thu, 18 Nov 2010 17:46:37 +0000 (18:46 +0100)
bacula/src/cats/postgresql.c
bacula/src/cats/sql_cmds.c
bacula/src/cats/sql_create.c
bacula/src/cats/sql_get.c
bacula/src/dird/backup.c
bacula/src/filed/accurate.c
bacula/src/filed/backup.c
bacula/src/findlib/find.h

index 959baf75ed239ab91f2c73307b47754834db3f9e..954b034978e7992297ef674763594c727fd54f05 100644 (file)
@@ -749,7 +749,8 @@ int my_postgresql_batch_start(JCR *jcr, B_DB *mdb)
                                "path varchar,"
                                "name varchar,"
                                "lstat varchar,"
-                               "md5 varchar)") == 1)
+                               "md5 varchar,"
+                               "markid int)") == 1)
    {
       Dmsg0(500, "my_postgresql_batch_start failed\n");
       return 1;
@@ -857,9 +858,9 @@ int my_postgresql_batch_insert(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
       digest = ar->Digest;
    }
 
-   len = Mmsg(mdb->cmd, "%u\t%s\t%s\t%s\t%s\t%s\n", 
+   len = Mmsg(mdb->cmd, "%u\t%s\t%s\t%s\t%s\t%s\t%u\n", 
               ar->FileIndex, edit_int64(ar->JobId, ed1), mdb->esc_path, 
-              mdb->esc_name, ar->attr, digest);
+              mdb->esc_name, ar->attr, digest, ar->DeltaSeq);
 
    do { 
       res = PQputCopyData(mdb->db,
index e94298c7a564866ea85739297451dbd3781c330b..b0070cc63f4f4ac2feb563d3bb04e6d11d4f4f21 100644 (file)
@@ -280,7 +280,7 @@ const char *uar_jobids_fileindex =
 const char *uar_jobid_fileindex_from_table = 
    "SELECT JobId,FileIndex from %s";
 
-/* Get the list of the last recent version with a given jobid list 
+/* Get the list of the last recent version per Delta with a given jobid list 
  * This is a tricky part because with SQL the result of 
  *
  * SELECT MAX(A), B, C, D FROM... GROUP BY (B,C)
@@ -290,10 +290,9 @@ const char *uar_jobid_fileindex_from_table =
  * With PostgreSQL, we can use DISTINCT ON(), but with Mysql or Sqlite,
  * we need an extra join using JobTDate. 
  */
-const char *select_recent_version_with_basejob[5] = {
- /* MySQL */
+const char *select_recent_version_with_basejob_default = 
 "SELECT FileId, Job.JobId AS JobId, FileIndex, File.PathId AS PathId, "
-       "File.FilenameId AS FilenameId, LStat, MD5 "
+       "File.FilenameId AS FilenameId, LStat, MD5, MarkId "
 "FROM Job, File, ( "
     "SELECT MAX(JobTDate) AS JobTDate, PathId, FilenameId "
       "FROM ( "
@@ -306,7 +305,8 @@ const char *select_recent_version_with_basejob[5] = {
                "JOIN File USING (FileId) "
                "JOIN Job  ON    (BaseJobId = Job.JobId) "
          "WHERE BaseFiles.JobId IN (%s) "        /* Use Max(JobTDate) to find */
-       ") AS tmp GROUP BY PathId, FilenameId "   /* the latest file version */
+       ") AS tmp "
+       "GROUP BY PathId, FilenameId "            /* the latest file version */
     ") AS T1 "
 "WHERE (Job.JobId IN ( "  /* Security, we force JobId to be valid */
         "SELECT DISTINCT BaseJobId FROM BaseFiles WHERE JobId IN (%s)) "
@@ -314,102 +314,110 @@ const char *select_recent_version_with_basejob[5] = {
   "AND T1.JobTDate = Job.JobTDate " /* Join on JobTDate to get the orginal */
   "AND Job.JobId = File.JobId "     /* Job/File record */
   "AND T1.PathId = File.PathId "
-  "AND T1.FilenameId = File.FilenameId",
+  "AND T1.FilenameId = File.FilenameId";
+
+const char *select_recent_version_with_basejob[5] = {
+ /* MySQL */
+   select_recent_version_with_basejob_default,
 
   /* Postgresql */    /* The DISTINCT ON () permits to avoid extra join */
  "SELECT DISTINCT ON (FilenameId, PathId) StartTime, JobId, FileId, "
-         "FileIndex, PathId, FilenameId, LStat, MD5 "
+         "FileIndex, PathId, FilenameId, LStat, MD5, MarkId "
    "FROM "
-       "(SELECT FileId, JobId, PathId, FilenameId, FileIndex, LStat, MD5 "
-          "FROM File WHERE JobId IN (%s) "
-         "UNION ALL "
-        "SELECT File.FileId, File.JobId, PathId, FilenameId, "
-               "File.FileIndex, LStat, MD5 "
-          "FROM BaseFiles JOIN File USING (FileId) "
-         "WHERE BaseFiles.JobId IN (%s) "
-        ") AS T JOIN Job USING (JobId) "
+     "(SELECT FileId, JobId, PathId, FilenameId, FileIndex, LStat, MD5, MarkId "
+         "FROM File WHERE JobId IN (%s) "
+        "UNION ALL "
+       "SELECT File.FileId, File.JobId, PathId, FilenameId, "
+              "File.FileIndex, LStat, MD5, MarkId "
+         "FROM BaseFiles JOIN File USING (FileId) "
+        "WHERE BaseFiles.JobId IN (%s) "
+       ") AS T JOIN Job USING (JobId) "
    "ORDER BY FilenameId, PathId, StartTime DESC ",
 
-  /* SQLite */              /* See Mysql section for doc */
-"SELECT FileId, Job.JobId AS JobId, FileIndex, File.PathId AS PathId, "
-       "File.FilenameId AS FilenameId, LStat, MD5 "
-"FROM Job, File, ( "
-    "SELECT MAX(JobTDate) AS JobTDate, PathId, FilenameId "
-      "FROM ( "
-        "SELECT JobTDate, PathId, FilenameId "
-          "FROM File JOIN Job USING (JobId) "
-         "WHERE File.JobId IN (%s) "
-          "UNION ALL "
-        "SELECT JobTDate, PathId, FilenameId "
-          "FROM BaseFiles "
-               "JOIN File USING (FileId) "
-               "JOIN Job  ON    (BaseJobId = Job.JobId) "
-         "WHERE BaseFiles.JobId IN (%s) "
-       ") AS tmp GROUP BY PathId, FilenameId "
-    ") AS T1 "
-"WHERE (Job.JobId IN ( "
-       "SELECT DISTINCT BaseJobId FROM BaseFiles WHERE JobId IN (%s)) "
-       "OR Job.JobId IN (%s)) "
-  "AND T1.JobTDate = Job.JobTDate "
-  "AND Job.JobId = File.JobId "
-  "AND T1.PathId = File.PathId "
-  "AND T1.FilenameId = File.FilenameId",
+  /* SQLite */
+   select_recent_version_with_basejob_default,
 
- /* SQLite3 */              /* See Mysql section for doc */
-"SELECT FileId, Job.JobId AS JobId, FileIndex, File.PathId AS PathId, "
-       "File.FilenameId AS FilenameId, LStat, MD5 "
-"FROM Job, File, ( "
-    "SELECT MAX(JobTDate) AS JobTDate, PathId, FilenameId "
-      "FROM ( "
-        "SELECT JobTDate, PathId, FilenameId "
-          "FROM File JOIN Job USING (JobId) "
-         "WHERE File.JobId IN (%s) "
-          "UNION ALL "
-        "SELECT JobTDate, PathId, FilenameId "
-          "FROM BaseFiles "
-               "JOIN File USING (FileId) "
-               "JOIN Job  ON    (BaseJobId = Job.JobId) "
-         "WHERE BaseFiles.JobId IN (%s) "
-       ") AS tmp GROUP BY PathId, FilenameId "
-    ") AS T1 "
-"WHERE (Job.JobId IN ( "
-         "SELECT DISTINCT BaseJobId FROM BaseFiles WHERE JobId IN (%s)) "
-        "OR Job.JobId IN (%s)) "
-  "AND T1.JobTDate = Job.JobTDate "
-  "AND Job.JobId = File.JobId "
-  "AND T1.PathId = File.PathId "
-  "AND T1.FilenameId = File.FilenameId",
+ /* SQLite3 */
+   select_recent_version_with_basejob_default,
+
+  /* Ingres */
+   select_recent_version_with_basejob_default
+};
 
-  /* Ingres */              /* See Mysql section for doc */
+/* We do the same thing than the previous query, but we include
+ * all delta parts. If the file has been deleted, we can have irrelevant
+ * parts.
+ *
+ * The code that uses results should control the delta sequence with
+ * the following rules:
+ * First Delta = 0
+ * Delta = Previous Delta + 1
+ *
+ * If we detect a gap, we can discard further pieces
+ * If a file starts at 1 instead of 0, the file has been deleted, and further
+ * pieces are useless.
+ * 
+ * This control should be reset for each new file
+ */
+const char *select_recent_version_with_basejob_and_delta_default = 
 "SELECT FileId, Job.JobId AS JobId, FileIndex, File.PathId AS PathId, "
-       "File.FilenameId AS FilenameId, LStat, MD5 "
+       "File.FilenameId AS FilenameId, LStat, MD5, MarkId "
 "FROM Job, File, ( "
-    "SELECT MAX(JobTDate) AS JobTDate, PathId, FilenameId "
+    "SELECT MAX(JobTDate) AS JobTDate, PathId, FilenameId, MarkId "
       "FROM ( "
-        "SELECT JobTDate, PathId, FilenameId "
-          "FROM File JOIN Job USING (JobId) "
+        "SELECT JobTDate, PathId, FilenameId "   /* Get all normal files */
+          "FROM File JOIN Job USING (JobId) "    /* from selected backup */
          "WHERE File.JobId IN (%s) "
           "UNION ALL "
-        "SELECT JobTDate, PathId, FilenameId "
-          "FROM BaseFiles "
+        "SELECT JobTDate, PathId, FilenameId "   /* Get all files from */ 
+          "FROM BaseFiles "                      /* BaseJob */
                "JOIN File USING (FileId) "
                "JOIN Job  ON    (BaseJobId = Job.JobId) "
-         "WHERE BaseFiles.JobId IN (%s) "
-       ") AS tmp GROUP BY PathId, FilenameId "
+         "WHERE BaseFiles.JobId IN (%s) "        /* Use Max(JobTDate) to find */
+       ") AS tmp "
+       "GROUP BY PathId, FilenameId, MarkId "    /* the latest file version */
     ") AS T1 "
-"WHERE (Job.JobId IN ( "
-         "SELECT DISTINCT BaseJobId FROM BaseFiles WHERE JobId IN (%s)) "
+"WHERE (Job.JobId IN ( "  /* Security, we force JobId to be valid */
+        "SELECT DISTINCT BaseJobId FROM BaseFiles WHERE JobId IN (%s)) "
         "OR Job.JobId IN (%s)) "
-  "AND T1.JobTDate = Job.JobTDate "
-  "AND Job.JobId = File.JobId "
+  "AND T1.JobTDate = Job.JobTDate " /* Join on JobTDate to get the orginal */
+  "AND Job.JobId = File.JobId "     /* Job/File record */
   "AND T1.PathId = File.PathId "
-  "AND T1.FilenameId = File.FilenameId"
+  "AND T1.FilenameId = File.FilenameId";
+
+const char *select_recent_version_with_basejob_and_delta[5] = {
+ /* MySQL */
+   select_recent_version_with_basejob_and_delta_default,
+
+  /* Postgresql */    /* The DISTINCT ON () permits to avoid extra join */
+ "SELECT DISTINCT ON (FilenameId, PathId, MarkId) JobTDate, JobId, FileId, "
+         "FileIndex, PathId, FilenameId, LStat, MD5, MarkId "
+   "FROM "
+     "(SELECT FileId, JobId, PathId, FilenameId, FileIndex, LStat, MD5, MarkId "
+         "FROM File WHERE JobId IN (%s) "
+        "UNION ALL "
+       "SELECT File.FileId, File.JobId, PathId, FilenameId, "
+              "File.FileIndex, LStat, MD5, MarkId "
+         "FROM BaseFiles JOIN File USING (FileId) "
+        "WHERE BaseFiles.JobId IN (%s) "
+       ") AS T JOIN Job USING (JobId) "
+   "ORDER BY FilenameId, PathId, MarkId, JobTDate DESC ",
+
+  /* SQLite */
+   select_recent_version_with_basejob_and_delta_default,
+
+ /* SQLite3 */
+   select_recent_version_with_basejob_and_delta_default,
+
+  /* Ingres */
+   select_recent_version_with_basejob_and_delta_default
 };
 
-/* Get the list of the last recent version with a given BaseJob jobid list */
-const char *select_recent_version[5] = {
-   /* MySQL */
-   "SELECT j1.JobId AS JobId, f1.FileId AS FileId, f1.FileIndex AS FileIndex, "
+/* Get the list of the last recent version with a given BaseJob jobid list
+ * We don't handle Delta with BaseJobs, they have only Full files
+ */
+const char *select_recent_version_default = 
+  "SELECT j1.JobId AS JobId, f1.FileId AS FileId, f1.FileIndex AS FileIndex, "
           "f1.PathId AS PathId, f1.FilenameId AS FilenameId, "
           "f1.LStat AS LStat, f1.MD5 AS MD5 "
      "FROM ( "     /* Choose the last version for each Path/Filename */
@@ -422,62 +430,27 @@ const char *select_recent_version[5] = {
       "AND j1.JobId IN (%s) "
       "AND t1.FilenameId = f1.FilenameId "
       "AND t1.PathId = f1.PathId "
-      "AND j1.JobId = f1.JobId",
+      "AND j1.JobId = f1.JobId";
+
+const char *select_recent_version[5] = {
+   /* MySQL */
+   select_recent_version_default,
 
    /* Postgresql */
-   "SELECT DISTINCT ON (FilenameId, PathId) StartTime, JobId, FileId, "
+   "SELECT DISTINCT ON (FilenameId, PathId) JobTDate, JobId, FileId, "
           "FileIndex, PathId, FilenameId, LStat, MD5 "
      "FROM File JOIN Job USING (JobId) "
     "WHERE JobId IN (%s) "
-    "ORDER BY FilenameId, PathId, StartTime DESC ",
+    "ORDER BY FilenameId, PathId, JobTDate DESC ",
 
    /* SQLite */
-   "SELECT j1.JobId AS JobId, f1.FileId AS FileId, f1.FileIndex AS FileIndex, "
-          "f1.PathId AS PathId, f1.FilenameId AS FilenameId, "
-          "f1.LStat AS LStat, f1.MD5 AS MD5 "
-     "FROM ( "
-       "SELECT max(JobTDate) AS JobTDate, PathId, FilenameId "
-         "FROM File JOIN Job USING (JobId) "
-        "WHERE File.JobId IN (%s) "
-       "GROUP BY PathId, FilenameId "
-     ") AS t1, Job AS j1, File AS f1 "
-    "WHERE t1.JobTDate = j1.JobTDate "
-      "AND j1.JobId IN (%s) "
-      "AND t1.FilenameId = f1.FilenameId "
-      "AND t1.PathId = f1.PathId "
-      "AND j1.JobId = f1.JobId",
+   select_recent_version_default,
 
    /* SQLite3 */
-   "SELECT j1.JobId AS JobId, f1.FileId AS FileId, f1.FileIndex AS FileIndex, "
-          "f1.PathId AS PathId, f1.FilenameId AS FilenameId, "
-          "f1.LStat AS LStat, f1.MD5 AS MD5 "
-     "FROM ( "
-       "SELECT max(JobTDate) AS JobTDate, PathId, FilenameId "
-         "FROM File JOIN Job USING (JobId) "
-        "WHERE File.JobId IN (%s) "
-       "GROUP BY PathId, FilenameId "
-     ") AS t1, Job AS j1, File AS f1 "
-    "WHERE t1.JobTDate = j1.JobTDate "
-      "AND j1.JobId IN (%s) "
-      "AND t1.FilenameId = f1.FilenameId "
-      "AND t1.PathId = f1.PathId "
-      "AND j1.JobId = f1.JobId",
+   select_recent_version_default,
 
    /* Ingres */
-   "SELECT j1.JobId AS JobId, f1.FileId AS FileId, f1.FileIndex AS FileIndex, "
-          "f1.PathId AS PathId, f1.FilenameId AS FilenameId, "
-          "f1.LStat AS LStat, f1.MD5 AS MD5 "
-     "FROM ( "     /* Choose the last version for each Path/Filename */
-       "SELECT max(JobTDate) AS JobTDate, PathId, FilenameId "
-         "FROM File JOIN Job USING (JobId) "
-        "WHERE File.JobId IN (%s) "
-       "GROUP BY PathId, FilenameId "
-     ") AS t1, Job AS j1, File AS f1 "
-    "WHERE t1.JobTDate = j1.JobTDate "
-      "AND j1.JobId IN (%s) "
-      "AND t1.FilenameId = f1.FilenameId "
-      "AND t1.PathId = f1.PathId "
-      "AND j1.JobId = f1.JobId"
+   select_recent_version_default
 };
 
 /* We don't create this table as TEMPORARY because MySQL MyISAM 
index 3dcc13c81e5707f5020157a784c0be3289fb7488..1998aebec74814f00270b3d6aee166e7cb231dd4 100644 (file)
@@ -763,7 +763,8 @@ bool my_batch_start(JCR *jcr, B_DB *mdb)
                 "Path blob,"
                 "Name blob,"
                 "LStat tinyblob,"
-                "MD5 tinyblob)",NULL, NULL);
+                "MD5 tinyblob,"
+                "MarkId integer)",NULL, NULL);
    db_unlock(mdb);
    return ok;
 }
@@ -790,9 +791,10 @@ bool my_batch_insert(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
       digest = ar->Digest;
    }
 
-   len = Mmsg(mdb->cmd, "INSERT INTO batch VALUES (%u,%s,'%s','%s','%s','%s')",
+   len = Mmsg(mdb->cmd, "INSERT INTO batch VALUES "
+                         "(%u,%s,'%s','%s','%s','%s',%u)",
               ar->FileIndex, edit_int64(ar->JobId,ed1), mdb->esc_path, 
-              mdb->esc_name, ar->attr, digest);
+              mdb->esc_name, ar->attr, digest, ar->DeltaSeq);
 
    return INSERT_DB(jcr, mdb, mdb->cmd);
 }
@@ -884,12 +886,12 @@ bool db_write_batch_file_records(JCR *jcr)
    }
    
    if (!db_sql_query(jcr->db_batch, 
-       "INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5) "
-         "SELECT batch.FileIndex, batch.JobId, Path.PathId, "
-                "Filename.FilenameId,batch.LStat, batch.MD5 "
-           "FROM batch "
-           "JOIN Path ON (batch.Path = Path.Path) "
-           "JOIN Filename ON (batch.Name = Filename.Name)",
+  "INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5, MarkId) "
+    "SELECT batch.FileIndex, batch.JobId, Path.PathId, "
+           "Filename.FilenameId,batch.LStat, batch.MD5, batch.MarkId "
+      "FROM batch "
+      "JOIN Path ON (batch.Path = Path.Path) "
+      "JOIN Filename ON (batch.Name = Filename.Name)",
                      NULL,NULL))
    {
       Jmsg1(jcr, M_FATAL, 0, "Fill File table %s\n", jcr->db_batch->errmsg);
@@ -1023,9 +1025,9 @@ static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
    /* Must create it */
    Mmsg(mdb->cmd,
         "INSERT INTO File (FileIndex,JobId,PathId,FilenameId,"
-        "LStat,MD5) VALUES (%u,%u,%u,%u,'%s','%s')",
+        "LStat,MD5,MarkId) VALUES (%u,%u,%u,%u,'%s','%s',%u)",
         ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId,
-        ar->attr, digest);
+        ar->attr, digest, ar->DeltaSeq);
 
    ar->FileId = sql_insert_autokey_record(mdb, mdb->cmd, NT_("File"));
    if (ar->FileId == 0) {
index f5b226d902417c90d53b3ab6e09d237ce64bfaac..069fb0b321cdb64182ea737f80ff0194624c4cd7 100644 (file)
@@ -1111,14 +1111,15 @@ bool db_get_file_list(JCR *jcr, B_DB *mdb, char *jobids,
    Mmsg(buf2, select_recent_version_with_basejob[db_type], 
         jobids, jobids, jobids, jobids);
    Mmsg(buf,
-"SELECT Path.Path, Filename.Name, Temp.FileIndex, Temp.JobId, LStat, MD5 "
- "FROM ( %s ) AS Temp "
- "JOIN Filename ON (Filename.FilenameId = Temp.FilenameId) "
- "JOIN Path ON (Path.PathId = Temp.PathId) "
+"SELECT Path.Path, Filename.Name, T1.FileIndex, T1.JobId, LStat, MD5, MarkId "
+ "FROM ( %s ) AS T1 "
+ "JOIN Filename ON (Filename.FilenameId = T1.FilenameId) "
+ "JOIN Path ON (Path.PathId = T1.PathId) "
 "WHERE FileIndex > 0 "
-"ORDER BY Temp.JobId, FileIndex ASC",/* Return sorted by JobId, */
+"ORDER BY T1.JobId, FileIndex ASC",/* Return sorted by JobId, */
                                      /* FileIndex for restore code */ 
         buf2.c_str());
+   Dmsg1(100, "q=%s\n", buf.c_str());
 #else
    /*  
     * I am not sure that this works the same as the code in ua_restore.c but it
@@ -1243,7 +1244,7 @@ bool db_get_base_file_list(JCR *jcr, B_DB *mdb,
    POOL_MEM buf(PM_MESSAGE);
          
    Mmsg(buf,
- "SELECT Path, Name, FileIndex, JobId, LStat, MD5 "
+ "SELECT Path, Name, FileIndex, JobId, LStat, MD5, 0 As MarkId "
    "FROM new_basefile%lld ORDER BY JobId, FileIndex ASC",
         (uint64_t) jcr->JobId);
 
index 746346abfb22105214762795e77148017a416d0c..9467a478b9a0f2b867242f9dac37766821d85809 100644 (file)
@@ -137,7 +137,7 @@ static bool get_base_jobids(JCR *jcr, db_list_ctx *jobids)
 }
 
 /*
- * Foreach files in currrent list, send "/path/fname\0LStat\0MD5" to FD
+ * Foreach files in currrent list, send "/path/fname\0LStat\0MD5\0Delta" to FD
  */
 static int accurate_list_handler(void *ctx, int num_fields, char **row)
 {
@@ -147,21 +147,21 @@ static int accurate_list_handler(void *ctx, int num_fields, char **row)
       return 1;
    }
    
-   if (row[2] == 0) {           /* discard when file_index == 0 */
+   if (row[2][0] == '0') {           /* discard when file_index == 0 */
       return 0;
    }
 
    /* sending with checksum */
    if (jcr->use_accurate_chksum 
-       && num_fields == 6 
+       && num_fields == 7 
        && row[5][0] /* skip checksum = '0' */
        && row[5][1])
    { 
-      jcr->file_bsock->fsend("%s%s%c%s%c%s", 
-                             row[0], row[1], 0, row[4], 0, row[5]); 
+      jcr->file_bsock->fsend("%s%s%c%s%c%s%c%s", 
+                             row[0], row[1], 0, row[4], 0, row[5], 0, row[6]); 
    } else {
-      jcr->file_bsock->fsend("%s%s%c%s", 
-                             row[0], row[1], 0, row[4]); 
+      jcr->file_bsock->fsend("%s%s%c%s%c%c%s", 
+                             row[0], row[1], 0, row[4], 0, 0, row[6]); 
    }
    return 0;
 }
@@ -229,8 +229,8 @@ static bool is_checksum_needed_by_fileset(JCR *jcr)
 /*
  * Send current file list to FD
  *    DIR -> FD : accurate files=xxxx
- *    DIR -> FD : /path/to/file\0Lstat\0MD5
- *    DIR -> FD : /path/to/dir/\0Lstat\0MD5
+ *    DIR -> FD : /path/to/file\0Lstat\0MD5\0Delta
+ *    DIR -> FD : /path/to/dir/\0Lstat\0MD5\0Delta
  *    ...
  *    DIR -> FD : EOD
  */
index edaa3c2a19e08069363f6fce3371aaf05580f1db..bd2fa1a9e0a87724ccbb604a4847f3841d9cdf36 100644 (file)
@@ -40,6 +40,7 @@ typedef struct PrivateCurFile {
    char *fname;
    char *lstat;
    char *chksum;
+   int32_t delta_seq;
    bool seen;
 } CurFile;
 
@@ -199,7 +200,8 @@ bool accurate_finish(JCR *jcr)
 }
 
 static bool accurate_add_file(JCR *jcr, uint32_t len, 
-                              char *fname, char *lstat, char *chksum)
+                              char *fname, char *lstat, char *chksum,
+                              int32_t delta)
 {
    bool ret = true;
    CurFile elt;
@@ -219,9 +221,12 @@ static bool accurate_add_file(JCR *jcr, uint32_t len,
    item->chksum = item->lstat+strlen(item->lstat)+1;
    strcpy(item->chksum, chksum);
 
+   item->delta_seq = delta;
+
    jcr->file_list->insert(item->fname, item); 
 
-   Dmsg3(dbglvl, "add fname=<%s> lstat=%s chksum=%s\n", fname, lstat, chksum);
+   Dmsg4(dbglvl, "add fname=<%s> lstat=%s  delta_seq=%i chksum=%s\n", 
+         fname, lstat, delta, chksum);
    return ret;
 }
 
@@ -246,6 +251,8 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
    char *fname;
    CurFile elt;
 
+   ff_pkt->delta_seq = 0;
+
    if (!jcr->accurate) {
       return true;
    }
@@ -264,6 +271,9 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
       goto bail_out;
    }
 
+   ff_pkt->delta_seq = elt.delta_seq;
+   Dmsg1(10, "accurate delta_seq=%i\n", ff_pkt->delta_seq);
+
    if (elt.seen) { /* file has been seen ? */
       Dmsg1(dbglvl, "accurate %s (already seen)\n", fname);
       goto bail_out;
@@ -479,6 +489,7 @@ int accurate_cmd(JCR *jcr)
    BSOCK *dir = jcr->dir_bsock;
    int lstat_pos, chksum_pos;
    int32_t nb;
+   uint16_t delta_seq;
 
    if (job_canceled(jcr)) {
       return true;
@@ -494,7 +505,7 @@ int accurate_cmd(JCR *jcr)
 
    /*
     * buffer = sizeof(CurFile) + dirmsg
-    * dirmsg = fname + \0 + lstat + \0 + checksum + \0
+    * dirmsg = fname + \0 + lstat + \0 + checksum + \0 + delta_seq + \0
     */
    /* get current files */
    while (dir->recv() >= 0) {
@@ -504,12 +515,18 @@ int accurate_cmd(JCR *jcr)
 
          if (chksum_pos >= dir->msglen) {
             chksum_pos = lstat_pos - 1;    /* tweak: no checksum, point to the last \0 */
-         } 
+            delta_seq = 0;
+         } else {
+            delta_seq = str_to_int32(dir->msg + 
+                                     chksum_pos + 
+                                     strlen(dir->msg + chksum_pos) + 1);
+         }
 
          accurate_add_file(jcr, dir->msglen, 
                            dir->msg,               /* Path */
                            dir->msg + lstat_pos,   /* LStat */
-                           dir->msg + chksum_pos); /* CheckSum */
+                           dir->msg + chksum_pos,  /* CheckSum */
+                           delta_seq);             /* Delta Sequence */
       }
    }
 
index 9dcf15efee302c3bbba145668ce35a274a06bbfa..3116d7f62e59400a1cb5a9c6ea1d46172f9f3397 100644 (file)
@@ -1187,15 +1187,16 @@ bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream)
    case FT_LNK:
    case FT_LNKSAVED:
       Dmsg2(300, "Link %s to %s\n", ff_pkt->fname, ff_pkt->link);
-      stat = sd->fsend("%ld %d %s%c%s%c%s%c%s%c", jcr->JobFiles,
-               ff_pkt->type, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0,
-               attribsEx, 0);
+      stat = sd->fsend("%ld %d %s%c%s%c%s%c%s%c%u%c", jcr->JobFiles,
+                       ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 
+                       ff_pkt->link, 0, attribsEx, 0, ff_pkt->delta_seq, 0);
       break;
    case FT_DIREND:
    case FT_REPARSE:
       /* Here link is the canonical filename (i.e. with trailing slash) */
-      stat = sd->fsend("%ld %d %s%c%s%c%c%s%c", jcr->JobFiles,
-               ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, attribsEx, 0);
+      stat = sd->fsend("%ld %d %s%c%s%c%c%s%c%u%c", jcr->JobFiles,
+                       ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, 
+                       attribsEx, 0, ff_pkt->delta_seq, 0);
       break;
    case FT_RESTORE_FIRST:
       comp_len = ff_pkt->object_len;
@@ -1229,8 +1230,9 @@ bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream)
       }
       break;
    default:
-      stat = sd->fsend("%ld %d %s%c%s%c%c%s%c", jcr->JobFiles,
-               ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0, attribsEx, 0);
+      stat = sd->fsend("%ld %d %s%c%s%c%c%s%c%u%c", jcr->JobFiles,
+                       ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0, 
+                       attribsEx, 0, ff_pkt->delta_seq, 0);
       break;
    }
    if (ff_pkt->type != FT_DELETED) {
index 6a57528a2e69a2c1a9fbad82d9b696be48f3a31b..4939d7446cf94a3c926acce16af57bc753ba670a 100644 (file)
@@ -197,6 +197,7 @@ struct FF_PKT {
    struct stat statp;                 /* stat packet */
    int32_t FileIndex;                 /* FileIndex of this file */
    int32_t LinkFI;                    /* FileIndex of main hard linked file */
+   int32_t delta_seq;                 /* Delta Sequence number */
    int32_t object_index;              /* Object index */
    int32_t object_len;                /* Object length */
    int32_t object_compression;        /* Type of compression for object */