improvements to cqld4

This commit is contained in:
Jonathan Shook 2021-07-09 15:35:21 -05:00
parent e88197a1b8
commit f7bf1a0276
6 changed files with 83 additions and 43 deletions

View File

@ -1,9 +1,8 @@
package io.nosqlbench.adapter.cqld4;
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
import io.nosqlbench.engine.api.activityimpl.OpMapper;
import io.nosqlbench.engine.api.activityimpl.uniform.BaseDriverAdapter;
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
import io.nosqlbench.engine.api.templating.ParsedCommand;
import io.nosqlbench.nb.annotations.Service;
import java.util.function.Function;
@ -14,7 +13,7 @@ public class Cqld4DriverAdapter extends BaseDriverAdapter<Cqld4Op,Cqld4Space> {
private Cqld4SpaceCache sessionCache;
@Override
public Function<ParsedCommand, OpDispenser<Cqld4Op>> getOpMapper() {
public OpMapper<Cqld4Op> getOpMapper() {
return new Cqld4OpMapper(getSpaceCache());
}

View File

@ -9,7 +9,6 @@ import io.nosqlbench.engine.api.activityimpl.OpDispenser;
import io.nosqlbench.engine.api.activityimpl.OpMapper;
import io.nosqlbench.engine.api.activityimpl.uniform.DriverSpaceCache;
import io.nosqlbench.engine.api.templating.ParsedCommand;
import io.nosqlbench.nb.api.errors.BasicError;
public class Cqld4OpMapper implements OpMapper<Cqld4Op> {
@ -22,18 +21,9 @@ public class Cqld4OpMapper implements OpMapper<Cqld4Op> {
public OpDispenser<Cqld4Op> apply(ParsedCommand cmd) {
// if session field = static string, else ...
boolean prepared = cmd.getStaticValueOr("prepared",false);
boolean batch = cmd.getStaticValueOr("boolean",false);
if (cmd.isDefinedDynamic("session")) {
throw new BasicError("This driver adapter does not support dynamic sessions.");
}
// If it did, we would use something like this instead...
// LongFunction<String> session = cmd.getAsFunctionOr("session", "default");
Cqld4Space cqld4Space = cache.get(cmd.getStaticValueOr("session", "default"));
Cqld4Space cqld4Space = cache.get(cmd.getStaticConfigOr("space", "default"));
boolean prepared = cmd.getStaticConfigOr("prepared",true);
boolean batch = cmd.getStaticConfigOr("boolean",false);
CqlSession session = cqld4Space.getSession();
if (prepared && batch) {

View File

@ -1,9 +1,8 @@
package io.nosqlbench.driver.direct;
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
import io.nosqlbench.engine.api.activityimpl.OpMapper;
import io.nosqlbench.engine.api.activityimpl.uniform.BaseDriverAdapter;
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
import io.nosqlbench.engine.api.templating.ParsedCommand;
import io.nosqlbench.nb.annotations.Service;
import java.util.List;
@ -29,7 +28,7 @@ public class DirectCallAdapter extends BaseDriverAdapter<DirectCall,Void> {
}
@Override
public Function<ParsedCommand, OpDispenser<DirectCall>> getOpMapper() {
public OpMapper<DirectCall> getOpMapper() {
return new DirectOpMapper();
}
}

View File

@ -1,18 +1,21 @@
package io.nosqlbench.driver.direct;
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
import io.nosqlbench.engine.api.activityimpl.OpMapper;
import io.nosqlbench.engine.api.templating.ParsedCommand;
import io.nosqlbench.nb.api.errors.OpConfigError;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.function.Function;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.LongFunction;
import java.util.stream.Collectors;
public class DirectOpMapper implements Function<ParsedCommand, OpDispenser<DirectCall>> {
public class DirectOpMapper implements OpMapper<DirectCall> {
@Override
public OpDispenser<DirectCall> apply(ParsedCommand cmd) {

View File

@ -2,6 +2,7 @@ package io.nosqlbench.engine.api.activityimpl.uniform;
import io.nosqlbench.engine.api.activityapi.core.ActivityType;
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
import io.nosqlbench.engine.api.activityimpl.OpMapper;
import io.nosqlbench.engine.api.templating.ParsedCommand;
import java.util.Map;
@ -31,15 +32,50 @@ public interface DriverAdapter<R extends Runnable, S> {
/**
* <p>
* <H2>Op Mapping</H2>
* An Op Mapper is a function which can look at the parsed
* fields in a {@link ParsedCommand} and create an OpDispenser.
* An OpDispenser is a function that will produce an special
* An OpDispenser is a function that will produce a special
* type {@link R} that this DriverAdapter implements as its
* op implementation.
* op implementation.</p>
*
* <p>
* The function that is returned is responsible for creating another function.
* This might seem counter-intuitive but it is very intentional because
* of these design constraints:
* <UL>
* <LI>Mapping op semantics to a type of operation must be very clear
* and flexible. Performance is not important at this layer because this is all done
* during initialization time for an activity.</LI>
* <LI>Synthesizing executable operations from a known type of operational template
* must be done very efficiently. This part is done during activity execution, so
* having the details of how you are going to create an op for execution already
* sorted out is important.</LI>
* </UL>
*
* To clarify the distinction between these two phases, the first is canonically
* called <em>op mapping</em> in the documentation. The second is called
* <em>op synthesis</em>.
* </p>
*
* <p>
* <H2>A note on implementation strategy</H2>
* Generally speaking, implementations of this method should interrogate the op fields
* in the ParsedCommand and return an OpDispenser that matches the user's intentions.
* This can be based on something explicit, like the value of a {@code type} field,
* or it can be based on whether certain fields are present or not. Advanced implementations
* might take into account which fields are provided as static values and which are
* specified as bindings. In any case, the op mapping phase is meant to qualify and
* pre-check that the fields provided are valid and specific for a given type of operation.
* What happens within {@link OpDispenser} implementations, however, should do
* as little qualification of field value as possible, focusing simply on constructing
* the type of operation for which they are designed.
* </p>
*
* @return a synthesizer function for {@link R} op generation
*/
Function<ParsedCommand, OpDispenser<R>> getOpMapper();
OpMapper<R> getOpMapper();
/**
* The preprocessor function allows the driver adapter to remap
@ -47,19 +83,21 @@ public interface DriverAdapter<R extends Runnable, S> {
* At this level, the transform is applied once to the input map
* (once per op template) to yield the map that is provided to
* {@link io.nosqlbench.engine.api.activityimpl.OpMapper} implementations.
*
* @return A function to pre-process the op template fields.
*/
default Function<Map<String,Object>,Map<String,Object>> getPreprocessor() {
return f->f;
default Function<Map<String, Object>, Map<String, Object>> getPreprocessor() {
return f -> f;
}
/**
* When a driver needs to identify an error uniquely for the purposes of
* routing it to the correct error handler, or naming it in logs, or naming
* metrics, override this method in your activity.
*
* @return A function that can reliably and safely map an instance of Throwable to a stable name.
*/
default Function<Throwable,String> getErrorNameMapper() {
default Function<Throwable, String> getErrorNameMapper() {
return t -> t.getClass().getSimpleName();
}
@ -75,7 +113,7 @@ public interface DriverAdapter<R extends Runnable, S> {
*
* @return A function which can initialize a new S
*/
default Function<String,? extends S> getSpaceInitializer() {
default Function<String, ? extends S> getSpaceInitializer() {
return n -> null;
}
@ -84,6 +122,7 @@ public interface DriverAdapter<R extends Runnable, S> {
* of a DriverAdapter which are not operations. These are generally
* things needed by operations, or things needed during the
* construction of operations.
*
* @return A cache of named objects
*/
DriverSpaceCache<? extends S> getSpaceCache();

View File

@ -25,11 +25,6 @@ public class ParsedCommand implements LongFunction<Map<String, ?>> {
private final static Logger logger = LogManager.getLogger(ParsedCommand.class);
/**
* the name of this operation
**/
private final String name;
/**
* The fields which are statically assigned
**/
@ -50,6 +45,7 @@ public class ParsedCommand implements LongFunction<Map<String, ?>> {
private final List<List<CapturePoint>> captures = new ArrayList<>();
private final int mapsize;
private final LinkedHashMap<String,Object> protomap = new LinkedHashMap<>();
private final OpTemplate ot;
/**
* Create a parsed command from an Op template. The op template is simply the normalized view of
@ -62,7 +58,7 @@ public class ParsedCommand implements LongFunction<Map<String, ?>> {
}
public ParsedCommand(OpTemplate ot, List<Function<Map<String, Object>, Map<String, Object>>> preprocessors) {
this.name = ot.getName();
this.ot = ot;
Map<String, Object> map = ot.getOp().orElseThrow();
for (Function<Map<String, Object>, Map<String, Object>> preprocessor : preprocessors) {
@ -104,7 +100,7 @@ public class ParsedCommand implements LongFunction<Map<String, ?>> {
}
public String getName() {
return name;
return ot.getName();
}
public Map<String, Object> getStaticMap() {
@ -199,6 +195,20 @@ public class ParsedCommand implements LongFunction<Map<String, ?>> {
}
}
public <T> T getStaticConfigOr(String name, T defaultValue) {
if (statics.containsKey(name)) {
return (T) statics.get(name);
} else if (ot.getParams().containsKey(name)) {
return (T) ot.getParams().get(name);
} else if (dynamics.containsKey(name)) {
throw new BasicError("static config field '" + name + "' was defined dynamically. This may be supportable if the driver developer" +
"updates the op mapper to support this field as a dynamic field, but it is not yet supported.");
} else {
return defaultValue;
}
}
/**
* Return an optional value for the named field. This is an {@link Optional} form of {@link #getStaticValue}.