hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From t...@apache.org
Subject svn commit: r1170468 - in /hbase/trunk: ./ src/main/java/org/apache/hadoop/hbase/ src/main/java/org/apache/hadoop/hbase/regionserver/ src/test/java/org/apache/hadoop/hbase/regionserver/
Date Wed, 14 Sep 2011 08:07:33 GMT
Author: todd
Date: Wed Sep 14 08:07:33 2011
New Revision: 1170468

URL: http://svn.apache.org/viewvc?rev=1170468&view=rev
Log:
HBASE-4381  Refactor split decisions into a split policy class.

Added:
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/ConstantSizeRegionSplitPolicy.java
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionSplitPolicy.java
    hbase/trunk/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java
Modified:
    hbase/trunk/CHANGES.txt
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/HConstants.java
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/HTableDescriptor.java
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/Store.java
    hbase/trunk/src/test/java/org/apache/hadoop/hbase/regionserver/TestStore.java

Modified: hbase/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hbase/trunk/CHANGES.txt?rev=1170468&r1=1170467&r2=1170468&view=diff
==============================================================================
--- hbase/trunk/CHANGES.txt (original)
+++ hbase/trunk/CHANGES.txt Wed Sep 14 08:07:33 2011
@@ -479,6 +479,7 @@ Release 0.91.0 - Unreleased
                (Harsh J)
    HBASE-4287  If region opening fails, change region in transition into
                a FAILED_OPEN state so that it can be retried quickly. (todd)
+   HBASE-4381  Refactor split decisions into a split policy class. (todd)
 
   TASKS
    HBASE-3559  Move report of split to master OFF the heartbeat channel

Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/HConstants.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/HConstants.java?rev=1170468&r1=1170467&r2=1170468&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/HConstants.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/HConstants.java Wed Sep 14 08:07:33
2011
@@ -488,7 +488,10 @@ public final class HConstants {
   public static final String HBASE_MASTER_LOGCLEANER_PLUGINS =
       "hbase.master.logcleaner.plugins";
 
-   /*
+  public static final String HBASE_REGION_SPLIT_POLICY_KEY =
+    "hbase.regionserver.region.split.policy";
+
+  /*
     * Minimum percentage of free heap necessary for a successful cluster startup.
     */
   public static final float HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD = 0.2f;

Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/HTableDescriptor.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/HTableDescriptor.java?rev=1170468&r1=1170467&r2=1170468&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/HTableDescriptor.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/HTableDescriptor.java Wed Sep 14 08:07:33
2011
@@ -63,6 +63,12 @@ public class HTableDescriptor implements
   public static final String MAX_FILESIZE = "MAX_FILESIZE";
   public static final ImmutableBytesWritable MAX_FILESIZE_KEY =
     new ImmutableBytesWritable(Bytes.toBytes(MAX_FILESIZE));
+
+  // The class which determines when a region should split
+  public static final String SPLIT_POLICY = "SPLIT_POLICY";
+  public static final ImmutableBytesWritable SPLIT_POLICY_KEY =
+    new ImmutableBytesWritable(Bytes.toBytes(SPLIT_POLICY));
+  
   public static final String READONLY = "READONLY";
   public static final ImmutableBytesWritable READONLY_KEY =
     new ImmutableBytesWritable(Bytes.toBytes(READONLY));
@@ -422,6 +428,15 @@ public class HTableDescriptor implements
       return Long.valueOf(Bytes.toString(value)).longValue();
     return HConstants.DEFAULT_MAX_FILE_SIZE;
   }
