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

stoty pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-3 by this push:
     new 49caa728ed3 HBASE-28411 Remove direct dependency on Curator (#5726)
49caa728ed3 is described below

commit 49caa728ed30e558c6a5354044a1da01d8f909d9
Author: Istvan Toth <[email protected]>
AuthorDate: Tue Sep 2 14:55:02 2025 +0200

    HBASE-28411 Remove direct dependency on Curator (#5726)
    
    Signed-off-by: Duo Zhang <[email protected]>
    (cherry picked from commit c170311752ff578f3fc83ca81368d6b94416e95e)
---
 hbase-examples/pom.xml                             |  12 --
 .../example/ZooKeeperScanPolicyObserver.java       | 121 +++++++++++++--------
 pom.xml                                            |  50 ++-------
 3 files changed, 85 insertions(+), 98 deletions(-)

diff --git a/hbase-examples/pom.xml b/hbase-examples/pom.xml
index c90a46644a4..e1a29d665b9 100644
--- a/hbase-examples/pom.xml
+++ b/hbase-examples/pom.xml
@@ -127,18 +127,6 @@
       <artifactId>protobuf-java</artifactId>
       <version>${internal.protobuf.version}</version>
     </dependency>
-    <dependency>
-      <groupId>org.apache.curator</groupId>
-      <artifactId>curator-framework</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.curator</groupId>
-      <artifactId>curator-client</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.curator</groupId>
-      <artifactId>curator-recipes</artifactId>
-    </dependency>
     <dependency>
       <groupId>com.github.stephenc.findbugs</groupId>
       <artifactId>findbugs-annotations</artifactId>
diff --git 
a/hbase-examples/src/main/java/org/apache/hadoop/hbase/coprocessor/example/ZooKeeperScanPolicyObserver.java
 
b/hbase-examples/src/main/java/org/apache/hadoop/hbase/coprocessor/example/ZooKeeperScanPolicyObserver.java
index 1fba63d054a..7a8978ea8d0 100644
--- 
a/hbase-examples/src/main/java/org/apache/hadoop/hbase/coprocessor/example/ZooKeeperScanPolicyObserver.java
+++ 
b/hbase-examples/src/main/java/org/apache/hadoop/hbase/coprocessor/example/ZooKeeperScanPolicyObserver.java
@@ -20,11 +20,6 @@ package org.apache.hadoop.hbase.coprocessor.example;
 import java.io.IOException;
 import java.util.Optional;
 import java.util.OptionalLong;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.framework.recipes.cache.ChildData;
-import org.apache.curator.framework.recipes.cache.NodeCache;
-import org.apache.curator.retry.RetryForever;
 import org.apache.hadoop.hbase.CoprocessorEnvironment;
 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
 import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor;
@@ -39,6 +34,14 @@ import 
org.apache.hadoop.hbase.regionserver.compactions.CompactionRequest;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.yetus.audience.InterfaceAudience;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.KeeperException.NodeExistsException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.Stat;
 
 /**
  * This is an example showing how a RegionObserver could be configured via 
ZooKeeper in order to
@@ -66,72 +69,105 @@ public class ZooKeeperScanPolicyObserver implements 
RegionCoprocessor, RegionObs
   public static final String NODE = "/backup/example/lastbackup";
   private static final String ZKKEY = "ZK";
 
-  private NodeCache cache;
+  private ZKDataHolder cache;
 
   /**
    * Internal watcher that keep "data" up to date asynchronously.
    */
-  private static final class ZKDataHolder {
+  private static final class ZKDataHolder implements Watcher {
 
     private final String ensemble;
 
     private final int sessionTimeout;
 
-    private CuratorFramework client;
-
-    private NodeCache cache;
+    private ZooKeeper zk;
 
     private int ref;
 
+    private byte[] data;
+
     public ZKDataHolder(String ensemble, int sessionTimeout) {
       this.ensemble = ensemble;
       this.sessionTimeout = sessionTimeout;
     }
 
-    private void create() throws Exception {
-      client =
-        
CuratorFrameworkFactory.builder().connectString(ensemble).sessionTimeoutMs(sessionTimeout)
-          .retryPolicy(new RetryForever(1000)).canBeReadOnly(true).build();
-      client.start();
-      cache = new NodeCache(client, NODE);
-      cache.start(true);
+    private void open() throws IOException {
+      if (zk == null) {
+        zk = new ZooKeeper(ensemble, sessionTimeout, this);
+        // In a real application, you'd probably want to create these Znodes 
externally,
+        // and not from the coprocessor
+        StringBuffer createdPath = new StringBuffer();
+        byte[] empty = new byte[0];
+        for (String element : NODE.split("/")) {
+          if (element.isEmpty()) {
+            continue;
+          }
+          try {
+            createdPath = createdPath.append("/").append(element);
+            zk.create(createdPath.toString(), empty, 
ZooDefs.Ids.OPEN_ACL_UNSAFE,
+              CreateMode.PERSISTENT);
+          } catch (NodeExistsException e) {
+            // That's OK
+          } catch (KeeperException e) {
+            throw new IOException(e);
+          } catch (InterruptedException e) {
+            // Restore interrupt status
+            Thread.currentThread().interrupt();
+          }
+        }
+      }
     }
 
     private void close() {
-      if (cache != null) {
+      if (zk != null) {
         try {
-          cache.close();
-        } catch (IOException e) {
-          // should not happen
-          throw new AssertionError(e);
+          zk.close();
+          zk = null;
+        } catch (InterruptedException e) {
+          // Restore interrupt status
+          Thread.currentThread().interrupt();
         }
-        cache = null;
-      }
-      if (client != null) {
-        client.close();
-        client = null;
       }
     }
 
-    public synchronized NodeCache acquire() throws Exception {
+    public synchronized byte[] getData() {
       if (ref == 0) {
+        Stat stat = null;
         try {
-          create();
-        } catch (Exception e) {
-          close();
-          throw e;
+          stat = zk.exists(NODE, this);
+        } catch (KeeperException e) {
+          // Value will always be null if the initial connection fails.
+          // In a real application you probably want to try to
+          // periodically re-connect in this case.
+        } catch (InterruptedException e) {
+          // Restore interrupt status
+          Thread.currentThread().interrupt();
+        }
+        if (stat != null) {
+          refresh();
         }
       }
       ref++;
-      return cache;
+      return data;
     }
 
-    public synchronized void release() {
-      ref--;
-      if (ref == 0) {
-        close();
+    private synchronized void refresh() {
+      try {
+        data = zk.getData(NODE, this, null);
+      } catch (KeeperException e) {
+        // Value will always be null if this fails (as we cannot set the new 
watcher)
+        // In a real application you probably want to try to
+        // periodically re-connect in this case.
+      } catch (InterruptedException e) {
+        // Restore interrupt status
+        Thread.currentThread().interrupt();
       }
     }
+
+    @Override
+    public void process(WatchedEvent event) {
+      refresh();
+    }
   }
 
   @Override
@@ -143,7 +179,8 @@ public class ZooKeeperScanPolicyObserver implements 
RegionCoprocessor, RegionObs
         int sessionTimeout =
           renv.getConfiguration().getInt(ZK_SESSION_TIMEOUT_KEY, 
ZK_SESSION_TIMEOUT_DEFAULT);
         return new ZKDataHolder(ensemble, sessionTimeout);
-      })).acquire();
+      }));
+      cache.open();
     } catch (Exception e) {
       throw new IOException(e);
     }
