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 int 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];
79 pm_strcpy(stime, "0000-00-00 00:00:00"); /* default */
80 if (!bdb_open_jobs_file(mdb)) {
84 fseek(mdb->jobfd, 0L, SEEK_SET); /* rewind file */
85 /* Linear search through JobStart records
88 while (fgets(cmd, sizeof(cmd), mdb->jobfd)) {
89 if (sscanf(cmd, "JobStart JobId=%d Name=%127s Type=%1s Level=%1s \
90 StartTime=%100s", &JobId, Name, cType, cLevel, StartTime) == 5) {
91 if (JobId < jr->JobId) {
92 continue; /* older not a candidate */
97 unbash_spaces(StartTime);
98 Dmsg4(200, "Got Type=%c Level=%c Name=%s StartTime=%s\n",
99 Type, Level, Name, StartTime);
100 Dmsg3(200, "Want Type=%c Level=%c Name=%s\n", jr->Type, jr->Level,
102 /* Differential is since last Full backup */
103 /* Incremental is since last FULL or Incremental or Differential */
104 if (((jr->Level == L_DIFFERENTIAL) && (Type == jr->Type &&
105 Level == L_FULL && strcmp(Name, jr->Name) == 0)) ||
106 ((jr->Level == L_INCREMENTAL) && (Type == jr->Type &&
107 (Level == L_FULL || Level == L_INCREMENTAL ||
108 Level == L_DIFFERENTIAL) && strcmp(Name, jr->Name) == 0))) {
109 addr = ftell(mdb->jobfd); /* save current location */
112 /* Search for matching JobEnd record */
113 while (!found && fgets(cmd, sizeof(cmd), mdb->jobfd)) {
114 if (sscanf(cmd, "JobEnd JobId=%d JobStatus=%1s ClientId=%d",
115 &EndId, JobStatus, &ClientId) == 3) {
116 if (EndId == JobId && *JobStatus == 'T' && ClientId == jr->ClientId) {
117 Dmsg0(200, "====found EndJob matching Job\n");
123 /* Reset for next read */
124 fseek(mdb->jobfd, addr, SEEK_SET);
126 pm_strcpy(stime, StartTime);
127 stat = 1; /* Got a candidate */
128 Dmsg5(200, "Got candidate JobId=%d Type=%c Level=%c Name=%s StartTime=%s\n",
129 JobId, Type, Level, Name, StartTime);
140 * Find Available Media (Volume) for Pool
142 * Find a Volume for a given PoolId, MediaType, and VolStatus
144 * Note! this does not correctly implement InChanger.
146 * Returns: 0 on failure
150 db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr)
158 if (!bdb_open_media_file(mdb)) {
162 fseek(mdb->mediafd, 0L, SEEK_SET); /* rewind file */
164 while (fread(&omr, len, 1, mdb->mediafd) > 0) {
165 if (mr->PoolId == omr.PoolId && strcmp(mr->VolStatus, omr.VolStatus) == 0 &&
166 strcmp(mr->MediaType, omr.MediaType) == 0) {
167 if (!(++index == item)) { /* looking for item'th entry */
168 Dmsg0(200, "Media record matches, but not index\n");
171 Dmsg0(200, "Media record matches\n");
172 memcpy(mr, &omr, len);
173 Dmsg1(200, "Findnextvol MediaId=%d\n", mr->MediaId);
175 break; /* found it */
183 db_find_last_jobid(JCR *jcr, B_DB *mdb, char *Name, JOB_DBR *jr)
187 #endif /* HAVE_BACULA_DB */