}
@Override
public void run() {
RegionScanner scanner = null;
PhoenixConnection conn = null;
if (inProgress.get() > 0) {
LOG.debug("New ScheduledBuildIndexTask skipped as there is already one running");
return;
}
try {
inProgress.incrementAndGet();
Scan scan = new Scan();
SingleColumnValueFilter filter = new SingleColumnValueFilter(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.INDEX_DISABLE_TIMESTAMP_BYTES,
CompareFilter.CompareOp.NOT_EQUAL, PDataType.LONG.toBytes(0L));
filter.setFilterIfMissing(true);
scan.setFilter(filter);
scan.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.TABLE_NAME_BYTES);
scan.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.DATA_TABLE_NAME_BYTES);
scan.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.INDEX_STATE_BYTES);
scan.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.INDEX_DISABLE_TIMESTAMP_BYTES);
boolean hasMore = false;
List<KeyValue> results = new ArrayList<KeyValue>();
scanner = this.env.getRegion().getScanner(scan);
do {
results.clear();
hasMore = scanner.next(results);
if (results.isEmpty()) break;
Result r = new Result(results);
byte[] disabledTimeStamp = r.getValue(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.INDEX_DISABLE_TIMESTAMP_BYTES);
Long disabledTimeStampVal = 0L;
if (disabledTimeStamp == null || disabledTimeStamp.length == 0) {
continue;
}
// disableTimeStamp has to be a positive value
disabledTimeStampVal = (Long) PDataType.LONG.toObject(disabledTimeStamp);
if (disabledTimeStampVal <= 0) {
continue;
}
byte[] dataTable = r.getValue(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.DATA_TABLE_NAME_BYTES);
byte[] indexStat = r.getValue(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.INDEX_STATE_BYTES);
if ((dataTable == null || dataTable.length == 0)
|| (indexStat == null || indexStat.length == 0)
|| ((Bytes.compareTo(PIndexState.DISABLE.getSerializedBytes(), indexStat) != 0)
&& (Bytes.compareTo(PIndexState.INACTIVE.getSerializedBytes(), indexStat) != 0))) {
// index has to be either in disable or inactive state
// data table name can't be empty
continue;
}
byte[][] rowKeyMetaData = new byte[3][];
SchemaUtil.getVarChars(r.getRow(), 3, rowKeyMetaData);
byte[] schemaName = rowKeyMetaData[PhoenixDatabaseMetaData.SCHEMA_NAME_INDEX];
byte[] indexTable = rowKeyMetaData[PhoenixDatabaseMetaData.TABLE_NAME_INDEX];
// validity check
if (indexTable == null || indexTable.length == 0) {
LOG.debug("Index rebuild has been skipped for row=" + r);
continue;
}
if (conn == null) {
conn = DriverManager.getConnection(getJdbcUrl()).unwrap(PhoenixConnection.class);
}
String dataTableFullName = SchemaUtil.getTableName(schemaName, dataTable);
String indexTableFullName = SchemaUtil.getTableName(schemaName, indexTable);
PTable dataPTable = PhoenixRuntime.getTable(conn, dataTableFullName);
PTable indexPTable = PhoenixRuntime.getTable(conn, indexTableFullName);
if (!MetaDataUtil.tableRegionsOnline(this.env.getConfiguration(), indexPTable)) {
LOG.debug("Index rebuild has been skipped because not all regions of index table="
+ indexPTable.getName() + " are online.");
continue;
}
MetaDataClient client = new MetaDataClient(conn);
long overlapTime = env.getConfiguration().getLong(
QueryServices.INDEX_FAILURE_HANDLING_REBUILD_OVERLAP_TIME_ATTRIB,
QueryServicesOptions.DEFAULT_INDEX_FAILURE_HANDLING_REBUILD_OVERLAP_TIME);
long timeStamp = Math.max(0, disabledTimeStampVal - overlapTime);
LOG.info("Starting to build index=" + indexPTable.getName() + " from timestamp=" + timeStamp);
client.buildPartialIndexFromTimeStamp(indexPTable, new TableRef(dataPTable, Long.MAX_VALUE, timeStamp));
} while (hasMore);
} catch (Throwable t) {
LOG.warn("ScheduledBuildIndexTask failed!", t);
} finally {
inProgress.decrementAndGet();
if (scanner != null) {
try {
scanner.close();
} catch (IOException ignored) {
LOG.debug("ScheduledBuildIndexTask can't close scanner.", ignored);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException ignored) {
LOG.debug("ScheduledBuildIndexTask can't close connection", ignored);
}
}
}