]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_update.c
Apply patch (with some difficulties) from Joao Henrique Freitas
[bacula/bacula] / bacula / src / cats / sql_update.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Bacula Catalog Database Update record interface routines
30  *
31  *    Kern Sibbald, March 2000
32  *
33  *    Version $Id$
34  */
35
36 /* The following is necessary so that we do not include
37  * the dummy external definition of DB.
38  */
39 #define __SQL_C                       /* indicate that this is sql.c */
40
41 #include "bacula.h"
42 #include "cats.h"
43
44 #if    HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_DBI
45
46 /* -----------------------------------------------------------------------
47  *
48  *   Generic Routines (or almost generic)
49  *
50  * -----------------------------------------------------------------------
51  */
52
53 /* -----------------------------------------------------------------------
54  *
55  *   Generic Routines (or almost generic)
56  *
57  * -----------------------------------------------------------------------
58  */
59 /* Update the attributes record by adding the file digest */
60 int
61 db_add_digest_to_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, char *digest,
62                           int type)
63 {
64    int stat;
65    char ed1[50];
66
67    db_lock(mdb);
68    Mmsg(mdb->cmd, "UPDATE File SET MD5='%s' WHERE FileId=%s", digest, 
69       edit_int64(FileId, ed1));
70    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
71    db_unlock(mdb);
72    return stat;
73 }
74
75 /* Mark the file record as being visited during database
76  * verify compare. Stuff JobId into the MarkId field
77  */
78 int db_mark_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, JobId_t JobId)
79 {
80    int stat;
81    char ed1[50], ed2[50];
82
83    db_lock(mdb);
84    Mmsg(mdb->cmd, "UPDATE File SET MarkId=%s WHERE FileId=%s", 
85       edit_int64(JobId, ed1), edit_int64(FileId, ed2));
86    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
87    db_unlock(mdb);
88    return stat;
89 }
90
91 /*
92  * Update the Job record at start of Job
93  *
94  *  Returns: false on failure
95  *           true  on success
96  */
97 bool
98 db_update_job_start_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
99 {
100    char dt[MAX_TIME_LENGTH];
101    time_t stime;
102    struct tm tm;
103    btime_t JobTDate;
104    int stat;
105    char ed1[50], ed2[50], ed3[50], ed4[50];
106
107    stime = jr->StartTime;
108    (void)localtime_r(&stime, &tm);
109    strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
110    JobTDate = (btime_t)stime;
111
112    db_lock(mdb);
113    Mmsg(mdb->cmd, "UPDATE Job SET JobStatus='%c',Level='%c',StartTime='%s',"
114 "ClientId=%s,JobTDate=%s,PoolId=%s WHERE JobId=%s",
115       (char)(jcr->JobStatus),
116       (char)(jr->JobLevel), dt, 
117       edit_int64(jr->ClientId, ed1),
118       edit_uint64(JobTDate, ed2), 
119       edit_int64(jr->PoolId, ed3),
120       edit_int64(jr->JobId, ed4));
121
122    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
123    mdb->changes = 0;
124    db_unlock(mdb);
125    return stat;
126 }
127
128 /*
129  * Given an incoming integer, set the string buffer to either NULL or the value
130  *
131  */
132 static void edit_num_or_null(char *s, size_t n, uint64_t id) {
133    char ed1[50];
134    bsnprintf(s, n, id ? "%s" : "NULL", edit_int64(id, ed1));
135 }
136
137
138 /*
139  * Update the Job record at end of Job
140  *
141  *  Returns: 0 on failure
142  *           1 on success
143  */
144 int
145 db_update_job_end_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
146 {
147    char dt[MAX_TIME_LENGTH];
148    char rdt[MAX_TIME_LENGTH];
149    time_t ttime;
150    struct tm tm;
151    int stat;
152    char ed1[30], ed2[30], ed3[50];
153    btime_t JobTDate;
154    char PoolId[50], FileSetId[50], ClientId[50], PriorJobId[50];
155
156
157    /* some values are set to zero, which translates to NULL in SQL */
158    edit_num_or_null(PoolId,    sizeof(PoolId),    jr->PoolId);
159    edit_num_or_null(FileSetId, sizeof(FileSetId), jr->FileSetId);
160    edit_num_or_null(ClientId,  sizeof(ClientId),  jr->ClientId);
161
162    if (jr->PriorJobId) {
163       bstrncpy(PriorJobId, edit_int64(jr->PriorJobId, ed1), sizeof(PriorJobId));
164    } else {
165       bstrncpy(PriorJobId, "0", sizeof(PriorJobId));
166    }
167
168    ttime = jr->EndTime;
169    (void)localtime_r(&ttime, &tm);
170    strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
171
172    if (jr->RealEndTime == 0) {
173       jr->RealEndTime = jr->EndTime;
174    }
175    ttime = jr->RealEndTime;
176    (void)localtime_r(&ttime, &tm);
177    strftime(rdt, sizeof(rdt), "%Y-%m-%d %H:%M:%S", &tm);
178
179    JobTDate = ttime;
180
181    db_lock(mdb);
182    Mmsg(mdb->cmd,
183       "UPDATE Job SET JobStatus='%c',EndTime='%s',"
184 "ClientId=%s,JobBytes=%s,JobFiles=%u,JobErrors=%u,VolSessionId=%u,"
185 "VolSessionTime=%u,PoolId=%s,FileSetId=%s,JobTDate=%s,"
186 "RealEndTime='%s',PriorJobId=%s WHERE JobId=%s",
187       (char)(jr->JobStatus), dt, ClientId, edit_uint64(jr->JobBytes, ed1),
188       jr->JobFiles, jr->JobErrors, jr->VolSessionId, jr->VolSessionTime,
189       PoolId, FileSetId, edit_uint64(JobTDate, ed2), 
190       rdt,
191       PriorJobId,
192       edit_int64(jr->JobId, ed3));
193
194    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
195    db_unlock(mdb);
196    return stat;
197 }
198
199
200 /*
201  * Update Client record
202  *   Returns: 0 on failure
203  *            1 on success
204  */
205 int
206 db_update_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr)
207 {
208    int stat;
209    char ed1[50], ed2[50];
210    CLIENT_DBR tcr;
211
212    db_lock(mdb);
213    memcpy(&tcr, cr, sizeof(tcr));
214    if (!db_create_client_record(jcr, mdb, &tcr)) {
215       db_unlock(mdb);
216       return 0;
217    }
218
219    Mmsg(mdb->cmd,
220 "UPDATE Client SET AutoPrune=%d,FileRetention=%s,JobRetention=%s,"
221 "Uname='%s' WHERE Name='%s'",
222       cr->AutoPrune,
223       edit_uint64(cr->FileRetention, ed1),
224       edit_uint64(cr->JobRetention, ed2),
225       cr->Uname, cr->Name);
226
227    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
228    db_unlock(mdb);
229    return stat;
230 }
231
232
233 /*
234  * Update Counters record
235  *   Returns: 0 on failure
236  *            1 on success
237  */
238 int db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
239 {
240    db_lock(mdb);
241
242    Mmsg(mdb->cmd,
243 "UPDATE Counters SET MinValue=%d,MaxValue=%d,CurrentValue=%d,"
244 "WrapCounter='%s' WHERE Counter='%s'",
245       cr->MinValue, cr->MaxValue, cr->CurrentValue,
246       cr->WrapCounter, cr->Counter);
247
248    int stat = UPDATE_DB(jcr, mdb, mdb->cmd);
249    db_unlock(mdb);
250    return stat;
251 }
252
253
254 int db_update_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
255 {
256    int stat;
257    char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50];
258
259    db_lock(mdb);
260    Mmsg(mdb->cmd, "SELECT count(*) from Media WHERE PoolId=%s",
261       edit_int64(pr->PoolId, ed4));
262    pr->NumVols = get_sql_record_max(jcr, mdb);
263    Dmsg1(400, "NumVols=%d\n", pr->NumVols);
264
265    Mmsg(mdb->cmd,
266 "UPDATE Pool SET NumVols=%u,MaxVols=%u,UseOnce=%d,UseCatalog=%d,"
267 "AcceptAnyVolume=%d,VolRetention='%s',VolUseDuration='%s',"
268 "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,Recycle=%d,"
269 "AutoPrune=%d,LabelType=%d,LabelFormat='%s',RecyclePoolId=%s WHERE PoolId=%s",
270       pr->NumVols, pr->MaxVols, pr->UseOnce, pr->UseCatalog,
271       pr->AcceptAnyVolume, edit_uint64(pr->VolRetention, ed1),
272       edit_uint64(pr->VolUseDuration, ed2),
273       pr->MaxVolJobs, pr->MaxVolFiles,
274       edit_uint64(pr->MaxVolBytes, ed3),
275       pr->Recycle, pr->AutoPrune, pr->LabelType,
276       pr->LabelFormat, edit_int64(pr->RecyclePoolId,ed5),
277       ed4);
278
279    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
280    db_unlock(mdb);
281    return stat;
282 }
283
284 bool
285 db_update_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr)
286 {
287    int stat;
288    char ed1[50];
289
290    db_lock(mdb);
291    Mmsg(mdb->cmd, "UPDATE Storage SET AutoChanger=%d WHERE StorageId=%s", 
292       sr->AutoChanger, edit_int64(sr->StorageId, ed1));
293
294    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
295    db_unlock(mdb);
296    return stat;
297 }
298
299
300 /*
301  * Update the Media Record at end of Session
302  *
303  * Returns: 0 on failure
304  *          numrows on success
305  */
306 int
307 db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
308 {
309    char dt[MAX_TIME_LENGTH];
310    time_t ttime;
311    struct tm tm;
312    int stat;
313    char ed1[50], ed2[50],  ed3[50],  ed4[50]; 
314    char ed5[50], ed6[50],  ed7[50],  ed8[50];
315    char ed9[50], ed10[50], ed11[50];
316
317
318    Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
319    db_lock(mdb);
320    if (mr->set_first_written) {
321       Dmsg1(400, "Set FirstWritten Vol=%s\n", mr->VolumeName);
322       ttime = mr->FirstWritten;
323       (void)localtime_r(&ttime, &tm);
324       strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
325       Mmsg(mdb->cmd, "UPDATE Media SET FirstWritten='%s'"
326            " WHERE VolumeName='%s'", dt, mr->VolumeName);
327       stat = UPDATE_DB(jcr, mdb, mdb->cmd);
328       Dmsg1(400, "Firstwritten=%d\n", mr->FirstWritten);
329    }
330
331    /* Label just done? */
332    if (mr->set_label_date) {
333       ttime = mr->LabelDate;
334       if (ttime == 0) {
335          ttime = time(NULL);
336       }
337       (void)localtime_r(&ttime, &tm);
338       strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
339       Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' "
340            "WHERE VolumeName='%s'", dt, mr->VolumeName);
341       UPDATE_DB(jcr, mdb, mdb->cmd);
342    }
343
344    if (mr->LastWritten != 0) {
345       ttime = mr->LastWritten;
346       (void)localtime_r(&ttime, &tm);
347       strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
348       Mmsg(mdb->cmd, "UPDATE Media Set LastWritten='%s' "
349            "WHERE VolumeName='%s'", dt, mr->VolumeName);
350       UPDATE_DB(jcr, mdb, mdb->cmd);
351    }
352
353    Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u,"
354         "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u,"
355         "VolWrites=%u,MaxVolBytes=%s,VolStatus='%s',"
356         "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d,"
357         "LabelType=%d,StorageId=%s,PoolId=%s,VolRetention=%s,VolUseDuration=%s,"
358         "MaxVolJobs=%d,MaxVolFiles=%d,Enabled=%d,LocationId=%s,"
359         "ScratchPoolId=%s,RecyclePoolId=%s,RecycleCount=%d"
360         " WHERE VolumeName='%s'",
361         mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
362         mr->VolMounts, mr->VolErrors, mr->VolWrites,
363         edit_uint64(mr->MaxVolBytes, ed2),
364         mr->VolStatus, mr->Slot, mr->InChanger,
365         edit_int64(mr->VolReadTime, ed3),
366         edit_int64(mr->VolWriteTime, ed4),
367         mr->VolParts,
368         mr->LabelType,
369         edit_int64(mr->StorageId, ed5),
370         edit_int64(mr->PoolId, ed6),
371         edit_uint64(mr->VolRetention, ed7),
372         edit_uint64(mr->VolUseDuration, ed8),
373         mr->MaxVolJobs, mr->MaxVolFiles,
374         mr->Enabled, edit_uint64(mr->LocationId, ed9),
375         edit_uint64(mr->ScratchPoolId, ed10),
376         edit_uint64(mr->RecyclePoolId, ed11),
377         mr->RecycleCount,
378         mr->VolumeName);
379
380    Dmsg1(400, "%s\n", mdb->cmd);
381
382    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
383
384    /* Make sure InChanger is 0 for any record having the same Slot */
385    db_make_inchanger_unique(jcr, mdb, mr);
386
387    db_unlock(mdb);
388    return stat;
389 }
390
391 /*
392  * Update the Media Record Default values from Pool
393  *
394  * Returns: 0 on failure
395  *          numrows on success
396  */
397 int
398 db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
399 {
400    int stat;
401    char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50];
402
403
404    db_lock(mdb);
405    if (mr->VolumeName[0]) {
406       Mmsg(mdb->cmd, "UPDATE Media SET "
407            "Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
408            "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s"
409            " WHERE VolumeName='%s'",
410            mr->Recycle,edit_uint64(mr->VolRetention, ed1),
411            edit_uint64(mr->VolUseDuration, ed2),
412            mr->MaxVolJobs, mr->MaxVolFiles,
413            edit_uint64(mr->MaxVolBytes, ed3),
414            edit_uint64(mr->RecyclePoolId, ed4),
415            mr->VolumeName);
416    } else {
417       Mmsg(mdb->cmd, "UPDATE Media SET "
418            "Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
419            "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s"
420            " WHERE PoolId=%s",
421            mr->Recycle,edit_uint64(mr->VolRetention, ed1),
422            edit_uint64(mr->VolUseDuration, ed2),
423            mr->MaxVolJobs, mr->MaxVolFiles,
424            edit_uint64(mr->MaxVolBytes, ed3),
425            edit_int64(mr->RecyclePoolId, ed4),
426            edit_int64(mr->PoolId, ed5));
427    }
428
429    Dmsg1(400, "%s\n", mdb->cmd);
430
431    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
432
433    db_unlock(mdb);
434    return stat;
435 }
436
437
438 /*
439  * If we have a non-zero InChanger, ensure that no other Media
440  *  record has InChanger set on the same Slot.
441  *
442  * This routine assumes the database is already locked.
443  */
444 void
445 db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
446 {
447    char ed1[50], ed2[50];
448    if (mr->InChanger != 0 && mr->Slot != 0) {
449       Mmsg(mdb->cmd, "UPDATE Media SET InChanger=0 WHERE "
450            "Slot=%d AND StorageId=%s AND MediaId!=%s",
451             mr->Slot, 
452             edit_int64(mr->StorageId, ed1), edit_int64(mr->MediaId, ed2));
453       Dmsg1(400, "%s\n", mdb->cmd);
454       UPDATE_DB(jcr, mdb, mdb->cmd);
455    }
456 }
457
458 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/