]> git.sur5r.net Git - bacula/bacula/commitdiff
9Nov06
authorKern Sibbald <kern@sibbald.com>
Sun, 19 Nov 2006 09:43:51 +0000 (09:43 +0000)
committerKern Sibbald <kern@sibbald.com>
Sun, 19 Nov 2006 09:43:51 +0000 (09:43 +0000)
kes  Implement unique dbid routine for migration to prevent the same
     JobId from being migrated twice. This should fix bug #709.
18Nov06
kes  Apply Jaime Ventura's 'mail on success' patch.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3656 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/projects
bacula/src/dird/migrate.c
bacula/src/lib/message.c
bacula/src/lib/message.h
bacula/src/lib/parse_conf.c
bacula/src/version.h
bacula/technotes-1.39

index 0cd172413dd2090ebe99b4e0527c01441f63c832..5bc64dfb4f931d9749c65bc8bbb280077f60b97e 100644 (file)
@@ -1154,35 +1154,3 @@ Item n:   Allow inclusion/exclusion of files in a fileset by creation/mod times
           So one could compare against 'ctime' and/or 'mtime', but ONLY 'before'
            or 'since'.
 
-
-Item 1:   Bacula support for a MailOnSuccess feature.
-  Origin: Jaime Ventura <jaimeventura at ipp dot pt>
-  Date:   15 November 2006
-  Status: for 1.38.11: coded(patch on attachment), compiled, tested
-          for 1.39.28: coded(patch on attachment), complied, NOT tested
-
-
-  What:  be able to send a email message for a specified email address if (and only if) a job finishes successfully.
-         Its similar to the MailOnError feature. 
-
-  Why:    The importance is about the same as MailOnError feature.
-          Since its not possible to do it using bacula's message types(info, error,...)filter, this could be done using some kind of filter, right after the mail was sent.
-          But since there is a MailOnError feature, why not have a MailOnSuccess feature?
-
-
-Notes: 
-
-        Why its not possible to do it using bacula's message types(info, error,...)? 
-
-        Imagine I want bacula to send ONLY successful job reports/messages to baculaOK@domain.
-        When a job starts, bacula send the message : 10-Nov 17:37 bserver-dir: Start Backup JobId 1605, Job=Job.GSI04.2006-11-10_17.37.30   
-        Since this is a info message (msgtype = M_INFO) the "bacula's messaging system" put it on the job messages (jcr->jcr_msgs) to be sent 
-        to all dest that have the info type enabled (including baculaOK@domain).
-        But when/if the job fails, that message (10-Nov 17:37 bserver-dir: Start Backup JobId 1605, Job=Job.GSI04.2006-11-10_17.37.30) has already 
-        been queued to be sent to baculaOK@domain, even though it refers to a unsuccessful backup.
-        So when its time to send all messages to emails, the "bacula's messaging system" send that message (10-Nov 17:37 bserver-dir: Start 
-        Backup JobId 1605, Job=Job.GSI04.2006-11-10_17.37.30) to baculaOK@domain, but using the subject "bacula ERROR", because the job terminated unsuccessful.
-   
-        This "problem" could also happen if I wanted bacula to send emails regarding unsuccessful backups, if i didnt use the MailOnError feature. 
-        This feature is implemented so that if messages that  where queued to be sent if the backup was unsuccessful, to be discarded if the backup is 
-
index 1f6e13fd0e58edb6f8250a2e5baf9275c2a6fe1d..2ddba5ccc0ae8bfe03965519b86c0a300d4d0628 100644 (file)
@@ -38,7 +38,7 @@
 #include <regex.h>
 #endif
 
-static const int dbglevel = 100;
+static const int dbglevel = 10;
 
 static char OKbootstrap[] = "3000 OK bootstrap\n";
 static bool get_job_to_migrate(JCR *jcr);
@@ -61,12 +61,15 @@ bool do_migration_init(JCR *jcr)
    if (!get_job_to_migrate(jcr)) {
       return false;
    }
+   Dmsg1(dbglevel, "Back from get_job_to_migrate JobId=%d\n", (int)jcr->JobId);
 
    if (jcr->previous_jr.JobId == 0) {
+      Dmsg1(dbglevel, "JobId=%d no previous JobId\n", (int)jcr->JobId);
       return true;                    /* no work */
    }
 
    if (!get_or_create_fileset_record(jcr)) {
+      Dmsg1(dbglevel, "JobId=%d no FileSet\n", (int)jcr->JobId);
       return false;
    }
 
