]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/job.c
20Dec08
[bacula/bacula] / bacula / src / dird / job.c
index 106757514f216d1917b0828a9c5d72971cf87a5b..8a88516bb138d5a850d2bad083e94857d3621d6e 100644 (file)
@@ -173,6 +173,8 @@ bool setup_job(JCR *jcr)
        jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
 
    generate_daemon_event(jcr, "JobStart");
+   new_plugins(jcr);                  /* instantiate plugins for this jcr */
+   generate_plugin_event(jcr, bEventJobStart);
 
    if (job_canceled(jcr)) {
       goto bail_out;
@@ -228,6 +230,7 @@ bool setup_job(JCR *jcr)
    }
 
    generate_job_event(jcr, "JobInit");
+   generate_plugin_event(jcr, bEventJobInit);
    Dsm_check(1);
    return true;
 
@@ -284,68 +287,64 @@ static void *job_thread(void *arg)
    /* Run any script BeforeJob on dird */
    run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
 
-   if (job_canceled(jcr)) {
-      update_job_end(jcr, jcr->JobStatus);
+   /*
+    * We re-update the job start record so that the start
+    *  time is set after the run before job.  This avoids
+    *  that any files created by the run before job will
+    *  be saved twice.  They will be backed up in the current
+    *  job, but not in the next one unless they are changed.
+    *  Without this, they will be backed up in this job and
+    *  in the next job run because in that case, their date
+    *   is after the start of this run.
+    */
+   jcr->start_time = time(NULL);
+   jcr->jr.StartTime = jcr->start_time;
+   if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
+      Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
+   }
+   generate_job_event(jcr, "JobRun");
+   generate_plugin_event(jcr, bEventJobRun);
 
-   } else {
-      /*
-       * We re-update the job start record so that the start
-       *  time is set after the run before job.  This avoids
-       *  that any files created by the run before job will
-       *  be saved twice.  They will be backed up in the current
-       *  job, but not in the next one unless they are changed.
-       *  Without this, they will be backed up in this job and
-       *  in the next job run because in that case, their date
-       *   is after the start of this run.
-       */
-      jcr->start_time = time(NULL);
-      jcr->jr.StartTime = jcr->start_time;
-      if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
-         Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
+   switch (jcr->get_JobType()) {
+   case JT_BACKUP:
+      if (!job_canceled(jcr) && do_backup(jcr)) {
+         do_autoprune(jcr);
+      } else {
+         backup_cleanup(jcr, JS_ErrorTerminated);
       }
-      generate_job_event(jcr, "JobRun");
-
-      switch (jcr->get_JobType()) {
-      case JT_BACKUP:
-         if (do_backup(jcr)) {
-            do_autoprune(jcr);
-         } else {
-            backup_cleanup(jcr, JS_ErrorTerminated);
-         }
-         break;
-      case JT_VERIFY:
-         if (do_verify(jcr)) {
-            do_autoprune(jcr);
-         } else {
-            verify_cleanup(jcr, JS_ErrorTerminated);
-         }
-         break;
-      case JT_RESTORE:
-         if (do_restore(jcr)) {
-            do_autoprune(jcr);
-         } else {
-            restore_cleanup(jcr, JS_ErrorTerminated);
-         }
-         break;
-      case JT_ADMIN:
-         if (do_admin(jcr)) {
-            do_autoprune(jcr);
-         } else {
-            admin_cleanup(jcr, JS_ErrorTerminated);
-         }
-         break;
-      case JT_COPY:
-      case JT_MIGRATE:
-         if (do_migration(jcr)) {
-            do_autoprune(jcr);
-         } else {
-            migration_cleanup(jcr, JS_ErrorTerminated);
-         }
-         break;
-      default:
-         Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->get_JobType());
-         break;
+      break;
+   case JT_VERIFY:
+      if (!job_canceled(jcr) && do_verify(jcr)) {
+         do_autoprune(jcr);
+      } else {
+         verify_cleanup(jcr, JS_ErrorTerminated);
+      }
+      break;
+   case JT_RESTORE:
+      if (!job_canceled(jcr) && do_restore(jcr)) {
+         do_autoprune(jcr);
+      } else {
+         restore_cleanup(jcr, JS_ErrorTerminated);
+      }
+      break;
+   case JT_ADMIN:
+      if (!job_canceled(jcr) && do_admin(jcr)) {
+         do_autoprune(jcr);
+      } else {
+         admin_cleanup(jcr, JS_ErrorTerminated);
+      }
+      break;
+   case JT_COPY:
+   case JT_MIGRATE:
+      if (!job_canceled(jcr) && do_migration(jcr)) {
+         do_autoprune(jcr);
+      } else {
+         migration_cleanup(jcr, JS_ErrorTerminated);
       }
+      break;
+   default:
+      Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->get_JobType());
+      break;
    }
 
    run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
@@ -356,6 +355,7 @@ static void *job_thread(void *arg)
    }
 
    generate_daemon_event(jcr, "JobEnd");
+   generate_plugin_event(jcr, bEventJobEnd);
    Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
    sm_check(__FILE__, __LINE__, true);
    return NULL;
