You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ns...@apache.org on 2011/10/11 04:10:12 UTC

svn commit: r1181458 - in /hbase/branches/0.89/src: main/java/org/apache/hadoop/hbase/ main/java/org/apache/hadoop/hbase/client/ main/java/org/apache/hadoop/hbase/master/ main/java/org/apache/hadoop/hbase/regionserver/ test/java/org/apache/hadoop/hbase...

Author: nspiegelberg
Date: Tue Oct 11 02:10:11 2011
New Revision: 1181458

URL: http://svn.apache.org/viewvc?rev=1181458&view=rev
Log:
Explicit Split Points

Summary:
Added the ability to explicitly split an existing region at a
user-specified point.  Note that significant changes will be required
for 0.90 version.

Test Plan:
- mvn test -Dtest=TestHeapSize
 - mvn test -Dtest=TestAdmin
 - mvn test (underway)

DiffCamp Revision: 191101
Reviewed By: kannan
Reviewers: jgray, kannan, kranganathan
Commenters: jgray
CC: jgray, nspiegelberg, kannan
Tasks:
#443065: increase the number of splits

Revert Plan:
OK

Modified:
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/HConstants.java
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/Store.java
    hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java
    hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/HConstants.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/HConstants.java?rev=1181458&r1=1181457&r2=1181458&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/HConstants.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/HConstants.java Tue Oct 11 02:10:11 2011
