blob: bfd85298eb3a22a6a4d115069c161327b48bb48a [file] [log] [blame]
package org.apache.cassandra.stress.settings;
/*
*
* 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.
*
*/
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import com.google.common.util.concurrent.Uninterruptibles;
import org.apache.cassandra.stress.operations.OpDistributionFactory;
import org.apache.cassandra.stress.util.JavaDriverClient;
import org.apache.cassandra.thrift.ConsistencyLevel;
// Generic command settings - common to read/write/etc
public abstract class SettingsCommand implements Serializable
{
public static enum TruncateWhen
{
NEVER, ONCE, ALWAYS
}
public final Command type;
public final long count;
public final long duration;
public final TimeUnit durationUnits;
public final boolean noWarmup;
public final TruncateWhen truncate;
public final ConsistencyLevel consistencyLevel;
public final double targetUncertainty;
public final int minimumUncertaintyMeasurements;
public final int maximumUncertaintyMeasurements;
public abstract OpDistributionFactory getFactory(StressSettings settings);
public SettingsCommand(Command type, GroupedOptions options)
{
this(type, (Options) options,
options instanceof Count ? (Count) options : null,
options instanceof Duration ? (Duration) options : null,
options instanceof Uncertainty ? (Uncertainty) options : null
);
}
public SettingsCommand(Command type, Options options, Count count, Duration duration, Uncertainty uncertainty)
{
this.type = type;
this.consistencyLevel = ConsistencyLevel.valueOf(options.consistencyLevel.value().toUpperCase());
this.noWarmup = options.noWarmup.setByUser();
this.truncate = TruncateWhen.valueOf(options.truncate.value().toUpperCase());
if (count != null)
{
this.count = OptionDistribution.parseLong(count.count.value());
this.duration = 0;
this.durationUnits = null;
this.targetUncertainty = -1;
this.minimumUncertaintyMeasurements = -1;
this.maximumUncertaintyMeasurements = -1;
}
else if (duration != null)
{
this.count = -1;
this.duration = Long.parseLong(duration.duration.value().substring(0, duration.duration.value().length() - 1));
switch (duration.duration.value().toLowerCase().charAt(duration.duration.value().length() - 1))
{
case 's':
this.durationUnits = TimeUnit.SECONDS;
break;
case 'm':
this.durationUnits = TimeUnit.MINUTES;
break;
case 'h':
this.durationUnits = TimeUnit.HOURS;
break;
default:
throw new IllegalStateException();
}
this.targetUncertainty = -1;
this.minimumUncertaintyMeasurements = -1;
this.maximumUncertaintyMeasurements = -1;
}
else
{
this.count = -1;
this.duration = 0;
this.durationUnits = null;
this.targetUncertainty = Double.parseDouble(uncertainty.uncertainty.value());
this.minimumUncertaintyMeasurements = Integer.parseInt(uncertainty.minMeasurements.value());
this.maximumUncertaintyMeasurements = Integer.parseInt(uncertainty.maxMeasurements.value());
}
}
// Option Declarations
static abstract class Options extends GroupedOptions
{
final OptionSimple noWarmup = new OptionSimple("no-warmup", "", null, "Do not warmup the process", false);
final OptionSimple truncate = new OptionSimple("truncate=", "never|once|always", "never", "Truncate the table: never, before performing any work, or before each iteration", false);
final OptionSimple consistencyLevel = new OptionSimple("cl=", "ONE|QUORUM|LOCAL_QUORUM|EACH_QUORUM|ALL|ANY|TWO|THREE|LOCAL_ONE", "LOCAL_ONE", "Consistency level to use", false);
}
static class Count extends Options
{
final OptionSimple count = new OptionSimple("n=", "[0-9]+[bmk]?", null, "Number of operations to perform", true);
@Override
public List<? extends Option> options()
{
return Arrays.asList(count, noWarmup, truncate, consistencyLevel);
}
}
static class Duration extends Options
{
final OptionSimple duration = new OptionSimple("duration=", "[0-9]+[smh]", null, "Time to run in (in seconds, minutes or hours)", true);
@Override
public List<? extends Option> options()
{
return Arrays.asList(duration, noWarmup, truncate, consistencyLevel);
}
}
static class Uncertainty extends Options
{
final OptionSimple uncertainty = new OptionSimple("err<", "0\\.[0-9]+", "0.02", "Run until the standard error of the mean is below this fraction", false);
final OptionSimple minMeasurements = new OptionSimple("n>", "[0-9]+", "30", "Run at least this many iterations before accepting uncertainty convergence", false);
final OptionSimple maxMeasurements = new OptionSimple("n<", "[0-9]+", "200", "Run at most this many iterations before accepting uncertainty convergence", false);
@Override
public List<? extends Option> options()
{
return Arrays.asList(uncertainty, minMeasurements, maxMeasurements, noWarmup, truncate, consistencyLevel);
}
}
public abstract void truncateTables(StressSettings settings);
protected void truncateTables(StressSettings settings, String ks, String ... tables)
{
JavaDriverClient client = settings.getJavaDriverClient(false);
assert settings.command.truncate != SettingsCommand.TruncateWhen.NEVER;
for (String table : tables)
{
String cql = String.format("TRUNCATE %s.%s", ks, table);
client.execute(cql, org.apache.cassandra.db.ConsistencyLevel.ONE);
}
System.out.println(String.format("Truncated %s.%s. Sleeping %ss for propagation.",
ks, Arrays.toString(tables), settings.node.nodes.size()));
Uninterruptibles.sleepUninterruptibly(settings.node.nodes.size(), TimeUnit.SECONDS);
}
// CLI Utility Methods
static SettingsCommand get(Map<String, String[]> clArgs)
{
for (Command cmd : Command.values())
{
if (cmd.category == null)
continue;
for (String name : cmd.names)
{
final String[] params = clArgs.remove(name);
if (params == null)
continue;
switch (cmd.category)
{
case BASIC:
return SettingsCommandPreDefined.build(cmd, params);
case MIXED:
return SettingsCommandPreDefinedMixed.build(params);
case USER:
return SettingsCommandUser.build(params);
}
}
}
return null;
}
static void printHelp(Command type)
{
printHelp(type.toString().toLowerCase());
}
static void printHelp(String type)
{
GroupedOptions.printOptions(System.out, type.toLowerCase(), new Uncertainty(), new Count(), new Duration());
}
static Runnable helpPrinter(final Command type)
{
return new Runnable()
{
@Override
public void run()
{
printHelp(type);
}
};
}
}