mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
support named steps in named scenarios
This commit is contained in:
parent
cc5b57ebd9
commit
579a3c1ec2
@ -4,26 +4,30 @@ import java.util.*;
|
||||
|
||||
public class RawScenarios extends LinkedHashMap<String, LinkedList<String>> {
|
||||
|
||||
public static String STEPNAME = "%03d";
|
||||
|
||||
public List<String> getScenarioNames() {
|
||||
return new LinkedList<>(this.keySet());
|
||||
}
|
||||
|
||||
public List<String> getNamedScenario(String scenarioName) {
|
||||
public Map<String,String> getNamedScenario(String scenarioName) {
|
||||
|
||||
Object v = this.get(scenarioName);
|
||||
|
||||
if (v==null) { return null; }
|
||||
|
||||
// Yes this looks strange. Yes it will work. SnakeYaml and generics are a bad combo.
|
||||
if (v instanceof List) {
|
||||
return (List<String>) v;
|
||||
} else if (v instanceof CharSequence) {
|
||||
return List.of(v.toString());
|
||||
} else if (v instanceof Map) {
|
||||
Object[] o = ((Map) v).values().toArray();
|
||||
ArrayList<String> strings = new ArrayList<>(o.length);
|
||||
for (Object o1 : o) {
|
||||
strings.add(o1.toString());
|
||||
List<String> list = (List<String>) v;
|
||||
Map<String,String> map = new LinkedHashMap<>();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
map.put(String.format(STEPNAME,i),list.get(i));
|
||||
}
|
||||
return strings;
|
||||
return map;
|
||||
} else if (v instanceof CharSequence) {
|
||||
return Map.of(String.format(STEPNAME,1),v.toString());
|
||||
} else if (v instanceof Map) {
|
||||
return ((Map)v);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown type while access raw named scenarios data: " + v.getClass().getCanonicalName());
|
||||
}
|
||||
|
@ -3,8 +3,10 @@ package io.nosqlbench.engine.api.activityconfig.yaml;
|
||||
import io.nosqlbench.engine.api.activityconfig.rawyaml.RawScenarios;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Scenarios {
|
||||
|
||||
private RawScenarios rawScenarios;
|
||||
|
||||
public Scenarios(RawScenarios rawScenarios) {
|
||||
@ -15,7 +17,7 @@ public class Scenarios {
|
||||
return rawScenarios.getScenarioNames();
|
||||
}
|
||||
|
||||
public List<String> getNamedScenario(String scenarioName) {
|
||||
public Map<String,String> getNamedScenario(String scenarioName) {
|
||||
return rawScenarios.getNamedScenario(scenarioName);
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ public class NBCLIScenarioParser {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(NBCLIScenarioParser.class);
|
||||
private static final String SEARCH_IN = "activities";
|
||||
public static final String WORKLOAD_SCENARIO_STEP = "WORKLOAD_SCENARIO_STEP";
|
||||
|
||||
public static boolean isFoundWorkload(String workload,
|
||||
String... includes) {
|
||||
@ -84,7 +85,7 @@ public class NBCLIScenarioParser {
|
||||
|
||||
StrInterpolator userParamsInterp = new StrInterpolator(userParams);
|
||||
|
||||
// This will hold the command to be prepended to the main arglist
|
||||
// This will buffer the new command before adding it to the main arg list
|
||||
LinkedList<String> buildCmdBuffer = new LinkedList<>();
|
||||
|
||||
for (String scenarioName : scenarioNames) {
|
||||
@ -97,63 +98,74 @@ public class NBCLIScenarioParser {
|
||||
.extension("yaml")
|
||||
.one();
|
||||
|
||||
// // TODO: ugly hack remove this
|
||||
// workloadName = (workloadName.endsWith(".yaml")) ? workloadName : workloadName + ".yaml";
|
||||
// StmtsDocList stmts = StatementsLoader.load(logger, workloadName, SEARCH_IN);
|
||||
|
||||
|
||||
StmtsDocList stmts = StatementsLoader.load(logger,yamlWithNamedScenarios);
|
||||
|
||||
StmtsDocList stmts = StatementsLoader.load(logger, yamlWithNamedScenarios);
|
||||
|
||||
Scenarios scenarios = stmts.getDocScenarios();
|
||||
List<String> cmds = scenarios.getNamedScenario(scenarioName);
|
||||
if (cmds == null) {
|
||||
|
||||
Map<String, String> namedSteps = scenarios.getNamedScenario(scenarioName);
|
||||
|
||||
if (namedSteps == null) {
|
||||
throw new BasicError("Unable to find named scenario '" + scenarioName + "' in workload '" + workloadName
|
||||
+ "', but you can pick from " + String.join(",", scenarios.getScenarioNames()));
|
||||
}
|
||||
|
||||
Pattern cmdpattern = Pattern.compile("(?<name>\\w+)((?<oper>=+)(?<val>.+))?");
|
||||
for (String cmd : cmds) { // each command line of the named scenario
|
||||
// each named command line step of the named scenario
|
||||
for (Map.Entry<String, String> cmdEntry : namedSteps.entrySet()) {
|
||||
|
||||
String stepName = cmdEntry.getKey();
|
||||
String cmd = cmdEntry.getValue();
|
||||
cmd = userParamsInterp.apply(cmd);
|
||||
LinkedHashMap<String, CmdArg> parsedStep = parseStep(cmd);
|
||||
LinkedHashMap<String, String> usersCopy = new LinkedHashMap<>(userParams);
|
||||
LinkedHashMap<String, CmdArg> cmdline = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, String> buildingCmd = new LinkedHashMap<>();
|
||||
|
||||
String[] cmdparts = cmd.split(" ");
|
||||
for (String cmdpart : cmdparts) {
|
||||
Matcher matcher = cmdpattern.matcher(cmdpart);
|
||||
if (!matcher.matches()) {
|
||||
throw new BasicError("Unable to recognize scenario cmd spec in '" + cmdpart + "'");
|
||||
}
|
||||
String name = Synonyms.canonicalize(matcher.group("name"), logger);
|
||||
String oper = matcher.group("oper");
|
||||
String val = matcher.group("val");
|
||||
cmdline.put(name, new CmdArg(name, oper, val));
|
||||
}
|
||||
// consume each of the parameters from the steps to produce a composited command
|
||||
// order is primarily based on the step template, then on user-provided parameters
|
||||
for (CmdArg cmdarg : parsedStep.values()) {
|
||||
|
||||
LinkedHashMap<String, String> builtcmd = new LinkedHashMap<>();
|
||||
|
||||
for (CmdArg cmdarg : cmdline.values()) {
|
||||
// allow user provided parameter values to override those in the template,
|
||||
// if the assignment operator used in the template allows for it
|
||||
if (usersCopy.containsKey(cmdarg.getName())) {
|
||||
cmdarg = cmdarg.override(usersCopy.remove(cmdarg.getName()));
|
||||
}
|
||||
builtcmd.put(cmdarg.getName(), cmdarg.toString());
|
||||
}
|
||||
usersCopy.forEach((k, v) -> builtcmd.put(k, k + "=" + v));
|
||||
|
||||
if (!builtcmd.containsKey("workload")) {
|
||||
builtcmd.put("workload", "workload=" + workloadName);
|
||||
buildingCmd.put(cmdarg.getName(), cmdarg.toString());
|
||||
}
|
||||
usersCopy.forEach((k, v) -> buildingCmd.put(k, k + "=" + v));
|
||||
|
||||
// Undefine any keys with a value of 'undef'
|
||||
List<String> undefKeys = builtcmd.entrySet()
|
||||
List<String> undefKeys = buildingCmd.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e.getValue().toLowerCase().endsWith("=undef"))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
undefKeys.forEach(builtcmd::remove);
|
||||
undefKeys.forEach(buildingCmd::remove);
|
||||
|
||||
logger.debug("Named scenario built command: " + String.join(" ", builtcmd.values()));
|
||||
buildCmdBuffer.addAll(builtcmd.values());
|
||||
if (!buildingCmd.containsKey("workload")) {
|
||||
buildingCmd.put("workload", "workload=" + workloadName);
|
||||
}
|
||||
|
||||
if (!buildingCmd.containsKey("alias")) {
|
||||
buildingCmd.put("alias", WORKLOAD_SCENARIO_STEP);
|
||||
}
|
||||
|
||||
String alias = buildingCmd.get("alias");
|
||||
for (String token : new String[]{"WORKLOAD", "SCENARIO", "STEP"}) {
|
||||
if (!alias.contains(token)) {
|
||||
logger.warn("Your alias template '" + alias + "' does not contain " + token + ", which will " +
|
||||
"cause your metrics to be combined under the same name. It is strongly advised that you " +
|
||||
"include them in a template like " + WORKLOAD_SCENARIO_STEP + ".");
|
||||
}
|
||||
}
|
||||
|
||||
alias = alias.replaceAll("WORKLOAD", workloadContent.asPath().getFileName().toString().replaceAll(
|
||||
".yaml",""));
|
||||
alias = alias.replaceAll("SCENARIO", scenarioName);
|
||||
alias = alias.replaceAll("STEP", stepName);
|
||||
buildingCmd.put("alias", "alias="+alias);
|
||||
|
||||
logger.debug("Named scenario built command: " + String.join(" ", buildingCmd.values()));
|
||||
buildCmdBuffer.addAll(buildingCmd.values());
|
||||
}
|
||||
|
||||
}
|
||||
@ -161,6 +173,26 @@ public class NBCLIScenarioParser {
|
||||
|
||||
}
|
||||
|
||||
private static final Pattern WordAndMaybeAssignment = Pattern.compile("(?<name>\\w+)((?<oper>=+)(?<val>.+))?");
|
||||
|
||||
private static LinkedHashMap<String, CmdArg> parseStep(String cmd) {
|
||||
LinkedHashMap<String, CmdArg> parsedStep = new LinkedHashMap<>();
|
||||
|
||||
String[] namedStepPieces = cmd.split(" ");
|
||||
for (String commandFragment : namedStepPieces) {
|
||||
Matcher matcher = WordAndMaybeAssignment.matcher(commandFragment);
|
||||
if (!matcher.matches()) {
|
||||
throw new BasicError("Unable to recognize scenario cmd spec in '" + commandFragment + "'");
|
||||
}
|
||||
String commandName = matcher.group("name");
|
||||
commandName = Synonyms.canonicalize(commandName, logger);
|
||||
String assignmentOp = matcher.group("oper");
|
||||
String assignedValue = matcher.group("val");
|
||||
parsedStep.put(commandName, new CmdArg(commandName, assignmentOp, assignedValue));
|
||||
}
|
||||
return parsedStep;
|
||||
}
|
||||
|
||||
private final static class CmdArg {
|
||||
private final String name;
|
||||
private final String operator;
|
||||
@ -176,9 +208,11 @@ public class NBCLIScenarioParser {
|
||||
public boolean isReassignable() {
|
||||
return UNLOCKED.equals(operator);
|
||||
}
|
||||
|
||||
public boolean isFinalSilent() {
|
||||
return SILENT_LOCKED.equals(operator);
|
||||
}
|
||||
|
||||
public boolean isFinalVerbose() {
|
||||
return VERBOSE_LOCKED.equals(operator);
|
||||
}
|
||||
@ -298,7 +332,7 @@ public class NBCLIScenarioParser {
|
||||
.name(referenced).extension("yaml")
|
||||
.one();
|
||||
|
||||
StmtsDocList stmts = StatementsLoader.load(logger,content);
|
||||
StmtsDocList stmts = StatementsLoader.load(logger, content);
|
||||
|
||||
Map<String, String> templates = new HashMap<>();
|
||||
try {
|
||||
@ -315,7 +349,7 @@ public class NBCLIScenarioParser {
|
||||
|
||||
List<String> scenarioNames = scenarios.getScenarioNames();
|
||||
|
||||
if (scenarioNames != null && scenarioNames.size() >0){
|
||||
if (scenarioNames != null && scenarioNames.size() > 0) {
|
||||
String path = yamlPath.toString();
|
||||
path = path.startsWith(FileSystems.getDefault().getSeparator()) ? path.substring(1) : path;
|
||||
workloadDescriptions.add(new WorkloadDesc(path, scenarioNames, templates));
|
||||
@ -340,7 +374,7 @@ public class NBCLIScenarioParser {
|
||||
//We want the outer name with the inner default value
|
||||
templates.put(matchArray[0], innerMatch[1]);
|
||||
|
||||
}else{
|
||||
} else {
|
||||
templates.put(matchArray[0], matchArray[1]);
|
||||
}
|
||||
}
|
||||
@ -349,7 +383,7 @@ public class NBCLIScenarioParser {
|
||||
while (matcher.find()) {
|
||||
String match = matcher.group(1);
|
||||
String[] matchArray = match.split(":");
|
||||
templates.put(matchArray[0],matchArray[1]);
|
||||
templates.put(matchArray[0], matchArray[1]);
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ -68,10 +69,16 @@ public class RawYamlStatementLoaderTest {
|
||||
|
||||
RawScenarios rawScenarios = rawStmtsDoc.getRawScenarios();
|
||||
assertThat(rawScenarios.getScenarioNames()).containsExactly("default", "schema-only");
|
||||
List<String> defaultScenario = rawScenarios.getNamedScenario("default");
|
||||
assertThat(defaultScenario).containsExactly("run driver=stdout alias=step1","run driver=stdout alias=step2");
|
||||
List<String> schemaOnlyScenario = rawScenarios.getNamedScenario("schema-only");
|
||||
assertThat(schemaOnlyScenario).containsExactly("run driver=blah tags=phase:schema");
|
||||
Map<String, String> defaultScenario = rawScenarios.getNamedScenario("default");
|
||||
assertThat(defaultScenario.keySet())
|
||||
.containsExactly("000","001");
|
||||
assertThat(defaultScenario.values())
|
||||
.containsExactly("run driver=stdout alias=step1","run driver=stdout alias=step2");
|
||||
Map<String, String> schemaOnlyScenario = rawScenarios.getNamedScenario("schema-only");
|
||||
assertThat(schemaOnlyScenario.keySet())
|
||||
.containsExactly("000");
|
||||
assertThat(schemaOnlyScenario.values())
|
||||
.containsExactly("run driver=blah tags=phase:schema");
|
||||
|
||||
assertThat(rawStmtsDoc.getName()).isEqualTo("doc1");
|
||||
assertThat(blocks).hasSize(1);
|
||||
|
Loading…
Reference in New Issue
Block a user