HBASE-538 Improve exceptions that come out on client-side
git-svn-id: https://svn.apache.org/repos/asf/hadoop/hbase/trunk@656341 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8d5e1e7025
commit
595b75b105
|
@ -53,6 +53,7 @@ Hbase Change Log
|
||||||
HBASE-611 regionserver should do basic health check before reporting
|
HBASE-611 regionserver should do basic health check before reporting
|
||||||
alls-well to the master
|
alls-well to the master
|
||||||
HBASE-614 Retiring regions is not used; exploit or remove
|
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
|
Release 0.1.1 - 04/11/2008
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.apache.hadoop.hbase.client;
|
package org.apache.hadoop.hbase.client;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.SortedMap;
|
|
||||||
|
|
||||||
import org.apache.hadoop.io.Text;
|
import org.apache.hadoop.io.Text;
|
||||||
import org.apache.hadoop.hbase.ipc.HMasterInterface;
|
import org.apache.hadoop.hbase.ipc.HMasterInterface;
|
||||||
|
@ -69,6 +68,7 @@ public interface HConnection {
|
||||||
* @param row row key you're trying to find the region of
|
* @param row row key you're trying to find the region of
|
||||||
* @return HRegionLocation that describes where to find the reigon in
|
* @return HRegionLocation that describes where to find the reigon in
|
||||||
* question
|
* question
|
||||||
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public HRegionLocation locateRegion(Text tableName, Text row)
|
public HRegionLocation locateRegion(Text tableName, Text row)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
@ -80,6 +80,7 @@ public interface HConnection {
|
||||||
* @param row row key you're trying to find the region of
|
* @param row row key you're trying to find the region of
|
||||||
* @return HRegionLocation that describes where to find the reigon in
|
* @return HRegionLocation that describes where to find the reigon in
|
||||||
* question
|
* question
|
||||||
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public HRegionLocation relocateRegion(Text tableName, Text row)
|
public HRegionLocation relocateRegion(Text tableName, Text row)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
@ -92,4 +93,29 @@ public interface HConnection {
|
||||||
*/
|
*/
|
||||||
public HRegionInterface getHRegionConnection(HServerAddress regionServer)
|
public HRegionInterface getHRegionConnection(HServerAddress regionServer)
|
||||||
throws IOException;
|
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;
|
||||||
|
}
|
|
@ -20,9 +20,12 @@
|
||||||
package org.apache.hadoop.hbase.client;
|
package org.apache.hadoop.hbase.client;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.UndeclaredThrowableException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@ -239,63 +242,47 @@ public class HConnectionManager implements HConstants {
|
||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public HRegionLocation getRegionLocation(Text tableName, Text row,
|
||||||
|
boolean reload) throws IOException {
|
||||||
|
return reload ?
|
||||||
|
relocateRegion(tableName, row) :
|
||||||
|
locateRegion(tableName, row);
|
||||||
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public HTableDescriptor[] listTables() throws IOException {
|
public HTableDescriptor[] listTables() throws IOException {
|
||||||
HashSet<HTableDescriptor> uniqueTables = new HashSet<HTableDescriptor>();
|
HashSet<HTableDescriptor> uniqueTables = new HashSet<HTableDescriptor>();
|
||||||
long scannerId = -1L;
|
|
||||||
HRegionInterface server = null;
|
|
||||||
|
|
||||||
Text startRow = EMPTY_START_ROW;
|
Text startRow = EMPTY_START_ROW;
|
||||||
HRegionLocation metaLocation = null;
|
|
||||||
|
|
||||||
// scan over the each meta region
|
// scan over the each meta region
|
||||||
do {
|
do {
|
||||||
for (int triesSoFar = 0; triesSoFar < numRetries; triesSoFar++) {
|
ScannerCallable callable = new ScannerCallable(this, META_TABLE_NAME,
|
||||||
try{
|
COL_REGIONINFO_ARRAY, startRow, LATEST_TIMESTAMP, null);
|
||||||
// turn the start row into a location
|
try {
|
||||||
metaLocation = locateRegion(META_TABLE_NAME, startRow);
|
// open scanner
|
||||||
|
getRegionServerWithRetries(callable);
|
||||||
// connect to the server hosting the .META. region
|
// iterate through the scanner, accumulating unique table names
|
||||||
server = getHRegionConnection(metaLocation.getServerAddress());
|
while (true) {
|
||||||
|
RowResult values = getRegionServerWithRetries(callable);
|
||||||
// open a scanner over the meta region
|
if (values == null || values.size() == 0) {
|
||||||
scannerId = server.openScanner(
|
break;
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
server.close(scannerId);
|
HRegionInfo info =
|
||||||
scannerId = -1L;
|
Writables.getHRegionInfo(values.get(COL_REGIONINFO));
|
||||||
|
|
||||||
// advance the startRow to the end key of the current region
|
// Only examine the rows where the startKey is zero length
|
||||||
startRow = metaLocation.getRegionInfo().getEndKey();
|
if (info.getStartKey().getLength() == 0) {
|
||||||
// break out of retry loop
|
uniqueTables.add(info.getTableDesc());
|
||||||
break;
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Retry once.
|
|
||||||
metaLocation = relocateRegion(META_TABLE_NAME, startRow);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (scannerId != -1L && server != null) {
|
|
||||||
server.close(scannerId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 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);
|
} while (startRow.compareTo(LAST_ROW) != 0);
|
||||||
|
|
||||||
|
@ -723,5 +710,38 @@ public class HConnectionManager implements HConstants {
|
||||||
return new HRegionLocation(
|
return new HRegionLocation(
|
||||||
HRegionInfo.rootRegionInfo, rootRegionAddress);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,6 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
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.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -35,7 +33,6 @@ import org.apache.hadoop.hbase.HConstants;
|
||||||
import org.apache.hadoop.hbase.HRegionInfo;
|
import org.apache.hadoop.hbase.HRegionInfo;
|
||||||
import org.apache.hadoop.hbase.HRegionLocation;
|
import org.apache.hadoop.hbase.HRegionLocation;
|
||||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
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.RowFilterInterface;
|
||||||
import org.apache.hadoop.hbase.filter.StopRowFilter;
|
import org.apache.hadoop.hbase.filter.StopRowFilter;
|
||||||
import org.apache.hadoop.hbase.filter.WhileMatchRowFilter;
|
import org.apache.hadoop.hbase.filter.WhileMatchRowFilter;
|
||||||
|
@ -45,20 +42,18 @@ import org.apache.hadoop.hbase.io.RowResult;
|
||||||
import org.apache.hadoop.hbase.ipc.HRegionInterface;
|
import org.apache.hadoop.hbase.ipc.HRegionInterface;
|
||||||
import org.apache.hadoop.hbase.util.Writables;
|
import org.apache.hadoop.hbase.util.Writables;
|
||||||
import org.apache.hadoop.io.Text;
|
import org.apache.hadoop.io.Text;
|
||||||
import org.apache.hadoop.ipc.RemoteException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to communicate with a single HBase table
|
* Used to communicate with a single HBase table
|
||||||
*/
|
*/
|
||||||
public class HTable implements HConstants {
|
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 HConnection connection;
|
||||||
protected final Text tableName;
|
protected final Text tableName;
|
||||||
protected final long pause;
|
protected final long pause;
|
||||||
protected final int numRetries;
|
protected final int numRetries;
|
||||||
protected Random rand;
|
protected Random rand;
|
||||||
protected AtomicReference<BatchUpdate> batch;
|
|
||||||
|
|
||||||
protected volatile boolean tableDoesNotExist;
|
protected volatile boolean tableDoesNotExist;
|
||||||
|
|
||||||
|
@ -77,7 +72,6 @@ public class HTable implements HConstants {
|
||||||
this.pause = conf.getLong("hbase.client.pause", 10 * 1000);
|
this.pause = conf.getLong("hbase.client.pause", 10 * 1000);
|
||||||
this.numRetries = conf.getInt("hbase.client.retries.number", 5);
|
this.numRetries = conf.getInt("hbase.client.retries.number", 5);
|
||||||
this.rand = new Random();
|
this.rand = new Random();
|
||||||
this.batch = new AtomicReference<BatchUpdate>();
|
|
||||||
this.connection.locateRegion(tableName, EMPTY_START_ROW);
|
this.connection.locateRegion(tableName, EMPTY_START_ROW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,19 +82,7 @@ public class HTable implements HConstants {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public HRegionLocation getRegionLocation(Text row) throws IOException {
|
public HRegionLocation getRegionLocation(Text row) throws IOException {
|
||||||
return this.connection.locateRegion(this.tableName, row);
|
return connection.getRegionLocation(tableName, row, false);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,36 +91,6 @@ public class HTable implements HConstants {
|
||||||
return connection;
|
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 */
|
/** @return the table name */
|
||||||
public Text getTableName() {
|
public Text getTableName() {
|
||||||
return this.tableName;
|
return this.tableName;
|
||||||
|
@ -241,11 +193,14 @@ public class HTable implements HConstants {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public Cell get(final Text row, final Text column) throws IOException {
|
public Cell get(final Text row, final Text column) throws IOException {
|
||||||
return getRegionServerWithRetries(new ServerCallable<Cell>(row){
|
return connection.getRegionServerWithRetries(
|
||||||
public Cell call() throws IOException {
|
new ServerCallable<Cell>(connection, tableName, row) {
|
||||||
return server.get(location.getRegionInfo().getRegionName(), row, column);
|
public Cell call() throws IOException {
|
||||||
}
|
return server.get(location.getRegionInfo().getRegionName(), row,
|
||||||
});
|
column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -261,12 +216,14 @@ public class HTable implements HConstants {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Cell[] values = null;
|
Cell[] values = null;
|
||||||
|
|
||||||
values = getRegionServerWithRetries(new ServerCallable<Cell[]>(row) {
|
values = connection.getRegionServerWithRetries(
|
||||||
public Cell[] call() throws IOException {
|
new ServerCallable<Cell[]>(connection, tableName, row) {
|
||||||
return server.get(location.getRegionInfo().getRegionName(), row,
|
public Cell[] call() throws IOException {
|
||||||
column, numVersions);
|
return server.get(location.getRegionInfo().getRegionName(), row,
|
||||||
}
|
column, numVersions);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (values != null) {
|
if (values != null) {
|
||||||
ArrayList<Cell> cellValues = new ArrayList<Cell>();
|
ArrayList<Cell> cellValues = new ArrayList<Cell>();
|
||||||
|
@ -294,12 +251,14 @@ public class HTable implements HConstants {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Cell[] values = null;
|
Cell[] values = null;
|
||||||
|
|
||||||
values = getRegionServerWithRetries(new ServerCallable<Cell[]>(row) {
|
values = connection.getRegionServerWithRetries(
|
||||||
public Cell[] call() throws IOException {
|
new ServerCallable<Cell[]>(connection, tableName, row) {
|
||||||
return server.get(location.getRegionInfo().getRegionName(), row,
|
public Cell[] call() throws IOException {
|
||||||
column, timestamp, numVersions);
|
return server.get(location.getRegionInfo().getRegionName(), row,
|
||||||
}
|
column, timestamp, numVersions);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (values != null) {
|
if (values != null) {
|
||||||
ArrayList<Cell> cellValues = new ArrayList<Cell>();
|
ArrayList<Cell> cellValues = new ArrayList<Cell>();
|
||||||
|
@ -332,11 +291,14 @@ public class HTable implements HConstants {
|
||||||
*/
|
*/
|
||||||
public Map<Text, Cell> getRow(final Text row, final long ts)
|
public Map<Text, Cell> getRow(final Text row, final long ts)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return getRegionServerWithRetries(new ServerCallable<RowResult>(row) {
|
return connection.getRegionServerWithRetries(
|
||||||
public RowResult call() throws IOException {
|
new ServerCallable<RowResult>(connection, tableName, row) {
|
||||||
return server.getRow(location.getRegionInfo().getRegionName(), row, ts);
|
public RowResult call() throws IOException {
|
||||||
}
|
return server.getRow(location.getRegionInfo().getRegionName(), row,
|
||||||
});
|
ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -364,12 +326,14 @@ public class HTable implements HConstants {
|
||||||
public Map<Text, Cell> getRow(final Text row, final Text[] columns,
|
public Map<Text, Cell> getRow(final Text row, final Text[] columns,
|
||||||
final long ts)
|
final long ts)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return getRegionServerWithRetries(new ServerCallable<RowResult>(row) {
|
return connection.getRegionServerWithRetries(
|
||||||
public RowResult call() throws IOException {
|
new ServerCallable<RowResult>(connection, tableName, row) {
|
||||||
return server.getRow(location.getRegionInfo().getRegionName(), row,
|
public RowResult call() throws IOException {
|
||||||
columns, ts);
|
return server.getRow(location.getRegionInfo().getRegionName(), row,
|
||||||
}
|
columns, ts);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -520,13 +484,15 @@ public class HTable implements HConstants {
|
||||||
*/
|
*/
|
||||||
public void deleteAll(final Text row, final Text column, final long ts)
|
public void deleteAll(final Text row, final Text column, final long ts)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
getRegionServerWithRetries(new ServerCallable<Boolean>(row) {
|
connection.getRegionServerWithRetries(
|
||||||
public Boolean call() throws IOException {
|
new ServerCallable<Boolean>(connection, tableName, row) {
|
||||||
server.deleteAll(location.getRegionInfo().getRegionName(), row,
|
public Boolean call() throws IOException {
|
||||||
column, ts);
|
server.deleteAll(location.getRegionInfo().getRegionName(), row,
|
||||||
return null;
|
column, ts);
|
||||||
}
|
return null;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -537,12 +503,14 @@ public class HTable implements HConstants {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void deleteAll(final Text row, final long ts) throws IOException {
|
public void deleteAll(final Text row, final long ts) throws IOException {
|
||||||
getRegionServerWithRetries(new ServerCallable<Boolean>(row){
|
connection.getRegionServerWithRetries(
|
||||||
public Boolean call() throws IOException {
|
new ServerCallable<Boolean>(connection, tableName, row) {
|
||||||
server.deleteAll(location.getRegionInfo().getRegionName(), row, ts);
|
public Boolean call() throws IOException {
|
||||||
return null;
|
server.deleteAll(location.getRegionInfo().getRegionName(), row, ts);
|
||||||
}
|
return null;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -567,13 +535,15 @@ public class HTable implements HConstants {
|
||||||
public void deleteFamily(final Text row, final Text family,
|
public void deleteFamily(final Text row, final Text family,
|
||||||
final long timestamp)
|
final long timestamp)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
getRegionServerWithRetries(new ServerCallable<Boolean>(row){
|
connection.getRegionServerWithRetries(
|
||||||
public Boolean call() throws IOException {
|
new ServerCallable<Boolean>(connection, tableName, row) {
|
||||||
server.deleteFamily(location.getRegionInfo().getRegionName(), row,
|
public Boolean call() throws IOException {
|
||||||
family, timestamp);
|
server.deleteFamily(location.getRegionInfo().getRegionName(), row,
|
||||||
return null;
|
family, timestamp);
|
||||||
}
|
return null;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -594,8 +564,8 @@ public class HTable implements HConstants {
|
||||||
*/
|
*/
|
||||||
public synchronized void commit(final BatchUpdate batchUpdate)
|
public synchronized void commit(final BatchUpdate batchUpdate)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
getRegionServerWithRetries(
|
connection.getRegionServerWithRetries(
|
||||||
new ServerCallable<Boolean>(batchUpdate.getRow()){
|
new ServerCallable<Boolean>(connection, tableName, batchUpdate.getRow()) {
|
||||||
public Boolean call() throws IOException {
|
public Boolean call() throws IOException {
|
||||||
server.batchUpdate(location.getRegionInfo().getRegionName(),
|
server.batchUpdate(location.getRegionInfo().getRegionName(),
|
||||||
batchUpdate);
|
batchUpdate);
|
||||||
|
@ -610,28 +580,25 @@ public class HTable implements HConstants {
|
||||||
* If there are multiple regions in a table, this scanner will iterate
|
* If there are multiple regions in a table, this scanner will iterate
|
||||||
* through them all.
|
* through them all.
|
||||||
*/
|
*/
|
||||||
protected class ClientScanner implements Scanner {
|
private class ClientScanner implements Scanner {
|
||||||
private Text[] columns;
|
protected Text[] columns;
|
||||||
private Text startRow;
|
private Text startRow;
|
||||||
private long scanTime;
|
protected long scanTime;
|
||||||
@SuppressWarnings("hiding")
|
@SuppressWarnings("hiding")
|
||||||
private boolean closed;
|
private boolean closed = false;
|
||||||
private HRegionLocation currentRegionLocation;
|
private HRegionInfo currentRegion = null;
|
||||||
private HRegionInterface server;
|
private ScannerCallable callable = null;
|
||||||
private long scannerId;
|
protected RowFilterInterface filter;
|
||||||
private RowFilterInterface filter;
|
|
||||||
|
|
||||||
protected ClientScanner(Text[] columns, Text startRow, long timestamp,
|
protected ClientScanner(Text[] columns, Text startRow, long timestamp,
|
||||||
RowFilterInterface filter)
|
RowFilterInterface filter)
|
||||||
throws IOException {
|
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
|
// save off the simple parameters
|
||||||
this.columns = columns;
|
this.columns = columns;
|
||||||
this.startRow = startRow;
|
this.startRow = startRow;
|
||||||
|
@ -653,74 +620,42 @@ public class HTable implements HConstants {
|
||||||
*/
|
*/
|
||||||
private boolean nextScanner() throws IOException {
|
private boolean nextScanner() throws IOException {
|
||||||
// close the previous scanner if it's open
|
// close the previous scanner if it's open
|
||||||
if (this.scannerId != -1L) {
|
if (this.callable != null) {
|
||||||
this.server.close(this.scannerId);
|
this.callable.setClose();
|
||||||
this.scannerId = -1L;
|
connection.getRegionServerWithRetries(callable);
|
||||||
|
this.callable = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're at the end of the table, then close and return false
|
// if we're at the end of the table, then close and return false
|
||||||
// to stop iterating
|
// to stop iterating
|
||||||
if (currentRegionLocation != null){
|
if (currentRegion != null){
|
||||||
LOG.debug("Advancing forward from region "
|
if (LOG.isDebugEnabled()) {
|
||||||
+ currentRegionLocation.getRegionInfo());
|
LOG.debug("Advancing forward from region " + currentRegion);
|
||||||
|
}
|
||||||
|
|
||||||
Text endKey = currentRegionLocation.getRegionInfo().getEndKey();
|
Text endKey = currentRegion.getEndKey();
|
||||||
if (endKey == null || endKey.equals(EMPTY_TEXT)) {
|
if (endKey == null || endKey.equals(EMPTY_TEXT)) {
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRegionLocation oldLocation = this.currentRegionLocation;
|
HRegionInfo oldRegion = this.currentRegion;
|
||||||
|
Text localStartKey = oldRegion == null ? startRow : oldRegion.getEndKey();
|
||||||
Text localStartKey = oldLocation == null ?
|
|
||||||
startRow : oldLocation.getRegionInfo().getEndKey();
|
|
||||||
|
|
||||||
// advance to the region that starts with the current region's end key
|
if (LOG.isDebugEnabled()) {
|
||||||
currentRegionLocation = getRegionLocation(localStartKey);
|
LOG.debug("Advancing internal scanner to startKey " + localStartKey);
|
||||||
|
}
|
||||||
LOG.debug("Advancing internal scanner to startKey " + localStartKey
|
|
||||||
+ ", new region: " + currentRegionLocation);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (int tries = 0; tries < numRetries; tries++) {
|
callable = new ScannerCallable(connection, tableName, columns,
|
||||||
// connect to the server
|
localStartKey, scanTime, filter);
|
||||||
server = connection.getHRegionConnection(
|
// open a scanner on the region server starting at the
|
||||||
this.currentRegionLocation.getServerAddress());
|
// beginning of the region
|
||||||
|
connection.getRegionServerWithRetries(callable);
|
||||||
try {
|
currentRegion = callable.getHRegionInfo();
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
close();
|
close();
|
||||||
if (e instanceof RemoteException) {
|
|
||||||
e = RemoteExceptionHandler.decodeRemoteException((RemoteException) e);
|
|
||||||
}
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -734,7 +669,7 @@ public class HTable implements HConstants {
|
||||||
|
|
||||||
RowResult values = null;
|
RowResult values = null;
|
||||||
do {
|
do {
|
||||||
values = server.next(scannerId);
|
values = connection.getRegionServerWithRetries(callable);
|
||||||
} while (values != null && values.size() == 0 && nextScanner());
|
} while (values != null && values.size() == 0 && nextScanner());
|
||||||
|
|
||||||
if (values != null && values.size() != 0) {
|
if (values != null && values.size() != 0) {
|
||||||
|
@ -748,18 +683,18 @@ public class HTable implements HConstants {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
if (scannerId != -1L) {
|
if (callable != null) {
|
||||||
|
callable.setClose();
|
||||||
try {
|
try {
|
||||||
server.close(scannerId);
|
connection.getRegionServerWithRetries(callable);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// We used to catch this error, interpret, and rethrow. However, we
|
// 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
|
// have since decided that it's not nice for a scanner's close to
|
||||||
// throw exceptions. Chances are it was just an UnknownScanner
|
// throw exceptions. Chances are it was just an UnknownScanner
|
||||||
// exception due to lease time out.
|
// exception due to lease time out.
|
||||||
}
|
}
|
||||||
scannerId = -1L;
|
callable = null;
|
||||||
}
|
}
|
||||||
server = null;
|
|
||||||
closed = true;
|
closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,58 +743,4 @@ public class HTable implements HConstants {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,8 @@ import java.io.IOException;
|
||||||
|
|
||||||
/** Thrown when a table can not be located */
|
/** Thrown when a table can not be located */
|
||||||
public class RegionOfflineException extends IOException {
|
public class RegionOfflineException extends IOException {
|
||||||
/** default constructor */
|
private static final long serialVersionUID = 466008402L;
|
||||||
|
/** default constructor */
|
||||||
public RegionOfflineException() {
|
public RegionOfflineException() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,25 +24,36 @@ import org.apache.hadoop.io.Text;
|
||||||
* commit changes) fails after a bunch of retries.
|
* commit changes) fails after a bunch of retries.
|
||||||
*/
|
*/
|
||||||
public class RetriesExhaustedException extends IOException {
|
public class RetriesExhaustedException extends IOException {
|
||||||
|
private static final long serialVersionUID = 1876775844L;
|
||||||
/**
|
/**
|
||||||
* Create a new RetriesExhaustedException from the list of prior failures.
|
* 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 row The row we were pursuing when we ran out of retries
|
||||||
* @param numTries The number of tries we made
|
* @param numTries The number of tries we made
|
||||||
* @param exceptions List of exceptions that failed before giving up
|
* @param exceptions List of exceptions that failed before giving up
|
||||||
*/
|
*/
|
||||||
public RetriesExhaustedException(Text row, int numTries,
|
public RetriesExhaustedException(String serverName, Text regionName, Text row,
|
||||||
List<Exception> exceptions) {
|
int numTries, List<Throwable> exceptions) {
|
||||||
super(getMessage(row, numTries, exceptions));
|
super(getMessage(serverName, regionName, row, numTries, exceptions));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getMessage(Text row, int numTries,
|
private static String getMessage(String serverName, Text regionName, Text row,
|
||||||
List<Exception> exceptions) {
|
int numTries, List<Throwable> exceptions) {
|
||||||
String buffer = "Trying to contact region server for row '" +
|
StringBuilder buffer = new StringBuilder("Trying to contact region server ");
|
||||||
row + "', but failed after " + (numTries + 1) + " attempts.\nExceptions:\n";
|
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) {
|
for (Throwable t : exceptions) {
|
||||||
buffer += e.toString() + "\n";
|
buffer.append(t.toString());
|
||||||
|
buffer.append("\n");
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,8 +21,6 @@ package org.apache.hadoop.hbase.client;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.SortedMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import org.apache.hadoop.hbase.io.RowResult;
|
import org.apache.hadoop.hbase.io.RowResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue