1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.regionserver;
19  
20  import java.io.IOException;
21  
22  import org.apache.hadoop.hbase.HBaseTestingUtility;
23  import org.apache.hadoop.hbase.HConstants;
24  import org.apache.hadoop.hbase.client.Get;
25  import org.apache.hadoop.hbase.client.HConnection;
26  import org.apache.hadoop.hbase.client.HConnectionManager;
27  import org.apache.hadoop.hbase.client.HTable;
28  import org.apache.hadoop.hbase.client.Scan;
29  import org.apache.hadoop.hbase.util.Bytes;
30  import org.apache.hadoop.hbase.util.PairOfSameType;
31  import org.junit.AfterClass;
32  import org.junit.BeforeClass;
33  import org.junit.Test;
34  
35  import static org.junit.Assert.assertTrue;
36  import static org.junit.Assert.assertFalse;
37  
38  public class TestEndToEndSplitTransaction {
39    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
40  
41    @BeforeClass
42    public static void beforeAllTests() throws Exception {
43      TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 5);
44      TEST_UTIL.startMiniCluster();
45    }
46  
47    @AfterClass
48    public static void afterAllTests() throws Exception {
49      TEST_UTIL.shutdownMiniCluster();
50    }
51    
52    @Test
53    public void testMasterOpsWhileSplitting() throws Exception {
54      byte[] tableName = Bytes.toBytes("TestSplit");
55      byte[] familyName = Bytes.toBytes("fam");
56      TEST_UTIL.createTable(tableName, familyName);
57      TEST_UTIL.loadTable(new HTable(TEST_UTIL.getConfiguration(), tableName),
58          familyName);
59      HRegionServer server = TEST_UTIL.getHBaseCluster().getRegionServer(0);
60      byte []firstRow = Bytes.toBytes("aaa");
61      byte []splitRow = Bytes.toBytes("lll");
62      byte []lastRow = Bytes.toBytes("zzz");
63      HConnection con = HConnectionManager
64          .getConnection(TEST_UTIL.getConfiguration());
65      // this will also cache the region
66      byte[] regionName = con.locateRegion(tableName, splitRow).getRegionInfo()
67          .getRegionName();
68      HRegion region = server.getRegion(regionName);
69      SplitTransaction split = new SplitTransaction(region, splitRow);
70      split.prepare();
71  
72      // 1. phase I
73      PairOfSameType<HRegion> regions = split.createDaughters(server, server);
74      assertFalse(test(con, tableName, firstRow, server));
75      assertFalse(test(con, tableName, lastRow, server));
76  
77      // passing null as services prevents final step
78      // 2, most of phase II
79      split.openDaughters(server, null, regions.getFirst(), regions.getSecond());
80      assertFalse(test(con, tableName, firstRow, server));
81      assertFalse(test(con, tableName, lastRow, server));
82  
83      // 3. finish phase II
84      // note that this replicates some code from SplitTransaction
85      // 2nd daughter first
86      server.postOpenDeployTasks(regions.getSecond(), server.getCatalogTracker(), true);
87      // THIS is the crucial point:
88      // the 2nd daughter was added, so querying before the split key should fail.
89      assertFalse(test(con, tableName, firstRow, server));
90      // past splitkey is ok.
91      assertTrue(test(con, tableName, lastRow, server));
92  
93      // first daughter second
94      server.postOpenDeployTasks(regions.getFirst(), server.getCatalogTracker(), true);
95      assertTrue(test(con, tableName, firstRow, server));
96      assertTrue(test(con, tableName, lastRow, server));
97  
98      // 4. phase III
99      split.transitionZKNode(server, regions.getFirst(), regions.getSecond());
100     assertTrue(test(con, tableName, firstRow, server));
101     assertTrue(test(con, tableName, lastRow, server));
102   }
103 
104   /**
105    * attempt to locate the region and perform a get and scan
106    * @return True if successful, False otherwise.
107    */
108   private boolean test(HConnection con, byte[] tableName, byte[] row,
109       HRegionServer server) {
110     // not using HTable to avoid timeouts and retries
111     try {
112       byte[] regionName = con.relocateRegion(tableName, row).getRegionInfo()
113           .getRegionName();
114       // get and scan should now succeed without exception
115       server.get(regionName, new Get(row));
116       server.openScanner(regionName, new Scan(row));
117     } catch (IOException x) {
118       return false;
119     }
120     return true;
121   }
122 }