mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2024-11-27 19:20:42 -06:00
checkpoint:
various fixes to enable rampup and main phases inclusion of Mark Wolters stats parsing; ratio injection based on nodetool stats allow bind point names to include angle brackets disable raw format processing
This commit is contained in:
parent
71fd51225c
commit
080d9005e0
@ -25,6 +25,7 @@ import io.nosqlbench.adapter.cqld4.optypes.Cqld4CqlOp;
|
||||
import io.nosqlbench.adapter.cqld4.optypes.Cqld4CqlPreparedStatement;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
|
||||
import io.nosqlbench.engine.api.templating.ParsedOp;
|
||||
import io.nosqlbench.nb.api.errors.OpConfigError;
|
||||
import io.nosqlbench.virtdata.core.templates.ParsedStringTemplate;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -64,7 +65,11 @@ public class Cqld4PreparedStmtDispenser extends BaseCqlStmtDispenser {
|
||||
|
||||
String preparedQueryString = stmtTpl.getPositionalStatement(s -> "?");
|
||||
boundSession = getSessionFunc().apply(0);
|
||||
preparedStmt = boundSession.prepare(preparedQueryString);
|
||||
try {
|
||||
preparedStmt = boundSession.prepare(preparedQueryString);
|
||||
} catch (Exception e) {
|
||||
throw new OpConfigError(e + "( for statement '" + stmtTpl + "')");
|
||||
}
|
||||
|
||||
LongFunction<Statement> boundStmtFunc = c -> {
|
||||
Object[] apply = fieldsF.apply(c);
|
||||
|
@ -57,6 +57,10 @@ public class CqlColumnDef implements Labeled {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getTrimmedTypedef() {
|
||||
return type.replaceAll(" ","");
|
||||
}
|
||||
|
||||
public String getTable() {
|
||||
return table;
|
||||
}
|
||||
@ -87,4 +91,8 @@ public class CqlColumnDef implements Labeled {
|
||||
public void setTable(String table) {
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
public boolean isCounter() {
|
||||
return getTrimmedTypedef().equalsIgnoreCase("counter");
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package io.nosqlbench.converters.cql.cqlast;
|
||||
|
||||
import io.nosqlbench.nb.api.labels.Labeled;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CqlKeyspace implements Labeled {
|
||||
@ -25,6 +26,17 @@ public class CqlKeyspace implements Labeled {
|
||||
String refddl;
|
||||
private String refReplDdl;
|
||||
|
||||
public Map<String, String> getKeyspaceAttributes() {
|
||||
return keyspaceAttributes;
|
||||
}
|
||||
|
||||
public void setKeyspaceAttributes(Map<String, String> keyspaceAttributes) {
|
||||
this.keyspaceAttributes = keyspaceAttributes;
|
||||
}
|
||||
|
||||
Map<String,String> keyspaceAttributes = new HashMap<String,String>();
|
||||
|
||||
|
||||
public CqlKeyspace() {
|
||||
}
|
||||
|
||||
|
@ -18,10 +18,7 @@ package io.nosqlbench.converters.cql.cqlast;
|
||||
|
||||
import io.nosqlbench.nb.api.labels.Labeled;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CqlTable implements Labeled {
|
||||
@ -31,6 +28,16 @@ public class CqlTable implements Labeled {
|
||||
|
||||
private String refddl;
|
||||
|
||||
public Map<String, String> getTableAttributes() {
|
||||
return tableAttributes;
|
||||
}
|
||||
|
||||
public void setTableAttributes(Map<String, String> tableAttributes) {
|
||||
this.tableAttributes = tableAttributes;
|
||||
}
|
||||
|
||||
Map<String,String> tableAttributes = new HashMap<String,String>();
|
||||
|
||||
List<String> partitionKeys = new ArrayList<>();
|
||||
List<String> clusteringColumns = new ArrayList<>();
|
||||
|
||||
@ -117,12 +124,6 @@ public class CqlTable implements Labeled {
|
||||
return this.clusteringColumns;
|
||||
}
|
||||
|
||||
public String typedefForColumn(String colname) {
|
||||
return coldefs.stream()
|
||||
.filter(c -> c.getName().equalsIgnoreCase(colname))
|
||||
.map(CqlColumnDef::getType).findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
public CqlColumnDef getColumnDefForName(String colname) {
|
||||
Optional<CqlColumnDef> def = coldefs
|
||||
.stream()
|
||||
@ -135,4 +136,10 @@ public class CqlTable implements Labeled {
|
||||
return def.orElseThrow();
|
||||
}
|
||||
|
||||
public List<CqlColumnDef> getNonKeyColumnDefinitions() {
|
||||
return coldefs.stream()
|
||||
.filter(n -> !partitionKeys.contains(n.getName()))
|
||||
.filter(n -> !clusteringColumns.contains(n.getName()))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.converters.cql.exporters;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CqlKeyspaceStats {
|
||||
String keyspaceName;
|
||||
|
||||
Map<String,String> keyspaceAttributes = new HashMap<String,String>();
|
||||
|
||||
Map<String, CqlTableStats> keyspaceTables = new HashMap<String, CqlTableStats>();
|
||||
public String getKeyspaceName() {
|
||||
return keyspaceName;
|
||||
}
|
||||
|
||||
public void setKeyspaceName(String keyspaceName) {
|
||||
this.keyspaceName = keyspaceName;
|
||||
}
|
||||
|
||||
public Map<String, String> getKeyspaceAttributes() {
|
||||
return keyspaceAttributes;
|
||||
}
|
||||
|
||||
public String getKeyspaceAttribute(String attributeName) {
|
||||
return keyspaceAttributes.get(attributeName);
|
||||
}
|
||||
|
||||
public void setKeyspaceAttributes(Map<String, String> keyspaceAttributes) {
|
||||
this.keyspaceAttributes = keyspaceAttributes;
|
||||
}
|
||||
|
||||
public void setKeyspaceAttribute(String attributeName, String attributeVal) {
|
||||
this.keyspaceAttributes.put(attributeName, attributeVal);
|
||||
}
|
||||
|
||||
public Map<String, CqlTableStats> getKeyspaceTables() {
|
||||
return keyspaceTables;
|
||||
}
|
||||
|
||||
public CqlTableStats getKeyspaceTable(String tableName) {
|
||||
return keyspaceTables.get(tableName);
|
||||
}
|
||||
|
||||
public void setKeyspaceTables(Map<String, CqlTableStats> keyspaceTables) {
|
||||
this.keyspaceTables = keyspaceTables;
|
||||
}
|
||||
|
||||
public void setKeyspaceTable(String tableName, CqlTableStats tableAttributes) {
|
||||
this.keyspaceTables.put(tableName, tableAttributes);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -16,6 +16,8 @@
|
||||
|
||||
package io.nosqlbench.converters.cql.exporters;
|
||||
|
||||
import io.nosqlbench.converters.cql.cqlast.CqlColumnDef;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
@ -47,6 +49,10 @@ public enum CqlLiteralFormat {
|
||||
this.literalFormat = modifier;
|
||||
}
|
||||
|
||||
public static String formatBindType(CqlColumnDef cd, String valueref) {
|
||||
return CqlLiteralFormat.valueOfCqlType(cd.getTrimmedTypedef()).orElse(CqlLiteralFormat.UNKNOWN).format(valueref);
|
||||
}
|
||||
|
||||
public String format(String value) {
|
||||
return this.literalFormat.apply(value);
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.converters.cql.exporters;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CqlSchemaStats {
|
||||
Map<String, CqlKeyspaceStats> keyspaces = new HashMap<String, CqlKeyspaceStats>();
|
||||
|
||||
public Map<String, CqlKeyspaceStats> getKeyspaces() {
|
||||
return keyspaces;
|
||||
}
|
||||
|
||||
public void setKeyspaces(Map<String, CqlKeyspaceStats> keyspaces) {
|
||||
this.keyspaces = keyspaces;
|
||||
}
|
||||
|
||||
public CqlKeyspaceStats getKeyspace(String keyspaceName) {
|
||||
return keyspaces.get(keyspaceName);
|
||||
}
|
||||
|
||||
public void setKeyspace(CqlKeyspaceStats keyspace) {
|
||||
this.keyspaces.put(keyspace.getKeyspaceName(), keyspace);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.converters.cql.exporters;
|
||||
|
||||
import org.apache.commons.math4.util.Pair;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
|
||||
public class CqlSchemaStatsParser {
|
||||
private static final String KEYSPACE = "Keyspace";
|
||||
private static final String TABLE = "Table";
|
||||
|
||||
CqlSchemaStats stats = null;
|
||||
CqlKeyspaceStats currentKeyspace = null;
|
||||
CqlTableStats currentTable = null;
|
||||
|
||||
public CqlSchemaStats parse(Path statspath) throws IOException {
|
||||
this.stats = new CqlSchemaStats();
|
||||
BufferedReader reader = Files.newBufferedReader(statspath);
|
||||
String currentLine = reader.readLine(); //ignore 1st line
|
||||
while((currentLine = reader.readLine()) != null) {
|
||||
currentLine = currentLine.replaceAll("\t","");
|
||||
if (!evalForKeyspace(currentLine)) {
|
||||
if (!evalForTable(currentLine)) {
|
||||
String[] splitLine = currentLine.split(":");
|
||||
if (splitLine.length > 1) {
|
||||
Pair<String, String> keyval = new Pair(splitLine[0].trim(), splitLine[1].trim());
|
||||
addAttribute(keyval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
writeCurrentTable();
|
||||
writeCurrentKeyspace();
|
||||
return stats;
|
||||
}
|
||||
|
||||
private void addAttribute(Pair<String, String> keyval) {
|
||||
if (currentTable != null) {
|
||||
currentTable.setAttribute(keyval.getFirst(), keyval.getSecond());
|
||||
} else if (currentKeyspace != null) {
|
||||
currentKeyspace.setKeyspaceAttribute(keyval.getFirst(), keyval.getSecond());
|
||||
} else {
|
||||
throw new RuntimeException("Orphaned attribute: " + keyval.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean evalForTable(String currentLine) {
|
||||
if (currentLine.startsWith(TABLE)) {
|
||||
writeCurrentTable();
|
||||
currentTable = new CqlTableStats();
|
||||
currentTable.setTableName(currentLine.split(":")[1].trim());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean evalForKeyspace(String currentLine) {
|
||||
if (currentLine.startsWith(KEYSPACE)) {
|
||||
writeCurrentTable();
|
||||
writeCurrentKeyspace();
|
||||
currentKeyspace = new CqlKeyspaceStats();
|
||||
currentKeyspace.setKeyspaceName(currentLine.split(":")[1].trim());
|
||||
currentTable = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void writeCurrentKeyspace() {
|
||||
if (currentKeyspace != null) {
|
||||
stats.setKeyspace(currentKeyspace);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCurrentTable() {
|
||||
if (currentTable != null) {
|
||||
if (currentKeyspace == null) {
|
||||
throw new RuntimeException("Table " + currentTable.getTableName() + "has no associated keyspace");
|
||||
} else {
|
||||
currentKeyspace.setKeyspaceTable(currentTable.getTableName(), currentTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.converters.cql.exporters;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CqlTableStats {
|
||||
String tableName;
|
||||
|
||||
Map<String,String> attributes = new HashMap<String,String>();
|
||||
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public Map<String, String> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public String getAttribute(String attributeName) {
|
||||
return attributes.get(attributeName);
|
||||
}
|
||||
|
||||
public void setAttributes(Map<String, String> attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
public void setAttribute(String attributeName, String attributeVal) {
|
||||
attributes.put(attributeName, attributeVal);
|
||||
}
|
||||
|
||||
}
|
@ -24,6 +24,7 @@ import io.nosqlbench.converters.cql.cqlast.CqlModel;
|
||||
import io.nosqlbench.converters.cql.cqlast.CqlTable;
|
||||
import io.nosqlbench.converters.cql.exporters.binders.*;
|
||||
import io.nosqlbench.converters.cql.exporters.transformers.CqlModelFixup;
|
||||
import io.nosqlbench.converters.cql.exporters.transformers.RatioCalculator;
|
||||
import io.nosqlbench.converters.cql.parser.CqlModelParser;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -62,31 +63,32 @@ public class CqlWorkloadExporter {
|
||||
private final BindingsAccumulator bindings = new BindingsAccumulator(namer, List.of(defaultBindings));
|
||||
private CqlModel model;
|
||||
private final Map<String, String> bindingsMap = new LinkedHashMap<>();
|
||||
private final List<Function<CqlModel, CqlModel>> transformers = List.of(new CqlModelFixup());
|
||||
private final int DEFAULT_RESOLUTION = 10000;
|
||||
|
||||
public CqlWorkloadExporter(CqlModel model) {
|
||||
public CqlWorkloadExporter(CqlModel model, List<Function<CqlModel, CqlModel>> transformers) {
|
||||
this.model = model;
|
||||
for (Function<CqlModel, CqlModel> transformer : transformers) {
|
||||
this.model = transformer.apply(this.model);
|
||||
}
|
||||
}
|
||||
|
||||
public CqlWorkloadExporter(String ddl, Path srcpath) {
|
||||
public CqlWorkloadExporter(String ddl, Path srcpath, List<Function<CqlModel, CqlModel>> transformers) {
|
||||
this.model = CqlModelParser.parse(ddl, srcpath);
|
||||
for (Function<CqlModel, CqlModel> transformer : transformers) {
|
||||
this.model = transformer.apply(this.model);
|
||||
}
|
||||
}
|
||||
|
||||
public CqlWorkloadExporter(String ddl) {
|
||||
public CqlWorkloadExporter(String ddl, List<Function<CqlModel, CqlModel>> transformers) {
|
||||
this.model = CqlModelParser.parse(ddl, null);
|
||||
for (Function<CqlModel, CqlModel> transformer : transformers) {
|
||||
this.model = transformer.apply(this.model);
|
||||
}
|
||||
}
|
||||
|
||||
public CqlWorkloadExporter(Path path) {
|
||||
public CqlWorkloadExporter(Path path, List<Function<CqlModel, CqlModel>> transformers) {
|
||||
this.model = CqlModelParser.parse(path);
|
||||
|
||||
for (Function<CqlModel, CqlModel> transformer : transformers) {
|
||||
this.model = transformer.apply(this.model);
|
||||
}
|
||||
@ -107,7 +109,7 @@ public class CqlWorkloadExporter {
|
||||
}
|
||||
|
||||
Path target = null;
|
||||
if (args.length == 2) {
|
||||
if (args.length >= 2) {
|
||||
target = Path.of(args[1]);
|
||||
logger.info("using output path as '" + target + "'");
|
||||
} else {
|
||||
@ -123,7 +125,25 @@ public class CqlWorkloadExporter {
|
||||
throw new RuntimeException("Target file '" + target + "' exists. Please remove it first or use a different target file name.");
|
||||
}
|
||||
|
||||
CqlWorkloadExporter exporter = new CqlWorkloadExporter(srcpath);
|
||||
CqlSchemaStats schemaStats = null;
|
||||
if (args.length == 3) {
|
||||
Path statspath = Path.of(args[2]);
|
||||
try {
|
||||
CqlSchemaStatsParser parser = new CqlSchemaStatsParser();
|
||||
schemaStats = parser.parse(statspath);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
List<Function<CqlModel, CqlModel>> transformers = List.of(
|
||||
new CqlModelFixup(), // elide UDTs in lieu of blobs for now
|
||||
new StatsEnhancer(schemaStats), // add keyspace, schema and table stats from nodetool
|
||||
new RatioCalculator() // Normalize read and write fraction over total ops in unit interval
|
||||
);
|
||||
|
||||
CqlWorkloadExporter exporter = new CqlWorkloadExporter(srcpath, transformers);
|
||||
|
||||
String workload = exporter.getWorkloadAsYaml();
|
||||
try {
|
||||
Files.writeString(
|
||||
@ -136,6 +156,7 @@ public class CqlWorkloadExporter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Object> getWorkload() {
|
||||
namer.populate(model);
|
||||
|
||||
@ -165,41 +186,84 @@ public class CqlWorkloadExporter {
|
||||
}
|
||||
|
||||
private Map<String, Object> genMainBlock(CqlModel model) {
|
||||
Map<String, String> mainOpTemplates = new LinkedHashMap<>();
|
||||
Map<String, Object> mainOpTemplates = new LinkedHashMap<>();
|
||||
|
||||
for (CqlTable table : model.getAllTables()) {
|
||||
Optional<String> template = this.genInsertTemplate(table);
|
||||
if (template.isPresent()) {
|
||||
mainOpTemplates.put(namer.nameFor(table, "optype", "insert"),
|
||||
template.get());
|
||||
|
||||
if (!isCounterTable(table)) {
|
||||
|
||||
Optional<String> insertTemplate = this.genInsertTemplate(table);
|
||||
if (insertTemplate.isPresent()) {
|
||||
mainOpTemplates.put(namer.nameFor(table, "optype", "insert"),
|
||||
Map.of(
|
||||
"stmt", insertTemplate.get(),
|
||||
"ratio", writeRatioFor(table)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
throw new RuntimeException("Unable to generate main insert template for table '" + table + "'");
|
||||
}
|
||||
} else {
|
||||
logger.info("skipped insert for counter table '" + table.getTableName() + "'");
|
||||
}
|
||||
|
||||
Optional<String> updateTemplate = this.genUpdateTemplate(table);
|
||||
if (updateTemplate.isPresent()) {
|
||||
mainOpTemplates.put(namer.nameFor(table, "optype", "update"),
|
||||
Map.of(
|
||||
"stmt", updateTemplate.get(),
|
||||
"ratio", writeRatioFor(table)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
throw new RuntimeException("Unable to generate main insert template for table '" + table + "'");
|
||||
}
|
||||
}
|
||||
|
||||
for (CqlTable table : model.getAllTables()) {
|
||||
Optional<String> template = this.genSelectTemplate(table);
|
||||
if (template.isPresent()) {
|
||||
|
||||
Optional<String> selectTemplate = this.genSelectTemplate(table);
|
||||
if (selectTemplate.isPresent()) {
|
||||
mainOpTemplates.put(namer.nameFor(table, "optype", "select"),
|
||||
template.get());
|
||||
Map.of("stmt", selectTemplate.get(),
|
||||
"ratio", readRatioFor(table))
|
||||
);
|
||||
} else {
|
||||
throw new RuntimeException("Unable to generate main select template for table '" + table + "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Map.of("ops", mainOpTemplates);
|
||||
}
|
||||
|
||||
private boolean isCounterTable(CqlTable table) {
|
||||
return table.getColumnDefinitions().stream()
|
||||
.anyMatch(cd -> cd.getTrimmedTypedef().equalsIgnoreCase("counter"));
|
||||
}
|
||||
|
||||
|
||||
private int readRatioFor(CqlTable table) {
|
||||
double weighted_reads = Double.parseDouble(table.getTableAttributes().get("weighted_reads"));
|
||||
return (int) (weighted_reads * DEFAULT_RESOLUTION);
|
||||
}
|
||||
|
||||
private int writeRatioFor(CqlTable table) {
|
||||
double weighted_writes = Double.parseDouble(table.getTableAttributes().get("weighted_writes"));
|
||||
return (int) (weighted_writes * DEFAULT_RESOLUTION);
|
||||
}
|
||||
|
||||
|
||||
private Map<String, Object> genRampupBlock(CqlModel model) {
|
||||
Map<String, String> rampupOpTemplates = new LinkedHashMap<>();
|
||||
|
||||
|
||||
for (CqlTable table : model.getAllTables()) {
|
||||
Optional<String> insert = genInsertTemplate(table);
|
||||
if (insert.isPresent()) {
|
||||
rampupOpTemplates.put(namer.nameFor(table, "optype", "insert"), insert.get());
|
||||
} else {
|
||||
throw new RuntimeException("Unable to create rampup template for table '" + table + "'");
|
||||
if (!isCounterTable(table)) {
|
||||
Optional<String> insert = genInsertTemplate(table);
|
||||
if (insert.isPresent()) {
|
||||
rampupOpTemplates.put(namer.nameFor(table, "optype", "insert"), insert.get());
|
||||
} else {
|
||||
throw new RuntimeException("Unable to create rampup template for table '" + table + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,19 +302,46 @@ public class CqlWorkloadExporter {
|
||||
}
|
||||
|
||||
private String genPredicatePart(CqlColumnDef def) {
|
||||
String typeName = def.getType();
|
||||
|
||||
CqlLiteralFormat cqlLiteralFormat =
|
||||
CqlLiteralFormat.valueOfCqlType(typeName).orElse(CqlLiteralFormat.UNKNOWN);
|
||||
if (cqlLiteralFormat == CqlLiteralFormat.UNKNOWN) {
|
||||
logger.warn("Unknown literal format for " + typeName);
|
||||
}
|
||||
|
||||
String typeName = def.getTrimmedTypedef();
|
||||
Binding binding = bindings.forColumn(def);
|
||||
|
||||
return def.getName() + "=" + cqlLiteralFormat.format("{" + binding.name() + "}");
|
||||
return def.getName() + "={" + binding.name() + "}";
|
||||
}
|
||||
|
||||
private Optional<String> genUpdateTemplate(CqlTable table) {
|
||||
try {
|
||||
|
||||
return Optional.of("""
|
||||
update KEYSPACE.TABLE
|
||||
set ASSIGNMENTS
|
||||
where PREDICATES;
|
||||
"""
|
||||
.replaceAll("KEYSPACE", table.getKeySpace())
|
||||
.replaceAll("TABLE", table.getTableName())
|
||||
.replaceAll("PREDICATES", genPredicateTemplate(table))
|
||||
.replaceAll("ASSIGNMENTS", genAssignments(table)));
|
||||
|
||||
} catch (UnresolvedBindingException ube) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private String genAssignments(CqlTable table) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (CqlColumnDef coldef : table.getNonKeyColumnDefinitions()) {
|
||||
if (coldef.isCounter()) {
|
||||
sb.append(coldef.getName()).append("=")
|
||||
.append(coldef.getName()).append("+").append("{").append(bindings.forColumn(coldef).name()).append("}")
|
||||
.append(", ");
|
||||
} else {
|
||||
sb.append(coldef.getName()).append("=")
|
||||
.append("{").append(bindings.forColumn(coldef).name()).append("}")
|
||||
.append(", ");
|
||||
}
|
||||
}
|
||||
sb.setLength(sb.length() - ", ".length());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private Optional<String> genInsertTemplate(CqlTable table) {
|
||||
try {
|
||||
@ -264,9 +355,9 @@ public class CqlWorkloadExporter {
|
||||
.stream()
|
||||
.map(cd -> {
|
||||
Binding binding = bindings.forColumn(cd);
|
||||
return binding.name();
|
||||
return "{" + binding.name() + "}";
|
||||
})
|
||||
.collect(Collectors.joining("},{", "{", "}"))
|
||||
.collect(Collectors.joining(","))
|
||||
+ ");");
|
||||
} catch (UnresolvedBindingException ube) {
|
||||
return Optional.empty();
|
||||
|
@ -58,6 +58,9 @@ public class DefaultCqlBindings implements BindingsLibrary {
|
||||
|
||||
@Override
|
||||
public Optional<Binding> resolveBindingsFor(CqlColumnDef def) {
|
||||
return Optional.ofNullable(new Binding(def.getType(),bindings.get(def.getType())));
|
||||
String typedef = def.getTrimmedTypedef();
|
||||
String recipe = bindings.get(def.getTrimmedTypedef());
|
||||
Binding optionalBinding = new Binding(typedef, recipe);
|
||||
return Optional.ofNullable(optionalBinding);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.converters.cql.exporters;
|
||||
|
||||
import io.nosqlbench.converters.cql.cqlast.CqlModel;
|
||||
import io.nosqlbench.converters.cql.cqlast.CqlTable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class StatsEnhancer implements Function<CqlModel, CqlModel> {
|
||||
private final CqlSchemaStats schemaStats;
|
||||
|
||||
public StatsEnhancer(CqlSchemaStats schemaStats) {
|
||||
this.schemaStats = schemaStats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CqlModel apply(CqlModel model) {
|
||||
if (schemaStats != null) {
|
||||
//TODO: rewrite this in something resembling an efficient way
|
||||
CqlKeyspaceStats ksStats = null;
|
||||
for (String ksName : model.getKeyspaces().keySet()) {
|
||||
if ((ksStats = schemaStats.getKeyspace(ksName)) != null) {
|
||||
model.getKeyspaces().get(ksName).setKeyspaceAttributes(ksStats.getKeyspaceAttributes());
|
||||
Map<String, CqlTable> ksTables = model.getTablesByKeyspace().get(ksName);
|
||||
for (String tableName : ksTables.keySet()) {
|
||||
if (ksStats.getKeyspaceTable(tableName) != null) {
|
||||
model.getTablesByKeyspace().get(ksName).get(tableName)
|
||||
.setTableAttributes(ksStats.getKeyspaceTable(tableName).getAttributes());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return model;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.converters.cql.exporters.transformers;
|
||||
|
||||
import io.nosqlbench.converters.cql.cqlast.CqlModel;
|
||||
import io.nosqlbench.converters.cql.cqlast.CqlTable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class RatioCalculator implements Function<CqlModel,CqlModel> {
|
||||
|
||||
@Override
|
||||
public CqlModel apply(CqlModel model) {
|
||||
double totalReads = 0.0d;
|
||||
double totalWrites = 0.0d;
|
||||
double totalSpace = 0.0d;
|
||||
double totalOps=0.0d;
|
||||
|
||||
for (CqlTable table : model.getAllTables()) {
|
||||
String local_read_count = table.getTableAttributes().get("Local read count");
|
||||
double reads = Double.parseDouble(local_read_count);
|
||||
totalReads+=reads;
|
||||
totalOps+=reads;
|
||||
|
||||
String local_write_count = table.getTableAttributes().get("Local write count");
|
||||
double writes = Double.parseDouble(local_write_count);
|
||||
totalWrites += writes;
|
||||
totalOps+=writes;
|
||||
|
||||
String space_used_total = table.getTableAttributes().get("Space used (total)");
|
||||
double space = Double.parseDouble(space_used_total);
|
||||
totalSpace+=space;
|
||||
}
|
||||
|
||||
for (CqlTable table : model.getAllTables()) {
|
||||
double reads = Double.parseDouble(table.getTableAttributes().get("Local read count"));
|
||||
double writes = Double.parseDouble(table.getTableAttributes().get("Local write count"));
|
||||
|
||||
table.getTableAttributes().put("weighted_reads", String.valueOf(reads / totalOps));
|
||||
table.getTableAttributes().put("weighted_writes", String.valueOf(writes / totalOps));
|
||||
|
||||
table.getTableAttributes().put("weighted_space", String.valueOf(Double.parseDouble(table.getTableAttributes().get("Space used (total)")) / totalReads));
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -22,6 +22,7 @@ import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
@ -46,7 +47,7 @@ public class CqlParserHarnessTest {
|
||||
|
||||
@Test
|
||||
public void testAllTypes() {
|
||||
CqlWorkloadExporter exporter = new CqlWorkloadExporter(Path.of("src/test/resources/testschemas/cql_alltypes.cql"));
|
||||
CqlWorkloadExporter exporter = new CqlWorkloadExporter(Path.of("src/test/resources/testschemas/cql_alltypes.cql"), List.of());
|
||||
var data = exporter.getWorkloadAsYaml();
|
||||
|
||||
}
|
||||
@ -54,7 +55,7 @@ public class CqlParserHarnessTest {
|
||||
@Disabled
|
||||
@Test
|
||||
public void testGenBasicWorkload() {
|
||||
CqlWorkloadExporter exporter = new CqlWorkloadExporter(ddl);
|
||||
CqlWorkloadExporter exporter = new CqlWorkloadExporter(ddl, List.of());
|
||||
assertThatThrownBy(() -> exporter.getWorkloadAsYaml()).isInstanceOf(RuntimeException.class);
|
||||
}
|
||||
|
||||
|
@ -466,22 +466,23 @@ public class SimpleActivity implements Activity, ProgressCapable {
|
||||
List<DriverAdapter> adapters,
|
||||
List<ParsedOp> pops
|
||||
) {
|
||||
List<Long> ratios = new ArrayList<>(pops.size());
|
||||
|
||||
for (int i = 0; i < pops.size(); i++) {
|
||||
|
||||
ParsedOp pop = pops.get(i);
|
||||
long ratio = pop.takeStaticConfigOr("ratio", 1);
|
||||
ratios.add(ratio);
|
||||
}
|
||||
|
||||
SequencerType sequencerType = getParams()
|
||||
.getOptionalString("seq")
|
||||
.map(SequencerType::valueOf)
|
||||
.orElse(SequencerType.bucket);
|
||||
SequencePlanner<OpDispenser<? extends O>> planner = new SequencePlanner<>(sequencerType);
|
||||
|
||||
try {
|
||||
|
||||
List<Long> ratios = new ArrayList<>(pops.size());
|
||||
|
||||
for (int i = 0; i < pops.size(); i++) {
|
||||
|
||||
ParsedOp pop = pops.get(i);
|
||||
long ratio = pop.takeStaticConfigOr("ratio", 1);
|
||||
ratios.add(ratio);
|
||||
}
|
||||
|
||||
SequencerType sequencerType = getParams()
|
||||
.getOptionalString("seq")
|
||||
.map(SequencerType::valueOf)
|
||||
.orElse(SequencerType.bucket);
|
||||
SequencePlanner<OpDispenser<? extends O>> planner = new SequencePlanner<>(sequencerType);
|
||||
|
||||
for (int i = 0; i < pops.size(); i++) {
|
||||
long ratio = ratios.get(i);
|
||||
ParsedOp pop = pops.get(i);
|
||||
@ -493,11 +494,13 @@ public class SimpleActivity implements Activity, ProgressCapable {
|
||||
// }
|
||||
planner.addOp((OpDispenser<? extends O>) dispenser, ratio);
|
||||
}
|
||||
|
||||
return planner.resolve();
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new OpConfigError(e.getMessage(), workloadSource, e);
|
||||
}
|
||||
|
||||
return planner.resolve();
|
||||
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class BindPointParser implements BiFunction<String, Map<String, String>, BindPointParser.Result> {
|
||||
|
||||
public final static Pattern BINDPOINT_ANCHOR = Pattern.compile("(\\{((?<anchor>\\w+[-_\\d\\w.]*)})|(\\{\\{(?<extended>(?!}}).+?)}}))");
|
||||
public final static Pattern BINDPOINT_ANCHOR = Pattern.compile("(\\{((?<anchor>\\w+[-_<>,\\d\\w.]*)})|(\\{\\{(?<extended>(?!}}).+?)}}))");
|
||||
public final static String DEFINITION = "DEFINITION";
|
||||
|
||||
|
||||
|
@ -25,6 +25,16 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class BindPointParserTest {
|
||||
|
||||
@Test
|
||||
public void testSpecialCharsInRefBindPoint() {
|
||||
BindPointParser bpp = new BindPointParser();
|
||||
assertThat(bpp.apply("test {list<one>}", Map.of())).isEqualTo(
|
||||
new BindPointParser.Result(
|
||||
List.of("test ","list<one>",""),
|
||||
List.of(BindPoint.of("list<one>",null, BindPoint.Type.reference)))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleRefTypeBindPoint() {
|
||||
BindPointParser bpp = new BindPointParser();
|
||||
|
Loading…
Reference in New Issue
Block a user