package hbase.operations; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Set; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellScanner; import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; 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.Result; import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.filter.FuzzyRowFilter; import org.apache.hadoop.hbase.regionserver.BloomType; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Pair; import org.apache.log4j.Logger; /** * Hbase Operations for version 1.0 * * @author quh * */ public final class HBaseOperations { private static final HBaseOperations instance; public static final List<String> tableNames = Arrays.asList("DisLTR_Cache", "DisLTR_UserResults", "LDADC_EntToSf", "LDADC_SFToEnt", "LDADC_Context", "DBPEDIA_CatToEnts", "DBPEDIA_EntityFacts"); private Date date; private Connection conn; static { try { instance = new HBaseOperations(); } catch (Exception e) { throw new RuntimeException( "An error occurred during initalization", e); } } public static HBaseOperations getInstance() { return instance; } /** * Constructor Creates a Configuration */ private HBaseOperations() { super(); this.date = new Date(); Configuration conf = HBaseConfiguration.create(); conf.set("hbase.zookeeper.quorum", "localhost"); try { conn = ConnectionFactory.createConnection(conf); } catch (IOException e) { throw new RuntimeException( "An error occurred during initalization", e); } initializeTablesPerDefault(); } /** * Add a new Record in the Hbase table * * @param tableName * Name of the table * @param rowKey * Rowkey * @param family * HBase family * @param qualifier * HBase qualifier * @param value * The value to store * @throws IOException * Nothing happens! */ public void addRecord(final String tableName, final String rowKey, final String family, final String qualifier, final String value) throws IOException { final Put put = new Put(Bytes.toBytes(rowKey)); Cell cell = CellUtil.createCell(Bytes.toBytes(rowKey), Bytes.toBytes(family), Bytes.toBytes(qualifier), date.getTime(), KeyValue.Type.Put.getCode(), Bytes.toBytes(value)); put.add(cell); Table table = null; try { table = conn.getTable(TableName.valueOf(tableName)); table.put(put); } catch (IOException e) { e.printStackTrace(); Logger.getRootLogger().error( "Error while fetching HBase table " + tableName + ". Entry not added!", e); } finally { if (table != null) { try { table.close(); } catch (IOException e) { e.printStackTrace(); Logger.getRootLogger().error( "Error IOException while closing HBase table", e); } } } } /** * Fast Version of addRecord. If a huge number of addrecords must be * performed we fetch the table once by calling getTable. All records are * stored without closing the table object. The user must close table object * manually with closeTable(); * * * @param table * The already opened table object * @param rowKey * Rowkey * @param family * Hbase family * @param qualifier * HBase Qualifier * @param value * The value to store * @throws IOException * Nothing happens! */ public void addRecordFast(Table table, final String rowKey, final String family, final String qualifier, final String value) throws IOException { final Put put = new Put(Bytes.toBytes(rowKey)); put.add(CellUtil.createCell(Bytes.toBytes(rowKey), Bytes.toBytes(family), Bytes.toBytes(qualifier), date.getTime(), KeyValue.Type.Put.getCode(), Bytes.toBytes(value))); table.put(put); } /** * Fetches a table by name. * * @param tableName * The tableName to fetch. * @return Table. Return null of table is not available */ public Table getTable(String tableName) { Table table = null; try { table = conn.getTable(TableName.valueOf(tableName)); } catch (IOException e) { e.printStackTrace(); Logger.getRootLogger().error( "Error while fetching HBase table " + tableName + ". Entry not added!", e); } return table; } /** * Closes a table instance * * @param table * Table to close */ public void closeTable(Table table) { if (table != null) { try { table.close(); } catch (IOException e) { e.printStackTrace(); Logger.getRootLogger().error( "Error IOException while closing HBase table", e); } } } /** * Adds a complete put object to the table * * * @param tableName * The name of the table * @param put * An already preconfigured Put object * @throws IOException * Nothing will be done */ public void addCompleteEntry(final String tableName, final Put put) { Table table = null; try { table = conn.getTable(TableName.valueOf(tableName)); table.put(put); } catch (IOException e) { Logger.getRootLogger().error( "Error while fetching HBase table " + tableName + ". Entry not added!", e); } finally { if (table != null) { try { table.close(); } catch (IOException e) { Logger.getRootLogger().error( "Error IOException while closing HBase table", e); } } } } /** * Checks the amount if available versions of a specific rowkey. For this * purpose we count the number of different row spellings with the row * prefix wildcardRow * * @param tableName * The name of the table to search * @param wildcardRow * The row prefix which must match with the rownames * @param hashLength * Length of a default rowkey without version * @return The amount of available versions of row wildcardRow * * Return 0 after an IOException * * @throws IOException */ public int getAmountRowVersions(final String tableName, final String wildcardRow, final int hashLength) { int result = 0; final String wildcRow = transformRowKey(wildcardRow, hashLength); final Scan scan = new Scan(); scan.setFilter(new FuzzyRowFilter(Arrays .asList(new Pair<byte[], byte[]>(Bytes.toBytesBinary(wildcRow + "_\\x00\\x00"), new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 })))); Table table = null; try { table = conn.getTable(TableName.valueOf(tableName)); final ResultScanner res = table.getScanner(scan); for (Result r = res.next(); r != null; r = res.next()) { result++; } } catch (IOException e) { Logger.getRootLogger().error( "Error while fetching HBase table " + tableName + ". Entry not added!", e); } finally { if (table != null) { try { table.close(); } catch (IOException e) { Logger.getRootLogger().error( "Error IOException while closing HBase table", e); } } } return result; } /** * Remove an Hbase table entry * * @param tableName * Name of the Hbase table * @param wildCardRowKey * The rowkey without standard length and without version * @param family * HBase family * @param qualifier * HBase qualifier * @param ver * The highest version of the entry to delete * @param length * Length of a default rowkey without version * @return The value of the deleted entry. * * Returns null if an IOException occurs. * * @throws IOException */ public String removeHbaseEntry(final String tableName, final String wildCardRowKey, final String family, final String qualifier, final String ver, final int length) throws IOException { String result = null; final String wildcRowKey = transformRowKey(wildCardRowKey, length); Table table = null; try { table = conn.getTable(TableName.valueOf(tableName)); } catch (IOException e) { Logger.getRootLogger().error( "Error while fetching HBase table " + tableName + ". Entry not added!", e); } if (table != null) { int version = Integer.valueOf(ver); while (version > 0) { final String currentRowKey = wildcRowKey + "_" + transformRowKey(String.valueOf(version), 2); final Get get = new Get(currentRowKey.getBytes()); get.addFamily("data".getBytes()); final Scan scan = new Scan(get); final ResultScanner resultScanner = table.getScanner(scan); // Result size should be 1 final Result res = resultScanner.next(); if (res.containsColumn(family.getBytes(), qualifier.getBytes())) { result = Bytes.toString(res.getValue(family.getBytes(), qualifier.getBytes())); final List<Delete> list = new ArrayList<Delete>(); final Delete del = new Delete(res.getRow()); del.addColumn(family.getBytes(), qualifier.getBytes()); list.add(del); table.delete(del); break; } else { version--; } } try { table.close(); } catch (IOException e) { Logger.getRootLogger().error( "Error IOException while closing HBase table", e); } } return result; } /** * Method adds 0 values ahead of the string to provide a standard length * * @param rowKey * The input string to enrich * @param length * The length * @return The new String value */ public String transformRowKey(final String rowKey, final int length) { final Integer val = Integer.valueOf(rowKey); if (val < 0) { String rowK = rowKey.replace("-", ""); while (rowK.length() < (length - 1)) { final StringBuffer buffer = new StringBuffer("0"); buffer.append(rowKey); rowK = buffer.toString(); } final StringBuffer buffer = new StringBuffer("-"); buffer.append(rowK); rowK = buffer.toString(); } else { String rowK = rowKey; while (rowK.length() < length) { final StringBuffer buffer = new StringBuffer("0"); buffer.append(rowKey); rowK = buffer.toString(); } } return rowKey; } /** * Get all values of a specific row of a specific table * * If an IOException occurs, the result set is empty or at least incomplete */ public void getRow(String tableName, String rowKey, String family, Set<String> res, int limit) throws IOException { Table table = null; try { table = conn.getTable(TableName.valueOf(tableName)); } catch (IOException e) { Logger.getRootLogger().error( "Error while fetching HBase table " + tableName + ". Entry not added!", e); } if (table == null) { return; } Get get = new Get(rowKey.getBytes()); if (limit != 0) { get.setMaxResultsPerColumnFamily(limit); } get.addFamily(Bytes.toBytes(family)); Result rs = table.get(get); CellScanner scanner = rs.cellScanner(); while (scanner.advance()) { Cell cell = scanner.current(); String s = new String(CellUtil.cloneValue(cell)); if (!s.startsWith(".") && !s.startsWith(",") && s.length() > 2) { res.add(s); } } try { table.close(); } catch (IOException e) { Logger.getRootLogger().error( "Error IOException while closing HBase table", e); } } public Result[] getMultipleRow(final String tableName, final List<Get> gets) { Table table = null; Result[] res = null; try { table = conn.getTable(TableName.valueOf(tableName)); } catch (IOException e) { Logger.getRootLogger().error( "Error while fetching HBase table " + tableName + ". Entry not added!", e); } if (table != null) { try { long time = System.currentTimeMillis(); res = table.get(gets); System.out.println("Fetchtime: "+(System.currentTimeMillis() - time)); } catch (IOException e) { e.printStackTrace(); } } return res; } /** * Deletes all entries of row with id rowkey * * * @param tableName * the respective tablename * @param rowKey * the respective rowkey * @throws IOException * Nothing will be deleted */ public void deleteIDRow(String tableName, String rowKey) throws IOException { Table table = null; try { table = conn.getTable(TableName.valueOf(tableName)); Delete del = new Delete(rowKey.getBytes()); table.delete(del); } catch (IOException e) { Logger.getRootLogger().error( "Error while fetching HBase table " + tableName + ". Entry not added!", e); } finally { if (table != null) { try { table.close(); } catch (IOException e) { Logger.getRootLogger().error( "Error IOException while closing HBase table", e); } } } } private void initializeTablesPerDefault() { for (String tableName : tableNames) { Admin admin = null; try { admin = conn.getAdmin(); if (!admin.tableExists(TableName.valueOf(tableName))) { admin.createTable(createTableObject(tableName)); } } catch (IOException e) { e.printStackTrace(); Logger.getRootLogger().error( "Error IOException while initializing HBase tables", e); } finally { if (admin != null) { try { admin.close(); } catch (IOException e) { Logger.getRootLogger().error( "Error IOException while closing HBase admin", e); } } } } } private HTableDescriptor createTableObject(final String tableName) { final HTableDescriptor tabledesc = new HTableDescriptor( TableName.valueOf(tableName)); HColumnDescriptor descriptor = new HColumnDescriptor("data"); descriptor.setBloomFilterType(BloomType.ROWCOL); tabledesc.addFamily(descriptor); return tabledesc; } }