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:50 UTC

[helix] 15/20: refactor LockInfo and some updates on the HelixLockScope

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 4746a7e20fede793be7dd540501c57db7d421a87
Author: Molly Gao <mg...@mgao-mn1.linkedin.biz>
AuthorDate: Mon Feb 10 18:31:26 2020 -0800

    refactor LockInfo and some updates on the HelixLockScope
---
 .../main/java/org/apache/helix/lock/HelixLock.java |   2 +-
 .../java/org/apache/helix/lock/HelixLockScope.java |  27 ++--
 .../main/java/org/apache/helix/lock/LockInfo.java  | 152 +++++++++++++++++++--
 .../apache/helix/lock/ZKHelixNonblockingLock.java  |  87 ++++++------
 .../helix/lock/ZKHelixNonblockingLockInfo.java     |  92 -------------
 .../helix/lock/TestZKHelixNonblockingLock.java     |  21 ++-
 6 files changed, 203 insertions(+), 178 deletions(-)

diff --git a/helix-lock/src/main/java/org/apache/helix/lock/HelixLock.java b/helix-lock/src/main/java/org/apache/helix/lock/HelixLock.java
index ec425f6..1cd9e60 100644
--- a/helix-lock/src/main/java/org/apache/helix/lock/HelixLock.java
+++ b/helix-lock/src/main/java/org/apache/helix/lock/HelixLock.java
@@ -41,7 +41,7 @@ public interface HelixLock {
    * Retrieve the lock information, e.g. lock timeout, lock message, etc.
    * @return lock metadata information
    */
-  <K, V> LockInfo<K, V> getLockInfo();
+  LockInfo getLockInfo();
 
   /**
    * If the user is current lock owner
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
index e31991a..3df0e7e 100644
--- a/helix-lock/src/main/java/org/apache/helix/lock/HelixLockScope.java
+++ b/helix-lock/src/main/java/org/apache/helix/lock/HelixLockScope.java
@@ -34,20 +34,23 @@ public class HelixLockScope {
    */
   public enum LockScopeProperty {
 
-    CLUSTER(1, 0),
+    CLUSTER(1),
 
-    PARTICIPANT(2, 1),
+    PARTICIPANT(2),
 
-    RESOURCE(3, 2),
+    RESOURCE(3),
 
-    PARTITION(4, 3);
+    PARTITION(4);
 
+    //the number of arguments required to generate a full path for the specific scope
     final int _zkPathArgNum;
-    final int _argumentPos;
 
-    private LockScopeProperty(int zkPathArgNum, int argumentPos) {
+    /**
+     * Initialize a LockScopeProperty
+     * @param zkPathArgNum the number of arguments required to generate a full path for the specific scope
+\     */
+    private LockScopeProperty(int zkPathArgNum) {
       _zkPathArgNum = zkPathArgNum;
-      _argumentPos = argumentPos;
     }
 
     /**
@@ -63,7 +66,7 @@ public class HelixLockScope {
      * @return the number of position of value for this property in the list of keys input
      */
     public int getArgumentPos() {
-      return _argumentPos;
+      return _zkPathArgNum - 1;
     }
   }
 
@@ -73,13 +76,13 @@ public class HelixLockScope {
   private static final StringTemplate template = new StringTemplate();
 
   static {
-    template.addEntry(LockScopeProperty.CLUSTER, 1, "/{clusterName}");
+    template.addEntry(LockScopeProperty.CLUSTER, 1, "/{clusterName}/LOCK");
     template.addEntry(HelixLockScope.LockScopeProperty.PARTICIPANT, 2,
-        "/{clusterName}/{participantName}");
+        "/{clusterName}/LOCK/{participantName}");
     template.addEntry(HelixLockScope.LockScopeProperty.RESOURCE, 3,
-        "/{clusterName}/{participantName}/{resourceName}");
+        "/{clusterName}/LOCK/{participantName}/{resourceName}");
     template.addEntry(HelixLockScope.LockScopeProperty.PARTITION, 4,
-        "/{clusterName}/{participantName}/{resourceName}/{partitionName}");
+        "/{clusterName}/LOCK/{participantName}/{resourceName}/{partitionName}");
   }
 
   private final HelixLockScope.LockScopeProperty _type;
