mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
MongoDB Adapter fix and updates for scenarios (#1196)
* Updates for mongodb adapter; fix connection usage on cli * Reduce the cycles for test w/ sporadic failures * Removed redundant '-> string' * Removed state tracking and cleanup * Space cache capture and connection management * Mongo client management w/ connection * Remove unused getData() * Removed debug entry no longer required
This commit is contained in:
parent
1e27a93e8a
commit
388ece75f7
@ -19,38 +19,9 @@ package io.nosqlbench.adapter.mongodb.core;
|
||||
public enum MongoDBOpTypes {
|
||||
/**
|
||||
* Use direct command structure....
|
||||
*
|
||||
* @see <a href="https://docs.mongodb.com/manual/reference/method/db.runCommand/#command-response">command-response</a>
|
||||
*/
|
||||
command,
|
||||
|
||||
// /**
|
||||
// * @see <a href="https://www.mongodb.com/docs/manual/reference/command/update/#mongodb-dbcommand-dbcmd.update">update</a>
|
||||
// */
|
||||
// update,
|
||||
|
||||
// /**
|
||||
// * @see <a href="https://www.mongodb.com/docs/manual/reference/command/insert/">insert</a>
|
||||
// */
|
||||
// insert,
|
||||
//
|
||||
// /**
|
||||
// * @see <a href="https://www.mongodb.com/docs/manual/reference/command/delete/">delete</a>
|
||||
// */
|
||||
// delete,
|
||||
//
|
||||
// /**
|
||||
// * @see <a href="https://www.mongodb.com/docs/manual/reference/command/find/">find</a>
|
||||
// */
|
||||
// find,
|
||||
//
|
||||
// /**
|
||||
// * @see <a href="https://www.mongodb.com/docs/manual/reference/command/findAndModify/">findAndModify</a>
|
||||
// */
|
||||
// findAndModify,
|
||||
//
|
||||
// /**
|
||||
// * @see <a href="https://www.mongodb.com/docs/manual/reference/command/getMore/">getMore</a>
|
||||
// */
|
||||
// getMore
|
||||
|
||||
}
|
||||
|
@ -17,8 +17,11 @@
|
||||
package io.nosqlbench.adapter.mongodb.core;
|
||||
|
||||
import io.nosqlbench.adapter.mongodb.dispensers.MongoCommandOpDispenser;
|
||||
import io.nosqlbench.api.config.standard.NBConfiguration;
|
||||
import io.nosqlbench.api.errors.BasicError;
|
||||
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.activityimpl.uniform.flowtypes.Op;
|
||||
import io.nosqlbench.engine.api.templating.ParsedOp;
|
||||
import io.nosqlbench.engine.api.templating.TypeAndTarget;
|
||||
@ -29,36 +32,46 @@ import java.util.Optional;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
public class MongoOpMapper implements OpMapper<Op> {
|
||||
private final static Logger logger = LogManager.getLogger(MongoOpMapper.class);
|
||||
private static final Logger logger = LogManager.getLogger(MongoOpMapper.class);
|
||||
|
||||
private final MongodbDriverAdapter adapter;
|
||||
private final NBConfiguration configuration;
|
||||
private final DriverSpaceCache<? extends MongoSpace> spaceCache;
|
||||
|
||||
public MongoOpMapper(MongodbDriverAdapter adapter) {
|
||||
public MongoOpMapper(MongodbDriverAdapter adapter, NBConfiguration cfg,
|
||||
DriverSpaceCache<? extends MongoSpace> spaceCache) {
|
||||
this.configuration = cfg;
|
||||
this.spaceCache = spaceCache;
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpDispenser<? extends Op> apply(ParsedOp op) {
|
||||
|
||||
LongFunction<String> ctxNamer = op.getAsFunctionOr("space", "default");
|
||||
LongFunction<MongoSpace> spaceF = l -> adapter.getSpaceCache().get(ctxNamer.apply(l));
|
||||
LongFunction<MongoSpace> spaceF = l -> adapter.getSpaceCache()
|
||||
.get(ctxNamer.apply(l));
|
||||
|
||||
String connectionURL = op.getStaticConfigOr("connection", "unknown");
|
||||
if (connectionURL == null) {
|
||||
throw new BasicError("Must provide a connection value for use by the MongoDB adapter.");
|
||||
}
|
||||
spaceCache.get(ctxNamer.apply(0L)).createMongoClient(connectionURL);
|
||||
|
||||
Optional<LongFunction<String>> oDatabaseF = op.getAsOptionalFunction("database");
|
||||
if (oDatabaseF.isEmpty()) {
|
||||
logger.warn("op field 'database' was not defined");
|
||||
}
|
||||
|
||||
Optional<TypeAndTarget<MongoDBOpTypes, String>> target = op.getOptionalTypeAndTargetEnum(MongoDBOpTypes.class, String.class);
|
||||
Optional<TypeAndTarget<MongoDBOpTypes, String>> target = op.getOptionalTypeAndTargetEnum(MongoDBOpTypes.class,
|
||||
String.class);
|
||||
|
||||
// For any of the named operations which are called out directly AND supported via the fluent API,
|
||||
// use specialized dispensers
|
||||
if (target.isPresent()) {
|
||||
TypeAndTarget<MongoDBOpTypes, String> targetdata = target.get();
|
||||
return switch (targetdata.enumId) {
|
||||
TypeAndTarget<MongoDBOpTypes, String> targetData = target.get();
|
||||
return switch (targetData.enumId) {
|
||||
case command -> new MongoCommandOpDispenser(adapter, spaceF, op);
|
||||
// case update -> new MongoDbUpdateOpDispenser(adapter, op, targetdata.targetFunction);
|
||||
// case insert -> new MongoDbInsertOpDispenser(adapter, op, opTypeAndTarget.targetFunction);
|
||||
// case delete -> new MongoDbDeleteOpDispenser(adapter, op, opTypeAndTarget.targetFunction);
|
||||
// case find -> new mongoDbFindOpDispenser(adapter, op, opTypeAndTarget.targetFunction);
|
||||
// case findAndModify -> new MongoDbFindAndModifyOpDispenser(adapter, op, opTypeAndTarget.targetFunction);
|
||||
// case getMore -> new MongoDbGetMoreOpDispenser(adapter, op, opTypeAndTarget.targetFunction);
|
||||
};
|
||||
}
|
||||
// For everything else use the command API
|
||||
@ -67,8 +80,5 @@ public class MongoOpMapper implements OpMapper<Op> {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -20,12 +20,13 @@ import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import io.nosqlbench.api.config.NBNamedElement;
|
||||
import io.nosqlbench.api.config.standard.ConfigModel;
|
||||
import io.nosqlbench.api.config.standard.NBConfigModel;
|
||||
import io.nosqlbench.api.config.standard.NBConfiguration;
|
||||
import io.nosqlbench.api.config.standard.Param;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bson.UuidRepresentation;
|
||||
import org.bson.codecs.UuidCodec;
|
||||
import org.bson.codecs.configuration.CodecRegistry;
|
||||
@ -33,54 +34,62 @@ import org.bson.codecs.configuration.CodecRegistry;
|
||||
import static org.bson.codecs.configuration.CodecRegistries.fromCodecs;
|
||||
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
|
||||
|
||||
public class MongoSpace implements NBNamedElement {
|
||||
private final String name;
|
||||
private final NBConfiguration cfg;
|
||||
private final String connectionString;
|
||||
private final MongoClient client;
|
||||
private MongoDatabase mongoDatabase;
|
||||
public class MongoSpace implements NBNamedElement, AutoCloseable {
|
||||
private final static Logger logger = LogManager.getLogger(MongoSpace.class);
|
||||
private final String spaceName;
|
||||
private final NBConfiguration mongoConfig;
|
||||
private MongoClient mongoClient;
|
||||
|
||||
public MongoSpace(String name, NBConfiguration cfg) {
|
||||
this.name = name;
|
||||
this.cfg = cfg;
|
||||
this.connectionString = cfg.get("connection",String.class);
|
||||
this.client = createMongoClient(connectionString);
|
||||
this.spaceName = name;
|
||||
this.mongoConfig = cfg;
|
||||
}
|
||||
|
||||
public static NBConfigModel getConfigModel() {
|
||||
return ConfigModel.of(MongoSpace.class)
|
||||
.add(Param.required("connection", String.class)
|
||||
.setDescription("The connection string for your MongoDB endpoint"))
|
||||
.add(Param.required("database", String.class)
|
||||
.setDescription("The database name to connect to."))
|
||||
.asReadOnly();
|
||||
.add(Param.required("connection", String.class)
|
||||
.setDescription("The connection string for your MongoDB endpoint"))
|
||||
.add(Param.required("database", String.class)
|
||||
.setDescription("The database name to connect to."))
|
||||
.asReadOnly();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
return spaceName;
|
||||
}
|
||||
|
||||
public MongoClient createMongoClient(String connectionString) {
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
if (mongoClient != null) {
|
||||
mongoClient.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(() -> "auto-closeable mongodb connection threw exception in " +
|
||||
"mongodb space(" + this.spaceName + "): " + e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void createMongoClient(String connectionURL) {
|
||||
|
||||
CodecRegistry codecRegistry = fromRegistries(
|
||||
fromCodecs(new UuidCodec(UuidRepresentation.STANDARD)),
|
||||
MongoClientSettings.getDefaultCodecRegistry()
|
||||
fromCodecs(new UuidCodec(UuidRepresentation.STANDARD)),
|
||||
MongoClientSettings.getDefaultCodecRegistry()
|
||||
);
|
||||
|
||||
MongoClientSettings settings = MongoClientSettings.builder()
|
||||
.applyConnectionString(new ConnectionString(connectionString))
|
||||
.codecRegistry(codecRegistry)
|
||||
.uuidRepresentation(UuidRepresentation.STANDARD)
|
||||
.build();
|
||||
return MongoClients.create(settings);
|
||||
}
|
||||
|
||||
protected MongoDatabase getDatabase() {
|
||||
return mongoDatabase;
|
||||
.applyConnectionString(new ConnectionString(connectionURL))
|
||||
.codecRegistry(codecRegistry)
|
||||
.uuidRepresentation(UuidRepresentation.STANDARD)
|
||||
.build();
|
||||
this.mongoClient = MongoClients.create(settings);
|
||||
}
|
||||
|
||||
public MongoClient getClient() {
|
||||
return this.client;
|
||||
return this.mongoClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,22 +29,21 @@ import java.util.function.Function;
|
||||
/**
|
||||
* Special thanks to Justin Chu who authored the original NoSQLBench MongoDB ActivityType.
|
||||
*/
|
||||
@Service(value=DriverAdapter.class, selector ="mongodb")
|
||||
@Service(value = DriverAdapter.class, selector = "mongodb")
|
||||
public class MongodbDriverAdapter extends BaseDriverAdapter<Op, MongoSpace> {
|
||||
|
||||
@Override
|
||||
public OpMapper<Op> getOpMapper() {
|
||||
return new MongoOpMapper(this);
|
||||
return new MongoOpMapper(this, getConfiguration(), getSpaceCache());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<String, ? extends MongoSpace> getSpaceInitializer(NBConfiguration cfg) {
|
||||
return s -> new MongoSpace(s, cfg);
|
||||
return spaceName -> new MongoSpace(spaceName, cfg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBConfigModel getConfigModel() {
|
||||
return super.getConfigModel().add(MongoSpace.getConfigModel());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package io.nosqlbench.adapter.mongodb.dispensers;
|
||||
|
||||
import com.mongodb.ReadPreference;
|
||||
import io.nosqlbench.adapter.mongodb.core.MongoSpace;
|
||||
import io.nosqlbench.adapter.mongodb.ops.MongoDirectCommandOp;
|
||||
import io.nosqlbench.engine.api.activityimpl.BaseOpDispenser;
|
||||
@ -30,40 +29,33 @@ import java.util.Map;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
public class MongoCommandOpDispenser extends BaseOpDispenser<Op, MongoSpace> {
|
||||
private final LongFunction<MongoDirectCommandOp> opFunc;
|
||||
|
||||
private final LongFunction<MongoDirectCommandOp> mongoOpF;
|
||||
|
||||
public MongoCommandOpDispenser(DriverAdapter adapter, LongFunction<MongoSpace> ctxFunc, ParsedOp op) {
|
||||
super(adapter,op);
|
||||
opFunc = createOpFunc(ctxFunc, op);
|
||||
this.mongoOpF = createOpFunc(ctxFunc,op);
|
||||
public MongoCommandOpDispenser(DriverAdapter<Op, MongoSpace> adapter, LongFunction<MongoSpace> ctxFunc, ParsedOp op) {
|
||||
super(adapter, op);
|
||||
this.mongoOpF = createOpFunc(ctxFunc, op);
|
||||
}
|
||||
|
||||
private LongFunction<MongoDirectCommandOp> createOpFunc(LongFunction<MongoSpace> ctxFunc, ParsedOp op) {
|
||||
|
||||
LongFunction<String> rpstring = op.getAsOptionalFunction("readPreference")
|
||||
.orElseGet(() -> op.getAsOptionalFunction("read-preference")
|
||||
.orElse(l -> "primary"));
|
||||
LongFunction<ReadPreference> readPreferenceF = l -> ReadPreference.valueOf(rpstring.apply(l));
|
||||
|
||||
LongFunction<?> payload = op.getAsRequiredFunction("stmt", Object.class);
|
||||
Object exampleValue = payload.apply(0);
|
||||
|
||||
LongFunction<Bson> bsonFunc;
|
||||
if (exampleValue instanceof CharSequence cs) {
|
||||
if (exampleValue instanceof CharSequence) {
|
||||
bsonFunc = l -> Document.parse(payload.apply(l).toString());
|
||||
} else if ( exampleValue instanceof Map map) {
|
||||
bsonFunc = l -> new Document((Map<String,Object>)payload.apply(l));
|
||||
} else if (exampleValue instanceof Map) {
|
||||
bsonFunc = l -> new Document((Map<String, Object>) payload.apply(l));
|
||||
} else {
|
||||
throw new RuntimeException("You must provide a String or Map for your BSON payload.");
|
||||
}
|
||||
|
||||
LongFunction<String> databaseNamerF = op.getAsRequiredFunction("database", String.class);
|
||||
|
||||
return l-> new MongoDirectCommandOp(
|
||||
ctxFunc.apply(l).getClient(),
|
||||
databaseNamerF.apply(l),
|
||||
bsonFunc.apply(l)
|
||||
final LongFunction<String> databaseNamerF = op.getAsRequiredFunction("database", String.class);
|
||||
return l -> new MongoDirectCommandOp(
|
||||
ctxFunc.apply(l).getClient(),
|
||||
databaseNamerF.apply(l),
|
||||
bsonFunc.apply(l)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -44,11 +44,7 @@ public class MongoDbUpdateOpDispenser extends BaseOpDispenser<Op, MongoSpace> {
|
||||
|
||||
private LongFunction<Op> createOpF(ParsedOp pop) {
|
||||
LongFunction<MongoClient> clientF = cycle -> spaceF.apply(cycle).getClient();
|
||||
|
||||
LongFunction<MongoDatabase> docF = l -> clientF.apply(l).getDatabase(collectionF.apply(l));
|
||||
// docF.apply(1).getCollection()
|
||||
// LongFunctionclientF.apply(l).getDatabase()
|
||||
|
||||
return l -> new Op() {};
|
||||
}
|
||||
|
||||
|
@ -2,49 +2,45 @@ description: An example of a basic mongo insert and find.
|
||||
|
||||
scenarios:
|
||||
default:
|
||||
rampup: run driver=mongodb tags==block:rampup cycles===TEMPLATE(rampup-cycles,1000000) threads=auto
|
||||
main: run driver=mongodb tags==block:"main.*" cycles===TEMPLATE(main-cycles,10000000) threads=auto
|
||||
rampup: run driver=mongodb tags==block:"rampup.*", cycles===TEMPLATE(rampup-cycles,10) threads=auto errors=timer,warn
|
||||
write: run driver=mongodb tags==block:"write.*", cycles===TEMPLATE(write-cycles,10) threads=auto errors=timer,warn
|
||||
read: run driver=mongodb tags==block:"read.*", cycles===TEMPLATE(read-cycles,10) threads=auto errors=timer,warn
|
||||
|
||||
bindings:
|
||||
seq_key: Mod(<<keyCount:1000000>>L); ToInt()
|
||||
seq_value: Mod(<<valueCount:1000000000>>L); <<valueSizeDist:Hash()>>; ToString() -> String
|
||||
rw_key: <<keyDist:Uniform(0,1000000)->long>>; ToInt()
|
||||
rw_value: <<valDist:Uniform(0,1000000000)->int>>; <<valueSizeDist:Hash()>>; ToString() -> String
|
||||
seq_key: Mod(<<keyCount:1000000>>); ToString();
|
||||
seq_value: Mod(<<valueCount:1000000000>>); <<valueSizeDist:Hash()>>; ToString();
|
||||
rw_key: <<keyDist:Uniform(0,1000000)>>; ToString();
|
||||
rw_value: <<valDist:Uniform(0,1000000000)>>; <<valueSizeDist:Hash()>>; ToString();
|
||||
|
||||
blocks:
|
||||
rampup:
|
||||
ops:
|
||||
rampup-insert: |
|
||||
rampup:
|
||||
params:
|
||||
readPreference: primary
|
||||
ops:
|
||||
insert: >2
|
||||
{
|
||||
insert: "<<collection:keyvalue>>",
|
||||
documents: [ { _id: {seq_key}, value: {seq_value} } ]
|
||||
}
|
||||
params:
|
||||
readPreference: primary
|
||||
tags:
|
||||
name: rampup-insert
|
||||
|
||||
main-read:
|
||||
params:
|
||||
ratio: <<read_ratio:1>>
|
||||
readPreference: primary
|
||||
type: read
|
||||
ops:
|
||||
main-find: |
|
||||
read:
|
||||
ops:
|
||||
find: >2
|
||||
{
|
||||
find: "<<collection:keyvalue>>",
|
||||
filter: { _id: {rw_key} }
|
||||
}
|
||||
|
||||
main-write:
|
||||
}
|
||||
params:
|
||||
ratio: <<write_ratio:1>>
|
||||
type: write
|
||||
ops:
|
||||
main-insert: |
|
||||
ratio: <<read_ratio:1>>
|
||||
readPreference: primary
|
||||
|
||||
write:
|
||||
ops:
|
||||
insert: >2
|
||||
{
|
||||
insert: "<<collection:keyvalue>>",
|
||||
documents: [ { _id: {rw_key}, value: {rw_value} } ]
|
||||
}
|
||||
params:
|
||||
readPreference: primary
|
||||
params:
|
||||
ratio: <<write_ratio:1>>
|
||||
readPreference: primary
|
@ -7,10 +7,10 @@ description: |
|
||||
scenarios:
|
||||
default:
|
||||
schema: run driver=mongodb tags==block:"schema.*" threads==1 cycles==UNDEF
|
||||
write: run driver=mongodb tags==block:main-write,type:write cycles===TEMPLATE(write-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
read: run driver=mongodb tags==block:main-read,type:read cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
update: run driver=mongodb tags==block:main-update,type:update cycles===TEMPLATE(update-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
delete: run driver=mongodb tags==block:main-delete,type:delete cycles===TEMPLATE(delete-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
write: run driver=mongodb tags==block:"write.*", cycles===TEMPLATE(write-cycles,TEMPLATE(docscount,10)) threads=auto errors=timer,warn
|
||||
read: run driver=mongodb tags==block:"read.*", cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10)) threads=auto errors=timer,warn
|
||||
update: run driver=mongodb tags==block:"update.*", cycles===TEMPLATE(update-cycles,TEMPLATE(docscount,10)) threads=auto errors=timer,warn
|
||||
delete: run driver=mongodb tags==block:"delete.*", cycles===TEMPLATE(delete-cycles,TEMPLATE(docscount,10)) threads=auto errors=timer,warn
|
||||
|
||||
bindings:
|
||||
seq_key: Mod(<<docscount:10000000>>); ToString() -> String
|
||||
@ -30,7 +30,7 @@ bindings:
|
||||
blocks:
|
||||
schema:
|
||||
ops:
|
||||
dummy-insert: |
|
||||
dummy-insert: >2
|
||||
{
|
||||
insert: "<<collection:crud_basic>>",
|
||||
documents: [ { _id: "dummyyyy" } ]
|
||||
@ -63,9 +63,9 @@ blocks:
|
||||
]
|
||||
}
|
||||
|
||||
main-write:
|
||||
write:
|
||||
ops:
|
||||
write-document: |
|
||||
write-document: >2
|
||||
{
|
||||
insert: "<<collection:crud_basic>>",
|
||||
writeConcern: { w: "majority" },
|
||||
@ -79,35 +79,34 @@ blocks:
|
||||
"married": {married},
|
||||
"address": {
|
||||
"primary": {
|
||||
"city": "{city}",
|
||||
"cc": "{country_code}"
|
||||
"city": "{city}",
|
||||
"cc": "{country_code}"
|
||||
},
|
||||
"secondary": {}
|
||||
},
|
||||
"coordinates": [
|
||||
{lat},
|
||||
{lng}
|
||||
{lat},
|
||||
{lng}
|
||||
],
|
||||
"children": [],
|
||||
"children": [],
|
||||
"friends": [
|
||||
"{friend_id}"
|
||||
"{friend_id}"
|
||||
],
|
||||
"debt": null
|
||||
"debt": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
main-read:
|
||||
}
|
||||
read:
|
||||
ops:
|
||||
read-document: |
|
||||
read-document: >2
|
||||
{
|
||||
find: "<<collection:crud_basic>>",
|
||||
filter: { _id: "{random_key}" }
|
||||
}
|
||||
|
||||
main-update:
|
||||
update:
|
||||
ops:
|
||||
update-document: |
|
||||
update-document: >2
|
||||
{
|
||||
update: "<<collection:crud_basic>>",
|
||||
writeConcern: { w: "majority" },
|
||||
@ -123,28 +122,28 @@ blocks:
|
||||
"married": {married},
|
||||
"address": {
|
||||
"primary": {
|
||||
"city": "{city}",
|
||||
"cc": "{country_code}"
|
||||
"city": "{city}",
|
||||
"cc": "{country_code}"
|
||||
},
|
||||
"secondary": {}
|
||||
},
|
||||
"coordinates": [
|
||||
{lat},
|
||||
{lng}
|
||||
{lat},
|
||||
{lng}
|
||||
],
|
||||
"children": [],
|
||||
"children": [],
|
||||
"friends": [
|
||||
"{friend_id}"
|
||||
"{friend_id}"
|
||||
],
|
||||
"debt": null
|
||||
"debt": null
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
main-delete:
|
||||
delete:
|
||||
ops:
|
||||
delete-document: |
|
||||
delete-document: >2
|
||||
{
|
||||
delete: "<<collection:crud_basic>>",
|
||||
deletes: [
|
||||
|
@ -6,79 +6,76 @@ description: |
|
||||
|
||||
scenarios:
|
||||
default:
|
||||
schema: run driver=mongodb tags==block:"schema.*" threads==1 cycles==UNDEF
|
||||
write: run driver=mongodb tags==block:main-write,type:write cycles===TEMPLATE(write-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
read: run driver=mongodb tags==block:main-read,type:read cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
update: run driver=mongodb tags==block:main-update,type:update cycles===TEMPLATE(update-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
delete: run driver=mongodb tags==block:main-delete,type:delete cycles===TEMPLATE(delete-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
schema: run driver=mongodb tags==block:"schema.*", threads==1 cycles==UNDEF
|
||||
write: run driver=mongodb tags==block:"write.*", cycles===TEMPLATE(write-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
read: run driver=mongodb tags==block:"read.*", cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
update: run driver=mongodb tags==block:"update.*", cycles===TEMPLATE(update-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
delete: run driver=mongodb tags==block:"delete.*", cycles===TEMPLATE(delete-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn
|
||||
|
||||
bindings:
|
||||
seq_key: Mod(<<docscount:10000000>>); ToString() -> String
|
||||
random_key: Uniform(0,<<docscount:10000000>>); ToString() -> String
|
||||
document_json_without_id: ModuloLineToString('<<dataset_file>>'); ReplaceRegex('^\{', '')
|
||||
|
||||
blocks:
|
||||
schema:
|
||||
ops:
|
||||
dummy-insert: |
|
||||
dummy-insert: >2
|
||||
{
|
||||
insert: "<<collection:crud_dataset>>",
|
||||
documents: [ { _id: "dummyyyy" } ]
|
||||
}
|
||||
|
||||
drop-collection: |
|
||||
drop-collection: >2
|
||||
{
|
||||
drop: "<<collection:crud_dataset>>"
|
||||
}
|
||||
|
||||
create-collection: |
|
||||
create-collection: >2
|
||||
{
|
||||
create: "<<collection:crud_dataset>>"
|
||||
}
|
||||
|
||||
create-indexes: |
|
||||
create-indexes: >2
|
||||
{
|
||||
createIndexes: "<<collection:crud_dataset>>",
|
||||
indexes: <<indexes:[ { key: { dummy : 1 }, name: "dummy_idx", sparse: true } ]>>
|
||||
}
|
||||
|
||||
main-write:
|
||||
write:
|
||||
ops:
|
||||
write-document: |
|
||||
write-docs: >2
|
||||
{
|
||||
insert: "<<collection:crud_dataset>>",
|
||||
writeConcern: { w: "majority" },
|
||||
documents: [ { "_id": "{seq_key}", {document_json_without_id} ]
|
||||
documents: [ { "_id": "{seq_key}", {document_json_without_id} } ]
|
||||
}
|
||||
bindings:
|
||||
document_json_without_id: ModuloLineToString('<<dataset_file>>'); ReplaceRegex('^\{', '')
|
||||
|
||||
main-read:
|
||||
read:
|
||||
ops:
|
||||
read-document: |
|
||||
read-docs: >2
|
||||
{
|
||||
find: "<<collection:crud_dataset>>",
|
||||
filter: { _id: "{random_key}" }
|
||||
}
|
||||
|
||||
main-update:
|
||||
update:
|
||||
ops:
|
||||
update-document: |
|
||||
update-docs: >2
|
||||
{
|
||||
update: "<<collection:crud_dataset>>",
|
||||
writeConcern: { w: "majority" },
|
||||
updates: [
|
||||
{
|
||||
q: { _id: "{random_key}" },
|
||||
u: { "_id": "{random_key}", {document_json_without_id}
|
||||
u: { "_id": "{random_key}", {document_json_without_id} }
|
||||
}
|
||||
]
|
||||
}
|
||||
bindings:
|
||||
document_json_without_id: ModuloLineToString('<<dataset_file>>'); ReplaceRegex('^\{', '')
|
||||
|
||||
main-delete:
|
||||
delete:
|
||||
ops:
|
||||
delete-document: |
|
||||
delete-docs: >2
|
||||
{
|
||||
delete: "<<collection:crud_dataset>>",
|
||||
deletes: [
|
||||
|
@ -7,8 +7,8 @@ description: |
|
||||
|
||||
scenarios:
|
||||
schema: run driver=mongodb tags==block:"schema.*" threads==1 cycles==UNDEF
|
||||
rampup-write: run driver=mongodb tags==block:rampup-write cycles===TEMPLATE(docscount,10000000) docpadding=TEMPLATE(docpadding,0) match-ratio=TEMPLATE(match-ratio,0.01) threads=auto errors=timer,warn
|
||||
rampup-read: run driver=mongodb tags==block:rampup-read cycles===TEMPLATE(rampup-cycles, 10000000) field-projection=TEMPLATE(fields,null) threads=<<threads:auto>> errors=timer,warn
|
||||
rampup-write: run driver=mongodb tags==block:"rampup-write.*" cycles===TEMPLATE(docscount,10000000) docpadding=TEMPLATE(docpadding,0) match-ratio=TEMPLATE(match-ratio,0.01) threads=auto errors=timer,warn
|
||||
rampup-read: run driver=mongodb tags==block:"rampup-read.*" cycles===TEMPLATE(rampup-cycles, 10000000) field-projection=TEMPLATE(fields,null) threads=<<threads:auto>> errors=timer,warn
|
||||
main: run driver=mongodb tags==block:main cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) field-projection=TEMPLATE(fields,null) threads=<<threads:auto>> errors=timer,warn
|
||||
main-eq: run driver=mongodb tags==block:main-eq,filter:eq cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) field-projection=TEMPLATE(fields,null) threads=<<threads:auto>> errors=timer,warn
|
||||
main-lt: run driver=mongodb tags==block:main-lt,filter:lt cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) field-projection=TEMPLATE(fields,null) threads=<<threads:auto>> errors=timer,warn
|
||||
|
41
adapter-mongodb/src/main/resources/data/mongo-test-ds.json
Executable file
41
adapter-mongodb/src/main/resources/data/mongo-test-ds.json
Executable file
@ -0,0 +1,41 @@
|
||||
{
|
||||
meta: {
|
||||
disclaimer: "Do not rely on openFDA to make decisions regarding medical care. While we make every effort to ensure that data is accurate, you should assume all results are unvalidated. We may limit or otherwise restrict your access to the API in line with our Terms of Service.",
|
||||
terms: "https://open.fda.gov/terms/",
|
||||
license: "https://open.fda.gov/license/",
|
||||
last_updated: "2023-03-29",
|
||||
results: {
|
||||
skip: 0,
|
||||
limit: 1,
|
||||
total: 23693
|
||||
}
|
||||
},
|
||||
results: [
|
||||
{
|
||||
country: "United States",
|
||||
city: "Davie",
|
||||
address_1: "4131 SW 47th Ave Ste 1403",
|
||||
reason_for_recall: "Recall initiated as a precautionary measure due to potential risk of product contamination with Burkholderia cepacia.",
|
||||
address_2: "",
|
||||
product_quantity: "1,990 bottles",
|
||||
code_info: "UPC No. 632687615989; Lot No. 30661601, Exp. Date 05/2018.",
|
||||
center_classification_date: "20161025",
|
||||
distribution_pattern: "FL, MI, MS, and OH.",
|
||||
state: "FL",
|
||||
product_description: "CytoDetox, Hydrolyzed Clinoptilolite Fragments, 1 oz./30 mL, OTC Non-Sterile. Dietary supplement.",
|
||||
report_date: "20161102",
|
||||
classification: "Class II",
|
||||
openfda: { },
|
||||
recalling_firm: "Pharmatech LLC",
|
||||
recall_number: "F-0276-2017",
|
||||
initial_firm_notification: "Letter",
|
||||
product_type: "Food",
|
||||
event_id: "75272",
|
||||
more_code_info: "",
|
||||
recall_initiation_date: "20160808",
|
||||
postal_code: "33314-4036",
|
||||
voluntary_mandated: "Voluntary: Firm initiated",
|
||||
status: "Ongoing"
|
||||
}
|
||||
]
|
||||
}
|
@ -18,9 +18,9 @@ package io.nosqlbench.engine.api.activityimpl;
|
||||
|
||||
import com.codahale.metrics.Histogram;
|
||||
import com.codahale.metrics.Timer;
|
||||
import io.nosqlbench.api.engine.metrics.ActivityMetrics;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op;
|
||||
import io.nosqlbench.api.engine.metrics.ActivityMetrics;
|
||||
import io.nosqlbench.engine.api.metrics.ThreadLocalNamedTimers;
|
||||
import io.nosqlbench.engine.api.templating.ParsedOp;
|
||||
|
||||
@ -29,7 +29,7 @@ import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* See {@link OpDispenser} for details on how to use this type.
|
||||
*
|
||||
* <p>
|
||||
* Some details are tracked per op template, which aligns to the life-cycle of the op dispenser.
|
||||
* Thus, each op dispenser is where the stats for all related operations are kept.
|
||||
*
|
||||
@ -37,51 +37,41 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public abstract class BaseOpDispenser<T extends Op, S> implements OpDispenser<T> {
|
||||
|
||||
private final String name;
|
||||
private final String opName;
|
||||
protected final DriverAdapter<T, S> adapter;
|
||||
private boolean instrument;
|
||||
private Histogram resultSizeHistogram;
|
||||
private Timer successTimer;
|
||||
private Timer errorTimer;
|
||||
private String[] timerStarts = new String[0];
|
||||
private String[] timerStops = new String[0];
|
||||
private final String[] timerStarts;
|
||||
private final String[] timerStops;
|
||||
|
||||
public BaseOpDispenser(DriverAdapter<T,S> adapter,ParsedOp op) {
|
||||
this.name = op.getName();
|
||||
protected BaseOpDispenser(DriverAdapter<T, S> adapter, ParsedOp op) {
|
||||
this.opName = op.getName();
|
||||
this.adapter = adapter;
|
||||
timerStarts = op.takeOptionalStaticValue("start-timers", String.class)
|
||||
.map(s -> s.split(", *"))
|
||||
.orElse(null);
|
||||
.map(s -> s.split(", *"))
|
||||
.orElse(null);
|
||||
|
||||
timerStops = op.takeOptionalStaticValue("stop-timers", String.class)
|
||||
.map(s -> s.split(", *"))
|
||||
.orElse(null);
|
||||
.map(s -> s.split(", *"))
|
||||
.orElse(null);
|
||||
|
||||
if (timerStarts!=null) {
|
||||
if (timerStarts != null) {
|
||||
for (String timerStart : timerStarts) {
|
||||
ThreadLocalNamedTimers.addTimer(op,timerStart);
|
||||
ThreadLocalNamedTimers.addTimer(op, timerStart);
|
||||
}
|
||||
}
|
||||
configureInstrumentation(op);
|
||||
}
|
||||
|
||||
public DriverAdapter<T,S> getAdapter() {
|
||||
return adapter;
|
||||
String getOpName() {
|
||||
return opName;
|
||||
}
|
||||
|
||||
// public BaseOpDispenser(CommandTemplate cmdtpl) {
|
||||
// this.name = cmdtpl.getName();
|
||||
// }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param cycle The cycle number which serves as the seed for any
|
||||
* generated op fields to be bound into an operation.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public abstract T apply(long cycle);
|
||||
public DriverAdapter<T, S> getAdapter() {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
protected String getDefaultMetricsPrefix(ParsedOp pop) {
|
||||
return pop.getStaticConfigOr("alias", "UNKNOWN") + "-" + pop.getName() + "--";
|
||||
@ -98,32 +88,31 @@ public abstract class BaseOpDispenser<T extends Op, S> implements OpDispenser<T>
|
||||
|
||||
@Override
|
||||
public void onStart(long cycleValue) {
|
||||
if (timerStarts!=null) {
|
||||
if (timerStarts != null) {
|
||||
ThreadLocalNamedTimers.TL_INSTANCE.get().start(timerStarts);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(long cycleValue, long nanoTime, long resultsize) {
|
||||
public void onSuccess(long cycleValue, long nanoTime, long resultSize) {
|
||||
if (instrument) {
|
||||
successTimer.update(nanoTime, TimeUnit.NANOSECONDS);
|
||||
if (resultsize>-1) {
|
||||
resultSizeHistogram.update(resultsize);
|
||||
if (resultSize > -1) {
|
||||
resultSizeHistogram.update(resultSize);
|
||||
}
|
||||
}
|
||||
if (timerStops!=null) {
|
||||
if (timerStops != null) {
|
||||
ThreadLocalNamedTimers.TL_INSTANCE.get().stop(timerStops);
|
||||
}
|
||||
|
||||
// ThreadLocalNamedTimers.TL_INSTANCE.get().stop(stopTimers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(long cycleValue, long resultNanos, Throwable t) {
|
||||
|
||||
if (instrument) {
|
||||
errorTimer.update(resultNanos, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
if (timerStops!=null) {
|
||||
if (timerStops != null) {
|
||||
ThreadLocalNamedTimers.TL_INSTANCE.get().stop(timerStops);
|
||||
}
|
||||
}
|
||||
|
@ -42,15 +42,16 @@ public abstract class BaseDriverAdapter<R extends Op, S> implements DriverAdapte
|
||||
* BaseDriverAdapter will take any provided functions from {@link #getOpStmtRemappers()}
|
||||
* and {@link #getOpFieldRemappers()} and construct a preprocessor list. These are applied
|
||||
* successively to the op template fields so long as remapping occurs.
|
||||
*
|
||||
* @return a list of preprocessors for op template fields
|
||||
*/
|
||||
@Override
|
||||
public final Function<Map<String, Object>, Map<String, Object>> getPreprocessor() {
|
||||
List<Function<Map<String, Object>, Map<String, Object>>> mappers = new ArrayList<>();
|
||||
List<Function<Map<String, Object>, Map<String, Object>>> stmtRemappers =
|
||||
getOpStmtRemappers().stream()
|
||||
.map(m -> new FieldDestructuringMapper("stmt", m))
|
||||
.collect(Collectors.toList());
|
||||
getOpStmtRemappers().stream()
|
||||
.map(m -> new FieldDestructuringMapper("stmt", m))
|
||||
.collect(Collectors.toList());
|
||||
mappers.addAll(stmtRemappers);
|
||||
mappers.addAll(getOpFieldRemappers());
|
||||
|
||||
@ -77,13 +78,13 @@ public abstract class BaseDriverAdapter<R extends Op, S> implements DriverAdapte
|
||||
* This allows users to specify String-form op templates which are automatically
|
||||
* parsed and destructured into the canonical field-wise form for a given type of
|
||||
* operation.</p>
|
||||
*
|
||||
* <p>
|
||||
* <br/>
|
||||
*
|
||||
* <p>Each function in this list is applied in order. If the function returns a value,
|
||||
* then the 'stmt' field is removed and the resulting map is added to the other
|
||||
* fields in the op template.</p>
|
||||
*
|
||||
* <p>
|
||||
* <br/>
|
||||
*
|
||||
* <p>If a driver adapter is meant to support the {@code stmt} field, then this
|
||||
@ -92,7 +93,7 @@ public abstract class BaseDriverAdapter<R extends Op, S> implements DriverAdapte
|
||||
* implementation does nothing, as it must be decided per-driver whether or not
|
||||
* the stmt field will be used directly or whether it is short-hand for a more
|
||||
* canonical form.
|
||||
*
|
||||
* <p>
|
||||
* <br/>
|
||||
*
|
||||
* <p>If you want to automatically destructure stmt values into a map and inject
|
||||
@ -112,6 +113,7 @@ public abstract class BaseDriverAdapter<R extends Op, S> implements DriverAdapte
|
||||
/**
|
||||
* <p>Provide a list of field remappers which operate on arbitrary fields.
|
||||
* Each function is applied to the op template fields. </p>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@ -120,7 +122,7 @@ public abstract class BaseDriverAdapter<R extends Op, S> implements DriverAdapte
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized final DriverSpaceCache<? extends S> getSpaceCache() {
|
||||
public final synchronized DriverSpaceCache<? extends S> getSpaceCache() {
|
||||
if (spaceCache == null) {
|
||||
spaceCache = new DriverSpaceCache<>(getSpaceInitializer(getConfiguration()));
|
||||
}
|
||||
@ -151,33 +153,33 @@ public abstract class BaseDriverAdapter<R extends Op, S> implements DriverAdapte
|
||||
@Override
|
||||
public NBConfigModel getConfigModel() {
|
||||
return ConfigModel.of(BaseDriverAdapter.class)
|
||||
.add(Param.optional("alias"))
|
||||
.add(Param.defaultTo("strict", true, "strict op field mode, which requires that provided op fields are recognized and used"))
|
||||
.add(Param.optional(List.of("op", "stmt", "statement"), String.class, "op template in statement form"))
|
||||
.add(Param.optional("tags", String.class, "tags to be used to filter operations"))
|
||||
.add(Param.defaultTo("errors", "stop", "error handler configuration"))
|
||||
.add(Param.optional("threads").setRegex("\\d+|\\d+x|auto").setDescription("number of concurrent operations, controlled by threadpool"))
|
||||
.add(Param.optional("stride").setRegex("\\d+"))
|
||||
.add(Param.optional("striderate", String.class, "rate limit for strides per second"))
|
||||
.add(Param.optional("cycles").setRegex("\\d+[KMBGTPE]?|\\d+[KMBGTPE]?\\.\\.\\d+[KMBGTPE]?").setDescription("cycle interval to use"))
|
||||
.add(Param.optional("recycles").setDescription("allow cycles to be re-used this many times"))
|
||||
.add(Param.optional(List.of("cyclerate", "targetrate", "rate"), String.class, "rate limit for cycles per second"))
|
||||
.add(Param.optional("phaserate", String.class, "rate limit for phases per second"))
|
||||
.add(Param.optional("seq", String.class, "sequencing algorithm"))
|
||||
.add(Param.optional("instrument", Boolean.class))
|
||||
.add(Param.optional(List.of("workload", "yaml"), String.class, "location of workload yaml file"))
|
||||
.add(Param.optional("driver", String.class))
|
||||
.add(Param.defaultTo("dryrun","none").setRegex("(op|jsonnet|none)"))
|
||||
.asReadOnly();
|
||||
.add(Param.optional("alias"))
|
||||
.add(Param.defaultTo("strict", true, "strict op field mode, which requires that provided op fields are recognized and used"))
|
||||
.add(Param.optional(List.of("op", "stmt", "statement"), String.class, "op template in statement form"))
|
||||
.add(Param.optional("tags", String.class, "tags to be used to filter operations"))
|
||||
.add(Param.defaultTo("errors", "stop", "error handler configuration"))
|
||||
.add(Param.optional("threads").setRegex("\\d+|\\d+x|auto").setDescription("number of concurrent operations, controlled by threadpool"))
|
||||
.add(Param.optional("stride").setRegex("\\d+"))
|
||||
.add(Param.optional("striderate", String.class, "rate limit for strides per second"))
|
||||
.add(Param.optional("cycles").setRegex("\\d+[KMBGTPE]?|\\d+[KMBGTPE]?\\.\\.\\d+[KMBGTPE]?").setDescription("cycle interval to use"))
|
||||
.add(Param.optional("recycles").setDescription("allow cycles to be re-used this many times"))
|
||||
.add(Param.optional(List.of("cyclerate", "targetrate", "rate"), String.class, "rate limit for cycles per second"))
|
||||
.add(Param.optional("phaserate", String.class, "rate limit for phases per second"))
|
||||
.add(Param.optional("seq", String.class, "sequencing algorithm"))
|
||||
.add(Param.optional("instrument", Boolean.class))
|
||||
.add(Param.optional(List.of("workload", "yaml"), String.class, "location of workload yaml file"))
|
||||
.add(Param.optional("driver", String.class))
|
||||
.add(Param.defaultTo("dryrun", "none").setRegex("(op|jsonnet|none)"))
|
||||
.asReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBConfigModel getReconfigModel() {
|
||||
return ConfigModel.of(BaseDriverAdapter.class)
|
||||
.add(Param.optional("threads").setRegex("\\d+|\\d+x|auto").setDescription("number of concurrent operations, controlled by threadpool"))
|
||||
.add(Param.optional("striderate", String.class, "rate limit for strides per second"))
|
||||
.add(Param.optional(List.of("cyclerate", "targetrate", "rate"), String.class, "rate limit for cycles per second"))
|
||||
.asReadOnly();
|
||||
.add(Param.optional("threads").setRegex("\\d+|\\d+x|auto").setDescription("number of concurrent operations, controlled by threadpool"))
|
||||
.add(Param.optional("striderate", String.class, "rate limit for strides per second"))
|
||||
.add(Param.optional(List.of("cyclerate", "targetrate", "rate"), String.class, "rate limit for cycles per second"))
|
||||
.asReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -114,6 +114,7 @@ public class StandardActivity<R extends Op, S> extends SimpleActivity implements
|
||||
adapters.put(driverName, adapter);
|
||||
mappers.put(driverName, adapter.getOpMapper());
|
||||
}
|
||||
|
||||
supersetConfig.assertValidConfig(activityDef.getParams().getStringStringMap());
|
||||
|
||||
DriverAdapter adapter = adapters.get(driverName);
|
||||
|
@ -274,6 +274,7 @@ public class ConfigModel implements NBConfigModel {
|
||||
if (param.isRequired() && param.getDefaultValue() == null) {
|
||||
boolean provided = false;
|
||||
for (String name : param.getNames()) {
|
||||
|
||||
if (config.containsKey(name)) {
|
||||
provided = true;
|
||||
break;
|
||||
@ -305,7 +306,6 @@ public class ConfigModel implements NBConfigModel {
|
||||
throw new BasicError(paramhelp.toString());
|
||||
}
|
||||
Object value = config.get(configkey);
|
||||
Object testValue = convertValueTo(ofType.getSimpleName(), configkey, value, element.getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,13 +41,18 @@ public class NBConfiguration {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public NBConfigModel getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public static NBConfiguration empty() {
|
||||
return new NBConfiguration(ConfigModel.of(Object.class).asReadOnly(),new LinkedHashMap<>());
|
||||
return new NBConfiguration(ConfigModel.of(Object.class).asReadOnly(), new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the named parameter as {@link #getOptional(String)}, so long
|
||||
* as no env vars were reference OR all env var references were found.
|
||||
*
|
||||
* @param name The name of the variable to look up
|
||||
* @return An optional value, if present and (optionally) interpolated correctly from the environment
|
||||
*/
|
||||
@ -59,7 +64,7 @@ public class NBConfiguration {
|
||||
String span = optionalValue.get();
|
||||
Optional<String> maybeInterpolated = NBEnvironment.INSTANCE.interpolate(span);
|
||||
if (maybeInterpolated.isEmpty()) {
|
||||
throw new NBConfigError("Unable to interpolate '" + span +"' with env vars.");
|
||||
throw new NBConfigError("Unable to interpolate '" + span + "' with env vars.");
|
||||
}
|
||||
return maybeInterpolated;
|
||||
}
|
||||
@ -70,7 +75,7 @@ public class NBConfiguration {
|
||||
|
||||
public <T> T getWithEnv(String name, Class<? extends T> vclass) {
|
||||
T value = get(name, vclass);
|
||||
if (value==null) {
|
||||
if (value == null) {
|
||||
|
||||
}
|
||||
if (value instanceof String) {
|
||||
@ -79,7 +84,7 @@ public class NBConfiguration {
|
||||
throw new NBConfigError("Unable to interpolate env and sys props in '" + value + "'");
|
||||
}
|
||||
String result = interpolated.get();
|
||||
return ConfigModel.convertValueTo(this.getClass().getSimpleName(),name, result, vclass);
|
||||
return ConfigModel.convertValueTo(this.getClass().getSimpleName(), name, result, vclass);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
@ -90,14 +95,15 @@ public class NBConfiguration {
|
||||
* in addition to the internal model for type checking and ergonomic use. If you do not
|
||||
* call this within an assignment or context where the Java compiler knows what type you
|
||||
* are expecting, then use {@link #get(String, Class)} instead.
|
||||
*
|
||||
* @param name The name of the configuration parameter
|
||||
* @param <T> The (inferred) generic type of the configuration value
|
||||
* @param <T> The (inferred) generic type of the configuration value
|
||||
* @return The value of type T, matching the config model type for the provided field name
|
||||
*/
|
||||
public <T> T get(String name) {
|
||||
Param<T> param = (Param<T>)model.getNamedParams().get(name);
|
||||
Param<T> param = (Param<T>) model.getNamedParams().get(name);
|
||||
Object object = this.data.get(name);
|
||||
object=object!=null?object: param.getDefaultValue();
|
||||
object = object != null ? object : param.getDefaultValue();
|
||||
if (param.type.isInstance(object)) {
|
||||
return (T) object;
|
||||
} else if (param.type.isAssignableFrom(object.getClass())) {
|
||||
@ -110,28 +116,26 @@ public class NBConfiguration {
|
||||
}
|
||||
|
||||
public <T> T get(String name, Class<? extends T> type) {
|
||||
|
||||
Param<T> param = model.getParam(name);
|
||||
if (param==null) {
|
||||
if (param == null) {
|
||||
throw new NBConfigError("Parameter named '" + name + "' is not valid for " + model.getOf().getSimpleName() + ".");
|
||||
}
|
||||
if ((!param.isRequired())&¶m.getDefaultValue()==null) {
|
||||
|
||||
if ((!param.isRequired()) && param.getDefaultValue() == null) {
|
||||
throw new RuntimeException("Non-optional get on optional parameter " + name + "' which has no default value while configuring " + model.getOf() + "." +
|
||||
"\nTo avoid user impact, ensure that ConfigModel and NBConfigurable usage are aligned.");
|
||||
"\nTo avoid user impact, ensure that ConfigModel and NBConfigurable usage are aligned.");
|
||||
}
|
||||
|
||||
Object o = data.get(name);
|
||||
if (o == null) {
|
||||
if (param.getDefaultValue()==null) {
|
||||
if (param.getDefaultValue() == null) {
|
||||
throw new NBConfigError("config param '" + name + "' was not defined.");
|
||||
} else {
|
||||
o= param.getDefaultValue();
|
||||
o = param.getDefaultValue();
|
||||
}
|
||||
}
|
||||
return ConfigModel.convertValueTo(this.getClass().getSimpleName(), name,o,type);
|
||||
// if (type.isAssignableFrom(o.getClass())) {
|
||||
// return (T) o;
|
||||
// }
|
||||
// throw new NBConfigError("config param '" + name + "' was not assignable to class '" + type.getCanonicalName() + "'");
|
||||
return ConfigModel.convertValueTo(this.getClass().getSimpleName(), name, o, type);
|
||||
}
|
||||
|
||||
public Optional<String> getOptional(String name) {
|
||||
@ -146,10 +150,10 @@ public class NBConfiguration {
|
||||
Object o = null;
|
||||
for (String name : names) {
|
||||
Param<?> param = model.getParam(names);
|
||||
if (param!=null) {
|
||||
if (param != null) {
|
||||
for (String pname : param.getNames()) {
|
||||
o =data.get(pname);
|
||||
if (o!=null) {
|
||||
o = data.get(pname);
|
||||
if (o != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -157,17 +161,17 @@ public class NBConfiguration {
|
||||
throw new NBConfigError("Parameter was not found for " + Arrays.toString(names) + ".");
|
||||
}
|
||||
}
|
||||
if (o==null) {
|
||||
if (o == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (type.isInstance(o)) {
|
||||
return Optional.of((T) o);
|
||||
} else if (type.isAssignableFrom(o.getClass())) {
|
||||
return Optional.of((T)type.cast(o));
|
||||
return Optional.of((T) type.cast(o));
|
||||
} else if (NBTypeConverter.canConvert(o, type)) {
|
||||
return Optional.of((T) NBTypeConverter.convert(o, type));
|
||||
} else {
|
||||
throw new NBConfigError("config param " + Arrays.toString(names) +" was not assignable to class '" + type.getCanonicalName() + "'");
|
||||
throw new NBConfigError("config param " + Arrays.toString(names) + " was not assignable to class '" + type.getCanonicalName() + "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ package io.nosqlbench.api.engine.activityimpl;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import io.nosqlbench.api.engine.util.Unit;
|
||||
import io.nosqlbench.api.config.params.ParamsParser;
|
||||
import io.nosqlbench.api.engine.util.Unit;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.graalvm.polyglot.Value;
|
||||
@ -43,24 +43,24 @@ import java.util.stream.Collectors;
|
||||
* <p>No non-String types are used internally. Everything is encoded as a String, even though the
|
||||
* generic type is parameterized for Bindings support.</p>
|
||||
*/
|
||||
public class ParameterMap extends ConcurrentHashMap<String,Object> implements Bindings, ProxyObject {
|
||||
public class ParameterMap extends ConcurrentHashMap<String, Object> implements Bindings, ProxyObject {
|
||||
private final static Logger logger = LogManager.getLogger("PARAMS");
|
||||
private final static Gson gson = new GsonBuilder().create();
|
||||
|
||||
|
||||
// private final ConcurrentHashMap<String, String> paramMap = new ConcurrentHashMap<>(10);
|
||||
// private final ConcurrentHashMap<String, String> paramMap = new ConcurrentHashMap<>(10);
|
||||
private final AtomicLong changeCounter;
|
||||
private final LinkedList<Listener> listeners = new LinkedList<>();
|
||||
|
||||
public ParameterMap(Map<String, String> valueMap) {
|
||||
logger.trace(() -> "new parameter map:" + valueMap.toString());
|
||||
this.changeCounter=new AtomicLong(0L);
|
||||
this.changeCounter = new AtomicLong(0L);
|
||||
putAll(valueMap);
|
||||
}
|
||||
|
||||
public void assertOnlyOneOf(String... paramName) {
|
||||
Object[] objects = Arrays.stream(paramName).map(super::get).filter(Objects::nonNull).toArray();
|
||||
if (objects.length>1) {
|
||||
if (objects.length > 1) {
|
||||
throw new RuntimeException("Multiple incompatible parameters are specified: " + Arrays.toString(paramName)
|
||||
+ ". Just use one of them.");
|
||||
}
|
||||
@ -68,9 +68,9 @@ public class ParameterMap extends ConcurrentHashMap<String,Object> implements Bi
|
||||
|
||||
public Optional<String> getOptionalString(String... paramName) {
|
||||
Object[] objects = Arrays.stream(paramName).map(super::get).filter(Objects::nonNull).toArray();
|
||||
if (objects.length>1) {
|
||||
throw new RuntimeException("Multiple parameters are specified for the same value: " + Arrays.toString(paramName)
|
||||
+ ". Just use one of them.");
|
||||
if (objects.length > 1) {
|
||||
throw new RuntimeException("Multiple parameters are specified for the same value: " + Arrays.toString(paramName)
|
||||
+ ". Just use one of them.");
|
||||
}
|
||||
return Arrays.stream(objects).map(String::valueOf).findAny();
|
||||
//return Optional.ofNullable(super.get(paramName)).map(String::valueOf);
|
||||
@ -89,10 +89,10 @@ public class ParameterMap extends ConcurrentHashMap<String,Object> implements Bi
|
||||
|
||||
public Optional<NamedParameter> getOptionalNamedParameter(String... paramName) {
|
||||
List<String> defined = Arrays.stream(paramName).filter(super::containsKey).collect(Collectors.toList());
|
||||
if (defined.size()==1) {
|
||||
return Optional.of(new NamedParameter(defined.get(0),String.valueOf(super.get(defined.get(0)))));
|
||||
if (defined.size() == 1) {
|
||||
return Optional.of(new NamedParameter(defined.get(0), String.valueOf(super.get(defined.get(0)))));
|
||||
}
|
||||
if (defined.size()>1) {
|
||||
if (defined.size() > 1) {
|
||||
throw new RuntimeException("Multiple incompatible parameter names are specified: " + Arrays.toString(paramName)
|
||||
+ ". Just use one of them.");
|
||||
}
|
||||
@ -237,7 +237,8 @@ public class ParameterMap extends ConcurrentHashMap<String,Object> implements Bi
|
||||
logger.debug(() -> "getting entry set for " + this);
|
||||
return super.entrySet()
|
||||
.stream()
|
||||
.map(e -> new AbstractMap.SimpleEntry<String,Object>(e.getKey(), e.getValue()) {})
|
||||
.map(e -> new AbstractMap.SimpleEntry<String, Object>(e.getKey(), e.getValue()) {
|
||||
})
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
}
|
||||
|
||||
@ -285,7 +286,7 @@ public class ParameterMap extends ConcurrentHashMap<String,Object> implements Bi
|
||||
if (encodedParams == null) {
|
||||
throw new RuntimeException("Must provide a non-null String to parse parameters.");
|
||||
}
|
||||
Map<String, String> parsedMap = ParamsParser.parse(encodedParams,true);
|
||||
Map<String, String> parsedMap = ParamsParser.parse(encodedParams, true);
|
||||
return new ParameterMap(parsedMap);
|
||||
}
|
||||
|
||||
@ -318,13 +319,13 @@ public class ParameterMap extends ConcurrentHashMap<String,Object> implements Bi
|
||||
|
||||
@Override
|
||||
public void putMember(String key, Value value) {
|
||||
this.put(key,value);
|
||||
this.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeMember(String key) {
|
||||
Object removed = this.remove(key);
|
||||
return removed!=null;
|
||||
return removed != null;
|
||||
}
|
||||
|
||||
|
||||
@ -332,10 +333,10 @@ public class ParameterMap extends ConcurrentHashMap<String,Object> implements Bi
|
||||
void handleParameterMapUpdate(ParameterMap parameterMap);
|
||||
}
|
||||
|
||||
public Map<String,String> getStringStringMap() {
|
||||
return new HashMap<String,String>() {{
|
||||
public Map<String, String> getStringStringMap() {
|
||||
return new HashMap<>() {{
|
||||
for (Entry entry : ParameterMap.this.entrySet()) {
|
||||
put(entry.getKey().toString(),entry.getValue().toString());
|
||||
put(entry.getKey().toString(), entry.getValue().toString());
|
||||
}
|
||||
}};
|
||||
}
|
||||
@ -348,21 +349,24 @@ public class ParameterMap extends ConcurrentHashMap<String,Object> implements Bi
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name+"="+value;
|
||||
return name + "=" + value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public static String toJSON(Map<?,?> map) {
|
||||
public static String toJSON(Map<?, ?> map) {
|
||||
List<String> l = new ArrayList<>();
|
||||
map.forEach((k,v) -> l.add("'" + k + "': '" + v + "'"));
|
||||
return "params={"+String.join(",\n ",l)+"};\n";
|
||||
map.forEach((k, v) -> l.add("'" + k + "': '" + v + "'"));
|
||||
return "params={" + String.join(",\n ", l) + "};\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ class ExitStatusIntegrationTests {
|
||||
invoker.setLogDir("logs/test");
|
||||
ProcessResult result = invoker.run("exitstatus_asyncstoprequest", 30,
|
||||
"java", "-jar", JARNAME, "--logs-dir", "logs/test/asyncstop", "--logs-level", "debug", "run",
|
||||
"driver=diag", "threads=2", "cyclerate=10", "op=erroroncycle:erroroncycle=10", "cycles=500", "-vvv"
|
||||
"driver=diag", "threads=2", "cyclerate=10", "op=erroroncycle:erroroncycle=10", "cycles=50", "-vvv"
|
||||
);
|
||||
assertThat(result.exception).isNull();
|
||||
String stdout = String.join("\n", result.getStdoutData());
|
||||
|
Loading…
Reference in New Issue
Block a user