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:
Jonathan Shook 2022-07-13 20:42:10 -05:00
parent 71fd51225c
commit 080d9005e0
17 changed files with 590 additions and 64 deletions

View File

@ -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);

View File

@ -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");
}
}

View File

@ -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() {
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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";

View File

@ -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();