All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.metamodel.hbase.HBaseClient Maven / Gradle / Ivy

The newest version!
/**
 * 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.metamodel.hbase;

import java.io.IOException;
import java.util.Set;

import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.metamodel.MetaModelException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class can perform client-operations on a HBase datastore
 */
final class HBaseClient {

    private static final Logger logger = LoggerFactory.getLogger(HBaseClient.class);

    private final Connection _connection;

    public HBaseClient(final Connection connection) {
        this._connection = connection;
    }

    /**
     * Insert a single row of values to a HBase table.
     * @param tableName
     * @param columns
     * @param values
     * @throws IllegalArgumentException when any parameter is null or the indexOfIdColumn is impossible
     * @throws MetaModelException when no ID-column is found.
     * @throws MetaModelException when a {@link IOException} is caught
     */
    public void insertRow(final String tableName, final HBaseColumn[] columns, final Object[] values,
            final int indexOfIdColumn) {
        if (tableName == null || columns == null || values == null || indexOfIdColumn >= values.length
                || values[indexOfIdColumn] == null) {
            throw new IllegalArgumentException(
                    "Can't insert a row without having (correct) tableName, columns, values or indexOfIdColumn");
        }
        if (columns.length != values.length) {
            throw new IllegalArgumentException("The amount of columns don't match the amount of values");
        }
        try (final Table table = _connection.getTable(TableName.valueOf(tableName))) {
            // Create a put with the values of indexOfIdColumn as rowkey
            final Put put = new Put(getValueAsByteArray(values[indexOfIdColumn]));

            // Add the other values to the put
            for (int i = 0; i < columns.length; i++) {
                if (i != indexOfIdColumn) {
                    // NullChecker is already forced within the HBaseColumn class
                    final byte[] columnFamily = Bytes.toBytes(columns[i].getColumnFamily());
                    // An HBaseColumn doesn't need a qualifier, this only works when the qualifier is empty (not
                    // null). Otherwise NullPointer exceptions will happen
                    byte[] qualifier = null;
                    if (columns[i].getQualifier() != null) {
                        qualifier = Bytes.toBytes(columns[i].getQualifier());
                    } else {
                        qualifier = Bytes.toBytes(new String(""));
                    }
                    final byte[] value = getValueAsByteArray(values[i]);
                    // A NULL value, doesn't get inserted in HBase
                    // TODO: Do we delete the cell (and therefore the qualifier) if the table get's updated by a NULL
                    // value?
                    if (value == null) {
                        logger.info("The value of column '{}' is null. This insertion is skipped", columns[i]
                                .getName());
                    } else {
                        put.addColumn(columnFamily, qualifier, value);
                    }
                }
            }
            // Add the put to the table
            table.put(put);
        } catch (IOException e) {
            throw new MetaModelException(e);
        }
    }

    /**
     * Delete 1 row based on the key
     * @param tableName
     * @param rowKey
     * @throws IllegalArgumentException when any parameter is null
     * @throws MetaModelException when a {@link IOException} is caught
     */
    public void deleteRow(final String tableName, final Object rowKey) {
        if (tableName == null || rowKey == null) {
            throw new IllegalArgumentException("Can't delete a row without having tableName or rowKey");
        }
        byte[] rowKeyAsByteArray = getValueAsByteArray(rowKey);
        if (rowKeyAsByteArray.length > 0) {
            try (final Table table = _connection.getTable(TableName.valueOf(tableName))) {
                if (rowExists(table, rowKeyAsByteArray)) {
                    table.delete(new Delete(rowKeyAsByteArray));
                } else {
                    logger.warn("Rowkey with value {} doesn't exist in the table", rowKey.toString());
                }
            } catch (IOException e) {
                throw new MetaModelException(e);
            }
        } else {
            throw new IllegalArgumentException("Can't delete a row without an empty rowKey.");
        }
    }

