Author: stack
Date: Sat Aug 30 21:48:57 2008
New Revision: 690637
URL: http://svn.apache.org/viewvc?rev=690637&view=rev
Log:
HBASE-840 More options on the row query in REST interface
Modified:
hadoop/hbase/trunk/CHANGES.txt
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/HConstants.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/HStoreKey.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/HRegion.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/Memcache.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/GenericHandler.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java
hadoop/hbase/trunk/src/test/org/apache/hadoop/hbase/TestCompare.java
Modified: hadoop/hbase/trunk/CHANGES.txt
URL:
http://svn.apache.org/viewvc/hadoop/hbase/trunk/CHANGES.txt?rev=690637&r1=690636&r2=690637&view=diff
==============================================================================
--- hadoop/hbase/trunk/CHANGES.txt (original)
+++ hadoop/hbase/trunk/CHANGES.txt Sat Aug 30 21:48:57 2008
@@ -67,6 +67,8 @@
HBASE-784 Base hbase-0.3.0 on hadoop-0.18
HBASE-841 Consolidate multiple overloaded methods in HRegionInterface,
HRegionServer (Jean-Daniel Cryans via Jim Kellerman)
+ HBASE-840 More options on the row query in REST interface
+ (Sishen Freecity via Stack)
NEW FEATURES
HBASE-787 Postgresql to HBase table replication example (Tim Sell via
Stack)
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/HConstants.java
URL:
http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/HConstants.java?rev=690637&r1=690636&r2=690637&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/HConstants.java
(original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/HConstants.java Sat Aug
30 21:48:57 2008
@@ -132,7 +132,10 @@
static final byte [] ROOT_TABLE_NAME = Bytes.toBytes("-ROOT-");
/** The META table's name. */
- static final byte [] META_TABLE_NAME = Bytes.toBytes(".META.");
+ static final byte [] META_TABLE_NAME = Bytes.toBytes(".META.");
+
+ /** delimiter used between portions of a region name */
+ public static final int META_ROW_DELIMITER = ',';
// Defines for the column names used in both ROOT and META HBase 'meta' tables.
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/HStoreKey.java
URL:
http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/HStoreKey.java?rev=690637&r1=690636&r2=690637&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/HStoreKey.java
(original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/HStoreKey.java Sat Aug
30 21:48:57 2008
@@ -40,6 +40,12 @@
private byte [] column = HConstants.EMPTY_BYTE_ARRAY;
private long timestamp = Long.MAX_VALUE;
+ /*
+ * regionInfo is only used as a hack to compare HSKs.
+ * It is not serialized. See https://issues.apache.org/jira/browse/HBASE-832
+ */
+ private HRegionInfo regionInfo = null;
+
/** Default constructor used in conjunction with Writable interface */
public HStoreKey() {
super();
@@ -47,8 +53,8 @@
/**
* Create an HStoreKey specifying only the row
- * The column defaults to the empty string and the time stamp defaults to
- * Long.MAX_VALUE
+ * The column defaults to the empty string, the time stamp defaults to
+ * Long.MAX_VALUE and the table defaults to empty string
*
* @param row - row key
*/
@@ -58,8 +64,8 @@
/**
* Create an HStoreKey specifying only the row
- * The column defaults to the empty string and the time stamp defaults to
- * Long.MAX_VALUE
+ * The column defaults to the empty string, the time stamp defaults to
+ * Long.MAX_VALUE and the table defaults to empty string
*
* @param row - row key
*/
@@ -69,7 +75,7 @@
/**
* Create an HStoreKey specifying the row and timestamp
- * The column name defaults to the empty string
+ * The column and table names default to the empty string
*
* @param row row key
* @param timestamp timestamp value
@@ -80,29 +86,31 @@
/**
* Create an HStoreKey specifying the row and timestamp
- * The column name defaults to the empty string
+ * The column and table names default to the empty string
*
* @param row row key
* @param timestamp timestamp value
*/
public HStoreKey(final String row, long timestamp) {
- this (row, "", timestamp);
+ this (row, "", timestamp, new HRegionInfo());
}
/**
* Create an HStoreKey specifying the row and column names
* The timestamp defaults to LATEST_TIMESTAMP
+ * and table name defaults to the empty string
*
* @param row row key
* @param column column key
*/
public HStoreKey(final String row, final String column) {
- this(row, column, HConstants.LATEST_TIMESTAMP);
+ this(row, column, HConstants.LATEST_TIMESTAMP, new HRegionInfo());
}
/**
* Create an HStoreKey specifying the row and column names
* The timestamp defaults to LATEST_TIMESTAMP
+ * and table name defaults to the empty string
*
* @param row row key
* @param column column key
@@ -110,6 +118,19 @@
public HStoreKey(final byte [] row, final byte [] column) {
this(row, column, HConstants.LATEST_TIMESTAMP);
}
+
+ /**
+ * Create an HStoreKey specifying the row, column names and table name
+ * The timestamp defaults to LATEST_TIMESTAMP
+ *
+ * @param row row key
+ * @param column column key
+ * @param regionInfo region info
+ */
+ public HStoreKey(final byte [] row,
+ final byte [] column, final HRegionInfo regionInfo) {
+ this(row, column, HConstants.LATEST_TIMESTAMP, regionInfo);
+ }
/**
* Create an HStoreKey specifying all the fields
@@ -118,13 +139,16 @@
* @param row row key
* @param column column key
* @param timestamp timestamp value
+ * @param regionInfo region info
*/
- public HStoreKey(final String row, final String column, long timestamp) {
- this (Bytes.toBytes(row), Bytes.toBytes(column), timestamp);
+ public HStoreKey(final String row,
+ final String column, long timestamp, final HRegionInfo regionInfo) {
+ this (Bytes.toBytes(row), Bytes.toBytes(column),
+ timestamp, regionInfo);
}
/**
- * Create an HStoreKey specifying all the fields
+ * Create an HStoreKey specifying all the fields with unspecified table
* Does not make copies of the passed byte arrays. Presumes the passed
* arrays immutable.
* @param row row key
@@ -132,10 +156,25 @@
* @param timestamp timestamp value
*/
public HStoreKey(final byte [] row, final byte [] column, long timestamp) {
+ this(row, column, timestamp, null);
+ }
+
+ /**
+ * Create an HStoreKey specifying all the fields with specified table
+ * Does not make copies of the passed byte arrays. Presumes the passed
+ * arrays immutable.
+ * @param row row key
+ * @param column column key
+ * @param timestamp timestamp value
+ * @param regionInfo region info
+ */
+ public HStoreKey(final byte [] row,
+ final byte [] column, long timestamp, final HRegionInfo regionInfo) {
// Make copies
this.row = row;
this.column = column;
this.timestamp = timestamp;
+ this.regionInfo = regionInfo;
}
/** @return Approximate size in bytes of this key. */
@@ -205,6 +244,11 @@
return this.timestamp;
}
+ /** @return value of regioninfo */
+ public HRegionInfo getHRegionInfo() {
+ return this.regionInfo;
+ }
+
/**
* Compares the row and column of two keys
* @param other Key to compare against. Compares row and column.
@@ -274,7 +318,7 @@
/** [EMAIL PROTECTED] */
public int compareTo(Object o) {
HStoreKey other = (HStoreKey)o;
- int result = Bytes.compareTo(this.row, other.row);
+ int result = compareTwoRowKeys(this.regionInfo, this.row, other.row);
if (result != 0) {
return result;
}
@@ -419,6 +463,66 @@
return Bytes.add(hsk.getRow(), hsk.getColumn());
}
+ /**
+ * Utility method to compare two row keys.
+ * This is required because of the meta delimiters.
+ * This is a hack.
+ * @param regioninfo
+ * @param rowA
+ * @param rowB
+ * @return value of the comparison
+ */
+ public static int compareTwoRowKeys(HRegionInfo regionInfo,
+ byte[] rowA, byte[] rowB) {
+ if(regionInfo != null && (regionInfo.isMetaRegion() ||
+ regionInfo.isRootRegion())) {
+ byte[][] keysA = stripStartKeyMeta(rowA);
+ byte[][] KeysB = stripStartKeyMeta(rowB);
+ int rowCompare = Bytes.compareTo(keysA[0], KeysB[0]);
+ if(rowCompare == 0)
+ rowCompare = Bytes.compareTo(keysA[1], KeysB[1]);
+ return rowCompare;
+ } else {
+ return Bytes.compareTo(rowA, rowB);
+ }
+ }
+
+ /**
+ * Utility method to check if two row keys are equal.
+ * This is required because of the meta delimiters
+ * This is a hack
+ * @param regioninfo
+ * @param rowA
+ * @param rowB
+ * @return if it's equal
+ */
+ public static boolean equalsTwoRowKeys(HRegionInfo regionInfo,
+ byte[] rowA, byte[] rowB) {
+ return rowA == null && rowB == null? true:
+ rowA == null && rowB != null? false:
+ rowA != null && rowB == null? false:
+ rowA.length != rowB.length? false:
+ compareTwoRowKeys(regionInfo,rowA,rowB) == 0;
+ }
+
+ private static byte[][] stripStartKeyMeta(byte[] rowKey) {
+ int offset = -1;
+ for (int i = rowKey.length - 1; i > 0; i--) {
+ if (rowKey[i] == HConstants.META_ROW_DELIMITER) {
+ offset = i;
+ break;
+ }
+ }
+ byte [] row = new byte[offset];
+ System.arraycopy(rowKey, 0, row, 0,offset);
+ byte [] timestamp = new byte[rowKey.length - offset - 1];
+ System.arraycopy(rowKey, offset+1, timestamp, 0,rowKey.length - offset -
1);
+ byte[][] elements = new byte[2][];
+ elements[0] = row;
+ elements[1] = timestamp;
+ return elements;
+ }
+
// Writable
/** [EMAIL PROTECTED] */
@@ -434,4 +538,4 @@
this.column = Bytes.readByteArray(in);
this.timestamp = in.readLong();
}
-}
\ No newline at end of file
+}
Modified:
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/HRegion.java
URL:
http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/HRegion.java?rev=690637&r1=690636&r2=690637&view=diff
==============================================================================
---
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/HRegion.java
(original)
+++
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/HRegion.java
Sat Aug 30 21:48:57 2008
@@ -1246,13 +1246,14 @@
// get the closest key
byte [] closestKey = store.getRowKeyAtOrBefore(row);
// if it happens to be an exact match, we can stop looping
- if (Bytes.equals(row, closestKey)) {
+ if (HStoreKey.equalsTwoRowKeys(regionInfo,row, closestKey)) {
key = new HStoreKey(closestKey);
break;
}
// otherwise, we need to check if it's the max and move to the next
if (closestKey != null
- && (key == null || Bytes.compareTo(closestKey, key.getRow()) > 0) ) {
+ && (key == null || HStoreKey.compareTwoRowKeys(
+ regionInfo,closestKey, key.getRow()) > 0) ) {
key = new HStoreKey(closestKey);
}
}
Modified:
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/Memcache.java
URL:
http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/Memcache.java?rev=690637&r1=690636&r2=690637&view=diff
==============================================================================
---
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/Memcache.java
(original)
+++
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/Memcache.java
Sat Aug 30 21:48:57 2008
@@ -37,6 +37,7 @@
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.HStoreKey;
import org.apache.hadoop.hbase.io.Cell;
import org.apache.hadoop.hbase.util.Bytes;
@@ -53,6 +54,8 @@
private final Log LOG = LogFactory.getLog(this.getClass().getName());
private final long ttl;
+
+ private HRegionInfo regionInfo;
// Note that since these structures are always accessed with a lock held,
// so no additional synchronization is required.
@@ -72,14 +75,17 @@
*/
public Memcache() {
this.ttl = HConstants.FOREVER;
+ this.regionInfo = null;
}
/**
* Constructor.
* @param ttl The TTL for cache entries, in milliseconds.
+ * @param regionInfo The HRI for this cache
*/
- public Memcache(final long ttl) {
+ public Memcache(final long ttl, HRegionInfo regionInfo) {
this.ttl = ttl;
+ this.regionInfo = regionInfo;
}
/*
@@ -383,7 +389,8 @@
// the search key, or a range of values between the first candidate key
// and the ultimate search key (or the end of the cache)
if (!tailMap.isEmpty() &&
- Bytes.compareTo(tailMap.firstKey().getRow(), search_key.getRow()) <=
0) {
+ HStoreKey.compareTwoRowKeys(regionInfo,
+ tailMap.firstKey().getRow(), search_key.getRow()) <= 0) {
Iterator<HStoreKey> key_iterator = tailMap.keySet().iterator();
// Keep looking at cells as long as they are no greater than the
@@ -391,9 +398,11 @@
HStoreKey deletedOrExpiredRow = null;
for (HStoreKey found_key = null; key_iterator.hasNext() &&
(found_key == null ||
- Bytes.compareTo(found_key.getRow(), row) <= 0);) {
+ HStoreKey.compareTwoRowKeys(regionInfo,
+ found_key.getRow(), row) <= 0);) {
found_key = key_iterator.next();
- if (Bytes.compareTo(found_key.getRow(), row) <= 0) {
+ if (HStoreKey.compareTwoRowKeys(regionInfo,
+ found_key.getRow(), row) <= 0) {
if (HLogEdit.isDeleted(tailMap.get(found_key))) {
HStore.handleDeleted(found_key, candidateKeys, deletes);
if (deletedOrExpiredRow == null) {
Modified:
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/GenericHandler.java
URL:
http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/GenericHandler.java?rev=690637&r1=690636&r2=690637&view=diff
==============================================================================
---
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/GenericHandler.java
(original)
+++
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/GenericHandler.java
Sat Aug 30 21:48:57 2008
@@ -55,6 +55,7 @@
protected static final String CONTENT_TYPE = "content-type";
protected static final String ROW = "row";
protected static final String REGIONS = "regions";
+ protected static final String VERSION = "version";
protected final Log LOG = LogFactory.getLog(this.getClass());
@@ -233,13 +234,32 @@
outputter.startTag(COLUMN);
doElement(outputter, "name",
org.apache.hadoop.hbase.util.Base64.encodeBytes(e.getKey()));
- // We don't know String from binary data so we always base64 encode.
- doElement(outputter, "value",
-
org.apache.hadoop.hbase.util.Base64.encodeBytes(e.getValue().getValue()));
+ outputCellXml(outputter, e.getValue());
outputter.endTag();
}
}
+ protected void outputColumnsWithMultiVersionsXml(final XMLOutputter outputter,
+ final Map<byte [], Cell[]> m)
+ throws IllegalStateException, IllegalArgumentException, IOException {
+ for (Map.Entry<byte [], Cell[]> e: m.entrySet()) {
+ for (Cell c : e.getValue()) {
+ outputter.startTag(COLUMN);
+ doElement(outputter, "name",
+ org.apache.hadoop.hbase.util.Base64.encodeBytes(e.getKey()));
+ outputCellXml(outputter, c);
+ outputter.endTag();
+ }
+ }
+ }
+
+ protected void outputCellXml(final XMLOutputter outputter, Cell c)
+ throws IllegalStateException, IllegalArgumentException, IOException {
+ // We don't know String from binary data so we always base64 encode.
+ doElement(outputter, "value",
+ org.apache.hadoop.hbase.util.Base64.encodeBytes(c.getValue()));
+ doElement(outputter, "timestamp", String.valueOf(c.getTimestamp()));
+ }
// Commented - multipart support is currently nonexistant.
// protected void outputColumnsMime(final MultiPartResponse mpr,
// final Map<Text, Cell> m)
Modified:
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java
URL:
http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java?rev=690637&r1=690636&r2=690637&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java
(original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java
Sat Aug 30 21:48:57 2008
@@ -2,9 +2,9 @@
import java.io.IOException;
import java.net.URLDecoder;
-import java.util.HashSet;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.TreeMap;
import javax.servlet.ServletException;
@@ -72,7 +72,7 @@
final HttpServletResponse response, final String [] pathSegments)
throws IOException {
// pull the row key out of the path
- String row = URLDecoder.decode(pathSegments[2], HConstants.UTF8_ENCODING);
+ byte[] row = Bytes.toBytes(URLDecoder.decode(pathSegments[2],
HConstants.UTF8_ENCODING));
String timestampStr = null;
if (pathSegments.length == 4) {
@@ -85,64 +85,63 @@
}
}
- String[] columns = request.getParameterValues(COLUMN);
-
- if (columns == null || columns.length == 0) {
- // They want full row returned.
-
- // Presumption is that this.table has already been focused on target
table.
- Map<byte [], Cell> result = timestampStr == null ?
- table.getRow(Bytes.toBytes(row))
- : table.getRow(Bytes.toBytes(row), Long.parseLong(timestampStr));
-
+ String[] column_params = request.getParameterValues(COLUMN);
+
+ byte[][] columns = null;
+
+ if (column_params != null && column_params.length > 0) {
+ List<String> available_columns = new ArrayList<String>();
+ for (String column_param : column_params) {
+ if (column_param.length() > 0 &&
table.getTableDescriptor().hasFamily(Bytes.toBytes(column_param))) {
+ available_columns.add(column_param);
+ }
+ }
+ columns = Bytes.toByteArrays(available_columns.toArray(new String[0]));
+ }
+
+ String[] version_params = request.getParameterValues(VERSION);
+ int version = 0;
+ if (version_params != null && version_params.length == 1) {
+ version = Integer.parseInt(version_params[0]);
+ }
+
+ if (version > 0 && columns != null) {
+ Map<byte[], Cell[]> result = new TreeMap<byte [], Cell[]>(Bytes.BYTES_COMPARATOR);
+
+ for (byte[] col : columns) {
+ Cell[] cells = timestampStr == null ? table.get(row, col, version)
+ : table.get(row, col, Long.parseLong(timestampStr),
version);
+ if (cells != null) {
+ result.put(col, cells);
+ }
+ }
+
if (result == null || result.size() == 0) {
doNotFound(response, "Row not found!");
} else {
switch (ContentType.getContentType(request.getHeader(ACCEPT))) {
case XML:
- outputRowXml(response, result);
+ outputRowWithMultiVersionsXml(response, result);
break;
case MIME:
default:
- doNotAcceptable(response, "Unsupported Accept Header Content: " +
- request.getHeader(CONTENT_TYPE));
+ doNotAcceptable(response, "Unsupported Accept Header Content: "
+ + request.getHeader(CONTENT_TYPE));
}
- }
+ }
} else {
- Map<byte [], Cell> prefiltered_result = table.getRow(Bytes.toBytes(row));
-
- if (prefiltered_result == null || prefiltered_result.size() == 0) {
+ Map<byte[], Cell> result = timestampStr == null ? table.getRow(row,
columns) : table.getRow(row, columns, Long.parseLong(timestampStr));
+ if (result == null || result.size() == 0) {
doNotFound(response, "Row not found!");
} else {
- // create a Set from the columns requested so we can
- // efficiently filter the actual found columns
- Set<String> requested_columns_set = new HashSet<String>();
- for(int i = 0; i < columns.length; i++){
- requested_columns_set.add(columns[i]);
- }
-
- // output map that will contain the filtered results
- Map<byte [], Cell> m =
- new TreeMap<byte [], Cell>(Bytes.BYTES_COMPARATOR);
-
- // get an array of all the columns retrieved
- Set<byte []> columns_retrieved = prefiltered_result.keySet();
-
- // copy over those cells with requested column names
- for(byte [] current_column: columns_retrieved) {
- if (requested_columns_set.contains(Bytes.toString(current_column))) {
- m.put(current_column, prefiltered_result.get(current_column));
- }
- }
-
switch (ContentType.getContentType(request.getHeader(ACCEPT))) {
- case XML:
- outputRowXml(response, m);
- break;
- case MIME:
- default:
- doNotAcceptable(response, "Unsupported Accept Header Content: " +
- request.getHeader(CONTENT_TYPE));
+ case XML:
+ outputRowXml(response, result);
+ break;
+ case MIME:
+ default:
+ doNotAcceptable(response, "Unsupported Accept Header Content: "
+ + request.getHeader(CONTENT_TYPE));
}
}
}
@@ -167,6 +166,18 @@
outputter.getWriter().close();
}
+ private void outputRowWithMultiVersionsXml(final HttpServletResponse response,
+ final Map<byte[], Cell[]> result)
+ throws IOException {
+ setResponseHeader(response, result.size() > 0? 200: 204,
+ ContentType.XML.toString());
+ XMLOutputter outputter = getXMLOutputter(response.getWriter());
+ outputter.startTag(ROW);
+ outputColumnsWithMultiVersionsXml(outputter, result);
+ outputter.endTag();
+ outputter.endDocument();
+ outputter.getWriter().close();
+ }
/*
* @param response
* @param result
Modified: hadoop/hbase/trunk/src/test/org/apache/hadoop/hbase/TestCompare.java
URL:
http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/test/org/apache/hadoop/hbase/TestCompare.java?rev=690637&r1=690636&r2=690637&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/test/org/apache/hadoop/hbase/TestCompare.java
(original)
+++ hadoop/hbase/trunk/src/test/org/apache/hadoop/hbase/TestCompare.java Sat
Aug 30 21:48:57 2008
@@ -54,6 +54,43 @@
}
/**
+ * Tests cases where rows keys have characters below the ','.
+ * See HBASE-832
+ */
+ public void testHStoreKeyBorderCases() {
+ HRegionInfo info = new HRegionInfo(new HTableDescriptor("testtable"),
+ HConstants.EMPTY_BYTE_ARRAY,HConstants.EMPTY_BYTE_ARRAY);
+ HStoreKey rowA = new HStoreKey("testtable,www.hbase.org/,1234",
+ "", Long.MAX_VALUE, info);
+ HStoreKey rowB = new HStoreKey("testtable,www.hbase.org/%20,99999",
+ "", Long.MAX_VALUE, info);
+
+ assertTrue(rowA.compareTo(rowB) > 0);
+
+ rowA = new HStoreKey("testtable,www.hbase.org/,1234",
+ "", Long.MAX_VALUE, HRegionInfo.FIRST_META_REGIONINFO);
+ rowB = new HStoreKey("testtable,www.hbase.org/%20,99999",
+ "", Long.MAX_VALUE, HRegionInfo.FIRST_META_REGIONINFO);
+
+ assertTrue(rowA.compareTo(rowB) < 0);
+
+ rowA = new HStoreKey("testtable,,1234",
+ "", Long.MAX_VALUE, HRegionInfo.FIRST_META_REGIONINFO);
+ rowB = new HStoreKey("testtable,$www.hbase.org/,99999",
+ "", Long.MAX_VALUE, HRegionInfo.FIRST_META_REGIONINFO);
+
+ assertTrue(rowA.compareTo(rowB) < 0);
+
+ rowA = new HStoreKey(".META.,testtable,www.hbase.org/,1234,4321",
+ "", Long.MAX_VALUE, HRegionInfo.ROOT_REGIONINFO);
+ rowB = new HStoreKey(".META.,testtable,www.hbase.org/%20,99999,99999",
+ "", Long.MAX_VALUE, HRegionInfo.ROOT_REGIONINFO);
+
+ assertTrue(rowA.compareTo(rowB) > 0);
+ }
+
+
+ /**
* Sort of HRegionInfo.
*/
public void testHRegionInfo() {