View Javadoc

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  
19  package org.apache.hadoop.hbase.client;
20  
21  import static org.junit.Assert.assertNotEquals;
22  import static org.junit.Assert.assertNull;
23  import static org.junit.Assert.assertTrue;
24  
25  import java.io.IOException;
26  import java.util.ArrayList;
27  import java.util.List;
28  
29  import org.apache.hadoop.hbase.HBaseTestingUtility;
30  import org.apache.hadoop.hbase.TableName;
31  import org.apache.hadoop.hbase.client.ConnectionManager.HConnectionImplementation;
32  import org.apache.hadoop.hbase.testclassification.ClientTests;
33  import org.apache.hadoop.hbase.testclassification.MediumTests;
34  import org.apache.hadoop.hbase.util.Bytes;
35  import org.junit.AfterClass;
36  import org.junit.BeforeClass;
37  import org.junit.Test;
38  import org.junit.experimental.categories.Category;
39  
40  @Category({MediumTests.class, ClientTests.class})
41  public class TestRegionLocationCaching {
42  
43    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
44    private static int SLAVES = 1;
45    private static int PER_REGIONSERVER_QUEUE_SIZE = 100000;
46    private static TableName TABLE_NAME = TableName.valueOf("TestRegionLocationCaching");
47    private static byte[] FAMILY = Bytes.toBytes("testFamily");
48    private static byte[] QUALIFIER = Bytes.toBytes("testQualifier");
49  
50    @BeforeClass
51    public static void setUpBeforeClass() throws Exception {
52      TEST_UTIL.startMiniCluster(SLAVES);
53      TEST_UTIL.createTable(TABLE_NAME, new byte[][] { FAMILY });
54      TEST_UTIL.waitUntilAllRegionsAssigned(TABLE_NAME);
55    }
56  
57    @AfterClass
58    public static void tearDownAfterClass() throws Exception {
59      TEST_UTIL.shutdownMiniCluster();
60    }
61  
62    @Test
63    public void testCachingForHTableMultiplexerSinglePut() throws Exception {
64      HTableMultiplexer multiplexer =
65          new HTableMultiplexer(TEST_UTIL.getConfiguration(), PER_REGIONSERVER_QUEUE_SIZE);
66      byte[] row = Bytes.toBytes("htable_multiplexer_single_put");
67      byte[] value = Bytes.toBytes("value");
68  
69      Put put = new Put(row);
70      put.addColumn(FAMILY, QUALIFIER, value);
71      assertTrue("Put request not accepted by multiplexer queue", multiplexer.put(TABLE_NAME, put));
72  
73      checkRegionLocationIsCached(TABLE_NAME, multiplexer.getConnection());
74      checkExistence(TABLE_NAME, row, FAMILY, QUALIFIER);
75  
76      multiplexer.close();
77    }
78  
79    @Test
80    public void testCachingForHTableMultiplexerMultiPut() throws Exception {
81      HTableMultiplexer multiplexer =
82          new HTableMultiplexer(TEST_UTIL.getConfiguration(), PER_REGIONSERVER_QUEUE_SIZE);
83  
84      List<Put> multiput = new ArrayList<Put>();
85      for (int i = 0; i < 10; i++) {
86        Put put = new Put(Bytes.toBytes("htable_multiplexer_multi_put" + i));
87        byte[] value = Bytes.toBytes("value_" + i);
88        put.addColumn(FAMILY, QUALIFIER, value);
89        multiput.add(put);
90      }
91  
92      List<Put> failedPuts = multiplexer.put(TABLE_NAME, multiput);
93      assertNull("All put requests were not accepted by multiplexer queue", failedPuts);
94  
95      checkRegionLocationIsCached(TABLE_NAME, multiplexer.getConnection());
96      for (int i = 0; i < 10; i++) {
97        checkExistence(TABLE_NAME, Bytes.toBytes("htable_multiplexer_multi_put" + i), FAMILY,
98          QUALIFIER);
99      }
100 
101     multiplexer.close();
102   }
103 
104   @Test
105   public void testCachingForHTableSinglePut() throws Exception {
106     byte[] row = Bytes.toBytes("htable_single_put");
107     byte[] value = Bytes.toBytes("value");
108 
109     Put put = new Put(row);
110     put.addColumn(FAMILY, QUALIFIER, value);
111 
112     try (Table table = TEST_UTIL.getConnection().getTable(TABLE_NAME)) {
113       table.put(put);
114     }
115 
116     checkRegionLocationIsCached(TABLE_NAME, TEST_UTIL.getConnection());
117     checkExistence(TABLE_NAME, row, FAMILY, QUALIFIER);
118   }
119 
120   @Test
121   public void testCachingForHTableMultiPut() throws Exception {
122     List<Put> multiput = new ArrayList<Put>();
123     for (int i = 0; i < 10; i++) {
124       Put put = new Put(Bytes.toBytes("htable_multi_put" + i));
125       byte[] value = Bytes.toBytes("value_" + i);
126       put.addColumn(FAMILY, QUALIFIER, value);
127       multiput.add(put);
128     }
129 
130     try (Table table = TEST_UTIL.getConnection().getTable(TABLE_NAME)) {
131       table.put(multiput);
132     }
133     checkRegionLocationIsCached(TABLE_NAME, TEST_UTIL.getConnection());
134     for (int i = 0; i < 10; i++) {
135       checkExistence(TABLE_NAME, Bytes.toBytes("htable_multi_put" + i), FAMILY, QUALIFIER);
136     }
137   }
138 
139   /**
140    * Method to check whether the cached region location is non-empty for the given table. It repeats
141    * the same check several times as clearing of cache by some async operations may not reflect
142    * immediately.
143    */
144   private void checkRegionLocationIsCached(final TableName tableName, final Connection conn)
145       throws InterruptedException, IOException {
146     for (int count = 0; count < 50; count++) {
147       int number = ((HConnectionImplementation) conn).getNumberOfCachedRegionLocations(tableName);
148       assertNotEquals("Expected non-zero number of cached region locations", 0, number);
149       Thread.sleep(100);
150     }
151   }
152 
153   /**
154    * Method to check whether the passed row exists in the given table
155    */
156   private static void checkExistence(final TableName tableName, final byte[] row,
157       final byte[] family, final byte[] qualifier) throws Exception {
158     // verify that the row exists
159     Result r;
160     Get get = new Get(row);
161     get.addColumn(family, qualifier);
162     int nbTry = 0;
163     try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
164       do {
165         assertTrue("Failed to get row after " + nbTry + " tries", nbTry < 50);
166         nbTry++;
167         Thread.sleep(100);
168         r = table.get(get);
169       } while (r == null || r.getValue(family, qualifier) == null);
170     }
171   }
172 }