/*
* Licensed 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 com.facebook.presto.raptor.storage.organization;
import com.facebook.presto.raptor.metadata.ColumnInfo;
import com.facebook.presto.raptor.metadata.MetadataDao;
import com.facebook.presto.raptor.metadata.ShardInfo;
import com.facebook.presto.raptor.metadata.ShardManager;
import com.facebook.presto.raptor.metadata.TableColumn;
import com.facebook.presto.raptor.metadata.TableMetadata;
import com.google.common.base.Throwables;
import io.airlift.log.Logger;
import java.io.IOException;
import java.util.List;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.Set;
import java.util.UUID;
import static com.facebook.presto.spi.block.SortOrder.ASC_NULLS_FIRST;
import static java.util.Collections.nCopies;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
class OrganizationJob
implements Runnable
{
private static final Logger log = Logger.get(OrganizationJob.class);
private final MetadataDao metadataDao;
private final ShardManager shardManager;
private final ShardCompactor compactor;
private final OrganizationSet organizationSet;
public OrganizationJob(OrganizationSet organizationSet, MetadataDao metadataDao, ShardManager shardManager, ShardCompactor compactor)
{
this.metadataDao = requireNonNull(metadataDao, "metadataDao is null");
this.shardManager = requireNonNull(shardManager, "shardManager is null");
this.compactor = requireNonNull(compactor, "compactor is null");
this.organizationSet = requireNonNull(organizationSet, "organizationSet is null");
}
@Override
public void run()
{
try {
runJob(organizationSet.getTableId(), organizationSet.getBucketNumber(), organizationSet.getShards());
}
catch (Throwable e) {
throw Throwables.propagate(e);
}
}
private void runJob(long tableId, OptionalInt bucketNumber, Set<UUID> shardUuids)
throws IOException
{
long transactionId = shardManager.beginTransaction();
try {
runJob(transactionId, bucketNumber, tableId, shardUuids);
}
catch (Throwable e) {
shardManager.rollbackTransaction(transactionId);
throw e;
}
}
private void runJob(long transactionId, OptionalInt bucketNumber, long tableId, Set<UUID> shardUuids)
throws IOException
{
TableMetadata metadata = getTableMetadata(tableId);
List<ShardInfo> newShards = performCompaction(transactionId, bucketNumber, shardUuids, metadata);
log.info("Compacted shards %s into %s", shardUuids, newShards.stream().map(ShardInfo::getShardUuid).collect(toList()));
shardManager.replaceShardUuids(transactionId, tableId, metadata.getColumns(), shardUuids, newShards, OptionalLong.empty());
}
private TableMetadata getTableMetadata(long tableId)
{
List<TableColumn> sortColumns = metadataDao.listSortColumns(tableId);
List<Long> sortColumnIds = sortColumns.stream()
.map(TableColumn::getColumnId)
.collect(toList());
List<ColumnInfo> columns = metadataDao.listTableColumns(tableId).stream()
.map(TableColumn::toColumnInfo)
.collect(toList());
return new TableMetadata(tableId, columns, sortColumnIds);
}
private List<ShardInfo> performCompaction(long transactionId, OptionalInt bucketNumber, Set<UUID> shardUuids, TableMetadata tableMetadata)
throws IOException
{
if (tableMetadata.getSortColumnIds().isEmpty()) {
return compactor.compact(transactionId, bucketNumber, shardUuids, tableMetadata.getColumns());
}
return compactor.compactSorted(
transactionId,
bucketNumber,
shardUuids,
tableMetadata.getColumns(),
tableMetadata.getSortColumnIds(),
nCopies(tableMetadata.getSortColumnIds().size(), ASC_NULLS_FIRST));
}
}