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