int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr);
bool db_get_query_dbids(JCR *jcr, B_DB *mdb, POOL_MEM &query, dbid_list &ids);
bool db_get_file_list(JCR *jcr, B_DB *mdb, char *jobids, DB_RESULT_HANDLER *result_handler, void *ctx);
+bool db_get_base_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr, JobId_t *jobid);
bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *jobids);
int db_get_int_handler(void *ctx, int num_fields, char **row);
-boot db_init_base_file(JCR *jcr, B_DB *mdb);
+bool db_init_base_file(JCR *jcr, B_DB *mdb);
bool db_create_base_file_attributes_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
bool db_commit_base_file_attributes_record(JCR *jcr, B_DB *mdb);
void db_cleanup_base_file(JCR *jcr, B_DB *mdb);
"Name TEXT)"
};
-boot db_init_base_file(JCR *jcr, B_DB *mdb)
+bool db_init_base_file(JCR *jcr, B_DB *mdb)
{
POOL_MEM q(PM_MESSAGE);
Mmsg(q, create_temp_basefile[db_type], (uint64_t) jcr->JobId);
*/
bool db_create_base_file_attributes_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
{
+ bool ret;
Dmsg1(dbglevel, "Fname=%s\n", ar->fname);
Dmsg0(dbglevel, "put_file_into_catalog\n");
}
db_lock(mdb);
- split_path_and_file(jcr, bdb, ar->fname);
+ split_path_and_file(jcr, mdb, ar->fname);
mdb->esc_name = check_pool_memory_size(mdb->esc_name, mdb->fnl*2+1);
db_escape_string(jcr, mdb, mdb->esc_name, mdb->fname, mdb->fnl);
mdb->esc_path = check_pool_memory_size(mdb->esc_path, mdb->pnl*2+1);
db_escape_string(jcr, mdb, mdb->esc_path, mdb->path, mdb->pnl);
- len = Mmsg(mdb->cmd, "INSERT INTO basefile%lld (Path, Name) VALUES ('%s','%s')",
- (uint64_t)jcr->JobId, mdb->esc_path, mdb->esc_name);
+ Mmsg(mdb->cmd, "INSERT INTO basefile%lld (Path, Name) VALUES ('%s','%s')",
+ (uint64_t)jcr->JobId, mdb->esc_path, mdb->esc_name);
- boot ret = INSERT_DB(jcr, mdb, mdb->cmd);
+ ret = INSERT_DB(jcr, mdb, mdb->cmd);
db_unlock(mdb);
return ret;
"WHERE A.Path = B.Path "
"AND A.Name = B.Name "
"ORDER BY B.FileId)",
- edit_uint64(ed1, jcr->JobId), ed1, ed1);
+ edit_uint64(jcr->JobId, ed1), ed1, ed1);
return db_sql_query(mdb, buf.c_str(), NULL, NULL);
}
*/
void db_cleanup_base_file(JCR *jcr, B_DB *mdb)
{
+ POOL_MEM buf(PM_MESSAGE);
Mmsg(buf, "DROP TABLE new_basefile%lld", (uint64_t) jcr->JobId);
db_sql_query(mdb, buf.c_str(), NULL, NULL);
/*
* Find the last "accurate" backup state (that can take deleted files in account)
- * 1) Get all files with jobid in list (F subquery)
+ * 1) Get all files with jobid in list (F subquery)
+ * Get all files in BaseFiles with jobid in list
* 2) Take only the last version of each file (Temp subquery) => accurate list is ok
* 3) Join the result to file table to get fileindex, jobid and lstat information
*
"SELECT Path.Path, Filename.Name, File.FileIndex, File.JobId, File.LStat "
"FROM ( "
"SELECT max(FileId) as FileId, PathId, FilenameId "
- "FROM (SELECT FileId, PathId, FilenameId FROM File WHERE JobId IN (%s)) AS F "
+ "FROM (SELECT FileId, PathId, FilenameId FROM File WHERE JobId IN (%s) "
+ "UNION "
+ "SELECT File.FileId, PathId, FilenameId "
+ "FROM BaseFiles JOIN File USING (FileId) "
+ "WHERE BaseFiles.JobId IN (%s) "
+ ") AS F "
"GROUP BY PathId, FilenameId "
") AS Temp "
"JOIN Filename ON (Filename.FilenameId = Temp.FilenameId) "
"JOIN Path ON (Path.PathId = Temp.PathId) "
"JOIN File ON (File.FileId = Temp.FileId) "
-"WHERE File.FileIndex > 0 ORDER BY JobId, FileIndex ASC", /* Return sorted by JobId, */
- /* FileIndex for restore code */
- jobids);
+"WHERE File.FileIndex > 0 ORDER BY JobId, FileIndex ASC",/* Return sorted by JobId, */
+ /* FileIndex for restore code */
+ jobids, jobids);
+ Dmsg1(0, "q=%s\n", buf.c_str());
#else
/*
* I am not sure that this works the same as the code in ua_restore.c
return ret;
}
+bool db_get_base_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr, JobId_t *jobid)
+{
+ char date[MAX_TIME_LENGTH];
+ int64_t id = *jobid = 0;
+ POOL_MEM query(PM_FNAME);
+
+// char clientid[50], filesetid[50];
+
+ utime_t StartTime = (jr->StartTime)?jr->StartTime:time(NULL);
+ bstrutime(date, sizeof(date), StartTime + 1);
+
+ /* we can take also client name, fileset, etc... */
+
+ Mmsg(query,
+ "SELECT JobId, Job, StartTime, EndTime, JobTDate, PurgedFiles "
+ "FROM Job "
+// "JOIN FileSet USING (FileSetId) JOIN Client USING (ClientId) "
+ "WHERE Job.Name = '%s' "
+ "AND Level='B' AND JobStatus IN ('T','W') AND Type='B' "
+// "AND FileSet.FileSet= '%s' "
+// "AND Client.Name = '%s' "
+ "AND StartTime<'%s' "
+ "ORDER BY Job.JobTDate DESC LIMIT 1",
+ jr->Name,
+// edit_uint64(jr->ClientId, clientid),
+// edit_uint64(jr->FileSetId, filesetid));
+ date);
+
+ Dmsg1(1, "db_get_base_jobid q=%s\n", query.c_str());
+ if (!db_sql_query(mdb, query.c_str(), db_int64_handler, &id)) {
+ goto bail_out;
+ }
+ *jobid = (JobId_t) id;
+
+ Dmsg1(1, "db_get_base_jobid=%lld\n", id);
+ return true;
+
+bail_out:
+ return false;
+}
+
/*
* Use to build a string of int list from a query. "10,20,30"
*/
return true;
}
+/* Take all base jobs from job resource and find the
+ * last L_BASE jobid.
+ */
+static void get_base_jobids(JCR *jcr, POOLMEM *jobids)
+{
+ JOB_DBR jr;
+ JOB *job;
+ JobId_t id;
+ char str_jobid[50];
+
+ if (!jcr->job->base) {
+ return;
+ }
+
+ memset(&jr, 0, sizeof(JOB_DBR));
+ jr.StartTime = jcr->jr.StartTime;
+
+ foreach_alist(job, jcr->job->base) {
+ bstrncpy(jr.Name, job->name(), sizeof(jr.Name));
+ db_get_base_jobid(jcr, jcr->db, &jr, &id);
+
+ if (id) {
+ if (jobids[0]) {
+ pm_strcat(jobids, ",");
+ }
+ pm_strcat(jobids, edit_uint64(id, str_jobid));
+ }
+ }
+}
+
/*
* Foreach files in currrent list, send "/path/fname\0LStat" to FD
*/
bool send_accurate_current_files(JCR *jcr)
{
POOL_MEM buf;
+ bool ret=true;
- if (!jcr->accurate || job_canceled(jcr) || jcr->get_JobLevel()==L_FULL) {
+ if (!jcr->accurate || job_canceled(jcr)) {
return true;
}
+ /* In base level, no previous job is used */
+ if (jcr->get_JobLevel() == L_BASE) {
+ return true;
+ }
+
+ POOLMEM *nb = get_pool_memory(PM_FNAME);
POOLMEM *jobids = get_pool_memory(PM_FNAME);
+ nb[0] = jobids[0] = '\0';
- db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, jobids);
+ get_base_jobids(jcr, jobids);
- if (*jobids == 0) {
- free_pool_memory(jobids);
- Jmsg(jcr, M_FATAL, 0, _("Cannot find previous jobids.\n"));
- return false;
+ /* On Full mode, if no previous base job, no accurate things */
+ if (jcr->get_JobLevel() == L_FULL && *jobids == 0) {
+ goto bail_out;
}
+
+ /* For Incr/Diff level, we search for older jobs */
+ if (jcr->get_JobLevel() != L_FULL) {
+ db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, jobids);
+
+ if (*jobids == 0) {
+ ret=false;
+ Jmsg(jcr, M_FATAL, 0, _("Cannot find previous jobids.\n"));
+ goto bail_out;
+ }
+ }
+
if (jcr->JobId) { /* display the message only for real jobs */
Jmsg(jcr, M_INFO, 0, _("Sending Accurate information.\n"));
}
+
/* to be able to allocate the right size for htable */
- POOLMEM *nb = get_pool_memory(PM_FNAME);
- *nb = 0; /* clear buffer */
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);
Dmsg2(200, "jobids=%s nb=%s\n", jobids, nb);
jcr->file_bsock->fsend("accurate files=%s\n", nb);
if (!db_open_batch_connexion(jcr, jcr->db)) {
+ ret = false;
Jmsg0(jcr, M_FATAL, 0, "Can't get dedicate sql connexion");
- return false;
+ goto bail_out;
}
db_get_file_list(jcr, jcr->db_batch, jobids, accurate_list_handler, (void *)jcr);
/* TODO: close the batch connexion ? (can be used very soon) */
+ jcr->file_bsock->signal(BNET_EOD);
+
+bail_out:
free_pool_memory(jobids);
free_pool_memory(nb);
- jcr->file_bsock->signal(BNET_EOD);
-
- return true;
+ return ret;
}
/*
/* Update BaseFile table */
if (ar->FileType == FT_BASE) {
- if (!db_create_base_file_attributes_record(jcr, jcr->mdb, ar)) {
+ if (!db_create_base_file_attributes_record(jcr, jcr->db, ar)) {
Jmsg1(jcr, M_FATAL, 0, _("Base attribute create error. %s"),
db_strerror(jcr->db));
}
FF_PKT *ff_pkt;
int stream = STREAM_UNIX_ATTRIBUTES;
- if (!jcr->accurate || jcr->get_JobLevel != L_FULL) {
+ if (!jcr->accurate || jcr->get_JobLevel() != L_FULL) {
return true;
}
return true;
}
-static void accurate_free(JCR *jcr)
+void accurate_free(JCR *jcr)
{
if (jcr->file_list) {
jcr->file_list->destroy();
{
bool ret=true;
if (jcr->accurate) {
- if (jcr->get_JobLevel == L_FULL) {
+ if (jcr->get_JobLevel() == L_FULL) {
ret = accurate_send_base_file_list(jcr);
} else {
ret = accurate_send_deleted_list(jcr);