diff --git a/helix-lock/src/main/java/org/apache/helix/lock/LockInfo.java b/helix-lock/src/main/java/org/apache/helix/lock/LockInfo.java
index afd4c00..3829d40 100644
--- a/helix-lock/src/main/java/org/apache/helix/lock/LockInfo.java
+++ b/helix-lock/src/main/java/org/apache/helix/lock/LockInfo.java
@@ -19,29 +19,153 @@
 
 package org.apache.helix.lock;
 
-import java.util.Map;
+import org.apache.helix.HelixProperty;
+import org.apache.helix.ZNRecord;
 
 
 /**
- * Generic interface for a map contains the Helix lock information
- * @param <K> The type of the LockInfo key
- * @param <V> the type of the LockInfo value
+ * Structure represents a lock node information, implemented using ZNRecord
  */
-public interface LockInfo<K, V> {
+public class LockInfo extends HelixProperty {
 
-  //TODO: add specific setter and getter for any field that is determined to be universal for all implementations of HelixLock
+  // Default values for each attribute if there are no current values set by user
+  public static final String DEFAULT_OWNER_TEXT = "";
+  public static final String DEFAULT_MESSAGE_TEXT = "";
+  public static final long DEFAULT_TIMEOUT_LONG = -1L;
+
+  // default lock info represents the status of a unlocked lock
+  public static final LockInfo defaultLockInfo = new LockInfo("");
+
+  /**
+   * The keys to lock information
+   */
+  public enum LockInfoAttribute {
+    OWNER, MESSAGE, TIMEOUT
+  }
+
+  /**
+   * Initialize a LockInfo with a ZNRecord id, set all info fields to default data
+   */
+  public LockInfo(String id) {
+    super(id);
+    resetLockInfo();
+  }
+
+  /**
+   * Initialize a LockInfo with a ZNRecord, set all info fields to default data
+   * @param znRecord The ZNRecord contains lock node data that used to initialize the LockInfo
+   */
+  public LockInfo(ZNRecord znRecord) {
+    super(znRecord);
+    setNullLockInfoFieldsToDefault();
+  }
+
+  /**
+   * Initialize a LockInfo with data for each field, set all null info fields to default data
+   * @param ownerId value of OWNER attribute
+   * @param message value of MESSAGE attribute
+   * @param timeout value of TIMEOUT attribute
+   */
+  public LockInfo(String ownerId, String message, long timeout) {
+    this(ownerId);
+    setLockInfoFields(ownerId, message, timeout);
+  }
+
+  /**
+   * Build a LOCKINFO instance that represents an unlocked lock states
+   * @return the unlocked lock node LockInfo instance
+   */
+  public static LockInfo buildUnlockedLockInfo() {
+    return new LockInfo("");
+  }
+
+  /**
+   * Set each field of lock info to user provided values if the values are not null, null values are set to default values
+   * @param ownerId value of OWNER attribute
+   * @param message value of MESSAGE attribute
+   * @param timeout value of TIMEOUT attribute
+   */
+  public void setLockInfoFields(String ownerId, String message, Long timeout) {
+    _record.setSimpleField(LockInfoAttribute.OWNER.name(),
+        ownerId == null ? DEFAULT_OWNER_TEXT : ownerId);
+    _record.setSimpleField(LockInfoAttribute.MESSAGE.name(),
+        message == null ? DEFAULT_MESSAGE_TEXT : message);
+    _record.setLongField(LockInfoAttribute.TIMEOUT.name(),
+        timeout == null ? DEFAULT_TIMEOUT_LONG : timeout);
+  }
+
+  /**
+   * Set all null values to default values in LockInfo, keep non-null values
+   */
+  private void setNullLockInfoFieldsToDefault() {
+    setLockInfoFields(getOwner(), getMessage(), getTimeout());
+  }
+
+  /**
+   * Reset the lock info to unlocked lock state
+   */
+  public void resetLockInfo() {
+    setLockInfoFields(DEFAULT_OWNER_TEXT, DEFAULT_MESSAGE_TEXT, DEFAULT_TIMEOUT_LONG);
+  }
+
+  /**
+   * Get the value for OWNER attribute of the lock
+   * @return the owner id of the lock, empty string if there is no owner id set
+   */
+  public String getOwner() {
+    String owner = _record.getSimpleField(LockInfoAttribute.OWNER.name());
+    return owner == null ? DEFAULT_OWNER_TEXT : owner;
+  }
+
+  /**
+   * Get the value for MESSAGE attribute of the lock
+   * @return the message of the lock, empty string if there is no message set
+   */
+  public String getMessage() {
+    String message = _record.getSimpleField(LockInfoAttribute.MESSAGE.name());
+    return message == null ? DEFAULT_MESSAGE_TEXT : message;
+  }
+
+  /**
+   * Get the value for TIMEOUT attribute of the lock
+   * @return the expiring time of the lock, -1 if there is no timeout set
+   */
+  public Long getTimeout() {
+    return _record.getLongField(LockInfoAttribute.TIMEOUT.name(), DEFAULT_TIMEOUT_LONG);
+  }
+
+  /**
+   * Get the value for OWNER attribute of the lock from a ZNRecord
+   * @return the owner id of the lock, empty string if there is no owner id set
+   */
+  static String getOwner(ZNRecord znRecord) {
+    if (znRecord == null) {
+      return DEFAULT_OWNER_TEXT;
+    }
+    String owner = znRecord.getSimpleField(LockInfoAttribute.OWNER.name());
+    return owner == null ? DEFAULT_OWNER_TEXT : owner;
+  }
 
   /**
-   * Create a single filed of LockInfo, or update the value of the field if it already exists
-   * @param infoKey the key of the LockInfo field
-   * @param infoValue the value of the LockInfo field
+   * Get the value for MESSAGE attribute of the lock from a ZNRecord
+   * @return the message of the lock, empty string if there is no message set
    */
-  void setInfoValue(K infoKey, V infoValue);
+  static String getMessage(ZNRecord znRecord) {
+    if (znRecord == null) {
+      return DEFAULT_MESSAGE_TEXT;
+    }
+    String message = znRecord.getSimpleField(LockInfoAttribute.MESSAGE.name());
+    return message == null ? DEFAULT_MESSAGE_TEXT : message;
+  }
 
   /**
-   * Get the value of a field in LockInfo
-   * @param infoKey the key of the LockInfo field
-   * @return the value of the field or null if this key does not exist
+   * Get the value for TIMEOUT attribute of the lock from a ZNRecord
+   * @return the expiring time of the lock, -1 if there is no timeout set
    */
-  V getInfoValue(K infoKey);
+  static long getTimeout(ZNRecord znRecord) {
+    if (znRecord == null) {
+      return DEFAULT_TIMEOUT_LONG;
+    }
+    return znRecord.getLongField(LockInfoAttribute.TIMEOUT.name(), DEFAULT_TIMEOUT_LONG);
+  }
 }
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 18cac1a..b0cc8f1 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
@@ -20,6 +20,7 @@
 package org.apache.helix.lock;
 
 import java.util.Date;
+import java.util.concurrent.locks.Lock;
 
 import org.I0Itec.zkclient.DataUpdater;
 import org.apache.helix.AccessOption;
@@ -29,8 +30,9 @@ import org.apache.helix.ZNRecord;
 import org.apache.helix.manager.zk.ZkBaseDataAccessor;
 import org.apache.log4j.Logger;
 
-import static org.apache.helix.lock.ZKHelixNonblockingLockInfo.DEFAULT_OWNER_TEXT;
-import static org.apache.helix.lock.ZKHelixNonblockingLockInfo.DEFAULT_TIMEOUT_LONG;
+import static org.apache.helix.lock.LockInfo.DEFAULT_OWNER_TEXT;
+import static org.apache.helix.lock.LockInfo.DEFAULT_TIMEOUT_LONG;
+import static org.apache.helix.lock.LockInfo.defaultLockInfo;
 
 
 /**
@@ -40,7 +42,6 @@ public class ZKHelixNonblockingLock implements HelixLock {
 
   private static final Logger LOG = Logger.getLogger(ZKHelixNonblockingLock.class);
 
-  private static final String LOCK_ROOT = "/LOCK";
   private final String _lockPath;
   private final String _userId;
   private final long _timeout;
@@ -49,16 +50,15 @@ public class ZKHelixNonblockingLock implements HelixLock {
 
   /**
    * Initialize the lock with user provided information, e.g.,cluster, scope, etc.
-   * @param clusterName the cluster under which the lock will live
    * @param scope the scope to lock
    * @param zkAddress the zk address the cluster connects to
    * @param timeout the timeout period of the lcok
    * @param lockMsg the reason for having this lock
    * @param userId a universal unique userId for lock owner identity
    */
-  public ZKHelixNonblockingLock(String clusterName, HelixLockScope scope, String zkAddress,
-      Long timeout, String lockMsg, String userId) {
-    this("/" + clusterName.toUpperCase() + LOCK_ROOT + scope.getZkPath(), zkAddress, timeout, lockMsg, userId);
+  public ZKHelixNonblockingLock(HelixLockScope scope, String zkAddress, Long timeout,
+      String lockMsg, String userId) {
+    this(scope.getZkPath(), zkAddress, timeout, lockMsg, userId);
   }
 
   /**
@@ -82,10 +82,6 @@ public class ZKHelixNonblockingLock implements HelixLock {
   public boolean acquireLock() {
 
     // Set lock information fields
-    ZNRecord lockInfo = new ZNRecord(_userId);
-    lockInfo.setSimpleField(ZKHelixNonblockingLockInfo.InfoKey.OWNER.name(), _userId);
-    lockInfo.setSimpleField(ZKHelixNonblockingLockInfo.InfoKey.MESSAGE.name(), _lockMsg);
-
     long deadline;
     // Prevent value overflow
     if (_timeout > Long.MAX_VALUE - System.currentTimeMillis()) {
@@ -93,7 +89,8 @@ public class ZKHelixNonblockingLock implements HelixLock {
     } else {
       deadline = System.currentTimeMillis() + _timeout;
     }
-    lockInfo.setLongField(ZKHelixNonblockingLockInfo.InfoKey.TIMEOUT.name(), deadline);
+    LockInfo lockInfo = new LockInfo(_userId);
+    lockInfo.setLockInfoFields(_userId, _lockMsg, deadline);
 
     LockUpdater updater = new LockUpdater(lockInfo);
     return _baseDataAccessor.update(_lockPath, updater, AccessOption.PERSISTENT);
@@ -101,70 +98,64 @@ public class ZKHelixNonblockingLock implements HelixLock {
 
   @Override
   public boolean releaseLock() {
-    ZNRecord newLockInfo = new ZKHelixNonblockingLockInfo<>().toZNRecord();
-    LockUpdater updater = new LockUpdater(newLockInfo);
+    // Initialize the lock updater with a default lock info represents the state of a unlocked lock
+    LockUpdater updater = new LockUpdater(LockInfo.defaultLockInfo);
     return _baseDataAccessor.update(_lockPath, updater, AccessOption.PERSISTENT);
   }
 
   @Override
-  public ZKHelixNonblockingLockInfo getLockInfo() {
+  public LockInfo getLockInfo() {
     ZNRecord curLockInfo = _baseDataAccessor.get(_lockPath, null, AccessOption.PERSISTENT);
-    return new ZKHelixNonblockingLockInfo(curLockInfo);
+    return new LockInfo(curLockInfo);
   }
 
   @Override
   public boolean isOwner() {
-    ZNRecord curLockInfo = _baseDataAccessor.get(_lockPath, null, AccessOption.PERSISTENT);
-    return userIdMatches(curLockInfo) && !hasTimedOut(curLockInfo);
+    LockInfo lockInfo = getLockInfo();
+    return userIdMatches(lockInfo) && !hasTimedOut(lockInfo);
   }
 
   /**
    * Check if a lock has timed out
-   * @param record the current lock information in ZNRecord format
    * @return return true if the lock has timed out, otherwise return false.
    */
-  private boolean hasTimedOut(ZNRecord record) {
-    if (record == null) {
-      return false;
-    }
-    long timeout = record
-        .getLongField(ZKHelixNonblockingLockInfo.InfoKey.TIMEOUT.name(), DEFAULT_TIMEOUT_LONG);
-    return System.currentTimeMillis() >= timeout;
+  private boolean hasTimedOut(LockInfo lockInfo) {
+    return System.currentTimeMillis() >= lockInfo.getTimeout();
+  }
+
+  /**
+   * Check if a lock has timed out with lock information stored in a ZNRecord
+   * @return return true if the lock has timed out, otherwise return false.
+   */
+  private boolean hasTimedOut(ZNRecord znRecord) {
+    return System.currentTimeMillis() >= LockInfo.getTimeout(znRecord);
   }
 
   /**
    * Check if the current user Id matches with the owner Id in a lock info
-   * @param record the lock information in ZNRecord format
    * @return return true if the two ids match, otherwise return false.
    */
-  private boolean userIdMatches(ZNRecord record) {
-    if (record == null) {
-      return false;
-    }
-    String ownerId = record.getSimpleField(ZKHelixNonblockingLockInfo.InfoKey.OWNER.name());
-    return ownerId.equals(_userId);
+  private boolean userIdMatches(LockInfo lockInfo) {
+    return lockInfo.getOwner().equals(_userId);
   }
 
   /**
-   * Check if the lock node has a owner id field in the lock information
-   * @param record Lock information in format of ZNRecord
-   * @return true if the lock has a owner id field that the ownership can be or not be timed out, otherwise false
+   * Check if a user id in the ZNRecord matches current user's id
+   * @param znRecord ZNRecord contains lock information
+   * @return true if the ids match, false if not or ZNRecord does not contain user id information
    */
-  private boolean hasOwnerField(ZNRecord record) {
-    if (record == null) {
-      return false;
-    }
-    String ownerId = record.getSimpleField(ZKHelixNonblockingLockInfo.InfoKey.OWNER.name());
-    return ownerId != null && !ownerId.equals(DEFAULT_OWNER_TEXT);
+  private boolean userIdMatches(ZNRecord znRecord) {
+    return LockInfo.getOwner(znRecord).equals(_userId);
   }
 
   /**
    * Check if the lock node has a current owner
-   * @param record Lock information in format of ZNRecord
+   * @param znRecord Lock information in format of ZNRecord
    * @return true if the lock has a current owner that the ownership has not be timed out, otherwise false
    */
-  private boolean hasNonExpiredOwner(ZNRecord record) {
-    return hasOwnerField(record) && !hasTimedOut(record);
+  private boolean hasNonExpiredOwner(ZNRecord znRecord) {
+    String owner = LockInfo.getOwner(znRecord);
+    return !owner.equals(DEFAULT_OWNER_TEXT) && !hasTimedOut(znRecord);
   }
 
   /**
@@ -175,10 +166,10 @@ public class ZKHelixNonblockingLock implements HelixLock {
 
     /**
      * Initialize a structure for lock user to update a lock node value
-     * @param record the lock node value will be updated in ZNRecord format
+     * @param lockInfo the lock node value will be used to update the lock
      */
-    public LockUpdater(ZNRecord record) {
-      _record = record;
+    public LockUpdater(LockInfo lockInfo) {
+      _record = lockInfo.getRecord();
     }
 
     @Override
diff --git a/helix-lock/src/main/java/org/apache/helix/lock/ZKHelixNonblockingLockInfo.java b/helix-lock/src/main/java/org/apache/helix/lock/ZKHelixNonblockingLockInfo.java
deleted file mode 100644
index 6e62717..0000000
--- a/helix-lock/src/main/java/org/apache/helix/lock/ZKHelixNonblockingLockInfo.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.HashMap;
-import java.util.Map;
-
-import org.apache.helix.ZNRecord;
-
-
-public class ZKHelixNonblockingLockInfo<K extends ZKHelixNonblockingLockInfo.InfoKey, V extends String> implements LockInfo<K, V> {
-
-  public static final String DEFAULT_OWNER_TEXT = "";
-  public static final String DEFAULT_MESSAGE_TEXT = "";
-  public static final long DEFAULT_TIMEOUT_LONG = -1L;
-  public static final String DEFAULT_TIMEOUT_TEXT = String.valueOf(DEFAULT_TIMEOUT_LONG);
-  private Map<InfoKey, String> lockInfo;
-
-  public enum InfoKey {
-    OWNER, MESSAGE, TIMEOUT
-  }
-
-  /**
-   * Constructor of ZKHelixNonblockingLockInfo that set each field to default data
-   */
-  public ZKHelixNonblockingLockInfo() {
-    lockInfo = new HashMap<>();
-    lockInfo.put(InfoKey.OWNER, DEFAULT_OWNER_TEXT);
-    lockInfo.put(InfoKey.MESSAGE, DEFAULT_MESSAGE_TEXT);
-    lockInfo.put(InfoKey.TIMEOUT, DEFAULT_TIMEOUT_TEXT);
-  }
-
-  /**
-   * Construct a ZKHelixNonblockingLockInfo using a ZNRecord format of data
-   * @param znRecord A ZNRecord that contains lock information in its simple fields
-   */
-  public ZKHelixNonblockingLockInfo(ZNRecord znRecord) {
-    this();
-    if (znRecord == null) {
-      return;
-    }
-    Map<String, String> simpleFields = znRecord.getSimpleFields();
-    lockInfo
-        .put(InfoKey.OWNER, simpleFields.getOrDefault(InfoKey.OWNER.name(), DEFAULT_OWNER_TEXT));
-    lockInfo.put(InfoKey.MESSAGE,
-        simpleFields.getOrDefault(InfoKey.MESSAGE.name(), DEFAULT_MESSAGE_TEXT));
-    lockInfo.put(InfoKey.TIMEOUT,
-        simpleFields.getOrDefault(InfoKey.TIMEOUT.name(), DEFAULT_TIMEOUT_TEXT));
-  }
-
-  @Override
-  public void setInfoValue(InfoKey infoKey, String infoValue) {
-    lockInfo.put(infoKey, infoValue);
-  }
-
-  @Override
-  public String getInfoValue(InfoKey infoKey) {
-    return lockInfo.get(infoKey);
-  }
-
-  /**
-   * Method to convert a ZKHelixNonblockingLockInfo to ZNRecord
-   * @return a ZNRecord format data contains lock information in its simple fields
-   */
-  public ZNRecord toZNRecord() {
-    ZNRecord znRecord = new ZNRecord("");
-    znRecord.setSimpleField(InfoKey.OWNER.name(),
-        lockInfo.getOrDefault(InfoKey.OWNER, DEFAULT_OWNER_TEXT));
-    znRecord.setSimpleField(InfoKey.MESSAGE.name(),
-        lockInfo.getOrDefault(InfoKey.MESSAGE, DEFAULT_MESSAGE_TEXT));
-    znRecord.setSimpleField(InfoKey.TIMEOUT.name(),
-        lockInfo.getOrDefault(InfoKey.TIMEOUT, DEFAULT_TIMEOUT_TEXT));
-    return znRecord;
-  }
-}
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 090a43d..5e28688 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
@@ -39,7 +39,6 @@ import org.testng.annotations.Test;
 public class TestZKHelixNonblockingLock extends ZkTestBase {
 
   private final String _clusterName = TestHelper.getTestClassName();
-  private final String _lockRoot = "/LOCK";
   private final String _lockMessage = "Test";
   private String _lockPath;
   private ZKHelixNonblockingLock _lock;
@@ -62,8 +61,8 @@ public class TestZKHelixNonblockingLock extends ZkTestBase {
     pathKeys.add("partition_name");
 
     _participantScope = new HelixLockScope(HelixLockScope.LockScopeProperty.PARTITION, pathKeys);
-    _lockPath = "/" + _clusterName.toUpperCase() + _lockRoot + _participantScope.getZkPath();
-    _lock = new ZKHelixNonblockingLock(_clusterName, _participantScope, ZK_ADDR, Long.MAX_VALUE,
+    _lockPath = _participantScope.getZkPath();
+    _lock = new ZKHelixNonblockingLock(_participantScope, ZK_ADDR, Long.MAX_VALUE,
         _lockMessage, _userId);
   }
 
@@ -81,9 +80,9 @@ public class TestZKHelixNonblockingLock extends ZkTestBase {
     Assert.assertTrue(_gZkClient.exists(_lockPath));
 
     // Get lock information
-    LockInfo<ZKHelixNonblockingLockInfo.InfoKey, String> record = _lock.getLockInfo();
-    Assert.assertEquals(record.getInfoValue(ZKHelixNonblockingLockInfo.InfoKey.OWNER), _userId);
-    Assert.assertEquals(record.getInfoValue(ZKHelixNonblockingLockInfo.InfoKey.MESSAGE),
+    LockInfo lockInfo = _lock.getLockInfo();
+    Assert.assertEquals(lockInfo.getOwner(), _userId);
+    Assert.assertEquals(lockInfo.getMessage(),
         _lockMessage);
 
     // Check if the user is lock owner
@@ -100,8 +99,8 @@ public class TestZKHelixNonblockingLock extends ZkTestBase {
     // Fake condition when the lock owner is not current user
     String fakeUserID = UUID.randomUUID().toString();
     ZNRecord fakeRecord = new ZNRecord(fakeUserID);
-    fakeRecord.setSimpleField(ZKHelixNonblockingLockInfo.InfoKey.OWNER.name(), fakeUserID);
-    fakeRecord.setSimpleField(ZKHelixNonblockingLockInfo.InfoKey.TIMEOUT.name(),
+    fakeRecord.setSimpleField(LockInfo.LockInfoAttribute.OWNER.name(), fakeUserID);
+    fakeRecord.setSimpleField(LockInfo.LockInfoAttribute.TIMEOUT.name(),
         String.valueOf(Long.MAX_VALUE));
     _gZkClient.create(_lockPath, fakeRecord, CreateMode.PERSISTENT);
 
@@ -122,8 +121,8 @@ public class TestZKHelixNonblockingLock extends ZkTestBase {
     // Fake condition when the current lock already expired
     String fakeUserID = UUID.randomUUID().toString();
     ZNRecord fakeRecord = new ZNRecord(fakeUserID);
-    fakeRecord.setSimpleField(ZKHelixNonblockingLockInfo.InfoKey.OWNER.name(), fakeUserID);
-    fakeRecord.setSimpleField(ZKHelixNonblockingLockInfo.InfoKey.TIMEOUT.name(),
+    fakeRecord.setSimpleField(LockInfo.LockInfoAttribute.OWNER.name(), fakeUserID);
+    fakeRecord.setSimpleField(LockInfo.LockInfoAttribute.TIMEOUT.name(),
         String.valueOf(System.currentTimeMillis()));
     _gZkClient.create(_lockPath, fakeRecord, CreateMode.PERSISTENT);
 
@@ -141,7 +140,7 @@ public class TestZKHelixNonblockingLock extends ZkTestBase {
     List<Callable<Boolean>> threads = new ArrayList<>();
     for (int i = 0; i < 2; i++) {
       ZKHelixNonblockingLock lock =
-          new ZKHelixNonblockingLock(_clusterName, _participantScope, ZK_ADDR, Long.MAX_VALUE,
+          new ZKHelixNonblockingLock(_participantScope, ZK_ADDR, Long.MAX_VALUE,
               _lockMessage, UUID.randomUUID().toString());
       threads.add(new TestSimultaneousAcquireLock(lock));
     }