diff --git a/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4OpMapper.java b/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4OpMapper.java index d9979013c..e04cb14a2 100644 --- a/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4OpMapper.java +++ b/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4OpMapper.java @@ -9,7 +9,7 @@ import io.nosqlbench.adapter.cqld4.processors.CqlFieldCaptureProcessor; 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.engine.api.templating.ParsedOp; import io.nosqlbench.nb.api.config.params.ParamsParser; import io.nosqlbench.nb.api.config.standard.NBConfiguration; import io.nosqlbench.nb.api.errors.BasicError; @@ -30,7 +30,7 @@ public class Cqld4OpMapper implements OpMapper { this.cache = cache; } - public OpDispenser apply(ParsedCommand cmd) { + public OpDispenser apply(ParsedOp cmd) { ParsedTemplate stmtTpl = cmd.getStmtAsTemplate().orElseThrow(() -> new BasicError( "No statement was found in the op template:" + cmd diff --git a/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/CqlD4PreparedBatchOpDispenser.java b/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/CqlD4PreparedBatchOpDispenser.java index 263b087d2..5d5cc2a94 100644 --- a/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/CqlD4PreparedBatchOpDispenser.java +++ b/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/CqlD4PreparedBatchOpDispenser.java @@ -3,15 +3,15 @@ package io.nosqlbench.adapter.cqld4.opdispensers; import com.datastax.oss.driver.api.core.CqlSession; import io.nosqlbench.adapter.cqld4.Cqld4Op; import io.nosqlbench.engine.api.activityimpl.OpDispenser; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; import io.nosqlbench.nb.api.errors.BasicError; public class CqlD4PreparedBatchOpDispenser implements OpDispenser { private final CqlSession session; - private final ParsedCommand cmd; + private final ParsedOp cmd; - public CqlD4PreparedBatchOpDispenser(CqlSession session, ParsedCommand cmd) { + public CqlD4PreparedBatchOpDispenser(CqlSession session, ParsedOp cmd) { this.session = session; this.cmd = cmd; } diff --git a/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4BatchStatementDispenser.java b/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4BatchStatementDispenser.java index 134a4dd07..e4527c0b2 100644 --- a/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4BatchStatementDispenser.java +++ b/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4BatchStatementDispenser.java @@ -3,13 +3,13 @@ package io.nosqlbench.adapter.cqld4.opdispensers; import com.datastax.oss.driver.api.core.CqlSession; import io.nosqlbench.adapter.cqld4.Cqld4Op; import io.nosqlbench.engine.api.activityimpl.OpDispenser; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; public class Cqld4BatchStatementDispenser implements OpDispenser { private final CqlSession session; - private final ParsedCommand cmd; + private final ParsedOp cmd; - public Cqld4BatchStatementDispenser(CqlSession session, ParsedCommand cmd) { + public Cqld4BatchStatementDispenser(CqlSession session, ParsedOp cmd) { this.session = session; this.cmd = cmd; } diff --git a/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4PreparedStmtDispenser.java b/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4PreparedStmtDispenser.java index c8d93c118..0c621e7b5 100644 --- a/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4PreparedStmtDispenser.java +++ b/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4PreparedStmtDispenser.java @@ -8,7 +8,7 @@ import io.nosqlbench.adapter.cqld4.Cqld4OpMetrics; import io.nosqlbench.adapter.cqld4.optypes.Cqld4PreparedStatement; import io.nosqlbench.adapter.cqld4.RSProcessors; import io.nosqlbench.engine.api.activityimpl.OpDispenser; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; import io.nosqlbench.virtdata.core.templates.ParsedTemplate; import java.util.function.LongFunction; @@ -24,7 +24,7 @@ public class Cqld4PreparedStmtDispenser implements OpDispenser { private final Cqld4OpMetrics metrics; private final RSProcessors processors; - public Cqld4PreparedStmtDispenser(CqlSession session, ParsedCommand cmd, RSProcessors processors) { + public Cqld4PreparedStmtDispenser(CqlSession session, ParsedOp cmd, RSProcessors processors) { this.session = session; this.processors = processors; diff --git a/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4SimpleCqlStmtDispenser.java b/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4SimpleCqlStmtDispenser.java index a658d15d2..0928ba6de 100644 --- a/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4SimpleCqlStmtDispenser.java +++ b/adapter-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/opdispensers/Cqld4SimpleCqlStmtDispenser.java @@ -6,17 +6,17 @@ import io.nosqlbench.adapter.cqld4.Cqld4Op; import io.nosqlbench.adapter.cqld4.Cqld4OpMetrics; import io.nosqlbench.adapter.cqld4.optypes.Cqld4SimpleCqlStatement; import io.nosqlbench.engine.api.activityimpl.OpDispenser; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; public class Cqld4SimpleCqlStmtDispenser implements OpDispenser { private final CqlSession session; - private final ParsedCommand cmd; + private final ParsedOp cmd; private final int maxpages; private final boolean retryreplace; private final Cqld4OpMetrics metrics; - public Cqld4SimpleCqlStmtDispenser(CqlSession session, ParsedCommand cmd) { + public Cqld4SimpleCqlStmtDispenser(CqlSession session, ParsedOp cmd) { this.session = session; this.cmd = cmd; this.maxpages = cmd.getStaticConfigOr("maxpages",1); diff --git a/adapters-api/src/main/java/io/nosqlbench/engine/api/activityimpl/OpMapper.java b/adapters-api/src/main/java/io/nosqlbench/engine/api/activityimpl/OpMapper.java index e1c3f24e4..93a09a086 100644 --- a/adapters-api/src/main/java/io/nosqlbench/engine/api/activityimpl/OpMapper.java +++ b/adapters-api/src/main/java/io/nosqlbench/engine/api/activityimpl/OpMapper.java @@ -1,7 +1,7 @@ package io.nosqlbench.engine.api.activityimpl; import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; import java.util.function.Function; @@ -39,7 +39,7 @@ import java.util.function.Function; * *

Implementation Strategy

*

- * A view of an op template is provided in the {@link ParsedCommand} API. This allows + * A view of an op template is provided in the {@link ParsedOp} API. This allows * you to examine the fields provided by users. It also lets you see which * of these fields are defined as dynamic and which are simply static values. * When multiple types of operations are supported for a driver adapter, you must decide @@ -62,16 +62,16 @@ import java.util.function.Function; * to hold all the details for executing an operation, * generally something that implements {@link Runnable}. */ -public interface OpMapper extends Function> { +public interface OpMapper extends Function> { /** * Interrogate the parsed command, and provide a new * - * @param cmd The {@link ParsedCommand} which is the parsed version of the user-provided op template. + * @param cmd The {@link ParsedOp} which is the parsed version of the user-provided op template. * This contains all the fields provided by the user, as well as explicit knowledge of * which ones are static and dynamic. * @return An OpDispenser which can be used to synthesize real operations. */ @Override - OpDispenser apply(ParsedCommand cmd); + OpDispenser apply(ParsedOp cmd); } diff --git a/adapters-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/DriverAdapter.java b/adapters-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/DriverAdapter.java index 7b6b3cffa..50829d611 100644 --- a/adapters-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/DriverAdapter.java +++ b/adapters-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/DriverAdapter.java @@ -3,7 +3,7 @@ package io.nosqlbench.engine.api.activityimpl.uniform; import io.nosqlbench.engine.api.activityimpl.OpDispenser; import io.nosqlbench.engine.api.activityimpl.OpMapper; import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; import io.nosqlbench.nb.api.config.standard.NBConfiguration; import java.util.Map; @@ -36,7 +36,7 @@ public interface DriverAdapter { *

*

Op Mapping

* An Op Mapper is a function which can look at the parsed - * fields in a {@link ParsedCommand} and create an OpDispenser. + * fields in a {@link ParsedOp} and create an OpDispenser. * An OpDispenser is a function that will produce a special * type {@link R} that this DriverAdapter implements as its * op implementation.

@@ -63,7 +63,7 @@ public interface DriverAdapter { *

*

A note on implementation strategy:

* Generally speaking, implementations of this method should interrogate the op fields - * in the ParsedCommand and return an OpDispenser that matches the user's intentions. + * in the ParsedOp 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 diff --git a/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/ParsedCommand.java b/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/ParsedCommand.java deleted file mode 100644 index ee46c4add..000000000 --- a/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/ParsedCommand.java +++ /dev/null @@ -1,438 +0,0 @@ -package io.nosqlbench.engine.api.templating; - -import io.nosqlbench.engine.api.activityconfig.yaml.OpTemplate; -import io.nosqlbench.engine.api.templating.binders.ArrayBinder; -import io.nosqlbench.engine.api.templating.binders.ListBinder; -import io.nosqlbench.engine.api.templating.binders.OrderedMapBinder; -import io.nosqlbench.nb.api.config.standard.NBConfigError; -import io.nosqlbench.nb.api.config.standard.NBConfiguration; -import io.nosqlbench.nb.api.config.standard.NBTypeConverter; -import io.nosqlbench.nb.api.errors.BasicError; -import io.nosqlbench.nb.api.errors.OpConfigError; -import io.nosqlbench.virtdata.core.bindings.DataMapper; -import io.nosqlbench.virtdata.core.bindings.VirtData; -import io.nosqlbench.virtdata.core.templates.BindPoint; -import io.nosqlbench.virtdata.core.templates.CapturePoint; -import io.nosqlbench.virtdata.core.templates.ParsedTemplate; -import io.nosqlbench.virtdata.core.templates.StringBindings; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.*; -import java.util.function.Function; -import java.util.function.LongFunction; - -/** - * Parse an OpTemplate into a ParsedCommand, which can dispense object maps - */ -public class ParsedCommand implements LongFunction> { - - private final static Logger logger = LogManager.getLogger(ParsedCommand.class); - - /** - * The fields which are statically assigned - **/ - private final Map statics = new LinkedHashMap<>(); - - /** - * The fields which are dynamic, and must be realized via functions. - * This map contains keys which identify the field names, and values, which may be null or undefined. - */ - private final Map> dynamics = new LinkedHashMap<>(); - - /** - * The names of payload values in the result of the operation which should be saved. - * The keys in this map represent the name of the value as it would be found in the native - * representation of a result. If the values are defined, then each one represents the name - * that the found value should be saved as instead of the original name. - */ - private final List> captures = new ArrayList<>(); - private final int mapsize; - - /** - * A prototype of the fully generated map, to be used as the starting point - * when rendering the full map with dynamic values. - */ - private final LinkedHashMap protomap = new LinkedHashMap<>(); - private final OpTemplate ot; - private final NBConfiguration acfg; - - /** - * Create a parsed command from an Op template. - * - * @param ot An OpTemplate representing an operation to be performed in a native driver. - * @param acfg The activity configuration, used for reading config parameters - */ - public ParsedCommand(OpTemplate ot, NBConfiguration acfg) { - this(ot, acfg, List.of()); - } - - /** - * Create a parsed command from an Op template. This version is exactly like - * {@link ParsedCommand(OpTemplate,NBConfiguration)} except that it allows - * preprocessors. Preprocessors are all applied to the the op template before - * it is applied to the parsed command fields, allowing you to combine or destructure - * fields from more tha one representation into a single canonical representation - * for processing. - * - * @param ot The OpTemplate as provided by a user via YAML, JSON, or API (data structure) - * @param acfg The activity configuration, used to resolve nested config parameters - * @param preprocessors Map->Map transformers. - */ - public ParsedCommand(OpTemplate ot, NBConfiguration acfg, List, Map>> preprocessors) { - this.ot = ot; - this.acfg = acfg; - - Map map = ot.getOp().orElseThrow(); - for (Function, Map> preprocessor : preprocessors) { - map = preprocessor.apply(map); - } - - applyTemplateFields(map, ot.getBindings()); - mapsize = statics.size() + dynamics.size(); - } - - // For now, we only allow bind points to reference bindings, not other op template - // fields. This seems like the saner and less confusing approach, so implementing - // op field references should be left until it is requested if at all - private void applyTemplateFields(Map map, Map bindings) { - map.forEach((k, v) -> { - if (v instanceof CharSequence) { - ParsedTemplate pt = ParsedTemplate.of(((CharSequence) v).toString(), bindings); - this.captures.add(pt.getCaptures()); - switch (pt.getType()) { - case literal: - statics.put(k, ((CharSequence) v).toString()); - protomap.put(k, ((CharSequence) v).toString()); - break; - case bindref: - String spec = pt.asBinding().orElseThrow().getBindspec(); - Optional> mapper = VirtData.getOptionalMapper(spec); - dynamics.put(k, mapper.orElseThrow()); - protomap.put(k, null); - break; - case concat: - StringBindings sb = new StringBindings(pt); - dynamics.put(k, sb); - protomap.put(k, null); - break; - } - } else { - // Eventually, nested and mixed static dynamic structure could be supported, but - // it would be complex to implement and also not that efficient, so let's just copy - // structure for now - statics.put(k, v); - protomap.put(k, v); - } - }); - - } - - public String getName() { - return ot.getName(); - } - - public Map getStaticPrototype() { - return statics; - } - - public Map> getDynamicPrototype() { - return dynamics; - } - - @Override - public Map apply(long value) { - LinkedHashMap map = new LinkedHashMap<>(protomap); - dynamics.forEach((k, v) -> { - map.put(k, v.apply(value)); - }); - return map; - } - - public boolean isDefinedDynamic(String field) { - return dynamics.containsKey(field); - } - - - /** - * @param field The field name to look for in the static field map. - * @return true if and only if the named field is present in the static field map. - */ - public boolean isDefinedStatic(String field) { - return statics.containsKey(field); - } - - public boolean isDefinedStatic(String field, Class type) { - return statics.containsKey(field) && type.isAssignableFrom(field.getClass()); - } - - /** - * @param fields Names of fields to look for in the static field map. - * @return true if and only if all provided field names are present in the static field map. - */ - public boolean isDefinedStaticAll(String... fields) { - for (String field : fields) { - if (!statics.containsKey(field)) { - return false; - } - } - return true; - } - - /** - * Get the static value for the provided name, cast to the required type. - * - * @param field Name of the field to get - * @param classOfT The type of the field to return. If actual type is not compatible to a cast to this type, then a - * casting error will be thrown. - * @param The parameter type of the return type, used at compile time only to qualify asserted return type - * @return A value of type T, or null - */ - public T getStaticValue(String field, Class classOfT) { - return (T) statics.get(field); - } - - /** - * Get the static value for the provided name, cast to the required type, where the type is inferred - * from the calling context. - * - * @param field Name of the field to get - * @param The parameter type of the return type. used at compile time only to quality return type. - * @return A value of type T, or null - */ - public T getStaticValue(String field) { - return (T) statics.get(field); - } - - public Optional getStmtAsTemplate() { - return ot.getParsed(); - } - - /** - * Get the named static field value, or return the provided default, but throw an exception if - * the named field is dynamic. - * - * @param name The name of the field value to return. - * @param defaultValue A value to return if the named value is not present in static nor dynamic fields. - * @param The type of the field to return. - * @return The value - * @throws RuntimeException if the field name is only present in the dynamic fields. - */ - public T getStaticValueOr(String name, T defaultValue) { - if (statics.containsKey(name)) { - return (T) statics.get(name); - } else if (dynamics.containsKey(name)) { - throw new BasicError("static 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; - } - } - - /** - * Get the specified parameter by the user using the defined field which is closest to the op - * template. This is the standard way of getting parameter values which can be specified at the - * op template, op param, or activity level. - * - * @param name The name of the configuration param - * @param defaultValue the default value to return if the value is not defined anywhere in - * (op fields, op params, activity params) - * @param The type of the value to return - * @return A configuration value - * @throws io.nosqlbench.nb.api.config.standard.NBConfigError if the named field is defined dynamically, - * as in this case, it is presumed that the parameter is not supported unless it is defined statically. - */ - public T getStaticConfigOr(String name, T defaultValue) { - if (statics.containsKey(name)) { - return NBTypeConverter.convertOr(statics.get(name), defaultValue); - } else if (ot.getParams().containsKey(name)) { - return NBTypeConverter.convertOr(ot.getParams().get(name), defaultValue); - } else if (acfg.getMap().containsKey(name)) { - return NBTypeConverter.convertOr(acfg.get("name"), defaultValue); - } else if (dynamics.containsKey(name)) { - throw new NBConfigError("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; - } - } - - public Optional getOptionalStaticConfig(String name, Class type) { - if (statics.containsKey(name)) { - return Optional.of(NBTypeConverter.convert(statics.get(name), type)); - } else if (ot.getParams().containsKey(name)) { - return Optional.of(NBTypeConverter.convert(ot.getParams().get(name), type)); - } else if (acfg.getMap().containsKey(name)) { - return Optional.of(NBTypeConverter.convert(acfg.get("name"), type)); - } else if (dynamics.containsKey("name")) { - throw new NBConfigError("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 Optional.empty(); - } - } - - - /** - * Works exactly like {@link #getStaticConfigOr(String, Object)}, except that dynamic values - * at the op field level will be generated on a per-input basis. This is a shortcut method for - * allowing configuration values to be accessed dynamically where it makes sense. - */ - public T getConfigOr(String name, T defaultValue, long input) { - if (statics.containsKey(name)) { - return NBTypeConverter.convertOr(statics.get(name), defaultValue); - } else if (dynamics.containsKey(name)) { - return NBTypeConverter.convertOr(dynamics.get(name).apply(input), defaultValue); - } else if (ot.getParams().containsKey(name)) { - return NBTypeConverter.convertOr(ot.getParams().get(name), defaultValue); - } else if (acfg.getMap().containsKey(name)) { - return NBTypeConverter.convertOr(acfg.get("name"), defaultValue); - } else return defaultValue; - - } - - - /** - * Return an optional value for the named field. This is an {@link Optional} form of {@link #getStaticValue}. - * - * @param field Name of the field to get - * @param classOfT The type of field to return. If the actual type is not compatible to a cast to this type, - * then a casting error will be thrown. - * @param The parameter type of the return - * @return An optional value, empty unless the named value is defined in the static field map. - */ - public Optional getStaticValueOptionally(String field, Class classOfT) { - return Optional.ofNullable(getStaticValue(field, classOfT)); - } - - public Optional getStaticValueOptionally(String field) { - return Optional.ofNullable(getStaticValue(field)); - } - - /** - * Get the named field value for a given long input. This uses parameter type inference -- The casting - * to the return type will be based on the type of any assignment or casting on the caller's side. - * Thus, if the actual type is not compatable to a cast to the needed return type, a casting error will - * be thrown. - * - * @param field The name of the field to get. - * @param input The seed value, or cycle value for which to generate the value. - * @param The parameter type of the returned value. Inferred from usage context. - * @return The value. - */ - public T get(String field, long input) { - if (statics.containsKey(field)) { - return (T) statics.get(field); - } - if (dynamics.containsKey(field)) { - return (T) dynamics.get(field).apply(input); - } - return null; - } - - /** - * Get the map of all fields for the given input cycle. - * - * @param l seed value, cycle number, input... - * @return A map of named objects - */ - public Map getMap(long l) { - return apply(l); - } - - public Set getDefinedNames() { - HashSet nameSet = new HashSet<>(statics.keySet()); - nameSet.addAll(dynamics.keySet()); - return nameSet; - } - - public LongFunction getAsFunctionOr(String name, V defaultValue) { - if (isDefinedStatic(name)) { - V value = getStaticValue(name); - return l -> value; - } else if (isDefinedDynamic(name)) { - return l -> get(name, l); - } else { - return l -> defaultValue; - } - } - - public boolean isDefined(String field) { - return statics.containsKey(field) || dynamics.containsKey(field); - } - - public boolean isDefinedAll(String... fields) { - for (String field : fields) { - if (!statics.containsKey(field) && !dynamics.containsKey(field)) { - return false; - } - } - return true; - } - - public void requireStaticFields(String... fields) { - for (String field : fields) { - if (!statics.containsKey(field)) { - Set missing = new HashSet<>(); - for (String readoutfield : fields) { - if (!statics.containsKey(readoutfield)) { - missing.add(readoutfield); - } - } - throw new OpConfigError("Fields " + missing + " are required to be defined with static values for this type of operation."); - } - } - } - - public LongFunction> newListBinder(String... fields) { - return new ListBinder(this, fields); - } - - public LongFunction> newListBinder(List fields) { - return new ListBinder(this, fields); - } - - public LongFunction> newOrderedMapBinder(String... fields) { - return new OrderedMapBinder(this, fields); - - } - - public LongFunction newArrayBinder(String... fields) { - return new ArrayBinder(this, fields); - } - - public LongFunction newArrayBinder(List fields) { - return new ArrayBinder(this, fields); - } - - public LongFunction newArrayBinderFromBindPoints(List bindPoints) { - return new ArrayBinder(bindPoints); - } - - public LongFunction getMapper(String field) { - LongFunction mapper = dynamics.get(field); - return mapper; - } - - public int getSize() { - return this.mapsize; - } - - public boolean isUndefined(String field) { - return !(statics.containsKey(field) || dynamics.containsKey(field)); - } - - -// ParsedCommand parseField(String srcField, Function> parser) { -// -// String field = Optional.ofNullable(statics.get(srcField)) -// .filter(o -> o instanceof CharSequence) -// .map(Object::toString) -// .orElseThrow(); -// -// Map newFields = parser.apply(field); -// apply(newFields) -// -// } - -} diff --git a/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/ArrayBinder.java b/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/ArrayBinder.java index 5dbd82600..efa61d75b 100644 --- a/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/ArrayBinder.java +++ b/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/ArrayBinder.java @@ -1,6 +1,6 @@ package io.nosqlbench.engine.api.templating.binders; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; import io.nosqlbench.nb.api.errors.OpConfigError; import io.nosqlbench.virtdata.core.bindings.DataMapper; import io.nosqlbench.virtdata.core.bindings.VirtData; @@ -17,7 +17,7 @@ public class ArrayBinder implements LongFunction { private final LongFunction[] mapperary; private final int[] dindexes; - public ArrayBinder(ParsedCommand cmd, String[] fields) { + public ArrayBinder(ParsedOp cmd, String[] fields) { this.protoary = new Object[fields.length]; this.mapperary = new LongFunction[fields.length]; int[] indexes = new int[fields.length]; @@ -25,7 +25,7 @@ public class ArrayBinder implements LongFunction { for (int i = 0; i < fields.length; i++) { String field = fields[i]; - if (cmd.isDefinedStatic(field)) { + if (cmd.isStatic(field)) { protoary[i] = cmd.getStaticValue(field); } else if (cmd.isDefinedDynamic(field)) { mapperary[i] = cmd.getMapper(field); @@ -37,7 +37,7 @@ public class ArrayBinder implements LongFunction { this.dindexes = Arrays.copyOf(indexes, nextIndex); } - public ArrayBinder(ParsedCommand cmd, List fields) { + public ArrayBinder(ParsedOp cmd, List fields) { this(cmd, fields.toArray(new String[0])); } diff --git a/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/ListBinder.java b/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/ListBinder.java index 8d3ec9984..a39eedfb0 100644 --- a/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/ListBinder.java +++ b/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/ListBinder.java @@ -1,6 +1,6 @@ package io.nosqlbench.engine.api.templating.binders; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; import io.nosqlbench.nb.api.errors.OpConfigError; import java.util.ArrayList; @@ -14,7 +14,7 @@ public class ListBinder implements LongFunction> { private final ArrayList> mapperlist; private final int[] dindexes; - public ListBinder(ParsedCommand cmd, String... fields) { + public ListBinder(ParsedOp cmd, String... fields) { this.protolist = new ArrayList<>(fields.length); this.mapperlist = new ArrayList<>(fields.length); int[] indexes = new int[fields.length]; @@ -22,7 +22,7 @@ public class ListBinder implements LongFunction> { for (int i = 0; i < fields.length; i++) { String field = fields[i]; - if (cmd.isDefinedStatic(field)) { + if (cmd.isStatic(field)) { protolist.add(cmd.getStaticValue(field)); mapperlist.add(null); } else if (cmd.isDefinedDynamic(field)) { @@ -36,7 +36,7 @@ public class ListBinder implements LongFunction> { this.dindexes = Arrays.copyOf(indexes,lastIndex); } - public ListBinder(ParsedCommand cmd, List fields) { + public ListBinder(ParsedOp cmd, List fields) { this(cmd,fields.toArray(new String[0])); } diff --git a/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/OrderedMapBinder.java b/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/OrderedMapBinder.java index 877271916..32da400be 100644 --- a/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/OrderedMapBinder.java +++ b/adapters-api/src/main/java/io/nosqlbench/engine/api/templating/binders/OrderedMapBinder.java @@ -1,6 +1,6 @@ package io.nosqlbench.engine.api.templating.binders; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; import io.nosqlbench.nb.api.errors.OpConfigError; import java.util.HashMap; @@ -13,9 +13,9 @@ public class OrderedMapBinder implements LongFunction> { private final Map protomap = new LinkedHashMap<>(); private final Map> bindermap = new HashMap<>(); - public OrderedMapBinder(ParsedCommand cmd, String... fields) { + public OrderedMapBinder(ParsedOp cmd, String... fields) { for (String field : fields) { - if (cmd.isDefinedStatic(field)) { + if (cmd.isStatic(field)) { protomap.put(field,cmd.getStaticValue(field)); } else if (cmd.isDefinedDynamic(field)) { bindermap.put(field,cmd.getMapper(field)); diff --git a/devdocs/devguide/drivers/driver_adapter_standards.md b/devdocs/devguide/drivers/driver_adapter_standards.md index af5b83e2e..b4db94b23 100644 --- a/devdocs/devguide/drivers/driver_adapter_standards.md +++ b/devdocs/devguide/drivers/driver_adapter_standards.md @@ -61,7 +61,7 @@ which is the same across all driver types that can be used with NoSQLBench. The Op Templates which are provided by users are normalized by NoSQLBench into a standard representation that is used within the op mapping and synthesis steps. This representation is -provided by the ParsedCommand and ParsedTemplate APIs. The User-Facing construct is _Op Template_, +provided by the ParsedOp and ParsedTemplate APIs. The User-Facing construct is _Op Template_, while the developer building driver adapters only sees _Parsed Commands_ and a fully-normalized API. ## Effective Op Mapping @@ -74,9 +74,9 @@ constructor. Op Mappers may need access to the activity's parameters or the acti These can be provided from the DriverAdapter base type when needed. Assuming you provide the activity params and the space cache to an OpMapper implementation, when -it's `apply(ParsedCommand cmd)` method is called, you have access to a few levels of information: +it's `apply(ParsedOp cmd)` method is called, you have access to a few levels of information: -1. The ParsedCommand -- representing the specific details of an operation to be performed: +1. The ParsedOp -- representing the specific details of an operation to be performed: * op field names * static field values - literal values or any non-string collection type (map, set, list) * dynamic field values - Any type which contains a string template or a single binding @@ -142,12 +142,12 @@ Activites have configuration at various levels: 5. op template fields Op template fields (seen by the NB driver developer through the -ParsedCommand API) are properly meant to specify a distinct type of operation +ParsedOp API) are properly meant to specify a distinct type of operation by its defined properties, no less or more. However, users will sometimes put op params into the op template alongside the op fields. This is *OK*. *The rule of thumb is to ensure that a named field can only be used as an -op field or an op param but not both.* Each ParsedCommand has access to +op field or an op param but not both.* Each ParsedOp has access to all of the layers above, and should be used to extract out the fields which are properly configuration level data before the fields are used for op mapping. By using this technique, op fields can be configured from any convenient diff --git a/drivers-api/src/test/java/io/nosqlbench/engine/api/templating/ParsedCommandTest.java b/drivers-api/src/test/java/io/nosqlbench/engine/api/templating/ParsedCommandTest.java deleted file mode 100644 index 2db9962a6..000000000 --- a/drivers-api/src/test/java/io/nosqlbench/engine/api/templating/ParsedCommandTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package io.nosqlbench.engine.api.templating; - -import io.nosqlbench.engine.api.activityconfig.yaml.OpData; -import io.nosqlbench.nb.api.config.standard.ConfigModel; -import io.nosqlbench.nb.api.config.standard.Param; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.Map; -import java.util.function.LongFunction; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ParsedCommandTest { - - ParsedCommand pc = new ParsedCommand( - new OpData().applyFields( - Map.of( - "op", Map.of( - "stmt", "test", - "dyna1", "{dyna1}", - "dyna2", "{{NumberNameToString()}}", - "identity", "{{Identity()}}" - ), - "bindings", Map.of( - "dyna1", "NumberNameToString()" - ) - ) - ), - ConfigModel.of(ParsedCommandTest.class) - .add(Param.defaultTo("testcfg","testval")) - .asReadOnly() - .apply(Map.of()) - ); - - @Test - public void testParsedCommand() { - Map m1 = pc.apply(0); - assertThat(m1).containsEntry("stmt", "test"); - assertThat(m1).containsEntry("dyna1","zero"); - assertThat(m1).containsEntry("dyna2","zero"); - assertThat(m1).containsEntry("identity", 0L); - } - - @Test - public void testNewListBinder() { - LongFunction> lb = pc.newListBinder("dyna1", "identity", "dyna2", "identity"); - List objects = lb.apply(1); - assertThat(objects).isEqualTo(List.of("one",1L,"one",1L)); - } - - @Test - public void testNewMapBinder() { - LongFunction> mb = pc.newOrderedMapBinder("dyna1", "identity", "dyna2"); - Map objects = mb.apply(2); - assertThat(objects).isEqualTo(Map.of("dyna1","two","identity",2L,"dyna2","two")); - } - - @Test - public void testNewAryBinder() { - LongFunction ab = pc.newArrayBinder("dyna1", "dyna1", "identity", "identity"); - Object[] objects = ab.apply(3); - assertThat(objects).isEqualTo(new Object[]{"three","three",3L,3L}); - } -} diff --git a/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java b/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java index 0e97ceb4b..1471a6ae5 100644 --- a/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java +++ b/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java @@ -21,7 +21,7 @@ import io.nosqlbench.engine.api.activityimpl.input.ProgressCapable; import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op; import io.nosqlbench.engine.api.metrics.ActivityMetrics; import io.nosqlbench.engine.api.templating.CommandTemplate; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; import io.nosqlbench.engine.api.templating.StrInterpolator; import io.nosqlbench.nb.api.config.standard.NBConfiguration; import io.nosqlbench.nb.api.errors.BasicError; @@ -427,11 +427,11 @@ public class SimpleActivity implements Activity, ProgressCapable { } protected OpSequence> createOpSourceFromCommands( - Function> opinit, + Function> opinit, NBConfiguration cfg, List, Map>> parsers ) { - Function f = t -> new ParsedCommand(t, cfg, parsers); + Function f = t -> new ParsedOp(t, cfg, parsers); Function> opTemplateOFunction = f.andThen(opinit); return createOpSequence(opTemplateOFunction); } diff --git a/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/StandardActivity.java b/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/StandardActivity.java index b23868820..16fac2f0c 100644 --- a/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/StandardActivity.java +++ b/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/StandardActivity.java @@ -7,7 +7,7 @@ import io.nosqlbench.engine.api.activityimpl.ActivityDef; import io.nosqlbench.engine.api.activityimpl.OpDispenser; import io.nosqlbench.engine.api.activityimpl.SimpleActivity; import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op; -import io.nosqlbench.engine.api.templating.ParsedCommand; +import io.nosqlbench.engine.api.templating.ParsedOp; import io.nosqlbench.nb.api.errors.OpConfigError; import java.util.List; @@ -33,7 +33,7 @@ public class StandardActivity extends SimpleActivity { this.adapter = adapter; try { - Function> opmapper = adapter.getOpMapper(); + Function> opmapper = adapter.getOpMapper(); Function, Map> preprocessor = adapter.getPreprocessor(); sequence = createOpSourceFromCommands(opmapper, adapter.getConfiguration(), List.of(preprocessor)); opsource= OpSource.of(sequence);