Index: src/test/java/org/apache/hadoop/hbase/catalog/TestMetaReaderEditor.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/catalog/TestMetaReaderEditor.java (revision 1064242) +++ src/test/java/org/apache/hadoop/hbase/catalog/TestMetaReaderEditor.java (working copy) @@ -19,11 +19,15 @@ */ package org.apache.hadoop.hbase.catalog; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -64,7 +68,7 @@ }; @BeforeClass public static void beforeClass() throws Exception { - UTIL.startMiniCluster(); + UTIL.startMiniCluster(3); } @Before public void setup() throws IOException, InterruptedException { @@ -111,17 +115,56 @@ LOG.info("Started " + name); final byte [] nameBytes = Bytes.toBytes(name); HTable t = UTIL.createTable(nameBytes, HConstants.CATALOG_FAMILY); - int regionCount = UTIL.createMultiRegions(t, HConstants.CATALOG_FAMILY); + final int regionCount = UTIL.createMultiRegions(t, HConstants.CATALOG_FAMILY); + // Test it works getting a region from user table. + testGettingTableRegions(this.ct, nameBytes, regionCount); + // Now test our being able to ride over .META. outage -- our MetaReader + // retrying. + final CatalogTracker finalCt = this.ct; + final AtomicInteger count = new AtomicInteger(0); + Thread backgroundTask = new Thread("reading-meta") { + @Override + public void run() { + while (true) { + try { + LOG.info("Scan .META. inside " + getName() + ": #" + count.get()); + testGettingTableRegions(finalCt, nameBytes, regionCount); + LOG.info("Scanned .META. inside " + getName() + ": #" + + count.incrementAndGet()); + } catch (IOException e) { + if (e.getCause() == null || + !(e.getCause() instanceof InterruptedException)) { + throw new RuntimeException("Failed", e); + } + // We get here if root cause was an InterruptedException + } catch (InterruptedException e) { + // Expected as this thread is stopped because of interrupt. + } + if (interrupted()) break; + } + } + }; + backgroundTask.start(); + for (int i = 0; i < 3; i++) { + LOG.info("Restart=" + i); + UTIL.ensureSomeRegionServersAvailable(2); + int index = -1; + do { + index = UTIL.getMiniHBaseCluster().getServerWithMeta(); + } while (index == -1); + UTIL.getMiniHBaseCluster().abortRegionServer(index); + UTIL.getMiniHBaseCluster().waitOnRegionServer(index); + } + // Wait on the completion of the scan if none yet. + while(count.get() == 0) Thread.sleep(1); + // Restarted + backgroundTask.interrupt(); + backgroundTask.join(); + assertTrue(count.get() > 0); - // Test it works getting a region from user table. - List regions = MetaReader.getTableRegions(ct, nameBytes); - assertEquals(regionCount, regions.size()); + // Test get on non-existent region. Pair pair = - MetaReader.getRegion(ct, regions.get(0).getRegionName()); - assertEquals(regions.get(0).getEncodedName(), - pair.getFirst().getEncodedName()); - // Test get on non-existent region. - pair = MetaReader.getRegion(ct, Bytes.toBytes("nonexistent-region")); + MetaReader.getRegion(ct, Bytes.toBytes("nonexistent-region")); assertNull(pair); // Test it works getting a region from meta/root. pair = @@ -130,4 +173,15 @@ pair.getFirst().getEncodedName()); LOG.info("Finished " + name); } + + private static void testGettingTableRegions(final CatalogTracker ct, + final byte [] nameBytes, final int regionCount) + throws IOException, InterruptedException { + List regions = MetaReader.getTableRegions(ct, nameBytes); + assertEquals(regionCount, regions.size()); + Pair pair = + MetaReader.getRegion(ct, regions.get(0).getRegionName()); + assertEquals(regions.get(0).getEncodedName(), + pair.getFirst().getEncodedName()); + } } \ No newline at end of file Index: src/main/java/org/apache/hadoop/hbase/HRegionLocation.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/HRegionLocation.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/HRegionLocation.java (working copy) @@ -44,7 +44,7 @@ */ @Override public String toString() { - return "address: " + this.serverAddress.toString() + ", regioninfo: " + + return "address=" + this.serverAddress.toString() + ", regioninfo=" + this.regionInfo.getRegionNameAsString(); } Index: src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java (working copy) @@ -1103,7 +1103,6 @@ // Presume that master has stale data. Presume remote side just split. // Presume that the split message when it comes in will fix up the master's // in memory cluster state. - return; } catch (ConnectException e) { LOG.info("Failed connect to " + server + ", message=" + e.getMessage() + ", region=" + region.getEncodedName()); @@ -1326,7 +1325,7 @@ private Map>> rebuildUserRegions() throws IOException { // Region assignment from META - List results = MetaReader.fullScanOfResults(catalogTracker); + List results = MetaReader.fullScan(catalogTracker); // Map of offline servers and their regions to be returned Map>> offlineServers = new TreeMap>>(); Index: src/main/java/org/apache/hadoop/hbase/master/handler/ServerShutdownHandler.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/handler/ServerShutdownHandler.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/master/handler/ServerShutdownHandler.java (working copy) @@ -41,7 +41,6 @@ import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.ServerManager; import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.hbase.util.Writables; import org.apache.zookeeper.KeeperException; /** @@ -209,7 +208,7 @@ final AssignmentManager assignmentManager, final CatalogTracker catalogTracker) throws IOException { - HRegionInfo daughter = getHRegionInfo(result, qualifier); + HRegionInfo daughter = MetaReader.getHRegionInfo(result, qualifier); if (daughter == null) return; if (isDaughterMissing(catalogTracker, daughter)) { LOG.info("Fixup; missing daughter " + daughter.getRegionNameAsString()); @@ -222,21 +221,6 @@ } /** - * Interpret the content of the cell at {@link HConstants#CATALOG_FAMILY} and - * qualifier as an HRegionInfo and return it, or null. - * @param r Result instance to pull from. - * @param qualifier Column family qualifier - * @return An HRegionInfo instance or null. - * @throws IOException - */ - private static HRegionInfo getHRegionInfo(final Result r, byte [] qualifier) - throws IOException { - byte [] bytes = r.getValue(HConstants.CATALOG_FAMILY, qualifier); - if (bytes == null || bytes.length <= 0) return null; - return Writables.getHRegionInfoOrNull(bytes); - } - - /** * Look for presence of the daughter OR of a split of the daughter. Daughter * could have been split over on regionserver before a run of the * catalogJanitor had chance to clear reference from parent. @@ -278,7 +262,7 @@ @Override public boolean visit(Result r) throws IOException { - HRegionInfo hri = getHRegionInfo(r, HConstants.REGIONINFO_QUALIFIER); + HRegionInfo hri = MetaReader.getHRegionInfo(r, HConstants.REGIONINFO_QUALIFIER); if (hri == null) { LOG.warn("No serialized HRegionInfo in " + r); return true; Index: src/main/java/org/apache/hadoop/hbase/master/handler/TableEventHandler.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/handler/TableEventHandler.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/master/handler/TableEventHandler.java (working copy) @@ -64,6 +64,9 @@ MetaReader.getTableRegions(this.server.getCatalogTracker(), tableName); handleTableOperation(hris); + } catch (InterruptedException e) { + LOG.error("Interrupted manipulation of table " + Bytes.toString(tableName), e); + Thread.currentThread().interrupt(); } catch (IOException e) { LOG.error("Error manipulating table " + Bytes.toString(tableName), e); } catch (KeeperException e) { Index: src/main/java/org/apache/hadoop/hbase/master/handler/EnableTableHandler.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/handler/EnableTableHandler.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/master/handler/EnableTableHandler.java (working copy) @@ -86,8 +86,15 @@ while (true) { // Get the regions of this table. We're done when all listed // tables are onlined. - List regionsInMeta = - MetaReader.getTableRegions(this.ct, tableName, true); + List regionsInMeta; + try { + regionsInMeta = MetaReader.getTableRegions(this.ct, tableName, true); + } catch (InterruptedException e1) { + LOG.warn("getTableRegions was interrupted"); + // Preserve the interrupt. + Thread.currentThread().interrupt(); + break; + } int countOfRegionsInTable = regionsInMeta.size(); List regions = regionsToAssign(regionsInMeta); if (regions.size() == 0) { Index: src/main/java/org/apache/hadoop/hbase/KeyValue.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/KeyValue.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/KeyValue.java (working copy) @@ -949,6 +949,7 @@ * @return True if this KV is a {@link KeyValue.Type#Delete} type. */ public boolean isDeleteType() { + // TODO: Fix this method name vis-a-vis isDelete! return getType() == Type.Delete.getCode(); } Index: src/main/java/org/apache/hadoop/hbase/catalog/RootLocationEditor.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/catalog/RootLocationEditor.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/catalog/RootLocationEditor.java (working copy) @@ -69,4 +69,4 @@ Bytes.toBytes(location.toString())); } } -} +} \ No newline at end of file Index: src/main/java/org/apache/hadoop/hbase/catalog/CatalogTracker.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/catalog/CatalogTracker.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/catalog/CatalogTracker.java (working copy) @@ -71,9 +71,8 @@ private final int defaultTimeout; private boolean stopped = false; - public static final byte [] ROOT_REGION = - HRegionInfo.ROOT_REGIONINFO.getRegionName(); - public static final byte [] META_REGION = + static final byte [] ROOT_REGION = HRegionInfo.ROOT_REGIONINFO.getRegionName(); + static final byte [] META_REGION = HRegionInfo.FIRST_META_REGIONINFO.getRegionName(); /** @@ -206,7 +205,7 @@ * @throws NotAllMetaRegionsOnlineException if timed out waiting * @throws IOException */ - public HRegionInterface waitForRootServerConnection(long timeout) + HRegionInterface waitForRootServerConnection(long timeout) throws InterruptedException, NotAllMetaRegionsOnlineException, IOException { return getCachedConnection(waitForRoot(timeout)); } @@ -219,7 +218,7 @@ * @throws NotAllMetaRegionsOnlineException if timed out waiting * @throws IOException */ - public HRegionInterface waitForRootServerConnectionDefault() + HRegionInterface waitForRootServerConnectionDefault() throws NotAllMetaRegionsOnlineException, IOException { try { return getCachedConnection(waitForRoot(defaultTimeout)); @@ -229,22 +228,6 @@ } /** - * Gets a connection to the server hosting root, as reported by ZooKeeper, - * if available. Returns null if no location is immediately available. - * @return connection to server hosting root, null if not available - * @throws IOException - * @throws InterruptedException - */ - private HRegionInterface getRootServerConnection() - throws IOException, InterruptedException { - HServerAddress address = this.rootRegionTracker.getRootRegionLocation(); - if (address == null) { - return null; - } - return getCachedConnection(address); - } - - /** * Gets a connection to the server currently hosting .META. or * null if location is not currently available. *

@@ -273,11 +256,11 @@ } resetMetaLocation(); } - HRegionInterface rootConnection = getRootServerConnection(); - if (rootConnection == null) { - return null; - } - HServerAddress newLocation = MetaReader.readMetaLocation(rootConnection); + // MetaReader.readRegionLocation will create an HTable instance and retry + // getting of cell. + HServerAddress newLocation = + MetaReader.readRegionLocation(this, + HRegionInfo.FIRST_META_REGIONINFO.getRegionName()); if (newLocation == null) { return null; } @@ -320,16 +303,16 @@ throws InterruptedException, IOException, NotAllMetaRegionsOnlineException { long stop = System.currentTimeMillis() + timeout; synchronized (metaAvailable) { - if (getMetaServerConnection(true) != null) { + if (verifyMetaRegionLocation(timeout)) { return metaLocation; } while(!stopped && !metaAvailable.get() && (timeout == 0 || System.currentTimeMillis() < stop)) { metaAvailable.wait(timeout); } - if (getMetaServerConnection(true) == null) { + if (!verifyMetaRegionLocation(timeout)) { throw new NotAllMetaRegionsOnlineException( - "Timed out (" + timeout + "ms)"); + "Timed out (" + timeout + "ms)"); } return metaLocation; } @@ -344,7 +327,7 @@ * @throws NotAllMetaRegionsOnlineException if timed out waiting * @throws IOException */ - public HRegionInterface waitForMetaServerConnection(long timeout) + HRegionInterface waitForMetaServerConnection(long timeout) throws InterruptedException, NotAllMetaRegionsOnlineException, IOException { return getCachedConnection(waitForMeta(timeout)); } @@ -479,6 +462,7 @@ */ public boolean verifyMetaRegionLocation(final long timeout) throws InterruptedException, IOException { + // Timeout is not used. return getMetaServerConnection(true) != null; } @@ -489,4 +473,4 @@ public HConnection getConnection() { return this.connection; } -} +} \ No newline at end of file Index: src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java (working copy) @@ -26,31 +26,29 @@ import java.util.NavigableMap; import java.util.Set; import java.util.TreeMap; -import java.util.TreeSet; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HServerAddress; import org.apache.hadoop.hbase.HServerInfo; import org.apache.hadoop.hbase.HTableDescriptor; -import org.apache.hadoop.hbase.NotAllMetaRegionsOnlineException; -import org.apache.hadoop.hbase.NotServingRegionException; import org.apache.hadoop.hbase.client.Get; +import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.ipc.HRegionInterface; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Pair; import org.apache.hadoop.hbase.util.Writables; -import org.apache.hadoop.ipc.RemoteException; /** * Reads region and assignment information from .META.. - *

