]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/jobq.c
Implement MaxVirtualFullInterval
[bacula/bacula] / bacula / src / dird / jobq.c
index e9f9343711d217b563647b601b2d2520947a33db..95168218b45ac94c26f22b8ea03e06e80b31a820 100644 (file)
@@ -1,17 +1,20 @@
 /*
-   Bacula® - The Network Backup Solution
+   Bacula(R) - The Network Backup Solution
 
-   Copyright (C) 2003-2014 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2015 Kern Sibbald
 
-   The main author of Bacula is Kern Sibbald, with contributions from many
-   others, a complete list can be found in the file AUTHORS.
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
 
    You may use this file and others of this release according to the
    license defined in the LICENSE file, which includes the Affero General
    Public License, v3.0 ("AGPLv3") and some additional permissions and
    terms pursuant to its AGPLv3 Section 7.
 
-   Bacula® is a registered trademark of Kern Sibbald.
+   This notice must be preserved when any source code is 
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
 */
 /*
  * Bacula job queue routines.
@@ -188,6 +191,30 @@ void *sched_wait(void *arg)
    return NULL;
 }
 
+/* Procedure to update the Client->NumConcurrentJobs */
+static void update_client_numconcurrentjobs(JCR *jcr, int val)
+{
+   if (!jcr->client) {
+      return;
+   }
+
+   switch (jcr->getJobType())
+   {
+   case JT_MIGRATE:
+   case JT_COPY:
+   case JT_ADMIN:
+      break;
+   case JT_BACKUP:
+      if (jcr->no_client_used()) {
+         break;
+      }
+   /* Failback wanted */
+   default:
+      jcr->client->NumConcurrentJobs += val;
+      break;
+   }
+}
+
 /*
  *  Add a job to the queue
  *    jq is a queue that was created with jobq_init
@@ -442,9 +469,6 @@ void *jobq_server(void *arg)
          remove_jcr_from_tsd(je->jcr);
          je->jcr->set_killable(false);
 
-         /* Clear the threadid, probably not necessary */
-         memset(&jcr->my_thread_id, 0, sizeof(jcr->my_thread_id));
-
          Dmsg2(2300, "Back from user engine jobid=%d use=%d.\n", jcr->JobId,
             jcr->use_count());
 
@@ -460,7 +484,7 @@ void *jobq_server(void *arg)
          if (jcr->acquired_resource_locks) {
             dec_read_store(jcr);
             dec_write_store(jcr);
-            jcr->client->NumConcurrentJobs--;
+            update_client_numconcurrentjobs(jcr, -1);
             jcr->job->NumConcurrentJobs--;
             jcr->acquired_resource_locks = false;
          }
