]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_delete.c
Tweak layout and remove double cats.h include.
[bacula/bacula] / bacula / src / cats / sql_delete.c
1 /*
2  * Bacula Catalog Database Delete record interface routines
3  *
4  *    Kern Sibbald, December 2000
5  *
6  *    Version $Id: sql_delete.c 7380 2008-07-14 10:42:59Z kerns $
7  */
8 /*
9    Bacula® - The Network Backup Solution
10
11    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
12
13    The main author of Bacula is Kern Sibbald, with contributions from
14    many others, a complete list can be found in the file AUTHORS.
15    This program is Free Software; you can redistribute it and/or
16    modify it under the terms of version three of the GNU Affero General Public
17    License as published by the Free Software Foundation and included
18    in the file LICENSE.
19
20    This program is distributed in the hope that it will be useful, but
21    WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23    General Public License for more details.
24
25    You should have received a copy of the GNU Affero General Public License
26    along with this program; if not, write to the Free Software
27    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28    02110-1301, USA.
29
30    Bacula® is a registered trademark of Kern Sibbald.
31    The licensor of Bacula is the Free Software Foundation Europe
32    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
33    Switzerland, email:ftf@fsfeurope.org.
34 */
35
36 /* *****FIXME**** fix fixed length of select_cmd[] and insert_cmd[] */
37
38 #include "bacula.h"
39
40 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI
41
42 #include "cats.h"
43 #include "bdb_priv.h"
44 #include "sql_glue.h"
45
46 /* -----------------------------------------------------------------------
47  *
48  *   Generic Routines (or almost generic)
49  *
50  * -----------------------------------------------------------------------
51  */
52
53 /*
54  * Delete Pool record, must also delete all associated
55  *  Media records.
56  *
57  *  Returns: 0 on error
58  *           1 on success
59  *           PoolId = number of Pools deleted (should be 1)
60  *           NumVols = number of Media records deleted
61  */
62 int
63 db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
64 {
65    SQL_ROW row;
66    int num_rows;
67    char esc[MAX_ESCAPE_NAME_LENGTH];
68
69    db_lock(mdb);
70    mdb->db_escape_string(jcr, esc, pr->Name, strlen(pr->Name));
71    Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", esc);
72    Dmsg1(10, "selectpool: %s\n", mdb->cmd);
73
74    pr->PoolId = pr->NumVols = 0;
75
76    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
77
78       num_rows = sql_num_rows(mdb);
79       if (num_rows == 0) {
80          Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
81          sql_free_result(mdb);
82          db_unlock(mdb);
83          return 0;
84       } else if (num_rows != 1) {
85          Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), num_rows);
86          sql_free_result(mdb);
87          db_unlock(mdb);
88          return 0;
89       }
90       if ((row = sql_fetch_row(mdb)) == NULL) {
91          Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb));
92          db_unlock(mdb);
93          return 0;
94       }
95       pr->PoolId = str_to_int64(row[0]);
96       sql_free_result(mdb);
97    }
98
99    /* Delete Media owned by this pool */
100    Mmsg(mdb->cmd,
101 "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId);
102
103    pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd);
104    Dmsg1(200, "Deleted %d Media records\n", pr->NumVols);
105
106    /* Delete Pool */
107    Mmsg(mdb->cmd,
108 "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId);
109    pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd);
110    Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId);
111
112    db_unlock(mdb);
113    return 1;
114 }
115
116 #define MAX_DEL_LIST_LEN 1000000
117
118 struct s_del_ctx {
119    JobId_t *JobId;
120    int num_ids;                       /* ids stored */
121    int max_ids;                       /* size of array */
122    int num_del;                       /* number deleted */
123    int tot_ids;                       /* total to process */
124 };
125
126 /*
127  * Called here to make in memory list of JobIds to be
128  *  deleted. The in memory list will then be transversed
129  *  to issue the SQL DELETE commands.  Note, the list
130  *  is allowed to get to MAX_DEL_LIST_LEN to limit the
131  *  maximum malloc'ed memory.
132  */
133 static int delete_handler(void *ctx, int num_fields, char **row)
134 {
135    struct s_del_ctx *del = (struct s_del_ctx *)ctx;
136
137    if (del->num_ids == MAX_DEL_LIST_LEN) {
138       return 1;
139    }
140    if (del->num_ids == del->max_ids) {
141       del->max_ids = (del->max_ids * 3) / 2;
142       del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
143          del->max_ids);
144    }
145    del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
146    return 0;
147 }
148
149
150 /*
151  * This routine will purge (delete) all records
152  * associated with a particular Volume. It will
153  * not delete the media record itself.
154  * TODO: This function is broken and it doesn't purge
155  *       File, BaseFiles, Log, ...
156  *       We call it from relabel and delete volume=, both ensure
157  *       that the volume is properly purged.
158  */
159 static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
160 {
161    POOLMEM *query = get_pool_memory(PM_MESSAGE);
162    struct s_del_ctx del;
163    char ed1[50];
164    int i;
165
166    del.num_ids = 0;
167    del.tot_ids = 0;
168    del.num_del = 0;
169    del.max_ids = 0;
170    Mmsg(mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId);
171    del.max_ids = mr->VolJobs;
172    if (del.max_ids < 100) {
173       del.max_ids = 100;
174    } else if (del.max_ids > MAX_DEL_LIST_LEN) {
175       del.max_ids = MAX_DEL_LIST_LEN;
176    }
177    del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
178    db_sql_query(mdb, mdb->cmd, delete_handler, (void *)&del);
179
180    for (i=0; i < del.num_ids; i++) {
181       Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]);
182       Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
183       db_sql_query(mdb, query, NULL, (void *)NULL);
184       Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
185       db_sql_query(mdb, query, NULL, (void *)NULL);
186       Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
187       db_sql_query(mdb, query, NULL, (void *)NULL);
188    }
189    free(del.JobId);
190    free_pool_memory(query);
191    return 1;
192 }
193
194 /* Delete Media record and all records that
195  * are associated with it.
196  */
197 int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
198 {
199    db_lock(mdb);
200    if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
201       db_unlock(mdb);
202       return 0;
203    }
204    /* Do purge if not already purged */
205    if (strcmp(mr->VolStatus, "Purged") != 0) {
206       /* Delete associated records */
207       do_media_purge(mdb, mr);
208    }
209
210    Mmsg(mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId);
211    db_sql_query(mdb, mdb->cmd, NULL, (void *)NULL);
212    db_unlock(mdb);
213    return 1;
214 }
215
216 /*
217  * Purge all records associated with a
218  * media record. This does not delete the
219  * media record itself. But the media status
220  * is changed to "Purged".
221  */
222 int db_purge_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
223 {
224    db_lock(mdb);
225    if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
226       db_unlock(mdb);
227       return 0;
228    }
229    /* Delete associated records */
230    do_media_purge(mdb, mr);           /* Note, always purge */
231
232    /* Mark Volume as purged */
233    strcpy(mr->VolStatus, "Purged");
234    if (!db_update_media_record(jcr, mdb, mr)) {
235       db_unlock(mdb);
236       return 0;
237    }
238
239    db_unlock(mdb);
240    return 1;
241 }
242
243
244 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES */