-2003-10-10 Version 1.32b 10Oct03 Release
+2003-10-15 Version 1.32b 14Oct03 Release
+14Oct03
+- Modify configure so that if threaded MySQL client library
+ is not present, Bacula will link with the non-threaded
+ version.
+- Updates to the Web pages and to the manual.
+- Remove trademark symbol from title. Phil pointed out that it
+ does not display correctly in a title.
+11Oct03
+- Implement restore by file before date.
+- Change restore arguments a bit so that you can feed it
+ multiple jobid= specifications or multiple file= specifications.
+- Pass restore with run option on to run_cmd.
+- Make run-cmd not prompt if it has a "run" on the command line.
10Oct03
- When pruning, select only old orphanned jobs to delete so that
the current job is not pruned too.
Release Notes for Bacula 1.32b
- Bacula code: Total files = 259 Total lines = 77,984 (*.h *.c *.in)
+ Bacula code: Total files = 259 Total lines = 78,067 (*.h *.c *.in)
-Changes since 1.32a:
+Most Significant Changes since 1.32a:
- Improve forward space file/block during restore, many
optimizations.
- Fix a bug that did not allow appending to a tape
on FreeBSD systems.
- Fix pruning so that it will not prune the current job.
+- Modify configure to use non-threaded MySQL client lib if
+ the threaded version is not present.
+- Implement restore by file before date.
+- When pruning don't prune the current job.
Major Changes 1.32a Release:
- Implemented forward space file/block whenever possible
/* Define if you want to use MySQL */
#undef HAVE_MYSQL
+/* Defined if MySQL thread safe library is present */
+#undef HAVE_THREAD_SAFE_MYSQL
+
/* Define if you want to use embedded MySQL */
#undef HAVE_EMBEDDED_MYSQL
#undef HAVE_OLD_SOCKOPT
#undef HAVE_BIGENDIAN
-
fi
fi
SQL_INCLUDE=-I$MYSQL_INCDIR
- SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient_r -lz"
+ if test -f $MYSQL_LIBDIR/libmysqlclient_r.a; then
+ SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient_r -lz"
+ AC_DEFINE(HAVE_THREAD_SAFE_MYSQL)
+ else
+ SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient -lz"
+ fi
SQL_BINDIR=$MYSQL_BINDIR
AC_DEFINE(HAVE_MYSQL)
/* Define if you want to use MySQL */
#undef HAVE_MYSQL
+/* Defined if MySQL thread safe library is present */
+#undef HAVE_THREAD_SAFE_MYSQL
+
/* Define if you want to use embedded MySQL */
#undef HAVE_EMBEDDED_MYSQL
#undef HAVE_BIGENDIAN
-
/* Define to 1 if the `closedir' function returns void instead of `int'. */
#undef CLOSEDIR_VOID
fi
fi
SQL_INCLUDE=-I$MYSQL_INCDIR
- SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient_r -lz"
+ if test -f $MYSQL_LIBDIR/libmysqlclient_r.a; then
+ SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient_r -lz"
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_THREAD_SAFE_MYSQL 1
+_ACEOF
+
+ else
+ SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient -lz"
+ fi
SQL_BINDIR=$MYSQL_BINDIR
cat >>confdefs.h <<\_ACEOF
SuSE.
For 1.33
+- Add VerifyJob to "run" summary (yes/mod/no) prompt.
+- Add device name to "Current Volume not acceptable because ..."
+- Make sure that Bacula rechecks the tape after the 20 min wait.
+- Set IO_NOWAIT on Bacula packets
+- Try doing a raw partition backup and restore by mounting a
+ Windows partition.
+- Implement Verify=DiskToCatalog
+- Implement a RunAfterFailedJob
- Report CVS problems to SourceForge.
- Implement .consolerc for Console
-- I want to restore by file to some date.
- Is it really important to make Job name the same to find the
Full backup to avoid promoting an Incremental job?
- Start label, then run job when tape labeled, it should broadcast.
-- Implement a RunAfterFailedJob
- Zap illegal characters in job name for mail files (e.g. /).
- From Lars Köllers:
Yes, it would allow to highly automatic the request for new tapes. If a
- Make sure a rescheduled job is properly reported by status.
- Walk through the Pool records rather than the Job records
in dird.c to create/update pools.
-- Figure out a way to move Volumes from one pool to another.
- What to do about "list files job=xxx".
- Implement delete Job.
- Document need to put LabelFormat in quotes.
- Test connect timeouts.
- Fix FreeBSD build with tcp_wrapper -- should not have -lnsl
- Implement fast block rejection.
+- I want to restore by file to some date.
+---- 1.32b released
+- Figure out a way to move Volumes from one pool to another.
return 0;
}
+#ifdef HAVE_TREAD_SAFE_MYSQL
my_thread_init();
+#endif
mdb->connected = TRUE;
V(mutex);
{
P(mutex);
mdb->ref_count--;
+#ifdef HAVE_TREAD_SAFE_MYSQL
my_thread_end();
+#endif
if (mdb->ref_count == 0) {
qdchain(&mdb->bq);
if (mdb->connected && mdb->db) {
/* find.c */
int db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime);
-int db_find_last_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr);
+int db_find_last_jobid(JCR *jcr, B_DB *mdb, char *Name, JOB_DBR *jr);
int db_find_next_volume(JCR *jcr, B_DB *mdb, int index, MEDIA_DBR *mr);
/* get.c */
int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr);
int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr);
int db_get_job_volume_names(JCR *jcr, B_DB *mdb, uint32_t JobId, POOLMEM **VolumeNames);
-int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, FILE_DBR *fdbr);
+int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr);
int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr);
int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr);
int db_get_num_media_records(JCR *jcr, B_DB *mdb);
* 0 on failure
*/
int
-db_find_last_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
+db_find_last_jobid(JCR *jcr, B_DB *mdb, char *Name, JOB_DBR *jr)
{
SQL_ROW row;
"ClientId=%u ORDER BY StartTime DESC LIMIT 1",
L_VERIFY_INIT, jr->Name, jr->ClientId);
} else if (jr->Level == L_VERIFY_VOLUME_TO_CATALOG) {
- Mmsg(&mdb->cmd,
+ if (Name) {
+ Mmsg(&mdb->cmd,
+"SELECT JobId FROM Job WHERE Type='B' AND JobStatus='T' AND "
+"Name='%s' ORDER BY StartTime DESC LIMIT 1", Name);
+ } else {
+ Mmsg(&mdb->cmd,
"SELECT JobId FROM Job WHERE Type='B' AND "
-"ClientId=%u ORDER BY StartTime DESC LIMIT 1",
- jr->ClientId);
+"ClientId=%u ORDER BY StartTime DESC LIMIT 1", jr->ClientId);
+ }
} else {
Mmsg1(&mdb->errmsg, _("Unknown Job level=%c\n"), jr->Level);
db_unlock(mdb);
*/
/* Forward referenced functions */
-static int db_get_file_record(JCR *jcr, B_DB *mdb, FILE_DBR *fdbr);
+static int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr);
static int db_get_filename_record(JCR *jcr, B_DB *mdb);
static int db_get_path_record(JCR *jcr, B_DB *mdb);
* Returns: 0 on failure
* 1 on success with the File record in FILE_DBR
*/
-int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, FILE_DBR *fdbr)
+int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
{
int stat;
Dmsg1(20, "Enter get_file_from_catalog fname=%s \n", fname);
fdbr->PathId = db_get_path_record(jcr, mdb);
- stat = db_get_file_record(jcr, mdb, fdbr);
+ stat = db_get_file_record(jcr, mdb, jr, fdbr);
db_unlock(mdb);
* "normal" if a new file is found during Verify.
*/
static
-int db_get_file_record(JCR *jcr, B_DB *mdb, FILE_DBR *fdbr)
+int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr)
{
SQL_ROW row;
int stat = 0;
- Mmsg(&mdb->cmd,
-"SELECT FileId, LStat, MD5 from File where File.JobId=%u and File.PathId=%u and \
-File.FilenameId=%u", fdbr->JobId, fdbr->PathId, fdbr->FilenameId);
-
+ if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) {
+ Mmsg(&mdb->cmd,
+"SELECT FileId, LStat, MD5 FROM File,Job WHERE "
+"File.JobId=Job.JobId AND File.PathId=%u AND "
+"File.FilenameId=%u AND Job.Type='B' AND Job.JobSTATUS='T' AND "
+"ClientId=%u ORDER BY StartTime DESC LIMIT 1",
+ fdbr->PathId, fdbr->FilenameId, jr->ClientId);
+ } else {
+ Mmsg(&mdb->cmd,
+"SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%u AND File.PathId=%u AND "
+"File.FilenameId=%u", fdbr->JobId, fdbr->PathId, fdbr->FilenameId);
+ }
Dmsg3(050, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n",
fdbr->JobId, fdbr->FilenameId, fdbr->PathId);
}
if (!cram_md5_get_auth(sd, jcr->store->password, ssl_need) ||
!cram_md5_auth(sd, jcr->store->password, ssl_need)) {
- Jmsg0(jcr, M_FATAL, 0, _("Director and Storage daemon passwords not the same.\n"));
+ Jmsg0(jcr, M_FATAL, 0, _("Director and Storage daemon passwords or names not the same.\n"));
return 0;
}
Dmsg1(116, ">stored: %s", sd->msg);
}
if (!cram_md5_get_auth(fd, jcr->client->password, ssl_need) ||
!cram_md5_auth(fd, jcr->client->password, ssl_need)) {
- Jmsg(jcr, M_FATAL, 0, _("Director and File daemon passwords not the same.\n"));
+ Jmsg(jcr, M_FATAL, 0, _("Director and File daemon passwords or names not the same.\n"));
return 0;
}
Dmsg1(116, ">filed: %s", fd->msg);
{"pool", store_res, ITEM(res_job.pool), R_POOL, 0, 0},
{"client", store_res, ITEM(res_job.client), R_CLIENT, 0, 0},
{"fileset", store_res, ITEM(res_job.fileset), R_FILESET, 0, 0},
+ {"verifyjob", store_res, ITEM(res_job.verify_job), R_JOB, 0, 0},
{"where", store_dir, ITEM(res_job.RestoreWhere), 0, 0, 0},
{"replace", store_replace, ITEM(res_job.replace), 0, ITEM_DEFAULT, REPLACE_ALWAYS},
{"bootstrap",store_dir, ITEM(res_job.RestoreBootstrap), 0, 0, 0},
{"Catalog", L_VERIFY_CATALOG, JT_VERIFY},
{"InitCatalog", L_VERIFY_INIT, JT_VERIFY},
{"VolumeToCatalog", L_VERIFY_VOLUME_TO_CATALOG, JT_VERIFY},
+ {"DiskToCatalog", L_VERIFY_DISK_TO_CATALOG, JT_VERIFY},
{"Data", L_VERIFY_DATA, JT_VERIFY},
{NULL, 0}
};
void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ...), void *sock)
{
URES *res = (URES *)reshdr;
- int recurse = 1;
+ bool recurse = true;
char ed1[100], ed2[100];
if (res == NULL) {
}
if (type < 0) { /* no recursion */
type = - type;
- recurse = 0;
+ recurse = false;
}
switch (type) {
case R_DIRECTOR:
} else {
sendit(sock, "!!! No Pool resource\n");
}
+ if (res->res_job.verify_job) {
+ sendit(sock, " --> ");
+ dump_resource(-R_JOB, (RES *)res->res_job.verify_job, sendit, sock);
+ }
+ break;
if (res->res_job.messages) {
sendit(sock, " --> ");
dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock);
if ((res = (URES *)GetResWithName(R_JOB, res_all.res_dir.hdr.name)) == NULL) {
Emsg1(M_ERROR_TERM, 0, "Cannot find Job resource %s\n", res_all.res_dir.hdr.name);
}
- res->res_job.messages = res_all.res_job.messages;
- res->res_job.schedule = res_all.res_job.schedule;
- res->res_job.client = res_all.res_job.client;
- res->res_job.fileset = res_all.res_job.fileset;
- res->res_job.storage = res_all.res_job.storage;
- res->res_job.pool = res_all.res_job.pool;
+ res->res_job.messages = res_all.res_job.messages;
+ res->res_job.schedule = res_all.res_job.schedule;
+ res->res_job.client = res_all.res_job.client;
+ res->res_job.fileset = res_all.res_job.fileset;
+ res->res_job.storage = res_all.res_job.storage;
+ res->res_job.pool = res_all.res_job.pool;
+ res->res_job.verify_job = res_all.res_job.verify_job;
if (res->res_job.JobType == 0) {
Emsg1(M_ERROR_TERM, 0, "Job Type not defined for Job resource %s\n", res_all.res_dir.hdr.name);
}
FILESET *fileset; /* What to backup -- Fileset */
STORE *storage; /* Where is device -- Storage daemon */
POOL *pool; /* Where is media -- Media Pool */
+ JOB *verify_job; /* Job name to verify */
uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
};
free_pool_memory(query);
}
+/* Modify the Pool in which this Volume is located */
+static void update_volpool(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+ POOL_DBR pr;
+ POOLMEM *query;
+ memset(&pr, 0, sizeof(pr));
+ bstrncpy(pr.Name, val, sizeof(pr.Name));
+ if (!get_pool_dbr(ua, &pr)) {
+ return;
+ }
+ query = get_pool_memory(PM_MESSAGE);
+ Mmsg(&query, "UPDATE Media SET PoolId=%u WHERE MediaId=%u", pr.PoolId, mr->MediaId);
+ if (!db_sql_query(ua->db, query, NULL, NULL)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ } else {
+ bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
+ }
+ free_pool_memory(query);
+}
+
/*
* Update a media record -- allows you to change the
* Volume status. E.g. if you want Bacula to stop
static int update_volume(UAContext *ua)
{
MEDIA_DBR mr;
+ POOL_DBR pr;
POOLMEM *query;
char ed1[30];
bool done = false;
N_("MaxVolFiles"), /* 4 */
N_("MaxVolBytes"), /* 5 */
N_("Recycle"), /* 6 */
+ N_("Pool"), /* 7 */
NULL };
for (int i=0; kw[i]; i++) {
case 6:
update_volrecycle(ua, ua->argv[j], &mr);
break;
+ case 7:
+ update_volpool(ua, ua->argv[j], &mr);
}
done = true;
}
add_prompt(ua, _("Recycle Flag"));
add_prompt(ua, _("Slot"));
add_prompt(ua, _("Volume Files"));
+ add_prompt(ua, _("Pool"));
add_prompt(ua, _("Done"));
switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
case 0: /* Volume Status */
case 7: /* Slot */
int slot;
- POOL_DBR pr;
memset(&pr, 0, sizeof(POOL_DBR));
pr.PoolId = mr.PoolId;
free_pool_memory(query);
break;
+ case 9: /* Volume's Pool */
+ memset(&pr, 0, sizeof(POOL_DBR));
+ pr.PoolId = mr.PoolId;
+ if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ return 0;
+ }
+ bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
+ if (!get_cmd(ua, _("Enter new Pool name: "))) {
+ return 0;
+ }
+ update_volpool(ua, ua->cmd, &mr);
+ return 1;
default: /* Done or error */
bsendmsg(ua, "Selection done.\n");
return 1;
add_prompt(ua, _("Initialize Catalog"));
add_prompt(ua, _("Verify Catalog"));
add_prompt(ua, _("Verify Volume to Catalog"));
+ add_prompt(ua, _("Verify Disk to Catalog"));
add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
case 0:
jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
break;
case 3:
+ jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
+ break;
+ case 4:
jcr->JobLevel = L_VERIFY_DATA;
break;
default:
tree_getpath(node, cwd, sizeof(cwd));
fdbr.FileId = 0;
fdbr.JobId = node->JobId;
- if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, &fdbr)) {
+ if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) {
int32_t LinkFI;
decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */
/*
tree_getpath(node, cwd, sizeof(cwd));
fdbr.FileId = 0;
fdbr.JobId = node->JobId;
- if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, &fdbr)) {
+ if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) {
int32_t LinkFI;
decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */
ls_output(buf, cwd, node->extract, &statp);
*/
int do_verify(JCR *jcr)
{
- char *level;
+ char *level, *Name;
BSOCK *fd;
- JOB_DBR jr;
+ JOB_DBR jr, verify_jr;
JobId_t JobId = 0;
int stat;
Dmsg1(9, "bdird: created client %s record\n", jcr->client->hdr.name);
- /* If we are doing a verify from the catalog,
- * we must look up the time and date of the
- * last full verify.
+ /*
+ * Find JobId of last job that ran. E.g.
+ * for VERIFY_CATALOG we want the JobId of the last INIT.
+ * for VERIFY_VOLUME_TO_CATALOG, we want the JobId of the
+ * last backup Job.
*/
if (jcr->JobLevel == L_VERIFY_CATALOG ||
jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) {
memcpy(&jr, &jcr->jr, sizeof(jr));
- if (!db_find_last_jobid(jcr, jcr->db, &jr)) {
+ if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG &&
+ jcr->job->verify_job) {
+ Name = jcr->job->verify_job->hdr.name;
+ } else {
+ Name = NULL;
+ }
+ Dmsg1(100, "find last jobid for: %s\n", NPRT(Name));
+ if (!db_find_last_jobid(jcr, jcr->db, Name, &jr)) {
if (jcr->JobLevel == L_VERIFY_CATALOG) {
Jmsg(jcr, M_FATAL, 0, _(
"Unable to find JobId of previous InitCatalog Job.\n"
goto bail_out;
}
JobId = jr.JobId;
- Dmsg1(20, "Last full id=%d\n", JobId);
+ Dmsg1(100, "Last full Jobid=%d\n", JobId);
}
jcr->jr.JobId = jcr->JobId;
jcr->fname = get_pool_memory(PM_FNAME);
}
- jcr->jr.JobId = JobId; /* save target JobId */
-
/* Print Job Start message */
Jmsg(jcr, M_INFO, 0, _("Start Verify JobId %d Job=%s\n"),
jcr->JobId, jcr->Job);
+ /*
+ * Now get the job record for the previous backup that interests
+ * us. We use the JobId that we found above.
+ */
if (jcr->JobLevel == L_VERIFY_CATALOG ||
- jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) {
- memset(&jr, 0, sizeof(jr));
- jr.JobId = JobId;
- if (!db_get_job_record(jcr, jcr->db, &jr)) {
+ jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG ||
+ jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) {
+ memset(&verify_jr, 0, sizeof(verify_jr));
+ verify_jr.JobId = JobId;
+ if (!db_get_job_record(jcr, jcr->db, &verify_jr)) {
Jmsg(jcr, M_FATAL, 0, _("Could not get job record for previous Job. ERR=%s"),
db_strerror(jcr->db));
goto bail_out;
}
- if (jr.JobStatus != 'T') {
+ if (verify_jr.JobStatus != 'T') {
Jmsg(jcr, M_FATAL, 0, _("Last Job %d did not terminate normally. JobStatus=%c\n"),
- JobId, jr.JobStatus);
+ JobId, verify_jr.JobStatus);
goto bail_out;
}
Jmsg(jcr, M_INFO, 0, _("Verifying against JobId=%d Job=%s\n"),
- JobId, jr.Job);
+ verify_jr.JobId, verify_jr.Job);
}
/*
if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) {
RBSR *bsr = new_bsr();
UAContext *ua;
- bsr->JobId = jr.JobId;
+ bsr->JobId = verify_jr.JobId;
ua = new_ua_context(jcr);
complete_bsr(ua, bsr);
bsr->fi = new_findex();
bsr->fi->findex = 1;
- bsr->fi->findex2 = jr.JobFiles;
+ bsr->fi->findex2 = verify_jr.JobFiles;
if (!write_bsr_file(ua, bsr)) {
free_ua_context(ua);
free_bsr(bsr);
} else {
jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */
}
+
+ if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG &&
+ jcr->job->verify_job) {
+ jcr->fileset = jcr->job->verify_job->fileset;
+ }
+ jcr->verify_jr = &verify_jr;
+
/*
* OK, now connect to the File daemon
* and ask him for the files.
set_jcr_job_status(jcr, JS_Running);
fd = jcr->file_bsock;
+
Dmsg0(30, ">filed: Send include list\n");
if (!send_include_list(jcr)) {
goto bail_out;
case L_VERIFY_DATA:
level = "data";
break;
+ case L_VERIFY_DISK_TO_CATALOG:
+ level="disk_to_catalog";
+ break;
default:
Jmsg1(jcr, M_FATAL, 0, _("Unimplemented save level %d\n"), jcr->JobLevel);
goto bail_out;
get_attributes_and_compare_to_catalog(jcr, JobId);
break;
+ case L_VERIFY_DISK_TO_CATALOG:
+ Dmsg0(10, "Verify level=disk_to_catalog\n");
+ get_attributes_and_compare_to_catalog(jcr, JobId);
+ break;
+
case L_VERIFY_INIT:
/* Build catalog */
Dmsg0(10, "Verify level=init\n");
* Find equivalent record in the database
*/
fdbr.FileId = 0;
- if (!db_get_file_attributes_record(jcr, jcr->db, jcr->fname, &fdbr)) {
+ if (!db_get_file_attributes_record(jcr, jcr->db, jcr->fname,
+ jcr->verify_jr, &fdbr)) {
Jmsg(jcr, M_INFO, 0, _("New file: %s\n"), jcr->fname);
Dmsg1(020, _("File not in catalog: %s\n"), jcr->fname);
stat = JS_Differences;
jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
} else if (strcasecmp(level, "data") == 0){
jcr->JobLevel = L_VERIFY_DATA;
+ } else if (strcasecmp(level, "disk_to_catalog") == 0) {
+ jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
} else {
bnet_fsend(dir, "2994 Bad verify level: %s\n", dir->msg);
return 0;
/* Inform Storage daemon that we are done */
bnet_sig(sd, BNET_TERMINATE);
+ break;
+ case L_VERIFY_DISK_TO_CATALOG:
+ do_verify(jcr);
break;
default:
bnet_fsend(dir, "2994 Bad verify level: %s\n", dir->msg);
return 0;
}
- /* If file opened, compute MD5 */
+ /* If file opened, compute MD5 or SHA1 hash */
if (is_bopen(&bfd) && ff_pkt->flags & FO_MD5) {
char MD5buf[40]; /* 24 should do */
MD5Init(&md5c);
#define L_VERIFY_CATALOG 'C' /* verify from catalog */
#define L_VERIFY_INIT 'V' /* verify save (init DB) */
#define L_VERIFY_VOLUME_TO_CATALOG 'O' /* verify Volume to catalog entries */
+#define L_VERIFY_DISK_TO_CATALOG 'd' /* verify Disk attributes to catalog */
#define L_VERIFY_DATA 'A' /* verify data on volume */
#define L_BASE 'B' /* Base level job */
POOLMEM *fname; /* name to put into catalog */
int fn_printed; /* printed filename */
POOLMEM *stime; /* start time for incremental/differential */
- JOB_DBR jr; /* Job record in Database */
+ JOB_DBR jr; /* Job DB record for current job */
+ JOB_DBR *verify_jr; /* Pointer to target job */
uint32_t RestoreJobId; /* Id specified by UA */
POOLMEM *client_uname; /* client uname */
int replace; /* Replace option */
}
fr.JobId = mjcr->JobId;
fr.FileId = 0;
- if (db_get_file_attributes_record(bjcr, db, attr->fname, &fr)) {
+ if (db_get_file_attributes_record(bjcr, db, attr->fname, NULL, &fr)) {
if (verbose > 1) {
Pmsg1(000, _("File record already exists for: %s\n"), attr->fname);
}
#undef VERSION
#define VERSION "1.32b"
#define VSTRING "1"
-#define BDATE "10 Oct 2003"
-#define LSMDATE "10Oct03"
+#define BDATE "14 Oct 2003"
+#define LSMDATE "14Oct03"
/* Debug flags */
#undef DEBUG