@@ -74,6 +77,7 @@ bool do_migration_init(JCR *jcr)
 
    jcr->jr.PoolId = get_or_create_pool_record(jcr, jcr->pool->hdr.name);
    if (jcr->jr.PoolId == 0) {
+      Dmsg1(dbglevel, "JobId=%d no PoolId\n", (int)jcr->JobId);
       return false;
    }
 
@@ -122,16 +126,19 @@ bool do_migration(JCR *jcr)
     */
    if (jcr->previous_jr.JobId == 0 || jcr->ExpectedFiles == 0) {
       set_jcr_job_status(jcr, JS_Terminated);
+      Dmsg1(dbglevel, "JobId=%d expected files == 0\n", (int)jcr->JobId);
       migration_cleanup(jcr, jcr->JobStatus);
       return true;                    /* no work */
    }
 
-   Dmsg4(dbglevel, "Previous: Name=%s JobId=%d Type=%c Level=%c\n",
-      jcr->previous_jr.Name, jcr->previous_jr.JobId, 
+   Dmsg5(dbglevel, "JobId=%d: Previous: Name=%s JobId=%d Type=%c Level=%c\n",
+      (int)jcr->JobId,
+      jcr->previous_jr.Name, (int)jcr->previous_jr.JobId, 
       jcr->previous_jr.JobType, jcr->previous_jr.JobLevel);
 
-   Dmsg4(dbglevel, "Current: Name=%s JobId=%d Type=%c Level=%c\n",
-      jcr->jr.Name, jcr->jr.JobId, 
+   Dmsg5(dbglevel, "JobId=%d: Current: Name=%s JobId=%d Type=%c Level=%c\n",
+      (int)jcr->JobId,
+      jcr->jr.Name, (int)jcr->jr.JobId, 
       jcr->jr.JobType, jcr->jr.JobLevel);
 
    LockRes();
@@ -163,7 +170,7 @@ bool do_migration(JCR *jcr)
    mig_jcr->jr.JobId = mig_jcr->JobId;
 
    Dmsg4(dbglevel, "mig_jcr: Name=%s JobId=%d Type=%c Level=%c\n",
-      mig_jcr->jr.Name, mig_jcr->jr.JobId, 
+      mig_jcr->jr.Name, (int)mig_jcr->jr.JobId, 
       mig_jcr->jr.JobType, mig_jcr->jr.JobLevel);
 
    /*
@@ -226,7 +233,7 @@ bool do_migration(JCR *jcr)
 
    set_jcr_job_status(jcr, JS_Running);
    set_jcr_job_status(mig_jcr, JS_Running);
-   Dmsg2(dbglevel, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel);
+   Dmsg2(dbglevel, "JobId=%d JobLevel=%c\n", (int)jcr->jr.JobId, jcr->jr.JobLevel);
 
    /* Update job start record for this migration control job */
    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
@@ -235,7 +242,7 @@ bool do_migration(JCR *jcr)
    }
 
    Dmsg4(dbglevel, "mig_jcr: Name=%s JobId=%d Type=%c Level=%c\n",
-      mig_jcr->jr.Name, mig_jcr->jr.JobId, 
+      mig_jcr->jr.Name, (int)mig_jcr->jr.JobId, 
       mig_jcr->jr.JobType, mig_jcr->jr.JobLevel);
 
    /* Update job start record for the real migration backup job */
@@ -318,20 +325,49 @@ struct idpkt {
    uint32_t count;
 };
 
-/*
- * Callback handler make list of DB Ids
- */
-static int dbid_handler(void *ctx, int num_fields, char **row)
+/* Add an item to the list if it is unique */
+static void add_unique_id(idpkt *ids, char *item) 
 {
-   idpkt *ids = (idpkt *)ctx;
-
+   char id[30];
+   char *q = ids->list;
+
+   /* Walk through current list to see if each item is the same as item */
+   for ( ; *q; ) {
+       id[0] = 0;
+       for (int i=0; i<(int)sizeof(id); i++) {
+          if (*q == 0) {
+             break;
+          } else if (*q == ',') {
+             q++;
+             break;
+          }
+          id[i] = *q++;
+          id[i+1] = 0;
+       }
+       if (strcmp(item, id) == 0) {
+          return;
+       }
+   }
+   /* Did not find item, so add it to list */
    if (ids->count == 0) {
       ids->list[0] = 0;
    } else {
       pm_strcat(ids->list, ",");
    }
-   pm_strcat(ids->list, row[0]);
+   pm_strcat(ids->list, item);
    ids->count++;
+// Dmsg3(0, "add_uniq count=%d Ids=%p %s\n", ids->count, ids->list, ids->list);
+   return;
+}
+
+/*
+ * Callback handler make list of DB Ids
+ */
+static int unique_dbid_handler(void *ctx, int num_fields, char **row)
+{
+   idpkt *ids = (idpkt *)ctx;
+
+   add_unique_id(ids, row[0]);
    Dmsg3(dbglevel, "dbid_hdlr count=%d Ids=%p %s\n", ids->count, ids->list, ids->list);
    return 0;
 }
@@ -368,29 +404,6 @@ static int unique_name_handler(void *ctx, int num_fields, char **row)
    return 0;
 }
 
