]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_delete.c
Turn off debug code in jobq.c
[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$
7  */
8
9 /*
10    Copyright (C) 2000-2006 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    version 2 as amended with additional clauses defined in the
15    file LICENSE in the main source directory.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
20    the file LICENSE for additional details.
21
22  */
23
24 /* *****FIXME**** fix fixed length of select_cmd[] and insert_cmd[] */
25
26 /* The following is necessary so that we do not include
27  * the dummy external definition of DB.
28  */
29 #define __SQL_C                       /* indicate that this is sql.c */
30
31 #include "bacula.h"
32 #include "cats.h"
33
34
35 #if    HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
36 /* -----------------------------------------------------------------------
37  *
38  *   Generic Routines (or almost generic)
39  *
40  * -----------------------------------------------------------------------
41  */
42
43 /* Imported subroutines */
44 extern void print_dashes(B_DB *mdb);
45 extern void print_result(B_DB *mdb);
46 extern int QueryDB(const char *file, int line, JCR *jcr, B_DB *db, char *select_cmd);
47 extern int DeleteDB(const char *file, int line, JCR *jcr, B_DB *db, char *delete_cmd);
48
49 /*
50  * Delete Pool record, must also delete all associated
51  *  Media records.
52  *
53  *  Returns: 0 on error
54  *           1 on success
55  *           PoolId = number of Pools deleted (should be 1)
56  *           NumVols = number of Media records deleted
57  */
58 int
59 db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
60 {
61    SQL_ROW row;
62
63    db_lock(mdb);
64    Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", pr->Name);
65    Dmsg1(10, "selectpool: %s\n", mdb->cmd);
66
67    pr->PoolId = pr->NumVols = 0;
68
69    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
70
71       mdb->num_rows = sql_num_rows(mdb);
72
73       if (mdb->num_rows == 0) {
74          Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
75          sql_free_result(mdb);
76          db_unlock(mdb);
77          return 0;
78       } else if (mdb->num_rows != 1) {
79          Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), mdb->num_rows);
80          sql_free_result(mdb);
81          db_unlock(mdb);
82          return 0;
83       }
84       if ((row = sql_fetch_row(mdb)) == NULL) {
85          Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb));
86          db_unlock(mdb);
87          return 0;
88       }
89       pr->PoolId = str_to_int64(row[0]);
90       sql_free_result(mdb);
91    }
92
93    /* Delete Media owned by this pool */
94    Mmsg(mdb->cmd,
95 "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId);
96
97    pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd);
98    Dmsg1(200, "Deleted %d Media records\n", pr->NumVols);
99
100    /* Delete Pool */
101    Mmsg(mdb->cmd,
102 "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId);
103    pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd);
104    Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId);
105
106    db_unlock(mdb);
107    return 1;
108 }
109
110 #define MAX_DEL_LIST_LEN 1000000
111
112 struct s_del_ctx {
113    JobId_t *JobId;
114    int num_ids;                       /* ids stored */
115    int max_ids;                       /* size of array */
116    int num_del;                       /* number deleted */
117    int tot_ids;                       /* total to process */
118 };
119
120 /*
121  * Called here to make in memory list of JobIds to be
122  *  deleted. The in memory list will then be transversed
123  *  to issue the SQL DELETE commands.  Note, the list
124  *  is allowed to get to MAX_DEL_LIST_LEN to limit the
125  *  maximum malloc'ed memory.
126  */
127 static int delete_handler(void *ctx, int num_fields, char **row)
128 {
129    struct s_del_ctx *del = (struct s_del_ctx *)ctx;
130
131    if (del->num_ids == MAX_DEL_LIST_LEN) {
132       return 1;
133    }
134    if (del->num_ids == del->max_ids) {
135       del->max_ids = (del->max_ids * 3) / 2;
136       del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
137          del->max_ids);
138    }
139    del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
140    return 0;
141 }
142
143
144 /*
145  * This routine will purge (delete) all records
146  * associated with a particular Volume. It will
147  * not delete the media record itself.
148  */
149 static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
150 {
151    POOLMEM *query = get_pool_memory(PM_MESSAGE);
152    struct s_del_ctx del;
153    char ed1[50];
154    int i;
155
156    del.num_ids = 0;
157    del.tot_ids = 0;
158    del.num_del = 0;
159    del.max_ids = 0;
160    Mmsg(mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId);
161    del.max_ids = mr->VolJobs;
162    if (del.max_ids < 100) {
163       del.max_ids = 100;
164    } else if (del.max_ids > MAX_DEL_LIST_LEN) {
165       del.max_ids = MAX_DEL_LIST_LEN;
166    }
167    del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
168    db_sql_query(mdb, mdb->cmd, delete_handler, (void *)&del);
169
170    for (i=0; i < del.num_ids; i++) {
171       Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]);
172       Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
173       db_sql_query(mdb, query, NULL, (void *)NULL);
174       Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
175       db_sql_query(mdb, query, NULL, (void *)NULL);
176       Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
177       db_sql_query(mdb, query, NULL, (void *)NULL);
178    }
179    free(del.JobId);
180    free_pool_memory(query);
181    return 1;
182 }
183
184 /* Delete Media record and all records that
185  * are associated with it.
186  */
187 int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
188 {
189    db_lock(mdb);
190    if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
191       db_unlock(mdb);
192       return 0;
193    }
194    /* Do purge if not already purged */
195    if (strcmp(mr->VolStatus, "Purged") != 0) {
196       /* Delete associated records */
197       do_media_purge(mdb, mr);
198    }
199
200    Mmsg(mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId);
201    db_sql_query(mdb, mdb->cmd, NULL, (void *)NULL);
202    db_unlock(mdb);
203    return 1;
204 }
205
206 /*
207  * Purge all records associated with a
208  * media record. This does not delete the
209  * media record itself. But the media status
210  * is changed to "Purged".
211  */
212 int db_purge_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
213 {
214    db_lock(mdb);
215    if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
216       db_unlock(mdb);
217       return 0;
218    }
219    /* Delete associated records */
220    do_media_purge(mdb, mr);           /* Note, always purge */
221
222    /* Mark Volume as purged */
223    strcpy(mr->VolStatus, "Purged");
224    if (!db_update_media_record(jcr, mdb, mr)) {
225       db_unlock(mdb);
226       return 0;
227    }
228
229    db_unlock(mdb);
230    return 1;
231 }
232
233
234 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/