// This file is part of OpenTSDB.
// Copyright (C) 2014 The OpenTSDB Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2.1 of the License, or (at your
// option) any later version. This program is distributed in the hope that it
// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
// General Public License for more details. You should have received a copy
// of the GNU Lesser General Public License along with this program. If not,
// see <http://www.gnu.org/licenses/>.
package net.opentsdb.tools;
import net.opentsdb.utils.Config;
/**
* Various options to use during fsck over OpenTSDB tables
*/
final class FsckOptions {
private boolean fix;
private boolean compact;
private boolean resolve_dupes;
private boolean last_write_wins;
private boolean delete_orphans;
private boolean delete_unknown_columns;
private boolean delete_bad_values;
private boolean delete_bad_rows;
private boolean delete_bad_compacts;
private int threads;
/**
* Default Ctor that sets the options based on command line flags and config
* object
* @param argp Command line arguments post parsing
* @param config The configuration object loaded from a file
* @throws IllegalArgumentException if a required value is missing or something
* was incorrect
*/
public FsckOptions(final ArgP argp, final Config config) {
fix = argp.has("--fix") || argp.has("--fix-all");
compact = argp.has("--compact") || argp.has("--fix-all");
resolve_dupes = argp.has("--resolve-duplicates") || argp.has("--fix-all");
last_write_wins = argp.has("--last-write-wins") ||
config.getBoolean("tsd.storage.fix_duplicates");
delete_orphans = argp.has("--delete-orphans") || argp.has("--fix-all");
delete_unknown_columns = argp.has("--delete-unknown-columns") ||
argp.has("--fix-all");
delete_bad_values = argp.has("--delete-bad-values") ||
argp.has("--fix-all");
delete_bad_rows = argp.has("--delete-bad-rows") ||
argp.has("--fix-all");
delete_bad_compacts = argp.has("--delete-bad-compacts") ||
argp.has("--fix-all");
if (argp.has("--threads")) {
threads = Integer.parseInt(argp.get("--threads"));
if (threads < 1) {
throw new IllegalArgumentException("Must have at least one thread");
}
if (threads > Runtime.getRuntime().availableProcessors() * 4) {
throw new IllegalArgumentException(
"Not allowed to run more than 4 threads per core");
}
} else {
threads = 0;
}
}
/**
* Add data table fsck options to the command line parser
* @param argp The parser to add options to
*/
public static void addDataOptions(final ArgP argp) {
argp.addOption("--full-scan", "Scan the entire data table.");
argp.addOption("--fix", "Fix errors as they're found. Use in combination with"
+ " other flags.");
argp.addOption("--fix-all", "Set all flags and fix errors as they're found.");
argp.addOption("--compact", "Compacts rows after parsing.");
argp.addOption("--resolve-duplicates",
"Keeps the oldest (default) or newest duplicates. See --last-write-wins");
argp.addOption("--last-write-wins",
"Last data point written will be kept when fixing duplicates.\n" +
" May be set via config file and the 'tsd.storage.fix_duplicates' option.");
argp.addOption("--delete-orphans",
"Delete any time series rows where one or more UIDs fail resolution.");
argp.addOption("--delete-unknown-columns",
"Delete any unrecognized column that doesn't belong to OpenTSDB.");
argp.addOption("--delete-bad-values",
"Delete single column datapoints with bad values.");
argp.addOption("--delete-bad-rows", "Delete rows with invalid keys.");
argp.addOption("--delete-bad-compacts",
"Delete compacted columns that cannot be parsed.");
argp.addOption("--threads", "NUMBER",
"Number of threads to use when executing a full table scan.");
}
/** @return Whether or not to fix errors while processing. Does not affect
* compacting */
public boolean fix() {
return fix;
}
/** @return Whether or not to compact rows while processing. Can cause
* compaction without the --fix flag. Will skip rows with duplicate data
* points unless --last-write-wins is also specified or set in the config
* file */
public boolean compact() {
return compact;
}
/** @return Whether or not to fix duplicates */
public boolean resolveDupes() {
return resolve_dupes;
}
/** @return Accept data points with the most recent timestamp when duplicates
* are found */
public boolean lastWriteWins() {
return last_write_wins;
}
/** @return Whether or not to delete rows where the UIDs failed to resolve
* to a name */
public boolean deleteOrphans() {
return delete_orphans;
}
/** @return Delete columns that aren't recognized */
public boolean deleteUnknownColumns() {
return delete_unknown_columns;
}
/** @return Remove data points with bad values */
public boolean deleteBadValues() {
return delete_bad_values;
}
/** @return Remove rows with invalid keys */
public boolean deleteBadRows() {
return delete_bad_rows;
}
/** @return Remove compacted columns that can't be parsed */
public boolean deleteBadCompacts() {
return delete_bad_compacts;
}
/** @return The number of threads to run. If 0, default to cores * 2 */
public int threads() {
return threads;
}
/** @param fix Whether or not to fix errors while processing. Does not affect
* compacting */
public void setFix(final boolean fix) {
this.fix = fix;
}
/** @param compact Whether or not to compact rows while processing. Can cause
* compaction without the --fix flag. Will skip rows with duplicate data
* points unless --last-write-wins is also specified or set in the config
* file */
public void setCompact(final boolean compact) {
this.compact = compact;
}
/** @param fix_dupes Whether or not to fix duplicate data points */
public void setResolveDupes(final boolean fix_dupes) {
this.resolve_dupes = fix_dupes;
}
/** @param last_write_wins Accept data points with the most recent timestamp when duplicates
* are found */
public void setLastWriteWins(final boolean last_write_wins) {
this.last_write_wins = last_write_wins;
}
/** @param delete_orphans Whether or not to delete rows where the UIDs failed to resolve
* to a name */
public void setDeleteOrphans(final boolean delete_orphans) {
this.delete_orphans = delete_orphans;
}
/** @param delete_unknown_columns Delete columns that aren't recognized */
public void setDeleteUnknownColumns(final boolean delete_unknown_columns) {
this.delete_unknown_columns = delete_unknown_columns;
}
/** @param delete_bad_values Remove data points with bad values */
public void setDeleteBadValues(final boolean delete_bad_values) {
this.delete_bad_values = delete_bad_values;
}
/** @param delete_bad_rows Remove data points with invalid keys */
public void setDeleteBadRows(final boolean delete_bad_rows) {
this.delete_bad_rows = delete_bad_rows;
}
/** @param delete_bad_compacts Remove compated columns that can't be parsed */
public void setDeleteBadCompacts(final boolean delete_bad_compacts) {
this.delete_bad_compacts = delete_bad_compacts;
}
/** @param threads The number of threads to run
* @throws IllegalArgumentException if < 1 threads or more than cores * 4
* threads are specified
*/
public void setThreads(final int threads) {
if (threads < 1) {
throw new IllegalArgumentException("Must have at least one thread");
}
if (threads > Runtime.getRuntime().availableProcessors() * 4) {
throw new IllegalArgumentException(
"Not allowed to run more than 4 threads per core");
}
this.threads = threads;
}
}