@@ -307,7 +307,8 @@ public final class HConstants {
     TABLE_FLUSH,
     TABLE_MAJOR_COMPACT,
     TABLE_SET_HTD,
-    TABLE_SPLIT
+    TABLE_SPLIT,
+    TABLE_EXPLICIT_SPLIT
   }
 
   /**

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java?rev=1181458&r1=1181457&r2=1181458&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java Tue Oct 11 02:10:11 2011
@@ -127,6 +127,7 @@ public class HRegionInfo extends Version
   private transient byte [] regionName = HConstants.EMPTY_BYTE_ARRAY;
   private String regionNameStr = "";
   private boolean split = false;
+  private byte [] splitPoint = null;
   private byte [] startKey = HConstants.EMPTY_BYTE_ARRAY;
   protected HTableDescriptor tableDesc = null;
   private int hashCode = -1;
@@ -475,6 +476,22 @@ public class HRegionInfo extends Version
   }
 
   /**
+   * @return point to explicitly split the region on
+   */
+  public byte[] getSplitPoint() {
+    return (this.splitPoint != null && this.splitPoint.length > 0)
+      ? this.splitPoint : null;
+  }
+
+  /**
+   * @param splitPoint set split status & position to split on
+   */
+  public void setSplitPoint(byte[] splitPoint) {
+    this.split = true;
+    this.splitPoint = splitPoint;
+  }
+
+  /**
    * @return True if this region is offline.
    */
   public boolean isOffline() {
@@ -547,6 +564,9 @@ public class HRegionInfo extends Version
     out.writeLong(regionId);
     Bytes.writeByteArray(out, regionName);
     out.writeBoolean(split);
+    if (split) {
+      Bytes.writeByteArray(out, splitPoint);
+    }
     Bytes.writeByteArray(out, startKey);
     tableDesc.write(out);
     out.writeInt(hashCode);
@@ -561,6 +581,9 @@ public class HRegionInfo extends Version
     this.regionName = Bytes.readByteArray(in);
     this.regionNameStr = Bytes.toStringBinary(this.regionName);
     this.split = in.readBoolean();
+    if (this.split) {
+      this.splitPoint = Bytes.readByteArray(in);
+    }
     this.startKey = Bytes.readByteArray(in);
     this.tableDesc.readFields(in);
     this.hashCode = in.readInt();

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java?rev=1181458&r1=1181457&r2=1181458&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java Tue Oct 11 02:10:11 2011
@@ -761,8 +761,8 @@ public class HBaseAdmin {
   }
 
   /**
-   * Split a table or an individual region.
-   * Asynchronous operation.
+   * Split a table or an individual region.  Implicitly finds an optimal split
+   * point.  Asynchronous operation.
    *
    * @param tableNameOrRegionName table to region to split
    * @throws IOException if a remote or network exception occurs
@@ -771,6 +771,27 @@ public class HBaseAdmin {
     modifyTable(tableNameOrRegionName, HConstants.Modify.TABLE_SPLIT);
   }
 
+  /**
+   * Split a table or an individual region.
+   * Asynchronous operation.
+   *
+   * @param tableNameOrRegionName table to region to split
+   * @param splitPoint the explicit position to split on
+   * @throws IOException if a remote or network exception occurs
+   */
+  public void split(final byte [] tableNameOrRegionName,
+      final byte [] splitPoint) throws IOException {
+    if (tableNameOrRegionName == null) {
+      throw new IllegalArgumentException("Pass a table name or region name");
+    }
+    byte [] tableName = tableExists(tableNameOrRegionName)?
+      tableNameOrRegionName: null;
+    byte [] regionName = tableName == null? tableNameOrRegionName: null;
+    Object [] args = regionName == null?
+      new byte [][] {splitPoint}: new byte [][] {regionName, splitPoint};
+    modifyTable(tableName, HConstants.Modify.TABLE_EXPLICIT_SPLIT, args);
+  }
+
   /*
    * Call modifyTable using passed tableName or region name String.  If no
    * such table, presume we have been passed a region name.
@@ -840,19 +861,13 @@ public class HBaseAdmin {
 
       case TABLE_COMPACT:
       case TABLE_SPLIT:
+      case TABLE_EXPLICIT_SPLIT:
       case TABLE_MAJOR_COMPACT:
       case TABLE_FLUSH:
         if (args != null && args.length > 0) {
-          arr = new Writable[1];
-          if (args[0] instanceof byte[]) {
-            arr[0] = new ImmutableBytesWritable((byte[])args[0]);
-          } else if (args[0] instanceof ImmutableBytesWritable) {
-            arr[0] = (ImmutableBytesWritable)args[0];
-          } else if (args[0] instanceof String) {
-            arr[0] = new ImmutableBytesWritable(Bytes.toBytes((String)args[0]));
-          } else {
-            throw new IllegalArgumentException("Requires byte[], String, or" +
-              "ImmutableBytesWritable");
+          arr = new Writable[args.length];
+          for (int i = 0; i < args.length; i++) {
+            arr[i] = toWritable(args[i]);
           }
         }
         this.master.modifyTable(tableName, op, arr);
@@ -864,18 +879,7 @@ public class HBaseAdmin {
         }
         arr = new Writable[args.length];
         for (int i = 0; i < args.length; i++) {
-          if (args[i] instanceof byte[]) {
-            arr[i] = new ImmutableBytesWritable((byte[])args[i]);
-          } else if (args[i] instanceof ImmutableBytesWritable) {
-            arr[i] = (ImmutableBytesWritable)args[i];
-          } else if (args[i] instanceof String) {
-            arr[i] = new ImmutableBytesWritable(Bytes.toBytes((String)args[i]));
-          } else if (args[i] instanceof Boolean) {
-            arr[i] = new BooleanWritable((Boolean) args[i]);
-          } else {
-            throw new IllegalArgumentException("Requires byte [] or " +
-              "ImmutableBytesWritable, not " + args[i]);
-          }
+          arr[i] = toWritable(args[i]);
         }
         this.master.modifyTable(tableName, op, arr);
         break;
@@ -888,6 +892,24 @@ public class HBaseAdmin {
     }
   }
 
+  private static Writable toWritable(Object o) {
+    if (o == null) {
+      return null;
+    }
+    if (o instanceof byte[]) {
+      return new ImmutableBytesWritable((byte[])o);
+    } else if (o instanceof ImmutableBytesWritable) {
+      return (ImmutableBytesWritable)o;
+    } else if (o instanceof String) {
+      return new ImmutableBytesWritable(Bytes.toBytes((String)o));
+    } else if (o instanceof Boolean) {
+      return new BooleanWritable((Boolean) o);
+    } else {
+      throw new IllegalArgumentException("Requires byte [] or " +
+        "ImmutableBytesWritable, not " + o.getClass() + " : " + o);
+    }
+  }
+
   /**
    * Shuts down the HBase instance
    * @throws IOException if a remote or network exception occurs

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/master/HMaster.java?rev=1181458&r1=1181457&r2=1181458&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/master/HMaster.java Tue Oct 11 02:10:11 2011
@@ -64,6 +64,7 @@ import org.apache.hadoop.hbase.MasterNot
 import org.apache.hadoop.hbase.MiniZooKeeperCluster;
 import org.apache.hadoop.hbase.RemoteExceptionHandler;
 import org.apache.hadoop.hbase.TableExistsException;
+import org.apache.hadoop.hbase.HConstants.Modify;
 import org.apache.hadoop.hbase.client.Get;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
 import org.apache.hadoop.hbase.client.MetaScanner;
@@ -1076,6 +1077,42 @@ public class HMaster extends Thread impl
       }
       break;
 
+    // format : {tableName row | region} splitPoint
+    case TABLE_EXPLICIT_SPLIT:
+      if (args == null || args.length < (tableName == null? 2 : 1)) {
+        throw new IOException("incorrect number of arguments given");
+      }
+      Pair<HRegionInfo,HServerAddress> pair = null;
+      byte[] splitPoint = null;
+
+      // split a single region
+      if(tableName == null) {
+        byte [] regionName = ((ImmutableBytesWritable)args[0]).get();
+        pair = getTableRegionFromName(regionName);
+        splitPoint = ((ImmutableBytesWritable)args[1]).get();
+      } else {
+        splitPoint = ((ImmutableBytesWritable)args[0]).get();
+        pair = getTableRegionForRow(tableName, splitPoint);
+      }
+      if (pair == null) {
+        throw new IOException("couldn't find RegionInfo from region name");
+      } else if (splitPoint == null) {
+        throw new IOException("must give explicit split point");
+      } else if (!pair.getFirst().containsRow(splitPoint)) {
+        throw new IOException("split point outside specified region's range");
+      }
+      HRegionInfo r = pair.getFirst();
+      r.setSplitPoint(splitPoint);
+      LOG.info("About to " + op.toString() + " on " +
+               Bytes.toString(pair.getFirst().getTableDesc().getName()) +
+               " at " + Bytes.toString(splitPoint) +
+               " and pair is " + pair);
+      if (pair.getSecond() != null) {
+        this.regionManager.startAction(pair.getFirst().getRegionName(),
+          pair.getFirst(), pair.getSecond(), Modify.TABLE_SPLIT);
+      }
+      break;
+
     case CLOSE_REGION:
       if (args == null || args.length < 1 || args.length > 2) {
         throw new IOException("Requires at least a region name; " +

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java?rev=1181458&r1=1181457&r2=1181458&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java Tue Oct 11 02:10:11 2011
@@ -234,6 +234,7 @@ public class HRegion implements HeapSize
     new ReentrantReadWriteLock();
   private final Object splitLock = new Object();
   private boolean splitRequest;
+  private byte[] splitPoint = null;
 
   private final ReadWriteConsistencyControl rwcc =
       new ReadWriteConsistencyControl();
@@ -881,6 +882,10 @@ public class HRegion implements HeapSize
           writestate.notifyAll();
         }
       }
+      if (splitRow != null) {
+        assert splitPoint == null || Bytes.equals(splitRow, splitPoint);
+        this.splitPoint = null; // clear the split point (if set)
+      }
       return splitRow;
     } finally {
       splitsAndClosesLock.readLock().unlock();
@@ -3139,8 +3144,8 @@ public class HRegion implements HeapSize
   }
 
   public static final long FIXED_OVERHEAD = ClassSize.align(
-      (4 * Bytes.SIZEOF_LONG) + Bytes.SIZEOF_BOOLEAN +
-      (22 * ClassSize.REFERENCE) + ClassSize.OBJECT + Bytes.SIZEOF_INT);
+      (4 * Bytes.SIZEOF_LONG) + Bytes.SIZEOF_BOOLEAN + ClassSize.ARRAY +
+      (23 * ClassSize.REFERENCE) + ClassSize.OBJECT + Bytes.SIZEOF_INT);
 
   public static final long DEEP_OVERHEAD = ClassSize.align(FIXED_OVERHEAD +
       ClassSize.OBJECT + (2 * ClassSize.ATOMIC_BOOLEAN) +
@@ -3243,6 +3248,14 @@ public class HRegion implements HeapSize
     return old;
   }
 
+  byte[] getSplitPoint() {
+    return this.splitPoint;
+  }
+
+  void setSplitPoint(byte[] sp) {
+    this.splitPoint = sp;
+  }
+
   /**
    * @return The priority that this region should have in the compaction queue
    */

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java?rev=1181458&r1=1181457&r2=1181458&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java Tue Oct 11 02:10:11 2011
@@ -1349,6 +1349,7 @@ public class HRegionServer implements HR
               region = getRegion(info.getRegionName());
               region.flushcache();
               region.shouldSplit(true);
+              region.setSplitPoint(info.getSplitPoint());
               // force a compaction; split will be side-effect.
               compactSplitThread.requestCompaction(region,
                 false, e.msg.getType().name(),

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/Store.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/Store.java?rev=1181458&r1=1181457&r2=1181458&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/Store.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/Store.java Tue Oct 11 02:10:11 2011
@@ -1310,6 +1310,10 @@ public class Store implements HeapSize {
           largestSf = sf;
         }
       }
+      // if the user explicit set a split point, use that
+      if (this.region.getSplitPoint() != null) {
+        return new StoreSize(maxSize, this.region.getSplitPoint());
+      }
       StoreFile.Reader r = largestSf.getReader();
       if (r == null) {
         LOG.warn("Storefile " + largestSf + " Reader is null");

Modified: hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java?rev=1181458&r1=1181457&r2=1181458&view=diff
==============================================================================
--- hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java (original)
+++ hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java Tue Oct 11 02:10:11 2011
@@ -456,6 +456,12 @@ public class HBaseTestingUtility {
     return new HTable(getConfiguration(), tableName);
   }
 
+  public void deleteTable(byte[] tableName) throws IOException {
+    HBaseAdmin hba = new HBaseAdmin(getConfiguration());
+    hba.disableTable(tableName);
+    hba.deleteTable(tableName);
+  }
+
   /**
    * Provide an existing table name to truncate
    * @param tableName existing table

Modified: hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java?rev=1181458&r1=1181457&r2=1181458&view=diff
==============================================================================
--- hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java (original)
+++ hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java Tue Oct 11 02:10:11 2011
@@ -297,85 +297,115 @@ public class TestAdmin {
    */
   @Test
   public void testForceSplit() throws Exception {
+    splitTest(null);
+    splitTest(Bytes.toBytes("pwn"));
+  }
+
+  void splitTest(byte[] splitPoint) throws Exception {
     byte [] familyName = HConstants.CATALOG_FAMILY;
     byte [] tableName = Bytes.toBytes("testForceSplit");
     final HTable table = TEST_UTIL.createTable(tableName, familyName);
-    byte[] k = new byte[3];
-    int rowCount = 0;
-    for (byte b1 = 'a'; b1 < 'z'; b1++) {
-      for (byte b2 = 'a'; b2 < 'z'; b2++) {
-        for (byte b3 = 'a'; b3 < 'z'; b3++) {
-          k[0] = b1;
-          k[1] = b2;
-          k[2] = b3;
-          Put put = new Put(k);
-          put.add(familyName, new byte[0], k);
-          table.put(put);
-          rowCount++;
+    try {
+      byte[] k = new byte[3];
+      int rowCount = 0;
+      for (byte b1 = 'a'; b1 < 'z'; b1++) {
+        for (byte b2 = 'a'; b2 < 'z'; b2++) {
+          for (byte b3 = 'a'; b3 < 'z'; b3++) {
+            k[0] = b1;
+            k[1] = b2;
+            k[2] = b3;
+            Put put = new Put(k);
+            put.add(familyName, new byte[0], k);
+            table.put(put);
+            rowCount++;
+          }
         }
       }
-    }
 
-    // get the initial layout (should just be one region)
-    Map<HRegionInfo,HServerAddress> m = table.getRegionsInfo();
-    System.out.println("Initial regions (" + m.size() + "): " + m);
-    assertTrue(m.size() == 1);
-
-    // Verify row count
-    Scan scan = new Scan();
-    ResultScanner scanner = table.getScanner(scan);
-    int rows = 0;
-    for(@SuppressWarnings("unused") Result result : scanner) {
-      rows++;
-    }
-    scanner.close();
-    assertEquals(rowCount, rows);
-
-    // Have an outstanding scan going on to make sure we can scan over splits.
-    scan = new Scan();
-    scanner = table.getScanner(scan);
-    // Scan first row so we are into first region before split happens.
-    scanner.next();
-
-    final AtomicInteger count = new AtomicInteger(0);
-    Thread t = new Thread("CheckForSplit") {
-      public void run() {
-        for (int i = 0; i < 20; i++) {
-          try {
-            sleep(1000);
-          } catch (InterruptedException e) {
-            continue;
-          }
-          // check again    table = new HTable(conf, tableName);
-          Map<HRegionInfo, HServerAddress> regions = null;
-          try {
-            regions = table.getRegionsInfo();
-          } catch (IOException e) {
-            e.printStackTrace();
+      // get the initial layout (should just be one region)
+      Map<HRegionInfo,HServerAddress> m = table.getRegionsInfo();
+      System.out.println("Initial regions (" + m.size() + "): " + m);
+      assertTrue(m.size() == 1);
+
+      // Verify row count
+      Scan scan = new Scan();
+      ResultScanner scanner = table.getScanner(scan);
+      int rows = 0;
+      for(@SuppressWarnings("unused") Result result : scanner) {
+        rows++;
+      }
+      scanner.close();
+      assertEquals(rowCount, rows);
+
+      // Have an outstanding scan going on to make sure we can scan over splits.
+      scan = new Scan();
+      scanner = table.getScanner(scan);
+      // Scan first row so we are into first region before split happens.
+      scanner.next();
+
+      final AtomicInteger count = new AtomicInteger(0);
+      Thread t = new Thread("CheckForSplit") {
+        public void run() {
+          for (int i = 0; i < 20; i++) {
+            try {
+              sleep(1000);
+            } catch (InterruptedException e) {
+              continue;
+            }
+            // check again    table = new HTable(conf, tableName);
+            Map<HRegionInfo, HServerAddress> regions = null;
+            try {
+              regions = table.getRegionsInfo();
+            } catch (IOException e) {
+              e.printStackTrace();
+            }
+            if (regions == null) continue;
+            count.set(regions.size());
+            if (count.get() >= 2) break;
+            LOG.debug("Cycle waiting on split");
           }
-          if (regions == null) continue;
-          count.set(regions.size());
-          if (count.get() >= 2) break;
-          LOG.debug("Cycle waiting on split");
         }
+      };
+      t.start();
+      // tell the master to split the table
+      if (splitPoint != null) {
+        admin.split(tableName, splitPoint);
+      } else {
+        admin.split(tableName);
       }
-    };
-    t.start();
-    // tell the master to split the table
-    admin.split(Bytes.toString(tableName));
-    t.join();
-
-    // Verify row count
-    rows = 1; // We counted one row above.
-    for (@SuppressWarnings("unused") Result result : scanner) {
-      rows++;
-      if (rows > rowCount) {
-        scanner.close();
-        assertTrue("Scanned more than expected (" + rowCount + ")", false);
+      t.join();
+
+      // Verify row count
+      rows = 1; // We counted one row above.
+      for (@SuppressWarnings("unused") Result result : scanner) {
+        rows++;
+        if (rows > rowCount) {
+          scanner.close();
+          assertTrue("Scanned more than expected (" + rowCount + ")", false);
+        }
+      }
+      scanner.close();
+      assertEquals(rowCount, rows);
+
+      if (splitPoint != null) {
+        // make sure the split point matches our explicit configuration
+        Map<HRegionInfo, HServerAddress> regions = null;
+        try {
+          regions = table.getRegionsInfo();
+        } catch (IOException e) {
+          e.printStackTrace();
+        }
+        assertEquals(2, regions.size());
+        HRegionInfo[] r = regions.keySet().toArray(new HRegionInfo[0]);
+        assertEquals(Bytes.toString(splitPoint),
+            Bytes.toString(r[0].getEndKey()));
+        assertEquals(Bytes.toString(splitPoint),
+            Bytes.toString(r[1].getStartKey()));
+        LOG.debug("Properly split on " + Bytes.toString(splitPoint));
       }
+    } finally {
+      TEST_UTIL.deleteTable(tableName);
     }
-    scanner.close();
-    assertEquals(rowCount, rows);
   }
 
   /**