]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_update.c
Merge branch 'master' of ssh://bacula.git.sourceforge.net/gitroot/bacula/bacula
[bacula/bacula] / bacula / src / cats / sql_update.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2008 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 Kern Sibbald.
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], ed5[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,FileSetId=%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->FileSetId, ed4),
121       edit_int64(jr->JobId, ed5));
122
123    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
124    mdb->changes = 0;
125    db_unlock(mdb);
126    return stat;
127 }
128
129 /*
130  * Update Long term statistics with all jobs that were run before
131  * age seconds
132  */
133 int
134 db_update_stats(JCR *jcr, B_DB *mdb, utime_t age)
135 {
136    char ed1[30];
137    utime_t now = (utime_t)time(NULL);
138    edit_uint64(now - age, ed1);
139
140    Mmsg(mdb->cmd, fill_jobhisto, ed1);
141    QUERY_DB(jcr, mdb, mdb->cmd); /* TODO: get a message ? */
142    return sql_affected_rows(mdb);
143 }
144
145 /*
146  * Update the Job record at end of Job
147  *
148  *  Returns: 0 on failure
149  *           1 on success
150  */
151 int
152 db_update_job_end_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
153 {
154    char dt[MAX_TIME_LENGTH];
155    char rdt[MAX_TIME_LENGTH];
156    time_t ttime;
157    struct tm tm;
158    int stat;
159    char ed1[30], ed2[30], ed3[50], ed4[50];
160    btime_t JobTDate;
161    char PriorJobId[50];
162
163    if (jr->PriorJobId) {
164       bstrncpy(PriorJobId, edit_int64(jr->PriorJobId, ed1), sizeof(PriorJobId));
165    } else {
166       bstrncpy(PriorJobId, "0", sizeof(PriorJobId));
167    }
168
169    ttime = jr->EndTime;
170    (void)localtime_r(&ttime, &tm);
171    strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
172
173    if (jr->RealEndTime == 0) {
174       jr->RealEndTime = jr->EndTime;
175    }
176    ttime = jr->RealEndTime;
177    (void)localtime_r(&ttime, &tm);
178    strftime(rdt, sizeof(rdt), "%Y-%m-%d %H:%M:%S", &tm);
179
180    JobTDate = ttime;
181
182    db_lock(mdb);
183    Mmsg(mdb->cmd,
184       "UPDATE Job SET JobStatus='%c',EndTime='%s',"
185 "ClientId=%u,JobBytes=%s,ReadBytes=%s,JobFiles=%u,JobErrors=%u,VolSessionId=%u,"
186 "VolSessionTime=%u,PoolId=%u,FileSetId=%u,JobTDate=%s,"
187 "RealEndTime='%s',PriorJobId=%s WHERE JobId=%s",
188       (char)(jr->JobStatus), dt, jr->ClientId, edit_uint64(jr->JobBytes, ed1),
189       edit_uint64(jr->ReadBytes, ed4),
190       jr->JobFiles, jr->JobErrors, jr->VolSessionId, jr->VolSessionTime,
191       jr->PoolId, jr->FileSetId, edit_uint64(JobTDate, ed2), 
192       rdt,
193       PriorJobId,
194       edit_int64(jr->JobId, ed3));
195
196    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
197
198    db_unlock(mdb);
199    return stat;
200 }
201
202 /*
203  * Update Client record
204  *   Returns: 0 on failure
205  *            1 on success
206  */
207 int
208 db_update_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr)
209 {
210    int stat;
211    char ed1[50], ed2[50];
212    CLIENT_DBR tcr;
213
214    db_lock(mdb);
215    memcpy(&tcr, cr, sizeof(tcr));
216    if (!db_create_client_record(jcr, mdb, &tcr)) {
217       db_unlock(mdb);
218       return 0;
219    }
220
221    Mmsg(mdb->cmd,
222 "UPDATE Client SET AutoPrune=%d,FileRetention=%s,JobRetention=%s,"
223 "Uname='%s' WHERE Name='%s'",
224       cr->AutoPrune,
225       edit_uint64(cr->FileRetention, ed1),
226       edit_uint64(cr->JobRetention, ed2),
227       cr->Uname, cr->Name);
228
229    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
230    db_unlock(mdb);
231    return stat;
232 }
233
234
235 /*
236  * Update Counters record
237  *   Returns: 0 on failure
238  *            1 on success
239  */
240 int db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
241 {
242    db_lock(mdb);
243
244    Mmsg(mdb->cmd,
245 "UPDATE Counters SET MinValue=%d,MaxValue=%d,CurrentValue=%d,"
246 "WrapCounter='%s' WHERE Counter='%s'",
247       cr->MinValue, cr->MaxValue, cr->CurrentValue,
248       cr->WrapCounter, cr->Counter);
249
250    int stat = UPDATE_DB(jcr, mdb, mdb->cmd);
251    db_unlock(mdb);
252    return stat;
253 }
254
255
256 int db_update_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
257 {
258    int stat;
259    char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50];
260
261    db_lock(mdb);
262    Mmsg(mdb->cmd, "SELECT count(*) from Media WHERE PoolId=%s",
263       edit_int64(pr->PoolId, ed4));
264    pr->NumVols = get_sql_record_max(jcr, mdb);
265    Dmsg1(400, "NumVols=%d\n", pr->NumVols);
266
267    Mmsg(mdb->cmd,
268 "UPDATE Pool SET NumVols=%u,MaxVols=%u,UseOnce=%d,UseCatalog=%d,"
269 "AcceptAnyVolume=%d,VolRetention='%s',VolUseDuration='%s',"
270 "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,Recycle=%d,"
271 "AutoPrune=%d,LabelType=%d,LabelFormat='%s',RecyclePoolId=%s,"
272 "ScratchPoolId=%s,ActionOnPurge=%d WHERE PoolId=%s",
273       pr->NumVols, pr->MaxVols, pr->UseOnce, pr->UseCatalog,
274       pr->AcceptAnyVolume, edit_uint64(pr->VolRetention, ed1),
275       edit_uint64(pr->VolUseDuration, ed2),
276       pr->MaxVolJobs, pr->MaxVolFiles,
277       edit_uint64(pr->MaxVolBytes, ed3),
278       pr->Recycle, pr->AutoPrune, pr->LabelType,
279       pr->LabelFormat, edit_int64(pr->RecyclePoolId,ed5),
280       edit_int64(pr->ScratchPoolId,ed6),
281       pr->ActionOnPurge,
282       ed4);
283    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
284    db_unlock(mdb);
285    return stat;
286 }
287
288 bool
289 db_update_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr)
290 {
291    int stat;
292    char ed1[50];
293    db_lock(mdb);
294    Mmsg(mdb->cmd, "UPDATE Storage SET AutoChanger=%d WHERE StorageId=%s", 
295       sr->AutoChanger, edit_int64(sr->StorageId, ed1));
296
297    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
298    db_unlock(mdb);
299    return stat;
300 }
301
302
303 /*
304  * Update the Media Record at end of Session
305  *
306  * Returns: 0 on failure
307  *          numrows on success
308  */
309 int
310 db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
311 {
312    char dt[MAX_TIME_LENGTH];
313    time_t ttime;
314    struct tm tm;
315    int stat;
316    char ed1[50], ed2[50],  ed3[50],  ed4[50]; 
317    char ed5[50], ed6[50],  ed7[50],  ed8[50];
318    char ed9[50], ed10[50], ed11[50];
319
320
321    Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
322    db_lock(mdb);
323    if (mr->set_first_written) {
324       Dmsg1(400, "Set FirstWritten Vol=%s\n", mr->VolumeName);
325       ttime = mr->FirstWritten;
326       (void)localtime_r(&ttime, &tm);
327       strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
328       Mmsg(mdb->cmd, "UPDATE Media SET FirstWritten='%s'"
329            " WHERE VolumeName='%s'", dt, mr->VolumeName);
330       stat = UPDATE_DB(jcr, mdb, mdb->cmd);
331       Dmsg1(400, "Firstwritten=%d\n", mr->FirstWritten);
332    }
333
334    /* Label just done? */
335    if (mr->set_label_date) {
336       ttime = mr->LabelDate;
337       if (ttime == 0) {
338          ttime = time(NULL);
339       }
340       (void)localtime_r(&ttime, &tm);
341       strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
342       Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' "
343            "WHERE VolumeName='%s'", dt, mr->VolumeName);
344       UPDATE_DB(jcr, mdb, mdb->cmd);
345    }
346
347    if (mr->LastWritten != 0) {
348       ttime = mr->LastWritten;
349       (void)localtime_r(&ttime, &tm);
350       strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
351       Mmsg(mdb->cmd, "UPDATE Media Set LastWritten='%s' "
352            "WHERE VolumeName='%s'", dt, mr->VolumeName);
353       UPDATE_DB(jcr, mdb, mdb->cmd);
354    }
355
356    /* sanity checks for #1066 */
357    if (mr->VolReadTime < 0) {
358       mr->VolReadTime = 0;
359    }
360    if (mr->VolWriteTime < 0) {
361       mr->VolWriteTime = 0;
362    }
363
364    Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u,"
365         "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u,"
366         "VolWrites=%u,MaxVolBytes=%s,VolStatus='%s',"
367         "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d,"
368         "LabelType=%d,StorageId=%s,PoolId=%s,VolRetention=%s,VolUseDuration=%s,"
369         "MaxVolJobs=%d,MaxVolFiles=%d,Enabled=%d,LocationId=%s,"
370         "ScratchPoolId=%s,RecyclePoolId=%s,RecycleCount=%d,Recycle=%d,ActionOnPurge=%d"
371         " WHERE VolumeName='%s'",
372         mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
373         mr->VolMounts, mr->VolErrors, mr->VolWrites,
374         edit_uint64(mr->MaxVolBytes, ed2),
375         mr->VolStatus, mr->Slot, mr->InChanger,
376         edit_int64(mr->VolReadTime, ed3),
377         edit_int64(mr->VolWriteTime, ed4),
378         mr->VolParts,
379         mr->LabelType,
380         edit_int64(mr->StorageId, ed5),
381         edit_int64(mr->PoolId, ed6),
382         edit_uint64(mr->VolRetention, ed7),
383         edit_uint64(mr->VolUseDuration, ed8),
384         mr->MaxVolJobs, mr->MaxVolFiles,
385         mr->Enabled, edit_uint64(mr->LocationId, ed9),
386         edit_uint64(mr->ScratchPoolId, ed10),
387         edit_uint64(mr->RecyclePoolId, ed11),
388         mr->RecycleCount,mr->Recycle, mr->ActionOnPurge,
389         mr->VolumeName);
390
391    Dmsg1(400, "%s\n", mdb->cmd);
392
393    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
394
395    /* Make sure InChanger is 0 for any record having the same Slot */
396    db_make_inchanger_unique(jcr, mdb, mr);
397
398    db_unlock(mdb);
399    return stat;
400 }
401
402 /*
403  * Update the Media Record Default values from Pool
404  *
405  * Returns: 0 on failure
406  *          numrows on success
407  */
408 int
409 db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
410 {
411    int stat;
412    char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50];
413
414
415    db_lock(mdb);
416    if (mr->VolumeName[0]) {
417       Mmsg(mdb->cmd, "UPDATE Media SET "
418            "ActionOnPurge=%d, Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
419            "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s"
420            " WHERE VolumeName='%s'",
421            mr->ActionOnPurge, 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_uint64(mr->RecyclePoolId, ed4),
426            mr->VolumeName);
427    } else {
428       Mmsg(mdb->cmd, "UPDATE Media SET "
429            "ActionOnPurge=%d, Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
430            "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s"
431            " WHERE PoolId=%s",
432            mr->ActionOnPurge, mr->Recycle,edit_uint64(mr->VolRetention, ed1),
433            edit_uint64(mr->VolUseDuration, ed2),
434            mr->MaxVolJobs, mr->MaxVolFiles,
435            edit_uint64(mr->MaxVolBytes, ed3),
436            edit_int64(mr->RecyclePoolId, ed4),
437            edit_int64(mr->PoolId, ed5));
438    }
439
440    Dmsg1(400, "%s\n", mdb->cmd);
441
442    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
443
444    db_unlock(mdb);
445    return stat;
446 }
447
448
449 /*
450  * If we have a non-zero InChanger, ensure that no other Media
451  *  record has InChanger set on the same Slot.
452  *
453  * This routine assumes the database is already locked.
454  */
455 void
456 db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
457 {
458    char ed1[50], ed2[50];
459    if (mr->InChanger != 0 && mr->Slot != 0 && mr->StorageId != 0) {
460
461        if (mr->MediaId != 0) {
462           Mmsg(mdb->cmd, "UPDATE Media SET InChanger=0, Slot=0 WHERE "
463                "Slot=%d AND StorageId=%s AND MediaId!=%s",
464                mr->Slot, 
465                edit_int64(mr->StorageId, ed1), edit_int64(mr->MediaId, ed2));
466
467        } else if (*mr->VolumeName) {
468           Mmsg(mdb->cmd, "UPDATE Media SET InChanger=0, Slot=0 WHERE "
469                "Slot=%d AND StorageId=%s AND VolumeName!='%s'",
470                mr->Slot, 
471                edit_int64(mr->StorageId, ed1), mr->VolumeName);
472
473        } else {  /* used by ua_label to reset all volume with this slot */
474           Mmsg(mdb->cmd, "UPDATE Media SET InChanger=0, Slot=0 WHERE "
475                "Slot=%d AND StorageId=%s",
476                mr->Slot, 
477                edit_int64(mr->StorageId, ed1), mr->VolumeName);          
478        }
479        Dmsg1(100, "%s\n", mdb->cmd);
480        UPDATE_DB(jcr, mdb, mdb->cmd);
481    }
482 }
483
484 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/