+  
+  /**
+   * @return the class name of the region split policy for this table.
+   * If this returns null, the default constant size based split policy
+   * is used.
+   */
+  public String getRegionSplitPolicyClassName() {
+    return getValue(SPLIT_POLICY);
+  }
 
   /** @param name name of table */
   public void setName(byte[] name) {

Added: hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/ConstantSizeRegionSplitPolicy.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/ConstantSizeRegionSplitPolicy.java?rev=1170468&view=auto
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/ConstantSizeRegionSplitPolicy.java
(added)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/ConstantSizeRegionSplitPolicy.java
Wed Sep 14 08:07:33 2011
@@ -0,0 +1,67 @@
+/**
+ * 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.regionserver;
+
+import org.apache.hadoop.hbase.HConstants;
+
+/**
+ * A {@link RegionSplitPolicy} implementation which splits a region
+ * as soon as any of its store files exceeds a maximum configurable
+ * size.
+ */
+class ConstantSizeRegionSplitPolicy extends RegionSplitPolicy {
+  private long desiredMaxFileSize;
+
+  @Override
+  void configureForRegion(HRegion region) {
+    super.configureForRegion(region);
+    long maxFileSize = region.getTableDesc().getMaxFileSize();
+
+    // By default we split region if a file > HConstants.DEFAULT_MAX_FILE_SIZE.
+    if (maxFileSize == HConstants.DEFAULT_MAX_FILE_SIZE) {
+      maxFileSize = getConf().getLong("hbase.hregion.max.filesize",
+        HConstants.DEFAULT_MAX_FILE_SIZE);
+    }
+    this.desiredMaxFileSize = maxFileSize;
+  }
+  
+  @Override
+  boolean shouldSplit() {
+    boolean force = region.shouldForceSplit();
+    boolean foundABigStore = false;
+    
+    for (Store store : region.getStores().values()) {
+      // If any of the stores are unable to split (eg they contain reference files)
+      // then don't split
+      if ((!store.canSplit())) {
+        return false;
+      }
+
+      // Mark if any store is big enough
+      if (store.getSize() > desiredMaxFileSize) {
+        foundABigStore = true;
+      }
+    }
+
+    return foundABigStore || force;
+  }
+
+  long getDesiredMaxFileSize() {
+    return desiredMaxFileSize;
+  }
+}

Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java?rev=1170468&r1=1170467&r2=1170468&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java Wed Sep 14
08:07:33 2011
@@ -257,7 +257,7 @@ public class HRegion implements HeapSize
   private final ReentrantReadWriteLock updatesLock =
     new ReentrantReadWriteLock();
   private boolean splitRequest;
-  private byte[] splitPoint = null;
+  private byte[] explicitSplitPoint = null;
 
   private final ReadWriteConsistencyControl rwcc =
       new ReadWriteConsistencyControl();
@@ -270,6 +270,7 @@ public class HRegion implements HeapSize
    */
   public final static String REGIONINFO_FILE = ".regioninfo";
   private HTableDescriptor htableDescriptor = null;
+  private RegionSplitPolicy splitPolicy;
 
   /**
    * Should only be used for testing purposes
@@ -419,6 +420,10 @@ public class HRegion implements HeapSize
     this.writestate.setReadOnly(this.htableDescriptor.isReadOnly());
 
     this.writestate.compacting = 0;
+    
+    // Initialize split policy
+    this.splitPolicy = RegionSplitPolicy.create(this, conf);
+    
     this.lastFlushTime = EnvironmentEdgeManager.currentTimeMillis();
     // Use maximum of log sequenceid or that which was found in stores
     // (particularly if no recovered edits, seqid will be -1).
@@ -1285,7 +1290,7 @@ public class HRegion implements HeapSize
     }
     // look across all the HStores for this region and determine what the
     // closest key is across all column families, since the data may be sparse
-    checkRow(row);
+    checkRow(row, "getClosestRowBefore");
     startRegionOperation();
     this.readRequestsCount.increment();
     try {
@@ -2403,10 +2408,10 @@ public class HRegion implements HeapSize
   //////////////////////////////////////////////////////////////////////////////
 
   /** Make sure this is a valid row for the HRegion */
-  private void checkRow(final byte [] row) throws IOException {
+  private void checkRow(final byte [] row, String op) throws IOException {
     if(!rowIsInRange(regionInfo, row)) {
       throw new WrongRegionException("Requested row out of range for " +
-          "HRegion " + this + ", startKey='" +
+          op + "on HRegion " + this + ", startKey='" +
           Bytes.toStringBinary(regionInfo.getStartKey()) + "', getEndKey()='" +
           Bytes.toStringBinary(regionInfo.getEndKey()) + "', row='" +
           Bytes.toStringBinary(row) + "'");
@@ -2454,7 +2459,7 @@ public class HRegion implements HeapSize
    */
   private Integer internalObtainRowLock(final byte[] row, boolean waitForLock)
       throws IOException {
-    checkRow(row);
+    checkRow(row, "row lock");
     startRegionOperation();
     try {
       HashedBytes rowKey = new HashedBytes(row);
@@ -3490,7 +3495,7 @@ public class HRegion implements HeapSize
   throws IOException {
     // TODO: Use RWCC to make this set of increments atomic to reads
     byte [] row = increment.getRow();
-    checkRow(row);
+    checkRow(row, "increment");
     TimeRange tr = increment.getTimeRange();
     boolean flush = false;
     WALEdit walEdits = null;
@@ -3591,7 +3596,7 @@ public class HRegion implements HeapSize
   public long incrementColumnValue(byte [] row, byte [] family,
       byte [] qualifier, long amount, boolean writeToWAL)
   throws IOException {
-    checkRow(row);
+    checkRow(row, "increment");
     boolean flush = false;
     boolean wrongLength = false;
     // Lock row
@@ -3877,8 +3882,8 @@ public class HRegion implements HeapSize
     return this.splitRequest;
   }
 
-  byte[] getSplitPoint() {
-    return this.splitPoint;
+  byte[] getExplicitSplitPoint() {
+    return this.explicitSplitPoint;
   }
 
   void forceSplit(byte[] sp) {
@@ -3886,7 +3891,7 @@ public class HRegion implements HeapSize
     //        therefore, no reason to clear this value
     this.splitRequest = true;
     if (sp != null) {
-      this.splitPoint = sp;
+      this.explicitSplitPoint = sp;
     }
   }
 
@@ -3908,20 +3913,33 @@ public class HRegion implements HeapSize
    * is based on the size of the store.
    */
   public byte[] checkSplit() {
-    if (this.splitPoint != null) {
-      return this.splitPoint;
-    }
-    byte[] splitPointFromLargestStore = null;
-    long largestStoreSize = 0;
-    for (Store s : stores.values()) {
-      byte[] splitPoint = s.checkSplit();
-      long storeSize = s.getSize();
-      if (splitPoint != null && largestStoreSize < storeSize) {
-        splitPointFromLargestStore = splitPoint;
-        largestStoreSize = storeSize;
+    // Can't split META
+    if (getRegionInfo().isMetaRegion()) {
+      if (shouldForceSplit()) {
+        LOG.warn("Cannot split meta regions in HBase 0.20 and above");
       }
+      return null;
+    }
+
+    if (this.explicitSplitPoint != null) {
+      return this.explicitSplitPoint;
+    }
+    
+    if (!splitPolicy.shouldSplit()) {
+      return null;
     }
-    return splitPointFromLargestStore;
+    
+    byte[] ret = splitPolicy.getSplitPoint();
+    
+    if (ret != null) {
+      try {
+        checkRow(ret, "calculated split");
+      } catch (IOException e) {
+        LOG.error("Ignoring invalid split", e);
+        return null;
+      }
+    }        
+    return ret;
   }
 
   /**

Added: hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionSplitPolicy.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionSplitPolicy.java?rev=1170468&view=auto
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionSplitPolicy.java
(added)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionSplitPolicy.java
Wed Sep 14 08:07:33 2011
@@ -0,0 +1,122 @@
+/**
+ * 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.regionserver;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.conf.Configured;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.util.ReflectionUtils;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * A split policy determines when a region should be split.
+ * {@see ConstantSizeRegionSplitPolicy}
+ */
+abstract class RegionSplitPolicy extends Configured {
+  private static final Class<ConstantSizeRegionSplitPolicy>
+    DEFAULT_SPLIT_POLICY_CLASS = ConstantSizeRegionSplitPolicy.class;
+
+  /**
+   * The region configured for this split policy.
+   */
+  protected HRegion region;
+  
+  /**
+   * Upon construction, this method will be called with the region
+   * to be governed. It will be called once and only once.
+   */
+  void configureForRegion(HRegion region) {
+    Preconditions.checkState(
+        this.region == null,
+        "Policy already configured for region {}",
+        this.region);
+    
+    this.region = region;
+  }
+
+  /**
+   * @return true if the specified region should be split.
+   */
+  abstract boolean shouldSplit();
+
+  /**
+   * @return the key at which the region should be split, or null
+   * if it cannot be split. This will only be called if shouldSplit
+   * previously returned true.
+   */
+  byte[] getSplitPoint() {
+    Map<byte[], Store> stores = region.getStores();
+
+    byte[] splitPointFromLargestStore = null;
+    long largestStoreSize = 0;
+    for (Store s : stores.values()) {
+      byte[] splitPoint = s.getSplitPoint();
+      long storeSize = s.getSize();
+      if (splitPoint != null && largestStoreSize < storeSize) {
+        splitPointFromLargestStore = splitPoint;
+        largestStoreSize = storeSize;
+      }
+    }
+    
+    return splitPointFromLargestStore;
+  }
+
+  /**
+   * Create the RegionSplitPolicy configured for the given table.
+   * Each
+   * @param htd
+   * @param conf
+   * @return
+   * @throws IOException
+   */
+  public static RegionSplitPolicy create(HRegion region,
+      Configuration conf) throws IOException {
+    
+    Class<? extends RegionSplitPolicy> clazz = getSplitPolicyClass(
+        region.getTableDesc(), conf);
+    RegionSplitPolicy policy = ReflectionUtils.newInstance(clazz, conf);
+    policy.configureForRegion(region);
+    return policy;
+  }
+  
+  static Class<? extends RegionSplitPolicy> getSplitPolicyClass(
+      HTableDescriptor htd, Configuration conf) throws IOException {
+    String className = htd.getRegionSplitPolicyClassName();
+    if (className == null) {
+      className = conf.get(HConstants.HBASE_REGION_SPLIT_POLICY_KEY,
+          DEFAULT_SPLIT_POLICY_CLASS.getName());
+    }
+
+    try {
+      Class<? extends RegionSplitPolicy> clazz =
+        Class.forName(className).asSubclass(RegionSplitPolicy.class);
+      return clazz;
+    } catch (Exception  e) {
+      throw new IOException(
+          "Unable to load configured region split policy '" +
+          className + "' for table '" + htd.getNameAsString() + "'",
+          e);
+    }
+  }
+
+}

Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/Store.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/Store.java?rev=1170468&r1=1170467&r2=1170468&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/Store.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/Store.java Wed Sep 14 08:07:33
2011
@@ -110,7 +110,6 @@ public class Store implements HeapSize {
   volatile boolean forceMajor = false;
   /* how many bytes to write between status checks */
   static int closeCheckInterval = 0;
-  private final long desiredMaxFileSize;
   private final int blockingStoreFileCount;
   private volatile long storeSize = 0L;
   private volatile long totalUncompressedBytes = 0L;
@@ -200,18 +199,6 @@ public class Store implements HeapSize {
     this.inMemory = family.isInMemory();
     long maxFileSize = 0L;
     HTableDescriptor hTableDescriptor = region.getTableDesc();
-    if (hTableDescriptor != null) {
-      maxFileSize = hTableDescriptor.getMaxFileSize();
-    } else {
-      maxFileSize = HConstants.DEFAULT_MAX_FILE_SIZE;
-    }
-
-    // By default we split region if a file > HConstants.DEFAULT_MAX_FILE_SIZE.
-    if (maxFileSize == HConstants.DEFAULT_MAX_FILE_SIZE) {
-      maxFileSize = conf.getLong("hbase.hregion.max.filesize",
-        HConstants.DEFAULT_MAX_FILE_SIZE);
-    }
-    this.desiredMaxFileSize = maxFileSize;
     this.blockingStoreFileCount =
       conf.getInt("hbase.hstore.blockingStoreFiles", 7);
 
@@ -1471,49 +1458,54 @@ public class Store implements HeapSize {
     return foundCandidate;
   }
 
+  public boolean canSplit() {
+    this.lock.readLock().lock();
+    try {
+      // Not splitable if we find a reference store file present in the store.
+      for (StoreFile sf : storefiles) {
+        if (sf.isReference()) {
+          if (LOG.isDebugEnabled()) {
+            LOG.debug(sf + " is not splittable");
+          }
+          return false;
+        }
+      }
+      
+      return true;
+    } finally {
+      this.lock.readLock().unlock();
+    }
+  }
   /**
    * Determines if Store should be split
    * @return byte[] if store should be split, null otherwise.
    */
-  public byte[] checkSplit() {
+  public byte[] getSplitPoint() {
     this.lock.readLock().lock();
     try {
-      boolean force = this.region.shouldForceSplit();
       // sanity checks
       if (this.storefiles.isEmpty()) {
         return null;
       }
-      if (!force && storeSize < this.desiredMaxFileSize) {
-        return null;
-      }
-
-      if (this.region.getRegionInfo().isMetaRegion()) {
-        if (force) {
-          LOG.warn("Cannot split meta regions in HBase 0.20");
-        }
-        return null;
-      }
+      // Should already be enforced by the split policy!
+      assert !this.region.getRegionInfo().isMetaRegion();
 
       // Not splitable if we find a reference store file present in the store.
-      boolean splitable = true;
       long maxSize = 0L;
       StoreFile largestSf = null;
       for (StoreFile sf : storefiles) {
-        if (splitable) {
-          splitable = !sf.isReference();
-          if (!splitable) {
-            // RETURN IN MIDDLE OF FUNCTION!!! If not splitable, just return.
-            if (LOG.isDebugEnabled()) {
-              LOG.debug(sf +  " is not splittable");
-            }
-            return null;
-          }
+        if (sf.isReference()) {
+          // Should already be enforced since we return false in this case
+          assert false : "getSplitPoint() called on a region that can't split!";
+          return null;
         }
+
         StoreFile.Reader r = sf.getReader();
         if (r == null) {
           LOG.warn("Storefile " + sf + " Reader is null");
           continue;
         }
+        
         long size = r.length();
         if (size > maxSize) {
           // This is the largest one so far
@@ -1521,10 +1513,7 @@ public class Store implements HeapSize {
           largestSf = sf;
         }
       }
-      // if the user explicit set a split point, use that
-      if (this.region.getSplitPoint() != null) {
-        return this.region.getSplitPoint();
-      }
+
       StoreFile.Reader r = largestSf.getReader();
       if (r == null) {
         LOG.warn("Storefile " + largestSf + " Reader is null");

Added: hbase/trunk/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java?rev=1170468&view=auto
==============================================================================
--- hbase/trunk/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java
(added)
+++ hbase/trunk/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java
Wed Sep 14 08:07:33 2011
@@ -0,0 +1,141 @@
+/**
+ * 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.regionserver;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.TreeMap;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TestRegionSplitPolicy {
+
+  private Configuration conf;
+  private HTableDescriptor htd;
+  private HRegion mockRegion;
+  private TreeMap<byte[], Store> stores;
+
+  @Before
+  public void setupMocks() {
+    conf = HBaseConfiguration.create();
+
+    HRegionInfo hri = new HRegionInfo(Bytes.toBytes("testtable"));
+
+    htd = new HTableDescriptor();
+    mockRegion = Mockito.mock(HRegion.class);
+    Mockito.doReturn(htd).when(mockRegion).getTableDesc();
+    Mockito.doReturn(hri).when(mockRegion).getRegionInfo();
+    
+    stores = new TreeMap<byte[], Store>(Bytes.BYTES_COMPARATOR);
+    Mockito.doReturn(stores).when(mockRegion).getStores();
+  }
+  
+  @Test
+  public void testCreateDefault() throws IOException {
+    conf.setLong("hbase.hregion.max.filesize", 1234L);
+    
+    // Using a default HTD, should pick up the file size from
+    // configuration.
+    ConstantSizeRegionSplitPolicy policy =
+        (ConstantSizeRegionSplitPolicy)RegionSplitPolicy.create(
+            mockRegion, conf);
+    assertEquals(1234L, policy.getDesiredMaxFileSize());
+    
+    // If specified in HTD, should use that
+    htd.setMaxFileSize(9999L);
+    policy = (ConstantSizeRegionSplitPolicy)RegionSplitPolicy.create(
+        mockRegion, conf);
+    assertEquals(9999L, policy.getDesiredMaxFileSize());    
+  }
+  
+  @Test
+  public void testConstantSizePolicy() throws IOException {
+    htd.setMaxFileSize(1024L);
+    
+    ConstantSizeRegionSplitPolicy policy =
+      (ConstantSizeRegionSplitPolicy)RegionSplitPolicy.create(mockRegion, conf);
+    
+    // For no stores, should not split
+    assertFalse(policy.shouldSplit());
+
+    // Add a store above the requisite size. Should split.
+    Store mockStore = Mockito.mock(Store.class);
+    Mockito.doReturn(2000L).when(mockStore).getSize();
+    Mockito.doReturn(true).when(mockStore).canSplit();
+    stores.put(new byte[]{1}, mockStore);
+    
+    assertTrue(policy.shouldSplit());
+    
+    // Act as if there's a reference file or some other reason it can't split.
+    // This should prevent splitting even though it's big enough.
+    Mockito.doReturn(false).when(mockStore).canSplit();
+    assertFalse(policy.shouldSplit());
+
+    // Reset splittability after above
+    Mockito.doReturn(true).when(mockStore).canSplit();
+    
+    // Set to a small size but turn on forceSplit. Should result in a split.
+    Mockito.doReturn(true).when(mockRegion).shouldForceSplit();
+    Mockito.doReturn(100L).when(mockStore).getSize();
+    assertTrue(policy.shouldSplit());
+    
+    // Turn off forceSplit, should not split
+    Mockito.doReturn(false).when(mockRegion).shouldForceSplit();
+    assertFalse(policy.shouldSplit());
+  }
+  
+  @Test
+  public void testGetSplitPoint() throws IOException {
+    ConstantSizeRegionSplitPolicy policy =
+      (ConstantSizeRegionSplitPolicy)RegionSplitPolicy.create(mockRegion, conf);
+    
+    // For no stores, should not split
+    assertFalse(policy.shouldSplit());
+    assertNull(policy.getSplitPoint());
+    
+    // Add a store above the requisite size. Should split.
+    Store mockStore = Mockito.mock(Store.class);
+    Mockito.doReturn(2000L).when(mockStore).getSize();
+    Mockito.doReturn(true).when(mockStore).canSplit();
+    Mockito.doReturn(Bytes.toBytes("store 1 split"))
+      .when(mockStore).getSplitPoint();
+    stores.put(new byte[]{1}, mockStore);
+
+    assertEquals("store 1 split",
+        Bytes.toString(policy.getSplitPoint()));
+    
+    // Add a bigger store. The split point should come from that one
+    Store mockStore2 = Mockito.mock(Store.class);
+    Mockito.doReturn(4000L).when(mockStore2).getSize();
+    Mockito.doReturn(true).when(mockStore2).canSplit();
+    Mockito.doReturn(Bytes.toBytes("store 2 split"))
+      .when(mockStore2).getSplitPoint();
+    stores.put(new byte[]{2}, mockStore2);
+    
+    assertEquals("store 2 split",
+        Bytes.toString(policy.getSplitPoint()));
+  }
+}

Modified: hbase/trunk/src/test/java/org/apache/hadoop/hbase/regionserver/TestStore.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/test/java/org/apache/hadoop/hbase/regionserver/TestStore.java?rev=1170468&r1=1170467&r2=1170468&view=diff
==============================================================================
--- hbase/trunk/src/test/java/org/apache/hadoop/hbase/regionserver/TestStore.java (original)
+++ hbase/trunk/src/test/java/org/apache/hadoop/hbase/regionserver/TestStore.java Wed Sep
14 08:07:33 2011
@@ -700,9 +700,9 @@ public class TestStore extends TestCase 
    */
   public void testSplitWithEmptyColFam() throws IOException {
     init(this.getName());
-    assertNull(store.checkSplit());
+    assertNull(store.getSplitPoint());
     store.getHRegion().forceSplit(null);
-    assertNull(store.checkSplit());
+    assertNull(store.getSplitPoint());
     store.getHRegion().clearSplit_TESTS_ONLY();
   }
 }



Mime
View raw message