You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2010/08/19 08:01:35 UTC

svn commit: r987026 - in /hbase/branches/0.90_master_rewrite/src: main/java/org/apache/hadoop/hbase/master/ main/java/org/apache/hadoop/hbase/master/handler/ test/java/org/apache/hadoop/hbase/master/

Author: stack
Date: Thu Aug 19 06:01:34 2010
New Revision: 987026

URL: http://svn.apache.org/viewvc?rev=987026&view=rev
Log:
Put together the two unit tests that were named with the prefix
TestZKBased*  They were duplicating a bunch of code.  They needed
fixup too to pass; they referenced what I'm guessing are old names
for messages.  Test passes now.

D src/test/java/org/apache/hadoop/hbase/master/TestZKBasedReopenRegion.java
  Moved test to TestZKBaseOpenCloseRegion; this test dupp'd a bunch of
  code from there anyways.
M src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
  More detail in log message about what type of event we just got.
M src/main/java/org/apache/hadoop/hbase/master/handler/TotesHRegionInfo.java
  New marker interface; useful testing.
M src/main/java/org/apache/hadoop/hbase/master/handler/ClosedRegionHandler.java
M src/main/java/org/apache/hadoop/hbase/master/handler/OpenedRegionHandler.java
  Implement the new interface.

Added:
    hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/TotesHRegionInfo.java
    hbase/branches/0.90_master_rewrite/src/test/java/org/apache/hadoop/hbase/master/TestZKBasedOpenCloseRegion.java
Removed:
    hbase/branches/0.90_master_rewrite/src/test/java/org/apache/hadoop/hbase/master/TestZKBasedCloseRegion.java
    hbase/branches/0.90_master_rewrite/src/test/java/org/apache/hadoop/hbase/master/TestZKBasedReopenRegion.java
Modified:
    hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
    hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/ClosedRegionHandler.java
    hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/OpenedRegionHandler.java

Modified: hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java?rev=987026&r1=987025&r2=987026&view=diff
==============================================================================
--- hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java (original)
+++ hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java Thu Aug 19 06:01:34 2010
@@ -239,8 +239,9 @@ public class AssignmentManager extends Z
       }
       String encodedName = HRegionInfo.encodeRegionName(data.getRegionName());
       String prettyPrintedRegionName = HRegionInfo.prettyPrint(encodedName);
