mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
@@ -95,7 +95,7 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
* for scenario encapsulation and concurrent testing.
|
||||
*
|
||||
* @param args
|
||||
* Command Line Args
|
||||
* Command Line Args
|
||||
*/
|
||||
public static void main(final String[] args) {
|
||||
try {
|
||||
@@ -158,17 +158,17 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
this.sessionName = SessionNamer.format(globalOptions.getSessionName(), sessionTime).replaceAll("SESSIONCODE", sessionCode);
|
||||
|
||||
NBCLI.loggerConfig
|
||||
.setSessionName(sessionName)
|
||||
.setConsoleLevel(globalOptions.getConsoleLogLevel())
|
||||
.setConsolePattern(globalOptions.getConsoleLoggingPattern())
|
||||
.setLogfileLevel(globalOptions.getScenarioLogLevel())
|
||||
.setLogfilePattern(globalOptions.getLogfileLoggingPattern())
|
||||
.setLoggerLevelOverrides(globalOptions.getLogLevelOverrides())
|
||||
.setMaxLogs(globalOptions.getLogsMax())
|
||||
.setLogsDirectory(globalOptions.getLogsDirectory())
|
||||
.setAnsiEnabled(globalOptions.isEnableAnsi())
|
||||
.setDedicatedVerificationLogger(globalOptions.isDedicatedVerificationLogger())
|
||||
.activate();
|
||||
.setSessionName(sessionName)
|
||||
.setConsoleLevel(globalOptions.getConsoleLogLevel())
|
||||
.setConsolePattern(globalOptions.getConsoleLoggingPattern())
|
||||
.setLogfileLevel(globalOptions.getScenarioLogLevel())
|
||||
.setLogfilePattern(globalOptions.getLogfileLoggingPattern())
|
||||
.setLoggerLevelOverrides(globalOptions.getLogLevelOverrides())
|
||||
.setMaxLogs(globalOptions.getLogsMax())
|
||||
.setLogsDirectory(globalOptions.getLogsDirectory())
|
||||
.setAnsiEnabled(globalOptions.isEnableAnsi())
|
||||
.setDedicatedVerificationLogger(globalOptions.isDedicatedVerificationLogger())
|
||||
.activate();
|
||||
ConfigurationFactory.setConfigurationFactory(NBCLI.loggerConfig); // THIS should be the first time log4j2 is invoked!
|
||||
|
||||
NBCLI.logger = LogManager.getLogger("NBCLI"); // TODO: Detect if the logger config was already initialized (error)
|
||||
@@ -208,15 +208,15 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
if (annotatorsConfig == null || annotatorsConfig.isBlank()) {
|
||||
List<Map<String, String>> annotatorsConfigs = new ArrayList<>();
|
||||
annotatorsConfigs.add(Map.of(
|
||||
"type", "log",
|
||||
"level", "info"
|
||||
"type", "log",
|
||||
"level", "info"
|
||||
));
|
||||
|
||||
Gson gson = new GsonBuilder().create();
|
||||
annotatorsConfig = gson.toJson(annotatorsConfigs);
|
||||
}
|
||||
|
||||
final NBCLIOptions options = new NBCLIOptions(args,Mode.ParseAllOptions);
|
||||
final NBCLIOptions options = new NBCLIOptions(args, Mode.ParseAllOptions);
|
||||
NBCLI.logger = LogManager.getLogger("NBCLI");
|
||||
|
||||
NBIO.addGlobalIncludes(options.wantsIncludes());
|
||||
@@ -277,18 +277,18 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
NBCLI.logger.debug(() -> "user requests to cat " + resourceToCat);
|
||||
|
||||
Optional<Content<?>> tocat = NBIO.classpath()
|
||||
.searchPrefixes("activities")
|
||||
.searchPrefixes(options.wantsIncludes())
|
||||
.pathname(resourceToCat).extensionSet(RawOpsLoader.YAML_EXTENSIONS).first();
|
||||
.searchPrefixes("activities")
|
||||
.searchPrefixes(options.wantsIncludes())
|
||||
.pathname(resourceToCat).extensionSet(RawOpsLoader.YAML_EXTENSIONS).first();
|
||||
|
||||
if (tocat.isEmpty()) tocat = NBIO.classpath()
|
||||
.searchPrefixes().searchPrefixes(options.wantsIncludes())
|
||||
.searchPrefixes(options.wantsIncludes())
|
||||
.pathname(resourceToCat).first();
|
||||
.searchPrefixes().searchPrefixes(options.wantsIncludes())
|
||||
.searchPrefixes(options.wantsIncludes())
|
||||
.pathname(resourceToCat).first();
|
||||
|
||||
final Content<?> data = tocat.orElseThrow(
|
||||
() -> new BasicError("Unable to find " + resourceToCat +
|
||||
" in classpath to cat out"));
|
||||
() -> new BasicError("Unable to find " + resourceToCat +
|
||||
" in classpath to cat out"));
|
||||
|
||||
System.out.println(data.get());
|
||||
NBCLI.logger.info(() -> "Dumped internal resource '" + data.asPath() + "' to stdout");
|
||||
@@ -300,19 +300,19 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
NBCLI.logger.debug(() -> "user requests to copy out " + resourceToCopy);
|
||||
|
||||
Optional<Content<?>> tocopy = NBIO.classpath()
|
||||
.searchPrefixes("activities")
|
||||
.searchPrefixes(options.wantsIncludes())
|
||||
.pathname(resourceToCopy).extensionSet(RawOpsLoader.YAML_EXTENSIONS).first();
|
||||
.searchPrefixes("activities")
|
||||
.searchPrefixes(options.wantsIncludes())
|
||||
.pathname(resourceToCopy).extensionSet(RawOpsLoader.YAML_EXTENSIONS).first();
|
||||
|
||||
if (tocopy.isEmpty()) tocopy = NBIO.classpath()
|
||||
.searchPrefixes().searchPrefixes(options.wantsIncludes())
|
||||
.searchPrefixes(options.wantsIncludes())
|
||||
.pathname(resourceToCopy).first();
|
||||
.searchPrefixes().searchPrefixes(options.wantsIncludes())
|
||||
.searchPrefixes(options.wantsIncludes())
|
||||
.pathname(resourceToCopy).first();
|
||||
|
||||
final Content<?> data = tocopy.orElseThrow(
|
||||
() -> new BasicError(
|
||||
"Unable to find " + resourceToCopy +
|
||||
" in classpath to copy out")
|
||||
() -> new BasicError(
|
||||
"Unable to find " + resourceToCopy +
|
||||
" in classpath to copy out")
|
||||
);
|
||||
|
||||
final Path writeTo = Path.of(data.asPath().getFileName().toString());
|
||||
@@ -350,7 +350,7 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
if (options.wantsTopicalHelp()) {
|
||||
final Optional<String> helpDoc = MarkdownFinder.forHelpTopic(options.wantsTopicalHelpFor());
|
||||
System.out.println(helpDoc.orElseThrow(
|
||||
() -> new RuntimeException("No help could be found for " + options.wantsTopicalHelpFor())
|
||||
() -> new RuntimeException("No help could be found for " + options.wantsTopicalHelpFor())
|
||||
));
|
||||
return NBCLI.EXIT_OK;
|
||||
}
|
||||
@@ -358,12 +358,12 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
NBCLI.logger.debug("initializing annotators with config:'{}'", annotatorsConfig);
|
||||
Annotators.init(annotatorsConfig, options.getAnnotateLabelSpec());
|
||||
Annotators.recordAnnotation(
|
||||
Annotation.newBuilder()
|
||||
.element(this)
|
||||
.now()
|
||||
.layer(Layer.Session)
|
||||
.addDetail("cli", String.join("\n", args))
|
||||
.build()
|
||||
Annotation.newBuilder()
|
||||
.element(this)
|
||||
.now()
|
||||
.layer(Layer.Session)
|
||||
.addDetail("cli", String.join("\n", args))
|
||||
.build()
|
||||
);
|
||||
|
||||
// if ((null != reportPromPushTo) || (null != reportGraphiteTo) || (null != options.wantsReportCsvTo())) {
|
||||
@@ -402,11 +402,11 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
NBCLI.logger.info(() -> "console logging level is " + options.getConsoleLogLevel());
|
||||
|
||||
Map<String, String> props = Map.of(
|
||||
"summary", options.getReportSummaryTo(),
|
||||
"logsdir", options.getLogsDirectory().toString(),
|
||||
"progress", options.getProgressSpec(),
|
||||
"prompush_cache", "prompush_cache.txt",
|
||||
"heartbeat", String.valueOf(options.wantsHeartbeatIntervalMs())
|
||||
"summary", options.getReportSummaryTo(),
|
||||
"logsdir", options.getLogsDirectory().toString(),
|
||||
"progress", options.getProgressSpec(),
|
||||
"prompush_cache", "prompush_cache.txt",
|
||||
"heartbeat", String.valueOf(options.wantsHeartbeatIntervalMs())
|
||||
);
|
||||
/**
|
||||
* At this point, the command stream from the CLI should be handed into the session, and the session should
|
||||
@@ -414,15 +414,15 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
*/
|
||||
|
||||
try (
|
||||
NBSession session = new NBSession(
|
||||
new NBBaseComponent(null,
|
||||
options.getLabelMap()
|
||||
.andDefault("jobname", "nosqlbench")
|
||||
.andDefault("instance", "default")
|
||||
),
|
||||
sessionName,
|
||||
props
|
||||
)) {
|
||||
NBSession session = new NBSession(
|
||||
new NBBaseComponent(null,
|
||||
options.getLabelMap()
|
||||
.andDefault("jobname", "nosqlbench")
|
||||
.andDefault("instance", "default")
|
||||
),
|
||||
sessionName,
|
||||
props
|
||||
)) {
|
||||
|
||||
options.wantsReportCsvTo().ifPresent(cfg -> {
|
||||
MetricInstanceFilter filter = new MetricInstanceFilter();
|
||||
@@ -450,6 +450,12 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
|
||||
ExecutionResult sessionResult = session.apply(options.getCommands());
|
||||
logger.info(sessionResult);
|
||||
if (sessionResult.getException() instanceof RuntimeException rte) {
|
||||
throw rte;
|
||||
} else if (sessionResult.getException() instanceof Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
|
||||
return sessionResult.getStatus().code;
|
||||
}
|
||||
// sessionResult.printSummary(System.out);
|
||||
|
||||
@@ -27,14 +27,21 @@ import io.nosqlbench.nb.annotations.Service;
|
||||
@Service(value= NBInvokableResolver.class,selector = "java")
|
||||
public class NBJavaNativeResolver implements NBInvokableResolver {
|
||||
@Override
|
||||
public NBInvokableCommand resolve(Cmd cmd, NBBufferedContainer parent, String phaseName) {
|
||||
public NBInvokableCommand resolve(Cmd cmd, NBBufferedContainer parent, String stepname) {
|
||||
return switch (cmd.getCmdType()) {
|
||||
case CmdType.indirect -> {
|
||||
String implName = cmd.takeArgValue("_impl");
|
||||
yield NBJavaCommandLoader.init(implName, parent, phaseName, cmd.getTargetContext());
|
||||
String implName = cmd.getArgValue("_impl");
|
||||
NBInvokableCommand invokable = NBJavaCommandLoader.init(implName, parent, stepname, cmd.getTargetContext());
|
||||
cmd.takeArgValue("_impl");
|
||||
yield invokable;
|
||||
}
|
||||
case CmdType.java -> NBJavaCommandLoader.init(cmd.getArgValue("class"), parent, phaseName, cmd.getTargetContext());
|
||||
case CmdType.java -> NBJavaCommandLoader.init(cmd.getArgValue("class"), parent, stepname, cmd.getTargetContext());
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(Cmd cmd) {
|
||||
return NBJavaCommandLoader.oneExists(cmd.getArgValue("_impl")) != null;
|
||||
}
|
||||
}
|
||||
@@ -133,8 +133,12 @@ public class Cmd {
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(cmdType.toString());
|
||||
sb.append(switch (cmdType) {
|
||||
case indirect -> getArgs().containsKey("_impl") ? getArgs().get("_impl").getValue() : "[]";
|
||||
default -> cmdType.name();
|
||||
});
|
||||
for (CmdArg value : getArgs().values()) {
|
||||
if (value.getParam().name.startsWith("_impl")) continue;
|
||||
sb.append(" ").append(value);
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
@@ -39,9 +39,9 @@ public class NBJavaCommandLoader {
|
||||
}
|
||||
}
|
||||
|
||||
public static NBInvokableCommand init(String cmdSelector, NBComponent parent, String cmdAlias, String ctxName) {
|
||||
public static NBInvokableCommand init(String cmdSelector, NBComponent parent, String stepName, String ctxName) {
|
||||
NBCommandInfo cmdInfo = getSelector(cmdSelector).getOne();
|
||||
NBInvokableCommand command = cmdInfo.create(parent, cmdAlias, ctxName);
|
||||
NBInvokableCommand command = cmdInfo.create(parent, cmdSelector, ctxName);
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2024 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.engine.core.lifecycle.commands.fortesting;
|
||||
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.container.ContainerActivitiesController;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.container.NBBufferedContainer;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.container.NBCommandParams;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.execution.NBBaseCommand;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
|
||||
public class CMD_error extends NBBaseCommand {
|
||||
|
||||
|
||||
public CMD_error(NBBufferedContainer parentComponent, String stepName, String targetScenario) {
|
||||
super(parentComponent, stepName, targetScenario);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(NBCommandParams params, PrintWriter stdout, PrintWriter stderr, Reader stdin, ContainerActivitiesController controller) {
|
||||
throw new RuntimeException("Command '" + this + "' throws ERROR.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2024 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.engine.core.lifecycle.commands.fortesting;
|
||||
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.container.ContainerActivitiesController;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.container.NBBufferedContainer;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.container.NBCommandParams;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.execution.NBBaseCommand;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.execution.NBInvokableCommand;
|
||||
import io.nosqlbench.nb.api.labels.NBLabels;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
|
||||
public class CMD_ok extends NBBaseCommand {
|
||||
|
||||
public CMD_ok(NBBufferedContainer parentComponent, String stepName, String targetScenario) {
|
||||
super(parentComponent, stepName, targetScenario);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(NBCommandParams params, PrintWriter stdout, PrintWriter stderr, Reader stdin, ContainerActivitiesController controller) {
|
||||
stdout.write("Command '" + this.toString() + "' says OK and exits with no object or exception.");
|
||||
for (String pkey : params.keySet()) {
|
||||
stdout.println("diagnostic 'ok' command setting key '" + pkey + " to " + params.get(pkey));
|
||||
}
|
||||
return params;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2024 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.engine.core.lifecycle.commands.fortesting;
|
||||
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.execution.NBCommandInfo;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.execution.NBInvokableCommand;
|
||||
import io.nosqlbench.nb.annotations.Service;
|
||||
|
||||
@Service(value = NBCommandInfo.class,selector = "test_error")
|
||||
public class INFO_error extends NBCommandInfo {
|
||||
@Override
|
||||
public Class<? extends NBInvokableCommand> getType() {
|
||||
return CMD_error.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2024 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.engine.core.lifecycle.commands.fortesting;
|
||||
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.execution.NBCommandInfo;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.execution.NBInvokableCommand;
|
||||
import io.nosqlbench.nb.annotations.Service;
|
||||
|
||||
@Service(value = NBCommandInfo.class,selector = "test_ok")
|
||||
public class INFO_test_ok extends NBCommandInfo {
|
||||
@Override
|
||||
public Class<? extends NBInvokableCommand> getType() {
|
||||
return CMD_ok.class;
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public abstract class NBCommandInfo {
|
||||
cmdCtor = getType().getConstructor(NBBufferedContainer.class, String.class, String.class);
|
||||
return cmdCtor.newInstance(parent, cmdName, ctxName);
|
||||
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
|
||||
throw new RuntimeException("Unable to instantiate command via ctor(parent,name,ctx): " + e,e);
|
||||
throw new RuntimeException("Unable to instantiate command via ctor(parent,name,ctx): " + e + (e.getCause()!=null ? "cause: " + e.getCause().toString() : ""),e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.util.Optional;
|
||||
@Service(value = NBInvokableResolver.class, selector = "autojs")
|
||||
public class NBAutoScriptResolver implements NBInvokableResolver {
|
||||
@Override
|
||||
public NBInvokableCommand resolve(Cmd cmd, NBBufferedContainer parent, String phaseName) {
|
||||
public NBInvokableCommand resolve(Cmd cmd, NBBufferedContainer parent, String stepname) {
|
||||
|
||||
Optional<Content<?>> scriptfile = NBIO.local()
|
||||
.searchPrefixes("scripts/auto")
|
||||
@@ -47,11 +47,21 @@ public class NBAutoScriptResolver implements NBInvokableResolver {
|
||||
Map<String, CmdArg> newArgs = new LinkedHashMap<>(cmd.getArgs());
|
||||
newArgs.put("path",new CmdArg(new CmdParam("name",s->s,false),"=",pathOf.toString()));
|
||||
Cmd reformattedCmd = new Cmd("script", newArgs);
|
||||
return new NBScriptedCommand(parent, phaseName, cmd.getTargetContext()).add(reformattedCmd);
|
||||
return new NBScriptedCommand(parent, stepname, cmd.getTargetContext()).add(reformattedCmd);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(Cmd cmd) {
|
||||
return NBIO.local()
|
||||
.searchPrefixes("scripts/auto")
|
||||
.pathname(cmd.getArgValue("_impl"))
|
||||
.extensionSet("js")
|
||||
.first()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -29,15 +29,35 @@ import java.util.function.Function;
|
||||
|
||||
public class NBCommandAssembly {
|
||||
|
||||
private static NBCoreInvokableResolver core_resolver = new NBCoreInvokableResolver();
|
||||
|
||||
private final static Logger logger = LogManager.getLogger(NBCommandAssembly.class);
|
||||
|
||||
public static NBCommandParams paramsFor(Cmd cmd) {
|
||||
return switch (cmd.getCmdType()) {
|
||||
case indirect, java, container -> {
|
||||
Map<String, String> params = cmd.getArgMap();
|
||||
params.remove("_impl");
|
||||
yield NBCommandParams.of(params);
|
||||
}
|
||||
default -> NBCommandParams.of(Map.of());
|
||||
};
|
||||
}
|
||||
|
||||
public static record CommandInvocation(NBInvokableCommand command, NBCommandParams params, String containerName) {
|
||||
}
|
||||
|
||||
public static List<CommandInvocation> assemble(List<Cmd> cmds, Function<String, NBBufferedContainer> ctxprovider) {
|
||||
public static List<Cmd> assemble(List<Cmd> cmds, Function<String, NBBufferedContainer> ctxprovider) {
|
||||
List<Cmd> mappedCmds = tagCommandsWithContext(cmds);
|
||||
List<CommandInvocation> invocations = prepareMappedPhases(mappedCmds, ctxprovider);
|
||||
return invocations;
|
||||
NBCoreInvokableResolver core_resolver = new NBCoreInvokableResolver();
|
||||
for (Cmd mappedCmd : mappedCmds) {
|
||||
core_resolver.verify(mappedCmd);
|
||||
}
|
||||
|
||||
return mappedCmds;
|
||||
|
||||
// List<CommandInvocation> invocations = prepareMappedPhases(mappedCmds, ctxprovider);
|
||||
// return invocations;
|
||||
}
|
||||
|
||||
private static List<Cmd> tagCommandsWithContext(List<Cmd> cmds) {
|
||||
@@ -62,6 +82,40 @@ public class NBCommandAssembly {
|
||||
return new ArrayList<>(tagged);
|
||||
}
|
||||
|
||||
|
||||
public static NBInvokableCommand resolve(Cmd cmd, Function<String, NBBufferedContainer> ctxProvider) {
|
||||
try {
|
||||
NBCommandParams params = switch (cmd.getCmdType()) {
|
||||
case indirect, java, container -> NBCommandParams.of(cmd.getArgMap());
|
||||
default -> NBCommandParams.of(Map.of());
|
||||
};
|
||||
|
||||
String targetContext = cmd.getTargetContext();
|
||||
NBInvokableCommand command = core_resolver.resolve(cmd, ctxProvider.apply(targetContext), cmd.getStepName());
|
||||
return command;
|
||||
} catch (Exception e) {
|
||||
throw new UnresolvedCommand(cmd, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static CommandInvocation assembleCommand(Cmd cmd, Function<String, NBBufferedContainer> ctxProvider) {
|
||||
NBCommandParams params = switch (cmd.getCmdType()) {
|
||||
case indirect, java, container -> NBCommandParams.of(cmd.getArgMap());
|
||||
default -> NBCommandParams.of(Map.of());
|
||||
};
|
||||
|
||||
String targetContext = cmd.getTargetContext();
|
||||
NBInvokableCommand command = core_resolver.resolve(cmd, ctxProvider.apply(targetContext), cmd.getStepName());
|
||||
if (command == null) {
|
||||
throw new BasicError("Found zero commands for spec;" + cmd);
|
||||
}
|
||||
String containerName = cmd.getTargetContext();
|
||||
|
||||
// TODO, make this unnecessary by moving the impl out of the map to a dedicated cmd structure
|
||||
params.remove("_impl");
|
||||
return new CommandInvocation(command, params, containerName);
|
||||
}
|
||||
|
||||
private static List<CommandInvocation> prepareMappedPhases(List<Cmd> mappedCmds, Function<String, NBBufferedContainer> ctxProvider) {
|
||||
List<CommandInvocation> parameterizedInvocations = new ArrayList<>();
|
||||
NBCoreInvokableResolver core_resolver = new NBCoreInvokableResolver();
|
||||
@@ -73,7 +127,7 @@ public class NBCommandAssembly {
|
||||
|
||||
String targetContext = cmd.getTargetContext();
|
||||
NBInvokableCommand command = core_resolver.resolve(cmd, ctxProvider.apply(targetContext), cmd.getStepName());
|
||||
if (command==null) {
|
||||
if (command == null) {
|
||||
throw new BasicError("Found zero commands for spec;" + cmd);
|
||||
}
|
||||
String containerName = cmd.getTargetContext();
|
||||
|
||||
@@ -45,6 +45,16 @@ public class NBCoreInvokableResolver implements NBInvokableResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(Cmd cmd) {
|
||||
for (NBInvokableResolver resolver : getResolvers().values()) {
|
||||
if (resolver.verify(cmd)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private SequencedMap<String, NBInvokableResolver> getResolvers() {
|
||||
if (this.resolvers == null || this.resolvers.isEmpty()) {
|
||||
SequencedMap<String,NBInvokableResolver> resolverMap = new LinkedHashMap<>();
|
||||
|
||||
@@ -21,6 +21,8 @@ import io.nosqlbench.engine.core.lifecycle.scenario.container.NBBufferedContaine
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.execution.NBInvokableCommand;
|
||||
|
||||
public interface NBInvokableResolver {
|
||||
NBInvokableCommand resolve(Cmd cmd, NBBufferedContainer parent, String phaseName);
|
||||
NBInvokableCommand resolve(Cmd cmd, NBBufferedContainer parent, String stepname);
|
||||
|
||||
boolean verify(Cmd cmd);
|
||||
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ import io.nosqlbench.nb.annotations.Service;
|
||||
@Service(value = NBInvokableResolver.class, selector = "js")
|
||||
public class NBScriptCommandResolver implements NBInvokableResolver {
|
||||
@Override
|
||||
public NBInvokableCommand resolve(Cmd cmd, NBBufferedContainer parent, String phaseName) {
|
||||
public NBInvokableCommand resolve(Cmd cmd, NBBufferedContainer parent, String stepname) {
|
||||
return switch (cmd.getCmdType()) {
|
||||
case fragment, script->
|
||||
new NBScriptedCommand(parent, phaseName, cmd.getTargetContext()).add(cmd);
|
||||
new NBScriptedCommand(parent, stepname, cmd.getTargetContext()).add(cmd);
|
||||
// case fragment ->
|
||||
// new NBScriptedCommand(parent, phaseName, cmd.getTargetContext()).addScriptText(cmd.getArgValue("fragment"));
|
||||
// case script ->
|
||||
@@ -37,5 +37,8 @@ public class NBScriptCommandResolver implements NBInvokableResolver {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean verify(Cmd cmd) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package io.nosqlbench.engine.core.lifecycle.session;
|
||||
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.container.NBCommandParams;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.execution.NBInvokableCommand;
|
||||
import io.nosqlbench.nb.api.components.status.NBHeartbeatComponent;
|
||||
import io.nosqlbench.nb.api.engine.activityimpl.ActivityDef;
|
||||
@@ -82,23 +83,22 @@ public class NBSession extends NBHeartbeatComponent implements Function<List<Cmd
|
||||
|
||||
// TODO: add container closing command
|
||||
// TODO: inject container closing commands after the last command referencing each container
|
||||
List<NBCommandAssembly.CommandInvocation> invocationCalls = NBCommandAssembly.assemble(cmds, this::getContext);
|
||||
List<Cmd> assembledCommands = NBCommandAssembly.assemble(cmds, this::getContext);
|
||||
ResultCollector collector = new ResultCollector();
|
||||
// TODO: When a command is not successful, automatically break out of the command loop
|
||||
|
||||
try (ResultContext results = new ResultContext(collector).ok()) {
|
||||
for (NBCommandAssembly.CommandInvocation invocation : invocationCalls) {
|
||||
String targetContext = invocation.containerName();
|
||||
String explanation = "in context '" + targetContext + "'";
|
||||
try (NBInvokableCommand command = invocation.command()) {
|
||||
explanation += " command '" + command.toString() + "'";
|
||||
NBBufferedContainer container = getContext(targetContext);
|
||||
NBCommandResult cmdResult = container.apply(command, invocation.params());
|
||||
for (Cmd cmd : assembledCommands) {
|
||||
String explanation = " in context " + cmd.getTargetContext() + ", command '" + cmd.toString() + "'";
|
||||
try (NBInvokableCommand command = NBCommandAssembly.resolve(cmd,this::getContext)) {
|
||||
NBCommandParams params = NBCommandAssembly.paramsFor(cmd);
|
||||
NBBufferedContainer container = getContext(cmd.getTargetContext());
|
||||
NBCommandResult cmdResult = container.apply(command, params);
|
||||
results.apply(cmdResult);
|
||||
if (cmdResult.hasException()) {
|
||||
throw cmdResult.getException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String msg = "While running " + explanation + "', an error occurred: " + e.toString();
|
||||
String msg = "While running " + explanation + ", an error occurred: " + e.toString();
|
||||
results.error(e);
|
||||
onError(e);
|
||||
logger.error(msg);
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2024 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.engine.core.lifecycle.session;
|
||||
|
||||
import io.nosqlbench.engine.cmdstream.Cmd;
|
||||
import scala.concurrent.impl.FutureConvertersImpl;
|
||||
|
||||
public class UnresolvedCommand extends RuntimeException {
|
||||
private final Cmd cmd;
|
||||
|
||||
public UnresolvedCommand(Cmd cmd, Throwable cause) {
|
||||
super(cause);
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
final String helpmsg = """
|
||||
Could not recognize command 'ARG'.
|
||||
This means that all of the following searches for a compatible command failed:
|
||||
1. commands: no scenario command named 'ARG' is known. (start, run, await, ...)
|
||||
2. scripts: no auto script named './scripts/auto/ARG.js' in the local filesystem.
|
||||
3. scripts: no auto script named 'scripts/auto/ARG.js' was found in the PROG binary.
|
||||
4. workloads: no workload file named ARG[.yaml] was found in the local filesystem, even in include paths INCLUDES.
|
||||
5. workloads: no workload file named ARG[.yaml] was bundled in PROG binary, even in include paths INCLUDES.
|
||||
6. apps: no application named ARG was bundled in PROG.
|
||||
|
||||
You can discover available ways to invoke PROG by using the various --list-* commands:
|
||||
[ --list-commands, --list-scripts, --list-workloads (and --list-scenarios), --list-apps ]
|
||||
"""
|
||||
.replaceAll("ARG", getCmdName())
|
||||
.replaceAll("PROG", "nb5");
|
||||
|
||||
return super.toString() + "\nadditional diagnostics:\n" + helpmsg;
|
||||
}
|
||||
|
||||
private String getCmdName() {
|
||||
String impl = cmd.getArgMap().get("_impl");
|
||||
if (impl!=null) return impl;
|
||||
return cmd.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2024 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.engine.core.lifecycle.session;
|
||||
|
||||
import io.nosqlbench.engine.cmdstream.Cmd;
|
||||
import io.nosqlbench.engine.cmdstream.CmdArg;
|
||||
import io.nosqlbench.nb.api.labels.NBLabeledElement;
|
||||
import io.nosqlbench.nb.api.labels.NBLabels;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class NBSessionTest implements NBLabeledElement {
|
||||
|
||||
@Test
|
||||
public void testThatSessionShortCircuitsCommandErrors() {
|
||||
NBSession session = new NBSession(this, "session_name", Map.of());
|
||||
Cmd c1 = new Cmd("test_ok", Map.of("test_ok", CmdArg.of("test_ok","key1","===","value1")));
|
||||
Cmd c2 = new Cmd("test_error", Map.of());
|
||||
Cmd c3 = new Cmd("test_ok", Map.of("test_ok", CmdArg.of("test_ok","key2","===","value2")));
|
||||
List<Cmd> cmdStream = List.of(c1, c2, c3);
|
||||
|
||||
session.apply(cmdStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBLabels getLabels() {
|
||||
return NBLabels.forKV("testing","session");
|
||||
}
|
||||
}
|
||||
@@ -23,15 +23,16 @@ import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A service loader filter which works with {@link io.nosqlbench.nb.annotations.Service} to load a named service.
|
||||
* This version requires the caller to provide the service loader instance, since it is now caller sensitive.
|
||||
*
|
||||
* <P>A service loader filter which works with {@link io.nosqlbench.nb.annotations.Service} to load a named service.
|
||||
* This version requires the caller to provide the service loader instance, since it is now caller sensitive.</P>
|
||||
* <p>
|
||||
* Use it like this:<pre>{@code
|
||||
* ResultValueFilterType filterType =
|
||||
* ServiceSelector.of("core", ServiceLoader.load(ResultValueFilterType.class)).get();
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T> The service type
|
||||
* @param <T>
|
||||
* The service type
|
||||
*/
|
||||
public class ServiceSelector<T> implements Predicate<ServiceLoader.Provider<? extends T>> {
|
||||
private final String name;
|
||||
@@ -61,11 +62,13 @@ public class ServiceSelector<T> implements Predicate<ServiceLoader.Provider<? ex
|
||||
|
||||
public ServiceLoader.Provider<? extends T> getOneProvider() {
|
||||
List<? extends ServiceLoader.Provider<? extends T>> providers = getAllProviders();
|
||||
if (providers.size()==0 || providers.size()>1) {
|
||||
throw new RuntimeException("You requested exactly one instance of a service by name '" + name + "', but got " +
|
||||
(providers.stream().map(s -> s.getClass().getSimpleName())).collect(Collectors.joining(",")) + " (" + providers.stream().count() + ")");
|
||||
if (providers.size() != 1) {
|
||||
throw new RuntimeException(
|
||||
"You requested exactly one instance of a service by name '" + name + "', but got " +
|
||||
(providers.stream().map(s -> s.getClass().getSimpleName())).collect(Collectors.joining(",")) + " (" + providers.size() + ")"
|
||||
);
|
||||
}
|
||||
return providers.get(0);
|
||||
return providers.getFirst();
|
||||
}
|
||||
|
||||
public T getOne() {
|
||||
@@ -73,7 +76,7 @@ public class ServiceSelector<T> implements Predicate<ServiceLoader.Provider<? ex
|
||||
}
|
||||
|
||||
public List<? extends ServiceLoader.Provider<? extends T>> getAllProviders() {
|
||||
List<? extends ServiceLoader.Provider<? extends T>> providers = loader
|
||||
return loader
|
||||
.stream()
|
||||
.peek(l -> {
|
||||
if (l.type().getAnnotation(Service.class) == null) {
|
||||
@@ -87,8 +90,8 @@ public class ServiceSelector<T> implements Predicate<ServiceLoader.Provider<? ex
|
||||
.filter(l -> l.type().getAnnotation(Service.class) != null)
|
||||
.filter(l -> l.type().getAnnotation(Service.class).selector().equals(name))
|
||||
.toList();
|
||||
return providers;
|
||||
}
|
||||
|
||||
public List<? extends T> getAll() {
|
||||
List<? extends ServiceLoader.Provider<? extends T>> providers = getAllProviders();
|
||||
return providers.stream()
|
||||
@@ -99,7 +102,7 @@ public class ServiceSelector<T> implements Predicate<ServiceLoader.Provider<? ex
|
||||
public Optional<? extends T> get() {
|
||||
List<? extends T> services = getAll();
|
||||
if (services.size() == 1) {
|
||||
return Optional.of(services.get(0));
|
||||
return Optional.of(services.getFirst());
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class ComponentPulse extends UnstartedPeriodicTaskComponent {
|
||||
LastReport.OnInterrupt
|
||||
);
|
||||
this.pulseOf = pulseOf;
|
||||
String logsdir = getComponentProp("logsdir").orElseThrow();
|
||||
String logsdir = getComponentProp("logsdir").orElse("logs");
|
||||
String labelElement = pulseOf.getLabels().valueOf(fileNameLabel);
|
||||
this.hbpath = Path.of(logsdir).resolve(labelElement +"_status.yaml");
|
||||
this.linkpath = Path.of(logsdir).resolve("status.yaml");
|
||||
|
||||
@@ -20,10 +20,13 @@ import io.nosqlbench.nb.api.components.core.NBComponent;
|
||||
import io.nosqlbench.nb.api.labels.NBLabels;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A <EM>live</EM> component is one which provides evidence that it is either
|
||||
* in a healthy state or that it is not, via a heartbeat mechanism.
|
||||
* A <EM>heartbeat</EM> component is one which provides evidence that it is either
|
||||
* in a healthy state or that it is not, via a heartbeat mechanism. This requires
|
||||
* that a component property 'heartbeat' is provides which is the millisecond interval
|
||||
* between beats.
|
||||
*/
|
||||
public class NBHeartbeatComponent extends NBStatusComponent {
|
||||
|
||||
@@ -33,8 +36,12 @@ public class NBHeartbeatComponent extends NBStatusComponent {
|
||||
|
||||
public NBHeartbeatComponent(NBComponent parentComponent, NBLabels componentSpecificLabelsOnly, Map<String, String> props, String liveLabel) {
|
||||
super(parentComponent, componentSpecificLabelsOnly, props);
|
||||
// attaches, no further reference needed
|
||||
new ComponentPulse(this, NBLabels.forKV(), liveLabel, Long.parseLong(getComponentProp("heartbeat").orElse("60000")));
|
||||
getComponentProp("heartbeat")
|
||||
.map(Long::parseLong)
|
||||
.ifPresent(
|
||||
// attaches, no further reference needed
|
||||
hbmillis -> new ComponentPulse(this, NBLabels.forKV(), liveLabel, hbmillis)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ class ExitStatusIntegrationTests {
|
||||
"driver=diag", "cyclerate=10", "not_a_thing", "cycles=100", "-vvv"
|
||||
);
|
||||
String stdout = String.join("\n", result.getStdoutData());
|
||||
assertThat(stdout).contains("internal error: You requested exactly one instance of a service by name 'not_a_thing'");
|
||||
assertThat(stdout).contains("You requested exactly one instance of a service by name 'not_a_thing'");
|
||||
assertThat(result.exitStatus).isEqualTo(2);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user