You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by jx...@apache.org on 2020/04/23 20:02:47 UTC

[helix] 12/20: Fixed lock path generation

This is an automated email from the ASF dual-hosted git repository.

jxue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/helix.git

commit bd0109534b5a331a0527c985f111e9580a87645e
Author: Molly Gao <mg...@mgao-ld1.linkedin.biz>
AuthorDate: Thu Feb 6 15:46:12 2020 -0800

    Fixed lock path generation
---
 .../java/org/apache/helix/lock/HelixLockScope.java | 160 +++++++++++++++++++++
 .../apache/helix/lock/ZKHelixNonblockingLock.java  |  10 +-
 .../helix/lock/TestZKHelixNonblockingLock.java     |  30 ++--
 3 files changed, 179 insertions(+), 21 deletions(-)

diff --git a/helix-lock/src/main/java/org/apache/helix/lock/HelixLockScope.java b/helix-lock/src/main/java/org/apache/helix/lock/HelixLockScope.java
new file mode 100644
index 0000000..9fc12fc
--- /dev/null
+++ b/helix-lock/src/main/java/org/apache/helix/lock/HelixLockScope.java
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+package org.apache.helix.lock;
+
+import java.util.List;
+
+import org.apache.helix.util.StringTemplate;
+
+
+/**
+ *  Defines the various scopes of Helix locks, and how they are represented on Zookeeper
+ */
+public class HelixLockScope {
+
+  /**
+   * Define various properties of Helix lock, and associate them with the number of arguments required for getting znode path
+   */
+  public enum LockScopeProperty {
+
+    PARTICIPANT(1, 0),
+
+    RESOURCE(2, 1),
+
+    PARTITION(3, 2);
+
+    final int _zkPathArgNum;
+    final int _argumentPos;
+
+    private LockScopeProperty(int zkPathArgNum, int argumentPos) {
+      _zkPathArgNum = zkPathArgNum;
+      _argumentPos = argumentPos;
+    }
+
+    /**
+     * Get the number of template arguments required to generate a full path
+     * @return number of template arguments in the path
+     */
+    public int getZkPathArgNum() {
+      return _zkPathArgNum;
+    }
+
+    /**
+     * Get the position of this argument from the input that used to generate the scope
+     * @return the number of position of value for this property in the list of keys input
+     */
+    public int getArgumentPos() {
+      return _argumentPos;
+    }
+  }
+
+  /**
+   * string templates to generate znode path
+   */
+  private static final StringTemplate template = new StringTemplate();
+
+  static {
+    template.addEntry(HelixLockScope.LockScopeProperty.PARTICIPANT, 1, "/{participantName}");
+    template.addEntry(HelixLockScope.LockScopeProperty.RESOURCE, 2,
+        "/{participantName}/{resourceName}");
+    template.addEntry(HelixLockScope.LockScopeProperty.PARTITION, 3,
+        "/{participantName}/{resourceName}/{partitionName}");
+  }
+
+  private final HelixLockScope.LockScopeProperty _type;
+  private final String _participantName;
+  private final String _resourceName;
+  private final String _partitionName;
+
+  private final String _zkPath;
+
+  /**
+   * Initialize with a type of scope and unique identifiers
+   * @param type the scope
+   * @param zkPathKeys keys identifying a ZNode location
+   */
+  public HelixLockScope(HelixLockScope.LockScopeProperty type, List<String> zkPathKeys) {
+
+    if (zkPathKeys.size() != type.getZkPathArgNum()) {
+      throw new IllegalArgumentException(
+          type + " requires " + type.getZkPathArgNum() + " arguments to get znode, but was: "
+              + zkPathKeys);
+    }
+
+    _type = type;
+
+    //Initialize the name fields for various scope
+    _participantName = zkPathKeys.get(LockScopeProperty.PARTICIPANT.getArgumentPos());
+
+    if (type.getZkPathArgNum() >= LockScopeProperty.RESOURCE.getZkPathArgNum()) {
+      _resourceName = zkPathKeys.get(LockScopeProperty.RESOURCE.getArgumentPos());
+    } else {
+      _resourceName = null;
+    }
+
+    if (type.getZkPathArgNum() >= LockScopeProperty.PARTITION.getZkPathArgNum()) {
+      _partitionName = zkPathKeys.get(LockScopeProperty.PARTITION.getArgumentPos());
+    } else {
+      _partitionName = null;
+    }
+
+    _zkPath = template.instantiate(type, zkPathKeys.toArray(new String[0]));
+  }
+
+  /**
+   * Get the scope
+   * @return the type of scope
+   */
+  public HelixLockScope.LockScopeProperty getType() {
+    return _type;
+  }
+
+  /**
+   * Get the participant name if it exists
+   * @return the participant name
+   */
+  public String getParticipantName() {
+    return _participantName;
+  }
+
+  /**
+   * Get the resource name if it exists
+   * @return the resource name
+   */
+  public String getResourceName() {
+    return _resourceName;
+  }
+
+  /**
+   * Get the partition name if it exists
+   * @return the partition name
+   */
+  public String getPartitionName() {
+    return _partitionName;
+  }
+
+  /**
+   * Get the path to the corresponding ZNode
+   * @return a Zookeeper path
+   */
+  public String getZkPath() {
+    return _zkPath;
+  }
+}
diff --git a/helix-lock/src/main/java/org/apache/helix/lock/ZKHelixNonblockingLock.java b/helix-lock/src/main/java/org/apache/helix/lock/ZKHelixNonblockingLock.java
index 0424177..0573228 100644
--- a/helix-lock/src/main/java/org/apache/helix/lock/ZKHelixNonblockingLock.java
+++ b/helix-lock/src/main/java/org/apache/helix/lock/ZKHelixNonblockingLock.java
@@ -28,6 +28,8 @@ import org.I0Itec.zkclient.exception.ZkNoNodeException;
 import org.apache.helix.AccessOption;
 import org.apache.helix.BaseDataAccessor;
 import org.apache.helix.HelixException;