-#ifdef xxx  /* in development */
-static int unique_dbid_handler(void *ctx, int num_fields, char **row)
-{
-   dlist *list = (dlist *)ctx;
-
-   uitem *new_item = (uitem *)malloc(sizeof(uitem));
-   uitem *item;
-   
-   memset(new_item, 0, sizeof(uitem));
-   new_item->item = bstrdup(row[0]);
-   Dmsg1(dbglevel, "Item=%s\n", row[0]);
-   item = (uitem *)list->binary_insert((void *)new_item, item_compare);
-   if (item != new_item) {            /* already in list */
-      free(new_item->item);
-      free((char *)new_item);
-      return 0;
-   }
-   return 0;
-}
-#endif
-
-
-
 /* Get Job names in Pool */
 const char *sql_job =
    "SELECT DISTINCT Job.Name from Job,Pool"
@@ -557,7 +570,7 @@ static bool get_job_to_migrate(JCR *jcr)
          }
          Dmsg1(dbglevel, "SQL=%s\n", jcr->job->selection_pattern);
          if (!db_sql_query(jcr->db, jcr->job->selection_pattern,
-              dbid_handler, (void *)&ids)) {
+              unique_dbid_handler, (void *)&ids)) {
             Jmsg(jcr, M_FATAL, 0,
                  _("SQL failed. ERR=%s\n"), db_strerror(jcr->db));
             goto bail_out;
@@ -598,8 +611,8 @@ static bool get_job_to_migrate(JCR *jcr)
          ids.count = 0;
          /* Find a list of MediaIds that could be migrated */
          Mmsg(query, sql_mediaids, jcr->pool->hdr.name);
-//       Dmsg1(dbglevel, "query=%s\n", query.c_str());
-         if (!db_sql_query(jcr->db, query.c_str(), dbid_handler, (void *)&ids)) {
+         Dmsg1(dbglevel, "query=%s\n", query.c_str());
+         if (!db_sql_query(jcr->db, query.c_str(), unique_dbid_handler, (void *)&ids)) {
             Jmsg(jcr, M_FATAL, 0, _("SQL failed. ERR=%s\n"), db_strerror(jcr->db));
             goto bail_out;
          }
@@ -664,8 +677,8 @@ static bool get_job_to_migrate(JCR *jcr)
 
          ids.count = 0;
          Mmsg(query, sql_pool_time, jcr->pool->hdr.name, dt);
-//       Dmsg1(000, "query=%s\n", query.c_str());
-         if (!db_sql_query(jcr->db, query.c_str(), dbid_handler, (void *)&ids)) {
+         Dmsg1(dbglevel, "query=%s\n", query.c_str());
+         if (!db_sql_query(jcr->db, query.c_str(), unique_dbid_handler, (void *)&ids)) {
             Jmsg(jcr, M_FATAL, 0, _("SQL failed. ERR=%s\n"), db_strerror(jcr->db));
             goto bail_out;
          }
@@ -688,8 +701,8 @@ static bool get_job_to_migrate(JCR *jcr)
     *  for each of them.  For the last JobId, we handle it below.
     */
    p = ids.list;
-   Jmsg(jcr, M_INFO, 0, _("The following %u JobIds will be migrated: %s\n"),
-      ids.count, ids.list);
+   Jmsg(jcr, M_INFO, 0, _("The following %u JobId%s will be migrated: %s\n"),
+      ids.count, ids.count==0?"":"s", ids.list);
    Dmsg2(dbglevel, "Before loop count=%d ids=%s\n", ids.count, ids.list);
    for (int i=1; i < (int)ids.count; i++) {
       JobId = 0;
@@ -710,7 +723,7 @@ static bool get_job_to_migrate(JCR *jcr)
    /* Now get the last JobId and handle it in the current job */
    JobId = 0;
    stat = get_next_jobid_from_list(&p, &JobId);
-   Dmsg2(dbglevel, "Last get_next_jobid stat=%d JobId=%u\n", stat, JobId);
+   Dmsg2(dbglevel, "Last get_next_jobid stat=%d JobId=%u\n", stat, (int)JobId);
    if (stat < 0) {
       Jmsg(jcr, M_FATAL, 0, _("Invalid JobId found.\n"));
       goto bail_out;
@@ -720,7 +733,7 @@ static bool get_job_to_migrate(JCR *jcr)
    }
 
    jcr->previous_jr.JobId = JobId;
-   Dmsg1(100, "Previous jobid=%d\n", jcr->previous_jr.JobId);
+   Dmsg1(dbglevel, "Previous jobid=%d\n", (int)jcr->previous_jr.JobId);
 
    if (!db_get_job_record(jcr, jcr->db, &jcr->previous_jr)) {
       Jmsg(jcr, M_FATAL, 0, _("Could not get job record for JobId %s to migrate. ERR=%s"),
@@ -728,20 +741,25 @@ static bool get_job_to_migrate(JCR *jcr)
            db_strerror(jcr->db));
       goto bail_out;
    }
-   Jmsg(jcr, M_INFO, 0, _("Migration using JobId=%d Job=%s\n"),
-      jcr->previous_jr.JobId, jcr->previous_jr.Job);
+   Jmsg(jcr, M_INFO, 0, _("Migration using JobId=%s Job=%s\n"),
+      edit_int64(jcr->previous_jr.JobId, ed1), jcr->previous_jr.Job);
+   Dmsg3(dbglevel, "Migration JobId=%d  using JobId=%s Job=%s\n",
+      jcr->JobId,
+      edit_int64(jcr->previous_jr.JobId, ed1), jcr->previous_jr.Job);
 
 ok_out:
-   free_pool_memory(ids.list);
-   free_pool_memory(mid.list);
-   free_pool_memory(jids.list);
-   return true;
+   ok = true;
+   goto out;
 
 bail_out:
+   jcr->MigrateJobId = 0;
+   ok = false;
+           
+out:
    free_pool_memory(ids.list);
    free_pool_memory(mid.list);
    free_pool_memory(jids.list);
-   return false;
+   return ok;
 }
 
 static void start_migration_job(JCR *jcr)
@@ -771,7 +789,7 @@ static bool find_mediaid_then_jobids(JCR *jcr, idpkt *ids, const char *query1,
    ids->count = 0;
    /* Basic query for MediaId */
    Mmsg(query, query1, jcr->pool->hdr.name);
-   if (!db_sql_query(jcr->db, query.c_str(), dbid_handler, (void *)ids)) {
+   if (!db_sql_query(jcr->db, query.c_str(), unique_dbid_handler, (void *)ids)) {
       Jmsg(jcr, M_FATAL, 0, _("SQL failed. ERR=%s\n"), db_strerror(jcr->db));
       goto bail_out;
    }
@@ -798,7 +816,7 @@ static bool find_jobids_from_mediaid_list(JCR *jcr, idpkt *ids, const char *type
 
    Mmsg(query, sql_jobids_from_mediaid, ids->list);
    ids->count = 0;
-   if (!db_sql_query(jcr->db, query.c_str(), dbid_handler, (void *)ids)) {
+   if (!db_sql_query(jcr->db, query.c_str(), unique_dbid_handler, (void *)ids)) {
       Jmsg(jcr, M_FATAL, 0, _("SQL failed. ERR=%s\n"), db_strerror(jcr->db));
       goto bail_out;
    }
@@ -879,7 +897,7 @@ static bool regex_find_jobids(JCR *jcr, idpkt *ids, const char *query1,
       Dmsg2(dbglevel, "Got %s: %s\n", type, item->item);
       Mmsg(query, query2, item->item, jcr->pool->hdr.name);
       Dmsg1(dbglevel, "get id from name query2=%s\n", query.c_str());
-      if (!db_sql_query(jcr->db, query.c_str(), dbid_handler, (void *)ids)) {
+      if (!db_sql_query(jcr->db, query.c_str(), unique_dbid_handler, (void *)ids)) {
          Jmsg(jcr, M_FATAL, 0,
               _("SQL failed. ERR=%s\n"), db_strerror(jcr->db));
          goto bail_out;
index 804a417d59774a11896a4ea6e8d6866c9e25f769..0774179bc2d73be321dd4ef72c1ef88f06099603 100755 (executable)
@@ -418,12 +418,18 @@ void close_msg(JCR *jcr)
             break;
          case MD_MAIL:
          case MD_MAIL_ON_ERROR:
-            Dmsg0(850, "Got MD_MAIL or MD_MAIL_ON_ERROR\n");
+         case MD_MAIL_ON_SUCCESS:
+            Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
             if (!d->fd) {
                break;
             }
-            if (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
-                jcr->JobStatus == JS_Terminated) {
+            if (
+                (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
+                 jcr->JobStatus == JS_Terminated) 
+                ||
+                (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
+                 jcr->JobStatus == JS_ErrorTerminated)
+                ){
                goto rem_temp_file;
             }
 
@@ -689,6 +695,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
                 break;
              case MD_MAIL:
              case MD_MAIL_ON_ERROR:
+             case MD_MAIL_ON_SUCCESS:
                 Dmsg1(850, "MAIL for following msg: %s", msg);
                 if (!d->fd) {
                    POOLMEM *name = get_pool_memory(PM_MESSAGE);
index 51d1f36dbd787d327b73c09f56b77e0d772e7074..37293f9b2645a850b654fe12cfddc886826b2041 100644 (file)
@@ -114,6 +114,7 @@ enum {
    MD_OPERATOR,                       /* email a single message to the operator */
    MD_CONSOLE,                        /* send msg to UserAgent or console */
    MD_MAIL_ON_ERROR,                  /* email messages if job errors */
+   MD_MAIL_ON_SUCCESS,               /* email messages if job succeeds */
    MD_CATALOG                         /* sent to catalog Log table */
 };
 
index 48c5a58cea468389d1ce4053c1f7279c13689cae..71b988353ffa5a2c4cd5a135debe1029e105de65 100755 (executable)
@@ -95,6 +95,7 @@ RES_ITEM msgs_items[] = {
    {"syslog",      store_msgs, ITEM(res_msgs), MD_SYSLOG,   0, 0},
    {"mail",        store_msgs, ITEM(res_msgs), MD_MAIL,     0, 0},
    {"mailonerror", store_msgs, ITEM(res_msgs), MD_MAIL_ON_ERROR, 0, 0},
+   {"mailonsuccess", store_msgs, ITEM(res_msgs), MD_MAIL_ON_SUCCESS, 0, 0},
    {"file",        store_msgs, ITEM(res_msgs), MD_FILE,     0, 0},
    {"append",      store_msgs, ITEM(res_msgs), MD_APPEND,   0, 0},
    {"stdout",      store_msgs, ITEM(res_msgs), MD_STDOUT,   0, 0},
@@ -244,6 +245,7 @@ void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
       case MD_DIRECTOR:            /* send to Director */
       case MD_MAIL:                /* mail */
       case MD_MAIL_ON_ERROR:       /* mail if Job errors */
+      case MD_MAIL_ON_SUCCESS:     /* mail if Job succeeds */
          if (item->code == MD_OPERATOR) {
             cmd = res_all.res_msgs.operator_cmd;
          } else {
index 16fe1db98d3c62dd0ae059a733239c7101a9f341..2f280e8ca642bed78ce5c091c9996c78bf582653 100644 (file)
@@ -4,8 +4,8 @@
 
 #undef  VERSION
 #define VERSION "1.39.29"
-#define BDATE   "18 November 2006"
-#define LSMDATE "18Nov06"
+#define BDATE   "19 November 2006"
+#define LSMDATE "19Nov06"
 #define BYEAR "2006"       /* year for copyright messages in progs */
 
 /* Debug flags */
index 8469fddff30fe06cf27951156ca84fbfa67bdb95..08758fe02a5bad1c31c33ff646f4ccaafaa11f6d 100644 (file)
@@ -1,7 +1,11 @@
               Technical notes on version 1.39  
 
 General:
+19Nov06
+kes  Implement unique dbid routine for migration to prevent the same
+     JobId from being migrated twice. This should fix bug #709.
 18Nov06
+kes  Apply Jaime Ventura's 'mail on success' patch.
 kes  Add a SMALLOC_SANITY_CHECK for Arno, which aborts Bacula
      if memory usage gets too big.
 kes  Tweak migration to ensure that read/write devices are different.