From 498e875fca8fa89568b691caa5d6d376c4595051 Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Thu, 7 Feb 2008 22:15:23 +0000 Subject: [PATCH] ebl Update accurate backup project git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6376 91ce42f0-d328-0410-95d8-f526ca767f89 --- .../testing/project-accurate-backup.patch | 432 +++++++++++------- 1 file changed, 278 insertions(+), 154 deletions(-) diff --git a/bacula/patches/testing/project-accurate-backup.patch b/bacula/patches/testing/project-accurate-backup.patch index 1b1f9d84bd..c873a7ae50 100644 --- a/bacula/patches/testing/project-accurate-backup.patch +++ b/bacula/patches/testing/project-accurate-backup.patch @@ -1,6 +1,6 @@ Index: src/dird/backup.c =================================================================== ---- src/dird/backup.c (révision 6373) +--- src/dird/backup.c (révision 6374) +++ src/dird/backup.c (copie de travail) @@ -44,6 +44,7 @@ #include "bacula.h" @@ -10,7 +10,7 @@ Index: src/dird/backup.c /* Commands sent to File daemon */ static char backupcmd[] = "backup\n"; -@@ -97,6 +98,308 @@ +@@ -97,6 +98,338 @@ } /* @@ -28,10 +28,116 @@ Index: src/dird/backup.c + } + + /* TODO: return the list to the FD */ -+ Qmsg(jcr, M_INFO, 0, " %s%s\n", row[0]?row[0]:"", row[1]?row[1]:""); ++ if (num_fields == 2) ++ Qmsg(jcr, M_INFO, 0, " %s%s\n", row[0]?row[0]:"", row[1]?row[1]:""); ++ else ++ Qmsg(jcr, M_INFO, 0, " %s\n", row[0]?row[0]:""); ++ + return 0; +} + ++bool accurate_check_file(JCR *jcr, FILE_DBR *fdbr, char *attr, char *Opts_Digest, int *do_Digest) ++{ ++ char *p; ++ int stat=false; ++ struct stat statf; /* file stat */ ++ struct stat statc; /* catalog stat */ ++ ++ int32_t LinkFIf, LinkFIc; ++ ++ decode_stat(attr, &statf, &LinkFIf); /* decode file stat packet */ ++ decode_stat(fdbr->LStat, &statc, &LinkFIc); /* decode catalog stat */ ++ *do_Digest = CRYPTO_DIGEST_NONE; ++ ++ for (p=Opts_Digest; *p; p++) { ++ char ed1[30], ed2[30]; ++ switch (*p) { ++ case 'i': /* compare INODEs */ ++ if (statc.st_ino != statf.st_ino) { ++ Jmsg(jcr, M_INFO, 0, _(" st_ino differ. Cat: %s File: %s\n"), ++ edit_uint64((uint64_t)statc.st_ino, ed1), ++ edit_uint64((uint64_t)statf.st_ino, ed2)); ++ stat = true; ++ } ++ break; ++ case 'p': /* permissions bits */ ++ if (statc.st_mode != statf.st_mode) { ++ Jmsg(jcr, M_INFO, 0, _(" st_mode differ. Cat: %x File: %x\n"), ++ (uint32_t)statc.st_mode, (uint32_t)statf.st_mode); ++ stat = true; ++ } ++ break; ++ case 'n': /* number of links */ ++ if (statc.st_nlink != statf.st_nlink) { ++ Jmsg(jcr, M_INFO, 0, _(" st_nlink differ. Cat: %d File: %d\n"), ++ (uint32_t)statc.st_nlink, (uint32_t)statf.st_nlink); ++ stat = true; ++ } ++ break; ++ case 'u': /* user id */ ++ if (statc.st_uid != statf.st_uid) { ++ Jmsg(jcr, M_INFO, 0, _(" st_uid differ. Cat: %u File: %u\n"), ++ (uint32_t)statc.st_uid, (uint32_t)statf.st_uid); ++ stat = true; ++ } ++ break; ++ case 'g': /* group id */ ++ if (statc.st_gid != statf.st_gid) { ++ Jmsg(jcr, M_INFO, 0, _(" st_gid differ. Cat: %u File: %u\n"), ++ (uint32_t)statc.st_gid, (uint32_t)statf.st_gid); ++ stat = true; ++ } ++ break; ++ case 's': /* size */ ++ if (statc.st_size != statf.st_size) { ++ Jmsg(jcr, M_INFO, 0, _(" st_size differ. Cat: %s File: %s\n"), ++ edit_uint64((uint64_t)statc.st_size, ed1), ++ edit_uint64((uint64_t)statf.st_size, ed2)); ++ stat = true; ++ } ++ break; ++ case 'a': /* access time */ ++ if (statc.st_atime != statf.st_atime) { ++ Jmsg(jcr, M_INFO, 0, _(" st_atime differs\n")); ++ stat = true; ++ } ++ break; ++ case 'm': ++ if (statc.st_mtime != statf.st_mtime) { ++ Jmsg(jcr, M_INFO, 0, _(" st_mtime differs\n")); ++ stat = true; ++ } ++ break; ++ case 'c': /* ctime */ ++ if (statc.st_ctime != statf.st_ctime) { ++ Jmsg(jcr, M_INFO, 0, _(" st_ctime differs\n")); ++ stat = true; ++ } ++ break; ++ case 'd': /* file size decrease */ ++ if (statc.st_size > statf.st_size) { ++ Jmsg(jcr, M_INFO, 0, _(" st_size decrease. Cat: %s File: %s\n"), ++ edit_uint64((uint64_t)statc.st_size, ed1), ++ edit_uint64((uint64_t)statf.st_size, ed2)); ++ stat = true; ++ } ++ break; ++ case '5': /* compare MD5 */ ++ Dmsg1(500, "set Do_MD5 for %s\n", jcr->fname); ++ *do_Digest = CRYPTO_DIGEST_MD5; ++ break; ++ case '1': /* compare SHA1 */ ++ *do_Digest = CRYPTO_DIGEST_SHA1; ++ break; ++ case ':': ++ case 'V': ++ default: ++ break; ++ } ++ } ++ return stat; ++} ++ +/* + * Accurate backup mode + * 1. Receive the list of all files including those backed up to the Dir @@ -40,20 +146,20 @@ Index: src/dird/backup.c + * deleted. + * + * Cleanup attributes (don't use atime, inode etc..) -+ * Need to insert file and attributes to temp table -+ * Batch compare files and attributes ++ * Need to insert file and attributes to temp table ? ++ * Batch compare files and attributes ? + * + * If file have file_index=0, they are discarded by FD + * ++ * TODO: send deleted list and new list to client ++ * initialize currentlist and currentbackupid tables ++ * tweak SD with file_index=-1 + */ +bool accurate_compute_files(JCR *jcr) +{ + BSOCK *fd; + int n, len; + FILE_DBR fdbr; -+ struct stat statf; /* file stat */ -+ struct stat statc; /* catalog stat */ -+ int stat = JS_Terminated; + char buf[MAXSTRING]; + char ed1[50], ed2[50]; + POOLMEM *fname = get_pool_memory(PM_MESSAGE); @@ -76,7 +182,7 @@ Index: src/dird/backup.c + Jmsg(jcr, M_ERROR, 0, _("Can't use Accurate mode ERR=Can't find BackupId\n")); + return false; + } -+ ++ db_accurate_create_backup_table(jcr, jcr->db, jcr->JobId); + Dmsg0(1, "bdird: waiting to receive file attributes\n"); + /* + * Get Attributes and Signature from File daemon @@ -94,7 +200,7 @@ Index: src/dird/backup.c + char Opts_Digest[MAXSTRING]; /* Verify Opts or MD5/SHA1 digest */ + + if (job_canceled(jcr)) { -+ return false; ++ goto bail_out2; + } + fname = check_pool_memory_size(fname, fd->msglen); + jcr->fname = check_pool_memory_size(jcr->fname, fd->msglen); @@ -103,7 +209,7 @@ Index: src/dird/backup.c + fname)) != 3) { + Jmsg3(jcr, M_FATAL, 0, _("birdmsglen, fd->msg); -+ return false; ++ goto bail_out2; + } + /* + * We read the Options or Signature into fname @@ -127,133 +233,45 @@ Index: src/dird/backup.c + * Got attributes stream, decode it + */ + if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX) { -+ int32_t LinkFIf, LinkFIc; ++ int changed=true; + Dmsg2(400, "file_index=%d attr=%s\n", file_index, attr); + jcr->JobFiles++; + jcr->FileIndex = file_index; /* remember attribute file_index */ -+ decode_stat(attr, &statf, &LinkFIf); /* decode file stat packet */ + do_Digest = CRYPTO_DIGEST_NONE; + pm_strcpy(jcr->fname, fname); /* move filename into JCR */ -+ -+ Dmsg3(040, "dirdfname, attr); ++ fdbr.FileId = 0; + + /* + * Find equivalent record in the database + */ -+ fdbr.FileId = 0; -+ /* If file_index==0, file is not saved by fd, check them */ -+ if (!db_accurate_get_file_attributes_record(jcr, jcr->db, jcr->fname, backupid, &fdbr)) { -+ Jmsg(jcr, M_INFO, 0, _("New file: %s\n"), jcr->fname); -+ Dmsg1(1, _("File not in catalog: %s\n"), jcr->fname); -+ continue; -+ } else { -+ Dmsg1(1, _("File in catalog: %s\n"), jcr->fname); -+ /* -+ * mark file record as visited by stuffing the -+ * current JobId, which is unique, into the MarkId field. -+ */ -+ db_mark_file_record(jcr, jcr->db, fdbr.FileId, jcr->JobId); -+ } -+ -+ Dmsg3(400, "Found %s in catalog. inx=%d Opts=%s\n", jcr->fname, -+ file_index, Opts_Digest); -+ decode_stat(fdbr.LStat, &statc, &LinkFIc); /* decode catalog stat */ -+ -+ // TODO: for each JS_Differences, send it to FD for backup -+ /* -+ * Loop over options supplied by user and verify the -+ * fields he requests. -+ */ -+ stat = JS_Terminated; /* TODO: track changes */ -+ for (p=Opts_Digest; *p; p++) { -+ char ed1[30], ed2[30]; -+ switch (*p) { -+ case 'i': /* compare INODEs */ -+ if (statc.st_ino != statf.st_ino) { -+ Jmsg(jcr, M_INFO, 0, _(" st_ino differ. Cat: %s File: %s\n"), -+ edit_uint64((uint64_t)statc.st_ino, ed1), -+ edit_uint64((uint64_t)statf.st_ino, ed2)); -+ stat = JS_Differences; -+ } -+ break; -+ case 'p': /* permissions bits */ -+ if (statc.st_mode != statf.st_mode) { -+ Jmsg(jcr, M_INFO, 0, _(" st_mode differ. Cat: %x File: %x\n"), -+ (uint32_t)statc.st_mode, (uint32_t)statf.st_mode); -+ stat = JS_Differences; -+ } -+ break; -+ case 'n': /* number of links */ -+ if (statc.st_nlink != statf.st_nlink) { -+ Jmsg(jcr, M_INFO, 0, _(" st_nlink differ. Cat: %d File: %d\n"), -+ (uint32_t)statc.st_nlink, (uint32_t)statf.st_nlink); -+ stat = JS_Differences; -+ } -+ break; -+ case 'u': /* user id */ -+ if (statc.st_uid != statf.st_uid) { -+ Jmsg(jcr, M_INFO, 0, _(" st_uid differ. Cat: %u File: %u\n"), -+ (uint32_t)statc.st_uid, (uint32_t)statf.st_uid); -+ stat = JS_Differences; -+ } -+ break; -+ case 'g': /* group id */ -+ if (statc.st_gid != statf.st_gid) { -+ Jmsg(jcr, M_INFO, 0, _(" st_gid differ. Cat: %u File: %u\n"), -+ (uint32_t)statc.st_gid, (uint32_t)statf.st_gid); -+ stat = JS_Differences; -+ } -+ break; -+ case 's': /* size */ -+ if (statc.st_size != statf.st_size) { -+ Jmsg(jcr, M_INFO, 0, _(" st_size differ. Cat: %s File: %s\n"), -+ edit_uint64((uint64_t)statc.st_size, ed1), -+ edit_uint64((uint64_t)statf.st_size, ed2)); -+ stat = JS_Differences; -+ } -+ break; -+ case 'a': /* access time */ -+ if (statc.st_atime != statf.st_atime) { -+ Jmsg(jcr, M_INFO, 0, _(" st_atime differs\n")); -+ stat = JS_Differences; -+ } -+ break; -+ case 'm': -+ if (statc.st_mtime != statf.st_mtime) { -+ Jmsg(jcr, M_INFO, 0, _(" st_mtime differs\n")); -+ stat = JS_Differences; -+ } -+ break; -+ case 'c': /* ctime */ -+ if (statc.st_ctime != statf.st_ctime) { -+ Jmsg(jcr, M_INFO, 0, _(" st_ctime differs\n")); -+ stat = JS_Differences; -+ } -+ break; -+ case 'd': /* file size decrease */ -+ if (statc.st_size > statf.st_size) { -+ Jmsg(jcr, M_INFO, 0, _(" st_size decrease. Cat: %s File: %s\n"), -+ edit_uint64((uint64_t)statc.st_size, ed1), -+ edit_uint64((uint64_t)statf.st_size, ed2)); -+ stat = JS_Differences; -+ } -+ break; -+ case '5': /* compare MD5 */ -+ Dmsg1(500, "set Do_MD5 for %s\n", jcr->fname); -+ do_Digest = CRYPTO_DIGEST_MD5; -+ break; -+ case '1': /* compare SHA1 */ -+ do_Digest = CRYPTO_DIGEST_SHA1; -+ break; -+ case ':': -+ case 'V': -+ default: -+ break; -+ } -+ } -+ if (stat == JS_Differences) { -+ Jmsg(jcr, M_INFO, 0, _(" fname=%s\n"), jcr->fname); ++ ++ if (db_accurate_get_file_attributes_record(jcr, jcr->db, jcr->fname, ++ backupid, &fdbr)) ++ { ++ Dmsg2(1, "get_file ok fname=%s fileid=%i\n", jcr->fname, fdbr.FileId); ++ ++ if (file_index != 0) { ++ changed = accurate_check_file(jcr, &fdbr, attr, Opts_Digest, &do_Digest); ++ Dmsg1(1, "check_file changed=%i\n", changed); ++ ++ if (changed == true) { ++ db_accurate_mark_file_for_backup(jcr, jcr->db, jcr->fname, jcr->JobId); ++ db_accurate_delete_file_record(jcr, jcr->db, fdbr.FileId, ++ backupid); ++ } ++ } ++ ++ if (file_index == 0 || changed == false) { ++ Dmsg1(1, "mark_file fileid=%i\n", fdbr.FileId); ++ db_accurate_mark_file_record(jcr, jcr->db, backupid, ++ fdbr.FileId, jcr->JobId); ++ } ++ ++ } else if (file_index == 0) { ++ Dmsg1(1, "mark_for_backup fname=%s\n", jcr->fname); ++ db_accurate_mark_file_for_backup(jcr, jcr->db, jcr->fname, jcr->JobId); + } ++ + + /* + * Got Digest Signature from Storage daemon @@ -268,7 +286,7 @@ Index: src/dird/backup.c + if (jcr->FileIndex != (uint32_t)file_index) { + Jmsg2(jcr, M_FATAL, 0, _("MD5/SHA1 index %d not same as attributes %d\n"), + file_index, jcr->FileIndex); -+ return false; ++ goto bail_out2; + } + if (do_Digest != CRYPTO_DIGEST_NONE) { + db_escape_string(jcr, jcr->db, buf, Opts_Digest, strlen(Opts_Digest)); @@ -280,7 +298,7 @@ Index: src/dird/backup.c + Jmsg(jcr, M_INFO, 0, _(" %d differs.\n"), + stream); + } -+ stat = JS_Differences; ++ //stat = JS_Differences; + } + do_Digest = CRYPTO_DIGEST_NONE; + } @@ -291,7 +309,7 @@ Index: src/dird/backup.c + berrno be; + Jmsg2(jcr, M_FATAL, 0, _("bdirdJobId, ed2)); + /* missing_handler is called for each file found */ ++ Dmsg1(1, "display deleted files cmd=%s\n", buf); ++ db_sql_query(jcr->db, buf, missing_handler, (void *)jcr); ++ ++ bsnprintf(buf, sizeof(buf), ++ "SELECT Name FROM ToBackup%s", ++ edit_uint64(jcr->JobId, ed2)); ++ /* missing_handler is called for each file found */ ++ Dmsg1(1, "display files to backup cmd=%s\n", buf); + db_sql_query(jcr->db, buf, missing_handler, (void *)jcr); + + free_pool_memory(fname); + + return true; ++ ++bail_out2: ++ db_accurate_drop_backup_table(jcr, jcr->db, jcr->JobId); ++ return false; +} + +/* * Do a backup of the specified FileSet * * Returns: false on failure -@@ -231,6 +534,13 @@ +@@ -231,6 +564,13 @@ goto bail_out; } @@ -335,7 +365,7 @@ Index: src/dird/backup.c db_write_batch_file_records(jcr); /* used by bulk batch file insert */ Index: src/dird/inc_conf.c =================================================================== ---- src/dird/inc_conf.c (révision 6373) +--- src/dird/inc_conf.c (révision 6374) +++ src/dird/inc_conf.c (copie de travail) @@ -94,6 +94,7 @@ * Items that are valid in an Options resource @@ -374,7 +404,7 @@ Index: src/dird/inc_conf.c Index: src/dird/dird_conf.c =================================================================== ---- src/dird/dird_conf.c (révision 6373) +--- src/dird/dird_conf.c (révision 6374) +++ src/dird/dird_conf.c (copie de travail) @@ -319,6 +319,7 @@ {"selectionpattern", store_str, ITEM(res_job.selection_pattern), 0, 0, 0}, @@ -396,7 +426,7 @@ Index: src/dird/dird_conf.c } Index: src/dird/dird_conf.h =================================================================== ---- src/dird/dird_conf.h (révision 6373) +--- src/dird/dird_conf.h (révision 6374) +++ src/dird/dird_conf.h (copie de travail) @@ -400,6 +400,7 @@ bool write_part_after_job; /* Set to write part after job in SD */ @@ -408,7 +438,7 @@ Index: src/dird/dird_conf.h SCHED *schedule; /* When -- Automatic schedule */ Index: src/filed/backup.c =================================================================== ---- src/filed/backup.c (révision 6373) +--- src/filed/backup.c (révision 6374) +++ src/filed/backup.c (copie de travail) @@ -50,6 +50,98 @@ static bool crypto_session_send(JCR *jcr, BSOCK *sd); @@ -564,7 +594,7 @@ Index: src/filed/backup.c Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), Index: src/filed/job.c =================================================================== ---- src/filed/job.c (révision 6373) +--- src/filed/job.c (révision 6374) +++ src/filed/job.c (copie de travail) @@ -1087,6 +1087,9 @@ case 'c': @@ -576,11 +606,92 @@ Index: src/filed/job.c default: Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p); break; +Index: src/cats/sql_update.c +=================================================================== +--- src/cats/sql_update.c (révision 6374) ++++ src/cats/sql_update.c (copie de travail) +@@ -88,6 +88,76 @@ + return stat; + } + ++int db_accurate_delete_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, JobId_t BackupId) ++{ ++ int stat; ++ char ed1[50], ed2[50]; ++ db_lock(mdb); ++ Mmsg(mdb->cmd, "DELETE FROM CurrentFile WHERE FileId=%s AND BackupId=%s", ++ edit_int64(FileId, ed1), edit_int64(BackupId, ed2)); ++ stat = QUERY_DB(jcr, mdb, mdb->cmd); ++ db_unlock(mdb); ++ return stat; ++} ++ ++int db_accurate_mark_file_for_backup(JCR *jcr, B_DB *mdb, char *fname, JobId_t JobId) ++{ ++ int stat; ++ int len=strlen(fname); ++ char ed1[50]; ++ db_lock(mdb); ++ /* TODO: mdb->esc_xxx are already ok but it's more smart to recompute it */ ++// mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*len+2); ++// mdb->esc_name = db_escape_string(jcr, mdb, mdb->esc_name, fname, len); ++ Mmsg(mdb->cmd, "INSERT INTO ToBackup%s (name) VALUES ('%s%s')", edit_int64(JobId, ed1), mdb->esc_path, mdb->esc_name); ++ stat = INSERT_DB(jcr, mdb, mdb->cmd); ++ db_unlock(mdb); ++ return stat; ++} ++ ++int db_accurate_create_backup_table(JCR *jcr, B_DB *mdb, JobId_t JobId) ++{ ++ int stat; ++ char ed1[50]; ++ db_lock(mdb); ++ Mmsg(mdb->cmd, "CREATE TABLE ToBackup%s (name text)", edit_int64(JobId, ed1)); ++// Mmsg(mdb->cmd, "CREATE TEMPORARY TABLE ToBackup%s (name text)", edit_int64(JobId, ed1)); ++ stat = QUERY_DB(jcr, mdb, mdb->cmd); ++ db_unlock(mdb); ++ return stat; ++} ++ ++int db_accurate_drop_backup_table(JCR *jcr, B_DB *mdb, JobId_t JobId) ++{ ++ int stat; ++ char ed1[50]; ++ db_lock(mdb); ++// Mmsg(mdb->cmd, "DROP TABLE ToBackup%s", edit_int64(JobId, ed1)); ++// stat = QUERY_DB(jcr, mdb, mdb->cmd); ++ db_unlock(mdb); ++ return stat; ++} ++ ++ ++/* Mark the file record as being visited during database ++ * accurate compare. Stuff JobId into the MarkId field ++ */ ++int db_accurate_mark_file_record(JCR *jcr, B_DB *mdb, JobId_t BackupId, FileId_t FileId, JobId_t JobId) ++{ ++ int stat; ++ char ed1[50], ed2[50], ed3[50]; ++ ++ db_lock(mdb); ++ Mmsg(mdb->cmd, "UPDATE CurrentFile SET MarkId=%s WHERE FileId=%s AND BackupId=%s", ++ edit_int64(JobId, ed1), edit_int64(FileId, ed2), edit_int64(BackupId, ed3)); ++ stat = QUERY_DB(jcr, mdb, mdb->cmd); ++ if (!stat || sql_affected_rows(mdb) != 1) { ++ stat = 0; ++ } ++ db_unlock(mdb); ++ return stat; ++} ++ + /* + * Update the Job record at start of Job + * Index: src/cats/make_postgresql_tables.in =================================================================== ---- src/cats/make_postgresql_tables.in (révision 6373) +--- src/cats/make_postgresql_tables.in (révision 6374) +++ src/cats/make_postgresql_tables.in (copie de travail) -@@ -43,6 +43,58 @@ +@@ -43,6 +43,59 @@ CREATE INDEX file_jobid_idx on file (jobid); CREATE INDEX file_fp_idx on file (filenameid, pathid); @@ -597,15 +708,16 @@ Index: src/cats/make_postgresql_tables.in +-- les File et le CurrentBackup... +-- Mais y'a des problemes pour les prunes + -+CREATE TABLE CurrentBackup ++CREATE TABLE CurrentFile +( + FileId integer not null, + BackupId integer not null, + FullMark char(1) default 0, ++ MarkId integer default 0, + primary key (FileId) +); + -+CREATE INDEX currentbackup_fileid on CurrentBackup (BackupId); ++CREATE INDEX currentfile_fileid on CurrentFile (BackupId); + +-- CREATE TEMPORARY TABLE batch (fileindex int, +-- jobid int, @@ -641,7 +753,7 @@ Index: src/cats/make_postgresql_tables.in -- if your Verifies are too slow. Index: src/cats/protos.h =================================================================== ---- src/cats/protos.h (révision 6373) +--- src/cats/protos.h (révision 6374) +++ src/cats/protos.h (copie de travail) @@ -82,10 +82,12 @@ /* sql_find.c */ @@ -656,9 +768,21 @@ Index: src/cats/protos.h bool db_get_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pdbr); int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr); bool db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr); +@@ -129,6 +131,11 @@ + int db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr); + int db_add_digest_to_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, char *digest, int type); + int db_mark_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, JobId_t JobId); ++int db_accurate_mark_file_for_backup(JCR *jcr, B_DB *mdb, char *fname, FileId_t JobId); ++int db_accurate_mark_file_record(JCR *jcr, B_DB *mdb, JobId_t BackupId, FileId_t FileId, JobId_t JobId); ++int db_accurate_drop_backup_table(JCR *jcr, B_DB *mdb, JobId_t JobId); ++int db_accurate_create_backup_table(JCR *jcr, B_DB *mdb, JobId_t JobId); ++int db_accurate_delete_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, JobId_t BackupId); + void db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr); + + #endif /* __SQL_PROTOS_H */ Index: src/cats/sql_find.c =================================================================== ---- src/cats/sql_find.c (révision 6373) +--- src/cats/sql_find.c (révision 6374) +++ src/cats/sql_find.c (copie de travail) @@ -190,7 +190,55 @@ return true; @@ -718,7 +842,7 @@ Index: src/cats/sql_find.c * VERIFY_CATALOG we want the JobId of the last INIT. Index: src/cats/sql_create.c =================================================================== ---- src/cats/sql_create.c (révision 6373) +--- src/cats/sql_create.c (révision 6374) +++ src/cats/sql_create.c (copie de travail) @@ -829,6 +829,14 @@ return true; @@ -737,7 +861,7 @@ Index: src/cats/sql_create.c * Index: src/cats/sql_get.c =================================================================== ---- src/cats/sql_get.c (révision 6373) +--- src/cats/sql_get.c (révision 6374) +++ src/cats/sql_get.c (copie de travail) @@ -66,6 +66,8 @@ * @@ -775,8 +899,8 @@ Index: src/cats/sql_get.c + db_escape_string(jcr, mdb, mdb->esc_path, mdb->path, mdb->pnl); + + Mmsg(mdb->cmd, -+"SELECT FileId, LStat, MD5, FilenameId, PathId, FileIndex, MarkId, JobId " -+ "FROM File JOIN CurrentBackup USING (FileId) " ++"SELECT FileId, LStat, MD5, FilenameId, PathId, FileIndex, CurrentFile.MarkId, JobId " ++ "FROM File JOIN CurrentFile USING (FileId) " + "JOIN Filename USING (FilenameId) " + "JOIN Path USING (PathId) " + "WHERE Path.Path='%s' " @@ -786,7 +910,7 @@ Index: src/cats/sql_get.c + mdb->esc_name, + edit_int64(backupid, ed1)); + -+ Dmsg1(1,"get_file %s\n", mdb->cmd); ++ Dmsg1(100,"get_file %s\n", mdb->cmd); + + if (QUERY_DB(jcr, mdb, mdb->cmd)) { + char ed1[30]; @@ -805,7 +929,7 @@ Index: src/cats/sql_get.c + fdbr->JobId = str_to_int64(row[7]); + stat=1; + } -+ } else { ++ } else if (mdb->num_rows > 1) { + Mmsg2(mdb->errmsg, _("Get DB File record %s failed num=%i\n"),fname,mdb->num_rows); + Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg); + } @@ -824,7 +948,7 @@ Index: src/cats/sql_get.c * Returns: 0 on failure Index: src/jcr.h =================================================================== ---- src/jcr.h (révision 6373) +--- src/jcr.h (révision 6374) +++ src/jcr.h (copie de travail) @@ -208,6 +208,7 @@ B_DB *db_batch; /* database pointer for batch insert */ @@ -836,7 +960,7 @@ Index: src/jcr.h void *plugin_ctx; /* current plugin context */ Index: src/findlib/find.h =================================================================== ---- src/findlib/find.h (révision 6373) +--- src/findlib/find.h (révision 6374) +++ src/findlib/find.h (copie de travail) @@ -108,6 +108,7 @@ #define FO_ENHANCEDWILD (1<<23) /* Enhanced wild card processing */ -- 2.39.5