Return-Path: Delivered-To: apmail-hadoop-hbase-commits-archive@locus.apache.org Received: (qmail 104 invoked from network); 16 Jul 2008 21:11:42 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 16 Jul 2008 21:11:42 -0000 Received: (qmail 11170 invoked by uid 500); 16 Jul 2008 21:11:42 -0000 Delivered-To: apmail-hadoop-hbase-commits-archive@hadoop.apache.org Received: (qmail 11147 invoked by uid 500); 16 Jul 2008 21:11:42 -0000 Mailing-List: contact hbase-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: hbase-dev@hadoop.apache.org Delivered-To: mailing list hbase-commits@hadoop.apache.org Received: (qmail 11138 invoked by uid 99); 16 Jul 2008 21:11:42 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 Jul 2008 14:11:42 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 Jul 2008 21:10:55 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 007EC2388A61; Wed, 16 Jul 2008 14:11:20 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r677431 [2/3] - in /hadoop/hbase/trunk: CHANGES.txt src/java/org/apache/hadoop/hbase/client/HTable.java src/test/org/apache/hadoop/hbase/client/TestBatchUpdate.java Date: Wed, 16 Jul 2008 21:11:19 -0000 To: hbase-commits@hadoop.apache.org From: jimk@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080716211120.007EC2388A61@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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=677431&r1=677430&r2=677431&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 Jul 16 14:11:19 2008 @@ -1,1376 +1,1387 @@ -/** - * 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.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.hadoop.hbase.HConstants; -import org.apache.hadoop.hbase.HRegionInfo; -import org.apache.hadoop.hbase.HRegionLocation; -import org.apache.hadoop.hbase.HServerAddress; -import org.apache.hadoop.hbase.HTableDescriptor; -import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor; -import org.apache.hadoop.hbase.filter.RowFilterInterface; -import org.apache.hadoop.hbase.filter.StopRowFilter; -import org.apache.hadoop.hbase.filter.WhileMatchRowFilter; -import org.apache.hadoop.hbase.io.BatchUpdate; -import org.apache.hadoop.hbase.io.Cell; -import org.apache.hadoop.hbase.io.RowResult; -import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.io.Text; - -/** - * Used to communicate with a single HBase table - */ -public class HTable { - private final HConnection connection; - private final byte [] tableName; - private HBaseConfiguration configuration; - - /** - * Creates an object to access a HBase table - * - * @param tableName name of the table - * @throws IOException - */ - public HTable(final Text tableName) - throws IOException { - this(new HBaseConfiguration(), tableName.getBytes()); - } - - /** - * Creates an object to access a HBase table - * - * @param tableName name of the table - * @throws IOException - */ - public HTable(final String tableName) - throws IOException { - this(new HBaseConfiguration(), Bytes.toBytes(tableName)); - } - - /** - * Creates an object to access a HBase table - * - * @param tableName name of the table - * @throws IOException - */ - public HTable(final byte [] tableName) - throws IOException { - this(new HBaseConfiguration(), tableName); - } - - /** - * Creates an object to access a HBase table - * - * @param conf configuration object - * @param tableName name of the table - * @throws IOException - */ - public HTable(HBaseConfiguration conf, final Text tableName) - throws IOException { - this(conf, tableName.getBytes()); - } - - /** - * Creates an object to access a HBase table - * - * @param conf configuration object - * @param tableName name of the table - * @throws IOException - */ - public HTable(HBaseConfiguration conf, final String tableName) - throws IOException { - this(conf, Bytes.toBytes(tableName)); - } - - /** - * Creates an object to access a HBase table - * - * @param conf configuration object - * @param tableName name of the table - * @throws IOException - */ - public HTable(HBaseConfiguration conf, final byte [] tableName) - throws IOException { - this.connection = HConnectionManager.getConnection(conf); - this.configuration = conf; - this.tableName = tableName; - this.connection.locateRegion(tableName, HConstants.EMPTY_START_ROW); - } - - /** - * @param tableName name of table to check - * @return true if table is on-line - * @throws IOException - */ - public static boolean isTableEnabled(Text tableName) throws IOException { - return isTableEnabled(tableName.getBytes()); - } - /** - * @param tableName name of table to check - * @return true if table is on-line - * @throws IOException - */ - public static boolean isTableEnabled(String tableName) throws IOException { - return isTableEnabled(Bytes.toBytes(tableName)); - } - /** - * @param tableName name of table to check - * @return true if table is on-line - * @throws IOException - */ - public static boolean isTableEnabled(byte[] tableName) throws IOException { - return isTableEnabled(new HBaseConfiguration(), tableName); - } - - /** - * @param conf HBaseConfiguration object - * @param tableName name of table to check - * @return true if table is on-line - * @throws IOException - */ - public static boolean isTableEnabled(HBaseConfiguration conf, Text tableName) - throws IOException { - return isTableEnabled(conf, tableName.getBytes()); - } - - /** - * @param conf HBaseConfiguration object - * @param tableName name of table to check - * @return true if table is on-line - * @throws IOException - */ - public static boolean isTableEnabled(HBaseConfiguration conf, String tableName) - throws IOException { - return isTableEnabled(conf, Bytes.toBytes(tableName)); - } - - /** - * @param conf HBaseConfiguration object - * @param tableName name of table to check - * @return true if table is on-line - * @throws IOException - */ - public static boolean isTableEnabled(HBaseConfiguration conf, byte[] tableName) - throws IOException { - return HConnectionManager.getConnection(conf).isTableEnabled(tableName); - } - - /** - * Find region location hosting passed row using cached info - * @param row Row to find. - * @return Location of row. - * @throws IOException - */ - public HRegionLocation getRegionLocation(final Text row) - throws IOException { - return connection.getRegionLocation(tableName, row.getBytes(), false); - } - - /** - * Find region location hosting passed row using cached info - * @param row Row to find. - * @return Location of row. - * @throws IOException - */ - public HRegionLocation getRegionLocation(final String row) - throws IOException { - return connection.getRegionLocation(tableName, Bytes.toBytes(row), false); - } - - /** - * Find region location hosting passed row using cached info - * @param row Row to find. - * @return Location of row. - * @throws IOException - */ - public HRegionLocation getRegionLocation(final byte [] row) - throws IOException { - return connection.getRegionLocation(tableName, row, false); - } - - /** @return the table name */ - public byte [] getTableName() { - return this.tableName; - } - - /** - * Used by unit tests and tools to do low-level manipulations. Not for - * general use. - * @return An HConnection instance. - */ - public HConnection getConnection() { - return this.connection; - } - - /** - * @return table metadata - * @throws IOException - */ - @Deprecated - public HTableDescriptor getMetadata() throws IOException { - return getTableDescriptor(); - } - - /** - * @return table metadata - * @throws IOException - */ - public HTableDescriptor getTableDescriptor() throws IOException { - return this.connection.getHTableDescriptor(this.tableName); - } - - /** - * Gets the starting row key for every region in the currently open table - * - * @return Array of region starting row keys - * @throws IOException - */ - @SuppressWarnings("null") - public byte[][] getStartKeys() throws IOException { - final List keyList = new ArrayList(); - - MetaScannerVisitor visitor = new MetaScannerVisitor() { - @SuppressWarnings("unused") - public boolean processRow(@SuppressWarnings("unused") RowResult rowResult, - @SuppressWarnings("unused") HRegionLocation regionLocation, - HRegionInfo info) - throws IOException { - if (!(Bytes.equals(info.getTableDesc().getName(), getTableName()))) { - return false; - } - if (!(info.isOffline() || info.isSplit())) { - keyList.add(info.getStartKey()); - } - return true; - } - - }; - MetaScanner.metaScan(configuration, visitor, this.tableName); - return keyList.toArray(new byte[keyList.size()][]); - } - - /** - * Get all the regions and their address for this table - * - * @return A map of HRegionInfo with it's server address - * @throws IOException - */ - public Map getRegionsInfo() throws IOException { - final Map regionMap = - new TreeMap(); - - MetaScannerVisitor visitor = new MetaScannerVisitor() { - public boolean processRow(@SuppressWarnings("unused") RowResult rowResult, - HRegionLocation regionLocation, HRegionInfo hri) { - - HRegionInfo info = new UnmodifyableHRegionInfo(hri); - if (!(Bytes.equals(info.getTableDesc().getName(), getTableName()))) { - return false; - } - if (!(info.isOffline() || info.isSplit())) { - regionMap.put(info, regionLocation.getServerAddress()); - } - return true; - } - - }; - MetaScanner.metaScan(configuration, visitor, tableName); - return regionMap; - } - - /** - * Get a single value for the specified row and column - * - * @param row row key - * @param column column name - * @return value for specified row/column - * @throws IOException - */ - public Cell get(final Text row, final Text column) - throws IOException { - return get(row.getBytes(), column.getBytes()); - } - - /** - * Get a single value for the specified row and column - * - * @param row row key - * @param column column name - * @param numVersions - number of versions to retrieve - * @return value for specified row/column - * @throws IOException - */ - public Cell[] get(final Text row, final Text column, int numVersions) - throws IOException { - return get(row.getBytes(), column.getBytes(), numVersions); - } - - /** - * Get a single value for the specified row and column - * - * @param row row key - * @param column column name - * @return value for specified row/column - * @throws IOException - */ - public Cell get(final String row, final String column) - throws IOException { - return get(Bytes.toBytes(row), Bytes.toBytes(column)); - } - - /** - * Get a single value for the specified row and column - * - * @param row row key - * @param column column name - * @param numVersions - number of versions to retrieve - * @return value for specified row/column - * @throws IOException - */ - public Cell[] get(final String row, final String column, int numVersions) - throws IOException { - return get(Bytes.toBytes(row), Bytes.toBytes(column), numVersions); - } - - /** - * Get a single value for the specified row and column - * - * @param row row key - * @param column column name - * @return value for specified row/column - * @throws IOException - */ - public Cell get(final byte [] row, final byte [] column) - throws IOException { - return connection.getRegionServerWithRetries( - new ServerCallable(connection, tableName, row) { - public Cell call() throws IOException { - return server.get(location.getRegionInfo().getRegionName(), row, - column); - } - } - ); - } - - /** - * Get the specified number of versions of the specified row and column - * @param row row key - * @param column column name - * @param numVersions number of versions to retrieve - * @return Array of Cells. - * @throws IOException - */ - public Cell[] get(final byte [] row, final byte [] column, - final int numVersions) - throws IOException { - return connection.getRegionServerWithRetries( - new ServerCallable(connection, tableName, row) { - public Cell[] call() throws IOException { - return server.get(location.getRegionInfo().getRegionName(), row, - column, numVersions); - } - } - ); - } - - /** - * Get the specified number of versions of the specified row and column with - * the specified timestamp. - * - * @param row - row key - * @param column - column name - * @param timestamp - timestamp - * @param numVersions - number of versions to retrieve - * @return - array of values that match the above criteria - * @throws IOException - */ - public Cell[] get(final Text row, final Text column, - final long timestamp, final int numVersions) - throws IOException { - return get(row.getBytes(), column.getBytes(), timestamp, numVersions); - } - - /** - * Get the specified number of versions of the specified row and column with - * the specified timestamp. - * - * @param row - row key - * @param column - column name - * @param timestamp - timestamp - * @param numVersions - number of versions to retrieve - * @return - array of values that match the above criteria - * @throws IOException - */ - public Cell[] get(final String row, final String column, - final long timestamp, final int numVersions) - throws IOException { - return get(Bytes.toBytes(row), Bytes.toBytes(column), timestamp, numVersions); - } - - /** - * Get the specified number of versions of the specified row and column with - * the specified timestamp. - * - * @param row - row key - * @param column - column name - * @param timestamp - timestamp - * @param numVersions - number of versions to retrieve - * @return - array of values that match the above criteria - * @throws IOException - */ - public Cell[] get(final byte [] row, final byte [] column, - final long timestamp, final int numVersions) - throws IOException { - Cell[] values = null; - values = connection.getRegionServerWithRetries( - new ServerCallable(connection, tableName, row) { - public Cell[] call() throws IOException { - return server.get(location.getRegionInfo().getRegionName(), row, - column, timestamp, numVersions); - } - } - ); - - if (values != null) { - ArrayList cellValues = new ArrayList(); - for (int i = 0 ; i < values.length; i++) { - cellValues.add(values[i]); - } - return cellValues.toArray(new Cell[values.length]); - } - return null; - } - - /** - * Get all the data for the specified row at the latest timestamp - * - * @param row row key - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final Text row) throws IOException { - return getRow(row.getBytes()); - } - - /** - * Get all the data for the specified row at the latest timestamp - * - * @param row row key - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final String row) throws IOException { - return getRow(Bytes.toBytes(row)); - } - - /** - * Get all the data for the specified row at the latest timestamp - * - * @param row row key - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final byte [] row) throws IOException { - return getRow(row, HConstants.LATEST_TIMESTAMP); - } - - /** - * Get all the data for the specified row at a specified timestamp - * - * @param row row key - * @param ts timestamp - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final Text row, final long ts) - throws IOException { - return getRow(row.getBytes(), ts); - } - - /** - * Get all the data for the specified row at a specified timestamp - * - * @param row row key - * @param ts timestamp - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final String row, final long ts) - throws IOException { - return getRow(Bytes.toBytes(row), ts); - } - - /** - * Get all the data for the specified row at a specified timestamp - * - * @param row row key - * @param ts timestamp - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final byte [] row, final long ts) - throws IOException { - return connection.getRegionServerWithRetries( - new ServerCallable(connection, tableName, row) { - public RowResult call() throws IOException { - return server.getRow(location.getRegionInfo().getRegionName(), row, - ts); - } - } - ); - } - - /** - * Get selected columns for the specified row at the latest timestamp - * - * @param row row key - * @param columns Array of column names and families you want to retrieve. - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final Text row, final Text[] columns) - throws IOException { - return getRow(row.getBytes(), Bytes.toByteArrays(columns)); - } - - /** - * Get selected columns for the specified row at the latest timestamp - * - * @param row row key - * @param columns Array of column names and families you want to retrieve. - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final String row, final String [] columns) - throws IOException { - return getRow(Bytes.toBytes(row), Bytes.toByteArrays(columns)); - } - - /** - * Get selected columns for the specified row at the latest timestamp - * - * @param row row key - * @param columns Array of column names and families you want to retrieve. - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final byte [] row, final byte [][] columns) - throws IOException { - return getRow(row, columns, HConstants.LATEST_TIMESTAMP); - } - - /** - * Get selected columns for the specified row at a specified timestamp - * - * @param row row key - * @param columns Array of column names and families you want to retrieve. - * @param ts timestamp - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final Text row, final Text [] columns, - final long ts) - throws IOException { - return getRow(row.getBytes(), Bytes.toByteArrays(columns), ts); - } - - /** - * Get selected columns for the specified row at a specified timestamp - * - * @param row row key - * @param columns Array of column names and families you want to retrieve. - * @param ts timestamp - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final String row, final String [] columns, - final long ts) - throws IOException { - return getRow(Bytes.toBytes(row), Bytes.toByteArrays(columns), ts); - } - - /** - * Get selected columns for the specified row at a specified timestamp - * - * @param row row key - * @param columns Array of column names and families you want to retrieve. - * @param ts timestamp - * @return RowResult is empty if row does not exist. - * @throws IOException - */ - public RowResult getRow(final byte [] row, final byte [][] columns, - final long ts) - throws IOException { - return connection.getRegionServerWithRetries( - new ServerCallable(connection, tableName, row) { - public RowResult call() throws IOException { - return server.getRow(location.getRegionInfo().getRegionName(), row, - columns, ts); - } - } - ); - } - - /** - * Get a scanner on the current table starting at first row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final Text [] columns) - throws IOException { - return getScanner(Bytes.toByteArrays(columns), HConstants.EMPTY_START_ROW); - } - - /** - * Get a scanner on the current table starting at first row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final String [] columns) - throws IOException { - return getScanner(Bytes.toByteArrays(columns), HConstants.EMPTY_START_ROW); - } - - /** - * Get a scanner on the current table starting at the specified row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final Text [] columns, final Text startRow) - throws IOException { - return getScanner(Bytes.toByteArrays(columns), startRow.getBytes()); - } - - /** - * Get a scanner on the current table starting at the specified row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final String [] columns, final String startRow) - throws IOException { - return getScanner(Bytes.toByteArrays(columns), Bytes.toBytes(startRow)); - } - - /** - * Get a scanner on the current table starting at first row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final byte[][] columns) - throws IOException { - return getScanner(columns, HConstants.EMPTY_START_ROW, - HConstants.LATEST_TIMESTAMP, null); - } - - /** - * Get a scanner on the current table starting at the specified row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final byte[][] columns, final byte [] startRow) - throws IOException { - return getScanner(columns, startRow, HConstants.LATEST_TIMESTAMP, null); - } - - /** - * Get a scanner on the current table starting at the specified row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @param timestamp only return results whose timestamp <= this value - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final byte[][] columns, final byte [] startRow, - long timestamp) - throws IOException { - return getScanner(columns, startRow, timestamp, null); - } - - /** - * Get a scanner on the current table starting at the specified row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @param filter a row filter using row-key regexp and/or column data filter. - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final byte[][] columns, final byte [] startRow, - RowFilterInterface filter) - throws IOException { - return getScanner(columns, startRow, HConstants.LATEST_TIMESTAMP, filter); - } - - /** - * Get a scanner on the current table starting at the specified row and - * ending just before stopRow. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @param stopRow Row to stop scanning on. Once we hit this row we stop - * returning values; i.e. we return the row before this one but not the - * stopRow itself. - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final byte [][] columns, - final byte [] startRow, final byte [] stopRow) - throws IOException { - return getScanner(columns, startRow, stopRow, - HConstants.LATEST_TIMESTAMP); - } - - /** - * Get a scanner on the current table starting at the specified row and - * ending just before stopRow. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @param stopRow Row to stop scanning on. Once we hit this row we stop - * returning values; i.e. we return the row before this one but not the - * stopRow itself. - * @param timestamp only return results whose timestamp <= this value - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final Text[] columns, - final Text startRow, final Text stopRow, final long timestamp) - throws IOException { - return getScanner(Bytes.toByteArrays(columns), startRow.getBytes(), - stopRow.getBytes(), timestamp); - } - - /** - * Get a scanner on the current table starting at the specified row and - * ending just before stopRow. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @param stopRow Row to stop scanning on. Once we hit this row we stop - * returning values; i.e. we return the row before this one but not the - * stopRow itself. - * @param timestamp only return results whose timestamp <= this value - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final String [] columns, - final String startRow, final String stopRow, final long timestamp) - throws IOException { - return getScanner(Bytes.toByteArrays(columns), Bytes.toBytes(startRow), - Bytes.toBytes(stopRow), timestamp); - } - - /** - * Get a scanner on the current table starting at the specified row and - * ending just before stopRow. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @param stopRow Row to stop scanning on. Once we hit this row we stop - * returning values; i.e. we return the row before this one but not the - * stopRow itself. - * @param timestamp only return results whose timestamp <= this value - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final byte [][] columns, - final byte [] startRow, final byte [] stopRow, final long timestamp) - throws IOException { - return getScanner(columns, startRow, timestamp, - new WhileMatchRowFilter(new StopRowFilter(stopRow))); - } - - /** - * Get a scanner on the current table starting at the specified row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @param timestamp only return results whose timestamp <= this value - * @param filter a row filter using row-key regexp and/or column data filter. - * @return scanner - * @throws IOException - */ - public Scanner getScanner(Text[] columns, - Text startRow, long timestamp, RowFilterInterface filter) - throws IOException { - return getScanner(Bytes.toByteArrays(columns), startRow.getBytes(), - timestamp, filter); - } - - /** - * Get a scanner on the current table starting at the specified row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @param timestamp only return results whose timestamp <= this value - * @param filter a row filter using row-key regexp and/or column data filter. - * @return scanner - * @throws IOException - */ - public Scanner getScanner(String[] columns, - String startRow, long timestamp, RowFilterInterface filter) - throws IOException { - return getScanner(Bytes.toByteArrays(columns), Bytes.toBytes(startRow), - timestamp, filter); - } - - /** - * Get a scanner on the current table starting at the specified row. - * Return the specified columns. - * - * @param columns columns to scan. If column name is a column family, all - * columns of the specified column family are returned. Its also possible - * to pass a regex in the column qualifier. A column qualifier is judged to - * be a regex if it contains at least one of the following characters: - * \+|^&*$[]]}{)(. - * @param startRow starting row in table to scan - * @param timestamp only return results whose timestamp <= this value - * @param filter a row filter using row-key regexp and/or column data filter. - * @return scanner - * @throws IOException - */ - public Scanner getScanner(final byte [][] columns, - final byte [] startRow, long timestamp, RowFilterInterface filter) - throws IOException { - return new ClientScanner(columns, startRow, timestamp, filter); - } - - /** - * Completely delete the row's cells. - * - * @param row Key of the row you want to completely delete. - * @throws IOException - */ - public void deleteAll(final byte [] row) throws IOException { - deleteAll(row, null); - } - - /** - * Completely delete the row's cells. - * - * @param row Key of the row you want to completely delete. - * @throws IOException - */ - public void deleteAll(final Text row) throws IOException { - deleteAll(row, null); - } - - /** - * Completely delete the row's cells. - * - * @param row Key of the row you want to completely delete. - * @throws IOException - */ - public void deleteAll(final String row) throws IOException { - deleteAll(row, null); - } - - /** - * Completely delete the row's cells. - * - * @param row Key of the row you want to completely delete. - * @param column column to be deleted - * @throws IOException - */ - public void deleteAll(final byte [] row, final byte [] column) - throws IOException { - deleteAll(row, column, HConstants.LATEST_TIMESTAMP); - } - - /** - * Completely delete the row's cells. - * - * @param row Key of the row you want to completely delete. - * @param ts Delete all cells of the same timestamp or older. - * @throws IOException - */ - public void deleteAll(final byte [] row, final long ts) - throws IOException { - deleteAll(row, null, ts); - } - - /** - * Completely delete the row's cells. - * - * @param row Key of the row you want to completely delete. - * @param ts Delete all cells of the same timestamp or older. - * @throws IOException - */ - public void deleteAll(final String row, final long ts) - throws IOException { - deleteAll(row, null, ts); - } - - /** - * Completely delete the row's cells. - * - * @param row Key of the row you want to completely delete. - * @param ts Delete all cells of the same timestamp or older. - * @throws IOException - */ - public void deleteAll(final Text row, final long ts) - throws IOException { - deleteAll(row, null, ts); - } - - /** - * Delete all cells that match the passed row and column. - * @param row Row to update - * @param column name of column whose value is to be deleted - * @throws IOException - */ - public void deleteAll(final Text row, final Text column) throws IOException { - deleteAll(row, column, HConstants.LATEST_TIMESTAMP); - } - - /** - * Delete all cells that match the passed row and column. - * @param row Row to update - * @param column name of column whose value is to be deleted - * @throws IOException - */ - public void deleteAll(final String row, final String column) - throws IOException { - deleteAll(row, column, HConstants.LATEST_TIMESTAMP); - } - - /** - * Delete all cells that match the passed row and column and whose - * timestamp is equal-to or older than the passed timestamp. - * @param row Row to update - * @param column name of column whose value is to be deleted - * @param ts Delete all cells of the same timestamp or older. - * @throws IOException - */ - public void deleteAll(final Text row, final Text column, final long ts) - throws IOException { - deleteAll(row.getBytes(), column.getBytes(), ts); - } - - /** - * Delete all cells that match the passed row and column and whose - * timestamp is equal-to or older than the passed timestamp. - * @param row Row to update - * @param column name of column whose value is to be deleted - * @param ts Delete all cells of the same timestamp or older. - * @throws IOException - */ - public void deleteAll(final String row, final String column, final long ts) - throws IOException { - deleteAll(Bytes.toBytes(row), - column != null? Bytes.toBytes(column): null, ts); - } - - /** - * Delete all cells that match the passed row and column and whose - * timestamp is equal-to or older than the passed timestamp. - * @param row Row to update - * @param column name of column whose value is to be deleted - * @param ts Delete all cells of the same timestamp or older. - * @throws IOException - */ - public void deleteAll(final byte [] row, final byte [] column, final long ts) - throws IOException { - connection.getRegionServerWithRetries( - new ServerCallable(connection, tableName, row) { - public Boolean call() throws IOException { - if (column != null) { - this.server.deleteAll(location.getRegionInfo().getRegionName(), - row, column, ts); - } else { - this.server.deleteAll(location.getRegionInfo().getRegionName(), - row, ts); - } - return null; - } - } - ); - } - - /** - * Delete all cells for a row with matching column family at all timestamps. - * - * @param row The row to operate on - * @param family The column family to match - * @param timestamp Timestamp to match - * @throws IOException - */ - public void deleteFamily(final Text row, final Text family, - final long timestamp) - throws IOException{ - deleteFamily(row.getBytes(), family.getBytes(), timestamp); - } - - /** - * Delete all cells for a row with matching column family at all timestamps. - * - * @param row The row to operate on - * @param family The column family to match - * @param timestamp Timestamp to match - * @throws IOException - */ - public void deleteFamily(final String row, final String family, - final long timestamp) - throws IOException{ - deleteFamily(Bytes.toBytes(row), Bytes.toBytes(family), timestamp); - } - - /** - * Delete all cells for a row with matching column family with timestamps - * less than or equal to timestamp. - * - * @param row The row to operate on - * @param family The column family to match - * @param timestamp Timestamp to match - * @throws IOException - */ - public void deleteFamily(final byte [] row, final byte [] family, - final long timestamp) - throws IOException { - connection.getRegionServerWithRetries( - new ServerCallable(connection, tableName, row) { - public Boolean call() throws IOException { - server.deleteFamily(location.getRegionInfo().getRegionName(), row, - family, timestamp); - return null; - } - } - ); - } - - /** - * Commit a BatchUpdate to the table. - * @param batchUpdate - * @throws IOException - */ - public synchronized void commit(final BatchUpdate batchUpdate) - throws IOException { - connection.getRegionServerWithRetries( - new ServerCallable(connection, tableName, batchUpdate.getRow()) { - public Boolean call() throws IOException { - server.batchUpdate(location.getRegionInfo().getRegionName(), - batchUpdate); - return null; - } - } - ); - } - - /** - * Implements the scanner interface for the HBase client. - * If there are multiple regions in a table, this scanner will iterate - * through them all. - */ - protected class ClientScanner implements Scanner { - private final Log CLIENT_LOG = LogFactory.getLog(this.getClass()); - private byte[][] columns; - private byte [] startRow; - protected long scanTime; - @SuppressWarnings("hiding") - private boolean closed = false; - private HRegionInfo currentRegion = null; - private ScannerCallable callable = null; - protected RowFilterInterface filter; - - protected ClientScanner(final Text [] columns, final Text startRow, - long timestamp, RowFilterInterface filter) - throws IOException { - this(Bytes.toByteArrays(columns), startRow.getBytes(), timestamp, - filter); - } - - protected ClientScanner(final byte[][] columns, final byte [] startRow, - final long timestamp, final RowFilterInterface filter) - throws IOException { - if (CLIENT_LOG.isDebugEnabled()) { - CLIENT_LOG.debug("Creating scanner over " + Bytes.toString(getTableName()) + - " starting at key '" + Bytes.toString(startRow) + "'"); - } - // save off the simple parameters - this.columns = columns; - this.startRow = startRow; - this.scanTime = timestamp; - - // save the filter, and make sure that the filter applies to the data - // we're expecting to pull back - this.filter = filter; - if (filter != null) { - filter.validate(columns); - } - nextScanner(); - } - - protected byte[][] getColumns() { - return columns; - } - - protected long getTimestamp() { - return scanTime; - } - - protected RowFilterInterface getFilter() { - return filter; - } - - /* - * Gets a scanner for the next region. - * Returns false if there are no more scanners. - */ - private boolean nextScanner() throws IOException { - // Close the previous scanner if it's open - if (this.callable != null) { - this.callable.setClose(); - getConnection().getRegionServerWithRetries(callable); - this.callable = null; - } - - // if we're at the end of the table, then close and return false - // to stop iterating - if (currentRegion != null) { - if (CLIENT_LOG.isDebugEnabled()) { - CLIENT_LOG.debug("Advancing forward from region " + currentRegion); - } - - byte [] endKey = currentRegion.getEndKey(); - if (endKey == null || - Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY) || - filterSaysStop(endKey)) { - close(); - return false; - } - } - - HRegionInfo oldRegion = this.currentRegion; - byte [] localStartKey = oldRegion == null? startRow: oldRegion.getEndKey(); - - if (CLIENT_LOG.isDebugEnabled()) { - CLIENT_LOG.debug("Advancing internal scanner to startKey at '" + - Bytes.toString(localStartKey) + "'"); - } - - try { - callable = getScannerCallable(localStartKey); - // open a scanner on the region server starting at the - // beginning of the region - getConnection().getRegionServerWithRetries(callable); - currentRegion = callable.getHRegionInfo(); - } catch (IOException e) { - close(); - throw e; - } - return true; - } - - protected ScannerCallable getScannerCallable(byte [] localStartKey) { - return new ScannerCallable(getConnection(), getTableName(), columns, - localStartKey, scanTime, filter); - } - - /** - * @param endKey - * @return Returns true if the passed region endkey is judged beyond - * filter. - */ - private boolean filterSaysStop(final byte [] endKey) { - if (this.filter == null) { - return false; - } - // Let the filter see current row. - this.filter.filterRowKey(endKey); - return this.filter.filterAllRemaining(); - } - - /** {@inheritDoc} */ - public RowResult next() throws IOException { - if (this.closed) { - return null; - } - RowResult values = null; - do { - values = getConnection().getRegionServerWithRetries(callable); - } while ((values == null || values.size() == 0) && nextScanner()); - - if (values != null && values.size() != 0) { - return values; - } - return null; - } - - /** - * {@inheritDoc} - */ - public void close() { - if (callable != null) { - callable.setClose(); - try { - getConnection().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. - } - callable = null; - } - closed = true; - } - - /** {@inheritDoc} */ - public Iterator iterator() { - return new Iterator() { - // The next RowResult, possibly pre-read - RowResult next = null; - - // return true if there is another item pending, false if there isn't. - // this method is where the actual advancing takes place, but you need - // to call next() to consume it. hasNext() will only advance if there - // isn't a pending next(). - public boolean hasNext() { - if (next == null) { - try { - next = ClientScanner.this.next(); - return next != null; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - return true; - } - - // get the pending next item and advance the iterator. returns null if - // there is no next item. - public RowResult next() { - // since hasNext() does the real advancing, we call this to determine - // if there is a next before proceeding. - if (!hasNext()) { - return null; - } - - // if we get to here, then hasNext() has given us an item to return. - // we want to return the item and then null out the next pointer, so - // we use a temporary variable. - RowResult temp = next; - next = null; - return temp; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - } -} +/** + * 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.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.HRegionLocation; +import org.apache.hadoop.hbase.HServerAddress; +import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor; +import org.apache.hadoop.hbase.filter.RowFilterInterface; +import org.apache.hadoop.hbase.filter.StopRowFilter; +import org.apache.hadoop.hbase.filter.WhileMatchRowFilter; +import org.apache.hadoop.hbase.io.BatchUpdate; +import org.apache.hadoop.hbase.io.Cell; +import org.apache.hadoop.hbase.io.RowResult; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.io.Text; + +/** + * Used to communicate with a single HBase table + */ +public class HTable { + private final HConnection connection; + private final byte [] tableName; + private HBaseConfiguration configuration; + + /** + * Creates an object to access a HBase table + * + * @param tableName name of the table + * @throws IOException + */ + public HTable(final Text tableName) + throws IOException { + this(new HBaseConfiguration(), tableName.getBytes()); + } + + /** + * Creates an object to access a HBase table + * + * @param tableName name of the table + * @throws IOException + */ + public HTable(final String tableName) + throws IOException { + this(new HBaseConfiguration(), Bytes.toBytes(tableName)); + } + + /** + * Creates an object to access a HBase table + * + * @param tableName name of the table + * @throws IOException + */ + public HTable(final byte [] tableName) + throws IOException { + this(new HBaseConfiguration(), tableName); + } + + /** + * Creates an object to access a HBase table + * + * @param conf configuration object + * @param tableName name of the table + * @throws IOException + */ + public HTable(HBaseConfiguration conf, final Text tableName) + throws IOException { + this(conf, tableName.getBytes()); + } + + /** + * Creates an object to access a HBase table + * + * @param conf configuration object + * @param tableName name of the table + * @throws IOException + */ + public HTable(HBaseConfiguration conf, final String tableName) + throws IOException { + this(conf, Bytes.toBytes(tableName)); + } + + /** + * Creates an object to access a HBase table + * + * @param conf configuration object + * @param tableName name of the table + * @throws IOException + */ + public HTable(HBaseConfiguration conf, final byte [] tableName) + throws IOException { + this.connection = HConnectionManager.getConnection(conf); + this.configuration = conf; + this.tableName = tableName; + this.connection.locateRegion(tableName, HConstants.EMPTY_START_ROW); + } + + /** + * @param tableName name of table to check + * @return true if table is on-line + * @throws IOException + */ + public static boolean isTableEnabled(Text tableName) throws IOException { + return isTableEnabled(tableName.getBytes()); + } + /** + * @param tableName name of table to check + * @return true if table is on-line + * @throws IOException + */ + public static boolean isTableEnabled(String tableName) throws IOException { + return isTableEnabled(Bytes.toBytes(tableName)); + } + /** + * @param tableName name of table to check + * @return true if table is on-line + * @throws IOException + */ + public static boolean isTableEnabled(byte[] tableName) throws IOException { + return isTableEnabled(new HBaseConfiguration(), tableName); + } + + /** + * @param conf HBaseConfiguration object + * @param tableName name of table to check + * @return true if table is on-line + * @throws IOException + */ + public static boolean isTableEnabled(HBaseConfiguration conf, Text tableName) + throws IOException { + return isTableEnabled(conf, tableName.getBytes()); + } + + /** + * @param conf HBaseConfiguration object + * @param tableName name of table to check + * @return true if table is on-line + * @throws IOException + */ + public static boolean isTableEnabled(HBaseConfiguration conf, String tableName) + throws IOException { + return isTableEnabled(conf, Bytes.toBytes(tableName)); + } + + /** + * @param conf HBaseConfiguration object + * @param tableName name of table to check + * @return true if table is on-line + * @throws IOException + */ + public static boolean isTableEnabled(HBaseConfiguration conf, byte[] tableName) + throws IOException { + return HConnectionManager.getConnection(conf).isTableEnabled(tableName); + } + + /** + * Find region location hosting passed row using cached info + * @param row Row to find. + * @return Location of row. + * @throws IOException + */ + public HRegionLocation getRegionLocation(final Text row) + throws IOException { + return connection.getRegionLocation(tableName, row.getBytes(), false); + } + + /** + * Find region location hosting passed row using cached info + * @param row Row to find. + * @return Location of row. + * @throws IOException + */ + public HRegionLocation getRegionLocation(final String row) + throws IOException { + return connection.getRegionLocation(tableName, Bytes.toBytes(row), false); + } + + /** + * Find region location hosting passed row using cached info + * @param row Row to find. + * @return Location of row. + * @throws IOException + */ + public HRegionLocation getRegionLocation(final byte [] row) + throws IOException { + return connection.getRegionLocation(tableName, row, false); + } + + /** @return the table name */ + public byte [] getTableName() { + return this.tableName; + } + + /** + * Used by unit tests and tools to do low-level manipulations. Not for + * general use. + * @return An HConnection instance. + */ + public HConnection getConnection() { + return this.connection; + } + + /** + * @return table metadata + * @throws IOException + */ + @Deprecated + public HTableDescriptor getMetadata() throws IOException { + return getTableDescriptor(); + } + + /** + * @return table metadata + * @throws IOException + */ + public HTableDescriptor getTableDescriptor() throws IOException { + return this.connection.getHTableDescriptor(this.tableName); + } + + /** + * Gets the starting row key for every region in the currently open table + * + * @return Array of region starting row keys + * @throws IOException + */ + @SuppressWarnings("null") + public byte[][] getStartKeys() throws IOException { + final List keyList = new ArrayList(); + + MetaScannerVisitor visitor = new MetaScannerVisitor() { + @SuppressWarnings("unused") + public boolean processRow(@SuppressWarnings("unused") RowResult rowResult, + @SuppressWarnings("unused") HRegionLocation regionLocation, + HRegionInfo info) + throws IOException { + if (!(Bytes.equals(info.getTableDesc().getName(), getTableName()))) { + return false; + } + if (!(info.isOffline() || info.isSplit())) { + keyList.add(info.getStartKey()); + } + return true; + } + + }; + MetaScanner.metaScan(configuration, visitor, this.tableName); + return keyList.toArray(new byte[keyList.size()][]); + } + + /** + * Get all the regions and their address for this table + * + * @return A map of HRegionInfo with it's server address + * @throws IOException + */ + public Map getRegionsInfo() throws IOException { + final Map regionMap = + new TreeMap(); + + MetaScannerVisitor visitor = new MetaScannerVisitor() { + public boolean processRow(@SuppressWarnings("unused") RowResult rowResult, + HRegionLocation regionLocation, HRegionInfo hri) { + + HRegionInfo info = new UnmodifyableHRegionInfo(hri); + if (!(Bytes.equals(info.getTableDesc().getName(), getTableName()))) { + return false; + } + if (!(info.isOffline() || info.isSplit())) { + regionMap.put(info, regionLocation.getServerAddress()); + } + return true; + } + + }; + MetaScanner.metaScan(configuration, visitor, tableName); + return regionMap; + } + + /** + * Get a single value for the specified row and column + * + * @param row row key + * @param column column name + * @return value for specified row/column + * @throws IOException + */ + public Cell get(final Text row, final Text column) + throws IOException { + return get(row.getBytes(), column.getBytes()); + } + + /** + * Get a single value for the specified row and column + * + * @param row row key + * @param column column name + * @param numVersions - number of versions to retrieve + * @return value for specified row/column + * @throws IOException + */ + public Cell[] get(final Text row, final Text column, int numVersions) + throws IOException { + return get(row.getBytes(), column.getBytes(), numVersions); + } + + /** + * Get a single value for the specified row and column + * + * @param row row key + * @param column column name + * @return value for specified row/column + * @throws IOException + */ + public Cell get(final String row, final String column) + throws IOException { + return get(Bytes.toBytes(row), Bytes.toBytes(column)); + } + + /** + * Get a single value for the specified row and column + * + * @param row row key + * @param column column name + * @param numVersions - number of versions to retrieve + * @return value for specified row/column + * @throws IOException + */ + public Cell[] get(final String row, final String column, int numVersions) + throws IOException { + return get(Bytes.toBytes(row), Bytes.toBytes(column), numVersions); + } + + /** + * Get a single value for the specified row and column + * + * @param row row key + * @param column column name + * @return value for specified row/column + * @throws IOException + */ + public Cell get(final byte [] row, final byte [] column) + throws IOException { + return connection.getRegionServerWithRetries( + new ServerCallable(connection, tableName, row) { + public Cell call() throws IOException { + return server.get(location.getRegionInfo().getRegionName(), row, + column); + } + } + ); + } + + /** + * Get the specified number of versions of the specified row and column + * @param row row key + * @param column column name + * @param numVersions number of versions to retrieve + * @return Array of Cells. + * @throws IOException + */ + public Cell[] get(final byte [] row, final byte [] column, + final int numVersions) + throws IOException { + return connection.getRegionServerWithRetries( + new ServerCallable(connection, tableName, row) { + public Cell[] call() throws IOException { + return server.get(location.getRegionInfo().getRegionName(), row, + column, numVersions); + } + } + ); + } + + /** + * Get the specified number of versions of the specified row and column with + * the specified timestamp. + * + * @param row - row key + * @param column - column name + * @param timestamp - timestamp + * @param numVersions - number of versions to retrieve + * @return - array of values that match the above criteria + * @throws IOException + */ + public Cell[] get(final Text row, final Text column, + final long timestamp, final int numVersions) + throws IOException { + return get(row.getBytes(), column.getBytes(), timestamp, numVersions); + } + + /** + * Get the specified number of versions of the specified row and column with + * the specified timestamp. + * + * @param row - row key + * @param column - column name + * @param timestamp - timestamp + * @param numVersions - number of versions to retrieve + * @return - array of values that match the above criteria + * @throws IOException + */ + public Cell[] get(final String row, final String column, + final long timestamp, final int numVersions) + throws IOException { + return get(Bytes.toBytes(row), Bytes.toBytes(column), timestamp, numVersions); + } + + /** + * Get the specified number of versions of the specified row and column with + * the specified timestamp. + * + * @param row - row key + * @param column - column name + * @param timestamp - timestamp + * @param numVersions - number of versions to retrieve + * @return - array of values that match the above criteria + * @throws IOException + */ + public Cell[] get(final byte [] row, final byte [] column, + final long timestamp, final int numVersions) + throws IOException { + Cell[] values = null; + values = connection.getRegionServerWithRetries( + new ServerCallable(connection, tableName, row) { + public Cell[] call() throws IOException { + return server.get(location.getRegionInfo().getRegionName(), row, + column, timestamp, numVersions); + } + } + ); + + if (values != null) { + ArrayList cellValues = new ArrayList(); + for (int i = 0 ; i < values.length; i++) { + cellValues.add(values[i]); + } + return cellValues.toArray(new Cell[values.length]); + } + return null; + } + + /** + * Get all the data for the specified row at the latest timestamp + * + * @param row row key + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final Text row) throws IOException { + return getRow(row.getBytes()); + } + + /** + * Get all the data for the specified row at the latest timestamp + * + * @param row row key + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final String row) throws IOException { + return getRow(Bytes.toBytes(row)); + } + + /** + * Get all the data for the specified row at the latest timestamp + * + * @param row row key + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final byte [] row) throws IOException { + return getRow(row, HConstants.LATEST_TIMESTAMP); + } + + /** + * Get all the data for the specified row at a specified timestamp + * + * @param row row key + * @param ts timestamp + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final Text row, final long ts) + throws IOException { + return getRow(row.getBytes(), ts); + } + + /** + * Get all the data for the specified row at a specified timestamp + * + * @param row row key + * @param ts timestamp + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final String row, final long ts) + throws IOException { + return getRow(Bytes.toBytes(row), ts); + } + + /** + * Get all the data for the specified row at a specified timestamp + * + * @param row row key + * @param ts timestamp + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final byte [] row, final long ts) + throws IOException { + return connection.getRegionServerWithRetries( + new ServerCallable(connection, tableName, row) { + public RowResult call() throws IOException { + return server.getRow(location.getRegionInfo().getRegionName(), row, + ts); + } + } + ); + } + + /** + * Get selected columns for the specified row at the latest timestamp + * + * @param row row key + * @param columns Array of column names and families you want to retrieve. + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final Text row, final Text[] columns) + throws IOException { + return getRow(row.getBytes(), Bytes.toByteArrays(columns)); + } + + /** + * Get selected columns for the specified row at the latest timestamp + * + * @param row row key + * @param columns Array of column names and families you want to retrieve. + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final String row, final String [] columns) + throws IOException { + return getRow(Bytes.toBytes(row), Bytes.toByteArrays(columns)); + } + + /** + * Get selected columns for the specified row at the latest timestamp + * + * @param row row key + * @param columns Array of column names and families you want to retrieve. + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final byte [] row, final byte [][] columns) + throws IOException { + return getRow(row, columns, HConstants.LATEST_TIMESTAMP); + } + + /** + * Get selected columns for the specified row at a specified timestamp + * + * @param row row key + * @param columns Array of column names and families you want to retrieve. + * @param ts timestamp + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final Text row, final Text [] columns, + final long ts) + throws IOException { + return getRow(row.getBytes(), Bytes.toByteArrays(columns), ts); + } + + /** + * Get selected columns for the specified row at a specified timestamp + * + * @param row row key + * @param columns Array of column names and families you want to retrieve. + * @param ts timestamp + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final String row, final String [] columns, + final long ts) + throws IOException { + return getRow(Bytes.toBytes(row), Bytes.toByteArrays(columns), ts); + } + + /** + * Get selected columns for the specified row at a specified timestamp + * + * @param row row key + * @param columns Array of column names and families you want to retrieve. + * @param ts timestamp + * @return RowResult is empty if row does not exist. + * @throws IOException + */ + public RowResult getRow(final byte [] row, final byte [][] columns, + final long ts) + throws IOException { + return connection.getRegionServerWithRetries( + new ServerCallable(connection, tableName, row) { + public RowResult call() throws IOException { + return server.getRow(location.getRegionInfo().getRegionName(), row, + columns, ts); + } + } + ); + } + + /** + * Get a scanner on the current table starting at first row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final Text [] columns) + throws IOException { + return getScanner(Bytes.toByteArrays(columns), HConstants.EMPTY_START_ROW); + } + + /** + * Get a scanner on the current table starting at first row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final String [] columns) + throws IOException { + return getScanner(Bytes.toByteArrays(columns), HConstants.EMPTY_START_ROW); + } + + /** + * Get a scanner on the current table starting at the specified row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final Text [] columns, final Text startRow) + throws IOException { + return getScanner(Bytes.toByteArrays(columns), startRow.getBytes()); + } + + /** + * Get a scanner on the current table starting at the specified row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final String [] columns, final String startRow) + throws IOException { + return getScanner(Bytes.toByteArrays(columns), Bytes.toBytes(startRow)); + } + + /** + * Get a scanner on the current table starting at first row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final byte[][] columns) + throws IOException { + return getScanner(columns, HConstants.EMPTY_START_ROW, + HConstants.LATEST_TIMESTAMP, null); + } + + /** + * Get a scanner on the current table starting at the specified row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final byte[][] columns, final byte [] startRow) + throws IOException { + return getScanner(columns, startRow, HConstants.LATEST_TIMESTAMP, null); + } + + /** + * Get a scanner on the current table starting at the specified row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @param timestamp only return results whose timestamp <= this value + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final byte[][] columns, final byte [] startRow, + long timestamp) + throws IOException { + return getScanner(columns, startRow, timestamp, null); + } + + /** + * Get a scanner on the current table starting at the specified row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @param filter a row filter using row-key regexp and/or column data filter. + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final byte[][] columns, final byte [] startRow, + RowFilterInterface filter) + throws IOException { + return getScanner(columns, startRow, HConstants.LATEST_TIMESTAMP, filter); + } + + /** + * Get a scanner on the current table starting at the specified row and + * ending just before stopRow. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @param stopRow Row to stop scanning on. Once we hit this row we stop + * returning values; i.e. we return the row before this one but not the + * stopRow itself. + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final byte [][] columns, + final byte [] startRow, final byte [] stopRow) + throws IOException { + return getScanner(columns, startRow, stopRow, + HConstants.LATEST_TIMESTAMP); + } + + /** + * Get a scanner on the current table starting at the specified row and + * ending just before stopRow. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @param stopRow Row to stop scanning on. Once we hit this row we stop + * returning values; i.e. we return the row before this one but not the + * stopRow itself. + * @param timestamp only return results whose timestamp <= this value + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final Text[] columns, + final Text startRow, final Text stopRow, final long timestamp) + throws IOException { + return getScanner(Bytes.toByteArrays(columns), startRow.getBytes(), + stopRow.getBytes(), timestamp); + } + + /** + * Get a scanner on the current table starting at the specified row and + * ending just before stopRow. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @param stopRow Row to stop scanning on. Once we hit this row we stop + * returning values; i.e. we return the row before this one but not the + * stopRow itself. + * @param timestamp only return results whose timestamp <= this value + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final String [] columns, + final String startRow, final String stopRow, final long timestamp) + throws IOException { + return getScanner(Bytes.toByteArrays(columns), Bytes.toBytes(startRow), + Bytes.toBytes(stopRow), timestamp); + } + + /** + * Get a scanner on the current table starting at the specified row and + * ending just before stopRow. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @param stopRow Row to stop scanning on. Once we hit this row we stop + * returning values; i.e. we return the row before this one but not the + * stopRow itself. + * @param timestamp only return results whose timestamp <= this value + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final byte [][] columns, + final byte [] startRow, final byte [] stopRow, final long timestamp) + throws IOException { + return getScanner(columns, startRow, timestamp, + new WhileMatchRowFilter(new StopRowFilter(stopRow))); + } + + /** + * Get a scanner on the current table starting at the specified row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @param timestamp only return results whose timestamp <= this value + * @param filter a row filter using row-key regexp and/or column data filter. + * @return scanner + * @throws IOException + */ + public Scanner getScanner(Text[] columns, + Text startRow, long timestamp, RowFilterInterface filter) + throws IOException { + return getScanner(Bytes.toByteArrays(columns), startRow.getBytes(), + timestamp, filter); + } + + /** + * Get a scanner on the current table starting at the specified row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @param timestamp only return results whose timestamp <= this value + * @param filter a row filter using row-key regexp and/or column data filter. + * @return scanner + * @throws IOException + */ + public Scanner getScanner(String[] columns, + String startRow, long timestamp, RowFilterInterface filter) + throws IOException { + return getScanner(Bytes.toByteArrays(columns), Bytes.toBytes(startRow), + timestamp, filter); + } + + /** + * Get a scanner on the current table starting at the specified row. + * Return the specified columns. + * + * @param columns columns to scan. If column name is a column family, all + * columns of the specified column family are returned. Its also possible + * to pass a regex in the column qualifier. A column qualifier is judged to + * be a regex if it contains at least one of the following characters: + * \+|^&*$[]]}{)(. + * @param startRow starting row in table to scan + * @param timestamp only return results whose timestamp <= this value + * @param filter a row filter using row-key regexp and/or column data filter. + * @return scanner + * @throws IOException + */ + public Scanner getScanner(final byte [][] columns, + final byte [] startRow, long timestamp, RowFilterInterface filter) + throws IOException { + return new ClientScanner(columns, startRow, timestamp, filter); + } + + /** + * Completely delete the row's cells. + * + * @param row Key of the row you want to completely delete. + * @throws IOException + */ + public void deleteAll(final byte [] row) throws IOException { + deleteAll(row, null); + } + + /** + * Completely delete the row's cells. + * + * @param row Key of the row you want to completely delete. + * @throws IOException + */ + public void deleteAll(final Text row) throws IOException { + deleteAll(row, null); + } + + /** + * Completely delete the row's cells. + * + * @param row Key of the row you want to completely delete. + * @throws IOException + */ + public void deleteAll(final String row) throws IOException { + deleteAll(row, null); + } + + /** + * Completely delete the row's cells. + * + * @param row Key of the row you want to completely delete. + * @param column column to be deleted + * @throws IOException + */ + public void deleteAll(final byte [] row, final byte [] column) + throws IOException { + deleteAll(row, column, HConstants.LATEST_TIMESTAMP); + } + + /** + * Completely delete the row's cells. + * + * @param row Key of the row you want to completely delete. + * @param ts Delete all cells of the same timestamp or older. + * @throws IOException + */ + public void deleteAll(final byte [] row, final long ts) + throws IOException { + deleteAll(row, null, ts); + } + + /** + * Completely delete the row's cells. + * + * @param row Key of the row you want to completely delete. + * @param ts Delete all cells of the same timestamp or older. + * @throws IOException + */ + public void deleteAll(final String row, final long ts) + throws IOException { + deleteAll(row, null, ts); + } + + /** + * Completely delete the row's cells. + * + * @param row Key of the row you want to completely delete. + * @param ts Delete all cells of the same timestamp or older. + * @throws IOException + */ + public void deleteAll(final Text row, final long ts) + throws IOException { + deleteAll(row, null, ts); + } + + /** + * Delete all cells that match the passed row and column. + * @param row Row to update + * @param column name of column whose value is to be deleted + * @throws IOException + */ + public void deleteAll(final Text row, final Text column) throws IOException { + deleteAll(row, column, HConstants.LATEST_TIMESTAMP); + } + + /** + * Delete all cells that match the passed row and column. + * @param row Row to update + * @param column name of column whose value is to be deleted + * @throws IOException + */ + public void deleteAll(final String row, final String column) + throws IOException { + deleteAll(row, column, HConstants.LATEST_TIMESTAMP); + } + + /** + * Delete all cells that match the passed row and column and whose + * timestamp is equal-to or older than the passed timestamp. + * @param row Row to update + * @param column name of column whose value is to be deleted + * @param ts Delete all cells of the same timestamp or older. + * @throws IOException + */ + public void deleteAll(final Text row, final Text column, final long ts) + throws IOException { + deleteAll(row.getBytes(), column.getBytes(), ts); + } + + /** + * Delete all cells that match the passed row and column and whose + * timestamp is equal-to or older than the passed timestamp. + * @param row Row to update + * @param column name of column whose value is to be deleted + * @param ts Delete all cells of the same timestamp or older. + * @throws IOException + */ + public void deleteAll(final String row, final String column, final long ts) + throws IOException { + deleteAll(Bytes.toBytes(row), + column != null? Bytes.toBytes(column): null, ts); + } + + /** + * Delete all cells that match the passed row and column and whose + * timestamp is equal-to or older than the passed timestamp. + * @param row Row to update + * @param column name of column whose value is to be deleted + * @param ts Delete all cells of the same timestamp or older. + * @throws IOException + */ + public void deleteAll(final byte [] row, final byte [] column, final long ts) + throws IOException { + connection.getRegionServerWithRetries( + new ServerCallable(connection, tableName, row) { + public Boolean call() throws IOException { + if (column != null) { + this.server.deleteAll(location.getRegionInfo().getRegionName(), + row, column, ts); + } else { + this.server.deleteAll(location.getRegionInfo().getRegionName(), + row, ts); + } + return null; + } + } + ); + } + + /** + * Delete all cells for a row with matching column family at all timestamps. + * + * @param row The row to operate on + * @param family The column family to match + * @param timestamp Timestamp to match + * @throws IOException + */ + public void deleteFamily(final Text row, final Text family, + final long timestamp) + throws IOException{ + deleteFamily(row.getBytes(), family.getBytes(), timestamp); + } + + /** + * Delete all cells for a row with matching column family at all timestamps. + * + * @param row The row to operate on + * @param family The column family to match + * @param timestamp Timestamp to match + * @throws IOException + */ + public void deleteFamily(final String row, final String family, + final long timestamp) + throws IOException{ + deleteFamily(Bytes.toBytes(row), Bytes.toBytes(family), timestamp); + } + + /** + * Delete all cells for a row with matching column family with timestamps + * less than or equal to timestamp. + * + * @param row The row to operate on + * @param family The column family to match + * @param timestamp Timestamp to match + * @throws IOException + */ + public void deleteFamily(final byte [] row, final byte [] family, + final long timestamp) + throws IOException { + connection.getRegionServerWithRetries( + new ServerCallable(connection, tableName, row) { + public Boolean call() throws IOException { + server.deleteFamily(location.getRegionInfo().getRegionName(), row, + family, timestamp); + return null; + } + } + ); + } + + /** + * Commit a BatchUpdate to the table. + * @param batchUpdate + * @throws IOException + */ + public synchronized void commit(final BatchUpdate batchUpdate) + throws IOException { + connection.getRegionServerWithRetries( + new ServerCallable(connection, tableName, batchUpdate.getRow()) { + public Boolean call() throws IOException { + server.batchUpdate(location.getRegionInfo().getRegionName(), + batchUpdate); + return null; + } + } + ); + } + + /** + * Commit a RowsBatchUpdate to the table. + * @param batchUpdate + * @throws IOException + */ [... 212 lines stripped ...]