]> git.sur5r.net Git - bacula/bacula/commitdiff
First cut at Duplicate Job implementation.
authorKern Sibbald <kern@sibbald.com>
Thu, 6 Mar 2008 13:57:00 +0000 (13:57 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 6 Mar 2008 13:57:00 +0000 (13:57 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6540 91ce42f0-d328-0410-95d8-f526ca767f89

12 files changed:
bacula/src/dird/admin.c
bacula/src/dird/backup.c
bacula/src/dird/dird_conf.c
bacula/src/dird/job.c
bacula/src/dird/migrate.c
bacula/src/dird/protos.h
bacula/src/dird/restore.c
bacula/src/dird/verify.c
bacula/src/lib/res.c
bacula/src/stored/reserve.c
bacula/src/version.h
bacula/technotes-2.3

index 520c80a05b188d318e8b7b4d54590403377e5df9..390c3b3aa8f45159373763740fb9c9a6edec7a21 100644 (file)
@@ -45,6 +45,9 @@
 bool do_admin_init(JCR *jcr)
 {
    free_rstorage(jcr);
+   if (!allow_duplicate_job(jcr)) {
+      return false;
+   }
    return true;
 }
 
index a8aa1d4f8795984746dfd92dfe506cff0f9c0d2e..2fbc295b869dad70238c2b6582303697b45758cc 100644 (file)
@@ -78,6 +78,10 @@ bool do_backup_init(JCR *jcr)
 
    apply_pool_overrides(jcr);
 
+   if (!allow_duplicate_job(jcr)) {
+      return false;
+   }
+
    jcr->jr.PoolId = get_or_create_pool_record(jcr, jcr->pool->name());
    if (jcr->jr.PoolId == 0) {
       return false;
index 4484ba430d4eaf76010fbd092a729fe4785138d2..d428169ab5af4a3a4997683949bdf44a5e0db273 100644 (file)
@@ -315,15 +315,15 @@ RES_ITEM job_items[] = {
    {"maximumconcurrentjobs", store_pint, ITEM(res_job.MaxConcurrentJobs), 0, ITEM_DEFAULT, 1},
    {"rescheduleonerror", store_bool, ITEM(res_job.RescheduleOnError), 0, ITEM_DEFAULT, false},
    {"rescheduleinterval", store_time, ITEM(res_job.RescheduleInterval), 0, ITEM_DEFAULT, 60 * 30},
-   {"rescheduletimes", store_pint, ITEM(res_job.RescheduleTimes), 0, 0, 0},
-   {"priority",   store_pint, ITEM(res_job.Priority), 0, ITEM_DEFAULT, 10},
-   {"writepartafterjob",   store_bool, ITEM(res_job.write_part_after_job), 0, ITEM_DEFAULT, true},
-   {"selectionpattern", store_str, ITEM(res_job.selection_pattern), 0, 0, 0},
-   {"runscript", store_runscript, ITEM(res_job.RunScripts), 0, ITEM_NO_EQUALS, 0},
-   {"selectiontype", store_migtype, ITEM(res_job.selection_type), 0, 0, 0},
-   {"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},
+   {"rescheduletimes",    store_pint, ITEM(res_job.RescheduleTimes), 0, 0, 0},
+   {"priority",           store_pint, ITEM(res_job.Priority), 0, ITEM_DEFAULT, 10},
+   {"writepartafterjob",  store_bool, ITEM(res_job.write_part_after_job), 0, ITEM_DEFAULT, true},
+   {"selectionpattern",   store_str, ITEM(res_job.selection_pattern), 0, 0, 0},
+   {"runscript",          store_runscript, ITEM(res_job.RunScripts), 0, ITEM_NO_EQUALS, 0},
+   {"selectiontype",      store_migtype, ITEM(res_job.selection_type), 0, 0, 0},
+   {"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},
    {"cancelqueuedduplicates",  store_bool, ITEM(res_job.CancelQueuedDuplicates), 0, ITEM_DEFAULT, true},
    {"cancelrunningduplicates", store_bool, ITEM(res_job.CancelRunningDuplicates), 0, ITEM_DEFAULT, false},
    {"pluginoptions", store_str, ITEM(res_job.PluginOptions), 0, 0, 0},
index 77700bf54e37cad718e99074d7f56746bdbfff5a..3a0bd8f7f2afca99d7632f5e824a1ac6f0fcae6f 100644 (file)
@@ -585,16 +585,77 @@ DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
    while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
       /* Try to create the pool */
       if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
-         Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
+         Jmsg(jcr, M_FATAL, 0, _("Pool \"%s\" not in database. ERR=%s"), pr.Name,
             db_strerror(jcr->db));
          return 0;
       } else {
-         Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
+         Jmsg(jcr, M_INFO, 0, _("Created database record for Pool \"%s\".\n"), pr.Name);
       }
    }
    return pr.PoolId;
 }
 
+/*
+ * 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) {
+         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.\n"));
+               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);
+               char ec1[50];
+               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;   
+}
+
 void apply_pool_overrides(JCR *jcr)
 {
    bool pool_override = false;
index 1808f403b729f0965f605afacab072d9478800fc..36b357418f5ce2487a110a3c53a92eaf3f2e6809 100644 (file)
@@ -104,6 +104,10 @@ bool do_migration_init(JCR *jcr)
 
    apply_pool_overrides(jcr);
 
+   if (!allow_duplicate_job(jcr)) {
+      return false;
+   }
+
    jcr->jr.PoolId = get_or_create_pool_record(jcr, jcr->pool->name());
    if (jcr->jr.PoolId == 0) {
       Dmsg1(dbglevel, "JobId=%d no PoolId\n", (int)jcr->JobId);
index 893b980bb68d34d9f224b52692ebf0097aacab59..e1c94b39c642b22c8a3cf38cae34aaf8bbed5ec0 100644 (file)
@@ -103,6 +103,7 @@ enum e_prtmsg {
 extern bool response(JCR *jcr, BSOCK *fd, char *resp, const char *cmd, e_prtmsg prtmsg);
 
 /* job.c */
+extern bool allow_duplicate_job(JCR *jcr);
 extern void set_jcr_defaults(JCR *jcr, JOB *job);
 extern void create_unique_job_name(JCR *jcr, const char *base_name);
 extern void update_job_end_record(JCR *jcr);
index bd27d6e94603c2e3e540257088ba208cc7a2c223..2a73362e51c65e9a0185c9aae149e777f23fca72 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-20087 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -69,15 +69,21 @@ bool do_restore(JCR *jcr)
 {
    BSOCK   *fd;
    JOB_DBR rjr;                       /* restore job record */
+   char replace, *where, *cmd;
+   char empty = '\0';
+   int stat;
 
    free_wstorage(jcr);                /* we don't write */
 
+   if (!allow_duplicate_job(jcr)) {
+      goto bail_out;
+   }
+
    memset(&rjr, 0, sizeof(rjr));
    jcr->jr.JobLevel = L_FULL;         /* Full restore */
    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return false;
+      goto bail_out;
    }
    Dmsg0(20, "Updated job start record\n");
 
@@ -87,8 +93,7 @@ bool do_restore(JCR *jcr)
       Jmsg0(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
           "You probably ran a restore job directly. All restore jobs must\n"
           "be run using the restore command.\n"));
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return false;
+      goto bail_out;
    }
 
 
@@ -107,25 +112,22 @@ bool do_restore(JCR *jcr)
     * Start conversation with Storage daemon
     */
    if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return false;
+      goto bail_out;
    }
    /*
     * Now start a job with the Storage daemon
     */
    if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return false;