-      LOG.debug("Handling transition=" + data.getEventType() + ", server=" +
-        data.getServerName() + ", region=" + prettyPrintedRegionName);
+      LOG.debug("Handling transition=" + data.getEventType().name() +
+        "/" + data.getEventType().toString() +
+        ", server=" + data.getServerName() + ", region=" + prettyPrintedRegionName);
       RegionState regionState = regionsInTransition.get(encodedName);
       switch(data.getEventType()) {
 

Modified: hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/ClosedRegionHandler.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/ClosedRegionHandler.java?rev=987026&r1=987025&r2=987026&view=diff
==============================================================================
--- hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/ClosedRegionHandler.java (original)
+++ hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/ClosedRegionHandler.java Thu Aug 19 06:01:34 2010
@@ -37,12 +37,13 @@ import org.apache.zookeeper.KeeperExcept
  * <p>
  * Otherwise, assigns the region to another server.
  */
-public class ClosedRegionHandler extends EventHandler {
+public class ClosedRegionHandler extends EventHandler implements TotesHRegionInfo {
   private static final Log LOG = LogFactory.getLog(ClosedRegionHandler.class);
 
   private final AssignmentManager assignmentManager;
   private final RegionTransitionData data;
   private final HRegionInfo regionInfo;
+
   private final ClosedPriority priority;
 
   private enum ClosedPriority {
@@ -81,6 +82,11 @@ public class ClosedRegionHandler extends
   }
 
   @Override
+  public HRegionInfo getHRegionInfo() {
+    return this.regionInfo;
+  }
+
+  @Override
   public void process() {
     LOG.debug("Handling CLOSED event with data: " + data);
     // Check if this table is being disabled or not

Modified: hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/OpenedRegionHandler.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/OpenedRegionHandler.java?rev=987026&r1=987025&r2=987026&view=diff
==============================================================================
--- hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/OpenedRegionHandler.java (original)
+++ hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/OpenedRegionHandler.java Thu Aug 19 06:01:34 2010
@@ -33,7 +33,7 @@ import org.apache.zookeeper.KeeperExcept
 /**
  * Handles OPENED region event on Master.
  */
-public class OpenedRegionHandler extends EventHandler {
+public class OpenedRegionHandler extends EventHandler implements TotesHRegionInfo {
   private static final Log LOG = LogFactory.getLog(OpenedRegionHandler.class);
 
   private final AssignmentManager assignmentManager;
@@ -79,6 +79,11 @@ public class OpenedRegionHandler extends
   }
 
   @Override
+  public HRegionInfo getHRegionInfo() {
+    return this.regionInfo;
+  }
+
+  @Override
   public void process() {
     LOG.debug("Handling OPENED event; deleting unassigned node with data: " + data);
     // TODO: should we check if this table was disabled and get it closed?

Added: hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/TotesHRegionInfo.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/TotesHRegionInfo.java?rev=987026&view=auto
==============================================================================
--- hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/TotesHRegionInfo.java (added)
+++ hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/handler/TotesHRegionInfo.java Thu Aug 19 06:01:34 2010
@@ -0,0 +1,36 @@
+/**
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * 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.hadoop.hbase.master.handler;
+
+import java.beans.EventHandler;
+
+import org.apache.hadoop.hbase.HRegionInfo;
+
+/**
+ * Implementors tote an HRegionInfo instance.
+ * This is a marker interface that can be put on {@link EventHandler}s that
+ * have an {@link HRegionInfo}.
+ */
+public interface TotesHRegionInfo {
+  /**
+   * @return HRegionInfo instance.
+   */
+  public HRegionInfo getHRegionInfo();
+}

Added: hbase/branches/0.90_master_rewrite/src/test/java/org/apache/hadoop/hbase/master/TestZKBasedOpenCloseRegion.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/src/test/java/org/apache/hadoop/hbase/master/TestZKBasedOpenCloseRegion.java?rev=987026&view=auto
==============================================================================
--- hbase/branches/0.90_master_rewrite/src/test/java/org/apache/hadoop/hbase/master/TestZKBasedOpenCloseRegion.java (added)
+++ hbase/branches/0.90_master_rewrite/src/test/java/org/apache/hadoop/hbase/master/TestZKBasedOpenCloseRegion.java Thu Aug 19 06:01:34 2010
@@ -0,0 +1,346 @@
+/**
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * 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.hadoop.hbase.master;
+
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.MiniHBaseCluster;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.executor.EventHandler;
+import org.apache.hadoop.hbase.executor.EventHandler.EventHandlerListener;
+import org.apache.hadoop.hbase.executor.EventHandler.EventType;
+import org.apache.hadoop.hbase.master.handler.TotesHRegionInfo;
+import org.apache.hadoop.hbase.regionserver.HRegion;
+import org.apache.hadoop.hbase.regionserver.HRegionServer;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.Threads;
+import org.apache.hadoop.hbase.util.Writables;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test open and close of regions using zk.
+ */
+public class TestZKBasedOpenCloseRegion {
+  private static final Log LOG = LogFactory.getLog(TestZKBasedOpenCloseRegion.class);
+  private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
+  private static final String TABLENAME = "TestZKBasedOpenCloseRegion";
+  private static final byte [][] FAMILIES = new byte [][] {Bytes.toBytes("a"),
+    Bytes.toBytes("b"), Bytes.toBytes("c")};
+
+  @BeforeClass public static void beforeAllTests() throws Exception {
+    Configuration c = TEST_UTIL.getConfiguration();
+    c.setBoolean("dfs.support.append", true);
+    c.setInt("hbase.regionserver.info.port", 0);
+    c.setInt("hbase.master.meta.thread.rescanfrequency", 5*1000);
+    TEST_UTIL.startMiniCluster(2);
+    TEST_UTIL.createTable(Bytes.toBytes(TABLENAME), FAMILIES);
+    HTable t = new HTable(TEST_UTIL.getConfiguration(), TABLENAME);
+    int countOfRegions = TEST_UTIL.createMultiRegions(t, getTestFamily());
+    waitUntilAllRegionsAssigned(countOfRegions);
+    addToEachStartKey(countOfRegions);
+  }
+
+  @AfterClass public static void afterAllTests() throws IOException {
+    TEST_UTIL.shutdownMiniCluster();
+  }
+
+  @Before public void setup() throws IOException {
+    if (TEST_UTIL.getHBaseCluster().getLiveRegionServerThreads().size() < 2) {
+      // Need at least two servers.
+      LOG.info("Started new server=" +
+        TEST_UTIL.getHBaseCluster().startRegionServer());
+
+    }
+  }
+
+  /**
+   * Test we reopen a region once closed.
+   * @throws Exception
+   */
+  @Test (timeout=300000) public void testReOpenRegion()
+  throws Exception {
+    MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
+    LOG.info("Number of region servers = " +
+      cluster.getLiveRegionServerThreads().size());
+
+    int rsIdx = 0;
+    HRegionServer regionServer =
+      TEST_UTIL.getHBaseCluster().getRegionServer(rsIdx);
+    Collection<HRegion> regions = regionServer.getOnlineRegions();
+    HRegion region;
+    while((region = regions.iterator().next()) != null) {
+      if(!region.getRegionInfo().isMetaRegion() && !region.getRegionInfo().isRootRegion()) {
+        break;
+      }
+    }
+    LOG.debug("Asking RS to close region " + region.getRegionNameAsString());
+
+    AtomicBoolean closeEventProcessed = new AtomicBoolean(false);
+    AtomicBoolean reopenEventProcessed = new AtomicBoolean(false);
+
+    EventHandlerListener closeListener =
+      new ReopenEventListener(region.getRegionNameAsString(),
+          closeEventProcessed, EventType.RS2ZK_REGION_CLOSED);
+    cluster.getMaster().executorService.
+      registerListener(EventType.RS2ZK_REGION_CLOSED, closeListener);
+
+    EventHandlerListener openListener =
+      new ReopenEventListener(region.getRegionNameAsString(),
+          reopenEventProcessed, EventType.RS2ZK_REGION_OPENED);
+    cluster.getMaster().executorService.
+      registerListener(EventType.RS2ZK_REGION_OPENED, openListener);
+
+    LOG.info("Unassign " + region.getRegionNameAsString());
+    cluster.getMaster().assignmentManager.unassign(region.getRegionInfo());
+
+    synchronized(closeEventProcessed) {
+      closeEventProcessed.wait(3*60*1000);
+    }
+
+    if (!closeEventProcessed.get()) {
+      throw new Exception("Timed out, close event not called on master.");
+    }
+
+    synchronized(reopenEventProcessed) {
+      reopenEventProcessed.wait(3*60*1000);
+    }
+
+    if(!reopenEventProcessed.get()) {
+      throw new Exception("Timed out, open event not called on master after region close.");
+    }
+
+    LOG.info("\n\n\nDone with test, RS informed master successfully.\n\n\n");
+  }
+
+  public static class ReopenEventListener implements EventHandlerListener {
+    private static final Log LOG = LogFactory.getLog(ReopenEventListener.class);
+    String regionName;
+    AtomicBoolean eventProcessed;
+    EventType eventType;
+
+    public ReopenEventListener(String regionName,
+        AtomicBoolean eventProcessed, EventType eventType) {
+      this.regionName = regionName;
+      this.eventProcessed = eventProcessed;
+      this.eventType = eventType;
+    }
+
+    @Override
+    public void beforeProcess(EventHandler event) {
+      if(event.getEventType() == eventType) {
+        LOG.info("Received " + eventType + " and beginning to process it");
+      }
+    }
+
+    @Override
+    public void afterProcess(EventHandler event) {
+      LOG.info("afterProcess(" + event + ")");
+      if(event.getEventType() == eventType) {
+        LOG.info("Finished processing " + eventType);
+        String regionName = "";
+        if(eventType == EventType.RS2ZK_REGION_OPENED) {
+          TotesHRegionInfo hriCarrier = (TotesHRegionInfo)event;
+          regionName = hriCarrier.getHRegionInfo().getRegionNameAsString();
+        } else if(eventType == EventType.RS2ZK_REGION_CLOSED) {
+          TotesHRegionInfo hriCarrier = (TotesHRegionInfo)event;
+          regionName = hriCarrier.getHRegionInfo().getRegionNameAsString();
+        }
+        if(this.regionName.equals(regionName)) {
+          eventProcessed.set(true);
+        }
+        synchronized(eventProcessed) {
+          eventProcessed.notifyAll();
+        }
+      }
+    }
+  }
+
+  @Test (timeout=300000) public void testCloseRegion()
+  throws Exception {
+    LOG.info("Running testCloseRegion");
+    MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
+    LOG.info("Number of region servers = " + cluster.getLiveRegionServerThreads().size());
+
+    int rsIdx = 0;
+    HRegionServer regionServer = TEST_UTIL.getHBaseCluster().getRegionServer(rsIdx);
+    Collection<HRegion> regions = regionServer.getOnlineRegions();
+    HRegion region;
+    while((region = regions.iterator().next()) != null) {
+      if(!region.getRegionInfo().isMetaRegion() && !region.getRegionInfo().isRootRegion()) {
+        break;
+      }
+    }
+    LOG.debug("Asking RS to close region " + region.getRegionNameAsString());
+
+    AtomicBoolean closeEventProcessed = new AtomicBoolean(false);
+    EventHandlerListener listener =
+      new CloseRegionEventListener(region.getRegionNameAsString(),
+          closeEventProcessed);
+    cluster.getMaster().executorService.registerListener(EventType.RS2ZK_REGION_CLOSED, listener);
+
+    cluster.getMaster().assignmentManager.unassign(region.getRegionInfo());
+
+    synchronized(closeEventProcessed) {
+      // wait for 3 minutes
+      closeEventProcessed.wait(3*60*1000);
+    }
+    if(!closeEventProcessed.get()) {
+      throw new Exception("Timed out, close event not called on master.");
+    }
+    else {
+      LOG.info("Done with test, RS informed master successfully.");
+    }
+  }
+
+  public static class CloseRegionEventListener implements EventHandlerListener {
+    private static final Log LOG = LogFactory.getLog(CloseRegionEventListener.class);
+    String regionToClose;
+    AtomicBoolean closeEventProcessed;
+
+    public CloseRegionEventListener(String regionToClose,
+        AtomicBoolean closeEventProcessed) {
+      this.regionToClose = regionToClose;
+      this.closeEventProcessed = closeEventProcessed;
+    }
+
+    @Override
+    public void afterProcess(EventHandler event) {
+      LOG.info("afterProcess(" + event + ")");
+      if(event.getEventType() == EventType.RS2ZK_REGION_CLOSED) {
+        LOG.info("Finished processing CLOSE REGION");
+        TotesHRegionInfo hriCarrier = (TotesHRegionInfo)event;
+        if(regionToClose.equals(hriCarrier.getHRegionInfo().getRegionNameAsString())) {
+          closeEventProcessed.set(true);
+        }
+        synchronized(closeEventProcessed) {
+          closeEventProcessed.notifyAll();
+        }
+      }
+    }
+
+    @Override
+    public void beforeProcess(EventHandler event) {
+      if(event.getEventType() == EventType.M2RS_CLOSE_REGION) {
+        LOG.info("Received CLOSE RPC and beginning to process it");
+      }
+    }
+  }
+
+  private static void waitUntilAllRegionsAssigned(final int countOfRegions)
+  throws IOException {
+    HTable meta = new HTable(TEST_UTIL.getConfiguration(),
+      HConstants.META_TABLE_NAME);
+    while (true) {
+      int rows = 0;
+      Scan scan = new Scan();
+      scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER);
+      ResultScanner s = meta.getScanner(scan);
+      for (Result r = null; (r = s.next()) != null;) {
+        byte [] b =
+          r.getValue(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER);
+        if (b == null || b.length <= 0) {
+          break;
+        }
+        rows++;
+      }
+      s.close();
+      // If I get to here and all rows have a Server, then all have been assigned.
+      if (rows == countOfRegions) {
+        break;
+      }
+      LOG.info("Found=" + rows);
+      Threads.sleep(1000);
+    }
+  }
+
+  /*
+   * Add to each of the regions in .META. a value.  Key is the startrow of the
+   * region (except its 'aaa' for first region).  Actual value is the row name.
+   * @param expected
+   * @return
+   * @throws IOException
+   */
+  private static int addToEachStartKey(final int expected) throws IOException {
+    HTable t = new HTable(TEST_UTIL.getConfiguration(), TABLENAME);
+    HTable meta = new HTable(TEST_UTIL.getConfiguration(),
+        HConstants.META_TABLE_NAME);
+    int rows = 0;
+    Scan scan = new Scan();
+    scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
+    ResultScanner s = meta.getScanner(scan);
+    for (Result r = null; (r = s.next()) != null;) {
+      byte [] b =
+        r.getValue(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
+      if (b == null || b.length <= 0) {
+        break;
+      }
+      HRegionInfo hri = Writables.getHRegionInfo(b);
+      // If start key, add 'aaa'.
+      byte [] row = getStartKey(hri);
+      Put p = new Put(row);
+      p.add(getTestFamily(), getTestQualifier(), row);
+      t.put(p);
+      rows++;
+    }
+    s.close();
+    Assert.assertEquals(expected, rows);
+    return rows;
+  }
+
+  private static byte [] getStartKey(final HRegionInfo hri) {
+    return Bytes.equals(HConstants.EMPTY_START_ROW, hri.getStartKey())?
+        Bytes.toBytes("aaa"): hri.getStartKey();
+  }
+
+  private static byte [] getTestFamily() {
+    return FAMILIES[0];
+  }
+
+  private static byte [] getTestQualifier() {
+    return getTestFamily();
+  }
+
+  public static void main(String args[]) throws Exception {
+    TestZKBasedOpenCloseRegion.beforeAllTests();
+
+    TestZKBasedOpenCloseRegion test = new TestZKBasedOpenCloseRegion();
+    test.setup();
+    test.testCloseRegion();
+
+    TestZKBasedOpenCloseRegion.afterAllTests();
+  }
+}