]> git.sur5r.net Git - bacula/bacula/commitdiff
First cut at fixing AllowDuplicateJobs bugs
authorKern Sibbald <kern@sibbald.com>
Fri, 12 Feb 2010 15:12:19 +0000 (16:12 +0100)
committerEric Bollengier <eric@eb.homelinux.org>
Mon, 2 Aug 2010 14:49:29 +0000 (16:49 +0200)
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/job.c

index 18954b8479f772980b8908cdeef4089e753947c5..d58aeaaf1c960ba682b5a974ad9d9bcd4cfb9438 100644 (file)
@@ -336,6 +336,7 @@ RES_ITEM job_items[] = {
    {"accurate",           store_bool, ITEM(res_job.accurate), 0,0,0},
    {"allowduplicatejobs", store_bool, ITEM(res_job.AllowDuplicateJobs), 0, ITEM_DEFAULT, false},
    {"allowhigherduplicates",   store_bool, ITEM(res_job.AllowHigherDuplicates), 0, ITEM_DEFAULT, true},
+   {"cancellowerlevelduplicates", store_bool, ITEM(res_job.CancelLowerLevelDuplicates), 0, ITEM_DEFAULT, false},
    {"cancelqueuedduplicates",  store_bool, ITEM(res_job.CancelQueuedDuplicates), 0, ITEM_DEFAULT, false},
    {"cancelrunningduplicates", store_bool, ITEM(res_job.CancelRunningDuplicates), 0, ITEM_DEFAULT, false},
    {"pluginoptions", store_str, ITEM(res_job.PluginOptions), 0, 0, 0},
index f57fe5fbd8e2d233f6e9b1e158ab91ad95b9f0ba..60993d41e1b7c1dac73f467fbf26ebb91bca2f5c 100644 (file)
@@ -434,6 +434,7 @@ public:
    bool accurate;                     /* Set if it is an accurate backup job */
    bool AllowDuplicateJobs;           /* Allow duplicate jobs */
    bool AllowHigherDuplicates;        /* Permit Higher Level */
+   bool CancelLowerLevelDuplicates;   /* Cancel lower level backup jobs */
    bool CancelQueuedDuplicates;       /* Cancel queued jobs */
    bool CancelRunningDuplicates;      /* Cancel Running jobs */
    alist *base;                       /* Base jobs */   
index 331cfd10c71391f462e98886bb31fbda23132875..3949cf33177f0e3b3d5966036088b7a8aa6989e5 100644 (file)
@@ -678,58 +678,97 @@ DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
 bool allow_duplicate_job(JCR *jcr)
 {
    JOB *job = jcr->job;
-   JCR *djcr;                /* possible duplicate */
+   JCR *djcr;                /* possible duplicate job */
 
    if (job->AllowDuplicateJobs) {
       return true;
    }
-   if (!job->AllowHigherDuplicates) {
-      foreach_jcr(djcr) {
-         if (jcr == djcr || djcr->JobId == 0) {
-            continue;                   /* do not cancel this job or consoles */
+   /*
+    * After this point, we do not want to allow any duplicate
+    * job to run.
+    */
+
+   foreach_jcr(djcr) {
+      if (jcr == djcr || djcr->JobId == 0) {
+         continue;                   /* do not cancel this job or consoles */
+      }
+      if (strcmp(job->name(), djcr->job->name()) == 0) {
+         bool cancel_dup = false;
+         bool cancel_me = true;
+         if (job->DuplicateJobProximity > 0) {
+            utime_t now = (utime_t)time(NULL);
+            if ((now - djcr->start_time) > job->DuplicateJobProximity) {
+               continue;               /* not really a duplicate */
+            }
          }
-         if (strcmp(job->name(), djcr->job->name()) == 0) {
-            bool cancel_queued = false;
-            if (job->DuplicateJobProximity > 0) {
-               utime_t now = (utime_t)time(NULL);
-               if ((now - djcr->start_time) > job->DuplicateJobProximity) {
-                  continue;               /* not really a duplicate */
+         if (job->CancelLowerLevelDuplicates &&                         
+             djcr->getJobType() == 'B' && jcr->getJobType() == 'B') {
+            switch (jcr->getJobLevel()) {
+            case L_FULL:
+               if (djcr->getJobLevel() == L_DIFFERENTIAL ||
+                   djcr->getJobLevel() == L_INCREMENTAL) {
+                  cancel_dup = true;
+               }
+               break;
+            case L_DIFFERENTIAL:
+               if (djcr->getJobLevel() == L_INCREMENTAL) {
+                  cancel_dup = true;
+               }
+               if (djcr->getJobLevel() == L_FULL) {
+                  cancel_me = true;
+               }
+               break;
+            case L_INCREMENTAL:
+               if (djcr->getJobLevel() == L_FULL ||
+                   djcr->getJobLevel() == L_DIFFERENTIAL) {
+                  cancel_me = true;
                }
             }
-            /* Cancel */
-            /* 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=%d.\n"), djcr->JobId);
-               ua->jcr = djcr;
-               cancel_job(ua, djcr);
-               free_ua_context(ua);
-               Dmsg2(800, "Have cancelled JCR %p JobId=%d\n", djcr, djcr->JobId);
-            } else {
-               /* Zap current job */
-               Jmsg(jcr, M_FATAL, 0, _("JobId %d already running. Duplicate job not allowed.\n"),
-                  djcr->JobId);
+            /*
+             * cancel_dup will be done below   
+             */
+            if (cancel_me) {
+              /* Zap current job */
+              Jmsg(jcr, M_FATAL, 0, _("JobId %d already running. Duplicate job not allowed.\n"),
+                 djcr->JobId);
+              break;     /* get out of foreach_jcr */
             }
-            break;                 /* did our work, get out */
+         }   
+         /* Cancel one of the two jobs (me or dup) */
+         /* 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_dup = true;  /* cancel queued duplicate */
+                break;
+             default:
+                break;
+             }
          }
+         if (cancel_dup || job->CancelRunningDuplicates) {
+            /* Zap the duplicated job djcr */
+            UAContext *ua = new_ua_context(djcr);
+            Jmsg(jcr, M_INFO, 0, _("Cancelling duplicate JobId=%d.\n"), djcr->JobId);
+            ua->jcr = djcr;
+            cancel_job(ua, djcr);
+            free_ua_context(ua);
+            Dmsg2(800, "Have cancelled JCR %p JobId=%d\n", djcr, djcr->JobId);
+         } else {
+            /* Zap current job */
+            Jmsg(jcr, M_FATAL, 0, _("JobId %d already running. Duplicate job not allowed.\n"),
+               djcr->JobId);
+         }
+         break;                 /* did our work, get out of foreach loop */
       }
-      endeach_jcr(djcr);
    }
+   endeach_jcr(djcr);
+
    return true;   
 }