package com.opower.updater.admin; import com.google.common.io.Closeables; import com.opower.updater.LayoutUpdate; import org.apache.hadoop.hbase.HConstants; import org.kiji.schema.EntityId; import org.kiji.schema.Kiji; import org.kiji.schema.KijiDataRequest; import org.kiji.schema.KijiDataRequestBuilder; import org.kiji.schema.KijiRowData; import org.kiji.schema.KijiTable; import org.kiji.schema.KijiTableReader; import org.kiji.schema.KijiTableWriter; import java.io.IOException; import java.util.Collection; import java.util.Map; /** * Kiji based implementation of {@link com.opower.updater.admin.LayoutUpdateTable}. * <p/> * The method {@link KijiLayoutUpdateTable#newInstance(org.kiji.schema.Kiji)} must be used to * create a new instance. * * @author felix.trepanier */ public final class KijiLayoutUpdateTable implements LayoutUpdateTable { private static final KijiDataRequest LATEST_UPDATE_REQUEST = KijiDataRequest.create( UPDATE_LOG_FAMILY_NAME, LAYOUT_UPDATE_COLUMN_NAME); private static final KijiDataRequest FULL_TABLE_HISTORY_REQUEST = KijiDataRequest.builder() .addColumns(KijiDataRequestBuilder.ColumnsDef.create() .withMaxVersions(HConstants.ALL_VERSIONS) .add(UPDATE_LOG_FAMILY_NAME, LAYOUT_UPDATE_COLUMN_NAME)).build(); private final KijiTable layoutUpdateTable; private final KijiTableReader reader; private final KijiTableWriter writer; /** * Create an instance of the {@link KijiLayoutUpdateTable}. * * @param kiji The kiji instance. * @return A new instance of {@link KijiLayoutUpdateTable} * @throws IOException */ public static KijiLayoutUpdateTable newInstance(Kiji kiji) throws IOException { return new KijiLayoutUpdateTable(kiji.openTable(TABLE_NAME)); } private KijiLayoutUpdateTable(KijiTable layoutUpdateTable) { this.layoutUpdateTable = layoutUpdateTable; this.reader = layoutUpdateTable.openTableReader(); this.writer = layoutUpdateTable.openTableWriter(); } @Override public Integer getLastUpdateIdForTable(String tableName) throws IOException { KijiRowData data = reader.get(createEntityId(tableName), LATEST_UPDATE_REQUEST); LayoutUpdate latestUpdate = data.getMostRecentValue(UPDATE_LOG_FAMILY_NAME, LAYOUT_UPDATE_COLUMN_NAME); return latestUpdate == null ? null : latestUpdate.getUpdateId(); } @Override public void insertLayoutUpdate(String tableName, LayoutUpdate layoutUpdate) throws IOException { writer.put(createEntityId(tableName), UPDATE_LOG_FAMILY_NAME, LAYOUT_UPDATE_COLUMN_NAME, layoutUpdate); writer.flush(); } @Override public Collection<LayoutUpdate> getTableHistory(String tableName, Integer numberOfVersions) throws IOException { KijiRowData data = reader.get(createEntityId(tableName), buildKijiDataRequest(numberOfVersions)); Map<Long, LayoutUpdate> rows = data.getValues(UPDATE_LOG_FAMILY_NAME, LAYOUT_UPDATE_COLUMN_NAME); return rows.values(); } @Override public void close() throws IOException { Closeables.close(reader, true); Closeables.close(writer, true); layoutUpdateTable.release(); } private EntityId createEntityId(String tableName) { return layoutUpdateTable.getEntityId(tableName); } private KijiDataRequest buildKijiDataRequest(Integer numberOfVersions) throws IOException { if (numberOfVersions == null) { return FULL_TABLE_HISTORY_REQUEST; } else { return KijiDataRequest.builder() .addColumns(KijiDataRequestBuilder.ColumnsDef.create() .withMaxVersions(numberOfVersions) .add(UPDATE_LOG_FAMILY_NAME, LAYOUT_UPDATE_COLUMN_NAME)).build(); } } }