diff --git a/CHANGES.txt b/CHANGES.txt
index b1874cb9495..391305c4257 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -497,6 +497,8 @@ Release 0.21.0 - Unreleased
(Todd Lipcon via Stack)
HBASE-2423 Update 'Getting Started' for 0.20.4 including making
"important configurations more visiable"
+ HBASE-2435 HTablePool - method to release resources after use
+ (Kay Kay via Stack)
NEW FEATURES
HBASE-1961 HBase EC2 scripts
diff --git a/core/src/main/java/org/apache/hadoop/hbase/client/HTableFactory.java b/core/src/main/java/org/apache/hadoop/hbase/client/HTableFactory.java
index 372ed19daab..6dfdff61331 100644
--- a/core/src/main/java/org/apache/hadoop/hbase/client/HTableFactory.java
+++ b/core/src/main/java/org/apache/hadoop/hbase/client/HTableFactory.java
@@ -39,4 +39,17 @@ public class HTableFactory implements HTableInterfaceFactory {
throw new RuntimeException(ioe);
}
}
+
+ @Override
+ public void releaseHTableInterface(HTableInterface table) {
+ try {
+ table.close();
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+
+ }
+
+
+
}
diff --git a/core/src/main/java/org/apache/hadoop/hbase/client/HTableInterfaceFactory.java b/core/src/main/java/org/apache/hadoop/hbase/client/HTableInterfaceFactory.java
index a82fb89bf12..a80d94ec92a 100644
--- a/core/src/main/java/org/apache/hadoop/hbase/client/HTableInterfaceFactory.java
+++ b/core/src/main/java/org/apache/hadoop/hbase/client/HTableInterfaceFactory.java
@@ -37,4 +37,11 @@ public interface HTableInterfaceFactory {
* @return HTableInterface instance.
*/
HTableInterface createHTableInterface(Configuration config, byte[] tableName);
+
+
+ /**
+ * Release the HTable resource represented by the table.
+ * @param table
+ */
+ void releaseHTableInterface(final HTableInterface table);
}
diff --git a/core/src/main/java/org/apache/hadoop/hbase/client/HTablePool.java b/core/src/main/java/org/apache/hadoop/hbase/client/HTablePool.java
index 2b92cbe5cd8..c7f61fa8048 100755
--- a/core/src/main/java/org/apache/hadoop/hbase/client/HTablePool.java
+++ b/core/src/main/java/org/apache/hadoop/hbase/client/HTablePool.java
@@ -27,6 +27,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
+import java.util.Queue;
/**
* A simple pool of HTable instances.
@@ -124,4 +125,41 @@ public class HTablePool {
protected HTableInterface createHTable(String tableName) {
return this.tableFactory.createHTableInterface(config, Bytes.toBytes(tableName));
}
+
+ /**
+ * Closes all the HTable instances , belonging to the given table, in the table pool.
+ *
+ * Note: this is a 'shutdown' of the given table pool and different from
+ * {@link #putTable(HTableInterface)}, that is used to return the table
+ * instance to the pool for future re-use.
+ *
+ * @param tableName
+ */
+ public void closeTablePool(final String tableName) {
+ Queue queue = tables.get(tableName);
+ synchronized (queue) {
+ HTableInterface table = queue.poll();
+ while (table != null) {
+ this.tableFactory.releaseHTableInterface(table);
+ table = queue.poll();
+ }
+ }
+
+ }
+
+ /**
+ * See {@link #closeTablePool(String)}.
+ *
+ * @param tableName
+ */
+ public void closeTablePool(final byte[] tableName) {
+ closeTablePool(Bytes.toString(tableName));
+ }
+
+ int getCurrentPoolSize(String tableName) {
+ Queue queue = tables.get(tableName);
+ synchronized(queue) {
+ return queue.size();
+ }
+ }
}
diff --git a/core/src/test/java/org/apache/hadoop/hbase/client/TestHTablePool.java b/core/src/test/java/org/apache/hadoop/hbase/client/TestHTablePool.java
index a58af1faf92..394fd674292 100644
--- a/core/src/test/java/org/apache/hadoop/hbase/client/TestHTablePool.java
+++ b/core/src/test/java/org/apache/hadoop/hbase/client/TestHTablePool.java
@@ -19,47 +19,73 @@
*/
package org.apache.hadoop.hbase.client;
+import java.io.IOException;
+
+import junit.framework.Assert;
+
import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.HBaseTestCase;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.util.Bytes;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
/**
* Tests HTablePool.
*/
-public class TestHTablePool extends HBaseTestCase {
+public class TestHTablePool {
+ private static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ TEST_UTIL.startMiniCluster(1);
+
+ }
+
+ @AfterClass
+ public static void afterClass() throws IOException {
+ TEST_UTIL.shutdownMiniCluster();
+ }
+
+ @Test
public void testTableWithStringName() {
HTablePool pool = new HTablePool((HBaseConfiguration)null, Integer.MAX_VALUE);
String tableName = "testTable";
// Request a table from an empty pool
HTableInterface table = pool.getTable(tableName);
- assertNotNull(table);
+ Assert.assertNotNull(table);
// Return the table to the pool
pool.putTable(table);
// Request a table of the same name
HTableInterface sameTable = pool.getTable(tableName);
- assertSame(table, sameTable);
+ Assert.assertSame(table, sameTable);
}
+ @Test
public void testTableWithByteArrayName() {
HTablePool pool = new HTablePool((HBaseConfiguration)null, Integer.MAX_VALUE);
byte[] tableName = Bytes.toBytes("testTable");
// Request a table from an empty pool
HTableInterface table = pool.getTable(tableName);
- assertNotNull(table);
+ Assert.assertNotNull(table);
// Return the table to the pool
pool.putTable(table);
// Request a table of the same name
HTableInterface sameTable = pool.getTable(tableName);
- assertSame(table, sameTable);
+ Assert.assertSame(table, sameTable);
}
+ @Test
public void testTableWithMaxSize() {
HTablePool pool = new HTablePool((HBaseConfiguration)null, 2);
String tableName = "testTable";
@@ -79,11 +105,12 @@ public class TestHTablePool extends HBaseTestCase {
HTableInterface sameTable1 = pool.getTable(tableName);
HTableInterface sameTable2 = pool.getTable(tableName);
HTableInterface sameTable3 = pool.getTable(tableName);
- assertSame(table1, sameTable1);
- assertSame(table2, sameTable2);
- assertNotSame(table3, sameTable3);
+ Assert.assertSame(table1, sameTable1);
+ Assert.assertSame(table2, sameTable2);
+ Assert.assertNotSame(table3, sameTable3);
}
+ @Test
public void testTablesWithDifferentNames() {
HTablePool pool = new HTablePool((HBaseConfiguration)null, Integer.MAX_VALUE);
String tableName1 = "testTable1";
@@ -92,7 +119,7 @@ public class TestHTablePool extends HBaseTestCase {
// Request a table from an empty pool
HTableInterface table1 = pool.getTable(tableName1);
HTableInterface table2 = pool.getTable(tableName2);
- assertNotNull(table2);
+ Assert.assertNotNull(table2);
// Return the tables to the pool
pool.putTable(table1);
@@ -101,7 +128,45 @@ public class TestHTablePool extends HBaseTestCase {
// Request tables of the same names
HTableInterface sameTable1 = pool.getTable(tableName1);
HTableInterface sameTable2 = pool.getTable(tableName2);
- assertSame(table1, sameTable1);
- assertSame(table2, sameTable2);
+ Assert.assertSame(table1, sameTable1);
+ Assert.assertSame(table2, sameTable2);
}
-}
\ No newline at end of file
+
+
+ @Test
+ public void testCloseTablePool() throws IOException {
+
+ HTablePool pool = new HTablePool(TEST_UTIL.getConfiguration(), 4);
+ String tableName = "testTable";
+ HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
+
+ if (admin.tableExists(tableName)) {
+ admin.deleteTable(tableName);
+ }
+
+ HTableDescriptor tableDescriptor = new HTableDescriptor(Bytes
+ .toBytes(tableName));
+ tableDescriptor.addFamily(new HColumnDescriptor("randomFamily"));
+ admin.createTable(tableDescriptor);
+
+
+ // Request tables from an empty pool
+ HTableInterface[] tables = new HTableInterface[4];
+ for (int i = 0; i < 4; ++i ) {
+ tables[i] = pool.getTable(tableName);
+ }
+
+ pool.closeTablePool(tableName);
+
+ for (int i = 0; i < 4; ++i ) {
+ pool.putTable(tables[i]);
+ }
+
+ Assert.assertEquals(4, pool.getCurrentPoolSize(tableName));
+
+ pool.closeTablePool(tableName);
+
+ Assert.assertEquals(0, pool.getCurrentPoolSize(tableName));
+
+ }
+}