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.
return true;
}
+/*
+ * Use pool and client specified by user to select jobs to prune
+ * returns add_from string to add in FROM clause
+ * add_where string to add in WHERE clause
+ */
+bool prune_set_filter(UAContext *ua, CLIENT *client, POOL *pool, utime_t period,
+ POOL_MEM *add_from, POOL_MEM *add_where)
+{
+ utime_t now;
+ char ed1[50], ed2[MAX_ESCAPE_NAME_LENGTH];
+ POOL_MEM tmp(PM_MESSAGE);
+
+ now = (utime_t)time(NULL);
+ edit_int64(now - period, ed1);
+ Dmsg3(150, "now=%lld period=%lld JobTDate=%s\n", now, period, ed1);
+ Mmsg(tmp, " AND JobTDate < %s ", ed1);
+ pm_strcat(*add_where, tmp.c_str());
+
+ db_lock(ua->db);
+ if (client) {
+ db_escape_string(ua->jcr, ua->db, ed2,
+ client->name(), strlen(client->name()));
+ Mmsg(tmp, " AND Client.Name = '%s' ", ed2);
+ pm_strcat(*add_where, tmp.c_str());
+ pm_strcat(*add_from, " JOIN Client USING (ClientId) ");
+ }
+
+ if (pool) {
+ db_escape_string(ua->jcr, ua->db, ed2,
+ pool->name(), strlen(pool->name()));
+ Mmsg(tmp, " AND Pool.Name = '%s' ", ed2);
+ pm_strcat(*add_where, tmp.c_str());
+ /* Use ON() instead of USING for some old SQLite */
+ pm_strcat(*add_from, " JOIN Pool ON (Job.PoolId = Pool.PoolId) ");
+ }
+ Dmsg2(150, "f=%s w=%s\n", add_from->c_str(), add_where->c_str());
+ db_unlock(ua->db);
+ return true;
+}
+
/*
* Prune File records from the database. For any Job which
* is older than the retention period, we unconditionally delete
* This routine assumes you want the pruning to be done. All checking
* must be done before calling this routine.
*
- * Note: pool can possibly be NULL.
+ * Note: client or pool can possibly be NULL (not both).
*/
int prune_files(UAContext *ua, CLIENT *client, POOL *pool)
{
struct del_ctx del;
struct s_count_ctx cnt;
POOL_MEM query(PM_MESSAGE);
- utime_t now, period;
- CLIENT_DBR cr;
- char ed1[50], ed2[50];
-
- db_lock(ua->db);
- memset(&cr, 0, sizeof(cr));
+ POOL_MEM sql_where(PM_MESSAGE);
+ POOL_MEM sql_from(PM_MESSAGE);
+ utime_t period;
+ char ed1[50];
+
memset(&del, 0, sizeof(del));
- bstrncpy(cr.Name, client->name(), sizeof(cr.Name));
- if (!db_create_client_record(ua->jcr, ua->db, &cr)) {
- db_unlock(ua->db);
- return 0;
- }
if (pool && pool->FileRetention > 0) {
period = pool->FileRetention;
- } else {
+
+ } else if (client) {
period = client->FileRetention;
+
+ } else { /* should specify at least pool or client */
+ return false;
+ }
+
+ db_lock(ua->db);
+ /* Specify JobTDate and Pool.Name= and/or Client.Name= in the query */
+ if (!prune_set_filter(ua, client, pool, period, &sql_from, &sql_where)) {
+ goto bail_out;
}
- now = (utime_t)time(NULL);
// edit_utime(now-period, ed1, sizeof(ed1));
// Jmsg(ua->jcr, M_INFO, 0, _("Begin pruning Jobs older than %s secs.\n"), ed1);
- Jmsg(ua->jcr, M_INFO, 0, _("Begin pruning Jobs.\n"));
+ Jmsg(ua->jcr, M_INFO, 0, _("Begin pruning Files.\n"));
/* Select Jobs -- for counting */
- edit_int64(now - period, ed1);
- Mmsg(query, count_select_job, ed1, edit_int64(cr.ClientId, ed2));
- Dmsg3(050, "select now=%u period=%u sql=%s\n", (uint32_t)now,
- (uint32_t)period, query.c_str());
+ Mmsg(query,
+ "SELECT COUNT(1) FROM Job %s WHERE PurgedFiles=0 %s",
+ sql_from.c_str(), sql_where.c_str());
+ Dmsg1(050, "select sql=%s\n", query.c_str());
cnt.count = 0;
if (!db_sql_query(ua->db, query.c_str(), del_count_handler, (void *)&cnt)) {
ua->error_msg("%s", db_strerror(ua->db));
del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
/* Now process same set but making a delete list */
- Mmsg(query, select_job, edit_int64(now - period, ed1),
- edit_int64(cr.ClientId, ed2));
+ Mmsg(query, "SELECT JobId FROM Job %s WHERE PurgedFiles=0 %s",
+ sql_from.c_str(), sql_where.c_str());
+ Dmsg1(050, "select sql=%s\n", query.c_str());
db_sql_query(ua->db, query.c_str(), file_delete_handler, (void *)&del);
purge_files_from_job_list(ua, del);
static bool create_temp_tables(UAContext *ua)
{
/* Create temp tables and indicies */
- if (!db_sql_query(ua->db, create_deltabs[db_type], NULL, (void *)NULL)) {
+ if (!db_sql_query(ua->db, create_deltabs[db_get_type_index(ua->db)], NULL, (void *)NULL)) {
ua->error_msg("%s", db_strerror(ua->db));
Dmsg0(050, "create DelTables table failed\n");
return false;
/* If this job doesn't exist anymore in the configuration, delete it */
if (GetResWithName(R_JOB, row[0]) == NULL) {
- return 1;
+ return 0;
}
/* If this fileset doesn't exist anymore in the configuration, delete it */
if (GetResWithName(R_FILESET, row[1]) == NULL) {
- return 1;
+ return 0;
}
/* If this client doesn't exist anymore in the configuration, delete it */
if (GetResWithName(R_CLIENT, row[2]) == NULL) {
- return 1;
+ return 0;
}
/* Don't compute accurate things for Verify jobs */
if (*row[5] == 'V') {
- return 1;
+ return 0;
}
res = (struct accurate_check_ctx*) malloc(sizeof(struct accurate_check_ctx));
*/
int prune_jobs(UAContext *ua, CLIENT *client, POOL *pool, int JobType)
{
- struct del_ctx del;
POOL_MEM query(PM_MESSAGE);
- utime_t now, period;
- CLIENT_DBR cr ;
- char ed1[50], ed2[50];
+ POOL_MEM sql_where(PM_MESSAGE);
+ POOL_MEM sql_from(PM_MESSAGE);
+ utime_t period;
+ char ed1[50];
alist *jobids_check=NULL;
struct accurate_check_ctx *elt;
db_list_ctx jobids, tempids;
JOB_DBR jr;
-
- db_lock(ua->db);
- memset(&cr, 0, sizeof(cr));
-
- bstrncpy(cr.Name, client->name(), sizeof(cr.Name));
- if (!db_create_client_record(ua->jcr, ua->db, &cr)) {
- db_unlock(ua->db);
- return 0;
- }
+ struct del_ctx del;
+ memset(&del, 0, sizeof(del));
if (pool && pool->JobRetention > 0) {
period = pool->JobRetention;
- } else {
+
+ } else if (client) {
period = client->JobRetention;
+
+ } else { /* should specify at least pool or client */
+ return false;
+ }
+
+ db_lock(ua->db);
+ if (!prune_set_filter(ua, client, pool, period, &sql_from, &sql_where)) {
+ goto bail_out;
}
- now = (utime_t)time(NULL);
/* Drop any previous temporary tables still there */
drop_temp_tables(ua);
edit_utime(period, ed1, sizeof(ed1));
Jmsg(ua->jcr, M_INFO, 0, _("Begin pruning Jobs older than %s.\n"), ed1);
- edit_int64(now - period, ed1); /* Jobs older than ed1 are good candidates */
- edit_int64(cr.ClientId, ed2);
-
- memset(&del, 0, sizeof(del));
del.max_ids = 100;
del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
del.PurgedFiles = (char *)malloc(del.max_ids);
/*
* Select all files that are older than the JobRetention period
- * and stuff them into the "DeletionCandidates" table.
+ * and add them into the "DeletionCandidates" table.
*/
Mmsg(query,
"INSERT INTO DelCandidates "
"SELECT JobId,PurgedFiles,FileSetId,JobFiles,JobStatus "
- "FROM Job "
+ "FROM Job %s " /* JOIN Pool/Client */
"WHERE Type IN ('B', 'C', 'M', 'V', 'D', 'R', 'c', 'm', 'g') "
- "AND JobTDate<%s AND ClientId=%s",
- ed1, ed2);
+ " %s ", /* Pool/Client + JobTDate */
+ sql_from.c_str(), sql_where.c_str());
+ Dmsg1(050, "select sql=%s\n", query.c_str());
if (!db_sql_query(ua->db, query.c_str(), NULL, (void *)NULL)) {
if (ua->verbose) {
ua->error_msg("%s", db_strerror(ua->db));
jr.ClientId = elt->ClientId; /* should be always the same */
jr.FileSetId = elt->FileSetId;
db_accurate_get_jobids(ua->jcr, ua->db, &jr, &tempids);
- jobids.cat(tempids);
+ jobids.add(tempids);
}
/* Discard latest Verify level=InitCatalog job
*/
Mmsg(query,
"SELECT JobId, JobTDate "
- "FROM Job "
- "WHERE JobTDate<%s AND ClientId=%s "
- "AND Type='V' AND Level='V' "
+ "FROM Job %s " /* JOIN Client/Pool */
+ "WHERE Type='V' AND Level='V' "
+ " %s " /* Pool, JobTDate, Client */
"ORDER BY JobTDate DESC LIMIT 1",
- ed1, ed2);
+ sql_from.c_str(), sql_where.c_str());
if (!db_sql_query(ua->db, query.c_str(), db_list_handler, &jobids)) {
ua->error_msg("%s", db_strerror(ua->db));