2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 Bacula® is a registered trademark of Kern Sibbald.
17 * Bacula Catalog Database Delete record interface routines
19 * Written by Kern Sibbald, December 2000
25 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL
31 /* -----------------------------------------------------------------------
33 * Generic Routines (or almost generic)
35 * -----------------------------------------------------------------------
39 * Delete Pool record, must also delete all associated
44 * PoolId = number of Pools deleted (should be 1)
45 * NumVols = number of Media records deleted
48 db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
52 char esc[MAX_ESCAPE_NAME_LENGTH];
55 mdb->db_escape_string(jcr, esc, pr->Name, strlen(pr->Name));
56 Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", esc);
57 Dmsg1(10, "selectpool: %s\n", mdb->cmd);
59 pr->PoolId = pr->NumVols = 0;
61 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
63 num_rows = sql_num_rows(mdb);
65 Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
69 } else if (num_rows != 1) {
70 Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), num_rows);
75 if ((row = sql_fetch_row(mdb)) == NULL) {
76 Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb));
80 pr->PoolId = str_to_int64(row[0]);
84 /* Delete Media owned by this pool */
86 "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId);
88 pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd);
89 Dmsg1(200, "Deleted %d Media records\n", pr->NumVols);
93 "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId);
94 pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd);
95 Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId);
101 #define MAX_DEL_LIST_LEN 1000000
105 int num_ids; /* ids stored */
106 int max_ids; /* size of array */
107 int num_del; /* number deleted */
108 int tot_ids; /* total to process */
112 * Called here to make in memory list of JobIds to be
113 * deleted. The in memory list will then be transversed
114 * to issue the SQL DELETE commands. Note, the list
115 * is allowed to get to MAX_DEL_LIST_LEN to limit the
116 * maximum malloc'ed memory.
118 static int delete_handler(void *ctx, int num_fields, char **row)
120 struct s_del_ctx *del = (struct s_del_ctx *)ctx;
122 if (del->num_ids == MAX_DEL_LIST_LEN) {
125 if (del->num_ids == del->max_ids) {
126 del->max_ids = (del->max_ids * 3) / 2;
127 del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
130 del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
136 * This routine will purge (delete) all records
137 * associated with a particular Volume. It will
138 * not delete the media record itself.
139 * TODO: This function is broken and it doesn't purge
140 * File, BaseFiles, Log, ...
141 * We call it from relabel and delete volume=, both ensure
142 * that the volume is properly purged.
144 static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
146 POOLMEM *query = get_pool_memory(PM_MESSAGE);
147 struct s_del_ctx del;
155 Mmsg(mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId);
156 del.max_ids = mr->VolJobs;
157 if (del.max_ids < 100) {
159 } else if (del.max_ids > MAX_DEL_LIST_LEN) {
160 del.max_ids = MAX_DEL_LIST_LEN;
162 del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
163 db_sql_query(mdb, mdb->cmd, delete_handler, (void *)&del);
165 for (i=0; i < del.num_ids; i++) {
166 Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]);
167 Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
168 db_sql_query(mdb, query, NULL, (void *)NULL);
169 Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
170 db_sql_query(mdb, query, NULL, (void *)NULL);
171 Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
172 db_sql_query(mdb, query, NULL, (void *)NULL);
175 free_pool_memory(query);
179 /* Delete Media record and all records that
180 * are associated with it.
182 int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
185 if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
189 /* Do purge if not already purged */
190 if (strcmp(mr->VolStatus, "Purged") != 0) {
191 /* Delete associated records */
192 do_media_purge(mdb, mr);
195 Mmsg(mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId);
196 db_sql_query(mdb, mdb->cmd, NULL, (void *)NULL);
202 * Purge all records associated with a
203 * media record. This does not delete the
204 * media record itself. But the media status
205 * is changed to "Purged".
207 int db_purge_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
210 if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
214 /* Delete associated records */
215 do_media_purge(mdb, mr); /* Note, always purge */
217 /* Mark Volume as purged */
218 strcpy(mr->VolStatus, "Purged");
219 if (!db_update_media_record(jcr, mdb, mr)) {
229 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL */