helix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From l...@apache.org
Subject [16/38] helix git commit: Persist session change history with timestamp for each participant.
Date Wed, 08 Feb 2017 17:59:51 GMT
Persist session change history with timestamp for each participant.


Project: http://git-wip-us.apache.org/repos/asf/helix/repo
Commit: http://git-wip-us.apache.org/repos/asf/helix/commit/8b320514
Tree: http://git-wip-us.apache.org/repos/asf/helix/tree/8b320514
Diff: http://git-wip-us.apache.org/repos/asf/helix/diff/8b320514

Branch: refs/heads/helix-0.6.x
Commit: 8b320514da58e38652f79f625576bb9895f6312c
Parents: 821fd04
Author: Lei Xia <lxia@linkedin.com>
Authored: Tue Aug 30 13:29:08 2016 -0700
Committer: Lei Xia <lxia@linkedin.com>
Committed: Sun Feb 5 19:20:27 2017 -0800

----------------------------------------------------------------------
 .../main/java/org/apache/helix/PropertyKey.java | 25 ++----
 .../org/apache/helix/PropertyPathBuilder.java   | 12 +++
 .../java/org/apache/helix/PropertyType.java     |  3 +-
 .../manager/zk/ParticipantManagerHelper.java    | 16 +++-
 .../apache/helix/manager/zk/ZKHelixAdmin.java   |  1 +
 .../org/apache/helix/manager/zk/ZKUtil.java     | 10 +++
 .../apache/helix/model/ParticipantHistory.java  | 89 ++++++++++++++++++++
 .../helix/integration/TestInstanceHistory.java  | 56 ++++++++++++
 8 files changed, 193 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/helix/blob/8b320514/helix-core/src/main/java/org/apache/helix/PropertyKey.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/PropertyKey.java b/helix-core/src/main/java/org/apache/helix/PropertyKey.java
index 88afc71..b95c790 100644
--- a/helix-core/src/main/java/org/apache/helix/PropertyKey.java
+++ b/helix-core/src/main/java/org/apache/helix/PropertyKey.java
@@ -19,23 +19,6 @@ package org.apache.helix;
  * under the License.
  */
 
-import static org.apache.helix.PropertyType.CONFIGS;
-import static org.apache.helix.PropertyType.CONTROLLER;
-import static org.apache.helix.PropertyType.CURRENTSTATES;
-import static org.apache.helix.PropertyType.ERRORS;
-import static org.apache.helix.PropertyType.ERRORS_CONTROLLER;
-import static org.apache.helix.PropertyType.EXTERNALVIEW;
-import static org.apache.helix.PropertyType.HISTORY;
-import static org.apache.helix.PropertyType.IDEALSTATES;
-import static org.apache.helix.PropertyType.LEADER;
-import static org.apache.helix.PropertyType.LIVEINSTANCES;
-import static org.apache.helix.PropertyType.MESSAGES;
-import static org.apache.helix.PropertyType.MESSAGES_CONTROLLER;
-import static org.apache.helix.PropertyType.PAUSE;
-import static org.apache.helix.PropertyType.STATEMODELDEFS;
-import static org.apache.helix.PropertyType.STATUSUPDATES;
-import static org.apache.helix.PropertyType.STATUSUPDATES_CONTROLLER;
-
 import java.util.Arrays;
 
 import org.apache.helix.model.ClusterConfig;
@@ -50,12 +33,15 @@ import org.apache.helix.model.InstanceConfig;
 import org.apache.helix.model.LeaderHistory;
 import org.apache.helix.model.LiveInstance;
 import org.apache.helix.model.Message;
+import org.apache.helix.model.ParticipantHistory;
 import org.apache.helix.model.PauseSignal;
 import org.apache.helix.model.ResourceConfig;
 import org.apache.helix.model.StateModelDefinition;
 import org.apache.helix.model.StatusUpdate;
 import org.apache.log4j.Logger;
 
+import static org.apache.helix.PropertyType.*;
+
 /**
  * Key allowing for type-safe lookups of and conversions to {@link HelixProperty} objects.
  */
@@ -315,6 +301,11 @@ public class PropertyKey {
       return new PropertyKey(ERRORS, Error.class, _clusterName, instanceName);
     }
 