+      goto bail_out;
    }
    if (!jcr->store_bsock->fsend("run")) {
-      return false;
+      goto bail_out;
    }
    /*
     * Now start a Storage daemon message thread
     */
    if (!start_storage_daemon_message_thread(jcr)) {
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return false;
+      goto bail_out;
    }
    Dmsg0(50, "Storage daemon connection OK\n");
 
@@ -135,8 +137,7 @@ bool do_restore(JCR *jcr)
     */
    set_jcr_job_status(jcr, JS_WaitFD);
    if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return false;
+      goto bail_out;
    }
 
    fd = jcr->file_bsock;
@@ -153,8 +154,7 @@ bool do_restore(JCR *jcr)
    fd->fsend(storaddr, jcr->rstore->address, jcr->rstore->SDDport);
    Dmsg1(6, "dird>filed: %s\n", fd->msg);
    if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return false;
+      goto bail_out;
    }
 
    /*
@@ -162,19 +162,15 @@ bool do_restore(JCR *jcr)
     */
    if (!send_bootstrap_file(jcr, fd) ||
        !response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return false;
+      goto bail_out;
    }
 
 
    if (!send_runscripts_commands(jcr)) {
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return false;
+      goto bail_out;
    }
 
    /* Send restore command */
-   char replace, *where, *cmd;
-   char empty = '\0';
 
    if (jcr->replace != 0) {
       replace = jcr->replace;
@@ -210,15 +206,17 @@ bool do_restore(JCR *jcr)
    unbash_spaces(where);
 
    if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return false;
+      goto bail_out;
    }
 
    /* Wait for Job Termination */
