Index: src/dird/fd_cmds.c
===================================================================
---- src/dird/fd_cmds.c (révision 6443)
+--- src/dird/fd_cmds.c (révision 6467)
+++ src/dird/fd_cmds.c (copie de travail)
@@ -50,7 +50,7 @@
static char filesetcmd[] = "fileset%s\n"; /* set full fileset */
static char runscript[] = "Run OnSuccess=%u OnFailure=%u AbortOnError=%u When=%u Command=%s\n";
static char runbeforenow[]= "RunBeforeNow\n";
-@@ -226,7 +226,7 @@
+@@ -226,13 +226,12 @@
char ed1[50];
stime = str_to_utime(jcr->stime);
while (bget_dirmsg(fd) >= 0) { /* allow him to poll us to sync clocks */
Jmsg(jcr, M_INFO, 0, "%s\n", fd->msg);
}
-@@ -240,24 +240,25 @@
+ }
+
+-
+ /*
+ * Send level command to FD.
+ * Used for backup jobs and estimate command.
+@@ -240,24 +239,26 @@
bool send_level_command(JCR *jcr)
{
BSOCK *fd = jcr->file_bsock;
+ const char *accurate=jcr->job->accurate?"accurate_":"";
++ const char *not_accurate="";
/*
* Send Level command to File daemon
*/
switch (jcr->JobLevel) {
case L_BASE:
- fd->fsend(levelcmd, "base", " ", 0);
-+ fd->fsend(levelcmd, "", "base", " ", 0);
++ fd->fsend(levelcmd, not_accurate, "base", " ", 0);
break;
/* L_NONE is the console, sending something off to the FD */
case L_NONE:
case L_FULL:
- fd->fsend(levelcmd, "full", " ", 0);
-+ fd->fsend(levelcmd, "", "full", " ", 0);
++ fd->fsend(levelcmd, not_accurate, "full", " ", 0);
break;
case L_DIFFERENTIAL:
- fd->fsend(levelcmd, "differential", " ", 0);
case L_SINCE:
Index: src/dird/backup.c
===================================================================
---- src/dird/backup.c (révision 6443)
+--- src/dird/backup.c (révision 6467)
+++ src/dird/backup.c (copie de travail)
-@@ -96,6 +96,54 @@
- return true;
+@@ -97,6 +97,65 @@
}
+ /*
++ * Foreach files in currrent list, send "/path/fname\0LStat" to FD
++ */
+static int accurate_list_handler(void *ctx, int num_fields, char **row)
+{
+ JCR *jcr = (JCR *)ctx;
+ return 0;
+}
+
++/*
++ * Send current file list to FD
++ * DIR -> FD : accurate files=xxxx
++ * DIR -> FD : /path/to/file\0Lstat
++ * DIR -> FD : /path/to/dir/\0Lstat
++ * ...
++ * DIR -> FD : EOD
++ */
+bool send_accurate_current_files(JCR *jcr)
+{
-+ char buf[MAXSTRING];
++ POOL_MEM buf;
+
-+ if (jcr->accurate == false || job_canceled(jcr) || jcr->JobLevel == L_FULL) {
++ if (jcr->accurate==false || job_canceled(jcr) || jcr->JobLevel==L_FULL) {
+ return true;
+ }
+ POOLMEM *jobids = get_pool_memory(PM_FNAME);
+
+ if (*jobids == 0) {
+ free_pool_memory(jobids);
-+ Jmsg(jcr, M_ERROR_TERM, 0, _("Cannot find previous jobids.\n"));
-+ return true;
++ Jmsg(jcr, M_FATAL, 0, _("Cannot find previous jobids.\n"));
++ return false;
+ }
++ Jmsg(jcr, M_INFO, 0, _("Sending Accurate informations.\n"));
+
+ /* to be able to allocate the right size for htable */
+ POOLMEM *nb = get_pool_memory(PM_FNAME);
-+ bsnprintf(buf, sizeof(buf),
-+ "SELECT sum(JobFiles) FROM Job WHERE JobId IN (%s)",jobids);
-+ db_sql_query(jcr->db, buf, db_get_int_handler, nb);
++ Mmsg(buf, "SELECT sum(JobFiles) FROM Job WHERE JobId IN (%s)",jobids);
++ db_sql_query(jcr->db, buf.c_str(), db_get_int_handler, nb);
+ jcr->file_bsock->fsend("accurate files=%s\n", nb);
+
+ db_get_file_list(jcr, jcr->db, jobids, accurate_list_handler, (void *)jcr);
+ return true;
+}
+
- /*
++/*
* Do a backup of the specified FileSet
*
-@@ -225,6 +273,14 @@
+ * Returns: false on failure
+@@ -225,6 +284,14 @@
Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
}
+ /*
-+ * If backup is in accurate mode, FD will send the list of
-+ * all files.
++ * If backup is in accurate mode, we send the list of
++ * all files to FD.
+ */
+ if (!send_accurate_current_files(jcr)) {
+ goto bail_out;
/* Send backup command */
fd->fsend(backupcmd);
if (!response(jcr, fd, OKbackup, "backup", DISPLAY_ERROR)) {
-@@ -234,6 +290,7 @@
- /* Pickup Job termination data */
- stat = wait_for_job_termination(jcr);
- db_write_batch_file_records(jcr); /* used by bulk batch file insert */
-+
- if (stat == JS_Terminated) {
- backup_cleanup(jcr, stat);
- return true;
-@@ -475,6 +532,7 @@
+@@ -475,6 +542,7 @@
" Software Compression: %s\n"
" VSS: %s\n"
" Encryption: %s\n"
" Volume name(s): %s\n"
" Volume Session Id: %d\n"
" Volume Session Time: %d\n"
-@@ -506,8 +564,9 @@
+@@ -506,8 +574,9 @@
edit_uint64_with_suffix(jcr->SDJobBytes, ec6),
kbps,
compress,
jcr->VolSessionTime,
Index: src/dird/ua_restore.c
===================================================================
---- src/dird/ua_restore.c (révision 6443)
+--- src/dird/ua_restore.c (révision 6467)
+++ src/dird/ua_restore.c (copie de travail)
-@@ -1006,7 +1006,6 @@
+@@ -1005,7 +1005,6 @@
* For display purposes, the same JobId, with different volumes may
* appear more than once, however, we only insert it once.
*/
p = rx->JobIds;
tree.FileEstimate = 0;
if (get_next_jobid_from_list(&p, &JobId) > 0) {
-@@ -1021,24 +1020,14 @@
+@@ -1020,23 +1019,12 @@
tree.DeltaCount = rx->JobId/50; /* print 50 ticks */
}
}
+ if (!db_get_file_list(ua->jcr, ua->db, rx->JobIds, insert_tree_handler, (void *)&tree)) {
+ ua->error_msg("%s", db_strerror(ua->db));
}
-+
if (tree.FileCount == 0) {
ua->send_msg(_("\nThere were no files inserted into the tree, so file selection\n"
- "is not possible.Most likely your retention policy pruned the files\n"));
-@@ -1056,26 +1045,13 @@
+@@ -1055,26 +1043,13 @@
}
} else {
char ec1[50];
if (find_arg(ua, NT_("done")) < 0) {
/* Let the user interact in selecting which files to restore */
-Index: src/dird/inc_conf.c
-===================================================================
---- src/dird/inc_conf.c (révision 6443)
-+++ src/dird/inc_conf.c (copie de travail)
-@@ -94,6 +94,7 @@
- * Items that are valid in an Options resource
- */
- static RES_ITEM options_items[] = {
-+ {"accurate", store_opts, {0}, 0, 0, 0},
- {"compression", store_opts, {0}, 0, 0, 0},
- {"signature", store_opts, {0}, 0, 0, 0},
- {"verify", store_opts, {0}, 0, 0, 0},
-@@ -153,7 +154,8 @@
- INC_KW_NOATIME,
- INC_KW_ENHANCEDWILD,
- INC_KW_CHKCHANGES,
-- INC_KW_STRIPPATH
-+ INC_KW_STRIPPATH,
-+ INC_KW_ACCURATE
- };
-
- /*
-@@ -163,6 +165,7 @@
- * options given above.
- */
- static struct s_kw FS_option_kw[] = {
-+ {"accurate", INC_KW_ACCURATE},
- {"compression", INC_KW_COMPRESSION},
- {"signature", INC_KW_DIGEST},
- {"encryption", INC_KW_ENCRYPTION},
-@@ -251,6 +254,8 @@
- {"no", INC_KW_ENHANCEDWILD, "0"},
- {"yes", INC_KW_CHKCHANGES, "c"},
- {"no", INC_KW_CHKCHANGES, "0"},
-+ {"yes", INC_KW_ACCURATE, "C"},
-+ {"no", INC_KW_ACCURATE, "0"},
- {NULL, 0, 0}
- };
-
Index: src/filed/backup.c
===================================================================
---- src/filed/backup.c (révision 6443)
+--- src/filed/backup.c (révision 6467)
+++ src/filed/backup.c (copie de travail)
@@ -37,6 +37,7 @@
/* Forward referenced functions */
int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level);
-@@ -48,8 +49,225 @@
+@@ -48,8 +49,224 @@
static bool crypto_session_start(JCR *jcr);
static void crypto_session_end(JCR *jcr);
static bool crypto_session_send(JCR *jcr, BSOCK *sd);
+
/*
+ * This function is called for each file seen in fileset.
-+ *
-+ * If the file is skipped (saved=false), we will check if this
-+ * file have been backuped before. If not, we decide to backup it.
-+ *
-+ * If the file have saved=true, we mark it as seen
++ * We check in file_list hash if fname have been backuped
++ * the last time. After we can compare Lstat field. When
++ * a file have been seen, we put '\0' in LStat field.
+ *
+ */
-+/* TODO: tweak verify code to use the same function */
++/* TODO: tweak verify code to use the same function ?? */
+bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
+{
+ char *p;
+ elt = (CurFile *) jcr->file_list->lookup(fname);
+
+ if (!elt) {
-+ // TODO: we must backup it !
-+ Dmsg1(1, "accurate %s = yes (not found)\n", fname);
++ Dmsg1(500, "accurate %s = yes (not found)\n", fname);
+ return true;
+ }
+
+ if (*elt->lstat == '\0') {
-+ Dmsg1(1, "accurate %s = no (already seen)\n", fname);
-+ *elt->lstat = '\0';
++ Dmsg1(500, "accurate %s = no (already seen)\n", fname);
+ return false;
+ }
+
+ }
+ }
+ *elt->lstat = '\0'; /* mark it as seen */
-+ Dmsg2(1, "accurate %s = %i\n", fname, stat);
++ Dmsg2(500, "accurate %s = %i\n", fname, stat);
+ return stat;
+}
+
+/*
+ * This function doesn't work very well with smartalloc
++ * TODO: use bigbuffer from htable
+ */
-+int accurate_get_current_file_list_cmd(JCR *jcr)
++int accurate_cmd(JCR *jcr)
+{
+ BSOCK *dir = jcr->dir_bsock;
+ int len;
+ uint64_t nb;
+ CurFile *elt=NULL;
+
-+ if (jcr->accurate == false || job_canceled(jcr) || jcr->JobLevel == L_FULL) {
++ if (jcr->accurate==false || job_canceled(jcr) || jcr->JobLevel==L_FULL) {
+ return true;
+ }
+
+ return false;
+ }
+
-+ Jmsg(jcr, M_INFO, 0, _("Getting Accurate informations.\n"));
-+
+ jcr->file_list = (htable *)malloc(sizeof(htable));
+ jcr->file_list->init(elt, &elt->link, nb);
+
++ /*
++ * buffer = sizeof(CurFile) + dirmsg
++ * dirmsg = fname + lstat
++ */
+ /* get current files */
+ while (dir->recv() >= 0) {
+ len = strlen(dir->msg);
+ elt->fname[dir->msglen]='\0';
+ elt->lstat = elt->fname + len + 1;
+ jcr->file_list->insert(elt->fname, elt);
-+ Dmsg2(5, "add fname=%s lstat=%s\n", elt->fname, elt->lstat);
++ Dmsg2(500, "add fname=%s lstat=%s\n", elt->fname, elt->lstat);
+ }
+ }
+
+ return true;
+ }
+
-+ if (jcr->file_list == NULL) { /* TODO: bug ? */
++ if (jcr->file_list == NULL) {
+ return true;
+ }
+
+ CurFile *elt;
+ foreach_htable (elt, jcr->file_list) {
-+ if (*elt->lstat != '\0') {
-+ Dmsg2(1, "deleted fname=%s lstat=%s\n", elt->fname, elt->lstat);
++ if (*elt->lstat != '\0') { /* already seen */
++ Dmsg2(500, "deleted fname=%s lstat=%s\n", elt->fname, elt->lstat);
+ encode_and_send_deleted_file(jcr, elt->fname);
+ }
+// free(elt->fname);
+ }
-+ jcr->file_list->destroy(); /* TODO: clean htable when this function is not reached ? */
++ jcr->file_list->destroy(); /* TODO: clean htable when this function is not reached ? */
+ free(jcr->file_list);
+ jcr->file_list = NULL;
+ return true;
* Find all the requested files and send them
* to the Storage daemon.
*
-@@ -66,7 +284,6 @@
- BSOCK *sd;
- bool ok = true;
- // TODO landonf: Allow user to specify encryption algorithm
--
- sd = jcr->store_bsock;
-
- set_jcr_job_status(jcr, JS_Running);
@@ -100,7 +317,7 @@
*/
jcr->compress_buf_size = jcr->buf_size + ((jcr->buf_size+999) / 1000) + 30;
start_heartbeat_monitor(jcr);
jcr->acl_text = get_pool_memory(PM_MESSAGE);
-@@ -134,7 +354,10 @@
- ok = false; /* error */
+@@ -135,6 +355,8 @@
set_jcr_job_status(jcr, JS_ErrorTerminated);
}
-+ Dmsg1(1, "jcr->accurate == %i\n", jcr->accurate);
+ accurate_send_deleted_list(jcr); /* send deleted list to SD */
+
free_pool_memory(jcr->acl_text);
stop_heartbeat_monitor(jcr);
-@@ -1128,6 +1351,58 @@
+@@ -1128,6 +1350,58 @@
return true;
}
*/
Index: src/filed/job.c
===================================================================
---- src/filed/job.c (révision 6443)
+--- src/filed/job.c (révision 6467)
+++ src/filed/job.c (copie de travail)
@@ -49,6 +49,7 @@
/* Imported functions */
extern int status_cmd(JCR *jcr);
extern int qstatus_cmd(JCR *jcr);
-+extern int accurate_get_current_file_list_cmd(JCR *jcr);
++extern int accurate_cmd(JCR *jcr);
/* Forward referenced functions */
static int backup_cmd(JCR *jcr);
{"RunBeforeJob", runbefore_cmd, 0},
{"RunAfterJob", runafter_cmd, 0},
{"Run", runscript_cmd, 0},
-+ {"accurate", accurate_get_current_file_list_cmd, 0},
++ {"accurate", accurate_cmd, 0},
{NULL, NULL} /* list terminator */
};
-@@ -1087,6 +1089,9 @@
- case 'c':
- fo->flags |= FO_CHKCHANGES;
- break;
-+ case 'C':
-+ fo->flags |= FO_ACCURATE;
-+ break;
- default:
- Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
- break;
-@@ -1195,6 +1200,9 @@
+@@ -1195,6 +1197,9 @@
level = get_memory(dir->msglen+1);
Dmsg1(110, "level_cmd: %s", dir->msg);
if (sscanf(dir->msg, "level = %s ", level) != 1) {
goto bail_out;
}
-@@ -1204,14 +1212,14 @@
+@@ -1204,14 +1209,14 @@
/* Full backup requested? */
} else if (strcmp(level, "full") == 0) {
jcr->JobLevel = L_FULL;
* to agree with our clock.
Index: src/filed/restore.c
===================================================================
---- src/filed/restore.c (révision 6443)
+--- src/filed/restore.c (révision 6467)
+++ src/filed/restore.c (copie de travail)
@@ -320,6 +320,11 @@
bclose(&rctx.bfd);
*/
Index: src/cats/protos.h
===================================================================
---- src/cats/protos.h (révision 6443)
+--- src/cats/protos.h (révision 6467)
+++ src/cats/protos.h (copie de travail)
@@ -102,6 +102,9 @@
int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr);
/* sql_list.c */
Index: src/cats/sql_get.c
===================================================================
---- src/cats/sql_get.c (révision 6443)
+--- src/cats/sql_get.c (révision 6467)
+++ src/cats/sql_get.c (copie de travail)
@@ -898,8 +898,6 @@
return ok;
+ jobids[0]='\0';
+
+ Mmsg(query,
-+"CREATE TEMPORARY TABLE btemp3%s AS ( "
++"CREATE TEMPORARY TABLE btemp3%s AS "
+ "SELECT JobId, StartTime, EndTime, JobTDate, PurgedFiles "
+ "FROM Job JOIN FileSet USING (FileSetId) "
+ "WHERE ClientId = %s "
+ "AND Level='F' AND JobStatus='T' AND Type='B' "
+ "AND StartTime<'%s' "
+ "AND FileSet.FileSet=(SELECT FileSet FROM FileSet WHERE FileSetId = %s) "
-+ "ORDER BY Job.JobTDate DESC LIMIT 1) ",
++ "ORDER BY Job.JobTDate DESC LIMIT 1",
+ edit_uint64(jcr->JobId, jobid),
+ edit_uint64(jr->ClientId, clientid),
+ date,
+ return 0;
+}
+
- #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/
+ #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_DBI */
Index: src/stored/bextract.c
===================================================================
---- src/stored/bextract.c (révision 6443)
+--- src/stored/bextract.c (révision 6467)
+++ src/stored/bextract.c (copie de travail)
@@ -324,6 +324,14 @@
Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n"));
rec->FileIndex, attr->file_index);
Index: src/stored/bscan.c
===================================================================
---- src/stored/bscan.c (révision 6443)
+--- src/stored/bscan.c (révision 6467)
+++ src/stored/bscan.c (copie de travail)
-@@ -648,6 +648,15 @@
+@@ -660,6 +660,15 @@
case STREAM_UNIX_ATTRIBUTES:
case STREAM_UNIX_ATTRIBUTES_EX:
}
Index: src/stored/append.c
===================================================================
---- src/stored/append.c (révision 6443)
+--- src/stored/append.c (révision 6467)
+++ src/stored/append.c (copie de travail)
@@ -146,7 +146,7 @@
if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX ||
Index: src/jcr.h
===================================================================
---- src/jcr.h (révision 6443)
+--- src/jcr.h (révision 6467)
+++ src/jcr.h (copie de travail)
@@ -119,6 +119,7 @@
Index: src/lib/Makefile.in
===================================================================
---- src/lib/Makefile.in (révision 6443)
+--- src/lib/Makefile.in (révision 6467)
+++ src/lib/Makefile.in (copie de travail)
@@ -29,7 +29,7 @@
res.c rwlock.c scan.c serial.c sha1.c \
EXTRAOBJS = @OBJLIST@
Index: src/findlib/find.c
===================================================================
---- src/findlib/find.c (révision 6443)
+--- src/findlib/find.c (révision 6467)
+++ src/findlib/find.c (copie de travail)
@@ -96,6 +96,13 @@
Dmsg0(100, "Leave set_find_options()\n");
* are used, because we create a snapshot of all used
Index: src/findlib/find_one.c
===================================================================
---- src/findlib/find_one.c (révision 6443)
+--- src/findlib/find_one.c (révision 6467)
+++ src/findlib/find_one.c (copie de travail)
@@ -258,6 +258,33 @@
}
/* Incremental option, directory entry not changed */
ff_pkt->type = FT_DIRNOCHG;
} else {
-- ff_pkt->type = FT_DIRBEGIN;
-+ ff_pkt->type = FT_DIRBEGIN;;
+ ff_pkt->type = FT_DIRBEGIN;
}
+
/* We have set st_rdev to 1 if it is a reparse point, otherwise 0 */
ff_pkt->type = FT_REPARSE;
Index: src/findlib/find.h
===================================================================
---- src/findlib/find.h (révision 6443)
+--- src/findlib/find.h (révision 6467)
+++ src/findlib/find.h (copie de travail)
-@@ -108,6 +108,7 @@
- #define FO_ENHANCEDWILD (1<<23) /* Enhanced wild card processing */
- #define FO_CHKCHANGES (1<<24) /* Check if file have been modified during backup */
- #define FO_STRIPPATH (1<<25) /* Check for stripping path */
-+#define FO_ACCURATE (1<<26) /* Accurate mode */
-
- struct s_included_file {
- struct s_included_file *next;
-@@ -215,6 +216,7 @@
+@@ -215,6 +215,7 @@
findFILESET *fileset;
int (*file_save)(JCR *, FF_PKT *, bool); /* User's callback */
int (*plugin_save)(JCR *, FF_PKT *, bool); /* User's callback */
uint32_t flags; /* backup options */
Index: src/findlib/protos.h
===================================================================
---- src/findlib/protos.h (révision 6443)
+--- src/findlib/protos.h (révision 6467)
+++ src/findlib/protos.h (copie de travail)
@@ -45,6 +45,7 @@
/* From find.c */