helix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject [1/2] helix git commit: Add support of setting/updating Cluster/Resource/Instance configs in ConfigAccessor.
Date Tue, 23 May 2017 21:28:47 GMT
Repository: helix
Updated Branches:
  refs/heads/helix-0.6.x 8cf80a9f8 -> 8ba068e7b


Add support of setting/updating Cluster/Resource/Instance configs in ConfigAccessor.


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

Branch: refs/heads/helix-0.6.x
Commit: 7c92bf543571daac555f5d8b933805dddced7ca5
Parents: 8cf80a9
Author: Lei Xia <lxia@linkedin.com>
Authored: Tue May 23 12:27:23 2017 -0700
Committer: Lei Xia <lxia@linkedin.com>
Committed: Tue May 23 12:27:23 2017 -0700

----------------------------------------------------------------------
 .../java/org/apache/helix/ConfigAccessor.java   | 248 +++++++++++++++++++
 .../main/java/org/apache/helix/ZNRecord.java    |  19 ++
 .../java/org/apache/helix/ZNRecordDelta.java    |   5 +-
 .../org/apache/helix/manager/zk/ZKUtil.java     |  31 ++-
 .../org/apache/helix/model/ClusterConfig.java   |  15 ++
 .../integration/ZkIntegrationTestBase.java      |  12 +-
 .../org/apache/helix/manager/zk/TestZKUtil.java | 113 ++++++---
 7 files changed, 401 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/helix/blob/7c92bf54/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java b/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java
index 34aef49..27a30cb 100644
--- a/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java
+++ b/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java
@@ -27,11 +27,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 
+import org.apache.helix.model.ClusterConfig;
 import org.apache.helix.model.ConfigScope;
 import org.apache.helix.model.HelixConfigScope;
 import org.apache.helix.model.HelixConfigScope.ConfigScopeProperty;
 import org.apache.helix.manager.zk.ZKUtil;
 import org.apache.helix.manager.zk.ZkClient;
+import org.apache.helix.model.InstanceConfig;
+import org.apache.helix.model.ResourceConfig;
+import org.apache.helix.model.builder.HelixConfigScopeBuilder;
 import org.apache.helix.util.StringTemplate;
 import org.apache.log4j.Logger;
 
@@ -509,4 +513,248 @@ public class ConfigAccessor {
     }
     return retKeys;
   }