+    public PropertyKey participantHistory(String instanceName) {
+      return new PropertyKey(INSTANCE_HISTORY, ParticipantHistory.class, _clusterName,
+          instanceName);
+    }
+
     /**
      * Get a property key associated with a specific {@link Message} on an instance
      * @param instanceName

http://git-wip-us.apache.org/repos/asf/helix/blob/8b320514/helix-core/src/main/java/org/apache/helix/PropertyPathBuilder.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/PropertyPathBuilder.java b/helix-core/src/main/java/org/apache/helix/PropertyPathBuilder.java
index 30fc0a9..6e963b6 100644
--- a/helix-core/src/main/java/org/apache/helix/PropertyPathBuilder.java
+++ b/helix-core/src/main/java/org/apache/helix/PropertyPathBuilder.java
@@ -111,6 +111,8 @@ public class PropertyPathBuilder {
         "/{clusterName}/INSTANCES/{instanceName}/ERRORS/{sessionId}/{subPath}");
     addEntry(PropertyType.ERRORS, 5,
         "/{clusterName}/INSTANCES/{instanceName}/ERRORS/{sessionId}/{subPath}/{recordName}");
+    addEntry(PropertyType.INSTANCE_HISTORY, 2,
+        "/{clusterName}/INSTANCES/{instanceName}/HISTORY");
     addEntry(PropertyType.HEALTHREPORT, 2, "/{clusterName}/INSTANCES/{instanceName}/HEALTHREPORT");
     addEntry(PropertyType.HEALTHREPORT, 3,
         "/{clusterName}/INSTANCES/{instanceName}/HEALTHREPORT/{reportName}");
@@ -267,6 +269,16 @@ public class PropertyPathBuilder {
     return String.format("/%s/INSTANCES/%s/ERRORS", clusterName, instanceName);
   }
 
+  public static String instanceError(
+      String clusterName, String instanceName, String sessionId, String resourceName, String
partitionName) {
+    return String.format("/%s/INSTANCES/%s/ERRORS/%s/%s/%s",
+        clusterName, instanceName, sessionId, resourceName, partitionName);
+  }
+
+  public static String instanceHistory(String clusterName, String instanceName) {
+    return String.format("/%s/INSTANCES/%s/HISTORY", clusterName, instanceName);
+  }
+
   public static String instanceStatusUpdate(String clusterName, String instanceName) {
     return String.format("/%s/INSTANCES/%s/STATUSUPDATES", clusterName, instanceName);
   }

http://git-wip-us.apache.org/repos/asf/helix/blob/8b320514/helix-core/src/main/java/org/apache/helix/PropertyType.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/PropertyType.java b/helix-core/src/main/java/org/apache/helix/PropertyType.java
index 32c9fd3..75bdc22 100644
--- a/helix-core/src/main/java/org/apache/helix/PropertyType.java
+++ b/helix-core/src/main/java/org/apache/helix/PropertyType.java
@@ -26,7 +26,7 @@ enum Type {
   CLUSTER,
   INSTANCE,
   CONTROLLER,
-  RESOURCE;
+  RESOURCE
 }
 
 /**
@@ -50,6 +50,7 @@ public enum PropertyType {
   CURRENTSTATES(Type.INSTANCE, true, true, false, false, true),
   STATUSUPDATES(Type.INSTANCE, true, true, false, false, false, true),
   ERRORS(Type.INSTANCE, true, true),
+  INSTANCE_HISTORY(Type.INSTANCE, true, true, true),
   HEALTHREPORT(Type.INSTANCE, true, false, false, false, false, true),
 
   // CONTROLLER PROPERTY

http://git-wip-us.apache.org/repos/asf/helix/blob/8b320514/helix-core/src/main/java/org/apache/helix/manager/zk/ParticipantManagerHelper.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ParticipantManagerHelper.java
b/helix-core/src/main/java/org/apache/helix/manager/zk/ParticipantManagerHelper.java
index 36a669a..19bbd80 100644
--- a/helix-core/src/main/java/org/apache/helix/manager/zk/ParticipantManagerHelper.java
+++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ParticipantManagerHelper.java
@@ -40,10 +40,10 @@ import org.apache.helix.ZNRecord;
 import org.apache.helix.ZNRecordBucketizer;
 import org.apache.helix.messaging.DefaultMessagingService;
 import org.apache.helix.model.CurrentState;
-import org.apache.helix.model.CurrentState.CurrentStateProperty;
 import org.apache.helix.model.HelixConfigScope;
 import org.apache.helix.model.InstanceConfig;
 import org.apache.helix.model.LiveInstance;
+import org.apache.helix.model.ParticipantHistory;
 import org.apache.helix.model.StateModelDefinition;
 import org.apache.helix.model.HelixConfigScope.ConfigScopeProperty;
 import org.apache.helix.model.Message.MessageType;
@@ -219,6 +219,8 @@ public class ParticipantManagerHelper {
         throw new HelixException(errorMessage);
       }
     }
+
+    updateHistory();
   }
 
   /**
@@ -310,7 +312,19 @@ public class ParticipantManagerHelper {
     _stateMachineEngine.registerStateModelFactory(
         DefaultSchedulerMessageHandlerFactory.SCHEDULER_TASK_QUEUE, stStateModelFactory);
     _messagingService.onConnected();
+  }
 
+  /**
+   * Update participant session history.
+   */
+  private void updateHistory() {
+    PropertyKey propertyKey = _keyBuilder.participantHistory(_instanceName);
+    ParticipantHistory history = _dataAccessor.getProperty(propertyKey);
+    if (history == null) {
+      history = new ParticipantHistory(_instanceName);
+    }
+    history.updateHistory(_sessionId);
+    _dataAccessor.setProperty(propertyKey, history);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/helix/blob/8b320514/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java
index c264e7b..629f40a 100644
--- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java
+++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java
@@ -115,6 +115,7 @@ public class ZKHelixAdmin implements HelixAdmin {
     _zkClient.createPersistent(PropertyPathBuilder.instanceCurrentState(clusterName, nodeId),
true);
     _zkClient.createPersistent(PropertyPathBuilder.instanceError(clusterName, nodeId), true);
     _zkClient.createPersistent(PropertyPathBuilder.instanceStatusUpdate(clusterName, nodeId),
true);
+    _zkClient.createPersistent(PropertyPathBuilder.instanceHistory(clusterName, nodeId),
true);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/helix/blob/8b320514/helix-core/src/main/java/org/apache/helix/manager/zk/ZKUtil.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKUtil.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKUtil.java
index 2840dbb..9131e5b 100644
--- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKUtil.java
+++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKUtil.java
@@ -112,6 +112,16 @@ public final class ZKUtil {
           logger.info("Invalid instance setup, missing znode path: " + path);
         }
       }
+
+      if (isValid) {
+        // Create the instance history node if it does not exist.
+        // This is for back-compatibility.
+        String historyPath = PropertyPathBuilder.instanceHistory(clusterName, instanceName);
+        if (!zkclient.exists(historyPath)) {
+          zkclient.createPersistent(historyPath, true);
+        }
+
+      }
       return isValid;
     }
 

