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 Bacula® - The Network Backup Solution
22 Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
24 The main author of Bacula is Kern Sibbald, with contributions from
25 many others, a complete list can be found in the file AUTHORS.
26 This program is Free Software; you can redistribute it and/or
27 modify it under the terms of version two of the GNU General Public
28 License as published by the Free Software Foundation and included
31 This program is distributed in the hope that it will be useful, but
32 WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 General Public License for more details.
36 You should have received a copy of the GNU General Public License
37 along with this program; if not, write to the Free Software
38 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
41 Bacula® is a registered trademark of John Walker.
42 The licensor of Bacula is the Free Software Foundation Europe
43 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
44 Switzerland, email:ftf@fsfeurope.org.
47 /* The following is necessary so that we do not include
48 * the dummy external definition of DB.
50 #define __SQL_C /* indicate that this is sql.c */
58 /* Forward referenced functions */
60 /* -----------------------------------------------------------------------
62 * Bacula specific defines and subroutines
64 * -----------------------------------------------------------------------
69 * Find job start time. Used to find last full save that terminated normally
70 * so we can do Incremental and Differential saves.
72 * Returns: 0 on failure
73 * 1 on success, jr unchanged, but stime set
75 bool db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime)
77 char cmd[MAXSTRING], Name[MAX_NAME_LENGTH], StartTime[MAXSTRING];
79 uint32_t JobId, EndId, ClientId;
80 char cType[10], cLevel[10], JobStatus[10];
85 pm_strcpy(stime, "0000-00-00 00:00:00"); /* default */
86 if (!bdb_open_jobs_file(mdb)) {
90 fseek(mdb->jobfd, 0L, SEEK_SET); /* rewind file */
91 /* Linear search through JobStart records
94 while (fgets(cmd, sizeof(cmd), mdb->jobfd)) {
95 if (sscanf(cmd, "JobStart JobId=%d Name=%127s Type=%1s Level=%1s "
96 "StartTime=%100s", &JobId, Name, cType, cLevel, StartTime) == 5) {
97 if (JobId < jr->JobId) {
98 continue; /* older not a candidate */
103 unbash_spaces(StartTime);
104 Dmsg4(200, "Got Type=%c Level=%c Name=%s StartTime=%s\n",
105 Type, Level, Name, StartTime);
106 Dmsg3(200, "Want Type=%c Level=%c Name=%s\n", jr->JobType, jr->JobLevel,
108 /* Differential is since last Full backup */
109 /* Incremental is since last FULL or Incremental or Differential */
110 if (((jr->JobLevel == L_DIFFERENTIAL) && (Type == jr->JobType &&
111 Level == L_FULL && strcmp(Name, jr->Name) == 0)) ||
112 ((jr->JobLevel == L_INCREMENTAL) && (Type == jr->JobType &&
113 (Level == L_FULL || Level == L_INCREMENTAL ||
114 Level == L_DIFFERENTIAL) && strcmp(Name, jr->Name) == 0))) {
115 addr = ftell(mdb->jobfd); /* save current location */
118 /* Search for matching JobEnd record */
119 while (!found && fgets(cmd, sizeof(cmd), mdb->jobfd)) {
120 if (sscanf(cmd, "JobEnd JobId=%d JobStatus=%1s ClientId=%d",
121 &EndId, JobStatus, &ClientId) == 3) {
122 if (EndId == JobId && *JobStatus == 'T' && ClientId == jr->ClientId) {
123 Dmsg0(200, "====found EndJob matching Job\n");
129 /* Reset for next read */
130 fseek(mdb->jobfd, addr, SEEK_SET);
132 pm_strcpy(stime, StartTime);
133 Dmsg5(200, "Got candidate JobId=%d Type=%c Level=%c Name=%s StartTime=%s\n",
134 JobId, Type, Level, Name, StartTime);
145 * Find Available Media (Volume) for Pool
147 * Find a Volume for a given PoolId, MediaType, and VolStatus
149 * Note! this does not correctly implement InChanger.
151 * Returns: 0 on failure
155 db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr)
163 if (!bdb_open_media_file(mdb)) {
167 fseek(mdb->mediafd, 0L, SEEK_SET); /* rewind file */
169 while (fread(&omr, len, 1, mdb->mediafd) > 0) {
170 if (mr->PoolId == omr.PoolId && strcmp(mr->VolStatus, omr.VolStatus) == 0 &&
171 strcmp(mr->MediaType, omr.MediaType) == 0) {
172 if (!(++index == item)) { /* looking for item'th entry */
173 Dmsg0(200, "Media record matches, but not index\n");
176 Dmsg0(200, "Media record matches\n");
177 memcpy(mr, &omr, len);
178 Dmsg1(200, "Findnextvol MediaId=%d\n", mr->MediaId);
180 break; /* found it */
188 db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
192 db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel)
196 #endif /* HAVE_BACULA_DB */