From f7bf1a0276f336bcff145a254f6234c2a9b19d04 Mon Sep 17 00:00:00 2001
From: Jonathan Shook
Date: Fri, 9 Jul 2021 15:35:21 -0500
Subject: [PATCH] improvements to cqld4
---
.../adapter/cqld4/Cqld4DriverAdapter.java | 5 +-
.../adapter/cqld4/Cqld4OpMapper.java | 16 +----
.../driver/direct/DirectCallAdapter.java | 5 +-
.../driver/direct/DirectOpMapper.java | 9 ++-
.../activityimpl/uniform/DriverAdapter.java | 67 +++++++++++++++----
.../engine/api/templating/ParsedCommand.java | 24 +++++--
6 files changed, 83 insertions(+), 43 deletions(-)
diff --git a/driver-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4DriverAdapter.java b/driver-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4DriverAdapter.java
index 616803fc3..47abcf903 100644
--- a/driver-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4DriverAdapter.java
+++ b/driver-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4DriverAdapter.java
@@ -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 {
private Cqld4SpaceCache sessionCache;
@Override
- public Function> getOpMapper() {
+ public OpMapper getOpMapper() {
return new Cqld4OpMapper(getSpaceCache());
}
diff --git a/driver-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4OpMapper.java b/driver-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4OpMapper.java
index 07960d809..8a6648ca6 100644
--- a/driver-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4OpMapper.java
+++ b/driver-cqld4/src/main/java/io/nosqlbench/adapter/cqld4/Cqld4OpMapper.java
@@ -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 {
@@ -22,18 +21,9 @@ public class Cqld4OpMapper implements OpMapper {
public OpDispenser 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 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) {
diff --git a/driver-direct/src/main/java/io/nosqlbench/driver/direct/DirectCallAdapter.java b/driver-direct/src/main/java/io/nosqlbench/driver/direct/DirectCallAdapter.java
index b1936d82d..af9fada5a 100644
--- a/driver-direct/src/main/java/io/nosqlbench/driver/direct/DirectCallAdapter.java
+++ b/driver-direct/src/main/java/io/nosqlbench/driver/direct/DirectCallAdapter.java
@@ -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 {
}
@Override
- public Function> getOpMapper() {
+ public OpMapper getOpMapper() {
return new DirectOpMapper();
}
}
diff --git a/driver-direct/src/main/java/io/nosqlbench/driver/direct/DirectOpMapper.java b/driver-direct/src/main/java/io/nosqlbench/driver/direct/DirectOpMapper.java
index 7e2420a40..5629e4ec7 100644
--- a/driver-direct/src/main/java/io/nosqlbench/driver/direct/DirectOpMapper.java
+++ b/driver-direct/src/main/java/io/nosqlbench/driver/direct/DirectOpMapper.java
@@ -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> {
+public class DirectOpMapper implements OpMapper {
@Override
public OpDispenser apply(ParsedCommand cmd) {
diff --git a/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/DriverAdapter.java b/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/DriverAdapter.java
index 0e9202537..853f59e1e 100644
--- a/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/DriverAdapter.java
+++ b/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/uniform/DriverAdapter.java
@@ -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;
@@ -18,28 +19,63 @@ import java.util.function.Function;
*
*
* @param The type of Runnable operation which will be used to wrap
- * all operations for this driver adapter. This allows you to
- * add context or features common to all operations of this
- * type.
+ * all operations for this driver adapter. This allows you to
+ * add context or features common to all operations of this
+ * type.
* @param The type of context space used by this driver to hold
- * cached instances of clients, session, or other native driver
- * esoterica. This is the shared state which might be needed
- * during construction of R type operations, or even for individual
- * operations.
+ * cached instances of clients, session, or other native driver
+ * esoterica. This is the shared state which might be needed
+ * during construction of R type operations, or even for individual
+ * operations.
*/
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.
- * 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.
+ *
+ *
+ * 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:
+ *
+ * - 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.
+ * - 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.
+ *
+ *
+ * To clarify the distinction between these two phases, the first is canonically
+ * called op mapping in the documentation. The second is called
+ * op synthesis.
+ *
+ *
+ *
+ *
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.
+ * 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.
+ *
*
* @return a synthesizer function for {@link R} op generation
*/
- Function> getOpMapper();
+ OpMapper getOpMapper();
/**
* The preprocessor function allows the driver adapter to remap
@@ -47,19 +83,21 @@ public interface DriverAdapter {
* 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