-   int stat = wait_for_job_termination(jcr);
+   stat = wait_for_job_termination(jcr);
    restore_cleanup(jcr, stat);
-
    return true;
+
+bail_out:
+   restore_cleanup(jcr, JS_ErrorTerminated);
+   return false;
 }
 
 bool do_restore_init(JCR *jcr) 
index 559eb0eaeab7e9f02a700eeb3ff74d9fb4b6d8ba..57663a26e29c9f0ac2629e9863a14782bc235070 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -66,6 +66,9 @@ static int missing_handler(void *ctx, int num_fields, char **row);
  */
 bool do_verify_init(JCR *jcr) 
 {
+   if (!allow_duplicate_job(jcr)) {
+      return false;
+   }
    return true;
 }
 
index 728cafb3f5d41f61f731c146288e165ff5227c7d..4209943ffee5992c991960ced082c31279bd1681 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
index 369921cbb505d64b4895e31f8aa9a244d2ef4fa7..7ae826b9993cbb989adad92cefb2289a30e893c1 100644 (file)
@@ -389,7 +389,7 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
             dev->vol = vol;               /* point dev at vol */
             dev->VolHdr.VolumeName[0] = 0;
          } else {
-            Dmsg3(dbglvl, "Volume busy could not swap vol=%s from dev=%s to %s\n", 
+            Dmsg3(dbglvl, "==== Swap not possible Vol busy vol=%s from dev=%s to %s\n", 
                VolumeName, vol->dev->print_name(), dev->print_name());
             vol = NULL;                /* device busy */
             goto get_out;
index 53512bd389b87c3aa6cbdd99e783542617f037dc..e2a91353561bb9a5a7acb5fc25a7a4f26c57dcfb 100644 (file)
@@ -3,9 +3,9 @@
  */
 
 #undef  VERSION
-#define VERSION "2.3.11"
-#define BDATE   "04 March 2008"
-#define LSMDATE "04Mar08"
+#define VERSION "2.3.12"
+#define BDATE   "06 March 2008"
+#define LSMDATE "06Mar08"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2008 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2008"       /* year for copyright messages in progs */
index 337aa7824994889397ef70ecdc6af439e63c690d..321d127d5954f563210822eb2a7efac84e7ef070 100644 (file)
@@ -1,6 +1,8 @@
               Technical notes on version 2.3
 
 General:
+06Mar08
+kes  First cut at Duplicate Job implementation.
 05Mar08
 kes  Fix bugs in MaxFullInterval and Implement MaxDiffInterval.
 kes  Start PluginOptions string, and refactor a bit of ua_run.c