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