+
+  private ZNRecord getConfigZnRecord(HelixConfigScope scope) {
+    String clusterName = scope.getClusterName();
+    if (!ZKUtil.isClusterSetup(clusterName, zkClient)) {
+      throw new HelixException("fail to get configs. cluster " + clusterName + " is not setup
yet");
+    }
+
+    return zkClient.readData(scope.getZkPath(), true);
+  }
+
+  /**
+   * Get ClusterConfig of the given cluster.
+   *
+   * @param clusterName
+   *
+   * @return
+   */
+  public ClusterConfig getClusterConfig(String clusterName) {
+    if (!ZKUtil.isClusterSetup(clusterName, zkClient)) {
+      throw new HelixException("fail to get config. cluster: " + clusterName + " is NOT setup.");
+    }
+
+    HelixConfigScope scope =
+        new HelixConfigScopeBuilder(ConfigScopeProperty.CLUSTER).forCluster(clusterName).build();
+    ZNRecord record = getConfigZnRecord(scope);
+
+    if (record == null) {
+      LOG.warn("No config found at " + scope.getZkPath());
+      return null;
+    }
+
+    return new ClusterConfig(record);
+  }
+
+  /**
+   * Set ClusterConfig of the given cluster.
+   * The current Cluster config will be replaced with the given clusterConfig.
+   * WARNING: This is not thread-safe or concurrent updates safe.
+   *
+   * @param clusterName
+   * @param clusterConfig
+   *
+   * @return
+   */
+  public void setClusterConfig(String clusterName, ClusterConfig clusterConfig) {
+    updateClusterConfig(clusterName, clusterConfig, true);
+  }
+
+  /**
+   * Update ClusterConfig of the given cluster.
+   * The value of field in current config will be replaced with the value of the same field
in given config if it
+   * presents. If there is new field in given config but not in current config, the field
will be added into
+   * the current config..
+   * The list fields and map fields will be replaced as a single entry.
+   *
+   * The current Cluster config will be replaced with the given clusterConfig.
+   * WARNING: This is not thread-safe or concurrent updates safe.
+   *
+   * @param clusterName
+   * @param clusterConfig
+   *
+   * @return
+   */
+  public void updateClusterConfig(String clusterName, ClusterConfig clusterConfig) {
+    updateClusterConfig(clusterName, clusterConfig, false);
+  }
+
+
+  private void updateClusterConfig(String clusterName, ClusterConfig clusterConfig, boolean
overwrite) {
+    if (!ZKUtil.isClusterSetup(clusterName, zkClient)) {
+      throw new HelixException("fail to update config. cluster: " + clusterName + " is NOT
setup.");
+    }
+
+    HelixConfigScope scope =
+        new HelixConfigScopeBuilder(ConfigScopeProperty.CLUSTER).forCluster(clusterName).build();
+    String zkPath = scope.getZkPath();
+
+    if (overwrite) {
+      ZKUtil.createOrReplace(zkClient, zkPath, clusterConfig.getRecord(), true);
+    } else {
+      ZKUtil.createOrUpdate(zkClient, zkPath, clusterConfig.getRecord(), true, true);
+    }
+  }
+
+  /**
+   * Get resource config for given resource in given cluster.
+   *
+   * @param clusterName
+   * @param resourceName
+   *
+   * @return
+   */
+  public ResourceConfig getResourceConfig(String clusterName, String resourceName) {
+    HelixConfigScope scope =
+        new HelixConfigScopeBuilder(ConfigScopeProperty.RESOURCE).forCluster(clusterName)
+            .forResource(resourceName).build();
+    ZNRecord record = getConfigZnRecord(scope);
+
+    if (record == null) {
+      LOG.warn("No config found at " + scope.getZkPath());
+      return null;
+    }
+
+    return new ResourceConfig(record);
+  }
+
+  /**
+   * Set config of the given resource.
+   * The current Resource config will be replaced with the given clusterConfig.
+   *
+   * WARNING: This is not thread-safe or concurrent updates safe.
+   *
+   * @param clusterName
+   * @param resourceName
+   * @param resourceConfig
+   *
+   * @return
+   */
+  public void setResourceConfig(String clusterName, String resourceName,
+      ResourceConfig resourceConfig) {
+    updateResourceConfig(clusterName, resourceName, resourceConfig, true);
+  }
+
+  /**
+   * Update ResourceConfig of the given resource.
+   * The value of field in current config will be replaced with the value of the same field
in given config if it
+   * presents. If there is new field in given config but not in current config, the field
will be added into
+   * the current config..
+   * The list fields and map fields will be replaced as a single entry.
+   *
+   * The current Cluster config will be replaced with the given clusterConfig.
+   * WARNING: This is not thread-safe or concurrent updates safe.
+   *
+   * @param clusterName
+   * @param resourceName
+   * @param resourceConfig
+   *
+   * @return
+   */
+  public void updateResourceConfig(String clusterName, String resourceName,
+      ResourceConfig resourceConfig) {
+    updateResourceConfig(clusterName, resourceName, resourceConfig, false);
+  }
+
+  private void updateResourceConfig(String clusterName, String resourceName,
+      ResourceConfig resourceConfig, boolean overwrite) {
+    if (!ZKUtil.isClusterSetup(clusterName, zkClient)) {
+      throw new HelixException("fail to setup config. cluster: " + clusterName + " is NOT
setup.");
+    }
+
+    HelixConfigScope scope =
+        new HelixConfigScopeBuilder(ConfigScopeProperty.RESOURCE).forCluster(clusterName)
+            .forResource(resourceName).build();
+    String zkPath = scope.getZkPath();
+
+    if (overwrite) {
+      ZKUtil.createOrReplace(zkClient, zkPath, resourceConfig.getRecord(), true);
+    } else {
+      ZKUtil.createOrUpdate(zkClient, zkPath, resourceConfig.getRecord(), true, true);
+    }
+  }
+
+  /**
+   * Get instance config for given resource in given cluster.
+   *
+   * @param clusterName
+   * @param instanceName
+   *
+   * @return
+   */
+  public InstanceConfig getInstanceConfig(String clusterName, String instanceName) {
+    if (!ZKUtil.isInstanceSetup(zkClient, clusterName, instanceName, InstanceType.PARTICIPANT))
{
+      throw new HelixException(
+          "fail to get config. instance: " + instanceName + " is NOT setup in cluster: "
+              + clusterName);
+    }
+
+    HelixConfigScope scope =
+        new HelixConfigScopeBuilder(ConfigScopeProperty.PARTICIPANT).forCluster(clusterName)
+            .forParticipant(instanceName).build();
+    ZNRecord record = getConfigZnRecord(scope);
+
+    if (record == null) {
+      LOG.warn("No config found at " + scope.getZkPath());
+      return null;
+    }
+
+    return new InstanceConfig(record);
+  }
+
+  /**
+   * Set config of the given instance config.
+   * The current instance config will be replaced with the given instanceConfig.
+   * WARNING: This is not thread-safe or concurrent updates safe.
+   *
+   * @param clusterName
+   * @param instanceName
+   * @param instanceConfig
+   *
+   * @return
+   */
+  public void setInstanceConfig(String clusterName, String instanceName,
+      InstanceConfig instanceConfig) {
+    updateInstanceConfig(clusterName, instanceName, instanceConfig, true);
+
+  }
+
+  /**
+   * Update ResourceConfig of the given resource. The value of field in current config will
be
+   * replaced with the value of the same field in given config if it presents. If there is
new field
+   * in given config but not in current config, the field will be added into the current
config..
+   * The list fields and map fields will be replaced as a single entry.
+   * The current Cluster config will be replaced with the given clusterConfig. WARNING: This
is not
+   * thread-safe or concurrent updates safe.
+   * *
+   *
+   * @param clusterName
+   * @param instanceName
+   * @param instanceConfig
+   *
+   * @return
+   */
+  public void updateInstanceConfig(String clusterName, String instanceName,
+      InstanceConfig instanceConfig) {
+    updateInstanceConfig(clusterName, instanceName, instanceConfig, false);
+  }
+
+  private void updateInstanceConfig(String clusterName, String instanceName,
+      InstanceConfig instanceConfig, boolean overwrite) {
+    if (!ZKUtil.isClusterSetup(clusterName, zkClient)) {
+      throw new HelixException("fail to setup config. cluster: " + clusterName + " is NOT
setup.");
+    }
+
+    HelixConfigScope scope =
+        new HelixConfigScopeBuilder(ConfigScopeProperty.PARTICIPANT).forCluster(clusterName)
+            .forParticipant(instanceName).build();
+    String zkPath = scope.getZkPath();
+
+    if (overwrite) {
+      ZKUtil.createOrReplace(zkClient, zkPath, instanceConfig.getRecord(), true);
+    } else {
+      ZKUtil.createOrUpdate(zkClient, zkPath, instanceConfig.getRecord(), true, true);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/helix/blob/7c92bf54/helix-core/src/main/java/org/apache/helix/ZNRecord.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/ZNRecord.java b/helix-core/src/main/java/org/apache/helix/ZNRecord.java
index 3ac9485..52bd5be 100644
--- a/helix-core/src/main/java/org/apache/helix/ZNRecord.java
+++ b/helix-core/src/main/java/org/apache/helix/ZNRecord.java
@@ -512,7 +512,24 @@ public class ZNRecord {
   }
 
   /**
+   * Replace functionality is used to update this ZNRecord with the given ZNRecord. The value
of a
+   * field in this record will be replaced with the value of the same field in given record
if it
+   * presents. If there is new field in given ZNRecord but not in this record, add that field
into
+   * this record. The list fields and map fields will be replaced as a single entry.
+   *
+   * @param record
+   */
+  public void update(ZNRecord record) {
+    if (record != null) {
+      simpleFields.putAll(record.simpleFields);
+      listFields.putAll(record.listFields);
+      mapFields.putAll(record.mapFields);
+    }
+  }
+
+  /**
    * Merge in a {@link ZNRecordDelta} corresponding to its merge policy
+   *
    * @param delta
    */
   void merge(ZNRecordDelta delta) {
@@ -520,6 +537,8 @@ public class ZNRecord {
       merge(delta.getRecord());
     } else if (delta.getMergeOperation() == MergeOperation.SUBTRACT) {
       subtract(delta.getRecord());
+    } else if (delta.getMergeOperation() == MergeOperation.UPDATE) {
+      update(delta.getRecord());
     }
   }
 

http://git-wip-us.apache.org/repos/asf/helix/blob/7c92bf54/helix-core/src/main/java/org/apache/helix/ZNRecordDelta.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/ZNRecordDelta.java b/helix-core/src/main/java/org/apache/helix/ZNRecordDelta.java
index eff725d..616e1f5 100644
--- a/helix-core/src/main/java/org/apache/helix/ZNRecordDelta.java
+++ b/helix-core/src/main/java/org/apache/helix/ZNRecordDelta.java
@@ -28,7 +28,8 @@ public class ZNRecordDelta {
    */
   public enum MergeOperation {
     ADD,
-    SUBTRACT
+    SUBTRACT,
+    UPDATE
   };
 
   /**
@@ -44,7 +45,7 @@ public class ZNRecordDelta {
   /**
    * Initialize the delta with a record and the update mode
    * @param record
-   * @param _mergeOperation
+   * @param mergeOperation
    */
   public ZNRecordDelta(ZNRecord record, MergeOperation mergeOperation) {
     _record = new ZNRecord(record);

http://git-wip-us.apache.org/repos/asf/helix/blob/7c92bf54/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 9131e5b..2b4cfb2 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
@@ -196,7 +196,7 @@ public final class ZKUtil {
     }
   }
 
-  public static void createOrUpdate(ZkClient client, String path, final ZNRecord record,
+  public static void createOrMerge(ZkClient client, String path, final ZNRecord record,
       final boolean persistent, final boolean mergeOnUpdate) {
     int retryCount = 0;
     while (retryCount < RETRYLIMIT) {
@@ -232,6 +232,35 @@ public final class ZKUtil {
     }
   }
 
+  public static void createOrUpdate(ZkClient client, String path, final ZNRecord record,
+      final boolean persistent, final boolean mergeOnUpdate) {
+    int retryCount = 0;
+    while (retryCount < RETRYLIMIT) {
+      try {
+        if (client.exists(path)) {
+          DataUpdater<ZNRecord> updater = new DataUpdater<ZNRecord>() {
+            @Override public ZNRecord update(ZNRecord currentData) {
+              if (currentData != null && mergeOnUpdate) {
+                currentData.update(record);
+                return currentData;
+              }
+              return record;
+            }
+          };
+          client.updateDataSerialized(path, updater);
+        } else {
+          CreateMode mode = (persistent) ? CreateMode.PERSISTENT : CreateMode.EPHEMERAL;
+          client.create(path, record, mode);
+        }
+        break;
+      } catch (Exception e) {
+        retryCount = retryCount + 1;
+        logger.warn("Exception trying to update " + path + " Exception:" + e.getMessage()
+            + ". Will retry.");
+      }
+    }
+  }
+
   public static void asyncCreateOrUpdate(ZkClient client, String path, final ZNRecord record,
       final boolean persistent, final boolean mergeOnUpdate) {
     try {

http://git-wip-us.apache.org/repos/asf/helix/blob/7c92bf54/helix-core/src/main/java/org/apache/helix/model/ClusterConfig.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/model/ClusterConfig.java b/helix-core/src/main/java/org/apache/helix/model/ClusterConfig.java
index 2be7ee1..3796f36 100644
--- a/helix-core/src/main/java/org/apache/helix/model/ClusterConfig.java
+++ b/helix-core/src/main/java/org/apache/helix/model/ClusterConfig.java
@@ -68,6 +68,21 @@ public class ClusterConfig extends HelixProperty {
   }
 
   /**
+   * Enable/Disable persist best possible assignment in a resource's idealstate.
+   *
+   * @return
+   */
+  public void setPersistBestPossibleAssignment(Boolean enable) {
+    if (enable == null) {
+      _record.getSimpleFields()
+          .remove(ClusterConfigProperty.PERSIST_BEST_POSSIBLE_ASSIGNMENT.toString());
+    } else {
+      _record.setBooleanField(ClusterConfigProperty.PERSIST_BEST_POSSIBLE_ASSIGNMENT.toString(),
+          enable);
+    }
+  }
+
+  /**
    *
    * @return
    */

http://git-wip-us.apache.org/repos/asf/helix/blob/7c92bf54/helix-core/src/test/java/org/apache/helix/integration/ZkIntegrationTestBase.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/integration/ZkIntegrationTestBase.java
b/helix-core/src/test/java/org/apache/helix/integration/ZkIntegrationTestBase.java
index 0edd4d3..08a5730 100644
--- a/helix-core/src/test/java/org/apache/helix/integration/ZkIntegrationTestBase.java
+++ b/helix-core/src/test/java/org/apache/helix/integration/ZkIntegrationTestBase.java
@@ -104,15 +104,11 @@ public class ZkIntegrationTestBase {
   }
 
   protected void enablePersistBestPossibleAssignment(ZkClient zkClient, String clusterName,
-      Boolean enable) {
+      Boolean enabled) {
     ConfigAccessor configAccessor = new ConfigAccessor(zkClient);
-    HelixConfigScope clusterScope =
-        new HelixConfigScopeBuilder(HelixConfigScope.ConfigScopeProperty.CLUSTER)
-            .forCluster(clusterName).build();
-
-    configAccessor.set(clusterScope,
-        ClusterConfig.ClusterConfigProperty.PERSIST_BEST_POSSIBLE_ASSIGNMENT.name(),
-        enable.toString());
+    ClusterConfig clusterConfig = configAccessor.getClusterConfig(clusterName);
+    clusterConfig.setPersistBestPossibleAssignment(enabled);
+    configAccessor.setClusterConfig(clusterName, clusterConfig);
   }
 
   protected void disableDelayRebalanceInCluster(ZkClient zkClient, String clusterName,

http://git-wip-us.apache.org/repos/asf/helix/blob/7c92bf54/helix-core/src/test/java/org/apache/helix/manager/zk/TestZKUtil.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/manager/zk/TestZKUtil.java b/helix-core/src/test/java/org/apache/helix/manager/zk/TestZKUtil.java
index ed604fa..19d30a6 100644
--- a/helix-core/src/test/java/org/apache/helix/manager/zk/TestZKUtil.java
+++ b/helix-core/src/test/java/org/apache/helix/manager/zk/TestZKUtil.java
@@ -19,16 +19,15 @@ package org.apache.helix.manager.zk;
  * under the License.
  */
 
-import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
-
+import java.util.Map;
 import org.apache.helix.PropertyPathBuilder;
-import org.apache.helix.PropertyType;
 import org.apache.helix.TestHelper;
 import org.apache.helix.ZNRecord;
 import org.apache.helix.ZkUnitTestBase;
-import org.apache.helix.model.HelixConfigScope.ConfigScopeProperty;
 import org.apache.log4j.Logger;
 import org.testng.AssertJUnit;
 import org.testng.annotations.AfterClass;
@@ -42,7 +41,7 @@ public class TestZKUtil extends ZkUnitTestBase {
   ZkClient _zkClient;
 
   @BeforeClass()
-  public void beforeClass() throws IOException, Exception {
+  public void beforeClass() throws Exception {
     _zkClient = new ZkClient(ZK_ADDR);
     _zkClient.setZkSerializer(new ZNRecordSerializer());
     if (_zkClient.exists("/" + clusterName)) {
@@ -79,9 +78,7 @@ public class TestZKUtil extends ZkUnitTestBase {
     List<ZNRecord> list = new ArrayList<ZNRecord>();
     list.add(new ZNRecord("id1"));
     list.add(new ZNRecord("id2"));
-    String path =
-        PropertyPathBuilder.getPath(PropertyType.CONFIGS, clusterName,
-            ConfigScopeProperty.PARTICIPANT.toString());
+    String path = PropertyPathBuilder.instanceConfig(clusterName);
     ZKUtil.createChildren(_zkClient, path, list);
     list = ZKUtil.getChildren(_zkClient, path);
     AssertJUnit.assertEquals(2, list.size());
@@ -96,63 +93,117 @@ public class TestZKUtil extends ZkUnitTestBase {
 
   @Test()
   public void testUpdateIfExists() {
-    String path =
-        PropertyPathBuilder.getPath(PropertyType.CONFIGS, clusterName,
-            ConfigScopeProperty.PARTICIPANT.toString(), "id3");
+    String path = PropertyPathBuilder.instanceConfig(clusterName, "id3");
     ZNRecord record = new ZNRecord("id4");
     ZKUtil.updateIfExists(_zkClient, path, record, false);
     AssertJUnit.assertFalse(_zkClient.exists(path));
     _zkClient.createPersistent(path);
     ZKUtil.updateIfExists(_zkClient, path, record, false);
     AssertJUnit.assertTrue(_zkClient.exists(path));
-    record = _zkClient.<ZNRecord> readData(path);
+    record = _zkClient.readData(path);
     AssertJUnit.assertEquals("id4", record.getId());
   }
 
   @Test()
   public void testSubtract() {
-    String path =
-        PropertyPathBuilder.getPath(PropertyType.CONFIGS, clusterName,
-            ConfigScopeProperty.PARTICIPANT.toString(), "id5");
+    String path = PropertyPathBuilder.instanceConfig(clusterName, "id5");
     ZNRecord record = new ZNRecord("id5");
     record.setSimpleField("key1", "value1");
     _zkClient.createPersistent(path, record);
     ZKUtil.subtract(_zkClient, path, record);
-    record = _zkClient.<ZNRecord> readData(path);
+    record = _zkClient.readData(path);
     AssertJUnit.assertNull(record.getSimpleField("key1"));
   }
 
   @Test()
   public void testNullChildren() {
-    String path =
-        PropertyPathBuilder.getPath(PropertyType.CONFIGS, clusterName,
-            ConfigScopeProperty.PARTICIPANT.toString(), "id6");
+    String path = PropertyPathBuilder.instanceConfig(clusterName, "id6");
     ZKUtil.createChildren(_zkClient, path, (List<ZNRecord>) null);
   }
 
   @Test()
-  public void testCreateOrUpdate() {
-    String path =
-        PropertyPathBuilder.getPath(PropertyType.CONFIGS, clusterName,
-            ConfigScopeProperty.PARTICIPANT.toString(), "id7");
+  public void testCreateOrMerge() {
+    String path = PropertyPathBuilder.instanceConfig(clusterName, "id7");
     ZNRecord record = new ZNRecord("id7");
-    ZKUtil.createOrUpdate(_zkClient, path, record, true, true);
-    record = _zkClient.<ZNRecord> readData(path);
-    AssertJUnit.assertEquals("id7", record.getId());
+    List<String> list = Arrays.asList("value1");
+    record.setListField("list", list);
+    ZKUtil.createOrMerge(_zkClient, path, record, true, true);
+    record = _zkClient.readData(path);
+    AssertJUnit.assertEquals(list, record.getListField("list"));
+
+    record = new ZNRecord("id7");
+    List<String> list2 = Arrays.asList("value2");
+    record.setListField("list", list2);
+    ZKUtil.createOrMerge(_zkClient, path, record, true, true);
+    record = _zkClient.readData(path);
+    AssertJUnit.assertEquals(Arrays.asList("value1", "value2"), record.getListField("list"));
+
+    Map<String, String> map = new HashMap<String, String>() {{put("k1", "v1");}};
+    record.setMapField("map", map);
+    ZKUtil.createOrMerge(_zkClient, path, record, true, true);
+    record = _zkClient.readData(path);
+    AssertJUnit.assertEquals(map, record.getMapField("map"));
+
+    record = new ZNRecord("id7");
+    Map<String, String> map2 = new HashMap<String, String>() {{put("k2", "v2");}};
+    record.setMapField("map", map2);
+    ZKUtil.createOrMerge(_zkClient, path, record, true, true);
+    record = _zkClient.readData(path);
+    AssertJUnit.assertEquals(new HashMap<String, String>() {{
+      put("k1", "v1");
+      put("k2", "v2");
+    }}, record.getMapField("map"));
   }
 
   @Test()
   public void testCreateOrReplace() {
-    String path =
-        PropertyPathBuilder.getPath(PropertyType.CONFIGS, clusterName,
-            ConfigScopeProperty.PARTICIPANT.toString(), "id8");
+    String path = PropertyPathBuilder.instanceConfig(clusterName, "id8");
     ZNRecord record = new ZNRecord("id8");
     ZKUtil.createOrReplace(_zkClient, path, record, true);
-    record = _zkClient.<ZNRecord> readData(path);
+    record = _zkClient.readData(path);
     AssertJUnit.assertEquals("id8", record.getId());
     record = new ZNRecord("id9");
     ZKUtil.createOrReplace(_zkClient, path, record, true);
-    record = _zkClient.<ZNRecord> readData(path);
+    record = _zkClient.readData(path);
     AssertJUnit.assertEquals("id9", record.getId());
   }
+
+  @Test()
+  public void testCreateOrUpdate() {
+    String path = PropertyPathBuilder.instanceConfig(clusterName, "id7");
+    ZNRecord record = new ZNRecord("id7");
+    ZKUtil.createOrMerge(_zkClient, path, record, true, true);
+    record = _zkClient.readData(path);
+    AssertJUnit.assertEquals("id7", record.getId());
+
+    record = new ZNRecord("id7");
+    List<String> list = Arrays.asList("value1", "value2");
+    record.setListField("list", list);
+    ZKUtil.createOrUpdate(_zkClient, path, record, true, true);
+    record = _zkClient.readData(path);
+    AssertJUnit.assertEquals(list, record.getListField("list"));
+
+    record = new ZNRecord("id7");
+    List<String> list2 = Arrays.asList("value3", "value4");
+    record.setListField("list", list2);
+    ZKUtil.createOrUpdate(_zkClient, path, record, true, true);
+    record = _zkClient.readData(path);
+    AssertJUnit.assertEquals(list2, record.getListField("list"));
+
+
+    Map<String, String> map = new HashMap<String, String>() {{put("k1", "v1");}};
+    record.setMapField("map", map);
+    ZKUtil.createOrUpdate(_zkClient, path, record, true, true);
+    record = _zkClient.readData(path);
+    AssertJUnit.assertEquals(map, record.getMapField("map"));
+
+    record = new ZNRecord("id7");
+    Map<String, String> map2 = new HashMap<String, String>() {{put("k2", "v2");}};
+    record.setMapField("map", map2);
+    ZKUtil.createOrUpdate(_zkClient, path, record, true, true);
+    record = _zkClient.readData(path);
+    AssertJUnit.assertEquals(new HashMap<String, String>() {{
+      put("k2", "v2");
+    }}, record.getMapField("map"));
+  }
 }


Mime
View raw message