2 * Bacula Catalog Database Find record interface routines
4 * Note, generally, these routines are more complicated
5 * that a simple search by name or id. Such simple
8 * Bacula Catalog Database routines written specifically
9 * for Bacula. Note, these routines are VERY dumb and
10 * do not provide all the functionality of an SQL database.
11 * The purpose of these routines is to ensure that Bacula
12 * can limp along if no real database is loaded on the
15 * Kern Sibbald, January MMI
20 Copyright (C) 2001-2006 Kern Sibbald
22 This program is free software; you can redistribute it and/or
23 modify it under the terms of the GNU General Public License
24 version 2 as amended with additional clauses defined in the
25 file LICENSE in the main source directory.
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 the file LICENSE for additional details.
34 /* The following is necessary so that we do not include
35 * the dummy external definition of DB.
37 #define __SQL_C /* indicate that this is sql.c */
45 /* Forward referenced functions */
47 /* -----------------------------------------------------------------------
49 * Bacula specific defines and subroutines
51 * -----------------------------------------------------------------------
56 * Find job start time. Used to find last full save that terminated normally
57 * so we can do Incremental and Differential saves.
59 * Returns: 0 on failure
60 * 1 on success, jr unchanged, but stime set
62 bool db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime)
64 char cmd[MAXSTRING], Name[MAX_NAME_LENGTH], StartTime[MAXSTRING];
66 uint32_t JobId, EndId, ClientId;
67 char cType[10], cLevel[10], JobStatus[10];
72 pm_strcpy(stime, "0000-00-00 00:00:00"); /* default */
73 if (!bdb_open_jobs_file(mdb)) {
77 fseek(mdb->jobfd, 0L, SEEK_SET); /* rewind file */
78 /* Linear search through JobStart records
81 while (fgets(cmd, sizeof(cmd), mdb->jobfd)) {
82 if (sscanf(cmd, "JobStart JobId=%d Name=%127s Type=%1s Level=%1s "
83 "StartTime=%100s", &JobId, Name, cType, cLevel, StartTime) == 5) {
84 if (JobId < jr->JobId) {
85 continue; /* older not a candidate */
90 unbash_spaces(StartTime);
91 Dmsg4(200, "Got Type=%c Level=%c Name=%s StartTime=%s\n",
92 Type, Level, Name, StartTime);
93 Dmsg3(200, "Want Type=%c Level=%c Name=%s\n", jr->JobType, jr->JobLevel,
95 /* Differential is since last Full backup */
96 /* Incremental is since last FULL or Incremental or Differential */
97 if (((jr->JobLevel == L_DIFFERENTIAL) && (Type == jr->JobType &&
98 Level == L_FULL && strcmp(Name, jr->Name) == 0)) ||
99 ((jr->JobLevel == L_INCREMENTAL) && (Type == jr->JobType &&
100 (Level == L_FULL || Level == L_INCREMENTAL ||
101 Level == L_DIFFERENTIAL) && strcmp(Name, jr->Name) == 0))) {
102 addr = ftell(mdb->jobfd); /* save current location */
105 /* Search for matching JobEnd record */
106 while (!found && fgets(cmd, sizeof(cmd), mdb->jobfd)) {
107 if (sscanf(cmd, "JobEnd JobId=%d JobStatus=%1s ClientId=%d",
108 &EndId, JobStatus, &ClientId) == 3) {
109 if (EndId == JobId && *JobStatus == 'T' && ClientId == jr->ClientId) {
110 Dmsg0(200, "====found EndJob matching Job\n");
116 /* Reset for next read */
117 fseek(mdb->jobfd, addr, SEEK_SET);
119 pm_strcpy(stime, StartTime);
120 Dmsg5(200, "Got candidate JobId=%d Type=%c Level=%c Name=%s StartTime=%s\n",
121 JobId, Type, Level, Name, StartTime);
132 * Find Available Media (Volume) for Pool
134 * Find a Volume for a given PoolId, MediaType, and VolStatus
136 * Note! this does not correctly implement InChanger.
138 * Returns: 0 on failure
142 db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr)
150 if (!bdb_open_media_file(mdb)) {
154 fseek(mdb->mediafd, 0L, SEEK_SET); /* rewind file */
156 while (fread(&omr, len, 1, mdb->mediafd) > 0) {
157 if (mr->PoolId == omr.PoolId && strcmp(mr->VolStatus, omr.VolStatus) == 0 &&
158 strcmp(mr->MediaType, omr.MediaType) == 0) {
159 if (!(++index == item)) { /* looking for item'th entry */
160 Dmsg0(200, "Media record matches, but not index\n");
163 Dmsg0(200, "Media record matches\n");
164 memcpy(mr, &omr, len);
165 Dmsg1(200, "Findnextvol MediaId=%d\n", mr->MediaId);
167 break; /* found it */
175 db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
179 db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel)
183 #endif /* HAVE_BACULA_DB */