diff --git a/nb-adapters/adapter-cqld4/pom.xml b/nb-adapters/adapter-cqld4/pom.xml
index cbd7011e8..124a9e244 100644
--- a/nb-adapters/adapter-cqld4/pom.xml
+++ b/nb-adapters/adapter-cqld4/pom.xml
@@ -93,7 +93,7 @@
org.bouncycastle
bcprov-jdk18on
- 1.77
+ 1.78
com.fasterxml.jackson.core
diff --git a/nb-adapters/adapter-cqld4/src/main/java/io/nosqlbench/cqlgen/grammars/CqlLexer.g4 b/nb-adapters/adapter-cqld4/src/main/java/io/nosqlbench/cqlgen/grammars/CqlLexer.g4
index 3704d355e..986367a38 100644
--- a/nb-adapters/adapter-cqld4/src/main/java/io/nosqlbench/cqlgen/grammars/CqlLexer.g4
+++ b/nb-adapters/adapter-cqld4/src/main/java/io/nosqlbench/cqlgen/grammars/CqlLexer.g4
@@ -6,26 +6,26 @@ options {
// Operators and Punctuators
-LR_BRACKET: '(';
+LR_BRACKET: '(' -> pushMode(IDENTIFIER_MODE);
RR_BRACKET: ')';
-LC_BRACKET: '{';
+LC_BRACKET: '{' -> pushMode(IDENTIFIER_MODE);
RC_BRACKET: '}';
-LS_BRACKET: '[';
+LS_BRACKET: '[' -> pushMode(IDENTIFIER_MODE);
RS_BRACKET: ']';
-COMMA: ',';
+COMMA: ',' -> pushMode(IDENTIFIER_MODE);
SEMI: ';';
COLON: ':';
-DOT: '.';
+DOT: '.' -> pushMode(IDENTIFIER_MODE);
STAR: '*';
DIVIDE: '/';
MODULE: '%';
-PLUS: '+';
+PLUS: '+' -> pushMode(IDENTIFIER_MODE);
MINUSMINUS: '--';
MINUS: '-';
DQUOTE: '"';
SQUOTE: '\'';
-OPERATOR_EQ: '=';
-OPERATOR_LT: '<';
+OPERATOR_EQ: '=' -> pushMode(IDENTIFIER_MODE);
+OPERATOR_LT: '<' -> pushMode(IDENTIFIER_MODE);
OPERATOR_GT: '>';
OPERATOR_LTE: '<=';
OPERATOR_GTE: '>=';
@@ -37,7 +37,7 @@ K_AGGREGATE: 'AGGREGATE';
K_ALL: 'ALL';
K_ALLOW: 'ALLOW';
K_ALTER: 'ALTER';
-K_AND: 'AND';
+K_AND: 'AND' -> pushMode(IDENTIFIER_MODE);
K_ANY: 'ANY';
K_APPLY: 'APPLY';
K_AS: 'AS';
@@ -63,7 +63,7 @@ K_DURABLE_WRITES: 'DURABLE_WRITES';
K_EACH_QUORUM: 'EACH_QUORUM';
K_ENTRIES: 'ENTRIES';
K_EXECUTE: 'EXECUTE';
-K_EXISTS: 'EXISTS';
+K_EXISTS: 'EXISTS' -> pushMode(IDENTIFIER_MODE);
K_FALSE: 'FALSE';
K_FILTERING: 'FILTERING';
K_FINALFUNC: 'FINALFUNC';
@@ -84,7 +84,7 @@ K_IS: 'IS';
K_JSON: 'JSON';
K_KEY: 'KEY';
K_KEYS: 'KEYS';
-K_KEYSPACE: 'KEYSPACE';
+K_KEYSPACE: 'KEYSPACE' -> pushMode(IDENTIFIER_MODE);
K_KEYSPACES: 'KEYSPACES';
K_LANGUAGE: 'LANGUAGE';
// Disabled because there was no definitive reference to this as a bare keyword in the specs
@@ -101,8 +101,8 @@ K_NORECURSIVE: 'NORECURSIVE';
K_NOSUPERUSER: 'NOSUPERUSER';
K_NOT: 'NOT';
K_NULL: 'NULL';
-K_OF: 'OF';
-K_ON: 'ON';
+K_OF: 'OF' -> pushMode(IDENTIFIER_MODE);
+K_ON: 'ON' -> pushMode(IDENTIFIER_MODE);
K_ONE: 'ONE';
K_OPTIONS: 'OPTIONS';
K_OR: 'OR';
@@ -114,7 +114,7 @@ K_PERMISSION: 'PERMISSION';
K_PERMISSIONS: 'PERMISSIONS';
K_PRIMARY: 'PRIMARY';
K_QUORUM: 'QUORUM';
-K_RENAME: 'RENAME';
+K_RENAME: 'RENAME' -> pushMode(IDENTIFIER_MODE);
K_REPLACE: 'REPLACE';
K_REPLICATION: 'REPLICATION';
K_RETURNS: 'RETURNS';
@@ -123,32 +123,34 @@ K_ROLE: 'ROLE';
K_ROLES: 'ROLES';
K_SCHEMA: 'SCHEMA';
K_SELECT: 'SELECT';
-K_SET: 'SET';
+K_SET_WITH_OPERATOR_LT: K_SET SPACE? OPERATOR_LT -> pushMode(IDENTIFIER_MODE);
+K_SET: 'SET' -> pushMode(IDENTIFIER_MODE);
K_SFUNC: 'SFUNC';
K_STATIC: 'STATIC';
K_STORAGE: 'STORAGE';
K_STYPE: 'STYPE';
K_SUPERUSER: 'SUPERUSER';
-K_TABLE: 'TABLE';
+K_TABLE: 'TABLE' -> pushMode(IDENTIFIER_MODE);
K_THREE: 'THREE';
+K_TIMESTAMP_WITH_DECIMAL_LITERAL: K_TIMESTAMP SPACE DECIMAL_LITERAL;
K_TIMESTAMP: 'TIMESTAMP';
-K_TO: 'TO';
+K_TO: 'TO' -> pushMode(IDENTIFIER_MODE);
K_TOKEN: 'TOKEN';
K_TRIGGER: 'TRIGGER';
K_TRUE: 'TRUE';
-K_TRUNCATE: 'TRUNCATE';
+K_TRUNCATE: 'TRUNCATE' -> pushMode(IDENTIFIER_MODE);
K_TTL: 'TTL';
K_TWO: 'TWO';
-K_TYPE: 'TYPE';
+K_TYPE: 'TYPE' -> pushMode(IDENTIFIER_MODE);
K_UNLOGGED: 'UNLOGGED';
-K_UPDATE: 'UPDATE';
-K_USE: 'USE';
+K_UPDATE: 'UPDATE' -> pushMode(IDENTIFIER_MODE);
+K_USE: 'USE' -> pushMode(IDENTIFIER_MODE);
K_USER: 'USER';
K_USING: 'USING';
K_UUID: 'UUID';
K_VALUES: 'VALUES';
K_VIEW: 'VIEW';
-K_WHERE: 'WHERE';
+K_WHERE: 'WHERE' -> pushMode(IDENTIFIER_MODE);
K_WITH: 'WITH';
K_WRITETIME: 'WRITETIME';
K_ASCII: 'ASCII';
@@ -160,10 +162,13 @@ K_DATE: 'DATE';
K_DECIMAL: 'DECIMAL';
K_DOUBLE: 'DOUBLE';
K_FLOAT: 'FLOAT';
+K_FROZEN_WITH_OPERATOR_LT: K_FROZEN SPACE? OPERATOR_LT -> pushMode(IDENTIFIER_MODE);
K_FROZEN: 'FROZEN';
K_INET: 'INET';
K_INT: 'INT';
+K_LIST_WITH_OPERATOR_LT: K_LIST SPACE? OPERATOR_LT -> pushMode(IDENTIFIER_MODE);
K_LIST: 'LIST';
+K_MAP_WITH_OPERATOR_LT: K_MAP SPACE? OPERATOR_LT -> pushMode(IDENTIFIER_MODE);
K_MAP: 'MAP';
K_SMALLINT: 'SMALLINT';
K_TEXT: 'TEXT';
@@ -221,5 +226,99 @@ fragment DEC_DIGIT: [0-9];
fragment EXPONENT_NUM_PART: 'E' ('-'|'+') ? DEC_DIGIT+;
+mode IDENTIFIER_MODE;
+SEMI_: SEMI -> type(SEMI), popMode;
+LC_BRACKET_: LC_BRACKET -> type(LC_BRACKET);
+LS_BRACKET_: LS_BRACKET -> type(LS_BRACKET);
+LR_BRACKET_: LR_BRACKET -> type(LR_BRACKET);
+OPERATOR_LT_: OPERATOR_LT -> type(OPERATOR_LT);
+
+RR_BRACKET_: RR_BRACKET -> type(RR_BRACKET), popMode;
+RC_BRACKET_: RC_BRACKET -> type(RC_BRACKET), popMode;
+RS_BRACKET_: RS_BRACKET -> type(RS_BRACKET), popMode;
+
+OPERATOR_GT_: OPERATOR_GT -> type(OPERATOR_GT), popMode;
+
+// Reserved Keywords which cannot be used as identifiers
+// https://cassandra.apache.org/doc/4.1/cassandra/cql/appendices.html#appendix-A
+K_ADD_: K_ADD -> type(K_ADD), popMode;
+K_AGGREGATE_: K_AGGREGATE -> type(K_AGGREGATE), popMode;
+K_ALLOW_: K_ALLOW -> type(K_ALLOW), popMode;
+K_ALTER_: K_ALTER -> type(K_ALTER), popMode;
+K_AND_: K_AND -> type(K_AND), popMode;
+K_ANY_: K_ANY -> type(K_ANY), popMode;
+K_APPLY_: K_APPLY -> type(K_APPLY), popMode;
+K_ASC_: K_ASC -> type(K_ASC), popMode;
+K_AUTHORIZE_: K_AUTHORIZE -> type(K_AUTHORIZE), popMode;
+K_BATCH_: K_BATCH -> type(K_BATCH), popMode;
+K_BEGIN_: K_BEGIN -> type(K_BEGIN), popMode;
+K_BY_: K_BY -> type(K_BY), popMode;
+K_COLUMNFAMILY_: K_COLUMNFAMILY -> type(K_COLUMNFAMILY), popMode;
+K_CREATE_: K_CREATE -> type(K_CREATE), popMode;
+K_DELETE_: K_DELETE -> type(K_DELETE), popMode;
+K_DESC_: K_DESC -> type(K_DESC), popMode;
+K_DROP_: K_DROP -> type(K_DROP), popMode;
+K_DURABLE_WRITES_: K_DURABLE_WRITES -> type(K_DURABLE_WRITES), popMode;
+K_ENTRIES_: K_ENTRIES -> type(K_ENTRIES), popMode;
+K_FALSE_: K_FALSE -> type(K_FALSE), popMode;
+K_FROM_: K_FROM -> type(K_FROM), popMode;
+K_FULL_: K_FULL -> type(K_FULL), popMode;
+K_GRANT_: K_GRANT -> type(K_GRANT), popMode;
+K_IF_: K_IF -> type(K_IF), popMode;
+K_IN_: K_IN -> type(K_IN), popMode;
+K_INDEX_: K_INDEX -> type(K_INDEX), popMode;
+K_INFINITY_: K_INFINITY -> type(K_INFINITY), popMode;
+K_INSERT_: K_INSERT -> type(K_INSERT), popMode;
+K_INTO_: K_INTO -> type(K_INTO), popMode;
+//K_IS: 'IS';
+K_KEYSPACE_: K_KEYSPACE -> type(K_KEYSPACE), popMode;
+K_LIMIT_: K_LIMIT -> type(K_LIMIT), popMode;
+K_LOGGED_: K_LOGGED -> type(K_LOGGED), popMode;
+K_MODIFY_: K_MODIFY -> type(K_MODIFY), popMode;
+K_NAN_: K_NAN -> type(K_NAN), popMode;
+K_NORECURSIVE_: K_NORECURSIVE -> type(K_NORECURSIVE), popMode;
+K_NOT_: K_NOT -> type(K_NOT), popMode;
+K_NULL_: K_NULL -> type(K_NULL), popMode;
+K_OF_: K_OF -> type(K_OF), popMode;
+K_ON_: K_ON -> type(K_ON), popMode;
+K_OR_: K_OR -> type(K_OR), popMode;
+K_ORDER_: K_ORDER -> type(K_ORDER), popMode;
+K_PRIMARY_: K_PRIMARY -> type(K_PRIMARY), popMode;
+K_RENAME_: K_RENAME -> type(K_RENAME), popMode;
+K_REPLACE_: K_REPLACE -> type(K_REPLACE), popMode;
+K_REVOKE_: K_REVOKE -> type(K_REVOKE), popMode;
+K_SCHEMA_: K_SCHEMA -> type(K_SCHEMA), popMode;
+K_SELECT_: K_SELECT -> type(K_SELECT), popMode;
+K_SET_: K_SET -> type(K_SET), popMode;
+K_TABLE_: K_TABLE -> type(K_TABLE), popMode;
+K_TO_: K_TO -> type(K_TO), popMode;
+K_TOKEN_: K_TOKEN -> type(K_TOKEN), popMode;
+K_TRUNCATE_: K_TRUNCATE -> type(K_TRUNCATE), popMode;
+K_UNLOGGED_: K_UNLOGGED -> type(K_UNLOGGED), popMode;
+K_UPDATE_: K_UPDATE -> type(K_UPDATE), popMode;
+K_USE_: K_USE -> type(K_USE), popMode;
+K_USING_: K_USING -> type(K_USING), popMode;
+K_WHERE_: K_WHERE -> type(K_WHERE), popMode;
+K_WITH_: K_WITH -> type(K_WITH), popMode;
+
+// handeling cases like 'frozen<','map<','list<','set<' and 'TIMESTAMP WITH 1234'
+K_MAP_WITH_OPERATOR_LT_: K_MAP_WITH_OPERATOR_LT -> type(K_MAP_WITH_OPERATOR_LT);
+K_TIMESTAMP_WITH_DECIMAL_LITERAL_: K_TIMESTAMP_WITH_DECIMAL_LITERAL -> type(K_TIMESTAMP_WITH_DECIMAL_LITERAL);
+K_FROZEN_WITH_OPERATOR_LT_: K_FROZEN_WITH_OPERATOR_LT -> type(K_FROZEN_WITH_OPERATOR_LT);
+K_SET_WITH_OPERATOR_LT_: K_SET_WITH_OPERATOR_LT -> type(K_SET_WITH_OPERATOR_LT);
+K_LIST_WITH_OPERATOR_LT_: K_LIST_WITH_OPERATOR_LT -> type(K_LIST_WITH_OPERATOR_LT);
+
+OBJECT_NAME_ : OBJECT_NAME -> type(OBJECT_NAME), popMode;
+SPACE_: [ \t\r\n]+ -> channel (HIDDEN);
+
+UUID_: UUID -> type(UUID), popMode;
+
+// Literals
+CODE_BLOCK_: CODE_BLOCK -> type(CODE_BLOCK), popMode;
+STRING_LITERAL_: STRING_LITERAL -> type(STRING_LITERAL), popMode;
+DECIMAL_LITERAL_: DECIMAL_LITERAL -> type(DECIMAL_LITERAL), popMode;
+FLOAT_LITERAL_: FLOAT_LITERAL -> type(FLOAT_LITERAL), popMode;
+HEXADECIMAL_LITERAL_: HEXADECIMAL_LITERAL -> type(HEXADECIMAL_LITERAL), popMode;
+REAL_LITERAL_ : REAL_LITERAL -> type(REAL_LITERAL), popMode;
diff --git a/nb-adapters/adapter-cqld4/src/main/java/io/nosqlbench/cqlgen/grammars/CqlParser.g4 b/nb-adapters/adapter-cqld4/src/main/java/io/nosqlbench/cqlgen/grammars/CqlParser.g4
index 1a998eeec..e4b3ab6e5 100644
--- a/nb-adapters/adapter-cqld4/src/main/java/io/nosqlbench/cqlgen/grammars/CqlParser.g4
+++ b/nb-adapters/adapter-cqld4/src/main/java/io/nosqlbench/cqlgen/grammars/CqlParser.g4
@@ -136,7 +136,7 @@ createType
;
typeMemberColumnList
- : column dataType (syntaxComma column dataType)*
+ : column dataType (syntaxComma column dataType)* syntaxComma?
;
createTrigger
@@ -244,8 +244,8 @@ alterType
;
alterTypeOperation
- : alterTypeAlterType
- | alterTypeAdd
+// : alterTypeAlterType
+ : alterTypeAdd
| alterTypeRename
;
@@ -262,7 +262,7 @@ alterTypeRenameItem
;
alterTypeAdd
- : kwAdd column dataType (syntaxComma column dataType)*
+ : kwAdd column dataType
;
alterTypeAlterType
@@ -615,7 +615,7 @@ usingTtlTimestamp
;
timestamp
- : kwTimestamp decimalLiteral
+ : K_TIMESTAMP_WITH_DECIMAL_LITERAL
;
ttl
@@ -767,6 +767,7 @@ stringLiteral
booleanLiteral
: K_TRUE
| K_FALSE
+ | OBJECT_NAME
;
hexadecimalLiteral
@@ -790,10 +791,10 @@ column
dataType
: dataTypeName
- | K_FROZEN syntaxBracketLa dataType syntaxBracketRa
- | K_SET syntaxBracketLa dataType syntaxBracketRa
- | K_LIST syntaxBracketLa dataType syntaxBracketRa
- | K_MAP syntaxBracketLa dataType syntaxComma dataType syntaxBracketRa
+ | K_FROZEN_WITH_OPERATOR_LT dataType syntaxBracketRa
+ | K_SET_WITH_OPERATOR_LT dataType syntaxBracketRa
+ | K_LIST_WITH_OPERATOR_LT dataType syntaxBracketRa
+ | K_MAP_WITH_OPERATOR_LT dataType syntaxComma dataType syntaxBracketRa
;
dataTypeName
@@ -901,6 +902,7 @@ kwAggregate
kwAll
: K_ALL
+ | OBJECT_NAME
;
kwAllPermissions
@@ -1101,6 +1103,7 @@ kwLogged
kwLogin
: K_LOGIN
+ | OBJECT_NAME
;
kwMaterialized
@@ -1137,6 +1140,7 @@ kwOn
kwOptions
: K_OPTIONS
+ | OBJECT_NAME
;
kwOr
@@ -1149,6 +1153,7 @@ kwOrder
kwPassword
: K_PASSWORD
+ | OBJECT_NAME
;
kwPrimary
@@ -1201,6 +1206,7 @@ kwStype
kwSuperuser
: K_SUPERUSER
+ | OBJECT_NAME
;
kwTable
diff --git a/nb-adapters/adapter-cqld4/src/test/java/io/nosqlbench/converters/cql/cql/parser/CqlParserHarnessTest.java b/nb-adapters/adapter-cqld4/src/test/java/io/nosqlbench/converters/cql/cql/parser/CqlParserHarnessTest.java
index b630a170b..f76c2557e 100644
--- a/nb-adapters/adapter-cqld4/src/test/java/io/nosqlbench/converters/cql/cql/parser/CqlParserHarnessTest.java
+++ b/nb-adapters/adapter-cqld4/src/test/java/io/nosqlbench/converters/cql/cql/parser/CqlParserHarnessTest.java
@@ -21,6 +21,12 @@ import io.nosqlbench.cqlgen.parser.CqlModelParser;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+
public class CqlParserHarnessTest {
private final static String ksddl = """
@@ -81,5 +87,22 @@ public class CqlParserHarnessTest {
""", null);
}
+ @Test
+ @Disabled
+ public void testCqlExamples() throws IOException {
+ File folderPath = new File("src/test/resources/cql3_examples");
+ for (final File file : Objects.requireNonNull(folderPath.listFiles())) {
+ String query = Files.readString(Path.of(file.getPath()));
+ CqlModelParser.parse(query, null);
+ }
+ }
+ @Disabled
+ @Test
+ public void testUdt() {
+ CGWorkloadExporter exporter = new CGWorkloadExporter();
+ exporter.applyAsInt(new String[] {"src/test/resources/testschemas/cql_udt.cql", "cql_udt.yaml"});
+ exporter.setNamingTemplate("[OPTYPE-][COLUMN-][TYPEDEF-][TABLE-]-[KEYSPACE]");
+ exporter.getWorkloadAsYaml();
+ }
}
diff --git a/nb-adapters/adapter-cqld4/src/test/resources/testschemas/cql_udt.cql b/nb-adapters/adapter-cqld4/src/test/resources/testschemas/cql_udt.cql
new file mode 100644
index 000000000..9e1898b2b
--- /dev/null
+++ b/nb-adapters/adapter-cqld4/src/test/resources/testschemas/cql_udt.cql
@@ -0,0 +1,27 @@
+CREATE KEYSPACE baselines
+ WITH REPLICATION = {
+ 'class' : 'SimpleStrategy',
+ 'replication_factor' : 1
+ };
+
+CREATE TYPE baselines.phone (
+ country_code int,
+ number text,
+);
+
+CREATE TYPE baselines.address (
+ street text,
+ city text,
+ zip text,
+ phones map
+);
+
+CREATE TABLE baselines.user (
+ name text PRIMARY KEY,
+ addresses map>
+);
+
+ALTER TYPE baselines.address RENAME zip TO zipcode AND city to city_code;
+ALTER TYPE baselines.address ADD country text;
+
+DROP TYPE IF EXISTS baselines.address;
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/Neo4JOpMapper.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/Neo4JOpMapper.java
index 918d52f4d..1f0691b61 100644
--- a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/Neo4JOpMapper.java
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/Neo4JOpMapper.java
@@ -43,13 +43,22 @@ public class Neo4JOpMapper implements OpMapper {
LongFunction spaceNameFunc = op.getAsFunctionOr("space", "default");
LongFunction spaceFunc = l -> cache.get(spaceNameFunc.apply(l));
return switch (typeAndTarget.enumId) {
- case autocommit -> new Neo4JAutoCommitOpDispenser(
+ case sync_autocommit -> new Neo4JSyncAutoCommitOpDispenser(
adapter, op, spaceFunc, typeAndTarget.enumId.getValue()
);
- case read_transaction -> new Neo4JReadTxnOpDispenser(
+ case async_autocommit -> new Neo4JAsyncAutoCommitOpDispenser(
adapter, op, spaceFunc, typeAndTarget.enumId.getValue()
);
- case write_transaction -> new Neo4JWriteTxnOpDispenser(
+ case sync_read_transaction -> new Neo4JSyncReadTxnOpDispenser(
+ adapter, op, spaceFunc, typeAndTarget.enumId.getValue()
+ );
+ case async_read_transaction -> new Neo4JAsyncReadTxnOpDispenser(
+ adapter, op, spaceFunc, typeAndTarget.enumId.getValue()
+ );
+ case sync_write_transaction -> new Neo4JSyncWriteTxnOpDispenser(
+ adapter, op, spaceFunc, typeAndTarget.enumId.getValue()
+ );
+ case async_write_transaction -> new Neo4JAsyncWriteTxnOpDispenser(
adapter, op, spaceFunc, typeAndTarget.enumId.getValue()
);
};
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JWriteTxnOpDispenser.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAsyncAutoCommitOpDispenser.java
similarity index 72%
rename from nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JWriteTxnOpDispenser.java
rename to nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAsyncAutoCommitOpDispenser.java
index cfb5d5aea..4d1079be7 100644
--- a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JWriteTxnOpDispenser.java
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAsyncAutoCommitOpDispenser.java
@@ -17,24 +17,24 @@
package io.nosqlbench.adapter.neo4j.opdispensers;
import io.nosqlbench.adapter.neo4j.Neo4JDriverAdapter;
+import io.nosqlbench.adapter.neo4j.ops.Neo4JAsyncAutoCommitOp;
import io.nosqlbench.adapter.neo4j.Neo4JSpace;
-import io.nosqlbench.adapter.neo4j.ops.Neo4JWriteTxnOp;
-import io.nosqlbench.adapter.neo4j.types.Neo4JOpType;
import io.nosqlbench.adapters.api.templating.ParsedOp;
+
import org.neo4j.driver.async.AsyncSession;
import java.util.function.LongFunction;
-public class Neo4JWriteTxnOpDispenser extends Neo4JBaseOpDispenser {
+public class Neo4JAsyncAutoCommitOpDispenser extends Neo4JBaseOpDispenser {
- public Neo4JWriteTxnOpDispenser(Neo4JDriverAdapter adapter, ParsedOp op, LongFunction spaceFunc, String requiredTemplateKey) {
+ public Neo4JAsyncAutoCommitOpDispenser(Neo4JDriverAdapter adapter, ParsedOp op, LongFunction spaceFunc, String requiredTemplateKey) {
super(adapter, op, spaceFunc, requiredTemplateKey);
}
@Override
- public LongFunction createOpFunc() {
- return l -> new Neo4JWriteTxnOp(
+ public LongFunction createOpFunc() {
+ return l -> new Neo4JAsyncAutoCommitOp(
spaceFunc.apply(l).getDriver().session(AsyncSession.class),
queryFunc.apply(l)
);
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAutoCommitOpDispenser.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAsyncReadTxnOpDispenser.java
similarity index 73%
rename from nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAutoCommitOpDispenser.java
rename to nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAsyncReadTxnOpDispenser.java
index f3899245e..a8eb63036 100644
--- a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAutoCommitOpDispenser.java
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAsyncReadTxnOpDispenser.java
@@ -17,8 +17,8 @@
package io.nosqlbench.adapter.neo4j.opdispensers;
import io.nosqlbench.adapter.neo4j.Neo4JDriverAdapter;
-import io.nosqlbench.adapter.neo4j.ops.Neo4JAutoCommitOp;
import io.nosqlbench.adapter.neo4j.Neo4JSpace;
+import io.nosqlbench.adapter.neo4j.ops.Neo4JAsyncReadTxnOp;
import io.nosqlbench.adapters.api.templating.ParsedOp;
import org.neo4j.driver.async.AsyncSession;
@@ -26,15 +26,14 @@ import org.neo4j.driver.async.AsyncSession;
import java.util.function.LongFunction;
-public class Neo4JAutoCommitOpDispenser extends Neo4JBaseOpDispenser {
-
- public Neo4JAutoCommitOpDispenser(Neo4JDriverAdapter adapter, ParsedOp op, LongFunction spaceFunc, String requiredTemplateKey) {
+public class Neo4JAsyncReadTxnOpDispenser extends Neo4JBaseOpDispenser {
+ public Neo4JAsyncReadTxnOpDispenser(Neo4JDriverAdapter adapter, ParsedOp op, LongFunction spaceFunc, String requiredTemplateKey) {
super(adapter, op, spaceFunc, requiredTemplateKey);
}
@Override
- public LongFunction createOpFunc() {
- return l -> new Neo4JAutoCommitOp(
+ public LongFunction createOpFunc() {
+ return l -> new Neo4JAsyncReadTxnOp(
spaceFunc.apply(l).getDriver().session(AsyncSession.class),
queryFunc.apply(l)
);
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JReadTxnOpDispenser.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAsyncWriteTxnOpDispenser.java
similarity index 73%
rename from nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JReadTxnOpDispenser.java
rename to nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAsyncWriteTxnOpDispenser.java
index 770d148cf..5bc5dc5da 100644
--- a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JReadTxnOpDispenser.java
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JAsyncWriteTxnOpDispenser.java
@@ -18,21 +18,23 @@ package io.nosqlbench.adapter.neo4j.opdispensers;
import io.nosqlbench.adapter.neo4j.Neo4JDriverAdapter;
import io.nosqlbench.adapter.neo4j.Neo4JSpace;
-import io.nosqlbench.adapter.neo4j.ops.Neo4JReadTxnOp;
+import io.nosqlbench.adapter.neo4j.ops.Neo4JAsyncWriteTxnOp;
import io.nosqlbench.adapters.api.templating.ParsedOp;
+
import org.neo4j.driver.async.AsyncSession;
import java.util.function.LongFunction;
-public class Neo4JReadTxnOpDispenser extends Neo4JBaseOpDispenser {
- public Neo4JReadTxnOpDispenser(Neo4JDriverAdapter adapter, ParsedOp op, LongFunction spaceFunc, String requiredTemplateKey) {
+public class Neo4JAsyncWriteTxnOpDispenser extends Neo4JBaseOpDispenser {
+
+ public Neo4JAsyncWriteTxnOpDispenser(Neo4JDriverAdapter adapter, ParsedOp op, LongFunction spaceFunc, String requiredTemplateKey) {
super(adapter, op, spaceFunc, requiredTemplateKey);
}
@Override
- public LongFunction createOpFunc() {
- return l -> new Neo4JReadTxnOp(
+ public LongFunction createOpFunc() {
+ return l -> new Neo4JAsyncWriteTxnOp(
spaceFunc.apply(l).getDriver().session(AsyncSession.class),
queryFunc.apply(l)
);
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JSyncAutoCommitOpDispenser.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JSyncAutoCommitOpDispenser.java
new file mode 100644
index 000000000..bd08aa88d
--- /dev/null
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JSyncAutoCommitOpDispenser.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 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.adapter.neo4j.opdispensers;
+
+import io.nosqlbench.adapter.neo4j.Neo4JDriverAdapter;
+import io.nosqlbench.adapter.neo4j.ops.Neo4JSyncAutoCommitOp;
+import io.nosqlbench.adapter.neo4j.Neo4JSpace;
+import io.nosqlbench.adapters.api.templating.ParsedOp;
+
+import org.neo4j.driver.Session;
+
+import java.util.function.LongFunction;
+
+
+public class Neo4JSyncAutoCommitOpDispenser extends Neo4JBaseOpDispenser {
+
+ public Neo4JSyncAutoCommitOpDispenser(Neo4JDriverAdapter adapter, ParsedOp op, LongFunction spaceFunc, String requiredTemplateKey) {
+ super(adapter, op, spaceFunc, requiredTemplateKey);
+ }
+
+ @Override
+ public LongFunction createOpFunc() {
+ return l -> new Neo4JSyncAutoCommitOp(
+ spaceFunc.apply(l).getDriver().session(Session.class),
+ queryFunc.apply(l)
+ );
+ }
+}
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JSyncReadTxnOpDispenser.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JSyncReadTxnOpDispenser.java
new file mode 100644
index 000000000..b1b170566
--- /dev/null
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JSyncReadTxnOpDispenser.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 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.adapter.neo4j.opdispensers;
+
+import io.nosqlbench.adapter.neo4j.Neo4JDriverAdapter;
+import io.nosqlbench.adapter.neo4j.ops.Neo4JSyncReadTxnOp;
+import io.nosqlbench.adapter.neo4j.Neo4JSpace;
+import io.nosqlbench.adapters.api.templating.ParsedOp;
+
+import org.neo4j.driver.Session;
+
+import java.util.function.LongFunction;
+
+
+public class Neo4JSyncReadTxnOpDispenser extends Neo4JBaseOpDispenser {
+
+ public Neo4JSyncReadTxnOpDispenser(Neo4JDriverAdapter adapter, ParsedOp op, LongFunction spaceFunc, String requiredTemplateKey) {
+ super(adapter, op, spaceFunc, requiredTemplateKey);
+ }
+
+ @Override
+ public LongFunction createOpFunc() {
+ return l -> new Neo4JSyncReadTxnOp(
+ spaceFunc.apply(l).getDriver().session(Session.class),
+ queryFunc.apply(l)
+ );
+ }
+}
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JSyncWriteTxnOpDispenser.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JSyncWriteTxnOpDispenser.java
new file mode 100644
index 000000000..7c7d095aa
--- /dev/null
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/opdispensers/Neo4JSyncWriteTxnOpDispenser.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 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.adapter.neo4j.opdispensers;
+
+import io.nosqlbench.adapter.neo4j.Neo4JDriverAdapter;
+import io.nosqlbench.adapter.neo4j.ops.Neo4JSyncWriteTxnOp;
+import io.nosqlbench.adapter.neo4j.Neo4JSpace;
+import io.nosqlbench.adapters.api.templating.ParsedOp;
+
+import org.neo4j.driver.Session;
+
+import java.util.function.LongFunction;
+
+
+public class Neo4JSyncWriteTxnOpDispenser extends Neo4JBaseOpDispenser {
+
+ public Neo4JSyncWriteTxnOpDispenser(Neo4JDriverAdapter adapter, ParsedOp op, LongFunction spaceFunc, String requiredTemplateKey) {
+ super(adapter, op, spaceFunc, requiredTemplateKey);
+ }
+
+ @Override
+ public LongFunction createOpFunc() {
+ return l -> new Neo4JSyncWriteTxnOp(
+ spaceFunc.apply(l).getDriver().session(Session.class),
+ queryFunc.apply(l)
+ );
+ }
+}
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAutoCommitOp.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAsyncAutoCommitOp.java
similarity index 90%
rename from nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAutoCommitOp.java
rename to nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAsyncAutoCommitOp.java
index 7505553af..b1fd89869 100644
--- a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAutoCommitOp.java
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAsyncAutoCommitOp.java
@@ -26,10 +26,12 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-public class Neo4JAutoCommitOp extends Neo4JBaseOp {
+public class Neo4JAsyncAutoCommitOp extends Neo4JBaseOp {
+ private final AsyncSession session;
- public Neo4JAutoCommitOp(AsyncSession session, Query query) {
- super(session, query);
+ public Neo4JAsyncAutoCommitOp(AsyncSession session, Query query) {
+ super(query);
+ this.session = session;
}
/**
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JReadTxnOp.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAsyncReadTxnOp.java
similarity index 91%
rename from nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JReadTxnOp.java
rename to nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAsyncReadTxnOp.java
index 861e1d33d..26f2deb93 100644
--- a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JReadTxnOp.java
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAsyncReadTxnOp.java
@@ -26,10 +26,12 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-public class Neo4JReadTxnOp extends Neo4JBaseOp{
+public class Neo4JAsyncReadTxnOp extends Neo4JBaseOp{
+ private final AsyncSession session;
- public Neo4JReadTxnOp(AsyncSession session, Query query) {
- super(session, query);
+ public Neo4JAsyncReadTxnOp(AsyncSession session, Query query) {
+ super(query);
+ this.session = session;
}
/**
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JWriteTxnOp.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAsyncWriteTxnOp.java
similarity index 91%
rename from nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JWriteTxnOp.java
rename to nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAsyncWriteTxnOp.java
index 1fec09fd6..aca7fa68b 100644
--- a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JWriteTxnOp.java
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JAsyncWriteTxnOp.java
@@ -26,10 +26,12 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-public class Neo4JWriteTxnOp extends Neo4JBaseOp{
+public class Neo4JAsyncWriteTxnOp extends Neo4JBaseOp{
+ private final AsyncSession session;
- public Neo4JWriteTxnOp(AsyncSession session, Query query) {
- super(session, query);
+ public Neo4JAsyncWriteTxnOp(AsyncSession session, Query query) {
+ super(query);
+ this.session = session;
}
/**
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JBaseOp.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JBaseOp.java
index 261b5cf19..aaced604e 100644
--- a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JBaseOp.java
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JBaseOp.java
@@ -24,20 +24,17 @@ import org.neo4j.driver.async.AsyncSession;
public abstract class Neo4JBaseOp implements CycleOp {
-
- protected final AsyncSession session;
protected final Query query;
- public Neo4JBaseOp(AsyncSession session, Query query) {
- this.session = session;
+ public Neo4JBaseOp(Query query) {
this.query = query;
}
/**
* In the child classes, this method will be responsible for:
- * - using the Neo4J AsyncSession object to run the Neo4J Query
+ * - using the Neo4J Session/AsyncSession object to run the Neo4J Query
* - process the Result to get an array of Records
- * - close the AsyncSession
+ * - close the Session/AsyncSession
* - Return the array of Records
*
* Session creation and closing is considered light-weight. Reference:
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JSyncAutoCommitOp.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JSyncAutoCommitOp.java
new file mode 100644
index 000000000..9b1fa5f31
--- /dev/null
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JSyncAutoCommitOp.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 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.adapter.neo4j.ops;
+
+import org.neo4j.driver.Query;
+import org.neo4j.driver.Record;
+import org.neo4j.driver.Session;
+
+import java.util.List;
+
+
+public class Neo4JSyncAutoCommitOp extends Neo4JBaseOp {
+ private final Session session;
+
+ public Neo4JSyncAutoCommitOp(Session session, Query query) {
+ super(query);
+ this.session = session;
+ }
+
+ @Override
+ public final Record[] apply(long value) {
+ List recordList = session.run(query).list();
+ if (session.isOpen()) {
+ session.close();
+ }
+ return recordList.toArray(new Record[recordList.size()]);
+ }
+}
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JSyncReadTxnOp.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JSyncReadTxnOp.java
new file mode 100644
index 000000000..9d6876633
--- /dev/null
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JSyncReadTxnOp.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024 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.adapter.neo4j.ops;
+
+import org.neo4j.driver.Query;
+import org.neo4j.driver.Record;
+import org.neo4j.driver.Session;
+
+import java.util.List;
+
+
+public class Neo4JSyncReadTxnOp extends Neo4JBaseOp{
+ private final Session session;
+
+ public Neo4JSyncReadTxnOp(Session session, Query query) {
+ super(query);
+ this.session = session;
+ }
+
+ @Override
+ public final Record[] apply(long value) {
+ List recordList = session.executeRead(
+ txn -> {
+ var result = txn.run(query);
+ return result.list();
+ }
+ );
+ if (session.isOpen()) {
+ session.close();
+ }
+ return recordList.toArray(new Record[recordList.size()]);
+ }
+}
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JSyncWriteTxnOp.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JSyncWriteTxnOp.java
new file mode 100644
index 000000000..746fee0fc
--- /dev/null
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/ops/Neo4JSyncWriteTxnOp.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024 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.adapter.neo4j.ops;
+
+import org.neo4j.driver.Query;
+import org.neo4j.driver.Record;
+import org.neo4j.driver.Session;
+
+import java.util.List;
+
+public class Neo4JSyncWriteTxnOp extends Neo4JBaseOp{
+ private final Session session;
+
+ public Neo4JSyncWriteTxnOp(Session session, Query query) {
+ super(query);
+ this.session = session;
+ }
+
+
+ @Override
+ public final Record[] apply(long value) {
+ List recordList = session.executeWrite(
+ txn -> {
+ var result = txn.run(query);
+ return result.list();
+ }
+ );
+ if (session.isOpen()) {
+ session.close();
+ }
+ return recordList.toArray(new Record[recordList.size()]);
+ }
+}
diff --git a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/types/Neo4JOpType.java b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/types/Neo4JOpType.java
index 8c5040ade..6f356deff 100644
--- a/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/types/Neo4JOpType.java
+++ b/nb-adapters/adapter-neo4j/src/main/java/io/nosqlbench/adapter/neo4j/types/Neo4JOpType.java
@@ -18,11 +18,17 @@ package io.nosqlbench.adapter.neo4j.types;
public enum Neo4JOpType {
- autocommit("autocommit"),
+ sync_autocommit("sync_autocommit"),
- read_transaction("read_transaction"),
+ async_autocommit("async_autocommit"),
- write_transaction("write_transaction");
+ sync_read_transaction("sync_read_transaction"),
+
+ async_read_transaction("async_read_transaction"),
+
+ sync_write_transaction("sync_write_transaction"),
+
+ async_write_transaction("async_write_transaction");
private final String value;
diff --git a/nb-adapters/adapter-neo4j/src/main/resources/activities/neo4j.yaml b/nb-adapters/adapter-neo4j/src/main/resources/activities/neo4j.yaml
index 825d8c05b..ee44a4a5e 100644
--- a/nb-adapters/adapter-neo4j/src/main/resources/activities/neo4j.yaml
+++ b/nb-adapters/adapter-neo4j/src/main/resources/activities/neo4j.yaml
@@ -24,7 +24,7 @@ blocks:
ops:
# Reference: https://support.neo4j.com/s/article/360059882854-Deleting-large-numbers-of-nodes#h_01H95CXNJ8TN4126T3Y01BRWKS
delete_nodes:
- autocommit: |
+ sync_autocommit: |
MATCH (n)
CALL { WITH n
DETACH DELETE n
@@ -32,14 +32,14 @@ blocks:
query_params:
delete_batch_size: TEMPLATE(delete_batch_size,5000)
drop_index:
- autocommit: DROP INDEX $index_name IF EXISTS
+ sync_autocommit: DROP INDEX $index_name IF EXISTS
query_params:
index_name: vector_index
schema:
ops:
create_vector_index:
- autocommit: |
+ sync_autocommit: |
CREATE VECTOR INDEX $index_name IF NOT EXISTS FOR (n:TEMPLATE(node_label,Node))
ON (n.embedding) OPTIONS
{indexConfig: {`vector.dimensions`: $dimension, `vector.similarity_function`: $similarity_function}}
@@ -51,7 +51,7 @@ blocks:
rampup:
ops:
insert_node:
- write_transaction: |
+ async_write_transaction: |
CREATE (v:TEMPLATE(node_label,Node) {id: $id, embedding: $vector})
query_params:
id: '{id}'
@@ -61,7 +61,7 @@ blocks:
ops:
# Reference: https://community.neo4j.com/t/unwind-multiple-arrays-to-set-property/59908/5
insert_nodes:
- write_transaction: |
+ async_write_transaction: |
WITH $id_list as ids, $vector_list as vectors
UNWIND RANGE(0, size(ids) - 1) as idx
CREATE (v:TEMPLATE(node_label,Node) {id: ids[idx], embedding: vectors[idx]})
@@ -72,7 +72,7 @@ blocks:
search:
ops:
search:
- read_transaction: |
+ async_read_transaction: |
WITH $query_vector AS queryVector
CALL db.index.vector.queryNodes($index_name, $k, queryVector)
YIELD node
diff --git a/nb-adapters/adapter-neo4j/src/main/resources/neo4j.md b/nb-adapters/adapter-neo4j/src/main/resources/neo4j.md
index 0a49784a5..e986529d0 100644
--- a/nb-adapters/adapter-neo4j/src/main/resources/neo4j.md
+++ b/nb-adapters/adapter-neo4j/src/main/resources/neo4j.md
@@ -13,10 +13,13 @@ instance of the Neo4J/Aura database:
## Op Templates
-The Neo4J adapter supports three different op types:
-- autocommit
-- read_transaction
-- write_transaction
+The Neo4J adapter supports six different op types:
+- sync_autocommit
+- async_autocommit
+- sync_read_transaction
+- async_read_transaction
+- sync_write_transaction
+- async_write_transaction
A good reference for when to use each is located at https://neo4j.com/docs/driver-manual/1.7/sessions-transactions/
@@ -32,7 +35,7 @@ vector search functionality has been properly worked through, currently.
```yaml
ops:
example_create_vector_index:
- autocommit: |
+ sync_autocommit: |
CREATE VECTOR INDEX $index_name IF NOT EXISTS FOR (n:TEMPLATE(node_label,Node))
ON (n.embedding) OPTIONS
{indexConfig: {`vector.dimensions`: $dimension, `vector.similarity_function`: $similarity_function}}
@@ -42,14 +45,14 @@ ops:
similarity_function: TEMPLATE(similarity_function,cosine)
example_insert_node:
- write_transaction: |
+ async_write_transaction: |
CREATE (v:TEMPLATE(node_label,Node) {id: $id, embedding: $vector})
query_params:
id: '{id}'
vector: '{train_vector}'
example_search:
- read_transaction: |
+ async_read_transaction: |
WITH $query_vector AS queryVector
CALL db.index.vector.queryNodes($index_name, $k, queryVector)
YIELD node
diff --git a/nb-adapters/adapter-s4j/pom.xml b/nb-adapters/adapter-s4j/pom.xml
index b3fec0325..3c154f816 100644
--- a/nb-adapters/adapter-s4j/pom.xml
+++ b/nb-adapters/adapter-s4j/pom.xml
@@ -37,7 +37,7 @@
- 4.0.1
+ 4.1.2-alpha
diff --git a/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/S4JSpace.java b/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/S4JSpace.java
index 181bdf5c8..d9153ea01 100644
--- a/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/S4JSpace.java
+++ b/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/S4JSpace.java
@@ -99,8 +99,9 @@ public class S4JSpace implements AutoCloseable {
// Keep track the transaction count per thread
private final ThreadLocal txnBatchTrackingCnt = ThreadLocal.withInitial(() -> 0);
- // Represents the JMS connection
- private PulsarConnectionFactory s4jConnFactory;
+ // Instead of using one "physical" connection per NB process,
+ // allows creating multiple connections to the Pulsar broker via the "num_conn" parameter
+ private final ConcurrentHashMap connFactories = new ConcurrentHashMap<>();
private long totalCycleNum;
@@ -125,6 +126,7 @@ public class S4JSpace implements AutoCloseable {
this.sessionMode = S4JAdapterUtil.getSessionModeFromStr(
cfg.getOptional("session_mode").orElse(""));
this.s4JClientConf = new S4JClientConf(webSvcUrl, pulsarSvcUrl, s4jClientConfFileName);
+ logger.info("{}", s4JClientConf.toString());
this.setS4JActivityStartTimeMills(System.currentTimeMillis());
@@ -217,45 +219,41 @@ public class S4JSpace implements AutoCloseable {
public long incTotalNullMsgRecvdCnt() { return nullMsgRecvCnt.incrementAndGet(); }
- public PulsarConnectionFactory getS4jConnFactory() { return s4jConnFactory; }
-
public long getTotalCycleNum() { return totalCycleNum; }
public void setTotalCycleNum(long cycleNum) { totalCycleNum = cycleNum; }
public void initializeSpace(S4JClientConf s4JClientConnInfo) {
- if (s4jConnFactory == null) {
- Map cfgMap;
- try {
- cfgMap = s4JClientConnInfo.getS4jConfObjMap();
- s4jConnFactory = new PulsarConnectionFactory(cfgMap);
+ Map cfgMap;
+ try {
+ cfgMap = s4JClientConnInfo.getS4jConfObjMap();
- for (int i=0; i {
- if (logger.isDebugEnabled()) {
- logger.error("onException::Unexpected JMS error happened:" + e);
- }
- });
+ // Establish a JMS connection
+ PulsarConnectionFactory s4jConnFactory = connFactories.computeIfAbsent(
+ connLvlJmsConnContextIdStr,
+ __ -> new PulsarConnectionFactory(cfgMap));
- connLvlJmsContexts.put(connLvlJmsConnContextIdStr, jmsConnContext);
+ JMSContext jmsConnContext = getOrCreateConnLvlJMSContext(s4jConnFactory, s4JClientConnInfo, sessionMode);
+ jmsConnContext.setClientID(connLvlJmsConnContextIdStr);
+ jmsConnContext.setExceptionListener(e -> {
if (logger.isDebugEnabled()) {
- logger.debug("[Connection level JMSContext] {} -- {}",
- Thread.currentThread().getName(),
- jmsConnContext );
+ logger.error("onException::Unexpected JMS error happened:" + e);
}
+ });
+
+ connLvlJmsContexts.put(connLvlJmsConnContextIdStr, jmsConnContext);
+ if (logger.isDebugEnabled()) {
+ logger.debug("[Connection level JMSContext] {} -- {}",
+ Thread.currentThread().getName(),
+ jmsConnContext );
}
}
- catch (JMSRuntimeException e) {
- logger.error("Unable to initialize JMS connection factory with the following configuration parameters: {}", s4JClientConnInfo.toString());
- throw new S4JAdapterUnexpectedException("Unable to initialize JMS connection factory with the following error message: " + e.getCause());
- }
- catch (Exception e) {
- e.printStackTrace();
- }
+ }
+ catch (JMSRuntimeException e) {
+ logger.error("Unable to initialize JMS connection factory with the following configuration parameters: {}", s4JClientConnInfo.toString());
+ throw new S4JAdapterUnexpectedException("Unable to initialize JMS connection factory with the following error message: " + e.getCause());
}
}
@@ -284,7 +282,9 @@ public class S4JSpace implements AutoCloseable {
if (jmsContext != null) jmsContext.close();
}
- s4jConnFactory.close();
+ for (PulsarConnectionFactory s4jConnFactory : connFactories.values()) {
+ if (s4jConnFactory != null) s4jConnFactory.close();
+ }
}
catch (Exception ex) {
String exp = "Unexpected error when shutting down the S4J adaptor space";
diff --git a/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/dispensers/MessageProducerOpDispenser.java b/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/dispensers/MessageProducerOpDispenser.java
index 584ebca04..2dac6c52f 100644
--- a/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/dispensers/MessageProducerOpDispenser.java
+++ b/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/dispensers/MessageProducerOpDispenser.java
@@ -40,11 +40,13 @@ public class MessageProducerOpDispenser extends S4JBaseOpDispenser {
private final static Logger logger = LogManager.getLogger("MessageProducerOpDispenser");
public static final String MSG_HEADER_OP_PARAM = "msg_header";
+ public static final String MSG_PRIORITY_OP_PARAM = "msg_priority";
public static final String MSG_PROP_OP_PARAM = "msg_property";
public static final String MSG_BODY_OP_PARAM = "msg_body";
public static final String MSG_TYPE_OP_PARAM = "msg_type";
private final LongFunction msgHeaderRawJsonStrFunc;
+ private final LongFunction msgPriorityStrFunc;
private final LongFunction msgPropRawJsonStrFunc;
private final LongFunction msgBodyRawJsonStrFunc;
private final LongFunction msgTypeFunc;
@@ -56,6 +58,7 @@ public class MessageProducerOpDispenser extends S4JBaseOpDispenser {
super(adapter, op, tgtNameFunc, s4jSpace);
this.msgHeaderRawJsonStrFunc = lookupOptionalStrOpValueFunc(MSG_HEADER_OP_PARAM);
+ this.msgPriorityStrFunc = lookupOptionalStrOpValueFunc(MSG_PRIORITY_OP_PARAM);
this.msgPropRawJsonStrFunc = lookupOptionalStrOpValueFunc(MSG_PROP_OP_PARAM);
this.msgBodyRawJsonStrFunc = lookupMandtoryStrOpValueFunc(MSG_BODY_OP_PARAM);
this.msgTypeFunc = lookupOptionalStrOpValueFunc(MSG_TYPE_OP_PARAM);
@@ -272,6 +275,7 @@ public class MessageProducerOpDispenser extends S4JBaseOpDispenser {
public MessageProducerOp getOp(long cycle) {
String destName = destNameStrFunc.apply(cycle);
String jmsMsgHeaderRawJsonStr = msgHeaderRawJsonStrFunc.apply(cycle);
+ String jmsMsgPriorityStr = msgPriorityStrFunc.apply(cycle);
String jmsMsgPropertyRawJsonStr = msgPropRawJsonStrFunc.apply(cycle);
String jmsMsgBodyRawJsonStr = msgBodyRawJsonStrFunc.apply(cycle);
@@ -294,6 +298,9 @@ public class MessageProducerOpDispenser extends S4JBaseOpDispenser {
JMSProducer producer;
try {
producer = getJmsProducer(s4JJMSContextWrapper, asyncAPI);
+ int priority = NumberUtils.toInt(jmsMsgPriorityStr);
+ assert (priority >= 0 && priority <= 9);
+ producer.setPriority(priority);
}
catch (JMSException jmsException) {
throw new S4JAdapterUnexpectedException("Unable to create the JMS producer!");
diff --git a/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/dispensers/S4JBaseOpDispenser.java b/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/dispensers/S4JBaseOpDispenser.java
index 5150fe329..d1e1176e6 100644
--- a/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/dispensers/S4JBaseOpDispenser.java
+++ b/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/dispensers/S4JBaseOpDispenser.java
@@ -225,7 +225,7 @@ public abstract class S4JBaseOpDispenser extends BaseOpDispenser LABELS = Stream.of(values()).map(v -> v.label)
+ .collect(Collectors.toUnmodifiableSet());
+ private static boolean isValidLabel(String label) {
+ return LABELS.contains(StringUtils.upperCase(label));
+ }
+ }
+ public static String getValidMsgCompressionTypeList() {
+ return StringUtils.join(MSG_COMPRESSION_TYPE_STR.LABELS, ", ");
+ }
+ public static boolean isValidMsgCompressionTypeStr(String type) {
+ return MSG_COMPRESSION_TYPE_STR.isValidLabel(type);
+ }
+
///////
// Convert JSON string to a key/value map
public static Map convertJsonToMap(String jsonStr) throws Exception {
diff --git a/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/util/S4JClientConfConverter.java b/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/util/S4JClientConfConverter.java
index 9ba86bfb3..f9908c527 100644
--- a/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/util/S4JClientConfConverter.java
+++ b/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/util/S4JClientConfConverter.java
@@ -22,6 +22,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import io.nosqlbench.adapter.s4j.exception.S4JAdapterInvalidParamException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.HashMap;
@@ -35,6 +37,8 @@ import java.util.Map;
*/
public class S4JClientConfConverter {
+ private final static Logger logger = LogManager.getLogger(S4JClientConfConverter.class);
+
public static Map convertRawClientConf(Map pulsarClientConfMapRaw) {
Map s4jClientConfObjMap = new HashMap<>();
s4jClientConfObjMap.putAll(pulsarClientConfMapRaw);
@@ -71,34 +75,31 @@ public class S4JClientConfConverter {
/**
* Non-primitive type processing for Pulsar producer configuration items
*/
- // "compressionType" has value type "CompressionType"
- // - expecting the following values: 'LZ4', 'ZLIB', 'ZSTD', 'SNAPPY'
String confKeyName = "compressionType";
String confVal = pulsarProducerConfMapRaw.get(confKeyName);
- String expectedVal = "(LZ4|ZLIB|ZSTD|SNAPPY)";
- if (StringUtils.isNotBlank(confVal)) {
- if (StringUtils.equalsAnyIgnoreCase(confVal, "LZ4", "ZLIB", "ZSTD", "SNAPPY")) {
- CompressionType compressionType = CompressionType.NONE;
-
- switch (StringUtils.upperCase(confVal)) {
- case "LZ4":
- compressionType = CompressionType.LZ4;
- case "ZLIB":
- compressionType = CompressionType.ZLIB;
- case "ZSTD":
- compressionType = CompressionType.ZSTD;
- case "SNAPPY":
- compressionType = CompressionType.SNAPPY;
- }
-
- s4jProducerConfObjMap.put(confKeyName, compressionType);
- } else {
- throw new S4JAdapterInvalidParamException(
- getInvalidConfValStr(confKeyName, confVal, "producer", expectedVal));
+ CompressionType compressionType = CompressionType.NONE;
+ if ( StringUtils.isNotBlank(confVal) ) {
+ try {
+ S4JAdapterUtil.MSG_COMPRESSION_TYPE_STR compressionTypeStr =
+ S4JAdapterUtil.MSG_COMPRESSION_TYPE_STR.valueOf(confVal);
+ compressionType = switch (compressionTypeStr) {
+ case LZ4 -> CompressionType.LZ4;
+ case ZLIB -> CompressionType.ZLIB;
+ case ZSTD -> CompressionType.ZSTD;
+ case SNAPPY -> CompressionType.SNAPPY;
+ };
+ } catch (IllegalArgumentException e) {
+ // Any invalid value will be treated as no compression
+ logger.warn("Invalid producer \"compressionType\" value ({}) in the config properties file. " +
+ "Expecting one of the following values: {}. " +
+ "No message compression will be applied (for producers).",
+ confVal,
+ S4JAdapterUtil.getValidMsgCompressionTypeList());
}
}
+ s4jProducerConfObjMap.put(confKeyName, compressionType);
// TODO: Skip the following Pulsar configuration items for now because they're not really
// needed in the NB S4J testing at the moment. Add support for them when needed.
// * messageRoutingMode
@@ -312,7 +313,9 @@ public class S4JClientConfConverter {
Map.entry("jms.usePulsarAdmin","boolean"),
Map.entry("jms.useServerSideFiltering","boolean"),
Map.entry("jms.waitForServerStartupTimeout","int"),
- Map.entry("jms.transactionsStickyPartitions", "boolean")
+ Map.entry("jms.transactionsStickyPartitions", "boolean"),
+ Map.entry("jms.enableJMSPriority","boolean"),
+ Map.entry("jms.priorityMapping","String")
);
public static Map convertRawJmsConf(Map s4jJmsConfMapRaw) {
Map s4jJmsConfObjMap = new HashMap<>();
diff --git a/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/util/S4JJMSContextWrapper.java b/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/util/S4JJMSContextWrapper.java
index f22b6d78b..7219dce3b 100644
--- a/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/util/S4JJMSContextWrapper.java
+++ b/nb-adapters/adapter-s4j/src/main/java/io/nosqlbench/adapter/s4j/util/S4JJMSContextWrapper.java
@@ -22,19 +22,19 @@ import javax.jms.Session;
* under the License.
*/
public class S4JJMSContextWrapper {
- private final String jmsContextIdentifer;
+ private final String jmsContextIdentifier;
private final JMSContext jmsContext;
private final int jmsSessionMode;
public S4JJMSContextWrapper(String identifer, JMSContext jmsContext) {
- this.jmsContextIdentifer = identifer;
+ this.jmsContextIdentifier = identifer;
this.jmsContext = jmsContext;
this.jmsSessionMode = jmsContext.getSessionMode();
}
public int getJmsSessionMode() { return jmsSessionMode; }
public boolean isTransactedMode() { return Session.SESSION_TRANSACTED == this.getJmsSessionMode(); }
- public String getJmsContextIdentifer() { return jmsContextIdentifer; }
+ public String getJmsContextIdentifier() { return jmsContextIdentifier; }
public JMSContext getJmsContext() { return jmsContext; }
public void close() {
@@ -45,7 +45,7 @@ public class S4JJMSContextWrapper {
public String toString() {
return new ToStringBuilder(this).
- append("jmsContextIdentifer", jmsContextIdentifer).
+ append("jmsContextIdentifier", jmsContextIdentifier).
append("jmsContext", jmsContext.toString()).
toString();
}
diff --git a/nb-adapters/adapter-s4j/src/main/resources/scenarios/pulsar_s4j_producer.yaml b/nb-adapters/adapter-s4j/src/main/resources/scenarios/pulsar_s4j_producer.yaml
index 260192c69..b9c37eb1a 100644
--- a/nb-adapters/adapter-s4j/src/main/resources/scenarios/pulsar_s4j_producer.yaml
+++ b/nb-adapters/adapter-s4j/src/main/resources/scenarios/pulsar_s4j_producer.yaml
@@ -5,6 +5,7 @@ bindings:
mymap_val1: AlphaNumericString(10)
mymap_val2: AlphaNumericString(20)
mystream_val1: AlphaNumericString(50)
+ my_priority: WeightedLongs('2:20;4:70;8:10')
# document level parameters that apply to all Pulsar client types:
params:
@@ -25,6 +26,12 @@ blocks:
"JMSPriority": "9"
}
+ ## (Optional) S4J Message priority emulation (since Pulsar doesn't have native message priority)
+ # - jms.enableJMSPriority must be set to true in S4J configuration;
+ # otherwise, the priority value will be ignored.
+ # - If this is set, the "JMSPriority" value in the header will be ignored.
+ msg_priority: "{my_priority}"
+
## (Optional) JMS properties, predefined or customized (in JSON format).
msg_property: |
{
diff --git a/nb-apis/nb-api/src/main/java/io/nosqlbench/nb/api/engine/activityimpl/CyclesSpec.java b/nb-apis/nb-api/src/main/java/io/nosqlbench/nb/api/engine/activityimpl/CyclesSpec.java
index 3c03c561f..595232ef7 100644
--- a/nb-apis/nb-api/src/main/java/io/nosqlbench/nb/api/engine/activityimpl/CyclesSpec.java
+++ b/nb-apis/nb-api/src/main/java/io/nosqlbench/nb/api/engine/activityimpl/CyclesSpec.java
@@ -22,7 +22,12 @@ import org.apache.logging.log4j.Logger;
import java.security.InvalidParameterException;
-public record CyclesSpec(long first_inclusive, long last_exclusive, String firstSpec, String lastSpec) {
+public record CyclesSpec(
+ long first_inclusive,
+ long last_exclusive,
+ String firstSpec,
+ String lastSpec
+) {
private final static Logger logger = LogManager.getLogger(CyclesSpec.class);
public CyclesSpec {
if (first_inclusive>last_exclusive) {
@@ -32,16 +37,24 @@ public record CyclesSpec(long first_inclusive, long last_exclusive, String first
public static CyclesSpec parse(String spec) {
int rangeAt = spec.indexOf("..");
- String beginningInclusive = "0";
- String endingExclusive = spec;
+ String beginningSpec = "0";
+ String endingSpec = spec;
if (0 < rangeAt) {
- beginningInclusive = spec.substring(0, rangeAt);
- endingExclusive = spec.substring(rangeAt+2);
+ beginningSpec = spec.substring(0, rangeAt);
+ endingSpec = spec.substring(rangeAt+2);
+ }
+ long first = Unit.longCountFor(beginningSpec).orElseThrow(() -> new RuntimeException("Unable to parse start cycles from " + spec));
+ long last=first;
+ if (endingSpec.startsWith("+")) {
+ long added=Unit.longCountFor(endingSpec.substring(1)).orElseThrow(() -> new RuntimeException(
+ "Unable to parse incremental cycle interval. Use one of these forms: 100 or 0..100 or 0..+100"
+ ));
+ last = first+added;
+ } else {
+ last = Unit.longCountFor(endingSpec).orElseThrow(() -> new RuntimeException("Unable to parse start cycles from " + spec));
}
- long first = Unit.longCountFor(beginningInclusive).orElseThrow(() -> new RuntimeException("Unable to parse start cycles from " + spec));
- long last = Unit.longCountFor(endingExclusive).orElseThrow(() -> new RuntimeException("Unable to parse start cycles from " + spec));
- return new CyclesSpec(first, last, beginningInclusive, endingExclusive);
+ return new CyclesSpec(first, last, beginningSpec, endingSpec);
}
public String summary() {
@@ -74,4 +87,30 @@ public record CyclesSpec(long first_inclusive, long last_exclusive, String first
public long cycle_count() {
return last_exclusive -first_inclusive;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (!(o instanceof CyclesSpec that))
+ return false;
+ if (last_exclusive!=that.last_exclusive)
+ return false;
+ if (first_inclusive!=that.first_inclusive)
+ return false;
+ if (!firstSpec.equals(that.firstSpec))
+ return false;
+ if (!lastSpec.equals(that.lastSpec))
+ return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Long.hashCode(first_inclusive);
+ result = 31 * result + Long.hashCode(last_exclusive);
+ result = 31 * result + firstSpec.hashCode();
+ result = 31 * result + lastSpec.hashCode();
+ return result;
+ }
}
diff --git a/nb-apis/nb-api/src/test/java/io/nosqlbench/nb/api/engine/activityimpl/CyclesSpecTest.java b/nb-apis/nb-api/src/test/java/io/nosqlbench/nb/api/engine/activityimpl/CyclesSpecTest.java
new file mode 100644
index 000000000..e5ffbdd3f
--- /dev/null
+++ b/nb-apis/nb-api/src/test/java/io/nosqlbench/nb/api/engine/activityimpl/CyclesSpecTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 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.nb.api.engine.activityimpl;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class CyclesSpecTest {
+
+ @Test
+ public void testSingleNumberSpec() {
+ assertThat(CyclesSpec.parse("100")).isEqualTo(
+ new CyclesSpec(0,100,"0","100")
+ );
+ }
+
+ @Test
+ public void testIntervalSpec() {
+ assertThat(CyclesSpec.parse("3..13")).isEqualTo(
+ new CyclesSpec(3,13,"3","13")
+ );
+ }
+
+ @Test
+ public void testUnitsSupport() {
+ assertThat(CyclesSpec.parse("5M")).isEqualTo(
+ new CyclesSpec(0,5_000_000L,"0","5M")
+ );
+ }
+
+ @Test
+ public void testIncrementalSupport() {
+ assertThat(CyclesSpec.parse("5M..+100")).isEqualTo(
+ new CyclesSpec(5_000_000L,5_000_100L,"5M","+100")
+ );
+ }
+
+ @Test
+ public void testIncrementalUnitsSupport() {
+ assertThat(CyclesSpec.parse("5M..+1M")).isEqualTo(
+ new CyclesSpec(5_000_000L,6_000_000L,"5M","+1M")
+ );
+ }
+}