From: Eric Bollengier Date: Thu, 1 May 2008 14:27:28 +0000 (+0000) Subject: ebl Add MaxRunSchedTime option that specifies the maximum allowed time X-Git-Tag: Release-3.0.0~1520 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=f212ff802e006dc09cbd78e3e731fe593b18f3fa;p=bacula%2Fbacula ebl Add MaxRunSchedTime option that specifies the maximum allowed time that a job may run, counted from when the job was scheduled. ebl Fix MaxWaitTime option that specifies the maximum allowed time that a job may block waiting for a resource, counted from the when the job starts ebl Rename (add) Max(Incr|Diff|Full)WaitTime to Max(Incr|Diff|Full)RunTime git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6863 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index f95f25f175..e0cbb58898 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -289,10 +289,15 @@ RES_ITEM job_items[] = { {"writebootstrap",store_dir, ITEM(res_job.WriteBootstrap), 0, 0, 0}, {"writeverifylist",store_dir, ITEM(res_job.WriteVerifyList), 0, 0, 0}, {"replace", store_replace, ITEM(res_job.replace), 0, ITEM_DEFAULT, REPLACE_ALWAYS}, + {"maxrunschedtime", store_time, ITEM(res_job.MaxRunSchedTime), 0, 0, 0}, {"maxruntime", store_time, ITEM(res_job.MaxRunTime), 0, 0, 0}, - {"fullmaxwaittime", store_time, ITEM(res_job.FullMaxWaitTime), 0, 0, 0}, - {"incrementalmaxwaittime", store_time, ITEM(res_job.IncMaxWaitTime), 0, 0, 0}, - {"differentialmaxwaittime", store_time, ITEM(res_job.DiffMaxWaitTime), 0, 0, 0}, + /* xxxMaxWaitTime are deprecated */ + {"fullmaxwaittime", store_time, ITEM(res_job.FullMaxRunTime), 0, 0, 0}, + {"incrementalmaxwaittime", store_time, ITEM(res_job.IncMaxRunTime), 0, 0, 0}, + {"differentialmaxwaittime", store_time, ITEM(res_job.DiffMaxRunTime), 0, 0, 0}, + {"fullmaxruntime", store_time, ITEM(res_job.FullMaxRunTime), 0, 0, 0}, + {"incrementalmaxruntime", store_time, ITEM(res_job.IncMaxRunTime), 0, 0, 0}, + {"differentialmaxruntime", store_time, ITEM(res_job.DiffMaxRunTime), 0, 0, 0}, {"maxwaittime", store_time, ITEM(res_job.MaxWaitTime), 0, 0, 0}, {"maxstartdelay",store_time, ITEM(res_job.MaxStartDelay), 0, 0, 0}, {"maxfullinterval", store_time, ITEM(res_job.MaxFullInterval), 0, 0, 0}, @@ -666,6 +671,15 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm if (res->res_job.PluginOptions) { sendit(sock, _(" --> PluginOptions=%s\n"), NPRT(res->res_job.PluginOptions)); } + if (res->res_job.MaxRunTime) { + sendit(sock, _(" --> MaxRunTime=%u\n"), res->res_job.MaxRunTime); + } + if (res->res_job.MaxWaitTime) { + sendit(sock, _(" --> MaxWaitTime=%u\n"), res->res_job.MaxWaitTime); + } + if (res->res_job.MaxStartDelay) { + sendit(sock, _(" --> MaxStartDelay=%u\n"), res->res_job.MaxStartDelay); + } if (res->res_job.storage) { STORE *store; foreach_alist(store, res->res_job.storage) { diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index f13205096d..57bc4bc432 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -384,10 +384,11 @@ public: }; utime_t MaxRunTime; /* max run time in seconds */ utime_t MaxWaitTime; /* max blocking time in seconds */ - utime_t FullMaxWaitTime; /* Max Full job wait time */ - utime_t DiffMaxWaitTime; /* Max Differential job wait time */ - utime_t IncMaxWaitTime; /* Max Incremental job wait time */ + utime_t FullMaxRunTime; /* Max Full job run time */ + utime_t DiffMaxRunTime; /* Max Differential job run time */ + utime_t IncMaxRunTime; /* Max Incremental job run time */ utime_t MaxStartDelay; /* max start delay in seconds */ + utime_t MaxRunSchedTime; /* max run time in seconds from Scheduled time*/ utime_t RescheduleInterval; /* Reschedule interval */ utime_t JobRetention; /* job retention period in seconds */ utime_t MaxFullInterval; /* Maximum time interval between Fulls */ diff --git a/bacula/src/dird/getmsg.c b/bacula/src/dird/getmsg.c index dae8f098fd..59a1ecd2de 100644 --- a/bacula/src/dird/getmsg.c +++ b/bacula/src/dird/getmsg.c @@ -70,6 +70,33 @@ static char Device_update[] = "DevUpd Job=%127s " static char OK_msg[] = "1000 OK\n"; + +void set_jcr_sd_job_status(JCR *jcr, int SDJobStatus) +{ + bool set_waittime=false; + Dmsg2(800, "set_jcr_sd_job_status(%s, %c)\n", jcr->Job, SDJobStatus); + /* if wait state is new, we keep current time for watchdog MaxWaitTime */ + switch (SDJobStatus) { + case JS_WaitMedia: + case JS_WaitMount: + case JS_WaitMaxJobs: + set_waittime = true; + default: + break; + } + + if (job_waiting(jcr)) { + set_waittime = false; + } + + if (set_waittime) { + /* set it before JobStatus */ + Dmsg0(800, "Setting wait_time\n"); + jcr->wait_time = time(NULL); + } + jcr->SDJobStatus = SDJobStatus; +} + /* * Get a message * Call appropriate processing routine @@ -230,7 +257,7 @@ int bget_dirmsg(BSOCK *bs) int JobStatus; char Job[MAX_NAME_LENGTH]; if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) { - jcr->SDJobStatus = JobStatus; /* current status */ + set_jcr_sd_job_status(jcr,JobStatus); /* current status */ } else { Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); } diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 4523a31c48..56b15930b9 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -41,8 +41,9 @@ static void *job_thread(void *arg); static void job_monitor_watchdog(watchdog_t *self); static void job_monitor_destructor(watchdog_t *self); -static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr); -static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr); +static bool job_check_maxwaittime(JCR *jcr); +static bool job_check_maxruntime(JCR *jcr); +static bool job_check_maxschedruntime(JCR *jcr); /* Imported subroutines */ extern void term_scheduler(); @@ -253,6 +254,11 @@ static void *job_thread(void *arg) Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n")); } + if (job_check_maxschedruntime(jcr)) { + set_jcr_job_status(jcr, JS_Canceled); + Jmsg(jcr, M_FATAL, 0, _("Job canceled because max sched run time exceeded.\n")); + } + /* TODO : check if it is used somewhere */ if (jcr->job->RunScripts == NULL) { Dmsg0(200, "Warning, job->RunScripts is empty\n"); @@ -493,15 +499,20 @@ static void job_monitor_watchdog(watchdog_t *self) } /* check MaxWaitTime */ - if (job_check_maxwaittime(control_jcr, jcr)) { + if (job_check_maxwaittime(jcr)) { set_jcr_job_status(jcr, JS_Canceled); Jmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n")); cancel = true; /* check MaxRunTime */ - } else if (job_check_maxruntime(control_jcr, jcr)) { + } else if (job_check_maxruntime(jcr)) { set_jcr_job_status(jcr, JS_Canceled); Jmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n")); cancel = true; + /* check MaxRunSchedTime */ + } else if (job_check_maxschedruntime(jcr)) { + set_jcr_job_status(jcr, JS_Canceled); + Jmsg(jcr, M_FATAL, 0, _("Max sched run time exceeded. Job canceled.\n")); + cancel = true; } if (cancel) { @@ -522,47 +533,71 @@ static void job_monitor_watchdog(watchdog_t *self) * Check if the maxwaittime has expired and it is possible * to cancel the job. */ -static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr) +static bool job_check_maxwaittime(JCR *jcr) { bool cancel = false; JOB *job = jcr->job; - if (job_canceled(jcr)) { - return false; /* already canceled */ + if (!job_waiting(jcr)) { + return false; } - if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 && - job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) { + Dmsg3(200, "check maxwaittime %u - %u >= %u\n", watchdog_time, jcr->wait_time, job->MaxWaitTime); + if (job->MaxWaitTime != 0 && + (watchdog_time - jcr->wait_time) >= job->MaxWaitTime) { + cancel = true; + } + + return cancel; +} + +/* + * Check if maxruntime has expired and if the job can be + * canceled. + */ +static bool job_check_maxruntime(JCR *jcr) +{ + bool cancel = false; + JOB *job = jcr->job; + + if (job_canceled(jcr) || jcr->JobStatus == JS_Created) { return false; - } - if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 && - (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) { + } + if (jcr->job->MaxRunTime == 0 && job->FullMaxRunTime == 0 && + job->IncMaxRunTime == 0 && job->DiffMaxRunTime == 0) { + return false; + } + Dmsg6(200, "check_maxruntime %u - %u >= %u|%u|%u|%u\n\n", + watchdog_time, jcr->start_time, job->MaxRunTime, job->FullMaxRunTime, + job->IncMaxRunTime, job->DiffMaxRunTime); + + if (jcr->JobLevel == L_FULL && job->FullMaxRunTime != 0 && + (watchdog_time - jcr->start_time) >= job->FullMaxRunTime) { cancel = true; - } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 && - (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) { + } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxRunTime != 0 && + (watchdog_time - jcr->start_time) >= job->DiffMaxRunTime) { cancel = true; - } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 && - (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) { + } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxRunTime != 0 && + (watchdog_time - jcr->start_time) >= job->IncMaxRunTime) { cancel = true; - } else if (job->MaxWaitTime != 0 && - (watchdog_time - jcr->start_time) >= job->MaxWaitTime) { + } else if ((watchdog_time - jcr->start_time) >= job->MaxRunTime) { cancel = true; } - + return cancel; } /* - * Check if maxruntime has expired and if the job can be + * Check if MaxRunSchedTime has expired and if the job can be * canceled. */ -static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr) +static bool job_check_maxschedruntime(JCR *jcr) { - if (jcr->job->MaxRunTime == 0 || job_canceled(jcr) || jcr->JobStatus == JS_Created) { + if (jcr->job->MaxRunSchedTime == 0 || job_canceled(jcr)) { return false; } - if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) { - Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n", - jcr, jcr->Job, jcr->job->MaxRunTime); + if ((watchdog_time - jcr->sched_time) < jcr->job->MaxRunSchedTime) { + Dmsg3(200, "Job %p (%s) with MaxRunSchedTime %d not expired\n", + jcr, jcr->Job, jcr->job->MaxRunSchedTime); return false; } diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 4a3c043133..5adfc4af05 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -109,6 +109,22 @@ enum { jcr->JobStatus == JS_ErrorTerminated || \ jcr->JobStatus == JS_FatalError) +#define job_waiting(jcr) \ + (jcr->JobStatus == JS_WaitFD || \ + jcr->JobStatus == JS_WaitSD || \ + jcr->JobStatus == JS_WaitMedia || \ + jcr->JobStatus == JS_WaitMount || \ + jcr->JobStatus == JS_WaitStoreRes || \ + jcr->JobStatus == JS_WaitJobRes || \ + jcr->JobStatus == JS_WaitClientRes|| \ + jcr->JobStatus == JS_WaitMaxJobs || \ + jcr->JobStatus == JS_WaitPriority || \ + jcr->SDJobStatus == JS_WaitMedia || \ + jcr->SDJobStatus == JS_WaitMount || \ + jcr->SDJobStatus == JS_WaitMaxJobs) + + + #define foreach_jcr(jcr) \ for (jcr=jcr_walk_start(); jcr; (jcr=jcr_walk_next(jcr)) ) @@ -189,6 +205,7 @@ public: time_t start_time; /* when job actually started */ time_t run_time; /* used for computing speed */ time_t end_time; /* job end time */ + time_t wait_time; /* when job have started to wait */ POOLMEM *client_name; /* client name */ POOLMEM *RestoreBootstrap; /* Bootstrap file to restore */ POOLMEM *stime; /* start time for incremental/differential */ diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index 80e404d7a0..276a29ea68 100644 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -632,6 +632,24 @@ JCR *get_jcr_by_full_name(char *Job) void set_jcr_job_status(JCR *jcr, int JobStatus) { + bool set_waittime=false; + Dmsg2(800, "set_jcr_job_status(%s, %c)\n", jcr->Job, JobStatus); + /* if wait state is new, we keep current time for watchdog MaxWaitTime */ + switch (JobStatus) { + case JS_WaitFD: + case JS_WaitSD: + case JS_WaitMedia: + case JS_WaitMount: + case JS_WaitStoreRes: + case JS_WaitJobRes: + case JS_WaitClientRes: + case JS_WaitMaxJobs: + case JS_WaitPriority: + set_waittime = true; + default: + break; + } + /* * For a set of errors, ... keep the current status * so it isn't lost. For all others, set it. @@ -652,10 +670,29 @@ void set_jcr_job_status(JCR *jcr, int JobStatus) /* Override more minor status */ jcr->JobStatus = JobStatus; break; + default: + break; } - break; + /* + * For a set of Wait situation, keep old time. + */ + case JS_WaitFD: + case JS_WaitSD: + case JS_WaitMedia: + case JS_WaitMount: + case JS_WaitStoreRes: + case JS_WaitJobRes: + case JS_WaitClientRes: + case JS_WaitMaxJobs: + case JS_WaitPriority: + set_waittime = false; /* keep old time */ default: jcr->JobStatus = JobStatus; + if (set_waittime) { + /* set it before JobStatus */ + Dmsg0(800, "Setting wait_time\n"); + jcr->wait_time = time(NULL); + } } Dmsg3(100, "jid=%u OnExit JobStatus=%c set=%c\n", (uint32_t)jcr->JobId, jcr->JobStatus, JobStatus); diff --git a/bacula/technotes-2.3 b/bacula/technotes-2.3 index 2d695e4780..65458204e8 100644 --- a/bacula/technotes-2.3 +++ b/bacula/technotes-2.3 @@ -25,6 +25,11 @@ Add long term statistics job table General: 01May08 +ebl Add MaxRunSchedTime option that specifies the maximum allowed time + that a job may run, counted from when the job was scheduled. +ebl Fix MaxWaitTime option that specifies the maximum allowed time that + a job may block waiting for a resource, counted from when the job starts +ebl Rename (add) Max(Incr|Diff|Full)WaitTime to Max(Incr|Diff|Full)RunTime kes Apply patch from bug #1076 by Tullio Andreatta that implements multiple commands per line in the console when using readline. Modify the default to use a semicolon as the command separator.