You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ap...@apache.org on 2017/09/19 22:05:59 UTC

[1/3] hbase git commit: HBASE-18796 Admin#isTableAvailable returns incorrect result before daughter regions are opened

Repository: hbase
Updated Branches:
  refs/heads/branch-1 539fce344 -> 2845ddaf9
  refs/heads/branch-1.3 025c3f47d -> c7a165cb4
  refs/heads/branch-1.4 a1d0bb97a -> d4aa7181c


HBASE-18796 Admin#isTableAvailable returns incorrect result before daughter regions are opened

Signed-off-by: Andrew Purtell <ap...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/2845ddaf
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/2845ddaf
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/2845ddaf

Branch: refs/heads/branch-1
Commit: 2845ddaf9e32d5aedc16424ba17e644411bc91ca
Parents: 539fce3
Author: Abhishek Singh Chouhan <ac...@apache.org>
Authored: Mon Sep 18 14:56:14 2017 +0530
Committer: Andrew Purtell <ap...@apache.org>
Committed: Tue Sep 19 13:52:15 2017 -0700

----------------------------------------------------------------------
 .../apache/hadoop/hbase/MetaTableAccessor.java  | 13 +++-
 .../hadoop/hbase/TestMetaTableAccessor.java     | 41 +++++++++++++
 .../TestEndToEndSplitTransaction.java           | 62 ++++++++++++++++++++
 3 files changed, 114 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/2845ddaf/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