    /**
     * Checks in the HBase datastore if a row exists based on the key
     * @param table
     * @param rowKey
     * @return boolean
     * @throws IOException
     */
    private boolean rowExists(final Table table, final byte[] rowKey) throws IOException {
        final Get get = new Get(rowKey);
        return !table.get(get).isEmpty();
    }

    /**
     * Creates a HBase table based on a tableName and it's columnFamilies
     * @param tableName
     * @param columnFamilies
     * @throws IllegalArgumentException when any parameter is null
     * @throws MetaModelException when a {@link IOException} is caught
     */
    public void createTable(final String tableName, final Set columnFamilies) {
        checkTableAndColumnFamilies(tableName, columnFamilies);
        try (final Admin admin = _connection.getAdmin()) {
            final TableDescriptorBuilder tableBuilder = getTableDescriptorBuilder(tableName, columnFamilies);
            admin.createTable(tableBuilder.build());
        } catch (IOException e) {
            throw new MetaModelException(e);
        }
    }

    /**
     * Creates a HBase table based on a tableName and it's columnFamilies and splitKeys
     * @param tableName
     * @param columnFamilies
     * @param splitKeys
     * @throws IllegalArgumentException when any parameter is null
     * @throws MetaModelException when a {@link IOException} is caught
     */
    public void createTable(final String tableName, final Set columnFamilies, byte[][] splitKeys) {
        checkTableAndColumnFamilies(tableName, columnFamilies);
        try (final Admin admin = _connection.getAdmin()) {
            final TableDescriptorBuilder tableBuilder = getTableDescriptorBuilder(tableName, columnFamilies);
            admin.createTable(tableBuilder.build(),splitKeys);
        } catch (IOException e) {
            throw new MetaModelException(e);
        }
    }

    private TableDescriptorBuilder getTableDescriptorBuilder(String tableName, Set columnFamilies) {
        final TableName hBasetableName = TableName.valueOf(tableName);
        final TableDescriptorBuilder tableBuilder = TableDescriptorBuilder.newBuilder(hBasetableName);
        // Add all columnFamilies to the tableDescriptor.
        for (final String columnFamily : columnFamilies) {
            // The ID-column isn't needed because, it will automatically be created.
            if (!columnFamily.equals(HBaseDataContext.FIELD_ID)) {
                final ColumnFamilyDescriptor columnDescriptor = ColumnFamilyDescriptorBuilder.of(columnFamily);
                tableBuilder.setColumnFamily(columnDescriptor);
            }
        }
        return tableBuilder;
    }

    private void checkTableAndColumnFamilies(String tableName, Set columnFamilies) {
        if (tableName == null || columnFamilies == null || columnFamilies.isEmpty()) {
            throw new IllegalArgumentException("Can't create a table without having the tableName or columnFamilies");
        }
    }

    /**
     * Disable and drop a table from a HBase datastore
     * @param tableName
     * @throws IllegalArgumentException when tableName is null
     * @throws MetaModelException when a {@link IOException} is caught
     */
    public void dropTable(final String tableName) {
        if (tableName == null) {
            throw new IllegalArgumentException("Can't drop a table without having the tableName");
        }
        try (final Admin admin = _connection.getAdmin()) {
            final TableName hBasetableName = TableName.valueOf(tableName);
            admin.disableTable(hBasetableName); // A table must be disabled first, before it can be deleted
            admin.deleteTable(hBasetableName);
        } catch (IOException e) {
            throw new MetaModelException(e);
        }
    }

    /**
     * Converts a Object value into a byte array, if it isn't a byte array already
     * @param value
     * @return value as a byte array
     */
    private byte[] getValueAsByteArray(final Object value) {
        byte[] valueAsByteArray;
        if (value == null) {
            valueAsByteArray = null;
        } else if (value instanceof byte[]) {
            valueAsByteArray = (byte[]) value;
        } else {
            valueAsByteArray = Bytes.toBytes(value.toString());
        }
        return valueAsByteArray;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy