You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by jd...@apache.org on 2009/08/30 22:42:00 UTC

svn commit: r809414 - in /hadoop/hbase/trunk: CHANGES.txt src/java/org/apache/hadoop/hbase/client/HConnectionManager.java src/test/org/apache/hadoop/hbase/TestZooKeeper.java

Author: jdcryans
Date: Sun Aug 30 20:41:59 2009
New Revision: 809414

URL: http://svn.apache.org/viewvc?rev=809414&view=rev
Log:
HBASE-1800  Too many ZK connections

Modified:
    hadoop/hbase/trunk/CHANGES.txt
    hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnectionManager.java
    hadoop/hbase/trunk/src/test/org/apache/hadoop/hbase/TestZooKeeper.java

Modified: hadoop/hbase/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/CHANGES.txt?rev=809414&r1=809413&r2=809414&view=diff
==============================================================================
--- hadoop/hbase/trunk/CHANGES.txt (original)
+++ hadoop/hbase/trunk/CHANGES.txt Sun Aug 30 20:41:59 2009
@@ -27,6 +27,7 @@
    HBASE-1776  Make rowcounter enum public
    HBASE-1276  [testing] Upgrade to JUnit 4.x and use @BeforeClass
                annotations to optimize tests
+   HBASE-1800  Too many ZK connections
 
   OPTIMIZATIONS
 

Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnectionManager.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnectionManager.java?rev=809414&r1=809413&r2=809414&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnectionManager.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnectionManager.java Sun Aug 30 20:41:59 2009
@@ -79,6 +79,9 @@
   final Map<HBaseConfiguration, TableServers> HBASE_INSTANCES =
     new WeakHashMap<HBaseConfiguration, TableServers>();
   
+  private static final Map<String, ClientZKWatcher> ZK_WRAPPERS = 
+    new HashMap<String, ClientZKWatcher>();
+  
   /**
    * Get the connection object for the instance specified by the configuration
    * If no current connection exists, create a new connection for that instance
@@ -124,10 +127,93 @@
         }
       }
     }
+    synchronized (ZK_WRAPPERS) {
+      for (ClientZKWatcher watch : ZK_WRAPPERS.values()) {
+        watch.resetZooKeeper();
+      }
+    }
+  }
+
+  /**
+   * Get a watcher of a zookeeper connection for a given quorum address.
+   * If the connection isn't established, a new one is created.
+   * This acts like a multiton.
+   * @param conf
+   * @return ZKW watcher
+   * @throws IOException
+   */
+  public static synchronized ClientZKWatcher getClientZooKeeperWatcher(
+      HBaseConfiguration conf) throws IOException {
+    if (!ZK_WRAPPERS.containsKey(conf.get(HConstants.ZOOKEEPER_QUORUM))) {
+      ZK_WRAPPERS.put(conf.get(HConstants.ZOOKEEPER_QUORUM),
+          new ClientZKWatcher(conf));
+    }
+    return ZK_WRAPPERS.get(conf.get(HConstants.ZOOKEEPER_QUORUM));
+  }
+  
+  /**
+   * This class is responsible to handle connection and reconnection
+   * to a zookeeper quorum.
+   *
+   */
+  public static class ClientZKWatcher implements Watcher {
+
+    static final Log LOG = LogFactory.getLog(ClientZKWatcher.class);
+    private ZooKeeperWrapper zooKeeperWrapper;
+    private HBaseConfiguration conf;
+
+    /**
+     * Takes a configuration to pass it to ZKW but won't instanciate it
+     * @param conf
+     * @throws IOException
+     */
+    public ClientZKWatcher(HBaseConfiguration conf) {
+      this.conf = conf;
+    }
+
+    /**
+     * Called by ZooKeeper when an event occurs on our connection. We use this to
+     * detect our session expiring. When our session expires, we have lost our
+     * connection to ZooKeeper. Our handle is dead, and we need to recreate it.
+     *
+     * See http://hadoop.apache.org/zookeeper/docs/current/zookeeperProgrammers.html#ch_zkSessions
+     * for more information.
+     *
+     * @param event WatchedEvent witnessed by ZooKeeper.
+     */
+    public void process(WatchedEvent event) {
+      KeeperState state = event.getState();
+      LOG.debug("Got ZooKeeper event, state: " + state + ", type: "
+          + event.getType() + ", path: " + event.getPath());
+      if (state == KeeperState.Expired) {
+        resetZooKeeper();
+      }
+    }
+    
+    /**
+     * Get this watcher's ZKW, instanciate it if necessary.
+     * @return ZKW
+     */
+    public ZooKeeperWrapper getZooKeeperWrapper() throws IOException {
+      if(zooKeeperWrapper == null) {
+        zooKeeperWrapper = new ZooKeeperWrapper(conf, this);
+      } 
+      return zooKeeperWrapper;
+    }
+    
+    /**
+     * Clear this connection to zookeeper.
+     */
+    private synchronized void resetZooKeeper() {
+      if (zooKeeperWrapper != null) {
+        zooKeeperWrapper.close();
+        zooKeeperWrapper = null;
+      }
+    }
   }
 
   /* Encapsulates finding the servers for an HBase instance */