index 739291a..2bc98be 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
@@ -1340,8 +1340,8 @@ public class MetaTableAccessor {
       Put putA = makePutFromRegionInfo(splitA);
       Put putB = makePutFromRegionInfo(splitB);
 
-      addLocation(putA, sn, 1, -1, splitA.getReplicaId()); //new regions, openSeqNum = 1 is fine.
-      addLocation(putB, sn, 1, -1, splitB.getReplicaId());
+      addSequenceNum(putA, 1, -1, splitA.getReplicaId()); //new regions, openSeqNum = 1 is fine.
+      addSequenceNum(putB, 1, -1, splitB.getReplicaId());
 
       // Add empty locations for region replicas of daughters so that number of replicas can be
       // cached whenever the primary region is looked up from meta
@@ -1612,6 +1612,15 @@ public class MetaTableAccessor {
     return p;
   }
 
+  public static Put addSequenceNum(final Put p, long openSeqNum, long time, int replicaId) {
+    if (time <= 0) {
+      time = EnvironmentEdgeManager.currentTime();
+    }
+    p.addImmutable(HConstants.CATALOG_FAMILY, getSeqNumColumn(replicaId), time,
+      Bytes.toBytes(openSeqNum));
+    return p;
+  }
+
   /**
    * Get replication position for a peer in a region.
    * @param connection connection we're using

http://git-wip-us.apache.org/repos/asf/hbase/blob/2845ddaf/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
index 5857f5d..98fff27 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
@@ -644,5 +644,46 @@ public class TestMetaTableAccessor {
       assertTrue(prevCalls < scheduler.numPriorityCalls);
     }
   }
+
+  @Test
+  public void testEmptyMetaDaughterLocationDuringSplit() throws IOException {
+    long regionId = System.currentTimeMillis();
+    ServerName serverName0 = ServerName.valueOf("foo", 60010, random.nextLong());
+    HRegionInfo parent = new HRegionInfo(TableName.valueOf("table_foo"), HConstants.EMPTY_START_ROW,
+        HConstants.EMPTY_END_ROW, false, regionId, 0);
+    HRegionInfo splitA = new HRegionInfo(TableName.valueOf("table_foo"), HConstants.EMPTY_START_ROW,
+        Bytes.toBytes("a"), false, regionId + 1, 0);
+    HRegionInfo splitB = new HRegionInfo(TableName.valueOf("table_foo"), Bytes.toBytes("a"),
+        HConstants.EMPTY_END_ROW, false, regionId + 1, 0);
+
+    Table meta = MetaTableAccessor.getMetaHTable(connection);
+    try {
+      List<HRegionInfo> regionInfos = Lists.newArrayList(parent);
+      MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
+
+      MetaTableAccessor.splitRegion(connection, parent, splitA, splitB, serverName0, 3, false);
+      Get get1 = new Get(splitA.getRegionName());
+      Result resultA = meta.get(get1);
+      Cell serverCellA = resultA.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getServerColumn(splitA.getReplicaId()));
+      Cell startCodeCellA = resultA.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getStartCodeColumn(splitA.getReplicaId()));
+      assertNull(serverCellA);
+      assertNull(startCodeCellA);
+
+      Get get2 = new Get(splitA.getRegionName());
+      Result resultB = meta.get(get2);
+      Cell serverCellB = resultB.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getServerColumn(splitB.getReplicaId()));
+      Cell startCodeCellB = resultB.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getStartCodeColumn(splitB.getReplicaId()));
+      assertNull(serverCellB);
+      assertNull(startCodeCellB);
+    } finally {
+      if (meta != null) {
+        meta.close();
+      }
+    }
+  }
 }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/2845ddaf/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
index b6e2424..14fdd5d 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
@@ -136,6 +136,11 @@ public class TestEndToEndSplitTransaction {
         regions.getSecond().getRegionInfo());
       }
 
+      // first daughter second
+      if (split.useZKForAssignment) {
+        server.postOpenDeployTasks(regions.getFirst());
+      }
+
       // Add to online regions
       server.addToOnlineRegions(regions.getSecond());
       // THIS is the crucial point:
@@ -161,6 +166,63 @@ public class TestEndToEndSplitTransaction {
     }
   }
 
+  @Test
+  public void testTableAvailableWhileSplitting() throws Exception {
+    TableName tableName = TableName.valueOf("TestTableAvailableWhileSplitting");
+    byte[] familyName = Bytes.toBytes("fam");
+    try (HTable ht = TEST_UTIL.createTable(tableName, familyName)) {
+      TEST_UTIL.loadTable(ht, familyName, false);
+    }
+    Admin admin = TEST_UTIL.getHBaseAdmin();
+    HRegionServer server = TEST_UTIL.getHBaseCluster().getRegionServer(0);
+    byte[] splitRow = Bytes.toBytes("lll");
+    try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) {
+      byte[] regionName = conn.getRegionLocator(tableName).getRegionLocation(splitRow)
+          .getRegionInfo().getRegionName();
+      Region region = server.getRegion(regionName);
+      SplitTransactionImpl split = new SplitTransactionImpl((HRegion) region, splitRow);
+      split.prepare();
+      assertTrue(admin.isTableAvailable(tableName));
+
+      // 1. phase I
+      PairOfSameType<Region> regions = split.createDaughters(server, server, null);
+      // Parent should be offline at this stage and daughters not yet open
+      assertFalse(admin.isTableAvailable(tableName));
+
+      // passing null as services prevents final step of postOpenDeployTasks
+      // 2, most of phase II
+      split.openDaughters(server, null, regions.getFirst(), regions.getSecond());
+      assertFalse(admin.isTableAvailable(tableName));
+
+      // Finish openeing daughters
+      // 2nd daughter first
+      if (split.useZKForAssignment) {
+        server.postOpenDeployTasks(regions.getSecond());
+      } else {
+        server.reportRegionStateTransition(
+          RegionServerStatusProtos.RegionStateTransition.TransitionCode.SPLIT,
+          region.getRegionInfo(), regions.getFirst().getRegionInfo(),
+          regions.getSecond().getRegionInfo());
+      }
+
+      // first daughter second
+      if (split.useZKForAssignment) {
+        server.postOpenDeployTasks(regions.getFirst());
+      }
+
+      // After postOpenDeploy daughters should have location in meta
+      assertTrue(admin.isTableAvailable(tableName));
+
+      server.addToOnlineRegions(regions.getSecond());
+      server.addToOnlineRegions(regions.getFirst());
+      assertTrue(admin.isTableAvailable(tableName));
+    } finally {
+      if (admin != null) {
+        admin.close();
+      }
+    }
+  }
+
   /**
    * attempt to locate the region and perform a get and scan
    * @return True if successful, False otherwise.


[3/3] hbase git commit: HBASE-18796 Admin#isTableAvailable returns incorrect result before daughter regions are opened

Posted by ap...@apache.org.
HBASE-18796 Admin#isTableAvailable returns incorrect result before daughter regions are opened

Signed-off-by: Andrew Purtell <ap...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/c7a165cb
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/c7a165cb
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/c7a165cb

Branch: refs/heads/branch-1.3
Commit: c7a165cb48ec27c0b12b0f6fdd499c14d6ba96b9
Parents: 025c3f4
Author: Abhishek Singh Chouhan <ac...@apache.org>
Authored: Mon Sep 18 14:56:14 2017 +0530
Committer: Andrew Purtell <ap...@apache.org>
Committed: Tue Sep 19 14:48:10 2017 -0700

----------------------------------------------------------------------
 .../apache/hadoop/hbase/MetaTableAccessor.java  | 13 +++-
 .../hadoop/hbase/TestMetaTableAccessor.java     | 41 +++++++++++++
 .../TestEndToEndSplitTransaction.java           | 62 ++++++++++++++++++++
 3 files changed, 114 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/c7a165cb/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
index a09ff88..3f11558 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
@@ -1297,8 +1297,8 @@ public class MetaTableAccessor {
       Put putA = makePutFromRegionInfo(splitA);
       Put putB = makePutFromRegionInfo(splitB);
 
-      addLocation(putA, sn, 1, -1, splitA.getReplicaId()); //new regions, openSeqNum = 1 is fine.
-      addLocation(putB, sn, 1, -1, splitB.getReplicaId());
+      addSequenceNum(putA, 1, -1, splitA.getReplicaId()); //new regions, openSeqNum = 1 is fine.
+      addSequenceNum(putB, 1, -1, splitB.getReplicaId());
 
       // Add empty locations for region replicas of daughters so that number of replicas can be
       // cached whenever the primary region is looked up from meta
@@ -1540,6 +1540,15 @@ public class MetaTableAccessor {
     return p;
   }
 
+  public static Put addSequenceNum(final Put p, long openSeqNum, long time, int replicaId) {
+    if (time <= 0) {
+      time = EnvironmentEdgeManager.currentTime();
+    }
+    p.addImmutable(HConstants.CATALOG_FAMILY, getSeqNumColumn(replicaId), time,
+      Bytes.toBytes(openSeqNum));
+    return p;
+  }
+
   /**
    * Checks whether hbase:meta contains any info:server entry.
    * @param connection connection we're using

http://git-wip-us.apache.org/repos/asf/hbase/blob/c7a165cb/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
index 3955a4c..cb2494b 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
@@ -644,5 +644,46 @@ public class TestMetaTableAccessor {
       assertTrue(prevCalls < scheduler.numPriorityCalls);
     }
   }
+
+  @Test
+  public void testEmptyMetaDaughterLocationDuringSplit() throws IOException {
+    long regionId = System.currentTimeMillis();
+    ServerName serverName0 = ServerName.valueOf("foo", 60010, random.nextLong());
+    HRegionInfo parent = new HRegionInfo(TableName.valueOf("table_foo"), HConstants.EMPTY_START_ROW,
+        HConstants.EMPTY_END_ROW, false, regionId, 0);
+    HRegionInfo splitA = new HRegionInfo(TableName.valueOf("table_foo"), HConstants.EMPTY_START_ROW,
+        Bytes.toBytes("a"), false, regionId + 1, 0);
+    HRegionInfo splitB = new HRegionInfo(TableName.valueOf("table_foo"), Bytes.toBytes("a"),
+        HConstants.EMPTY_END_ROW, false, regionId + 1, 0);
+
+    Table meta = MetaTableAccessor.getMetaHTable(connection);
+    try {
+      List<HRegionInfo> regionInfos = Lists.newArrayList(parent);
+      MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
+
+      MetaTableAccessor.splitRegion(connection, parent, splitA, splitB, serverName0, 3);
+      Get get1 = new Get(splitA.getRegionName());
+      Result resultA = meta.get(get1);
+      Cell serverCellA = resultA.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getServerColumn(splitA.getReplicaId()));
+      Cell startCodeCellA = resultA.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getStartCodeColumn(splitA.getReplicaId()));
+      assertNull(serverCellA);
+      assertNull(startCodeCellA);
+
+      Get get2 = new Get(splitA.getRegionName());
+      Result resultB = meta.get(get2);
+      Cell serverCellB = resultB.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getServerColumn(splitB.getReplicaId()));
+      Cell startCodeCellB = resultB.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getStartCodeColumn(splitB.getReplicaId()));
+      assertNull(serverCellB);
+      assertNull(startCodeCellB);
+    } finally {
+      if (meta != null) {
+        meta.close();
+      }
+    }
+  }
 }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/c7a165cb/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
index dfb01cb..0df3a91 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
@@ -136,6 +136,11 @@ public class TestEndToEndSplitTransaction {
         regions.getSecond().getRegionInfo());
       }
 
+      // first daughter second
+      if (split.useZKForAssignment) {
+        server.postOpenDeployTasks(regions.getFirst());
+      }
+
       // Add to online regions
       server.addToOnlineRegions(regions.getSecond());
       // THIS is the crucial point:
@@ -161,6 +166,63 @@ public class TestEndToEndSplitTransaction {
     }
   }
 
+  @Test
+  public void testTableAvailableWhileSplitting() throws Exception {
+    TableName tableName = TableName.valueOf("TestTableAvailableWhileSplitting");
+    byte[] familyName = Bytes.toBytes("fam");
+    try (HTable ht = TEST_UTIL.createTable(tableName, familyName)) {
+      TEST_UTIL.loadTable(ht, familyName, false);
+    }
+    Admin admin = TEST_UTIL.getHBaseAdmin();
+    HRegionServer server = TEST_UTIL.getHBaseCluster().getRegionServer(0);
+    byte[] splitRow = Bytes.toBytes("lll");
+    try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) {
+      byte[] regionName = conn.getRegionLocator(tableName).getRegionLocation(splitRow)
+          .getRegionInfo().getRegionName();
+      Region region = server.getRegion(regionName);
+      SplitTransactionImpl split = new SplitTransactionImpl((HRegion) region, splitRow);
+      split.prepare();
+      assertTrue(admin.isTableAvailable(tableName));
+
+      // 1. phase I
+      PairOfSameType<Region> regions = split.createDaughters(server, server, null);
+      // Parent should be offline at this stage and daughters not yet open
+      assertFalse(admin.isTableAvailable(tableName));
+
+      // passing null as services prevents final step of postOpenDeployTasks
+      // 2, most of phase II
+      split.openDaughters(server, null, regions.getFirst(), regions.getSecond());
+      assertFalse(admin.isTableAvailable(tableName));
+
+      // Finish openeing daughters
+      // 2nd daughter first
+      if (split.useZKForAssignment) {
+        server.postOpenDeployTasks(regions.getSecond());
+      } else {
+        server.reportRegionStateTransition(
+          RegionServerStatusProtos.RegionStateTransition.TransitionCode.SPLIT,
+          region.getRegionInfo(), regions.getFirst().getRegionInfo(),
+          regions.getSecond().getRegionInfo());
+      }
+
+      // first daughter second
+      if (split.useZKForAssignment) {
+        server.postOpenDeployTasks(regions.getFirst());
+      }
+
+      // After postOpenDeploy daughters should have location in meta
+      assertTrue(admin.isTableAvailable(tableName));
+
+      server.addToOnlineRegions(regions.getSecond());
+      server.addToOnlineRegions(regions.getFirst());
+      assertTrue(admin.isTableAvailable(tableName));
+    } finally {
+      if (admin != null) {
+        admin.close();
+      }
+    }
+  }
+
   /**
    * attempt to locate the region and perform a get and scan
    * @return True if successful, False otherwise.


[2/3] hbase git commit: HBASE-18796 Admin#isTableAvailable returns incorrect result before daughter regions are opened

Posted by ap...@apache.org.
HBASE-18796 Admin#isTableAvailable returns incorrect result before daughter regions are opened

Signed-off-by: Andrew Purtell <ap...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/d4aa7181
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/d4aa7181
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/d4aa7181

Branch: refs/heads/branch-1.4
Commit: d4aa7181c1f831f35fe76f88d7547575dae972af
Parents: a1d0bb9
Author: Abhishek Singh Chouhan <ac...@apache.org>
Authored: Mon Sep 18 14:56:14 2017 +0530
Committer: Andrew Purtell <ap...@apache.org>
Committed: Tue Sep 19 13:52:27 2017 -0700

----------------------------------------------------------------------
 .../apache/hadoop/hbase/MetaTableAccessor.java  | 13 +++-
 .../hadoop/hbase/TestMetaTableAccessor.java     | 41 +++++++++++++
 .../TestEndToEndSplitTransaction.java           | 62 ++++++++++++++++++++
 3 files changed, 114 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/d4aa7181/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
index 739291a..2bc98be 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
@@ -1340,8 +1340,8 @@ public class MetaTableAccessor {
       Put putA = makePutFromRegionInfo(splitA);
       Put putB = makePutFromRegionInfo(splitB);
 
-      addLocation(putA, sn, 1, -1, splitA.getReplicaId()); //new regions, openSeqNum = 1 is fine.
-      addLocation(putB, sn, 1, -1, splitB.getReplicaId());
+      addSequenceNum(putA, 1, -1, splitA.getReplicaId()); //new regions, openSeqNum = 1 is fine.
+      addSequenceNum(putB, 1, -1, splitB.getReplicaId());
 
       // Add empty locations for region replicas of daughters so that number of replicas can be
       // cached whenever the primary region is looked up from meta
@@ -1612,6 +1612,15 @@ public class MetaTableAccessor {
     return p;
   }
 
+  public static Put addSequenceNum(final Put p, long openSeqNum, long time, int replicaId) {
+    if (time <= 0) {
+      time = EnvironmentEdgeManager.currentTime();
+    }
+    p.addImmutable(HConstants.CATALOG_FAMILY, getSeqNumColumn(replicaId), time,
+      Bytes.toBytes(openSeqNum));
+    return p;
+  }
+
   /**
    * Get replication position for a peer in a region.
    * @param connection connection we're using

http://git-wip-us.apache.org/repos/asf/hbase/blob/d4aa7181/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
index 5857f5d..98fff27 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestMetaTableAccessor.java
@@ -644,5 +644,46 @@ public class TestMetaTableAccessor {
       assertTrue(prevCalls < scheduler.numPriorityCalls);
     }
   }
+
+  @Test
+  public void testEmptyMetaDaughterLocationDuringSplit() throws IOException {
+    long regionId = System.currentTimeMillis();
+    ServerName serverName0 = ServerName.valueOf("foo", 60010, random.nextLong());
+    HRegionInfo parent = new HRegionInfo(TableName.valueOf("table_foo"), HConstants.EMPTY_START_ROW,
+        HConstants.EMPTY_END_ROW, false, regionId, 0);
+    HRegionInfo splitA = new HRegionInfo(TableName.valueOf("table_foo"), HConstants.EMPTY_START_ROW,
+        Bytes.toBytes("a"), false, regionId + 1, 0);
+    HRegionInfo splitB = new HRegionInfo(TableName.valueOf("table_foo"), Bytes.toBytes("a"),
+        HConstants.EMPTY_END_ROW, false, regionId + 1, 0);
+
+    Table meta = MetaTableAccessor.getMetaHTable(connection);
+    try {
+      List<HRegionInfo> regionInfos = Lists.newArrayList(parent);
+      MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
+
+      MetaTableAccessor.splitRegion(connection, parent, splitA, splitB, serverName0, 3, false);
+      Get get1 = new Get(splitA.getRegionName());
+      Result resultA = meta.get(get1);
+      Cell serverCellA = resultA.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getServerColumn(splitA.getReplicaId()));
+      Cell startCodeCellA = resultA.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getStartCodeColumn(splitA.getReplicaId()));
+      assertNull(serverCellA);
+      assertNull(startCodeCellA);
+
+      Get get2 = new Get(splitA.getRegionName());
+      Result resultB = meta.get(get2);
+      Cell serverCellB = resultB.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getServerColumn(splitB.getReplicaId()));
+      Cell startCodeCellB = resultB.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+        MetaTableAccessor.getStartCodeColumn(splitB.getReplicaId()));
+      assertNull(serverCellB);
+      assertNull(startCodeCellB);
+    } finally {
+      if (meta != null) {
+        meta.close();
+      }
+    }
+  }
 }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/d4aa7181/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
index b6e2424..14fdd5d 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEndToEndSplitTransaction.java
@@ -136,6 +136,11 @@ public class TestEndToEndSplitTransaction {
         regions.getSecond().getRegionInfo());
       }
 
+      // first daughter second
+      if (split.useZKForAssignment) {
+        server.postOpenDeployTasks(regions.getFirst());
+      }
+
       // Add to online regions
       server.addToOnlineRegions(regions.getSecond());
       // THIS is the crucial point:
@@ -161,6 +166,63 @@ public class TestEndToEndSplitTransaction {
     }
   }
 
+  @Test
+  public void testTableAvailableWhileSplitting() throws Exception {
+    TableName tableName = TableName.valueOf("TestTableAvailableWhileSplitting");
+    byte[] familyName = Bytes.toBytes("fam");
+    try (HTable ht = TEST_UTIL.createTable(tableName, familyName)) {
+      TEST_UTIL.loadTable(ht, familyName, false);
+    }
+    Admin admin = TEST_UTIL.getHBaseAdmin();
+    HRegionServer server = TEST_UTIL.getHBaseCluster().getRegionServer(0);
+    byte[] splitRow = Bytes.toBytes("lll");
+    try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) {
+      byte[] regionName = conn.getRegionLocator(tableName).getRegionLocation(splitRow)
+          .getRegionInfo().getRegionName();
+      Region region = server.getRegion(regionName);
+      SplitTransactionImpl split = new SplitTransactionImpl((HRegion) region, splitRow);
+      split.prepare();
+      assertTrue(admin.isTableAvailable(tableName));
+
+      // 1. phase I
+      PairOfSameType<Region> regions = split.createDaughters(server, server, null);
+      // Parent should be offline at this stage and daughters not yet open
+      assertFalse(admin.isTableAvailable(tableName));
+
+      // passing null as services prevents final step of postOpenDeployTasks
+      // 2, most of phase II
+      split.openDaughters(server, null, regions.getFirst(), regions.getSecond());
+      assertFalse(admin.isTableAvailable(tableName));
+
+      // Finish openeing daughters
+      // 2nd daughter first
+      if (split.useZKForAssignment) {
+        server.postOpenDeployTasks(regions.getSecond());
+      } else {
+        server.reportRegionStateTransition(
+          RegionServerStatusProtos.RegionStateTransition.TransitionCode.SPLIT,
+          region.getRegionInfo(), regions.getFirst().getRegionInfo(),
+          regions.getSecond().getRegionInfo());
+      }
+
+      // first daughter second
+      if (split.useZKForAssignment) {
+        server.postOpenDeployTasks(regions.getFirst());
+      }
+
+      // After postOpenDeploy daughters should have location in meta
+      assertTrue(admin.isTableAvailable(tableName));
+
+      server.addToOnlineRegions(regions.getSecond());
+      server.addToOnlineRegions(regions.getFirst());
+      assertTrue(admin.isTableAvailable(tableName));
+    } finally {
+      if (admin != null) {
+        admin.close();
+      }
+    }
+  }
+
   /**
    * attempt to locate the region and perform a get and scan
    * @return True if successful, False otherwise.