Index: src/test/org/apache/hadoop/hbase/client/TestHTable.java =================================================================== --- src/test/org/apache/hadoop/hbase/client/TestHTable.java (revision 730269) +++ src/test/org/apache/hadoop/hbase/client/TestHTable.java (working copy) @@ -228,7 +228,11 @@ batchUpdate.put(COLUMN_FAMILY_STR+i, Bytes.toBytes(i)); table.commit(batchUpdate); - + + assertTrue(table.exists(row)); + for(int i = 0; i < 5; i++) + assertTrue(table.exists(row, Bytes.toBytes(COLUMN_FAMILY_STR+i))); + RowResult result = null; result = table.getRow(row, new byte[][] {COLUMN_FAMILY}); for(int i = 0; i < 5; i++) Index: src/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java =================================================================== --- src/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (revision 730269) +++ src/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (working copy) @@ -1774,6 +1774,13 @@ getLockFromId(lockId)); } + public boolean exists(byte[] regionName, byte[] row, byte[] column, + long timestamp, long lockId) + throws IOException { + return getRegion(regionName).exists(row, column, timestamp, + getLockFromId(lockId)); + } + public long lockRow(byte [] regionName, byte [] row) throws IOException { checkOpen(); Index: src/java/org/apache/hadoop/hbase/regionserver/HRegion.java =================================================================== --- src/java/org/apache/hadoop/hbase/regionserver/HRegion.java (revision 730269) +++ src/java/org/apache/hadoop/hbase/regionserver/HRegion.java (working copy) @@ -1501,8 +1501,37 @@ update(edits); } } - + /** + * Tests for the existence of any cells for a given coordinate. + * + * @param row the row + * @param column the column, or null + * @param timestamp the timestamp, or HConstants.LATEST_VERSION for any + * @param lockid the existing lock, or null + * @return true if cells exist for the row, false otherwise + * @throws IOException + */ + public boolean exists(final byte[] row, final byte[] column, + final long timestamp, final Integer lockid) + throws IOException { + checkRow(row); + Integer lid = getLock(lockid, row); + try { + HStoreKey origin; + if (column != null) { + origin = new HStoreKey(row, column, timestamp); + } else { + origin = new HStoreKey(row, timestamp); + } + return !getKeys(origin, 1).isEmpty(); + } finally { + if (lockid == null) + releaseRowLock(lid); + } + } + + /** * @throws IOException Throws exception if region is in read-only mode. */ protected void checkReadOnly() throws IOException { Index: src/java/org/apache/hadoop/hbase/ipc/HBaseRPCProtocolVersion.java =================================================================== --- src/java/org/apache/hadoop/hbase/ipc/HBaseRPCProtocolVersion.java (revision 730269) +++ src/java/org/apache/hadoop/hbase/ipc/HBaseRPCProtocolVersion.java (working copy) @@ -64,7 +64,8 @@ *
  • Version 12: HServerLoad extensions (HBASE-1018).
  • *
  • Version 13: HBASE-847
  • *
  • Version 14: HBASE-900
  • + *
  • Version 15: HRegionInterface.exists
  • * */ - public static final long versionID = 14L; + public static final long versionID = 15L; } Index: src/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java =================================================================== --- src/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java (revision 730269) +++ src/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java (working copy) @@ -191,7 +191,21 @@ long timestamp, long lockId) throws IOException; - + /** + * Returns true if any cells exist for the given coordinate. + * + * @param regionName The name of the region + * @param row The row + * @param column The column, or null for any + * @param timestamp The timestamp, or LATEST_TIMESTAMP for any + * @param lockId lock id + * @return true if the row exists, false otherwise + * @throws IOException + */ + public boolean exists(byte [] regionName, byte [] row, byte [] column, + long timestamp, long lockID) + throws IOException; + // // remote scanner interface // Index: src/java/org/apache/hadoop/hbase/client/HTable.java =================================================================== --- src/java/org/apache/hadoop/hbase/client/HTable.java (revision 730269) +++ src/java/org/apache/hadoop/hbase/client/HTable.java (working copy) @@ -1208,6 +1208,70 @@ } /** + * Test for the existence of a row in the table. + * + * @param row The row + * @return true if the row exists, false otherwise + * @throws IOException + */ + public boolean exists(final byte [] row) throws IOException { + return exists(row, null, HConstants.LATEST_TIMESTAMP, null); + } + + /** + * Test for the existence of a row and column in the table. + * + * @param row The row + * @param column The column + * @return true if the row exists, false otherwise + * @throws IOException + */ + public boolean exists(final byte [] row, final byte[] column) + throws IOException { + return exists(row, column, HConstants.LATEST_TIMESTAMP, null); + } + + /** + * Test for the existence of a coordinate in the table. + * + * @param row The row + * @param column The column + * @param timestamp The timestamp + * @return true if the specified coordinate exists + * @throws IOException + */ + public boolean exists(final byte [] row, final byte [] column, + long timestamp) throws IOException { + return exists(row, column, timestamp, null); + } + + /** + * Test for the existence of a coordinate in the table. + * + * @param row The row + * @param column The column + * @param timestamp The timestamp + * @param rl Existing row lock + * @return true if the specified coordinate exists + * @throws IOException + */ + public boolean exists(final byte [] row, final byte [] column, + final long timestamp, final RowLock rl) throws IOException { + return connection.getRegionServerWithRetries( + new ServerCallable(connection, tableName, row) { + public Boolean call() throws IOException { + long lockId = -1L; + if (rl != null) { + lockId = rl.getLockId(); + } + return server.exists(location.getRegionInfo().getRegionName(), row, + column, timestamp, lockId); + } + } + ); + } + + /** * Commit a BatchUpdate to the table. * If autoFlush is false, the update is buffered * @param batchUpdate