+/*
+ * Check for duplicate jobs.
+ * Returns: true if current job should continue
+ * false if current job should terminate
+ */
+bool allow_duplicate_job(JCR *jcr)
+{
+ JOB *job = jcr->job;
+ JCR *djcr; /* possible duplicate */
+
+ if (job->AllowDuplicateJobs) {
+ return true;
+ }
+ if (!job->AllowHigherDuplicates) {
+ foreach_jcr(djcr) {
+ char ec1[50];
+ if (strcmp(job->name(), djcr->job->name()) == 0) {
+ bool cancel_queued = false;
+ if (job->DuplicateJobProximity > 0) {
+ time_t now = time(NULL);
+ if ((now - djcr->start_time) > job->DuplicateJobProximity) {
+ continue; /* not really a duplicate */
+ }
+ }
+ /* Cancel */
+ if (!(job->CancelQueuedDuplicates || job->CancelRunningDuplicates)) {
+ /* Zap current job */
+ Jmsg(jcr, M_FATAL, 0, _("Duplicate job not allowed. JobId=%s\n"),
+ edit_uint64(djcr->JobId, ec1));
+ return false;
+ }
+ /* If CancelQueuedDuplicates is set do so only if job is queued */
+ if (job->CancelQueuedDuplicates) {
+ switch (djcr->JobStatus) {
+ case JS_Created:
+ case JS_WaitJobRes:
+ case JS_WaitClientRes:
+ case JS_WaitStoreRes:
+ case JS_WaitPriority:
+ case JS_WaitMaxJobs:
+ case JS_WaitStartTime:
+ cancel_queued = true;
+ break;
+ default:
+ break;
+ }
+ }
+ if (cancel_queued || job->CancelRunningDuplicates) {
+ UAContext *ua = new_ua_context(djcr);
+ Jmsg(jcr, M_INFO, 0, _("Cancelling duplicate JobId=%s.\n"),
+ edit_uint64(djcr->JobId, ec1));
+ ua->jcr = djcr;
+ cancel_job(ua, djcr);
+ free_ua_context(ua);
+ Dmsg2(800, "Have cancelled JCR %p Job=%d\n", djcr, djcr->JobId);
+ }
+ }
+ }
+ }
+ return true;
+}
+