@@ -373,10 +373,11 @@ bool cancel_job(UAContext *ua, JCR *jcr)
 {
    BSOCK *sd, *fd;
    char ed1[50];
+   int32_t old_status = jcr->JobStatus;
 
    set_jcr_job_status(jcr, JS_Canceled);
 
-   switch (jcr->JobStatus) {
+   switch (old_status) {
    case JS_Created:
    case JS_WaitJobRes:
    case JS_WaitClientRes:
@@ -549,13 +550,20 @@ static bool job_check_maxwaittime(JCR *jcr)
 {
    bool cancel = false;
    JOB *job = jcr->job;
+   utime_t current=0;
 
    if (!job_waiting(jcr)) {
       return false;
    }
-   Dmsg3(200, "check maxwaittime %u - %u >= %u\n", watchdog_time, jcr->wait_time, job->MaxWaitTime);
+
+   if (jcr->wait_time) {
+      current = watchdog_time - jcr->wait_time;
+   }
+
+   Dmsg2(200, "check maxwaittime %u >= %u\n", 
+         current + jcr->wait_time_sum, job->MaxWaitTime);
    if (job->MaxWaitTime != 0 &&
-       (watchdog_time - jcr->wait_time) >= job->MaxWaitTime) {
+       (current + jcr->wait_time_sum) >= job->MaxWaitTime) {
       cancel = true;
    }
 
@@ -661,7 +669,7 @@ bool allow_duplicate_job(JCR *jcr)
          if (strcmp(job->name(), djcr->job->name()) == 0) {
             bool cancel_queued = false;
             if (job->DuplicateJobProximity > 0) {
-               time_t now = time(NULL);
+               utime_t now = (utime_t)time(NULL);
                if ((now - djcr->start_time) > job->DuplicateJobProximity) {
                   continue;               /* not really a duplicate */
                }
@@ -700,6 +708,7 @@ bool allow_duplicate_job(JCR *jcr)
             }
          }
       }
+      endeach_jcr(djcr);
    }
    return true;   
 }
@@ -877,17 +886,17 @@ void create_unique_job_name(JCR *jcr, const char *base_name)
    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    static time_t last_start_time = 0;
    static int seq = 0;
-   time_t now;
+   time_t now = time(NULL);
    struct tm tm;
    char dt[MAX_TIME_LENGTH];
    char name[MAX_NAME_LENGTH];
    char *p;
+   int len;
 
    /* Guarantee unique start time -- maximum one per second, and
     * thus unique Job Name
     */
    P(mutex);                          /* lock creation of jobs */
-   now = time(NULL);
    seq++;
    if (seq > 59) {                    /* wrap as if it is seconds */
       seq = 0;
@@ -902,9 +911,10 @@ void create_unique_job_name(JCR *jcr, const char *base_name)
    /* Form Unique JobName */
    (void)localtime_r(&now, &tm);
    /* Use only characters that are permitted in Windows filenames */
-   strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M", &tm);
+   strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
+   len = strlen(dt) + 5;   /* dt + .%02d EOS */
    bstrncpy(name, base_name, sizeof(name));
-   name[sizeof(name)-22] = 0;          /* truncate if too long */
+   name[sizeof(name)-len] = 0;          /* truncate if too long */
    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s.%02d", name, dt, seq); /* add date & time */
    /* Convert spaces into underscores */
    for (p=jcr->Job; *p; p++) {
@@ -912,6 +922,7 @@ void create_unique_job_name(JCR *jcr, const char *base_name)
          *p = '_';
       }
    }
+   Dmsg2(100, "JobId=%u created Job=%s\n", jcr->JobId, jcr->Job);
 }
 
 /* Called directly from job rescheduling */
@@ -1020,6 +1031,8 @@ void dird_free_jcr(JCR *jcr)
    if (jcr->JobId != 0)
       write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
 
+   free_plugins(jcr);                 /* release instantiated plugins */
+
    Dmsg0(200, "End dird free_jcr\n");
 }
 
@@ -1351,31 +1364,40 @@ bool create_restore_bootstrap_file(JCR *jcr)
    rx.JobIds = (char *)"";                       
    rx.bsr->JobId = jcr->previous_jr.JobId;
    ua = new_ua_context(jcr);
-   complete_bsr(ua, rx.bsr);
+   if (!complete_bsr(ua, rx.bsr)) {
+      goto bail_out;
+   }
    rx.bsr->fi = new_findex();
    rx.bsr->fi->findex = 1;
    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
    jcr->ExpectedFiles = write_bsr_file(ua, rx);
    if (jcr->ExpectedFiles == 0) {
-      free_ua_context(ua);
-      free_bsr(rx.bsr);
-      return false;
+      goto bail_out;
    }
    free_ua_context(ua);
    free_bsr(rx.bsr);
    jcr->needs_sd = true;
    return true;
+
+bail_out:
+   free_ua_context(ua);
+   free_bsr(rx.bsr);
+   return false;
 }
 
+/* TODO: redirect command ouput to job log */
 bool run_console_command(JCR *jcr, const char *cmd){
    UAContext *ua;
    bool ok;
-
-   ua = new_ua_context(jcr);
+   JCR *ljcr = new_control_jcr("-RunScript-", JT_CONSOLE);
+   ua = new_ua_context(ljcr);
+   /* run from runscript and check if commands are autorized */
+   ua->runscript = true;
    Mmsg(ua->cmd, "%s", cmd);
    Dmsg1(100, "Console command: %s\n", ua->cmd);
    parse_ua_args(ua);
    ok= do_a_command(ua);
    free_ua_context(ua);
+   free_jcr(ljcr);
    return ok;
 }