4 * It looks at what jobs are to be run and when
5 * and waits around until it is time to
11 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of
16 the License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public
24 License along with this program; if not, write to the Free
25 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
34 /* Forward referenced subroutines */
35 static void find_runs();
37 /* Imported subroutines */
39 /* Imported variables */
48 static int num_runjobs; /* total jobs found by find_runs() */
49 static int rem_runjobs; /* jobs remaining to be processed */
50 static int max_runjobs; /* max jobs in runjobs array */
51 static RUNJOB *runjobs; /* array of jobs to be run */
54 /*********************************************************************
56 * Main Bacula Scheduler
59 JCR *wait_for_next_job(char *job_to_run)
64 time_t now, runtime, nexttime;
66 static int first = TRUE;
68 Dmsg0(200, "Enter wait_for_next_job\n");
72 runjobs = (RUNJOB *) malloc(sizeof(RUNJOB) * max_runjobs);
74 if (job_to_run) { /* one shot */
75 job = (JOB *)GetResWithName(R_JOB, job_to_run);
77 Emsg1(M_ERROR, 0, _("Job %s not found\n"), job_to_run);
79 Dmsg1(5, "Found job_to_run %s\n", job_to_run);
80 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
81 set_jcr_defaults(jcr, job);
86 /* Wait until we have something in the
89 while (num_runjobs == 0 || rem_runjobs == 0) {
94 * Sort through what is to be run in the next
95 * two hours to find the first job to be run,
96 * then wait around until it is time.
100 nexttime = now + 60 * 60 * 24; /* a much later time */
102 for (i=0; i<num_runjobs; i++) {
103 runtime = runjobs[i].runtime;
104 if (runtime > 0 && runtime < nexttime) { /* find minimum time job */
109 if (jobindex < 0) { /* we really should have something now */
110 Emsg0(M_ABORT, 0, _("Scheduler logic error\n"));
113 /* Now wait for the time to run the job */
117 twait = nexttime - now;
118 if (twait <= 0) /* time to run it */
120 if (twait > 20) /* sleep max 20 seconds */
124 run = runjobs[jobindex].run;
125 job = runjobs[jobindex].job;
126 runjobs[jobindex].runtime = 0; /* remove from list */
127 run->last_run = now; /* mark as run */
128 rem_runjobs--; /* decrement count of remaining jobs */
129 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
130 set_jcr_defaults(jcr, job);
131 jcr->level = run->level; /* override run level */
132 Dmsg0(200, "Leave wait_for_next_job()\n");
138 * Shutdown the scheduler
140 void term_scheduler()
142 if (runjobs) { /* free allocated memory */
151 * Find all jobs to be run this hour
154 static void find_runs()
161 int hour, next_hour, minute, mday, wday, month;
163 Dmsg0(200, "enter find_runs()\n");
167 localtime_r(&now, &tm);
170 next_hour = hour + 1;
174 mday = tm.tm_mday - 1;
178 /* Loop through all jobs */
180 for (job=NULL; (job=(JOB *)GetNextRes(R_JOB, (RES *)job)); ) {
181 sched = job->schedule;
182 if (sched == NULL) { /* scheduled? */
183 continue; /* no, skip this job */
185 for (run=sched->run; run; run=run->next) {
187 if (now - run->last_run < 60 * 20)
188 continue; /* wait at least 20 minutes */
190 /* Find runs scheduled in this our or in the
191 * next hour (we may be one second before the next hour).
193 if ((bit_is_set(hour, run->hour) || bit_is_set(next_hour, run->hour)) &&
194 (bit_is_set(mday, run->mday) || bit_is_set(wday, run->wday)) &&
195 bit_is_set(month, run->month)) {
197 /* find time (time_t) job is to be run */
198 localtime_r(&now, &tm);
199 if (bit_is_set(next_hour, run->hour))
203 tm.tm_min = run->minute;
205 runtime = mktime(&tm);
206 if (runtime < (now - 5 * 60)) /* give 5 min grace to pickup straglers */
208 /* Make sure array is big enough */
209 if (num_runjobs == max_runjobs) {
211 runjobs = (RUNJOB *) realloc(runjobs, sizeof(RUNJOB) * max_runjobs);
213 Emsg0(M_ABORT, 0, _("Out of memory\n"));
215 /* accept to run this job */
216 runjobs[num_runjobs].run = run;
217 runjobs[num_runjobs].job = job;
218 runjobs[num_runjobs++].runtime = runtime; /* when to run it */
225 rem_runjobs = num_runjobs;
226 Dmsg0(200, "Leave find_runs()\n");