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
21 Copyright (C) 2001-2003 Kern Sibbald and John Walker
23 This program is free software; you can redistribute it and/or
24 modify it under the terms of the GNU General Public License as
25 published by the Free Software Foundation; either version 2 of
26 the License, or (at your option) any later version.
28 This program is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 General Public License for more details.
33 You should have received a copy of the GNU General Public
34 License along with this program; if not, write to the Free
35 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
40 /* The following is necessary so that we do not include
41 * the dummy external definition of DB.
43 #define __SQL_C /* indicate that this is sql.c */
51 /* Forward referenced functions */
53 /* -----------------------------------------------------------------------
55 * Bacula specific defines and subroutines
57 * -----------------------------------------------------------------------
62 * Find job start time. Used to find last full save that terminated normally
63 * so we can do Incremental and Differential saves.
65 * Returns: 0 on failure
66 * 1 on success, jr unchanged, but stime set
68 bool db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime)
70 char cmd[MAXSTRING], Name[MAX_NAME_LENGTH], StartTime[MAXSTRING];
72 uint32_t JobId, EndId, ClientId;
73 char cType[10], cLevel[10], JobStatus[10];
78 pm_strcpy(stime, "0000-00-00 00:00:00"); /* default */
79 if (!bdb_open_jobs_file(mdb)) {
83 fseek(mdb->jobfd, 0L, SEEK_SET); /* rewind file */
84 /* Linear search through JobStart records
87 while (fgets(cmd, sizeof(cmd), mdb->jobfd)) {
88 if (sscanf(cmd, "JobStart JobId=%d Name=%127s Type=%1s Level=%1s "
89 "StartTime=%100s", &JobId, Name, cType, cLevel, StartTime) == 5) {
90 if (JobId < jr->JobId) {
91 continue; /* older not a candidate */
96 unbash_spaces(StartTime);
97 Dmsg4(200, "Got Type=%c Level=%c Name=%s StartTime=%s\n",
98 Type, Level, Name, StartTime);
99 Dmsg3(200, "Want Type=%c Level=%c Name=%s\n", jr->JobType, jr->JobLevel,
101 /* Differential is since last Full backup */
102 /* Incremental is since last FULL or Incremental or Differential */
103 if (((jr->JobLevel == L_DIFFERENTIAL) && (Type == jr->JobType &&
104 Level == L_FULL && strcmp(Name, jr->Name) == 0)) ||
105 ((jr->JobLevel == L_INCREMENTAL) && (Type == jr->JobType &&
106 (Level == L_FULL || Level == L_INCREMENTAL ||
107 Level == L_DIFFERENTIAL) && strcmp(Name, jr->Name) == 0))) {
108 addr = ftell(mdb->jobfd); /* save current location */
111 /* Search for matching JobEnd record */
112 while (!found && fgets(cmd, sizeof(cmd), mdb->jobfd)) {
113 if (sscanf(cmd, "JobEnd JobId=%d JobStatus=%1s ClientId=%d",
114 &EndId, JobStatus, &ClientId) == 3) {
115 if (EndId == JobId && *JobStatus == 'T' && ClientId == jr->ClientId) {
116 Dmsg0(200, "====found EndJob matching Job\n");
122 /* Reset for next read */
123 fseek(mdb->jobfd, addr, SEEK_SET);
125 pm_strcpy(stime, StartTime);
126 Dmsg5(200, "Got candidate JobId=%d Type=%c Level=%c Name=%s StartTime=%s\n",
127 JobId, Type, Level, Name, StartTime);
138 * Find Available Media (Volume) for Pool
140 * Find a Volume for a given PoolId, MediaType, and VolStatus
142 * Note! this does not correctly implement InChanger.
144 * Returns: 0 on failure
148 db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr)
156 if (!bdb_open_media_file(mdb)) {
160 fseek(mdb->mediafd, 0L, SEEK_SET); /* rewind file */
162 while (fread(&omr, len, 1, mdb->mediafd) > 0) {
163 if (mr->PoolId == omr.PoolId && strcmp(mr->VolStatus, omr.VolStatus) == 0 &&
164 strcmp(mr->MediaType, omr.MediaType) == 0) {
165 if (!(++index == item)) { /* looking for item'th entry */
166 Dmsg0(200, "Media record matches, but not index\n");
169 Dmsg0(200, "Media record matches\n");
170 memcpy(mr, &omr, len);
171 Dmsg1(200, "Findnextvol MediaId=%d\n", mr->MediaId);
173 break; /* found it */
181 db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
185 db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel)
189 #endif /* HAVE_BACULA_DB */