+import org.apache.helix.PropertyPathBuilder;
+import org.apache.helix.PropertyType;
 import org.apache.helix.ZNRecord;
 import org.apache.helix.api.exceptions.HelixMetaDataAccessException;
 import org.apache.helix.manager.zk.ZkBaseDataAccessor;
@@ -48,8 +50,7 @@ public class ZKHelixNonblockingLock implements HelixLock {
 
   private static final Logger LOG = Logger.getLogger(ZKHelixNonblockingLock.class);
 
-  private static final String LOCK_ROOT = "LOCKS";
-  private static final String PATH_DELIMITER = "/";
+  private static final String LOCK_ROOT = "/LOCK";
   private final String _lockPath;
   private final String _userId;
   private final long _timeout;
@@ -65,10 +66,9 @@ public class ZKHelixNonblockingLock implements HelixLock {
    * @param lockMsg the reason for having this lock
    * @param userId a universal unique userId for lock owner identity
    */
-  public ZKHelixNonblockingLock(String clusterName, HelixConfigScope scope, String zkAddress,
+  public ZKHelixNonblockingLock(String clusterName, HelixLockScope scope, String zkAddress,
       Long timeout, String lockMsg, String userId) {
-    this(PATH_DELIMITER +  String.join(PATH_DELIMITER, clusterName, LOCK_ROOT, scope.getZkPath()), zkAddress, timeout, lockMsg,
-        userId);
+    this("/" + clusterName + LOCK_ROOT + scope.getZkPath(), zkAddress, timeout, lockMsg, userId);
   }
 
   /**
diff --git a/helix-lock/src/test/java/org/apache/helix/lock/TestZKHelixNonblockingLock.java b/helix-lock/src/test/java/org/apache/helix/lock/TestZKHelixNonblockingLock.java
index 29f84ae..96a15b3 100644
--- a/helix-lock/src/test/java/org/apache/helix/lock/TestZKHelixNonblockingLock.java
+++ b/helix-lock/src/test/java/org/apache/helix/lock/TestZKHelixNonblockingLock.java
@@ -26,17 +26,12 @@ import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.Callable;
 
-import org.apache.helix.AccessOption;
 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.manager.zk.TestWtCacheAsyncOpMultiThread;
-import org.apache.helix.manager.zk.ZKHelixDataAccessor;
-import org.apache.helix.manager.zk.ZkCacheBaseDataAccessor;
-import org.apache.helix.model.HelixConfigScope;
-import org.apache.helix.model.HelixConfigScope.ConfigScopeProperty;
-import org.apache.helix.model.builder.HelixConfigScopeBuilder;
+import org.apache.helix.common.ZkTestBase;
 import org.apache.zookeeper.CreateMode;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
@@ -44,16 +39,15 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 
-public class TestZKHelixNonblockingLock extends ZkUnitTestBase {
+public class TestZKHelixNonblockingLock extends ZkTestBase {
 
-  private final String _className = TestHelper.getTestClassName();
-  private final String _methodName = TestHelper.getTestMethodName();
-  private final String _clusterName = _className + "_" + _methodName;
+  private final String _clusterName = TestHelper.getTestClassName();
+  private final String _lockRoot = "/LOCK";
   private final String _lockMessage = "Test";
   private String _lockPath;
   private ZKHelixNonblockingLock _lock;
   private String _userId;
-  private HelixConfigScope _participantScope;
+  private HelixLockScope _participantScope;
 
   @BeforeClass
   public void beforeClass() throws Exception {
@@ -63,10 +57,14 @@ public class TestZKHelixNonblockingLock extends ZkUnitTestBase {
     TestHelper.setupCluster(_clusterName, ZK_ADDR, 12918, "localhost", "TestDB", 1, 10, 5, 3,
         "MasterSlave", true);
     _userId = UUID.randomUUID().toString();
-    _participantScope =
-        new HelixConfigScopeBuilder(ConfigScopeProperty.PARTICIPANT).forCluster(_clusterName)
-            .forParticipant("localhost_12918").build();
-    _lockPath = "/" + _clusterName + '/' + "LOCKS" + '/' + _participantScope.getZkPath();
+
+    List<String> pathKeys = new ArrayList<>();
+    pathKeys.add("participant_name");
+    pathKeys.add("resource_name");
+    pathKeys.add("partition_name");
+
+    _participantScope = new HelixLockScope(HelixLockScope.LockScopeProperty.PARTITION, pathKeys);
+    _lockPath = "/" + _clusterName + _lockRoot + _participantScope.getZkPath();
     _lock = new ZKHelixNonblockingLock(_clusterName, _participantScope, ZK_ADDR, Long.MAX_VALUE,
         _lockMessage, _userId);
   }