@@ -612,6 +636,10 @@ static bool reschedule_job(JCR *jcr, jobq_t *jq, jobq_item_t *je)
    if (jcr->job->RescheduleTimes == 0 ||
        jcr->reschedule_count < jcr->job->RescheduleTimes) {
       resched =
+         /* Check for incomplete jobs */
+         (jcr->RescheduleIncompleteJobs &&
+          jcr->is_incomplete() && jcr->is_JobType(JT_BACKUP) &&
+          !(jcr->HasBase||jcr->is_JobLevel(L_BASE))) ||
          /* Check for failed jobs */
          (jcr->job->RescheduleOnError &&
           !jcr->is_JobStatus(JS_Terminated) &&
@@ -625,6 +653,7 @@ static bool reschedule_job(JCR *jcr, jobq_t *jq, jobq_item_t *je)
         * Reschedule this job by cleaning it up, but
         *  reuse the same JobId if possible.
         */
+      jcr->rerunning = jcr->is_incomplete();   /* save incomplete status */
       time_t now = time(NULL);
       jcr->reschedule_count++;
       jcr->sched_time = now + jcr->job->RescheduleInterval;
@@ -642,8 +671,8 @@ static bool reschedule_job(JCR *jcr, jobq_t *jq, jobq_item_t *je)
       if (!allow_duplicate_job(jcr)) {
          return false;
       }
-      /* Only jobs with no output jobs can run on same JCR */
-      if (jcr->JobBytes == 0) {
+      /* Only jobs with no output or Incomplete jobs can run on same JCR */
+      if (jcr->JobBytes == 0 || jcr->rerunning) {
          Dmsg2(2300, "Requeue job=%d use=%d\n", jcr->JobId, jcr->use_count());
          V(jq->mutex);
          /*
@@ -653,6 +682,11 @@ static bool reschedule_job(JCR *jcr, jobq_t *jq, jobq_item_t *je)
          if (jcr->wasVirtualFull) {
             jcr->setJobLevel(L_VIRTUAL_FULL);
          }
+         /*
+          * When we are using the same jcr then make sure to reset
+          *   RealEndTime back to zero.
+          */
+         jcr->jr.RealEndTime = 0;
          jobq_add(jq, jcr);     /* queue the job to run again */
          P(jq->mutex);
          free_jcr(jcr);         /* release jcr */
@@ -667,6 +701,21 @@ static bool reschedule_job(JCR *jcr, jobq_t *jq, jobq_item_t *je)
        */
       JCR *njcr = new_jcr(sizeof(JCR), dird_free_jcr);
       set_jcr_defaults(njcr, jcr->job);
+      /*
+       * Eliminate the new job_end_push, then copy the one from
+       *  the old job, and set the old one to be empty.
+       */
+      void *v;
+      lock_jobs();              /* protect ourself from reload_config() */
+      LockRes();
+      foreach_alist(v, (&jcr->job_end_push)) {
+         njcr->job_end_push.append(v);
+      }
+      jcr->job_end_push.destroy();
+      jcr->job_end_push.init(1, false);
+      UnlockRes();
+      unlock_jobs();
+
       njcr->reschedule_count = jcr->reschedule_count;
       njcr->sched_time = jcr->sched_time;
       njcr->initial_sched_time = jcr->initial_sched_time;
@@ -684,7 +733,9 @@ static bool reschedule_job(JCR *jcr, jobq_t *jq, jobq_item_t *je)
       njcr->next_pool = jcr->next_pool;
       njcr->run_next_pool_override = jcr->run_next_pool_override;
       njcr->full_pool = jcr->full_pool;
+      njcr->vfull_pool = jcr->vfull_pool;
       njcr->run_full_pool_override = jcr->run_full_pool_override;
+      njcr->run_vfull_pool_override = jcr->run_vfull_pool_override;
       njcr->inc_pool = jcr->inc_pool;
       njcr->run_inc_pool_override = jcr->run_inc_pool_override;
       njcr->diff_pool = jcr->diff_pool;
@@ -767,14 +818,16 @@ static bool acquire_resources(JCR *jcr)
       return false;
    }
 
-   if (jcr->client->NumConcurrentJobs < jcr->client->MaxConcurrentJobs) {
-      jcr->client->NumConcurrentJobs++;
-   } else {
-      /* Back out previous locks */
-      dec_write_store(jcr);
-      dec_read_store(jcr);
-      jcr->setJobStatus(JS_WaitClientRes);
-      return false;
+   if (jcr->client) {
+      if (jcr->client->NumConcurrentJobs < jcr->client->MaxConcurrentJobs) {
+         update_client_numconcurrentjobs(jcr, 1);
+      } else {
+         /* Back out previous locks */
+         dec_write_store(jcr);
+         dec_read_store(jcr);
+         jcr->setJobStatus(JS_WaitClientRes);
+         return false;
+      }
    }
    if (jcr->job->NumConcurrentJobs < jcr->job->MaxConcurrentJobs) {
       jcr->job->NumConcurrentJobs++;
@@ -782,7 +835,7 @@ static bool acquire_resources(JCR *jcr)
       /* Back out previous locks */
       dec_write_store(jcr);
       dec_read_store(jcr);
-      jcr->client->NumConcurrentJobs--;
+      update_client_numconcurrentjobs(jcr, -1);
       jcr->setJobStatus(JS_WaitJobRes);
       return false;
    }