/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
+ modify it under the terms of version three of the GNU Affero General Public
License as published by the Free Software Foundation and included
in the file LICENSE.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
-/*
+/**
* Bacula Catalog Database Get record interface routines
* Note, these routines generally get a record by id or
* by name. If more logic is involved, the routine
*
* Kern Sibbald, March 2000
*
- * Version $Id$
*/
-/* The following is necessary so that we do not include
+/**
+ * The following is necessary so that we do not include
* the dummy external definition of DB.
*/
#define __SQL_C /* indicate that this is sql.c */
#include "bacula.h"
#include "cats.h"
-#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_DBI
+#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI
/* -----------------------------------------------------------------------
*
/* Forward referenced functions */
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);
-/*
+/**
* Given a full filename (with path), look up the File record
* (with attributes) in the database.
*
}
-/*
+/**
* Get a File record
* Returns: 0 on failure
* 1 on success
* Note in this routine, we do not use Jmsg because it may be
* called to get attributes of a non-existent file, which is
* "normal" if a new file is found during Verify.
+ *
+ * The following is a bit of a kludge: because we always backup a
+ * directory entry, we can end up with two copies of the directory
+ * in the backup. One is when we encounter the directory and find
+ * we cannot recurse into it, and the other is when we find an
+ * explicit mention of the directory. This can also happen if the
+ * use includes the directory twice. In this case, Verify
+ * VolumeToCatalog fails because we have two copies in the catalog,
+ * and only the first one is marked (twice). So, when calling from Verify,
+ * jr is not NULL and we know jr->FileIndex is the fileindex
+ * of the version of the directory/file we actually want and do
+ * a more explicit SQL search.
*/
static
int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr)
int stat = 0;
char ed1[50], ed2[50], ed3[50];
- if (jcr->get_JobLevel() == L_VERIFY_DISK_TO_CATALOG) {
+ if (jcr->getJobLevel() == L_VERIFY_DISK_TO_CATALOG) {
Mmsg(mdb->cmd,
"SELECT FileId, LStat, MD5 FROM File,Job WHERE "
"File.JobId=Job.JobId AND File.PathId=%s AND "
-"File.FilenameId=%s AND Job.Type='B' AND Job.JobStatus='T' AND "
+"File.FilenameId=%s AND Job.Type='B' AND Job.JobStatus IN ('T','W') AND "
"ClientId=%s ORDER BY StartTime DESC LIMIT 1",
edit_int64(fdbr->PathId, ed1),
edit_int64(fdbr->FilenameId, ed2),
edit_int64(jr->ClientId,ed3));
-
} else {
Mmsg(mdb->cmd,
"SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%s AND File.PathId=%s AND "
edit_int64(fdbr->PathId, ed2),
edit_int64(fdbr->FilenameId,ed3));
}
- Dmsg3(050, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n",
+ Dmsg3(450, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n",
fdbr->JobId, fdbr->FilenameId, fdbr->PathId);
Dmsg1(100, "Query=%s\n", mdb->cmd);
if (QUERY_DB(jcr, mdb, mdb->cmd)) {
mdb->num_rows = sql_num_rows(mdb);
Dmsg1(050, "get_file_record num_rows=%d\n", (int)mdb->num_rows);
- if (mdb->num_rows > 1) {
- Mmsg1(mdb->errmsg, _("get_file_record want 1 got rows=%d\n"),
- mdb->num_rows);
- }
if (mdb->num_rows >= 1) {
if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb));
bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
bstrncpy(fdbr->Digest, row[2], sizeof(fdbr->Digest));
stat = 1;
+ if (mdb->num_rows > 1) {
+ Mmsg3(mdb->errmsg, _("get_file_record want 1 got rows=%d PathId=%s FilenameId=%s\n"),
+ mdb->num_rows,
+ edit_int64(fdbr->PathId, ed1),
+ edit_int64(fdbr->FilenameId, ed2));
+ Dmsg1(000, "=== Problem! %s", mdb->errmsg);
+ }
}
} else {
Mmsg2(mdb->errmsg, _("File record for PathId=%s FilenameId=%s not found.\n"),
}
-/* Get Filename record
+/**
+ * Get Filename record
* Returns: 0 on failure
* FilenameId on success
*
return FilenameId;
}
-/* Get path record
+/**
+ * Get path record
* Returns: 0 on failure
* PathId on success
*
* DO NOT use Jmsg in this routine (see notes for get_file_record)
*/
-static int db_get_path_record(JCR *jcr, B_DB *mdb)
+int db_get_path_record(JCR *jcr, B_DB *mdb)
{
SQL_ROW row;
uint32_t PathId = 0;
}
-/*
+/**
* Get Job record for given JobId or Job name
* Returns: false on failure
* true on success
Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
"PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
"Type,Level,ClientId,Name,PriorJobId,RealEndTime,JobId,FileSetId,"
-"SchedTime,RealEndTime "
+"SchedTime,RealEndTime,ReadBytes,HasBase,PurgedFiles "
"FROM Job WHERE Job='%s'", jr->Job);
} else {
Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
"PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
"Type,Level,ClientId,Name,PriorJobId,RealEndTime,JobId,FileSetId,"
-"SchedTime,RealEndTime "
+"SchedTime,RealEndTime,ReadBytes,HasBase,PurgedFiles "
"FROM Job WHERE JobId=%s",
edit_int64(jr->JobId, ed1));
}
jr->FileSetId = str_to_int64(row[17]);
bstrncpy(jr->cSchedTime, row[3]!=NULL?row[18]:"", sizeof(jr->cSchedTime));
bstrncpy(jr->cRealEndTime, row[3]!=NULL?row[19]:"", sizeof(jr->cRealEndTime));
+ jr->ReadBytes = str_to_int64(row[20]);
jr->StartTime = str_to_utime(jr->cStartTime);
jr->SchedTime = str_to_utime(jr->cSchedTime);
jr->EndTime = str_to_utime(jr->cEndTime);
jr->RealEndTime = str_to_utime(jr->cRealEndTime);
+ jr->HasBase = str_to_int64(row[21]);
+ jr->PurgedFiles = str_to_int64(row[22]);
sql_free_result(mdb);
db_unlock(mdb);
return true;
}
-/*
+/**
* Find VolumeNames for a given JobId
* Returns: 0 on error or no Volumes found
* number of volumes on success
return stat;
}
-/*
+/**
* Find Volume parameters for a give JobId
* Returns: 0 on error or no Volumes found
* number of volumes on success
db_lock(mdb);
Mmsg(mdb->cmd,
"SELECT VolumeName,MediaType,FirstIndex,LastIndex,StartFile,"
-"JobMedia.EndFile,StartBlock,JobMedia.EndBlock,Copy,"
-"Slot,StorageId"
+"JobMedia.EndFile,StartBlock,JobMedia.EndBlock,"
+"Slot,StorageId,InChanger"
" FROM JobMedia,Media WHERE JobMedia.JobId=%s"
" AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
edit_int64(JobId, ed1));
break;
} else {
DBId_t StorageId;
+ uint32_t StartBlock, EndBlock, StartFile, EndFile;
bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
Vols[i].FirstIndex = str_to_uint64(row[2]);
Vols[i].LastIndex = str_to_uint64(row[3]);
- Vols[i].StartFile = str_to_uint64(row[4]);
- Vols[i].EndFile = str_to_uint64(row[5]);
- Vols[i].StartBlock = str_to_uint64(row[6]);
- Vols[i].EndBlock = str_to_uint64(row[7]);
-// Vols[i].Copy = str_to_uint64(row[8]);
- Vols[i].Slot = str_to_uint64(row[9]);
- StorageId = str_to_uint64(row[10]);
+ StartFile = str_to_uint64(row[4]);
+ EndFile = str_to_uint64(row[5]);
+ StartBlock = str_to_uint64(row[6]);
+ EndBlock = str_to_uint64(row[7]);
+ Vols[i].StartAddr = (((uint64_t)StartFile)<<32) | StartBlock;
+ Vols[i].EndAddr = (((uint64_t)EndFile)<<32) | EndBlock;
+ Vols[i].Slot = str_to_uint64(row[8]);
+ StorageId = str_to_uint64(row[9]);
+ Vols[i].InChanger = str_to_uint64(row[10]);
Vols[i].Storage[0] = 0;
SId[i] = StorageId;
}
-/*
+/**
* Get the number of pool records
*
* Returns: -1 on failure
return stat;
}
-/*
+/**
* This function returns a list of all the Pool record ids.
* The caller must free ids if non-NULL.
*
return stat;
}
-/*
+/**
* This function returns a list of all the Client record ids.
* The caller must free ids if non-NULL.
*
db_lock(mdb);
*ids = NULL;
- Mmsg(mdb->cmd, "SELECT ClientId FROM Client");
+ Mmsg(mdb->cmd, "SELECT ClientId FROM Client ORDER BY Name");
if (QUERY_DB(jcr, mdb, mdb->cmd)) {
*num_ids = sql_num_rows(mdb);
if (*num_ids > 0) {
-/* Get Pool Record
+/**
+ * Get Pool Record
* If the PoolId is non-zero, we get its record,
* otherwise, we search on the PoolName
*
Mmsg(mdb->cmd,
"SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
"AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
-"MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId FROM Pool WHERE Pool.PoolId=%s",
+"MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId,ScratchPoolId,"
+"ActionOnPurge FROM Pool WHERE Pool.PoolId=%s",
edit_int64(pdbr->PoolId, ed1));
} else { /* find by name */
Mmsg(mdb->cmd,
"SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
"AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
-"MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId FROM Pool WHERE Pool.Name='%s'",
+"MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId,ScratchPoolId,"
+"ActionOnPurge FROM Pool WHERE Pool.Name='%s'",
pdbr->Name);
}
-
if (QUERY_DB(jcr, mdb, mdb->cmd)) {
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
pdbr->LabelType = str_to_int64(row[15]);
bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat));
pdbr->RecyclePoolId = str_to_int64(row[17]);
+ pdbr->ScratchPoolId = str_to_int64(row[18]);
+ pdbr->ActionOnPurge = str_to_int32(row[19]);
ok = true;
}
}
return ok;
}
-/* Get Client Record
+/**
+ * Get Client Record
* If the ClientId is non-zero, we get its record,
* otherwise, we search on the Client Name
*
return stat;
}
-/*
+/**
* Get Counter Record
*
* Returns: 0 on failure
SQL_ROW row;
db_lock(mdb);
- Mmsg(mdb->cmd, "SELECT MinValue,MaxValue,CurrentValue,WrapCounter "
+ Mmsg(mdb->cmd, "SELECT \"MinValue\",\"MaxValue\",CurrentValue,WrapCounter "
"FROM Counters WHERE Counter='%s'", cr->Counter);
if (QUERY_DB(jcr, mdb, mdb->cmd)) {
}
-/* Get FileSet Record
+/**
+ * Get FileSet Record
* If the FileSetId is non-zero, we get its record,
* otherwise, we search on the name
*
}
-/*
+/**
* Get the number of Media records
*
* Returns: -1 on failure
return stat;
}
-
-/*
+/**
* This function returns a list of all the Media record ids for
- * the current Pool with the correct Media Type.
+ * the current Pool, the correct Media Type, Recyle, Enabled, StorageId, VolBytes
+ * VolumeName if specified
* The caller must free ids if non-NULL.
*
* Returns false: on failure
uint32_t *id;
char ed1[50];
bool ok = false;
+ char buf[MAX_NAME_LENGTH*3]; /* Can contain MAX_NAME_LENGTH*2+1 + AND ....='' */
+ char esc[MAX_NAME_LENGTH*2+1];
db_lock(mdb);
*ids = NULL;
- Mmsg(mdb->cmd, "SELECT DISTINCT MediaId FROM Media WHERE PoolId=%s "
- " AND MediaType='%s'",
- edit_int64(mr->PoolId, ed1), mr->MediaType);
+
+ Mmsg(mdb->cmd, "SELECT DISTINCT MediaId FROM Media WHERE Recycle=%d AND Enabled=%d ",
+ mr->Recycle, mr->Enabled);
+
+ if (*mr->MediaType) {
+ db_escape_string(jcr, mdb, esc, mr->MediaType, strlen(mr->MediaType));
+ bsnprintf(buf, sizeof(buf), "AND MediaType='%s' ", esc);
+ pm_strcat(mdb->cmd, buf);
+ }
+
+ if (mr->StorageId) {
+ bsnprintf(buf, sizeof(buf), "AND StorageId=%s ", edit_uint64(mr->StorageId, ed1));
+ pm_strcat(mdb->cmd, buf);
+ }
+
+ if (mr->PoolId) {
+ bsnprintf(buf, sizeof(buf), "AND PoolId=%s ", edit_uint64(mr->PoolId, ed1));
+ pm_strcat(mdb->cmd, buf);
+ }
+
+ if (mr->VolBytes) {
+ bsnprintf(buf, sizeof(buf), "AND VolBytes > %s ", edit_uint64(mr->VolBytes, ed1));
+ pm_strcat(mdb->cmd, buf);
+ }
+
+ if (*mr->VolumeName) {
+ db_escape_string(jcr, mdb, esc, mr->VolumeName, strlen(mr->VolumeName));
+ bsnprintf(buf, sizeof(buf), "AND VolumeName = '%s' ", esc);
+ pm_strcat(mdb->cmd, buf);
+ }
+
+ if (*mr->VolStatus) {
+ db_escape_string(jcr, mdb, esc, mr->VolStatus, strlen(mr->VolStatus));
+ bsnprintf(buf, sizeof(buf), "AND VolStatus = '%s' ", esc);
+ pm_strcat(mdb->cmd, buf);
+ }
+
+ Dmsg1(100, "q=%s\n", mdb->cmd);
+
if (QUERY_DB(jcr, mdb, mdb->cmd)) {
*num_ids = sql_num_rows(mdb);
if (*num_ids > 0) {
}
-/*
+/**
* This function returns a list of all the DBIds that are returned
* for the query.
*
return ok;
}
-/* Get Media Record
+/**
+ * Get Media Record
*
* Returns: false: on failure
* true: on success
"MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
"EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
"Enabled,LocationId,RecycleCount,InitialWrite,"
- "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime "
+ "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime,ActionOnPurge "
"FROM Media WHERE MediaId=%s",
edit_int64(mr->MediaId, ed1));
} else { /* find by name */
"MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
"EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
"Enabled,LocationId,RecycleCount,InitialWrite,"
- "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime "
+ "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime,ActionOnPurge "
"FROM Media WHERE VolumeName='%s'", mr->VolumeName);
}
mr->RecyclePoolId = str_to_int64(row[34]);
mr->VolReadTime = str_to_int64(row[35]);
mr->VolWriteTime = str_to_int64(row[36]);
+ mr->ActionOnPurge = str_to_int32(row[37]);
ok = true;
}
return ok;
}
-/*
- * Find the last "accurate" backup state (that can take deleted files in account)
- * 1) Get all files with jobid in list (F subquery)
- * 2) Take only the last version of each file (Temp subquery) => accurate list is ok
+/**
+ * Find the last "accurate" backup state (that can take deleted files in
+ * account)
+ * 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
*
* TODO: See if we can do the SORT only if needed (as an argument)
#define new_db_get_file_list
#ifdef new_db_get_file_list
- /* This is broken, at least if called from ua_restore.c */
+ POOL_MEM buf2(PM_MESSAGE);
+ Mmsg(buf2, select_recent_version_with_basejob[db_type],
+ jobids, jobids, jobids, jobids);
Mmsg(buf,
- "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 "
- "GROUP BY PathId, FilenameId "
- ") AS Temp "
+"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) "
- "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 FileIndex > 0 "
+"ORDER BY Temp.JobId, FileIndex ASC",/* Return sorted by JobId, */
+ /* FileIndex for restore code */
+ buf2.c_str());
#else
/*
- * I am not sure that this works the same as the code in ua_restore.c
- * but it is very similar.
+ * I am not sure that this works the same as the code in ua_restore.c but it
+ * is very similar. The accurate-test fails in a restore. Bad file count.
*/
Mmsg(buf, uar_sel_files, jobids);
#endif
return db_sql_query(mdb, buf.c_str(), result_handler, ctx);
}
-/* The decision do change an incr/diff was done before
+/**
+ * This procedure gets the base jobid list used by jobids,
+ */
+bool db_get_used_base_jobids(JCR *jcr, B_DB *mdb,
+ POOLMEM *jobids, db_list_ctx *result)
+{
+ POOL_MEM buf;
+ Mmsg(buf,
+ "SELECT DISTINCT BaseJobId "
+ " FROM Job JOIN BaseFiles USING (JobId) "
+ " WHERE Job.HasBase = 1 "
+ " AND Job.JobId IN (%s) ", jobids);
+ return db_sql_query(mdb, buf.c_str(), db_list_handler, result);
+}
+
+/**
+ * The decision do change an incr/diff was done before
* Full : do nothing
* Differential : get the last full id
* Incremental : get the last full + last diff + last incr(s) ids
*
+ * If you specify jr->StartTime, it will be used to limit the search
+ * in the time. (usually now)
+ *
* TODO: look and merge from ua_restore.c
*/
bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb,
- JOB_DBR *jr, POOLMEM *jobids)
+ JOB_DBR *jr, db_list_ctx *jobids)
{
bool ret=false;
char clientid[50], jobid[50], filesetid[50];
char date[MAX_TIME_LENGTH];
POOL_MEM query(PM_FNAME);
- bstrutime(date, sizeof(date), time(NULL) + 1);
- jobids[0]='\0';
+
+ /* Take the current time as upper limit if nothing else specified */
+ utime_t StartTime = (jr->StartTime)?jr->StartTime:time(NULL);
+
+ bstrutime(date, sizeof(date), StartTime + 1);
+ jobids->reset();
/* First, find the last good Full backup for this job/client/fileset */
- Mmsg(query,
-"CREATE 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",
+ Mmsg(query, create_temp_accurate_jobids[db_type],
edit_uint64(jcr->JobId, jobid),
edit_uint64(jr->ClientId, clientid),
date,
"SELECT JobId, StartTime, EndTime, JobTDate, PurgedFiles "
"FROM Job JOIN FileSet USING (FileSetId) "
"WHERE ClientId = %s "
- "AND Level='D' AND JobStatus='T' AND Type='B' "
+ "AND Level='D' AND JobStatus IN ('T','W') AND Type='B' "
"AND StartTime > (SELECT EndTime FROM btemp3%s ORDER BY EndTime DESC LIMIT 1) "
+ "AND StartTime < '%s' "
"AND FileSet.FileSet= (SELECT FileSet FROM FileSet WHERE FileSetId = %s) "
"ORDER BY Job.JobTDate DESC LIMIT 1 ",
jobid,
clientid,
jobid,
+ date,
filesetid);
if (!db_sql_query(mdb, query.c_str(), NULL, NULL)) {
"SELECT JobId, StartTime, EndTime, JobTDate, PurgedFiles "
"FROM Job JOIN FileSet USING (FileSetId) "
"WHERE ClientId = %s "
- "AND Level='I' AND JobStatus='T' AND Type='B' "
+ "AND Level='I' AND JobStatus IN ('T','W') AND Type='B' "
"AND StartTime > (SELECT EndTime FROM btemp3%s ORDER BY EndTime DESC LIMIT 1) "
+ "AND StartTime < '%s' "
"AND FileSet.FileSet= (SELECT FileSet FROM FileSet WHERE FileSetId = %s) "
"ORDER BY Job.JobTDate DESC ",
jobid,
clientid,
jobid,
+ date,
filesetid);
if (!db_sql_query(mdb, query.c_str(), NULL, NULL)) {
goto bail_out;
}
/* build a jobid list ie: 1,2,3,4 */
- Mmsg(query, "SELECT JobId FROM btemp3%s", jobid);
- db_sql_query(mdb, query.c_str(), db_get_int_handler, jobids);
- Dmsg1(1, "db_accurate_get_jobids=%s\n", jobids);
+ Mmsg(query, "SELECT JobId FROM btemp3%s ORDER by JobTDate", jobid);
+ db_sql_query(mdb, query.c_str(), db_list_handler, jobids);
+ Dmsg1(1, "db_accurate_get_jobids=%s\n", jobids->list);
ret = true;
bail_out:
return ret;
}
-/*
- * Use to build a string of int list from a query. "10,20,30"
- */
-int db_get_int_handler(void *ctx, int num_fields, char **row)
+bool db_get_base_file_list(JCR *jcr, B_DB *mdb,
+ DB_RESULT_HANDLER *result_handler, void *ctx)
{
- POOLMEM *ret = (POOLMEM *)ctx;
- if (num_fields == 1) {
- if (ret[0]) {
- pm_strcat(ret, ",");
- }
- pm_strcat(ret, row[0]);
+ POOL_MEM buf(PM_MESSAGE);
+
+ Mmsg(buf,
+ "SELECT Path, Name, FileIndex, JobId, LStat, MD5 "
+ "FROM new_basefile%lld ORDER BY JobId, FileIndex ASC",
+ (uint64_t) jcr->JobId);
+
+ return db_sql_query(mdb, buf.c_str(), result_handler, ctx);
+}
+
+bool db_get_base_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr, JobId_t *jobid)
+{
+ POOL_MEM query(PM_FNAME);
+ utime_t StartTime;
+ db_int64_ctx lctx;
+ char date[MAX_TIME_LENGTH];
+ bool ret=false;
+// char clientid[50], filesetid[50];
+ *jobid = 0;
+ lctx.count = 0;
+ lctx.value = 0;
+
+ 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(10, "db_get_base_jobid q=%s\n", query.c_str());
+ if (!db_sql_query(mdb, query.c_str(), db_int64_handler, &lctx)) {
+ goto bail_out;
}
- return 0;
+ *jobid = (JobId_t) lctx.value;
+
+ Dmsg1(10, "db_get_base_jobid=%lld\n", *jobid);
+ ret = true;
+
+bail_out:
+ return ret;
}
-#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_DBI */
+#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI */