src/dird/jobq.c
static bool reschedule_job(JCR *jcr, jobq_t *jq, jobq_item_t *je)
{
   bool resched = false;
   /*
    * Reschedule the job if requested and possible
    */
   /* Basic condition is that more reschedule times remain */
   if (jcr->job->RescheduleTimes == 0 ||
       jcr->reschedule_count < jcr->job->RescheduleTimes) {

      /* Check for incomplete jobs */
      if (jcr->is_incomplete()) {
         resched = (jcr->RescheduleIncompleteJobs && jcr->is_JobType(JT_BACKUP) &&
                    !(jcr->HasBase||jcr->is_JobLevel(L_BASE)));
      } else {
         /* Check for failed jobs */
         resched = (jcr->job->RescheduleOnError &&
                    !jcr->is_JobStatus(JS_Terminated) &&
                    !jcr->is_JobStatus(JS_Canceled) &&
                    jcr->is_JobType(JT_BACKUP));
      }
   }
   if (resched) {
       char dt[50], dt2[50];

       /*
        * 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;
      bstrftime(dt, sizeof(dt), now);
      bstrftime(dt2, sizeof(dt2), jcr->sched_time);
      Dmsg4(2300, "Rescheduled Job %s to re-run in %d seconds.(now=%u,then=%u)\n", jcr->Job,
            (int)jcr->job->RescheduleInterval, now, jcr->sched_time);
      Jmsg(jcr, M_INFO, 0, _("Rescheduled Job %s at %s to re-run in %d seconds (%s).\n"),
           jcr->Job, dt, (int)jcr->job->RescheduleInterval, dt2);
      dird_free_jcr_pointers(jcr);     /* partial cleanup old stuff */
      jcr->JobStatus = -1;
      jcr->setJobStatus(JS_WaitStartTime);
      jcr->SDJobStatus = 0;
      jcr->JobErrors = 0;
      if (!allow_duplicate_job(jcr)) {
         return false;
      }
      /* 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);
         /*
          * Special test here since a Virtual Full gets marked
          *  as a Full, so we look at the resource record
          */
         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 */
         free(je);              /* free the job entry */
         return true;           /* we already cleaned up */
      }
      /*
       * Something was actually backed up, so we cannot reuse
       *   the old JobId or there will be database record
       *   conflicts.  We now create a new job, copying the
       *   appropriate fields.
       */
      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;
      /*
       * Special test here since a Virtual Full gets marked
       *  as a Full, so we look at the resource record
       */
      if (jcr->wasVirtualFull) {
         njcr->setJobLevel(L_VIRTUAL_FULL);
      } else {
         njcr->setJobLevel(jcr->getJobLevel());
      }
      njcr->pool = jcr->pool;
      njcr->run_pool_override = jcr->run_pool_override;
      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;
      njcr->JobStatus = -1;
      njcr->setJobStatus(jcr->JobStatus);
      if (jcr->rstore) {
         copy_rstorage(njcr, jcr->rstorage, _("previous Job"));
      } else {
         free_rstorage(njcr);
      }
      if (jcr->wstore) {
         copy_wstorage(njcr, jcr->wstorage, _("previous Job"));
      } else {
         free_wstorage(njcr);
      }
      njcr->messages = jcr->messages;
      njcr->spool_data = jcr->spool_data;
      njcr->write_part_after_job = jcr->write_part_after_job;
      Dmsg0(2300, "Call to run new job\n");
      V(jq->mutex);
      run_job(njcr);            /* This creates a "new" job */
      free_jcr(njcr);           /* release "new" jcr */
      P(jq->mutex);
      Dmsg0(2300, "Back from running new job.\n");
   }
   return false;
}
/*
 * Returns true if cleanup done and we should look for more work
 */
