blob: 7c92c530fe115da461d1452ecf79a0b0447c9bf6 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.hbase.util.compaction;
import java.io.IOException;
import java.util.Arrays;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executors;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.RegionInfo;
import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.util.ToolRunner;
import org.apache.yetus.audience.InterfaceAudience;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;
import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;
import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;
import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;
import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;
import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;
/**
* This tool compacts a table's regions that are beyond it's TTL. It helps to save disk space and
* regions become empty as a result of compaction.
*/
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS)
public class MajorCompactorTTL extends MajorCompactor {
private static final Logger LOG = LoggerFactory.getLogger(MajorCompactorTTL .class);
private TableDescriptor htd;
@InterfaceAudience.Private
public MajorCompactorTTL(Configuration conf, TableDescriptor htd, int concurrency,
long sleepForMs) throws IOException {
this.connection = ConnectionFactory.createConnection(conf);
this.htd = htd;
this.tableName = htd.getTableName();
this.storesToCompact = Sets.newHashSet(); // Empty set so all stores will be compacted
this.sleepForMs = sleepForMs;
this.executor = Executors.newFixedThreadPool(concurrency);
this.clusterCompactionQueues = new ClusterCompactionQueues(concurrency);
}
protected MajorCompactorTTL() {
super();
}
@Override
protected Optional<MajorCompactionRequest> getMajorCompactionRequest(RegionInfo hri)
throws IOException {
return MajorCompactionTTLRequest.newRequest(connection.getConfiguration(), hri, htd);
}
@Override
protected Set<String> getStoresRequiringCompaction(MajorCompactionRequest request)
throws IOException {
return ((MajorCompactionTTLRequest)request).getStoresRequiringCompaction(htd).keySet();
}
public int compactRegionsTTLOnTable(Configuration conf, String table, int concurrency,
long sleep, int numServers, int numRegions, boolean dryRun, boolean skipWait)
throws Exception {
Connection conn = ConnectionFactory.createConnection(conf);
TableName tableName = TableName.valueOf(table);
TableDescriptor htd = conn.getAdmin().getDescriptor(tableName);
if (!doesAnyColFamilyHaveTTL(htd)) {
LOG.info("No TTL present for CF of table: " + tableName + ", skipping compaction");
return 0;
}
LOG.info("Major compacting table " + tableName + " based on TTL");
MajorCompactor compactor = new MajorCompactorTTL(conf, htd, concurrency, sleep);
compactor.setNumServers(numServers);
compactor.setNumRegions(numRegions);
compactor.setSkipWait(skipWait);
compactor.initializeWorkQueues();
if (!dryRun) {
compactor.compactAllRegions();
}
compactor.shutdown();
return ERRORS.size();
}
private boolean doesAnyColFamilyHaveTTL(TableDescriptor htd) {
for (ColumnFamilyDescriptor descriptor : htd.getColumnFamilies()) {
if (descriptor.getTimeToLive() != HConstants.FOREVER) {
return true;
}
}
return false;
}
private Options getOptions() {
Options options = getCommonOptions();
options.addOption(
Option.builder("table")
.required()
.desc("table name")
.hasArg()
.build()
);
return options;
}
@Override
public int run(String[] args) throws Exception {
Options options = getOptions();
final CommandLineParser cmdLineParser = new DefaultParser();
CommandLine commandLine;
try {
commandLine = cmdLineParser.parse(options, args);
} catch (ParseException parseException) {
System.out.println(
"ERROR: Unable to parse command-line arguments " + Arrays.toString(args) + " due to: "
+ parseException);
printUsage(options);
return -1;
}
if (commandLine == null) {
System.out.println("ERROR: Failed parse, empty commandLine; " + Arrays.toString(args));
printUsage(options);
return -1;
}
String table = commandLine.getOptionValue("table");
int numServers = Integer.parseInt(commandLine.getOptionValue("numservers", "-1"));
int numRegions = Integer.parseInt(commandLine.getOptionValue("numregions", "-1"));
int concurrency = Integer.parseInt(commandLine.getOptionValue("servers", "1"));
long sleep = Long.parseLong(commandLine.getOptionValue("sleep", Long.toString(30000)));
boolean dryRun = commandLine.hasOption("dryRun");
boolean skipWait = commandLine.hasOption("skipWait");
return compactRegionsTTLOnTable(HBaseConfiguration.create(), table, concurrency, sleep,
numServers, numRegions, dryRun, skipWait);
}
public static void main(String[] args) throws Exception {
ToolRunner.run(HBaseConfiguration.create(), new MajorCompactorTTL(), args);
}
}