/** * */ package mil.nga.giat.geowave.datastore.hbase; import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.RowMutations; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.index.StringUtils; import mil.nga.giat.geowave.core.store.adapter.DataAdapter; import mil.nga.giat.geowave.core.store.adapter.WritableDataAdapter; import mil.nga.giat.geowave.core.store.base.DataStoreEntryInfo; import mil.nga.giat.geowave.core.store.callback.IngestCallback; import mil.nga.giat.geowave.core.store.data.VisibilityWriter; import mil.nga.giat.geowave.core.store.index.DataStoreIndexWriter; import mil.nga.giat.geowave.core.store.index.PrimaryIndex; import mil.nga.giat.geowave.core.store.index.SecondaryIndex; import mil.nga.giat.geowave.core.store.index.SecondaryIndexDataAdapter; import mil.nga.giat.geowave.core.store.index.SecondaryIndexUtils; import mil.nga.giat.geowave.datastore.hbase.io.HBaseWriter; import mil.nga.giat.geowave.datastore.hbase.operations.BasicHBaseOperations; import mil.nga.giat.geowave.datastore.hbase.operations.config.HBaseOptions; import mil.nga.giat.geowave.datastore.hbase.util.HBaseUtils; public class HBaseIndexWriter<T> extends DataStoreIndexWriter<T, RowMutations> { private final static Logger LOGGER = LoggerFactory.getLogger(HBaseIndexWriter.class); private final BasicHBaseOperations operations; protected final HBaseOptions options; public HBaseIndexWriter( final DataAdapter<T> adapter, final PrimaryIndex index, final BasicHBaseOperations operations, final HBaseOptions options, final IngestCallback<T> callback, final Closeable closable ) { super( adapter, index, operations, options, callback, closable); this.operations = operations; this.options = options; initializeSecondaryIndexTables(); } @Override protected DataStoreEntryInfo getEntryInfo( T entry, VisibilityWriter<T> visibilityWriter ) { return HBaseUtils.write( (WritableDataAdapter<T>) adapter, index, entry, (HBaseWriter) writer, visibilityWriter); } @Override protected synchronized void closeInternal() { if (writer != null) { try { writer.close(); writer = null; } catch (IOException e) { LOGGER.warn( "Unable to close HBase writer", e); } } } protected synchronized void ensureOpen() throws IOException { if (writer == null) { try { writer = operations.createWriter( StringUtils.stringFromBinary(index.getId().getBytes()), new String[] { adapter.getAdapterId().getString() }, options.isCreateTable(), index.getIndexStrategy().getNaturalSplits()); if (writer == null) { throw new IOException( "Create writer failed without an exception"); } } catch (final IOException e) { LOGGER.error( "Unable to open writer", e); throw (e); } } } private void initializeSecondaryIndexTables() { if (adapter instanceof SecondaryIndexDataAdapter<?>) { final Map<String, List<ByteArrayId>> tableToFieldMap = new HashMap<>(); final List<SecondaryIndex<T>> secondaryIndices = ((SecondaryIndexDataAdapter<T>) adapter) .getSupportedSecondaryIndices(); // aggregate fields for each unique table for (final SecondaryIndex<T> secondaryIndex : secondaryIndices) { final String tableName = operations.getQualifiedTableName(secondaryIndex.getId().getString()); if (tableToFieldMap.containsKey(tableName)) { final List<ByteArrayId> fieldIds = tableToFieldMap.get(tableName); fieldIds.add(secondaryIndex.getFieldId()); } else { final List<ByteArrayId> fieldIds = new ArrayList<>(); fieldIds.add(secondaryIndex.getFieldId()); tableToFieldMap.put( tableName, fieldIds); } } // ensure each table is configured for the appropriate column // families for (final Entry<String, List<ByteArrayId>> entry : tableToFieldMap.entrySet()) { final String table = entry.getKey(); final List<ByteArrayId> fieldIds = entry.getValue(); final String[] columnFamilies = new String[fieldIds.size()]; int idx = 0; for (final ByteArrayId fieldId : fieldIds) { final byte[] cfBytes = SecondaryIndexUtils.constructColumnFamily( adapter.getAdapterId(), fieldId); columnFamilies[idx++] = new ByteArrayId( cfBytes).getString(); } try { if (operations.tableExists(table)) { operations.addColumnFamiles( columnFamilies, table); } else { operations.createTable( columnFamilies, TableName.valueOf(table), null); } } catch (final IOException e) { LOGGER.error( "Unable to check if table " + table + " exists", e); } } } } }