@@ -153,15 +190,11 @@ public class ZooKeeperScanPolicyObserver implements 
RegionCoprocessor, RegionObs
   public void stop(CoprocessorEnvironment env) throws IOException {
     RegionCoprocessorEnvironment renv = (RegionCoprocessorEnvironment) env;
     this.cache = null;
-    ((ZKDataHolder) renv.getSharedData().get(ZKKEY)).release();
+    ((ZKDataHolder) renv.getSharedData().get(ZKKEY)).close();
   }
 
   private OptionalLong getExpireBefore() {
-    ChildData data = cache.getCurrentData();
-    if (data == null) {
-      return OptionalLong.empty();
-    }
-    byte[] bytes = data.getData();
+    byte[] bytes = cache.getData();
     if (bytes == null || bytes.length != Long.BYTES) {
       return OptionalLong.empty();
     }
diff --git a/pom.xml b/pom.xml
index 368fba739f2..6ff7f5a056a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -872,7 +872,6 @@
     <bouncycastle.version>1.81</bouncycastle.version>
     <skyscreamer.version>1.5.1</skyscreamer.version>
     <commons-crypto.version>1.1.0</commons-crypto.version>
-    <curator.version>5.7.1</curator.version>
     <!-- Plugin Dependencies -->
     <build.helper.maven.version>3.0.0</build.helper.maven.version>
     <buildnumber.maven.version>1.4</buildnumber.maven.version>
@@ -1695,47 +1694,6 @@
           </exclusion>
         </exclusions>
       </dependency>
-      <dependency>
-        <groupId>org.apache.curator</groupId>
-        <artifactId>curator-framework</artifactId>
-        <version>${curator.version}</version>
-        <exclusions>
-          <exclusion>
-            <groupId>org.apache.zookeeper</groupId>
-            <artifactId>zookeeper</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.curator</groupId>
-        <artifactId>curator-client</artifactId>
-        <version>${curator.version}</version>
-        <exclusions>
-          <exclusion>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>org.apache.zookeeper</groupId>
-            <artifactId>zookeeper</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.curator</groupId>
-        <artifactId>curator-recipes</artifactId>
-        <version>${curator.version}</version>
-        <exclusions>
-          <exclusion>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>org.apache.zookeeper</groupId>
-            <artifactId>zookeeper</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
       <dependency>
         <groupId>org.apache.yetus</groupId>
         <artifactId>audience-annotations</artifactId>
@@ -2586,6 +2544,14 @@
                     
<bannedImport>org.apache.hadoop.thirdparty.**</bannedImport>
                   </bannedImports>
                 </restrictImports>
+                <restrictImports 
implementation="de.skuzzle.enforcer.restrictimports.rule.RestrictImports">
+                  <includeTestCode>true</includeTestCode>
+                  <commentLineBufferSize>512</commentLineBufferSize>
+                  <reason>Use ZooKeeper directly</reason>
+                  <bannedImports>
+                    <bannedImport>org.apache.curator.**</bannedImport>
+                  </bannedImports>
+                </restrictImports>
                 <restrictImports 
implementation="de.skuzzle.enforcer.restrictimports.rule.RestrictImports">
                   <includeTestCode>true</includeTestCode>
                   <commentLineBufferSize>512</commentLineBufferSize>

Reply via email to