1 /** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 package org.apache.hadoop.hbase.client; 20 21 import java.io.IOException; 22 23 import org.apache.hadoop.hbase.*; 24 import org.apache.hadoop.hbase.testclassification.MediumTests; 25 import org.apache.hadoop.hbase.util.Bytes; 26 import org.apache.hadoop.hbase.util.PoolMap.PoolType; 27 import org.junit.*; 28 import org.junit.experimental.categories.Category; 29 import org.junit.runner.RunWith; 30 import org.junit.runners.Suite; 31 32 /** 33 * Tests HTablePool. 34 */ 35 @RunWith(Suite.class) 36 @Suite.SuiteClasses({TestHTablePool.TestHTableReusablePool.class, TestHTablePool.TestHTableThreadLocalPool.class}) 37 @Category(MediumTests.class) 38 public class TestHTablePool { 39 private static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 40 private final static String TABLENAME = "TestHTablePool"; 41 42 public abstract static class TestHTablePoolType { 43 44 @BeforeClass setUpBeforeClass()45 public static void setUpBeforeClass() throws Exception { 46 TEST_UTIL.startMiniCluster(1); 47 TEST_UTIL.createTable(TableName.valueOf(TABLENAME), HConstants.CATALOG_FAMILY); 48 } 49 50 @AfterClass tearDownAfterClass()51 public static void tearDownAfterClass() throws Exception { 52 TEST_UTIL.shutdownMiniCluster(); 53 } 54 getPoolType()55 protected abstract PoolType getPoolType(); 56 57 @Test testTableWithStringName()58 public void testTableWithStringName() throws Exception { 59 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 60 Integer.MAX_VALUE, getPoolType()); 61 String tableName = TABLENAME; 62 63 // Request a table from an empty pool 64 Table table = pool.getTable(tableName); 65 Assert.assertNotNull(table); 66 67 // Close table (returns table to the pool) 68 table.close(); 69 70 // Request a table of the same name 71 Table sameTable = pool.getTable(tableName); 72 Assert.assertSame( 73 ((HTablePool.PooledHTable) table).getWrappedTable(), 74 ((HTablePool.PooledHTable) sameTable).getWrappedTable()); 75 } 76 77 @Test testTableWithByteArrayName()78 public void testTableWithByteArrayName() throws IOException { 79 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 80 Integer.MAX_VALUE, getPoolType()); 81 82 // Request a table from an empty pool 83 Table table = pool.getTable(TABLENAME); 84 Assert.assertNotNull(table); 85 86 // Close table (returns table to the pool) 87 table.close(); 88 89 // Request a table of the same name 90 Table sameTable = pool.getTable(TABLENAME); 91 Assert.assertSame( 92 ((HTablePool.PooledHTable) table).getWrappedTable(), 93 ((HTablePool.PooledHTable) sameTable).getWrappedTable()); 94 } 95 96 @Test testTablesWithDifferentNames()97 public void testTablesWithDifferentNames() throws IOException { 98 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 99 Integer.MAX_VALUE, getPoolType()); 100 // We add the class to the table name as the HBase cluster is reused 101 // during the tests: this gives naming unicity. 102 byte[] otherTable = Bytes.toBytes( 103 "OtherTable_" + getClass().getSimpleName() 104 ); 105 TEST_UTIL.createTable(otherTable, HConstants.CATALOG_FAMILY); 106 107 // Request a table from an empty pool 108 Table table1 = pool.getTable(TABLENAME); 109 Table table2 = pool.getTable(otherTable); 110 Assert.assertNotNull(table2); 111 112 // Close tables (returns tables to the pool) 113 table1.close(); 114 table2.close(); 115 116 // Request tables of the same names 117 Table sameTable1 = pool.getTable(TABLENAME); 118 Table sameTable2 = pool.getTable(otherTable); 119 Assert.assertSame( 120 ((HTablePool.PooledHTable) table1).getWrappedTable(), 121 ((HTablePool.PooledHTable) sameTable1).getWrappedTable()); 122 Assert.assertSame( 123 ((HTablePool.PooledHTable) table2).getWrappedTable(), 124 ((HTablePool.PooledHTable) sameTable2).getWrappedTable()); 125 } 126 @Test testProxyImplementationReturned()127 public void testProxyImplementationReturned() { 128 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 129 Integer.MAX_VALUE); 130 String tableName = TABLENAME;// Request a table from 131 // an 132 // empty pool 133 Table table = pool.getTable(tableName); 134 135 // Test if proxy implementation is returned 136 Assert.assertTrue(table instanceof HTablePool.PooledHTable); 137 } 138 139 @Test testDeprecatedUsagePattern()140 public void testDeprecatedUsagePattern() throws IOException { 141 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 142 Integer.MAX_VALUE); 143 String tableName = TABLENAME;// Request a table from 144 // an 145 // empty pool 146 147 // get table will return proxy implementation 148 HTableInterface table = pool.getTable(tableName); 149 150 // put back the proxy implementation instead of closing it 151 pool.putTable(table); 152 153 // Request a table of the same name 154 Table sameTable = pool.getTable(tableName); 155 156 // test no proxy over proxy created 157 Assert.assertSame(((HTablePool.PooledHTable) table).getWrappedTable(), 158 ((HTablePool.PooledHTable) sameTable).getWrappedTable()); 159 } 160 161 @Test testReturnDifferentTable()162 public void testReturnDifferentTable() throws IOException { 163 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 164 Integer.MAX_VALUE); 165 String tableName = TABLENAME;// Request a table from 166 // an 167 // empty pool 168 169 // get table will return proxy implementation 170 final Table table = pool.getTable(tableName); 171 HTableInterface alienTable = new HTable(TEST_UTIL.getConfiguration(), 172 TableName.valueOf(TABLENAME)) { 173 // implementation doesn't matter as long the table is not from 174 // pool 175 }; 176 try { 177 // put the wrong table in pool 178 pool.putTable(alienTable); 179 Assert.fail("alien table accepted in pool"); 180 } catch (IllegalArgumentException e) { 181 Assert.assertTrue("alien table rejected", true); 182 } 183 } 184 185 @Test testHTablePoolCloseTwice()186 public void testHTablePoolCloseTwice() throws Exception { 187 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 188 Integer.MAX_VALUE, getPoolType()); 189 String tableName = TABLENAME; 190 191 // Request a table from an empty pool 192 Table table = pool.getTable(tableName); 193 Assert.assertNotNull(table); 194 Assert.assertTrue(((HTablePool.PooledHTable) table).isOpen()); 195 // Close table (returns table to the pool) 196 table.close(); 197 // check if the table is closed 198 Assert.assertFalse(((HTablePool.PooledHTable) table).isOpen()); 199 try { 200 table.close(); 201 Assert.fail("Should not allow table to be closed twice"); 202 } catch (IllegalStateException ex) { 203 Assert.assertTrue("table cannot be closed twice", true); 204 } finally { 205 pool.close(); 206 } 207 208 } 209 210 } 211 212 @Category(MediumTests.class) 213 public static class TestHTableReusablePool extends TestHTablePoolType { 214 @Override getPoolType()215 protected PoolType getPoolType() { 216 return PoolType.Reusable; 217 } 218 219 @Test testTableWithMaxSize()220 public void testTableWithMaxSize() throws Exception { 221 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 2, 222 getPoolType()); 223 224 // Request tables from an empty pool 225 Table table1 = pool.getTable(TABLENAME); 226 Table table2 = pool.getTable(TABLENAME); 227 Table table3 = pool.getTable(TABLENAME); 228 229 // Close tables (returns tables to the pool) 230 table1.close(); 231 table2.close(); 232 // The pool should reject this one since it is already full 233 table3.close(); 234 235 // Request tables of the same name 236 Table sameTable1 = pool.getTable(TABLENAME); 237 Table sameTable2 = pool.getTable(TABLENAME); 238 Table sameTable3 = pool.getTable(TABLENAME); 239 Assert.assertSame( 240 ((HTablePool.PooledHTable) table1).getWrappedTable(), 241 ((HTablePool.PooledHTable) sameTable1).getWrappedTable()); 242 Assert.assertSame( 243 ((HTablePool.PooledHTable) table2).getWrappedTable(), 244 ((HTablePool.PooledHTable) sameTable2).getWrappedTable()); 245 Assert.assertNotSame( 246 ((HTablePool.PooledHTable) table3).getWrappedTable(), 247 ((HTablePool.PooledHTable) sameTable3).getWrappedTable()); 248 } 249 250 @Test testCloseTablePool()251 public void testCloseTablePool() throws IOException { 252 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 4, 253 getPoolType()); 254 HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration()); 255 256 if (admin.tableExists(TABLENAME)) { 257 admin.disableTable(TABLENAME); 258 admin.deleteTable(TABLENAME); 259 } 260 261 HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(TABLENAME)); 262 tableDescriptor.addFamily(new HColumnDescriptor("randomFamily")); 263 admin.createTable(tableDescriptor); 264 265 // Request tables from an empty pool 266 Table[] tables = new Table[4]; 267 for (int i = 0; i < 4; ++i) { 268 tables[i] = pool.getTable(TABLENAME); 269 } 270 271 pool.closeTablePool(TABLENAME); 272 273 for (int i = 0; i < 4; ++i) { 274 tables[i].close(); 275 } 276 277 Assert.assertEquals(4, 278 pool.getCurrentPoolSize(TABLENAME)); 279 280 pool.closeTablePool(TABLENAME); 281 282 Assert.assertEquals(0, 283 pool.getCurrentPoolSize(TABLENAME)); 284 } 285 } 286 287 @Category(MediumTests.class) 288 public static class TestHTableThreadLocalPool extends TestHTablePoolType { 289 @Override getPoolType()290 protected PoolType getPoolType() { 291 return PoolType.ThreadLocal; 292 } 293 294 @Test testTableWithMaxSize()295 public void testTableWithMaxSize() throws Exception { 296 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 2, 297 getPoolType()); 298 299 // Request tables from an empty pool 300 Table table1 = pool.getTable(TABLENAME); 301 Table table2 = pool.getTable(TABLENAME); 302 Table table3 = pool.getTable(TABLENAME); 303 304 // Close tables (returns tables to the pool) 305 table1.close(); 306 table2.close(); 307 // The pool should not reject this one since the number of threads 308 // <= 2 309 table3.close(); 310 311 // Request tables of the same name 312 Table sameTable1 = pool.getTable(TABLENAME); 313 Table sameTable2 = pool.getTable(TABLENAME); 314 Table sameTable3 = pool.getTable(TABLENAME); 315 Assert.assertSame( 316 ((HTablePool.PooledHTable) table3).getWrappedTable(), 317 ((HTablePool.PooledHTable) sameTable1).getWrappedTable()); 318 Assert.assertSame( 319 ((HTablePool.PooledHTable) table3).getWrappedTable(), 320 ((HTablePool.PooledHTable) sameTable2).getWrappedTable()); 321 Assert.assertSame( 322 ((HTablePool.PooledHTable) table3).getWrappedTable(), 323 ((HTablePool.PooledHTable) sameTable3).getWrappedTable()); 324 } 325 326 @Test testCloseTablePool()327 public void testCloseTablePool() throws IOException { 328 HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 4, 329 getPoolType()); 330 HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration()); 331 332 if (admin.tableExists(TABLENAME)) { 333 admin.disableTable(TABLENAME); 334 admin.deleteTable(TABLENAME); 335 } 336 337 HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(TABLENAME)); 338 tableDescriptor.addFamily(new HColumnDescriptor("randomFamily")); 339 admin.createTable(tableDescriptor); 340 341 // Request tables from an empty pool 342 Table[] tables = new Table[4]; 343 for (int i = 0; i < 4; ++i) { 344 tables[i] = pool.getTable(TABLENAME); 345 } 346 347 pool.closeTablePool(TABLENAME); 348 349 for (int i = 0; i < 4; ++i) { 350 tables[i].close(); 351 } 352 353 Assert.assertEquals(1, 354 pool.getCurrentPoolSize(TABLENAME)); 355 356 pool.closeTablePool(TABLENAME); 357 358 Assert.assertEquals(0, 359 pool.getCurrentPoolSize(TABLENAME)); 360 } 361 } 362 363 } 364