http://git-wip-us.apache.org/repos/asf/helix/blob/8b320514/helix-core/src/main/java/org/apache/helix/model/ParticipantHistory.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/model/ParticipantHistory.java b/helix-core/src/main/java/org/apache/helix/model/ParticipantHistory.java
new file mode 100644
index 0000000..585fd59
--- /dev/null
+++ b/helix-core/src/main/java/org/apache/helix/model/ParticipantHistory.java
@@ -0,0 +1,89 @@
+package org.apache.helix.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.helix.HelixProperty;
+import org.apache.helix.ZNRecord;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+/**
+ * The history of participant.
+ */
+public class ParticipantHistory extends HelixProperty {
+  private final static int HISTORY_SIZE = 10;
+  private enum ConfigProperty {
+    TIME,
+    DATE,
+    SESSION,
+    HISTORY
+  }
+
+  public ParticipantHistory(String id) {
+    super(id);
+  }
+
+  public ParticipantHistory(ZNRecord znRecord) {
+    super(znRecord);
+  }
+
+  /**
+   * Update last offline timestamp in participant history.
+   *
+   * @return
+   */
+  public void updateHistory(String sessionId) {
+    List<String> list = _record.getListField(ConfigProperty.HISTORY.name());
+    if (list == null) {
+      list = new ArrayList<String>();
+      _record.setListField(ConfigProperty.HISTORY.name(), list);
+    }
+
+    if (list.size() == HISTORY_SIZE) {
+      list.remove(0);
+    }
+
+    Map<String, String> sessionEntry = new HashMap<String, String>();
+
+    sessionEntry.put(ConfigProperty.SESSION.name(), sessionId);
+
+    long timeMillis = System.currentTimeMillis();
+    sessionEntry.put(ConfigProperty.TIME.name(), String.valueOf(timeMillis));
+
+    DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSS");
+    df.setTimeZone(TimeZone.getTimeZone("UTC"));
+    String dateTime = df.format(new Date(timeMillis));
+    sessionEntry.put(ConfigProperty.DATE.name(), dateTime);
+
+    list.add(sessionEntry.toString());
+  }
+
+  @Override
+  public boolean isValid() {
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/8b320514/helix-core/src/test/java/org/apache/helix/integration/TestInstanceHistory.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/integration/TestInstanceHistory.java
b/helix-core/src/test/java/org/apache/helix/integration/TestInstanceHistory.java
new file mode 100644
index 0000000..64703b8
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/integration/TestInstanceHistory.java
@@ -0,0 +1,56 @@
+package org.apache.helix.integration;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import org.apache.helix.HelixManager;
+import org.apache.helix.HelixManagerFactory;
+import org.apache.helix.InstanceType;
+import org.apache.helix.PropertyKey;
+import org.apache.helix.model.ParticipantHistory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+public class TestInstanceHistory extends ZkStandAloneCMTestBase {
+
+  @Test() public void testInstanceHistory() throws Exception {
+    HelixManager manager = HelixManagerFactory
+        .getZKHelixManager(CLUSTER_NAME, "admin", InstanceType.ADMINISTRATOR, ZK_ADDR);
+    manager.connect();
+
+    PropertyKey.Builder keyBuilder = new PropertyKey.Builder(CLUSTER_NAME);
+    PropertyKey propertyKey = keyBuilder.participantHistory(_participants[0].getInstanceName());
+    ParticipantHistory history = manager.getHelixDataAccessor().getProperty(propertyKey);
+    Assert.assertNotNull(history);
+    List<String> list = history.getRecord().getListField("HISTORY");
+    Assert.assertEquals(list.size(), 1);
+
+    for (int i = 0; i <= 12; i++) {
+      _participants[0].disconnect();
+      _participants[0].connect();
+    }
+
+    history = manager.getHelixDataAccessor().getProperty(propertyKey);
+    Assert.assertNotNull(history);
+    list = history.getRecord().getListField("HISTORY");
+    Assert.assertEquals(list.size(), 10);
+    manager.disconnect();
+  }
+}


Mime
View raw message