-  private static class TableServers implements ServerConnection, HConstants, Watcher {
+  private static class TableServers implements ServerConnection, HConstants {
     static final Log LOG = LogFactory.getLog(TableServers.class);
     private final Class<? extends HRegionInterface> serverInterfaceClass;
     private final long pause;
@@ -157,8 +243,6 @@
       cachedRegionLocations =
         new HashMap<Integer, SoftValueSortedMap<byte [], HRegionLocation>>();
 
-    private ZooKeeperWrapper zooKeeperWrapper;
-
     /** 
      * constructor
      * @param conf Configuration object
@@ -197,32 +281,6 @@
       return this.pause * HConstants.RETRY_BACKOFF[ntries];
     }
 
-    /**
-     * Called by ZooKeeper when an event occurs on our connection. We use this to
-     * detect our session expiring. When our session expires, we have lost our
-     * connection to ZooKeeper. Our handle is dead, and we need to recreate it.
-     *
-     * See http://hadoop.apache.org/zookeeper/docs/current/zookeeperProgrammers.html#ch_zkSessions
-     * for more information.
-     *
-     * @param event WatchedEvent witnessed by ZooKeeper.
-     */
-    public void process(WatchedEvent event) {
-      KeeperState state = event.getState();
-      LOG.debug("Got ZooKeeper event, state: " + state + ", type: " +
-                event.getType() + ", path: " + event.getPath());
-      if (state == KeeperState.Expired) {
-        resetZooKeeper();
-      }
-    }
-
-    private synchronized void resetZooKeeper() {
-      if (zooKeeperWrapper != null) {
-        zooKeeperWrapper.close();
-        zooKeeperWrapper = null;
-      }
-    }
-
     // Used by master and region servers during safe mode only
     public void unsetRootRegionLocation() {
       this.rootRegionLocation = null;
@@ -814,11 +872,10 @@
       return getHRegionConnection(regionServer, false);
     }
 
-    public synchronized ZooKeeperWrapper getZooKeeperWrapper() throws IOException {
-      if (zooKeeperWrapper == null) {
-        zooKeeperWrapper = new ZooKeeperWrapper(conf, this);
-      }
-      return zooKeeperWrapper;
+    public synchronized ZooKeeperWrapper getZooKeeperWrapper()
+        throws IOException {
+      return HConnectionManager.getClientZooKeeperWatcher(conf)
+          .getZooKeeperWrapper();
     }
 
     /*
@@ -1084,7 +1141,6 @@
         master = null;
         masterChecked = false;
       }
-      resetZooKeeper();
       if (stopProxy) {
         synchronized (servers) {
           for (HRegionInterface i: servers.values()) {

Modified: hadoop/hbase/trunk/src/test/org/apache/hadoop/hbase/TestZooKeeper.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/test/org/apache/hadoop/hbase/TestZooKeeper.java?rev=809414&r1=809413&r2=809414&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/test/org/apache/hadoop/hbase/TestZooKeeper.java (original)
+++ hadoop/hbase/trunk/src/test/org/apache/hadoop/hbase/TestZooKeeper.java Sun Aug 30 20:41:59 2009
@@ -21,6 +21,7 @@
 
 import java.io.IOException;
 
+import org.apache.hadoop.hbase.client.Get;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
 import org.apache.hadoop.hbase.client.HConnection;
 import org.apache.hadoop.hbase.client.HConnectionManager;
@@ -150,4 +151,28 @@
       fail();
     }
   }
+  
+  public void testMultipleZK() {
+    try {
+      HTable localMeta = new HTable(conf, HConstants.META_TABLE_NAME);
+      HBaseConfiguration otherConf = new HBaseConfiguration(conf);
+      otherConf.set(HConstants.ZOOKEEPER_QUORUM, "127.0.0.1");
+      HTable ipMeta = new HTable(conf, HConstants.META_TABLE_NAME);
+      
+      // dummy, just to open the connection
+      localMeta.exists(new Get(HConstants.LAST_ROW));
+      ipMeta.exists(new Get(HConstants.LAST_ROW));
+
+      // make sure they aren't the same
+      assertFalse(HConnectionManager.getClientZooKeeperWatcher(conf)
+          .getZooKeeperWrapper() == HConnectionManager.getClientZooKeeperWatcher(
+          otherConf).getZooKeeperWrapper());
+      assertFalse(HConnectionManager.getConnection(conf)
+          .getZooKeeperWrapper().getQuorumServers().equals(HConnectionManager
+          .getConnection(otherConf).getZooKeeperWrapper().getQuorumServers()));
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail();
+    }
+  }
 }