mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-01-24 14:36:32 -06:00
directapi mapping logic
This commit is contained in:
parent
de26371496
commit
68c0ba277b
@ -1,8 +1,24 @@
|
||||
package io.nosqlbench.driver.direct;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class DirectCall implements Runnable {
|
||||
private final Method method;
|
||||
private final Object[] args;
|
||||
private final Object instance;
|
||||
|
||||
public DirectCall(Method method, Object instance, Object[] args) {
|
||||
this.method = method;
|
||||
this.instance = instance;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
method.invoke(instance,args);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package io.nosqlbench.driver.direct;
|
||||
|
||||
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
|
||||
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;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* This activity type driver allows you to dynamically map any available
|
||||
* Java API which is exposed to the NoSQLBench runtime, executing methods
|
||||
* on this API by name, (optionally) storing named results, and re-using
|
||||
* these named results as arguments to subsequent calls.
|
||||
*
|
||||
* It supports static method dispatch, instance methods, and per-thread
|
||||
* object scoping.
|
||||
*/
|
||||
@Service(value = DriverAdapter.class, selector = "directapi")
|
||||
public class DirectCallAdapter extends BaseDriverAdapter<DirectCall> {
|
||||
|
||||
@Override
|
||||
public List<Function<String, Optional<Map<String, Object>>>> getStmtRemappers() {
|
||||
return List.of(new DirectCallStmtParser());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<ParsedCommand, OpDispenser<DirectCall>> getOpMapper() {
|
||||
return new DirectOpMapper();
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package io.nosqlbench.driver.direct;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class DirectCallStmtParser implements Function<String, Optional<Map<String, Object>>> {
|
||||
|
||||
@Override
|
||||
public Optional<Map<String, Object>> apply(String s) {
|
||||
Pattern stmtPattern = Pattern.compile(
|
||||
"(?<package>[a-z](\\.[a-z]+)?)?(?<class>[A-Z]\\w+)(\\.(?<staticfield>\\w+))?(\\.(?<method>\\w+))\\((?<args>.+)\\)"
|
||||
);
|
||||
Matcher matcher = stmtPattern.matcher(s);
|
||||
if (matcher.matches()) {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
List.of("package","class","staticfield","method").forEach(n -> {
|
||||
if (matcher.group(n)!=null) {
|
||||
map.put(n,matcher.group(n));
|
||||
}
|
||||
});
|
||||
if (matcher.group("args")!=null) {
|
||||
String args = matcher.group("args");
|
||||
String[] argsplit = args.split(",");
|
||||
for (int i = 0; i < argsplit.length; i++) {
|
||||
String val = argsplit[i];
|
||||
if (val.startsWith("\\") && val.endsWith("\\")) {
|
||||
val = val.substring(1,val.length()-2);
|
||||
} else if (val.startsWith("'") && val.endsWith("'")) {
|
||||
val = val.substring(1,val.length()-2);
|
||||
}
|
||||
map.put("_arg"+i,argsplit[i]);
|
||||
}
|
||||
}
|
||||
return Optional.of(map);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +1,76 @@
|
||||
package io.nosqlbench.driver.direct;
|
||||
|
||||
import io.nosqlbench.engine.api.activityconfig.yaml.OpTemplate;
|
||||
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
|
||||
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.function.LongFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DirectOpMapper implements OpDispenser<DirectCall> {
|
||||
public class DirectOpMapper implements Function<ParsedCommand, OpDispenser<DirectCall>> {
|
||||
|
||||
private final OpTemplate opTemplate;
|
||||
private final LongFunction<DirectCall> readyOp;
|
||||
@Override
|
||||
public OpDispenser<DirectCall> apply(ParsedCommand cmd) {
|
||||
|
||||
public DirectOpMapper(OpTemplate opTemplate) {
|
||||
this.opTemplate = opTemplate;
|
||||
this.readyOp = resolve(opTemplate);
|
||||
}
|
||||
String pkg = cmd.getStaticValueOptionally("package", String.class).orElse("java.lang");
|
||||
String cls = cmd.getStaticValue("class");
|
||||
String fq = pkg + "." + cls;
|
||||
Class<?> clazz = null;
|
||||
Object instance = null;
|
||||
try {
|
||||
clazz = Class.forName(fq);
|
||||
|
||||
private LongFunction<DirectCall> resolve(OpTemplate opTemplate) {
|
||||
return new DynamicCallDispenser(opTemplate);
|
||||
}
|
||||
Class<?> finalClazz = clazz;
|
||||
Optional<Field> staticfield =
|
||||
cmd.getStaticValueOptionally("staticfield", String.class)
|
||||
.map(name -> {
|
||||
try {
|
||||
return finalClazz.getDeclaredField(name);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
if (staticfield.isPresent()) {
|
||||
Field sfield = staticfield.get();
|
||||
if ((sfield.getModifiers() | Modifier.STATIC) > 0) {
|
||||
instance = sfield.get(null);
|
||||
clazz = instance.getClass();
|
||||
|
||||
} else {
|
||||
throw new OpConfigError("staticfield '" + cmd.getStaticValue("staticfield", String.class) + "' is not static");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
String methodName = cmd.getStaticValue("method");
|
||||
|
||||
Map<String, Object> protomap = cmd.getMap(0L);
|
||||
List<Class<?>> protoargs = new ArrayList<>();
|
||||
List<String> argnames = protomap.keySet().stream()
|
||||
.filter(n -> n.startsWith("_"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
LongFunction<List<Object>> argsbinder = cmd.newListBinder(argnames);
|
||||
List<Object> args = argsbinder.apply(0L);
|
||||
List<Class<?>> types = args.stream().map(Object::getClass).collect(Collectors.toList());
|
||||
|
||||
Class<?>[] argTypes = types.toArray(new Class<?>[0]);
|
||||
|
||||
Method method = null;
|
||||
try {
|
||||
method = clazz.getMethod(methodName, argTypes);
|
||||
return new StaticMethodOpDispenser(method, instance, cmd.newArrayBinder(argnames));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
public DirectCall apply(long value) {
|
||||
return readyOp.apply(value);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
package io.nosqlbench.driver.direct;
|
||||
|
||||
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
public class StaticMethodOpDispenser implements OpDispenser<DirectCall> {
|
||||
private final LongFunction<Object[]> argsfunc;
|
||||
private final Method method;
|
||||
private final Object instance;
|
||||
|
||||
public StaticMethodOpDispenser(Method method, Object instance, LongFunction<Object[]> argsfunc) {
|
||||
this.method = method;
|
||||
this.instance = instance;
|
||||
this.argsfunc = argsfunc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DirectCall apply(long value) {
|
||||
Object[] args = argsfunc.apply(value);
|
||||
return new DirectCall(method, instance, args);
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
io.nosqlbench.nb.annotations.ServiceProcessor
|
@ -4,6 +4,7 @@ This is a unique type of NoSQLBench driver which assumes no particular
|
||||
runtime API, instead relying on runtime reflection to find and invoke
|
||||
the methods as specified in the op template.
|
||||
|
||||
Presently, therea re two
|
||||
```yaml
|
||||
statements:
|
||||
- "java.lang.System.out.println(\"Testing\");"
|
||||
@ -13,10 +14,10 @@ statements:
|
||||
class: java.lang.System
|
||||
field: out
|
||||
method: println
|
||||
arg0: Testing
|
||||
_arg0: Testing
|
||||
- op:
|
||||
class: java.lang.System
|
||||
field: out
|
||||
staticfield: out
|
||||
method: println
|
||||
_x: Testing
|
||||
- op:
|
||||
|
Loading…
Reference in New Issue
Block a user