- * Uses the {@link CatalogTracker} to obtain locations and connections to - * catalogs. */ public class MetaReader { + private static final Log LOG = LogFactory.getLog(MetaReader.class); public static final byte [] META_REGION_PREFIX; static { // Copy the prefix from FIRST_META_REGIONINFO into META_REGION_PREFIX. @@ -62,49 +60,7 @@ } /** - * @param ct - * @param tableName A user tablename or a .META. table name. - * @return Interface on to server hosting the -ROOT- or - * .META. regions. - * @throws NotAllMetaRegionsOnlineException - * @throws IOException - */ - private static HRegionInterface getCatalogRegionInterface(final CatalogTracker ct, - final byte [] tableName) - throws NotAllMetaRegionsOnlineException, IOException { - return Bytes.equals(HConstants.META_TABLE_NAME, tableName)? - ct.waitForRootServerConnectionDefault(): - ct.waitForMetaServerConnectionDefault(); - } - - /** - * @param tableName - * @return Returns region name to look in for regions for tableName; - * e.g. if we are looking for .META. regions, we need to look - * in the -ROOT- region, else if a user table, we need to look - * in the .META. region. - */ - private static byte [] getCatalogRegionNameForTable(final byte [] tableName) { - return Bytes.equals(HConstants.META_TABLE_NAME, tableName)? - HRegionInfo.ROOT_REGIONINFO.getRegionName(): - HRegionInfo.FIRST_META_REGIONINFO.getRegionName(); - } - - /** * @param regionName - * @return Returns region name to look in for regionName; - * e.g. if we are looking for .META.,,1 region, we need to look - * in -ROOT- region, else if a user region, we need to look - * in the .META.,,1 region. - */ - private static byte [] getCatalogRegionNameForRegion(final byte [] regionName) { - return isMetaRegion(regionName)? - HRegionInfo.ROOT_REGIONINFO.getRegionName(): - HRegionInfo.FIRST_META_REGIONINFO.getRegionName(); - } - - /** - * @param regionName * @return True if regionName is from .META. table. */ private static boolean isMetaRegion(final byte [] regionName) { @@ -119,22 +75,6 @@ } /** - * Performs a full scan of .META.. - *

- * Returns a map of every region to it's currently assigned server, according - * to META. If the region does not have an assignment it will have a null - * value in the map. - * - * @return map of regions to their currently assigned server - * @throws IOException - */ - public static Map fullScan( - CatalogTracker catalogTracker) - throws IOException { - return fullScan(catalogTracker, new TreeSet()); - } - - /** * Performs a full scan of .META., skipping regions from any * tables in the specified set of disabled tables. *

@@ -147,7 +87,7 @@ * @return map of regions to their currently assigned server * @throws IOException */ - public static Map fullScan( + public static Map fullScan( CatalogTracker catalogTracker, final Set disabledTables) throws IOException { return fullScan(catalogTracker, disabledTables, false); @@ -205,20 +145,16 @@ * @return map of regions to their currently assigned server * @throws IOException */ - public static List fullScanOfResults( - CatalogTracker catalogTracker) + public static List fullScan(CatalogTracker catalogTracker) throws IOException { - final List regions = new ArrayList(); - Visitor v = new Visitor() { + CollectingVisitor v = new CollectingVisitor() { @Override - public boolean visit(Result r) throws IOException { - if (r == null || r.isEmpty()) return true; - regions.add(r); - return true; + void add(Result r) { + this.results.add(r); } }; fullScan(catalogTracker, v); - return regions; + return v.getResults(); } /** @@ -252,36 +188,70 @@ public static void fullScan(CatalogTracker catalogTracker, final Visitor visitor, final byte [] startrow) throws IOException { - HRegionInterface metaServer = - catalogTracker.waitForMetaServerConnectionDefault(); + fullScan(catalogTracker, visitor, startrow, false); + } + + /** + * Performs a full scan of .META.. + *

+ * Returns a map of every region to it's currently assigned server, according + * to META. If the region does not have an assignment it will have a null + * value in the map. + * @param catalogTracker + * @param visitor + * @param startrow Where to start the scan. Pass null if want to begin scan + * at first row. + * @param scanRoot True if we are to scan -ROOT- rather than .META. + * @throws IOException + */ + static void fullScan(CatalogTracker catalogTracker, final Visitor visitor, + final byte [] startrow, final boolean scanRoot) + throws IOException { Scan scan = new Scan(); if (startrow != null) scan.setStartRow(startrow); scan.addFamily(HConstants.CATALOG_FAMILY); - long scannerid = metaServer.openScanner( - HRegionInfo.FIRST_META_REGIONINFO.getRegionName(), scan); + HTable metaTable = scanRoot? + getRootHTable(catalogTracker): getMetaHTable(catalogTracker); + ResultScanner scanner = metaTable.getScanner(scan); try { Result data; - while((data = metaServer.next(scannerid)) != null) { - if (!data.isEmpty()) visitor.visit(data); + while((data = scanner.next()) != null) { + if (data.isEmpty()) continue; + // Break if visit returns false. + if (!visitor.visit(data)) break; } } finally { - metaServer.close(scannerid); + scanner.close(); + metaTable.close(); } return; } - /** - * Reads the location of META from ROOT. - * @param metaServer connection to server hosting ROOT - * @return location of META in ROOT, null if not available - * @throws IOException - */ - public static HServerAddress readMetaLocation(HRegionInterface metaServer) + static HTable getHTableForRegion(final CatalogTracker catalogTracker, + final byte [] regionName) throws IOException { - return readLocation(metaServer, CatalogTracker.ROOT_REGION, - CatalogTracker.META_REGION); + return isMetaRegion(regionName)? + getRootHTable(catalogTracker): getMetaHTable(catalogTracker); } + static HTable getHTable(final CatalogTracker catalogTracker, + final byte [] tableName) + throws IOException { + // Passing the CatalogTracker's connection configuration ensures this + // HTable instance uses the CatalogTracker's connection. + return new HTable(catalogTracker.getConnection().getConfiguration(), tableName); + } + + static HTable getMetaHTable(final CatalogTracker ct) + throws IOException { + return getHTable(ct, HConstants.META_TABLE_NAME); + } + + static HTable getRootHTable(final CatalogTracker ct) + throws IOException { + return getHTable(ct, HConstants.ROOT_TABLE_NAME); + } + /** * Reads the location of the specified region from META. * @param catalogTracker @@ -292,58 +262,11 @@ public static HServerAddress readRegionLocation(CatalogTracker catalogTracker, byte [] regionName) throws IOException { - if (isMetaRegion(regionName)) throw new IllegalArgumentException("See readMetaLocation"); - return readLocation(catalogTracker.waitForMetaServerConnectionDefault(), - CatalogTracker.META_REGION, regionName); + Pair pair = getRegion(catalogTracker, regionName); + if (pair == null || pair.getSecond() == null) return null; + return pair.getSecond(); } - private static HServerAddress readLocation(HRegionInterface metaServer, - byte [] catalogRegionName, byte [] regionName) - throws IOException { - Result r = null; - try { - r = metaServer.get(catalogRegionName, - new Get(regionName).addColumn(HConstants.CATALOG_FAMILY, - HConstants.SERVER_QUALIFIER)); - } catch (java.net.SocketTimeoutException e) { - // Treat this exception + message as unavailable catalog table. Catch it - // and fall through to return a null - } catch (java.net.ConnectException e) { - if (e.getMessage() != null && - e.getMessage().contains("Connection refused")) { - // Treat this exception + message as unavailable catalog table. Catch it - // and fall through to return a null - } else { - throw e; - } - } catch (RemoteException re) { - IOException ioe = re.unwrapRemoteException(); - if (ioe instanceof NotServingRegionException) { - // Treat this NSRE as unavailable table. Catch and fall through to - // return null below - } else if (ioe.getMessage().contains("Server not running")) { - // Treat as unavailable table. - } else { - throw re; - } - } catch (IOException e) { - if (e.getCause() != null && e.getCause() instanceof IOException && - e.getCause().getMessage() != null && - e.getCause().getMessage().contains("Connection reset by peer")) { - // Treat this exception + message as unavailable catalog table. Catch it - // and fall through to return a null - } else { - throw e; - } - } - if (r == null || r.isEmpty()) { - return null; - } - byte [] value = r.getValue(HConstants.CATALOG_FAMILY, - HConstants.SERVER_QUALIFIER); - return new HServerAddress(Bytes.toString(value)); - } - /** * Gets the region info and assignment for the specified region from META. * @param catalogTracker @@ -356,11 +279,14 @@ throws IOException { Get get = new Get(regionName); get.addFamily(HConstants.CATALOG_FAMILY); - byte [] meta = getCatalogRegionNameForRegion(regionName); - Result r = catalogTracker.waitForMetaServerConnectionDefault().get(meta, get); - if(r == null || r.isEmpty()) { - return null; + HTable metaTable = getHTableForRegion(catalogTracker, regionName); + Result r = null; + try { + r = metaTable.get(get); + } finally { + metaTable.close(); } + if (r == null || r.isEmpty()) return null; return metaRowToRegionPair(r); } @@ -422,35 +348,43 @@ * @throws IOException */ public static boolean tableExists(CatalogTracker catalogTracker, - String tableName) + final String tableName) throws IOException { if (tableName.equals(HTableDescriptor.ROOT_TABLEDESC.getNameAsString()) || tableName.equals(HTableDescriptor.META_TABLEDESC.getNameAsString())) { // Catalog tables always exist. return true; } - HRegionInterface metaServer = - catalogTracker.waitForMetaServerConnectionDefault(); - byte[] firstRowInTable = Bytes.toBytes(tableName + ",,"); - Scan scan = new Scan(firstRowInTable); - scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER); - long scannerid = metaServer.openScanner( - HRegionInfo.FIRST_META_REGIONINFO.getRegionName(), scan); - try { - Result data = metaServer.next(scannerid); - if (data != null && data.size() > 0) { - HRegionInfo info = Writables.getHRegionInfo( - data.getValue(HConstants.CATALOG_FAMILY, - HConstants.REGIONINFO_QUALIFIER)); - if (info.getTableDesc().getNameAsString().equals(tableName)) { - // A region for this table already exists. Ergo table exists. + final byte [] tableNameBytes = Bytes.toBytes(tableName); + // Make a version of ResultCollectingVisitor that only collects the first + // region in a table, if one. + CollectingVisitor visitor = new CollectingVisitor() { + private HRegionInfo current = null; + + @Override + public boolean visit(Result r) throws IOException { + this.current = getHRegionInfo(r, HConstants.REGIONINFO_QUALIFIER); + if (this.current == null) { + LOG.warn("No serialized HRegionInfo in " + r); return true; } + if (!isInsideTable(this.current, tableNameBytes)) return false; + if (this.current.isSplitParent()) return true; + // Else call super and add this Result to the collection. + super.visit(r); + // Stop collecting regions from table after we get one. + return false; } - return false; - } finally { - metaServer.close(scannerid); - } + + @Override + void add(Result r) { + // Add the current HRI. + this.results.add(this.current); + } + }; + fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableNameBytes)); + // If visitor has results >= 1 then table exists. + return visitor.getResults().size() >= 1; } /** @@ -459,10 +393,11 @@ * @param tableName * @return Ordered list of {@link HRegionInfo}. * @throws IOException + * @throws InterruptedException */ public static List getTableRegions(CatalogTracker catalogTracker, byte [] tableName) - throws IOException { + throws IOException, InterruptedException { return getTableRegions(catalogTracker, tableName, false); } @@ -474,55 +409,50 @@ * parents in the return. * @return Ordered list of {@link HRegionInfo}. * @throws IOException + * @throws InterruptedException */ public static List getTableRegions(CatalogTracker catalogTracker, - byte [] tableName, final boolean excludeOfflinedSplitParents) - throws IOException { - if (Bytes.equals(tableName, HConstants.ROOT_TABLE_NAME)) { - // If root, do a bit of special handling. - List list = new ArrayList(); - list.add(HRegionInfo.ROOT_REGIONINFO); - return list; - } else if (Bytes.equals(tableName, HConstants.META_TABLE_NAME)) { - // Same for .META. table - List list = new ArrayList(); - list.add(HRegionInfo.FIRST_META_REGIONINFO); - return list; - } + final byte [] tableName, final boolean excludeOfflinedSplitParents) + throws IOException, InterruptedException { + List> result = + getTableRegionsAndLocations(catalogTracker, tableName, + excludeOfflinedSplitParents); + return getListOfHRegionInfos(result); + } - // Its a user table. - HRegionInterface metaServer = - getCatalogRegionInterface(catalogTracker, tableName); - List regions = new ArrayList(); - String tableString = Bytes.toString(tableName); - byte[] firstRowInTable = Bytes.toBytes(tableString + ",,"); - Scan scan = new Scan(firstRowInTable); - scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER); - long scannerid = - metaServer.openScanner(getCatalogRegionNameForTable(tableName), scan); - try { - Result data; - while((data = metaServer.next(scannerid)) != null) { - if (data != null && data.size() > 0) { - HRegionInfo info = Writables.getHRegionInfo( - data.getValue(HConstants.CATALOG_FAMILY, - HConstants.REGIONINFO_QUALIFIER)); - if (info.getTableDesc().getNameAsString().equals(tableString)) { - // Are we to include split parents in the list? - if (excludeOfflinedSplitParents && info.isSplitParent()) continue; - regions.add(info); - } else { - break; - } - } - } - return regions; - } finally { - metaServer.close(scannerid); + static List getListOfHRegionInfos(final List> pairs) { + if (pairs == null || pairs.isEmpty()) return null; + List result = new ArrayList(pairs.size()); + for (Pair pair: pairs) { + result.add(pair.getFirst()); } + return result; } /** + * @param current + * @param tableName + * @return True if current tablename is equal to + * tableName + */ + static boolean isInsideTable(final HRegionInfo current, final byte [] tableName) { + return Bytes.equals(tableName, current.getTableDesc().getName()); + } + + /** + * @param tableName + * @return Place to start Scan in .META. when passed a + * tableName; returns <tableName&rt; <,&rt; <,&rt; + */ + static byte [] getTableStartRowForMeta(final byte [] tableName) { + byte [] startRow = new byte[tableName.length + 2]; + System.arraycopy(tableName, 0, startRow, 0, tableName.length); + startRow[startRow.length - 2] = HRegionInfo.DELIMITER; + startRow[startRow.length - 1] = HRegionInfo.DELIMITER; + return startRow; + } + + /** * @param catalogTracker * @param tableName * @return Return list of regioninfos and server addresses. @@ -532,8 +462,22 @@ public static List> getTableRegionsAndLocations(CatalogTracker catalogTracker, String tableName) throws IOException, InterruptedException { - byte [] tableNameBytes = Bytes.toBytes(tableName); - if (Bytes.equals(tableNameBytes, HConstants.ROOT_TABLE_NAME)) { + return getTableRegionsAndLocations(catalogTracker, Bytes.toBytes(tableName), + true); + } + + /** + * @param catalogTracker + * @param tableName + * @return Return list of regioninfos and server addresses. + * @throws IOException + * @throws InterruptedException + */ + public static List> + getTableRegionsAndLocations(final CatalogTracker catalogTracker, + final byte [] tableName, final boolean excludeOfflinedSplitParents) + throws IOException, InterruptedException { + if (Bytes.equals(tableName, HConstants.ROOT_TABLE_NAME)) { // If root, do a bit of special handling. HServerAddress hsa = catalogTracker.getRootLocation(); List> list = @@ -541,33 +485,35 @@ list.add(new Pair(HRegionInfo.ROOT_REGIONINFO, hsa)); return list; } - HRegionInterface metaServer = - getCatalogRegionInterface(catalogTracker, tableNameBytes); - List> regions = - new ArrayList>(); - byte[] firstRowInTable = Bytes.toBytes(tableName + ",,"); - Scan scan = new Scan(firstRowInTable); - scan.addFamily(HConstants.CATALOG_FAMILY); - long scannerid = - metaServer.openScanner(getCatalogRegionNameForTable(tableNameBytes), scan); - try { - Result data; - while((data = metaServer.next(scannerid)) != null) { - if (data != null && data.size() > 0) { - Pair region = metaRowToRegionPair(data); - if (region == null) continue; - if (region.getFirst().getTableDesc().getNameAsString().equals( - tableName)) { - regions.add(region); - } else { - break; - } + // Make a version of CollectingVisitor that collects HRegionInfo and ServerAddress + CollectingVisitor> visitor = + new CollectingVisitor>() { + private Pair current = null; + + @Override + public boolean visit(Result r) throws IOException { + HRegionInfo hri = getHRegionInfo(r, HConstants.REGIONINFO_QUALIFIER); + if (hri == null) { + LOG.warn("No serialized HRegionInfo in " + r); + return true; } + if (!isInsideTable(hri, tableName)) return false; + if (excludeOfflinedSplitParents && hri.isSplitParent()) return true; + HServerAddress hsa = getHServerAddress(r, HConstants.SERVER_QUALIFIER); + // Populate this.current so available when we call #add + this.current = new Pair(hri, hsa); + // Else call super and add this Result to the collection. + return super.visit(r); } - return regions; - } finally { - metaServer.close(scannerid); - } + + @Override + void add(Result r) { + this.results.add(this.current); + } + }; + fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableName), + Bytes.equals(tableName, HConstants.META_TABLE_NAME)); + return visitor.getResults(); } /** @@ -607,6 +553,37 @@ } /** + * Interpret the content of the cell at {@link HConstants#CATALOG_FAMILY} and + * qualifier as an HRegionInfo and return it, or null. + * @param r Result instance to pull from. + * @param qualifier Column family qualifier -- either + * {@link HConstants#SPLITA_QUALIFIER}, {@link HConstants#SPLITB_QUALIFIER} or + * {@link HConstants#REGIONINFO_QUALIFIER}. + * @return An HRegionInfo instance or null. + * @throws IOException + */ + public static HRegionInfo getHRegionInfo(final Result r, byte [] qualifier) + throws IOException { + byte [] bytes = r.getValue(HConstants.CATALOG_FAMILY, qualifier); + if (bytes == null || bytes.length <= 0) return null; + return Writables.getHRegionInfoOrNull(bytes); + } + + /** + * @param r Result to pull from. + * @param qualifier + * @return An {@link HServerAddress} instance made from content of r + * at qualifier. + */ + public static HServerAddress getHServerAddress(final Result r, + byte [] qualifier) { + if (r == null || r.isEmpty()) return null; + byte [] value = r.getValue(HConstants.CATALOG_FAMILY, qualifier); + return value == null || value.length <= 0? null: + new HServerAddress(Bytes.toString(value)); + } + + /** * Implementations 'visit' a catalog table row. */ public interface Visitor { @@ -618,4 +595,27 @@ */ public boolean visit(final Result r) throws IOException; } -} + + /** + * A {@link Visitor} that collects content out of passed {@link Result}. + */ + static abstract class CollectingVisitor implements Visitor { + final List results = new ArrayList(); + @Override + public boolean visit(Result r) throws IOException { + if (r == null || r.isEmpty()) return true; + add(r); + return true; + } + + abstract void add(Result r); + + /** + * @return Collected results; wait till visits complete to collect all + * possible results + */ + List getResults() { + return this.results; + } + } +} \ No newline at end of file Index: src/main/java/org/apache/hadoop/hbase/catalog/MetaEditor.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/catalog/MetaEditor.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/catalog/MetaEditor.java (working copy) @@ -29,16 +29,13 @@ import org.apache.hadoop.hbase.HServerInfo; import org.apache.hadoop.hbase.NotAllMetaRegionsOnlineException; import org.apache.hadoop.hbase.client.Delete; +import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.client.Put; -import org.apache.hadoop.hbase.ipc.HRegionInterface; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Writables; /** * Writes region and assignment information to .META.. - *

- * Uses the {@link CatalogTracker} to obtain locations and connections to - * catalogs. */ public class MetaEditor { private static final Log LOG = LogFactory.getLog(MetaEditor.class); @@ -54,9 +51,13 @@ Put put = new Put(regionInfo.getRegionName()); put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, Writables.getBytes(regionInfo)); - catalogTracker.waitForMetaServerConnectionDefault().put( - CatalogTracker.META_REGION, put); - LOG.info("Added region " + regionInfo.getRegionNameAsString() + " to META"); + HTable metaTable = MetaReader.getMetaHTable(catalogTracker); + try { + metaTable.put(put); + LOG.info("Added region " + regionInfo.getRegionNameAsString() + " to META"); + } finally { + metaTable.close(); + } } /** @@ -81,24 +82,32 @@ Writables.getBytes(a)); put.add(HConstants.CATALOG_FAMILY, HConstants.SPLITB_QUALIFIER, Writables.getBytes(b)); - catalogTracker.waitForMetaServerConnectionDefault().put(CatalogTracker.META_REGION, put); - LOG.info("Offlined parent region " + parent.getRegionNameAsString() + + HTable metaTable = MetaReader.getMetaHTable(catalogTracker); + try { + metaTable.put(put); + LOG.info("Offlined parent region " + parent.getRegionNameAsString() + " in META"); + } finally { + metaTable.close(); + } } public static void addDaughter(final CatalogTracker catalogTracker, final HRegionInfo regionInfo, final HServerInfo serverInfo) throws NotAllMetaRegionsOnlineException, IOException { - HRegionInterface server = catalogTracker.waitForMetaServerConnectionDefault(); - byte [] catalogRegionName = CatalogTracker.META_REGION; Put put = new Put(regionInfo.getRegionName()); addRegionInfo(put, regionInfo); if (serverInfo != null) addLocation(put, serverInfo); - server.put(catalogRegionName, put); - LOG.info("Added daughter " + regionInfo.getRegionNameAsString() + - " in region " + Bytes.toString(catalogRegionName) + + HTable metaTable = MetaReader.getMetaHTable(catalogTracker); + try { + metaTable.put(put); + LOG.info("Added daughter " + regionInfo.getRegionNameAsString() + + " in region " + Bytes.toString(metaTable.getTableName()) + (serverInfo == null? ", serverInfo=null": ", serverInfo=" + serverInfo.getServerName())); + } finally { + metaTable.close(); + } } /** @@ -119,9 +128,7 @@ public static void updateMetaLocation(CatalogTracker catalogTracker, HRegionInfo regionInfo, HServerInfo serverInfo) throws IOException, ConnectException { - HRegionInterface server = catalogTracker.waitForRootServerConnectionDefault(); - if (server == null) throw new IOException("No server for -ROOT-"); - updateLocation(server, CatalogTracker.ROOT_REGION, regionInfo, serverInfo); + updateLocation(catalogTracker, regionInfo, serverInfo); } /** @@ -139,8 +146,7 @@ public static void updateRegionLocation(CatalogTracker catalogTracker, HRegionInfo regionInfo, HServerInfo serverInfo) throws IOException { - updateLocation(catalogTracker.waitForMetaServerConnectionDefault(), - CatalogTracker.META_REGION, regionInfo, serverInfo); + updateLocation(catalogTracker, regionInfo, serverInfo); } /** @@ -149,23 +155,28 @@ * Connects to the specified server which should be hosting the specified * catalog region name to perform the edit. * - * @param server connection to server hosting catalog region - * @param catalogRegionName name of catalog region being updated + * @param catalogTracker * @param regionInfo region to update location of * @param serverInfo server the region is located on * @throws IOException In particular could throw {@link java.net.ConnectException} * if the server is down on other end. */ - private static void updateLocation(HRegionInterface server, - byte [] catalogRegionName, HRegionInfo regionInfo, HServerInfo serverInfo) + private static void updateLocation(final CatalogTracker catalogTracker, + HRegionInfo regionInfo, HServerInfo serverInfo) throws IOException { + final byte [] regionName = regionInfo.getRegionName(); Put put = new Put(regionInfo.getRegionName()); addLocation(put, serverInfo); - server.put(catalogRegionName, put); - LOG.info("Updated row " + regionInfo.getRegionNameAsString() + - " in region " + Bytes.toString(catalogRegionName) + " with " + - "server=" + serverInfo.getHostnamePort() + ", " + - "startcode=" + serverInfo.getStartCode()); + HTable metaTable = + MetaReader.getHTableForRegion(catalogTracker, regionName); + try { + metaTable.put(put); + LOG.info("Updated row " + regionInfo.getRegionNameAsString() + + " in region " + Bytes.toString(metaTable.getTableName()) + + " with server=" + serverInfo.getServerName()); + } finally { + metaTable.close(); + } } /** @@ -178,9 +189,14 @@ HRegionInfo regionInfo) throws IOException { Delete delete = new Delete(regionInfo.getRegionName()); - catalogTracker.waitForMetaServerConnectionDefault(). - delete(CatalogTracker.META_REGION, delete); - LOG.info("Deleted region " + regionInfo.getRegionNameAsString() + " from META"); + HTable metaTable = MetaReader.getMetaHTable(catalogTracker); + try { + metaTable.delete(delete); + LOG.info("Deleted region " + regionInfo.getRegionNameAsString() + + " from META"); + } finally { + metaTable.close(); + } } /** @@ -198,11 +214,15 @@ throws NotAllMetaRegionsOnlineException, IOException { Delete delete = new Delete(parent.getRegionName()); delete.deleteColumns(HConstants.CATALOG_FAMILY, qualifier); - catalogTracker.waitForMetaServerConnectionDefault(). - delete(CatalogTracker.META_REGION, delete); - LOG.info("Deleted daughter reference " + daughter.getRegionNameAsString() + + HTable metaTable = MetaReader.getMetaHTable(catalogTracker); + try { + metaTable.delete(delete); + LOG.info("Deleted daughter reference " + daughter.getRegionNameAsString() + ", qualifier=" + Bytes.toString(qualifier) + ", from parent " + parent.getRegionNameAsString()); + } finally { + metaTable.close(); + } } /** @@ -216,15 +236,20 @@ throws IOException { Put put = new Put(regionInfo.getRegionName()); addRegionInfo(put, regionInfo); - catalogTracker.waitForMetaServerConnectionDefault().put( - CatalogTracker.META_REGION, put); - LOG.info("Updated region " + regionInfo.getRegionNameAsString() + " in META"); + HTable metaTable = MetaReader.getMetaHTable(catalogTracker); + try { + metaTable.put(put); + LOG.info("Updated region " + regionInfo.getRegionNameAsString() + + " in META"); + } finally { + metaTable.close(); + } } private static Put addRegionInfo(final Put p, final HRegionInfo hri) throws IOException { p.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, - Writables.getBytes(hri)); + Writables.getBytes(hri)); return p; } @@ -235,4 +260,4 @@ Bytes.toBytes(hsi.getStartCode())); return p; } -} +} \ No newline at end of file Index: src/main/java/org/apache/hadoop/hbase/client/MetaScanner.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/MetaScanner.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/client/MetaScanner.java (working copy) @@ -264,4 +264,4 @@ */ public boolean processRow(Result rowResult) throws IOException; } -} +} \ No newline at end of file Index: src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java (working copy) @@ -705,7 +705,7 @@ deleteCachedLocation(tableName, row); } - // Query the root or meta region for the location of the meta region + // Query the root or meta region for the location of the meta region regionInfoRow = server.getClosestRowBefore( metaLocation.getRegionInfo().getRegionName(), metaKey, HConstants.CATALOG_FAMILY); @@ -951,7 +951,7 @@ } catch (RemoteException e) { LOG.warn("RemoteException connecting to RS", e); // Throw what the RemoteException was carrying. - throw RemoteExceptionHandler.decodeRemoteException(e); + throw e.unwrapRemoteException(); } this.servers.put(regionServer.toString(), server); } @@ -989,21 +989,21 @@ List exceptions = new ArrayList(); for(int tries = 0; tries < numRetries; tries++) { try { - callable.instantiateServer(tries != 0); + callable.connect(tries != 0); return callable.call(); } catch (Throwable t) { t = translateException(t); exceptions.add(t); if (tries == numRetries - 1) { - throw new RetriesExhaustedException(callable.getServerName(), - callable.getRegionName(), callable.getRow(), tries, exceptions); + throw new RetriesExhaustedException(callable.toString(), tries, + exceptions); } } try { Thread.sleep(getPauseTime(tries)); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new IOException("Giving up trying to get region server: thread is interrupted."); + throw new IOException("Giving up trying to get region server", e); } } return null; @@ -1012,7 +1012,7 @@ public T getRegionServerWithoutRetries(ServerCallable callable) throws IOException, RuntimeException { try { - callable.instantiateServer(false); + callable.connect(false); return callable.call(); } catch (Throwable t) { Throwable t2 = translateException(t); @@ -1059,7 +1059,7 @@ return server.multi(multi); } @Override - public void instantiateServer(boolean reload) throws IOException { + public void connect(boolean reload) throws IOException { server = connection.getHRegionConnection(address); } } Index: src/main/java/org/apache/hadoop/hbase/client/RetriesExhaustedException.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/RetriesExhaustedException.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/client/RetriesExhaustedException.java (working copy) @@ -15,8 +15,6 @@ */ package org.apache.hadoop.hbase.client; -import org.apache.hadoop.hbase.util.Bytes; - import java.io.IOException; import java.util.List; @@ -37,27 +35,21 @@ /** * Create a new RetriesExhaustedException from the list of prior failures. - * @param serverName name of HRegionServer - * @param regionName name of region - * @param row The row we were pursuing when we ran out of retries + * @param callableVitals Details from the {@link ServerCallable} we were using + * when we got this exception. * @param numTries The number of tries we made * @param exceptions List of exceptions that failed before giving up */ - public RetriesExhaustedException(String serverName, final byte [] regionName, - final byte [] row, int numTries, List exceptions) { - super(getMessage(serverName, regionName, row, numTries, exceptions)); + public RetriesExhaustedException(final String callableVitals, int numTries, + List exceptions) { + super(getMessage(callableVitals, numTries, exceptions)); } - private static String getMessage(String serverName, final byte [] regionName, - final byte [] row, - int numTries, List exceptions) { - StringBuilder buffer = new StringBuilder("Trying to contact region server "); - buffer.append(serverName); - buffer.append(" for region "); - buffer.append(regionName == null? "": Bytes.toStringBinary(regionName)); - buffer.append(", row '"); - buffer.append(row == null? "": Bytes.toStringBinary(row)); - buffer.append("', but failed after "); + private static String getMessage(String callableVitals, int numTries, + List exceptions) { + StringBuilder buffer = new StringBuilder("Failed contacting "); + buffer.append(callableVitals); + buffer.append(" after "); buffer.append(numTries + 1); buffer.append(" attempts.\nExceptions:\n"); for (Throwable t : exceptions) { Index: src/main/java/org/apache/hadoop/hbase/client/HTable.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HTable.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/client/HTable.java (working copy) @@ -170,7 +170,8 @@ } this.connection = HConnectionManager.getConnection(conf); this.scannerTimeout = - (int) conf.getLong(HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY, HConstants.DEFAULT_HBASE_REGIONSERVER_LEASE_PERIOD); + (int)conf.getLong(HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY, + HConstants.DEFAULT_HBASE_REGIONSERVER_LEASE_PERIOD); this.configuration = conf; this.connection.locateRegion(tableName, HConstants.EMPTY_START_ROW); this.writeBufferSize = conf.getLong("hbase.client.write.buffer", 2097152); @@ -379,8 +380,9 @@ } }; MetaScanner.metaScan(configuration, visitor, this.tableName); - return new Pair(startKeyList.toArray(new byte[startKeyList.size()][]), - endKeyList.toArray(new byte[endKeyList.size()][])); + return new Pair( + startKeyList.toArray(new byte[startKeyList.size()][]), + endKeyList.toArray(new byte[endKeyList.size()][])); } /** Index: src/main/java/org/apache/hadoop/hbase/client/ScannerCallable.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/ScannerCallable.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/client/ScannerCallable.java (working copy) @@ -58,9 +58,9 @@ * @throws IOException */ @Override - public void instantiateServer(boolean reload) throws IOException { + public void connect(boolean reload) throws IOException { if (!instantiated || reload) { - super.instantiateServer(reload); + super.connect(reload); instantiated = true; } } Index: src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java (revision 1064242) +++ src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java (working copy) @@ -22,12 +22,21 @@ import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.ipc.HRegionInterface; +import org.apache.hadoop.hbase.util.Bytes; import java.io.IOException; import java.util.concurrent.Callable; /** - * Abstract class that implements Callable, used by retryable actions. + * Abstract class that implements {@link Callable}. Implementation stipulates + * return type and method we actually invoke on remote Server. Usually + * used inside a try/catch that fields usual connection failures all wrapped + * up in a retry loop. + *

Call {@link #connect(boolean)} to connect to server hosting region + * that contains the passed row in the passed table before invoking + * {@link #call()}. + * @see HConnection#getRegionServerWithoutRetries(ServerCallable) + * * @param the class that the ServerCallable handles */ public abstract class ServerCallable implements Callable { @@ -38,9 +47,9 @@ protected HRegionInterface server; /** - * @param connection connection callable is on - * @param tableName table name callable is on - * @param row row we are querying + * @param connection Connection to use. + * @param tableName Table name to which row belongs. + * @param row The row we want in tableName. */ public ServerCallable(HConnection connection, byte [] tableName, byte [] row) { this.connection = connection; @@ -49,33 +58,21 @@ } /** - * - * @param reload set this to true if connection should re-find the region + * Connect to the server hosting region with row from tablename. + * @param reload Set this to true if connection should re-find the region * @throws IOException e */ - public void instantiateServer(boolean reload) throws IOException { + public void connect(final boolean reload) throws IOException { this.location = connection.getRegionLocation(tableName, row, reload); this.server = connection.getHRegionConnection(location.getServerAddress()); } - /** @return the server name */ - public String getServerName() { - if (location == null) { - return null; - } - return location.getServerAddress().toString(); + /** + * @return String of current state. + */ + public String toString() { + return (location == null? "null": location.toString()) + + ", tableName=" + (tableName == null? "": Bytes.toString(this.tableName)) + + ", row=" + (row == null? "": Bytes.toStringBinary(this.row)); } - - /** @return the region name */ - public byte[] getRegionName() { - if (location == null) { - return null; - } - return location.getRegionInfo().getRegionName(); - } - - /** @return the row */ - public byte [] getRow() { - return row; - } } \ No newline at end of file