You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ji...@apache.org on 2008/05/14 20:07:03 UTC
svn commit: r656341 - in /hadoop/hbase/trunk: ./
src/java/org/apache/hadoop/hbase/client/
Author: jimk
Date: Wed May 14 11:07:03 2008
New Revision: 656341
URL: http://svn.apache.org/viewvc?rev=656341&view=rev
Log:
HBASE-538 Improve exceptions that come out on client-side
Added:
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/ScannerCallable.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/ServerCallable.java
Modified:
hadoop/hbase/trunk/CHANGES.txt
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnection.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnectionManager.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HTable.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/RegionOfflineException.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/RetriesExhaustedException.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/Scanner.java
Modified: hadoop/hbase/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/CHANGES.txt?rev=656341&r1=656340&r2=656341&view=diff
==============================================================================
--- hadoop/hbase/trunk/CHANGES.txt (original)
+++ hadoop/hbase/trunk/CHANGES.txt Wed May 14 11:07:03 2008
@@ -53,6 +53,7 @@
HBASE-611 regionserver should do basic health check before reporting
alls-well to the master
HBASE-614 Retiring regions is not used; exploit or remove
+ HBASE-538 Improve exceptions that come out on client-side
Release 0.1.1 - 04/11/2008
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnection.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnection.java?rev=656341&r1=656340&r2=656341&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnection.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnection.java Wed May 14 11:07:03 2008
@@ -20,7 +20,6 @@
package org.apache.hadoop.hbase.client;
import java.io.IOException;
-import java.util.SortedMap;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.hbase.ipc.HMasterInterface;
@@ -69,6 +68,7 @@
* @param row row key you're trying to find the region of
* @return HRegionLocation that describes where to find the reigon in
* question
+ * @throws IOException
*/
public HRegionLocation locateRegion(Text tableName, Text row)
throws IOException;
@@ -80,6 +80,7 @@
* @param row row key you're trying to find the region of
* @return HRegionLocation that describes where to find the reigon in
* question
+ * @throws IOException
*/
public HRegionLocation relocateRegion(Text tableName, Text row)
throws IOException;
@@ -92,4 +93,29 @@
*/
public HRegionInterface getHRegionConnection(HServerAddress regionServer)
throws IOException;
-}
+
+ /**
+ * Find region location hosting passed row
+ * @param tableName
+ * @param row Row to find.
+ * @param reload If true do not use cache, otherwise bypass.
+ * @return Location of row.
+ * @throws IOException
+ */
+ HRegionLocation getRegionLocation(Text tableName, Text row, boolean reload)
+ throws IOException;
+
+ /**
+ * Pass in a ServerCallable with your particular bit of logic defined and
+ * this method will manage the process of doing retries with timed waits
+ * and refinds of missing regions.
+ *
+ * @param <T> the type of the return value
+ * @param callable
+ * @return an object of type T
+ * @throws IOException
+ * @throws RuntimeException
+ */
+ public <T> T getRegionServerWithRetries(ServerCallable<T> callable)
+ throws IOException, RuntimeException;
+}
\ No newline at end of file
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnectionManager.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnectionManager.java?rev=656341&r1=656340&r2=656341&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnectionManager.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HConnectionManager.java Wed May 14 11:07:03 2008
@@ -20,9 +20,12 @@
package org.apache.hadoop.hbase.client;
import java.io.IOException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -240,62 +243,46 @@
}
/** {@inheritDoc} */
+ public HRegionLocation getRegionLocation(Text tableName, Text row,
+ boolean reload) throws IOException {
+ return reload ?
+ relocateRegion(tableName, row) :
+ locateRegion(tableName, row);
+ }
+
+ /** {@inheritDoc} */
public HTableDescriptor[] listTables() throws IOException {
HashSet<HTableDescriptor> uniqueTables = new HashSet<HTableDescriptor>();
- long scannerId = -1L;
- HRegionInterface server = null;
-
Text startRow = EMPTY_START_ROW;
- HRegionLocation metaLocation = null;
// scan over the each meta region
do {
- for (int triesSoFar = 0; triesSoFar < numRetries; triesSoFar++) {
- try{
- // turn the start row into a location
- metaLocation = locateRegion(META_TABLE_NAME, startRow);
-
- // connect to the server hosting the .META. region
- server = getHRegionConnection(metaLocation.getServerAddress());
-
- // open a scanner over the meta region
- scannerId = server.openScanner(
- metaLocation.getRegionInfo().getRegionName(),
- new Text[]{COL_REGIONINFO}, startRow, LATEST_TIMESTAMP, null);
-
- // iterate through the scanner, accumulating unique table names
- while (true) {
- RowResult values = server.next(scannerId);
- if (values == null || values.size() == 0) {
- break;
- }
-
- HRegionInfo info =
- Writables.getHRegionInfo(values.get(COL_REGIONINFO));
-
- // Only examine the rows where the startKey is zero length
- if (info.getStartKey().getLength() == 0) {
- uniqueTables.add(info.getTableDesc());
- }
+ ScannerCallable callable = new ScannerCallable(this, META_TABLE_NAME,
+ COL_REGIONINFO_ARRAY, startRow, LATEST_TIMESTAMP, null);
+ try {
+ // open scanner
+ getRegionServerWithRetries(callable);
+ // iterate through the scanner, accumulating unique table names
+ while (true) {
+ RowResult values = getRegionServerWithRetries(callable);
+ if (values == null || values.size() == 0) {
+ break;
}
-
- server.close(scannerId);
- scannerId = -1L;
-
- // advance the startRow to the end key of the current region
- startRow = metaLocation.getRegionInfo().getEndKey();
- // break out of retry loop
- break;
- } catch (IOException e) {
- // Retry once.
- metaLocation = relocateRegion(META_TABLE_NAME, startRow);
- continue;
- }
- finally {
- if (scannerId != -1L && server != null) {
- server.close(scannerId);
+
+ HRegionInfo info =
+ Writables.getHRegionInfo(values.get(COL_REGIONINFO));
+
+ // Only examine the rows where the startKey is zero length
+ if (info.getStartKey().getLength() == 0) {
+ uniqueTables.add(info.getTableDesc());
}
}
+ // advance the startRow to the end key of the current region
+ startRow = callable.getHRegionInfo().getEndKey();
+ } finally {
+ // close scanner
+ callable.setClose();
+ getRegionServerWithRetries(callable);
}
} while (startRow.compareTo(LAST_ROW) != 0);
@@ -723,5 +710,38 @@
return new HRegionLocation(
HRegionInfo.rootRegionInfo, rootRegionAddress);
}
+
+ /** {@inheritDoc} */
+ public <T> T getRegionServerWithRetries(ServerCallable<T> callable)
+ throws IOException, RuntimeException {
+ List<Throwable> exceptions = new ArrayList<Throwable>();
+ for(int tries = 0; tries < numRetries; tries++) {
+ try {
+ callable.instantiateServer(tries != 0);
+ return callable.call();
+ } catch (Throwable t) {
+ if (t instanceof UndeclaredThrowableException) {
+ t = t.getCause();
+ }
+ if (t instanceof RemoteException) {
+ t = RemoteExceptionHandler.decodeRemoteException((RemoteException) t);
+ }
+ exceptions.add(t);
+ if (tries == numRetries - 1) {
+ throw new RetriesExhaustedException(callable.getServerName(),
+ callable.getRegionName(), callable.getRow(), tries, exceptions);
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("reloading table servers because: " + t.getMessage());
+ }
+ }
+ try {
+ Thread.sleep(pause);
+ } catch (InterruptedException e) {
+ // continue
+ }
+ }
+ return null;
+ }
}
}
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HTable.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HTable.java?rev=656341&r1=656340&r2=656341&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HTable.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/HTable.java Wed May 14 11:07:03 2008
@@ -25,8 +25,6 @@
import java.util.List;
import java.util.Map;
import java.util.Random;
-import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -35,7 +33,6 @@
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.HTableDescriptor;
-import org.apache.hadoop.hbase.RemoteExceptionHandler;
import org.apache.hadoop.hbase.filter.RowFilterInterface;
import org.apache.hadoop.hbase.filter.StopRowFilter;
import org.apache.hadoop.hbase.filter.WhileMatchRowFilter;
@@ -45,20 +42,18 @@
import org.apache.hadoop.hbase.ipc.HRegionInterface;
import org.apache.hadoop.hbase.util.Writables;
import org.apache.hadoop.io.Text;
-import org.apache.hadoop.ipc.RemoteException;
/**
* Used to communicate with a single HBase table
*/
public class HTable implements HConstants {
- protected final Log LOG = LogFactory.getLog(this.getClass().getName());
+ protected final Log LOG = LogFactory.getLog(this.getClass());
protected final HConnection connection;
protected final Text tableName;
protected final long pause;
protected final int numRetries;
protected Random rand;
- protected AtomicReference<BatchUpdate> batch;
protected volatile boolean tableDoesNotExist;
@@ -77,7 +72,6 @@
this.pause = conf.getLong("hbase.client.pause", 10 * 1000);
this.numRetries = conf.getInt("hbase.client.retries.number", 5);
this.rand = new Random();
- this.batch = new AtomicReference<BatchUpdate>();
this.connection.locateRegion(tableName, EMPTY_START_ROW);
}
@@ -88,19 +82,7 @@
* @throws IOException
*/
public HRegionLocation getRegionLocation(Text row) throws IOException {
- return this.connection.locateRegion(this.tableName, row);
- }
-
- /**
- * Find region location hosting passed row
- * @param row Row to find.
- * @param reload If true do not use cache, otherwise bypass.
- * @return Location of row.
- */
- HRegionLocation getRegionLocation(Text row, boolean reload) throws IOException {
- return reload?
- this.connection.relocateRegion(this.tableName, row):
- this.connection.locateRegion(tableName, row);
+ return connection.getRegionLocation(tableName, row, false);
}
@@ -109,36 +91,6 @@
return connection;
}
- /**
- * Verifies that no update is in progress
- */
- public synchronized void checkUpdateInProgress() {
- updateInProgress(false);
- }
-
- /*
- * Checks to see if an update is in progress
- *
- * @param updateMustBeInProgress
- * If true, an update must be in progress. An IllegalStateException will be
- * thrown if not.
- *
- * If false, an update must not be in progress. An IllegalStateException
- * will be thrown if an update is in progress.
- */
- private void updateInProgress(boolean updateMustBeInProgress) {
- if (updateMustBeInProgress) {
- if (batch.get() == null) {
- throw new IllegalStateException("no update in progress");
- }
- } else {
- if (batch.get() != null) {
- throw new IllegalStateException("update in progress");
- }
- }
- }
-
-
/** @return the table name */
public Text getTableName() {
return this.tableName;
@@ -241,11 +193,14 @@
* @throws IOException
*/
public Cell get(final Text row, final Text column) throws IOException {
- return getRegionServerWithRetries(new ServerCallable<Cell>(row){
- public Cell call() throws IOException {
- return server.get(location.getRegionInfo().getRegionName(), row, column);
- }
- });
+ return connection.getRegionServerWithRetries(
+ new ServerCallable<Cell>(connection, tableName, row) {
+ public Cell call() throws IOException {
+ return server.get(location.getRegionInfo().getRegionName(), row,
+ column);
+ }
+ }
+ );
}
/**
@@ -261,12 +216,14 @@
throws IOException {
Cell[] values = null;
- values = getRegionServerWithRetries(new ServerCallable<Cell[]>(row) {
- public Cell[] call() throws IOException {
- return server.get(location.getRegionInfo().getRegionName(), row,
- column, numVersions);
- }
- });
+ values = connection.getRegionServerWithRetries(
+ new ServerCallable<Cell[]>(connection, tableName, row) {
+ public Cell[] call() throws IOException {
+ return server.get(location.getRegionInfo().getRegionName(), row,
+ column, numVersions);
+ }
+ }
+ );
if (values != null) {
ArrayList<Cell> cellValues = new ArrayList<Cell>();
@@ -294,12 +251,14 @@
throws IOException {
Cell[] values = null;
- values = getRegionServerWithRetries(new ServerCallable<Cell[]>(row) {
- public Cell[] call() throws IOException {
- return server.get(location.getRegionInfo().getRegionName(), row,
- column, timestamp, numVersions);
- }
- });
+ values = connection.getRegionServerWithRetries(
+ new ServerCallable<Cell[]>(connection, tableName, row) {
+ public Cell[] call() throws IOException {
+ return server.get(location.getRegionInfo().getRegionName(), row,
+ column, timestamp, numVersions);
+ }
+ }
+ );
if (values != null) {
ArrayList<Cell> cellValues = new ArrayList<Cell>();
@@ -332,11 +291,14 @@
*/
public Map<Text, Cell> getRow(final Text row, final long ts)
throws IOException {
- return getRegionServerWithRetries(new ServerCallable<RowResult>(row) {
- public RowResult call() throws IOException {
- return server.getRow(location.getRegionInfo().getRegionName(), row, ts);
- }
- });
+ return connection.getRegionServerWithRetries(
+ new ServerCallable<RowResult>(connection, tableName, row) {
+ public RowResult call() throws IOException {
+ return server.getRow(location.getRegionInfo().getRegionName(), row,
+ ts);
+ }
+ }
+ );
}
/**
@@ -364,12 +326,14 @@
public Map<Text, Cell> getRow(final Text row, final Text[] columns,
final long ts)
throws IOException {
- return getRegionServerWithRetries(new ServerCallable<RowResult>(row) {
- public RowResult call() throws IOException {
- return server.getRow(location.getRegionInfo().getRegionName(), row,
- columns, ts);
- }
- });
+ return connection.getRegionServerWithRetries(
+ new ServerCallable<RowResult>(connection, tableName, row) {
+ public RowResult call() throws IOException {
+ return server.getRow(location.getRegionInfo().getRegionName(), row,
+ columns, ts);
+ }
+ }
+ );
}
/**
@@ -520,13 +484,15 @@
*/
public void deleteAll(final Text row, final Text column, final long ts)
throws IOException {
- getRegionServerWithRetries(new ServerCallable<Boolean>(row) {
- public Boolean call() throws IOException {
- server.deleteAll(location.getRegionInfo().getRegionName(), row,
- column, ts);
- return null;
- }
- });
+ connection.getRegionServerWithRetries(
+ new ServerCallable<Boolean>(connection, tableName, row) {
+ public Boolean call() throws IOException {
+ server.deleteAll(location.getRegionInfo().getRegionName(), row,
+ column, ts);
+ return null;
+ }
+ }
+ );
}
/**
@@ -537,12 +503,14 @@
* @throws IOException
*/
public void deleteAll(final Text row, final long ts) throws IOException {
- getRegionServerWithRetries(new ServerCallable<Boolean>(row){
- public Boolean call() throws IOException {
- server.deleteAll(location.getRegionInfo().getRegionName(), row, ts);
- return null;
- }
- });
+ connection.getRegionServerWithRetries(
+ new ServerCallable<Boolean>(connection, tableName, row) {
+ public Boolean call() throws IOException {
+ server.deleteAll(location.getRegionInfo().getRegionName(), row, ts);
+ return null;
+ }
+ }
+ );
}
/**
@@ -567,13 +535,15 @@
public void deleteFamily(final Text row, final Text family,
final long timestamp)
throws IOException {
- getRegionServerWithRetries(new ServerCallable<Boolean>(row){
- public Boolean call() throws IOException {
- server.deleteFamily(location.getRegionInfo().getRegionName(), row,
- family, timestamp);
- return null;
- }
- });
+ connection.getRegionServerWithRetries(
+ new ServerCallable<Boolean>(connection, tableName, row) {
+ public Boolean call() throws IOException {
+ server.deleteFamily(location.getRegionInfo().getRegionName(), row,
+ family, timestamp);
+ return null;
+ }
+ }
+ );
}
/**
@@ -594,8 +564,8 @@
*/
public synchronized void commit(final BatchUpdate batchUpdate)
throws IOException {
- getRegionServerWithRetries(
- new ServerCallable<Boolean>(batchUpdate.getRow()){
+ connection.getRegionServerWithRetries(
+ new ServerCallable<Boolean>(connection, tableName, batchUpdate.getRow()) {
public Boolean call() throws IOException {
server.batchUpdate(location.getRegionInfo().getRegionName(),
batchUpdate);
@@ -610,28 +580,25 @@
* If there are multiple regions in a table, this scanner will iterate
* through them all.
*/
- protected class ClientScanner implements Scanner {
- private Text[] columns;
+ private class ClientScanner implements Scanner {
+ protected Text[] columns;
private Text startRow;
- private long scanTime;
+ protected long scanTime;
@SuppressWarnings("hiding")
- private boolean closed;
- private HRegionLocation currentRegionLocation;
- private HRegionInterface server;
- private long scannerId;
- private RowFilterInterface filter;
+ private boolean closed = false;
+ private HRegionInfo currentRegion = null;
+ private ScannerCallable callable = null;
+ protected RowFilterInterface filter;
protected ClientScanner(Text[] columns, Text startRow, long timestamp,
RowFilterInterface filter)
throws IOException {
- LOG.debug("Creating scanner over " + tableName + " starting at key " + startRow);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Creating scanner over " + tableName + " starting at key '" +
+ startRow + "'");
+ }
- // defaults
- this.closed = false;
- this.server = null;
- this.scannerId = -1L;
-
// save off the simple parameters
this.columns = columns;
this.startRow = startRow;
@@ -653,74 +620,42 @@
*/
private boolean nextScanner() throws IOException {
// close the previous scanner if it's open
- if (this.scannerId != -1L) {
- this.server.close(this.scannerId);
- this.scannerId = -1L;
+ if (this.callable != null) {
+ this.callable.setClose();
+ connection.getRegionServerWithRetries(callable);
+ this.callable = null;
}
// if we're at the end of the table, then close and return false
// to stop iterating
- if (currentRegionLocation != null){
- LOG.debug("Advancing forward from region "
- + currentRegionLocation.getRegionInfo());
+ if (currentRegion != null){
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Advancing forward from region " + currentRegion);
+ }
- Text endKey = currentRegionLocation.getRegionInfo().getEndKey();
+ Text endKey = currentRegion.getEndKey();
if (endKey == null || endKey.equals(EMPTY_TEXT)) {
close();
return false;
}
}
- HRegionLocation oldLocation = this.currentRegionLocation;
-
- Text localStartKey = oldLocation == null ?
- startRow : oldLocation.getRegionInfo().getEndKey();
-
- // advance to the region that starts with the current region's end key
- currentRegionLocation = getRegionLocation(localStartKey);
+ HRegionInfo oldRegion = this.currentRegion;
+ Text localStartKey = oldRegion == null ? startRow : oldRegion.getEndKey();
- LOG.debug("Advancing internal scanner to startKey " + localStartKey
- + ", new region: " + currentRegionLocation);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Advancing internal scanner to startKey " + localStartKey);
+ }
try {
- for (int tries = 0; tries < numRetries; tries++) {
- // connect to the server
- server = connection.getHRegionConnection(
- this.currentRegionLocation.getServerAddress());
-
- try {
- // open a scanner on the region server starting at the
- // beginning of the region
- scannerId = server.openScanner(
- this.currentRegionLocation.getRegionInfo().getRegionName(),
- this.columns, localStartKey, scanTime, filter);
-
- break;
- } catch (IOException e) {
- if (e instanceof RemoteException) {
- e = RemoteExceptionHandler.decodeRemoteException(
- (RemoteException) e);
- }
- if (tries == numRetries - 1) {
- // No more tries
- throw e;
- }
- try {
- Thread.sleep(pause);
- } catch (InterruptedException ie) {
- // continue
- }
- if (LOG.isDebugEnabled()) {
- LOG.debug("reloading table servers because: " + e.getMessage());
- }
- currentRegionLocation = getRegionLocation(localStartKey, true);
- }
- }
+ callable = new ScannerCallable(connection, tableName, columns,
+ localStartKey, scanTime, filter);
+ // open a scanner on the region server starting at the
+ // beginning of the region
+ connection.getRegionServerWithRetries(callable);
+ currentRegion = callable.getHRegionInfo();
} catch (IOException e) {
close();
- if (e instanceof RemoteException) {
- e = RemoteExceptionHandler.decodeRemoteException((RemoteException) e);
- }
throw e;
}
return true;
@@ -734,7 +669,7 @@
RowResult values = null;
do {
- values = server.next(scannerId);
+ values = connection.getRegionServerWithRetries(callable);
} while (values != null && values.size() == 0 && nextScanner());
if (values != null && values.size() != 0) {
@@ -748,18 +683,18 @@
* {@inheritDoc}
*/
public void close() {
- if (scannerId != -1L) {
+ if (callable != null) {
+ callable.setClose();
try {
- server.close(scannerId);
+ connection.getRegionServerWithRetries(callable);
} catch (IOException e) {
// We used to catch this error, interpret, and rethrow. However, we
// have since decided that it's not nice for a scanner's close to
// throw exceptions. Chances are it was just an UnknownScanner
// exception due to lease time out.
}
- scannerId = -1L;
+ callable = null;
}
- server = null;
closed = true;
}
@@ -808,58 +743,4 @@
};
}
}
-
- /**
- * Inherits from Callable, used to define the particular actions you would
- * like to take with retry logic.
- */
- protected abstract class ServerCallable<T> implements Callable<T> {
- HRegionLocation location;
- HRegionInterface server;
- Text row;
-
- protected ServerCallable(Text row) {
- this.row = row;
- }
-
- void instantiateServer(boolean reload) throws IOException {
- this.location = getRegionLocation(row, reload);
- this.server = connection.getHRegionConnection(location.getServerAddress());
- }
- }
-
- /**
- * Pass in a ServerCallable with your particular bit of logic defined and
- * this method will manage the process of doing retries with timed waits
- * and refinds of missing regions.
- */
- protected <T> T getRegionServerWithRetries(ServerCallable<T> callable)
- throws IOException, RuntimeException {
- List<Exception> exceptions = new ArrayList<Exception>();
- for(int tries = 0; tries < numRetries; tries++) {
- try {
- callable.instantiateServer(tries != 0);
- return callable.call();
- } catch (IOException e) {
- if (e instanceof RemoteException) {
- e = RemoteExceptionHandler.decodeRemoteException((RemoteException) e);
- }
- if (tries == numRetries - 1) {
- throw new RetriesExhaustedException(callable.row, tries, exceptions);
- }
- exceptions.add(e);
- if (LOG.isDebugEnabled()) {
- LOG.debug("reloading table servers because: " + e.getMessage());
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- try {
- Thread.sleep(pause);
- } catch (InterruptedException e) {
- // continue
- }
- }
- return null;
- }
}
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/RegionOfflineException.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/RegionOfflineException.java?rev=656341&r1=656340&r2=656341&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/RegionOfflineException.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/RegionOfflineException.java Wed May 14 11:07:03 2008
@@ -23,7 +23,8 @@
/** Thrown when a table can not be located */
public class RegionOfflineException extends IOException {
- /** default constructor */
+ private static final long serialVersionUID = 466008402L;
+/** default constructor */
public RegionOfflineException() {
super();
}
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/RetriesExhaustedException.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/RetriesExhaustedException.java?rev=656341&r1=656340&r2=656341&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/RetriesExhaustedException.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/RetriesExhaustedException.java Wed May 14 11:07:03 2008
@@ -24,25 +24,36 @@
* commit changes) fails after a bunch of retries.
*/
public class RetriesExhaustedException extends IOException {
+ private static final long serialVersionUID = 1876775844L;
/**
* 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 numTries The number of tries we made
* @param exceptions List of exceptions that failed before giving up
*/
- public RetriesExhaustedException(Text row, int numTries,
- List<Exception> exceptions) {
- super(getMessage(row, numTries, exceptions));
+ public RetriesExhaustedException(String serverName, Text regionName, Text row,
+ int numTries, List<Throwable> exceptions) {
+ super(getMessage(serverName, regionName, row, numTries, exceptions));
}
- private static String getMessage(Text row, int numTries,
- List<Exception> exceptions) {
- String buffer = "Trying to contact region server for row '" +
- row + "', but failed after " + (numTries + 1) + " attempts.\nExceptions:\n";
+ private static String getMessage(String serverName, Text regionName, Text row,
+ int numTries, List<Throwable> exceptions) {
+ StringBuilder buffer = new StringBuilder("Trying to contact region server ");
+ buffer.append(serverName);
+ buffer.append(" for region ");
+ buffer.append(regionName);
+ buffer.append(", row '");
+ buffer.append(row);
+ buffer.append("', but failed after ");
+ buffer.append(numTries + 1);
+ buffer.append(" attempts.\nExceptions:\n");
- for (Exception e : exceptions) {
- buffer += e.toString() + "\n";
+ for (Throwable t : exceptions) {
+ buffer.append(t.toString());
+ buffer.append("\n");
}
- return buffer;
+ return buffer.toString();
}
}
\ No newline at end of file
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/Scanner.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/Scanner.java?rev=656341&r1=656340&r2=656341&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/Scanner.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/Scanner.java Wed May 14 11:07:03 2008
@@ -21,8 +21,6 @@
import java.io.Closeable;
import java.io.IOException;
-import java.util.SortedMap;
-import java.util.Iterator;
import org.apache.hadoop.hbase.io.RowResult;
/**
Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/ScannerCallable.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/ScannerCallable.java?rev=656341&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/ScannerCallable.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/ScannerCallable.java Wed May 14 11:07:03 2008
@@ -0,0 +1,92 @@
+/**
+ * Copyright 2008 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.client;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.filter.RowFilterInterface;
+import org.apache.hadoop.hbase.io.RowResult;
+import org.apache.hadoop.io.Text;
+/**
+ * Retryable scanner
+ */
+public class ScannerCallable extends ServerCallable<RowResult> {
+ private long scannerId = -1L;
+ private boolean instantiated = false;
+ private boolean closed = false;
+ private final Text[] columns;
+ private final long timestamp;
+ private final RowFilterInterface filter;
+
+ ScannerCallable (HConnection connection, Text tableName, Text[] columns,
+ Text startRow, long timestamp, RowFilterInterface filter) {
+ super(connection, tableName, startRow);
+ this.columns = columns;
+ this.timestamp = timestamp;
+ this.filter = filter;
+ }
+
+ /**
+ * @param reload
+ * @throws IOException
+ */
+ @Override
+ public void instantiateServer(boolean reload) throws IOException {
+ if (!instantiated || reload) {
+ super.instantiateServer(reload);
+ instantiated = true;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RowResult call() throws IOException {
+ if (scannerId != -1L && closed) {
+ server.close(scannerId);
+ scannerId = -1L;
+ } else if (scannerId == -1L && !closed) {
+ // open the scanner
+ scannerId = server.openScanner(
+ this.location.getRegionInfo().getRegionName(), columns, row,
+ timestamp, filter);
+ } else {
+ return server.next(scannerId);
+ }
+ return null;
+ }
+
+ /**
+ * Call this when the next invocation of call should close the scanner
+ */
+ public void setClose() {
+ closed = true;
+ }
+
+ /**
+ * @return the HRegionInfo for the current region
+ */
+ public HRegionInfo getHRegionInfo() {
+ if (!instantiated) {
+ return null;
+ }
+ return location.getRegionInfo();
+ }
+}
Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/ServerCallable.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/ServerCallable.java?rev=656341&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/ServerCallable.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/client/ServerCallable.java Wed May 14 11:07:03 2008
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2008 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.client;
+
+import java.io.IOException;
+import java.util.concurrent.Callable;
+
+import org.apache.hadoop.hbase.HRegionLocation;
+import org.apache.hadoop.hbase.ipc.HRegionInterface;
+import org.apache.hadoop.io.Text;
+
+/**
+ * Implements Callable, used to define the particular actions you would
+ * like to take with retry logic.
+ * @param <T> the class that the ServerCallable handles
+ *
+ */
+public abstract class ServerCallable<T> implements Callable<T> {
+ protected final HConnection connection;
+ protected final Text tableName;
+ protected final Text row;
+ protected HRegionLocation location;
+ protected HRegionInterface server;
+
+ /**
+ * @param connection
+ * @param tableName
+ * @param row
+ */
+ public ServerCallable(HConnection connection, Text tableName, Text row) {
+ this.connection = connection;
+ this.tableName = tableName;
+ this.row = row;
+ }
+
+ /**
+ *
+ * @param reload set this to true if connection should re-find the region
+ * @throws IOException
+ */
+ public void instantiateServer(boolean reload) throws IOException {
+ this.location = connection.getRegionLocation(tableName, row, reload);
+ this.server = connection.getHRegionConnection(location.getServerAddress());
+ }
+
+ /** @return the server name */
+ public String getServerName() {
+ return location.getServerAddress().toString();
+ }
+
+ /** @return the region name */
+ public Text getRegionName() {
+ return location.getRegionInfo().getRegionName();
+ }
+
+ /** @return the row */
+ public Text getRow() {
+ return row;
+ }
+}