mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
additional improvements to cqld4 driver
This commit is contained in:
parent
05b3a50ec9
commit
e7668610c3
@ -3,8 +3,8 @@ package io.nosqlbench.adapter.cqld4;
|
|||||||
import com.datastax.oss.driver.api.core.CqlSession;
|
import com.datastax.oss.driver.api.core.CqlSession;
|
||||||
import io.nosqlbench.adapter.cqld4.opdispensers.CqlD4PreparedBatchOpDispenser;
|
import io.nosqlbench.adapter.cqld4.opdispensers.CqlD4PreparedBatchOpDispenser;
|
||||||
import io.nosqlbench.adapter.cqld4.opdispensers.Cqld4BatchStatementDispenser;
|
import io.nosqlbench.adapter.cqld4.opdispensers.Cqld4BatchStatementDispenser;
|
||||||
import io.nosqlbench.adapter.cqld4.opdispensers.Cqld4PreparedOpDispenser;
|
import io.nosqlbench.adapter.cqld4.opdispensers.Cqld4PreparedStmtDispenser;
|
||||||
import io.nosqlbench.adapter.cqld4.opdispensers.Cqld4SimpleCqlStatementDispenser;
|
import io.nosqlbench.adapter.cqld4.opdispensers.Cqld4SimpleCqlStmtDispenser;
|
||||||
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
|
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
|
||||||
import io.nosqlbench.engine.api.activityimpl.OpMapper;
|
import io.nosqlbench.engine.api.activityimpl.OpMapper;
|
||||||
import io.nosqlbench.engine.api.activityimpl.uniform.DriverSpaceCache;
|
import io.nosqlbench.engine.api.activityimpl.uniform.DriverSpaceCache;
|
||||||
@ -32,11 +32,11 @@ public class Cqld4OpMapper implements OpMapper<Cqld4Op> {
|
|||||||
if (prepared && batch) {
|
if (prepared && batch) {
|
||||||
return new CqlD4PreparedBatchOpDispenser(session, cmd, cfg);
|
return new CqlD4PreparedBatchOpDispenser(session, cmd, cfg);
|
||||||
} else if (prepared) {
|
} else if (prepared) {
|
||||||
return new Cqld4PreparedOpDispenser(session, cmd, cfg);
|
return new Cqld4PreparedStmtDispenser(session, cmd);
|
||||||
} else if (batch) {
|
} else if (batch) {
|
||||||
return new Cqld4BatchStatementDispenser(session, cmd, cfg);
|
return new Cqld4BatchStatementDispenser(session, cmd, cfg);
|
||||||
} else {
|
} else {
|
||||||
return new Cqld4SimpleCqlStatementDispenser(session, cmd, cfg);
|
return new Cqld4SimpleCqlStmtDispenser(session, cmd, cfg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package io.nosqlbench.adapter.cqld4;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maintain a cache of objects to use in a CQLD4 context.
|
|
||||||
*/
|
|
||||||
public class Cqld4SpaceCache {
|
|
||||||
private final ConcurrentHashMap<String, Cqld4Space> clientscopes = new ConcurrentHashMap<>();
|
|
||||||
private final Cqld4DriverAdapter adapter;
|
|
||||||
|
|
||||||
public Cqld4SpaceCache(Cqld4DriverAdapter adapter) {
|
|
||||||
this.adapter = adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cqld4Space getSpace(String name) {
|
|
||||||
return clientscopes.computeIfAbsent(name, newName -> {
|
|
||||||
return new Cqld4Space(adapter);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,36 +7,28 @@ import io.nosqlbench.adapter.cqld4.Cqld4Op;
|
|||||||
import io.nosqlbench.adapter.cqld4.optypes.Cqld4PreparedStatement;
|
import io.nosqlbench.adapter.cqld4.optypes.Cqld4PreparedStatement;
|
||||||
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
|
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
|
||||||
import io.nosqlbench.engine.api.templating.ParsedCommand;
|
import io.nosqlbench.engine.api.templating.ParsedCommand;
|
||||||
import io.nosqlbench.nb.api.config.standard.NBConfiguration;
|
|
||||||
import io.nosqlbench.virtdata.core.templates.ParsedTemplate;
|
import io.nosqlbench.virtdata.core.templates.ParsedTemplate;
|
||||||
|
|
||||||
import java.util.function.LongFunction;
|
import java.util.function.LongFunction;
|
||||||
|
|
||||||
public class Cqld4PreparedOpDispenser implements OpDispenser<Cqld4Op> {
|
public class Cqld4PreparedStmtDispenser implements OpDispenser<Cqld4Op> {
|
||||||
|
|
||||||
private final CqlSession session;
|
private final CqlSession session;
|
||||||
private final ParsedCommand cmd;
|
|
||||||
private final NBConfiguration cfg;
|
|
||||||
|
|
||||||
private final LongFunction<Object[]> varbinder;
|
private final LongFunction<Object[]> varbinder;
|
||||||
private final PreparedStatement preparedStmt;
|
private final PreparedStatement preparedStmt;
|
||||||
|
|
||||||
public Cqld4PreparedOpDispenser(CqlSession session, ParsedCommand cmd, NBConfiguration cfg) {
|
public Cqld4PreparedStmtDispenser(CqlSession session, ParsedCommand cmd) {
|
||||||
|
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.cmd = cmd;
|
|
||||||
this.cfg = cfg;
|
|
||||||
// if (cmd.isDefinedDynamic("stmt")) {
|
|
||||||
// throw new OpConfigError("You must have a static template to create prepared statements. (Do not make the stmt field a binding itself)");
|
|
||||||
// }
|
|
||||||
ParsedTemplate parsed = cmd.getStmtAsTemplate().orElseThrow();
|
ParsedTemplate parsed = cmd.getStmtAsTemplate().orElseThrow();
|
||||||
String preparedQueryString = parsed.getPositionalStatement(s -> "?");
|
|
||||||
|
|
||||||
varbinder = cmd.newArrayBinderFromBindPoints(parsed.getBindPoints());
|
varbinder = cmd.newArrayBinderFromBindPoints(parsed.getBindPoints());
|
||||||
preparedStmt = session.prepare(preparedQueryString);
|
|
||||||
|
|
||||||
|
String preparedQueryString = parsed.getPositionalStatement(s -> "?");
|
||||||
|
preparedStmt = session.prepare(preparedQueryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Explain in the dev guide that apply in the op dispenser should do all the "bind" level stuff
|
|
||||||
@Override
|
@Override
|
||||||
public Cqld4Op apply(long value) {
|
public Cqld4Op apply(long value) {
|
||||||
Object[] parameters = varbinder.apply(value);
|
Object[] parameters = varbinder.apply(value);
|
@ -8,13 +8,13 @@ import io.nosqlbench.engine.api.activityimpl.OpDispenser;
|
|||||||
import io.nosqlbench.engine.api.templating.ParsedCommand;
|
import io.nosqlbench.engine.api.templating.ParsedCommand;
|
||||||
import io.nosqlbench.nb.api.config.standard.NBConfiguration;
|
import io.nosqlbench.nb.api.config.standard.NBConfiguration;
|
||||||
|
|
||||||
public class Cqld4SimpleCqlStatementDispenser implements OpDispenser<Cqld4Op> {
|
public class Cqld4SimpleCqlStmtDispenser implements OpDispenser<Cqld4Op> {
|
||||||
|
|
||||||
private final CqlSession session;
|
private final CqlSession session;
|
||||||
private final ParsedCommand cmd;
|
private final ParsedCommand cmd;
|
||||||
private final NBConfiguration cfg;
|
private final NBConfiguration cfg;
|
||||||
|
|
||||||
public Cqld4SimpleCqlStatementDispenser(CqlSession session, ParsedCommand cmd, NBConfiguration cfg) {
|
public Cqld4SimpleCqlStmtDispenser(CqlSession session, ParsedCommand cmd, NBConfiguration cfg) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.cmd = cmd;
|
this.cmd = cmd;
|
||||||
this.cfg = cfg;
|
this.cfg = cfg;
|
@ -17,15 +17,46 @@ import java.util.function.LongFunction;
|
|||||||
* static and dynamic elements of the operation together.
|
* static and dynamic elements of the operation together.
|
||||||
* In most cases, implementations of OpDispenser will be constructed
|
* In most cases, implementations of OpDispenser will be constructed
|
||||||
* within the logic of an {@link OpMapper} which is responsible for
|
* within the logic of an {@link OpMapper} which is responsible for
|
||||||
* determine the type of OpDispenser to use as associated with a specific
|
* determining the type of OpDispenser to use as associated with a specific
|
||||||
* type {@code (<T>)}.
|
* type {@code (<T>)}. The OpMapper is called for each type of operation
|
||||||
|
* that is active during activity initialization. It's primary responsibility
|
||||||
|
* is figuring out what types of {@link OpDispenser}s to create based
|
||||||
|
* on the op templates provided by users. Once the activity is initialized,
|
||||||
|
* a set of op dispensers is held as live dispensers to use as needed
|
||||||
|
* to synthesize new operations from generated data in real time.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
|
* <hr/>
|
||||||
|
* <h2>Implementation Strategy</h2>
|
||||||
|
* <p>OpDispenser implementations are intended to be implemented
|
||||||
|
* for each type of distinct operation that is supported by a
|
||||||
|
* {@link io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter}.
|
||||||
|
* That is not to say that an OpDispenser can't be responsible for
|
||||||
|
* producing multiple types of operations. Operations which are similar
|
||||||
|
* in what they need and how they are constructed make sense to be implemented
|
||||||
|
* in the same op dispenser. Those which need different construction
|
||||||
|
* logic or fundamentally different types of field values should be implemented
|
||||||
|
* separately. The rule of thumb is to ensure that op construction patterns
|
||||||
|
* are easy to understand at the mapping level ({@link OpMapper}),
|
||||||
|
* and streamlined for fast execution at the synthesis level ({@link OpDispenser}).
|
||||||
|
*
|
||||||
* @param <T> The parameter type of the actual operation which will be used
|
* @param <T> The parameter type of the actual operation which will be used
|
||||||
* to hold all the details for executing an operation,
|
* to hold all the details for executing an operation,
|
||||||
* generally something that implements {@link Runnable}.
|
* something that implements {@link Runnable}.
|
||||||
*/
|
*/
|
||||||
public interface OpDispenser<T> extends LongFunction<T> {
|
public interface OpDispenser<T> extends LongFunction<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The apply method in an op dispenser should do all of the work of
|
||||||
|
* creating an operation that is executable by some other caller.
|
||||||
|
* The value produced by the apply method should not require
|
||||||
|
* additional processing if a caller wants to execute the operation
|
||||||
|
* multiple times, as for retries.
|
||||||
|
*
|
||||||
|
* @param value The cycle number which serves as the seed for any
|
||||||
|
* generated op fields to be bound into an operation.
|
||||||
|
* @return an executable operation
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
T apply(long value);
|
T apply(long value);
|
||||||
}
|
}
|
||||||
|
@ -8,23 +8,42 @@ import java.util.function.Function;
|
|||||||
* <p>
|
* <p>
|
||||||
* <h2>Synopsis</h2>
|
* <h2>Synopsis</h2>
|
||||||
* An OpMapper is responsible for converting parsed op templates
|
* An OpMapper is responsible for converting parsed op templates
|
||||||
* into dispensers of operations. the intention of the user,
|
* into dispensers of operations based on the intention of the user.
|
||||||
|
*
|
||||||
* Op Templates as expressed as a set of field values, some literal, and
|
* Op Templates as expressed as a set of field values, some literal, and
|
||||||
* some virtualized (to be generated per-cycle). The op template is
|
* some dynamic, to be generated based on a specific cycle value.
|
||||||
* parsed into a {@link ParsedCommand}.
|
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <h2>Concepts</h2>
|
* <h2>Concepts</h2>
|
||||||
* The OpMapper is a function (the op mapper) that returns another function (the op synthesizer).
|
* The OpMapper is basically a function that returns another function. The responsibility
|
||||||
* The returned function is then used to create actual operations in some executable form.
|
* for creating executable operations is shared between the {@link OpMapper} and the
|
||||||
* The difference
|
* {@link OpDispenser}. The logic needed to determine the type of an operation intended
|
||||||
* between the OpMapper and the OpDispenser is this: The OpMapper is responsible for
|
* by the user (mapping) is different from the logic you use to construct that specific
|
||||||
* identifying exactly what type of operation the user intends, according to the rules
|
* type of operation once you know the intent (dispensing). If you look at a example
|
||||||
* op construction documented by the driver maintainer. The OpDispenser is responsible
|
* of doing these together in code, there is always a point at which you know what is
|
||||||
* for efficiently dispensing objects of a given type which can be used to execute an
|
* needed to construct an operation. If you draw a line at this point, it represents
|
||||||
* operation. In short, mapping op templates to the users' intention must happen first, and
|
* the separation of responsibilities between op mappers and op dispensers.
|
||||||
* then building an operation efficiently with that specific knowledge can happen after.
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>This separation of responsibilities serves as both a conceptual clarification as
|
||||||
|
* well as a way to optimize runtime behavior. In the NoSQLBench model, all of the first step
|
||||||
|
* (mapping, the responsibility of this class) occurs at initialization time of an activity.
|
||||||
|
* This means that mapping logic can be as clear, readable, type-safe and obvious as
|
||||||
|
* possible without any negative effect on the later phase. In fact, clarity and obviousness
|
||||||
|
* at this level serves to keep implementations of the next phase much more straight-forward
|
||||||
|
* and streamlined, since all that is left to do is assemble the known elements together
|
||||||
|
* into an executable operation.</p>
|
||||||
|
*
|
||||||
|
* </hr>
|
||||||
|
* <h2>Implementation Strategy</h2>
|
||||||
|
* <p>
|
||||||
|
* A view of an op template is provided in the {@link ParsedCommand} 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
|
||||||
|
* on a distinct signature
|
||||||
|
*
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -417,7 +417,7 @@ public class SimpleActivity implements Activity, ProgressCapable {
|
|||||||
* @param <O>
|
* @param <O>
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected <O> OpSequence<OpDispenser<O>> createOpSequenceFromCommands(Function<CommandTemplate, OpDispenser<O>> opinit) {
|
protected <O extends Runnable> OpSequence<OpDispenser<O>> createOpSequenceFromCommands(Function<CommandTemplate, OpDispenser<O>> opinit) {
|
||||||
Function<OpTemplate, CommandTemplate> f = CommandTemplate::new;
|
Function<OpTemplate, CommandTemplate> f = CommandTemplate::new;
|
||||||
Function<OpTemplate, OpDispenser<O>> opTemplateOFunction = f.andThen(opinit);
|
Function<OpTemplate, OpDispenser<O>> opTemplateOFunction = f.andThen(opinit);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user