You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2016/04/01 15:43:12 UTC

ambari git commit: AMBARI-15656 - Record and Expose Alert Occurrence Values (jonathanhurley)

Repository: ambari
Updated Branches:
  refs/heads/trunk dc4186f50 -> 6b8b74366


AMBARI-15656 - Record and Expose Alert Occurrence Values (jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6b8b7436
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6b8b7436
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6b8b7436

Branch: refs/heads/trunk
Commit: 6b8b7436631b7e32b95676c80b5fb5afe683d70a
Parents: dc4186f
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Thu Mar 31 16:17:59 2016 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Fri Apr 1 09:41:12 2016 -0400

----------------------------------------------------------------------
 .../internal/AlertResourceProvider.java         | 23 ++++++++-
 .../listeners/alerts/AlertReceivedListener.java | 29 +++++++++--
 .../server/orm/entities/AlertCurrentEntity.java | 45 +++++++++++++++++
 .../server/upgrade/UpgradeCatalog240.java       | 16 ++++++
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |  1 +
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  1 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  1 +
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  1 +
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |  1 +
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |  1 +
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |  1 +
 .../state/alerts/AlertReceivedListenerTest.java | 53 ++++++++++++++++++++
 .../server/upgrade/UpgradeCatalog240Test.java   |  9 ++++
 13 files changed, 177 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertResourceProvider.java
index dc071e9..5a985d6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertResourceProvider.java
@@ -44,6 +44,7 @@ import org.apache.ambari.server.orm.dao.AlertsDAO;
 import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
+import org.apache.ambari.server.state.AlertState;
 import org.apache.commons.lang.StringUtils;
 
 import com.google.inject.Inject;
@@ -73,6 +74,10 @@ public class AlertResourceProvider extends ReadOnlyResourceProvider implements
   protected static final String ALERT_LABEL = "Alert/label";
   protected static final String ALERT_SCOPE = "Alert/scope";
 
+  protected static final String ALERT_REPEAT_TOLERANCE = "Alert/repeat_tolerance";
+  protected static final String ALERT_OCCURRENCES = "Alert/occurrences";
+  protected static final String ALERT_REPEAT_TOLERANCE_REMAINING = "Alert/repeat_tolerance_remaining";
+
   private static Set<String> pkPropertyIds = new HashSet<String>(
       Arrays.asList(ALERT_ID, ALERT_DEFINITION_NAME));
 
@@ -109,6 +114,9 @@ public class AlertResourceProvider extends ReadOnlyResourceProvider implements
     PROPERTY_IDS.add(ALERT_HOST);
     PROPERTY_IDS.add(ALERT_SERVICE);
     PROPERTY_IDS.add(ALERT_SCOPE);
+    PROPERTY_IDS.add(ALERT_REPEAT_TOLERANCE);
+    PROPERTY_IDS.add(ALERT_OCCURRENCES);
+    PROPERTY_IDS.add(ALERT_REPEAT_TOLERANCE_REMAINING);
 
     // keys
     KEY_PROPERTY_IDS.put(Resource.Type.Alert, ALERT_ID);
@@ -250,11 +258,24 @@ public class AlertResourceProvider extends ReadOnlyResourceProvider implements
     setResourceProperty(resource, ALERT_HOST, history.getHostName(), requestedIds);
     setResourceProperty(resource, ALERT_SERVICE, history.getServiceName(), requestedIds);
 
-
     setResourceProperty(resource, ALERT_DEFINITION_ID, definition.getDefinitionId(),requestedIds);
     setResourceProperty(resource, ALERT_DEFINITION_NAME, definition.getDefinitionName(), requestedIds);
     setResourceProperty(resource, ALERT_SCOPE, definition.getScope(), requestedIds);
 
+    // repeat tolerance values
+    int repeatTolerance = definition.getRepeatTolerance();
+    int occurrences = entity.getOccurrences();
+    int remaining = (occurrences > repeatTolerance) ? 0 : (repeatTolerance - occurrences);
+
+    // the OK state is special; when received, we ignore tolerance and notify
+    if (history.getAlertState() == AlertState.OK) {
+      remaining = 0;
+    }
+
+    setResourceProperty(resource, ALERT_REPEAT_TOLERANCE, repeatTolerance, requestedIds);
+    setResourceProperty(resource, ALERT_OCCURRENCES, occurrences, requestedIds);
+    setResourceProperty(resource, ALERT_REPEAT_TOLERANCE_REMAINING, remaining, requestedIds);
+
     if (isCollection) {
       // !!! want name/id to be populated as if it were a PK when requesting the
       // collection

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
index a3befa6..fbd5c12 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
@@ -207,9 +207,10 @@ public class AlertReceivedListener {
         // update the timestamp
         current.setLatestTimestamp(alert.getTimestamp());
 
-        // only update the text if the alert isn't being skipped
+        // only update some fields if the alert isn't being skipped
         if (alertState != AlertState.SKIPPED) {
           current.setLatestText(alert.getText());
+          current.setOccurrences(current.getOccurrences() + 1);
         }
 
         toMerge.put(alert, current);
@@ -235,6 +236,28 @@ public class AlertReceivedListener {
 
         current.setAlertHistory(history);
 
+        // figure out how to set the occurrences correctly
+        switch (alertState) {
+          // an OK state always resets, regardless of what the old one was
+          case OK:
+            current.setOccurrences(1);
+            break;
+          case CRITICAL:
+          case SKIPPED:
+          case UNKNOWN:
+          case WARNING:
+            // OK -> non-OK is a reset
+            if (oldState == AlertState.OK) {
+              current.setOccurrences(1);
+            } else {
+              // non-OK -> non-OK is a continuation
+              current.setOccurrences(current.getOccurrences() + 1);
+            }
+            break;
+          default:
+            break;
+        }
+
         toCreateHistoryAndMerge.put(alert, current);
         oldStates.put(alert, oldState);
       }
@@ -244,7 +267,7 @@ public class AlertReceivedListener {
     // transaction
     saveEntities(toCreate, toMerge, toCreateHistoryAndMerge);
 
-    //broadcast events
+    // broadcast events
     for (Map.Entry<Alert, AlertCurrentEntity> entry : toCreate.entrySet()) {
       Alert alert = entry.getKey();
       AlertCurrentEntity entity = entry.getValue();
@@ -260,7 +283,6 @@ public class AlertReceivedListener {
         clusterId, alert, entity);
 
       m_alertEventPublisher.publish(initialAlertEvent);
-
     }
 
     for (Map.Entry<Alert, AlertCurrentEntity> entry : toCreateHistoryAndMerge.entrySet()) {
@@ -279,7 +301,6 @@ public class AlertReceivedListener {
 
       m_alertEventPublisher.publish(alertChangedEvent);
     }
-
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
index 604b00e..31f2154 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
@@ -33,6 +33,7 @@ import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
 
+import org.apache.ambari.server.state.AlertState;
 import org.apache.ambari.server.state.MaintenanceState;
 
 /**
@@ -83,6 +84,17 @@ public class AlertCurrentEntity {
   private String latestText = null;
 
   /**
+   * The number of occurrences of this alert in its current state. States which
+   * are not {@link AlertState#OK} are aggregated such that transitioning
+   * between these states should not reset this value. For example, if an alert
+   * bounces between {@link AlertState#WARNING} and {@link AlertState#CRITICAL},
+   * then it will not reset this value.
+   *
+   */
+  @Column(name="occurrences", nullable=false)
+  private Integer occurrences = Integer.valueOf(1);
+
+  /**
    * Unidirectional one-to-one association to {@link AlertHistoryEntity}
    */
   @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.REFRESH })
@@ -201,6 +213,39 @@ public class AlertCurrentEntity {
   }
 
   /**
+   * Gets the number of occurrences of this alert in its current state. States
+   * which are not {@link AlertState#OK} are aggregated such that transitioning
+   * between these states should not reset this value. For example, if an alert
+   * bounces between {@link AlertState#WARNING} and {@link AlertState#CRITICAL},
+   * then it will not reset this value.
+   *
+   * @return the number of occurrences.
+   */
+  public Integer getOccurrences() {
+    return occurrences;
+  }
+
+  /**
+   * Sets the number of occurrences for this alert instance.
+   *
+   * @param occurrences
+   *          the occurrences.
+   * @see #getOccurrences()
+   *
+   */
+  public void setOccurrences(int occurrences) {
+    this.occurrences = occurrences;
+  }
+
+  /**
+   * @param occurrences
+   *          the occurrences to set
+   */
+  public void setOccurrences(Integer occurrences) {
+    this.occurrences = occurrences;
+  }
+
+  /**
    * Gets the associated {@link AlertHistoryEntity} entry for this current alert
    * instance.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
index 9e4b5ab..46aa152 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
@@ -70,6 +70,8 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
 
   protected static final String ADMIN_PERMISSION_TABLE = "adminpermission";
   protected static final String ALERT_DEFINITION_TABLE = "alert_definition";
+  protected static final String ALERT_CURRENT_TABLE = "alert_current";
+  protected static final String ALERT_CURRENT_OCCURRENCES_COLUMN = "occurrences";
   protected static final String HELP_URL_COLUMN = "help_url";
   protected static final String REPEAT_TOLERANCE_COLUMN = "repeat_tolerance";
   protected static final String REPEAT_TOLERANCE_ENABLED_COLUMN = "repeat_tolerance_enabled";
@@ -153,6 +155,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
     createServiceComponentHistoryTable();
     updateClusterTableDDL();
     updateAlertDefinitionTable();
+    updateAlertCurrentTable();
     createBlueprintSettingTable();
   }
 
@@ -574,6 +577,19 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
         new DBColumnInfo(REPEAT_TOLERANCE_ENABLED_COLUMN, Short.class, null, 0, false));
   }
 
+  /**
+   * Updates the {@value #ALERT_CURRENT_TABLE} in the following ways:
+   * <ul>
+   * <li>Craetes the {@value #ALERT_CURRENT_OCCURRENCES_COLUMN} column</li>
+   * </ul>
+   *
+   * @throws SQLException
+   */
+  protected void updateAlertCurrentTable() throws SQLException {
+    dbAccessor.addColumn(ALERT_CURRENT_TABLE,
+        new DBColumnInfo(ALERT_CURRENT_OCCURRENCES_COLUMN, Integer.class, null, 1, false));
+  }
+
   protected void setRoleSortOrder() throws SQLException {
     String updateStatement = "UPDATE " + ADMIN_PERMISSION_TABLE + " SET " + SORT_ORDER_COL + "=%d WHERE " + PERMISSION_ID_COL + "='%s'";
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
index 79f41e3..2fb2195 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -918,6 +918,7 @@ CREATE TABLE alert_current (
   original_timestamp BIGINT NOT NULL,
   latest_timestamp BIGINT NOT NULL,
   latest_text VARCHAR(3000),
+  occurrences INTEGER NOT NULL DEFAULT 1,
   PRIMARY KEY (alert_id),
   FOREIGN KEY (definition_id) REFERENCES alert_definition(definition_id),
   FOREIGN KEY (history_id) REFERENCES alert_history(alert_id)

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 90fc375..6a3712e 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -931,6 +931,7 @@ CREATE TABLE alert_current (
   original_timestamp BIGINT NOT NULL,
   latest_timestamp BIGINT NOT NULL,
   latest_text TEXT,
+  occurrences INTEGER NOT NULL DEFAULT 1,
   PRIMARY KEY (alert_id),
   FOREIGN KEY (definition_id) REFERENCES alert_definition(definition_id),
   FOREIGN KEY (history_id) REFERENCES alert_history(alert_id)

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index d1880bc..964941f 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -921,6 +921,7 @@ CREATE TABLE alert_current (
   original_timestamp NUMBER(19) NOT NULL,
   latest_timestamp NUMBER(19) NOT NULL,
   latest_text CLOB,
+  occurrences INTEGER DEFAULT 1 NOT NULL
   PRIMARY KEY (alert_id),
   FOREIGN KEY (definition_id) REFERENCES alert_definition(definition_id),
   FOREIGN KEY (history_id) REFERENCES alert_history(alert_id)

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index dd1fe5f..366bbeb 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -925,6 +925,7 @@ CREATE TABLE alert_current (
   original_timestamp BIGINT NOT NULL,
   latest_timestamp BIGINT NOT NULL,
   latest_text TEXT,
+  occurrences INTEGER NOT NULL DEFAULT 1,
   PRIMARY KEY (alert_id),
   FOREIGN KEY (definition_id) REFERENCES alert_definition(definition_id),
   FOREIGN KEY (history_id) REFERENCES alert_history(alert_id)

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index e7e1997..f7e7262 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -1012,6 +1012,7 @@ CREATE TABLE ambari.alert_current (
   original_timestamp BIGINT NOT NULL,
   latest_timestamp BIGINT NOT NULL,
   latest_text TEXT,
+  occurrences INTEGER NOT NULL DEFAULT 1,
   PRIMARY KEY (alert_id),
   FOREIGN KEY (definition_id) REFERENCES ambari.alert_definition(definition_id),
   FOREIGN KEY (history_id) REFERENCES ambari.alert_history(alert_id)

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index aa8a4d9..bdb6843 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -920,6 +920,7 @@ CREATE TABLE alert_current (
   original_timestamp NUMERIC(19) NOT NULL,
   latest_timestamp NUMERIC(19) NOT NULL,
   latest_text TEXT,
+  occurrences INTEGER NOT NULL DEFAULT 1,
   PRIMARY KEY (alert_id),
   FOREIGN KEY (definition_id) REFERENCES alert_definition(definition_id),
   FOREIGN KEY (history_id) REFERENCES alert_history(alert_id)

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index 504c910..c6df84a 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -1032,6 +1032,7 @@ CREATE TABLE alert_current (
   original_timestamp BIGINT NOT NULL,
   latest_timestamp BIGINT NOT NULL,
   latest_text TEXT,
+  occurrences INTEGER NOT NULL DEFAULT 1,
   PRIMARY KEY CLUSTERED (alert_id),
   FOREIGN KEY (definition_id) REFERENCES alert_definition(definition_id),
   FOREIGN KEY (history_id) REFERENCES alert_history(alert_id)

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java
index 0d893af..7d6c691 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java
@@ -500,4 +500,57 @@ public class AlertReceivedListenerTest {
     assertEquals(2L, (long) allCurrent.get(0).getLatestTimestamp());
     assertEquals(text, allCurrent.get(0).getLatestText());
   }
+
+  /**
+   * Tests that we correctly record alert occurance information.
+   */
+  @Test
+  public void testAlertOccurrences() {
+    String definitionName = ALERT_DEFINITION + "1";
+    String serviceName = "HDFS";
+    String componentName = "NAMENODE";
+    String text = serviceName + " " + componentName + " is OK";
+
+    Alert alert = new Alert(definitionName, null, serviceName, componentName, HOST1, AlertState.OK);
+
+    alert.setCluster(m_cluster.getClusterName());
+    alert.setLabel(ALERT_LABEL);
+    alert.setText(text);
+    alert.setTimestamp(1L);
+
+    // fire the alert, and check that the new entry was created with the right
+    // timestamp
+    AlertReceivedListener listener = m_injector.getInstance(AlertReceivedListener.class);
+    AlertReceivedEvent event = new AlertReceivedEvent(m_cluster.getClusterId(), alert);
+    listener.onAlertEvent(event);
+
+    List<AlertCurrentEntity> allCurrent = m_dao.findCurrent();
+    assertEquals(1, allCurrent.size());
+
+    // check occurrences (should be 1 since it's the first)
+    assertEquals(1, (int) allCurrent.get(0).getOccurrences());
+
+    // send OK again, then check that the value incremented
+    listener.onAlertEvent(event);
+    allCurrent = m_dao.findCurrent();
+    assertEquals(2, (int) allCurrent.get(0).getOccurrences());
+
+    // now change to WARNING and check that it reset the counter
+    alert.setState(AlertState.WARNING);
+    listener.onAlertEvent(event);
+    allCurrent = m_dao.findCurrent();
+    assertEquals(1, (int) allCurrent.get(0).getOccurrences());
+
+    // send another WARNING
+    listener.onAlertEvent(event);
+    allCurrent = m_dao.findCurrent();
+    assertEquals(2, (int) allCurrent.get(0).getOccurrences());
+
+    // now change from WARNING to CRITICAL; because they are both non-OK states,
+    // the counter should continue
+    alert.setState(AlertState.CRITICAL);
+    listener.onAlertEvent(event);
+    allCurrent = m_dao.findCurrent();
+    assertEquals(3, (int) allCurrent.get(0).getOccurrences());
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b8b7436/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
index f66f21b..3723ff8 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
@@ -169,9 +169,11 @@ public class UpgradeCatalog240Test {
     Capture<DBAccessor.DBColumnInfo> capturedHelpURLColumnInfo = newCapture();
     Capture<DBAccessor.DBColumnInfo> capturedRepeatToleranceColumnInfo = newCapture();
     Capture<DBAccessor.DBColumnInfo> capturedRepeatToleranceEnabledColumnInfo = newCapture();
+    Capture<DBAccessor.DBColumnInfo> capturedOccurrencesColumnInfo = newCapture();
     dbAccessor.addColumn(eq(UpgradeCatalog240.ALERT_DEFINITION_TABLE), capture(capturedHelpURLColumnInfo));
     dbAccessor.addColumn(eq(UpgradeCatalog240.ALERT_DEFINITION_TABLE), capture(capturedRepeatToleranceColumnInfo));
     dbAccessor.addColumn(eq(UpgradeCatalog240.ALERT_DEFINITION_TABLE), capture(capturedRepeatToleranceEnabledColumnInfo));
+    dbAccessor.addColumn(eq(UpgradeCatalog240.ALERT_CURRENT_TABLE), capture(capturedOccurrencesColumnInfo));
 
     // Test creation of blueprint_setting table
     Capture<List<DBAccessor.DBColumnInfo>> capturedBlueprintSettingColumns = EasyMock.newCapture();
@@ -284,6 +286,13 @@ public class UpgradeCatalog240Test {
     Assert.assertEquals(0, columnRepeatToleranceEnabledInfo.getDefaultValue());
     Assert.assertEquals(false, columnRepeatToleranceEnabledInfo.isNullable());
 
+    DBAccessor.DBColumnInfo columnOccurrencesInfo = capturedOccurrencesColumnInfo.getValue();
+    Assert.assertNotNull(columnOccurrencesInfo);
+    Assert.assertEquals(UpgradeCatalog240.ALERT_CURRENT_OCCURRENCES_COLUMN, columnOccurrencesInfo.getName());
+    Assert.assertEquals(Integer.class, columnOccurrencesInfo.getType());
+    Assert.assertEquals(1, columnOccurrencesInfo.getDefaultValue());
+    Assert.assertEquals(false, columnOccurrencesInfo.isNullable());    
+    
     assertEquals(expectedCaptures, actualCaptures);
 
     // Verify blueprint_setting columns