2 * Bacula Catalog Database Update record interface routines
4 * Kern Sibbald, March 2000
9 Copyright (C) 2000-2006 Kern Sibbald
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.
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.
23 /* The following is necessary so that we do not include
24 * the dummy external definition of DB.
26 #define __SQL_C /* indicate that this is sql.c */
31 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
33 /* -----------------------------------------------------------------------
35 * Generic Routines (or almost generic)
37 * -----------------------------------------------------------------------
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);
44 /* -----------------------------------------------------------------------
46 * Generic Routines (or almost generic)
48 * -----------------------------------------------------------------------
50 /* Update the attributes record by adding the file digest */
52 db_add_digest_to_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, char *digest,
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);
66 /* Mark the file record as being visited during database
67 * verify compare. Stuff JobId into the MarkId field
69 int db_mark_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, JobId_t JobId)
72 char ed1[50], ed2[50];
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);
83 * Update the Job record at start of Job
85 * Returns: false on failure
89 db_update_job_start_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
91 char dt[MAX_TIME_LENGTH];
96 char ed1[50], ed2[50], ed3[50], ed4[50];
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;
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));
113 stat = UPDATE_DB(jcr, mdb, mdb->cmd);
120 * Given an incoming integer, set the string buffer to either NULL or the value
123 static void edit_num_or_null(char *s, size_t n, uint64_t id) {
125 bsnprintf(s, n, id ? "%s" : "NULL", edit_int64(id, ed1));
130 * Update the Job record at end of Job
132 * Returns: 0 on failure
136 db_update_job_end_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
138 char dt[MAX_TIME_LENGTH];
142 char ed1[30], ed2[30], ed3[50];
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);
155 localtime_r(&ttime, &tm);
156 strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
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));
169 stat = UPDATE_DB(jcr, mdb, mdb->cmd);
176 * Update Client record
177 * Returns: 0 on failure
181 db_update_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr)
184 char ed1[50], ed2[50];
188 memcpy(&tcr, cr, sizeof(tcr));
189 if (!db_create_client_record(jcr, mdb, &tcr)) {
195 "UPDATE Client SET AutoPrune=%d,FileRetention=%s,JobRetention=%s,"
196 "Uname='%s' WHERE Name='%s'",
198 edit_uint64(cr->FileRetention, ed1),
199 edit_uint64(cr->JobRetention, ed2),
200 cr->Uname, cr->Name);
202 stat = UPDATE_DB(jcr, mdb, mdb->cmd);
209 * Update Counters record
210 * Returns: 0 on failure
213 int db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
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);
223 int stat = UPDATE_DB(jcr, mdb, mdb->cmd);
230 db_update_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
233 char ed1[50], ed2[50], ed3[50], ed4[50];
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);
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,
255 stat = UPDATE_DB(jcr, mdb, mdb->cmd);
261 db_update_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr)
267 Mmsg(mdb->cmd, "UPDATE Storage SET AutoChanger=%d WHERE StorageId=%s",
268 sr->AutoChanger, edit_int64(sr->StorageId, ed1));
270 stat = UPDATE_DB(jcr, mdb, mdb->cmd);
277 * Update the Media Record at end of Session
279 * Returns: 0 on failure
283 db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
285 char dt[MAX_TIME_LENGTH];
289 char ed1[50], ed2[50], ed3[50], ed4[50];
290 char ed5[50], ed6[50], ed7[50], ed8[50];
293 Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
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 %H:%M:%S", &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);
306 /* Label just done? */
307 if (mr->set_label_date) {
308 ttime = mr->LabelDate;
312 localtime_r(&ttime, &tm);
313 strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
314 Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' "
315 "WHERE VolumeName='%s'", dt, mr->VolumeName);
316 UPDATE_DB(jcr, mdb, mdb->cmd);
319 if (mr->LastWritten != 0) {
320 ttime = mr->LastWritten;
321 localtime_r(&ttime, &tm);
322 strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
323 Mmsg(mdb->cmd, "UPDATE Media Set LastWritten='%s' "
324 "WHERE VolumeName='%s'", dt, mr->VolumeName);
325 UPDATE_DB(jcr, mdb, mdb->cmd);
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),
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,
350 Dmsg1(400, "%s\n", mdb->cmd);
352 stat = UPDATE_DB(jcr, mdb, mdb->cmd);
354 /* Make sure InChanger is 0 for any record having the same Slot */
355 db_make_inchanger_unique(jcr, mdb, mr);
362 * Update the Media Record Default values from Pool
364 * Returns: 0 on failure
368 db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
371 char ed1[50], ed2[50], ed3[50], ed4[50];
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),
386 Mmsg(mdb->cmd, "UPDATE Media SET "
387 "Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
388 "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%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));
397 Dmsg1(400, "%s\n", mdb->cmd);
399 stat = UPDATE_DB(jcr, mdb, mdb->cmd);
407 * If we have a non-zero InChanger, ensure that no other Media
408 * record has InChanger set on the same Slot.
410 * This routine assumes the database is already locked.
413 db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
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",
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);
429 db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
431 /* DUMMY func for Bacula_DB */
435 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/