Returns true if cleanup done and we should look for more work
Returns true if cleanup done and we should look for more work
static bool reschedule_job(JCR *jcr, jobq_t *jq, jobq_item_t *je)
{
   bool resched = false;
   if (jcr->job->RescheduleTimes == 0 ||
       jcr->reschedule_count < jcr->job->RescheduleTimes) {
      if (jcr->is_incomplete()) {
         resched = (jcr->RescheduleIncompleteJobs && jcr->is_JobType(JT_BACKUP) &&
                    !(jcr->HasBase||jcr->is_JobLevel(L_BASE)));
      } else {
         resched = (jcr->job->RescheduleOnError &&
                    !jcr->is_JobStatus(JS_Terminated) &&
                    !jcr->is_JobStatus(JS_Canceled) &&
                    jcr->is_JobType(JT_BACKUP));
      }
   }
   if (resched) {
       char dt[50], dt2[50];
      jcr->rerunning = jcr->is_incomplete();   
      time_t now = time(NULL);
      jcr->reschedule_count++;
      jcr->sched_time = now + jcr->job->RescheduleInterval;
      bstrftime(dt, sizeof(dt), now);
      bstrftime(dt2, sizeof(dt2), jcr->sched_time);
      Dmsg4(2300, "Rescheduled Job %s to re-run in %d seconds.(now=%u,then=%u)\n", jcr->Job,
            (int)jcr->job->RescheduleInterval, now, jcr->sched_time);
      Jmsg(jcr, M_INFO, 0, _("Rescheduled Job %s at %s to re-run in %d seconds (%s).\n"),
           jcr->Job, dt, (int)jcr->job->RescheduleInterval, dt2);
      dird_free_jcr_pointers(jcr);     
      jcr->JobStatus = -1;
      jcr->setJobStatus(JS_WaitStartTime);
      jcr->SDJobStatus = 0;
      jcr->JobErrors = 0;
      if (!allow_duplicate_job(jcr)) {
         return false;
      }
      if (jcr->JobBytes == 0 || jcr->rerunning) {
         Dmsg2(2300, "Requeue job=%d use=%d\n", jcr->JobId, jcr->use_count());
         V(jq->mutex);
         if (jcr->wasVirtualFull) {
            jcr->setJobLevel(L_VIRTUAL_FULL);
         }
         jcr->jr.RealEndTime = 0;
         jobq_add(jq, jcr);     
         P(jq->mutex);
         free_jcr(jcr);         
         free(je);              
         return true;           
      }
      JCR *njcr = new_jcr(sizeof(JCR), dird_free_jcr);
      set_jcr_defaults(njcr, jcr->job);
      void *v;
      lock_jobs();              
      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;
      if (jcr->wasVirtualFull) {
         njcr->setJobLevel(L_VIRTUAL_FULL);
      } else {
         njcr->setJobLevel(jcr->getJobLevel());
      }
      njcr->pool = jcr->pool;
      njcr->run_pool_override = jcr->run_pool_override;
      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;
      njcr->JobStatus = -1;
      njcr->setJobStatus(jcr->JobStatus);
      if (jcr->rstore) {
         copy_rstorage(njcr, jcr->rstorage, _("previous Job"));
      } else {
         free_rstorage(njcr);
      }
      if (jcr->wstore) {
         copy_wstorage(njcr, jcr->wstorage, _("previous Job"));
      } else {
         free_wstorage(njcr);
      }
      njcr->messages = jcr->messages;
      njcr->spool_data = jcr->spool_data;
      njcr->write_part_after_job = jcr->write_part_after_job;
      Dmsg0(2300, "Call to run new job\n");
      V(jq->mutex);
      run_job(njcr);            
      free_jcr(njcr);           
      P(jq->mutex);
      Dmsg0(2300, "Back from running new job.\n");
   }
   return false;
}
static bool reschedule_job ( JCR * jcr , jobq_t * jq , jobq_item_t * je ) { bool resched = false ; if ( jcr -> job -> RescheduleTimes == 0 || jcr -> reschedule_count < jcr -> job -> RescheduleTimes ) { if ( jcr -> is_incomplete ( ) ) { resched = ( jcr -> RescheduleIncompleteJobs && jcr -> is_JobType ( JT_BACKUP ) && ! ( jcr -> HasBase || jcr -> is_JobLevel ( L_BASE ) ) ) ; } else { resched = ( jcr -> job -> RescheduleOnError && ! jcr -> is_JobStatus ( JS_Terminated ) && ! jcr -> is_JobStatus ( JS_Canceled ) && jcr -> is_JobType ( JT_BACKUP ) ) ; } } if ( resched ) { char dt [ 50 ] , dt2 [ 50 ] ; jcr -> rerunning = jcr -> is_incomplete ( ) ; time_t now = time ( NULL ) ; jcr -> reschedule_count ++ ; jcr -> sched_time = now + jcr -> job -> RescheduleInterval ; bstrftime ( dt , sizeof ( dt ) , now ) ; bstrftime ( dt2 , sizeof ( dt2 ) , jcr -> sched_time ) ; Dmsg4 ( 2300 , " \n " , jcr -> Job , ( int ) jcr -> job -> RescheduleInterval , now , jcr -> sched_time ) ; Jmsg ( jcr , M_INFO , 0 , _ ( " \n " ) , jcr -> Job , dt , ( int ) jcr -> job -> RescheduleInterval , dt2 ) ; dird_free_jcr_pointers ( jcr ) ; jcr -> JobStatus = -1 ; jcr -> setJobStatus ( JS_WaitStartTime ) ; jcr -> SDJobStatus = 0 ; jcr -> JobErrors = 0 ; if ( ! allow_duplicate_job ( jcr ) ) { return false ; } if ( jcr -> JobBytes == 0 || jcr -> rerunning ) { Dmsg2 ( 2300 , " \n " , jcr -> JobId , jcr -> use_count ( ) ) ; V ( jq -> mutex ) ; if ( jcr -> wasVirtualFull ) { jcr -> setJobLevel ( L_VIRTUAL_FULL ) ; } jcr -> jr . RealEndTime = 0 ; jobq_add ( jq , jcr ) ; P ( jq -> mutex ) ; free_jcr ( jcr ) ; free ( je ) ; return true ; } JCR * njcr = new_jcr ( sizeof ( JCR ) , dird_free_jcr ) ; set_jcr_defaults ( njcr , jcr -> job ) ; void * v ; lock_jobs ( ) ; 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 ; if ( jcr -> wasVirtualFull ) { njcr -> setJobLevel ( L_VIRTUAL_FULL ) ; } else { njcr -> setJobLevel ( jcr -> getJobLevel ( ) ) ; } njcr -> pool = jcr -> pool ; njcr -> run_pool_override = jcr -> run_pool_override ; 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 ; njcr -> JobStatus = -1 ; njcr -> setJobStatus ( jcr -> JobStatus ) ; if ( jcr -> rstore ) { copy_rstorage ( njcr , jcr -> rstorage , _ ( " " ) ) ; } else { free_rstorage ( njcr ) ; } if ( jcr -> wstore ) { copy_wstorage ( njcr , jcr -> wstorage , _ ( " " ) ) ; } else { free_wstorage ( njcr ) ; } njcr -> messages = jcr -> messages ; njcr -> spool_data = jcr -> spool_data ; njcr -> write_part_after_job = jcr -> write_part_after_job ; Dmsg0 ( 2300 , " \n " ) ; V ( jq -> mutex ) ; run_job ( njcr ) ; free_jcr ( njcr ) ; P ( jq -> mutex ) ; Dmsg0 ( 2300 , " \n " ) ; } return false ; }
Returns true if cleanup done and we should look for more work
Returns true if cleanup done and we should look for more work
/*
    * Reschedule the job if requested and possible
    */ /* Basic condition is that more reschedule times remain */ /* Check for incomplete jobs */ /* Check for failed jobs */ /*
        * Reschedule this job by cleaning it up, but
        *  reuse the same JobId if possible.
        */ /* save incomplete status */ /* partial cleanup old stuff */ /* Only jobs with no output or Incomplete jobs can run on same JCR */ /*
          * Special test here since a Virtual Full gets marked
          *  as a Full, so we look at the resource record
          */ /*
          * When we are using the same jcr then make sure to reset
          *   RealEndTime back to zero.
          */ /* queue the job to run again */ /* release jcr */ /* free the job entry */ /* we already cleaned up */ /*
       * Something was actually backed up, so we cannot reuse
       *   the old JobId or there will be database record
       *   conflicts.  We now create a new job, copying the
       *   appropriate fields.
       */ /*
       * Eliminate the new job_end_push, then copy the one from
       *  the old job, and set the old one to be empty.
       */ /* protect ourself from reload_config() */ /*
       * Special test here since a Virtual Full gets marked
       *  as a Full, so we look at the resource record
       */ /* This creates a "new" job */ /* release "new" jcr */