From aa660cfc5a26afddefd33b839c69defd6ac7e58e Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Mon, 31 Aug 2026 10:59:40 -0400 Subject: [PATCH 1/2] Remove unused DSE Graph support --- changelog/README.md | 1 + core-shaded/pom.xml | 22 +- core/pom.xml | 12 +- .../api/core/auth/ProxyAuthentication.java | 13 - .../api/core/config/DseDriverOption.java | 161 ---- .../api/core/graph/AsyncGraphResultSet.java | 101 -- .../api/core/graph/BatchGraphStatement.java | 150 --- .../graph/BatchGraphStatementBuilder.java | 112 --- .../dse/driver/api/core/graph/DseGraph.java | 79 -- .../DseGraphRemoteConnectionBuilder.java | 61 -- .../api/core/graph/FluentGraphStatement.java | 93 -- .../graph/FluentGraphStatementBuilder.java | 64 -- .../api/core/graph/GraphExecutionInfo.java | 94 -- .../dse/driver/api/core/graph/GraphNode.java | 234 ----- .../driver/api/core/graph/GraphResultSet.java | 93 -- .../driver/api/core/graph/GraphSession.java | 87 -- .../driver/api/core/graph/GraphStatement.java | 378 -------- .../core/graph/GraphStatementBuilderBase.java | 190 ---- .../api/core/graph/PagingEnabledOptions.java | 24 - .../api/core/graph/ScriptGraphStatement.java | 171 ---- .../graph/ScriptGraphStatementBuilder.java | 136 --- .../core/graph/predicates/CqlCollection.java | 81 -- .../driver/api/core/graph/predicates/Geo.java | 160 --- .../api/core/graph/predicates/Search.java | 136 --- .../graph/reactive/ReactiveGraphNode.java | 47 - .../reactive/ReactiveGraphResultSet.java | 66 -- .../graph/reactive/ReactiveGraphSession.java | 49 - .../api/core/metrics/DseNodeMetric.java | 59 -- .../api/core/metrics/DseSessionMetric.java | 2 - .../internal/core/data/geometry/Distance.java | 237 ----- .../geometry/DistanceSerializationProxy.java | 43 - .../internal/core/graph/ByteBufUtil.java | 47 - .../core/graph/BytecodeGraphStatement.java | 138 --- .../graph/ContinuousAsyncGraphResultSet.java | 151 --- .../graph/ContinuousGraphRequestHandler.java | 191 ---- .../core/graph/CqlCollectionPredicate.java | 75 -- .../graph/DefaultAsyncGraphResultSet.java | 83 -- .../graph/DefaultBatchGraphStatement.java | 161 ---- .../DefaultDseRemoteConnectionBuilder.java | 54 -- .../graph/DefaultFluentGraphStatement.java | 113 --- .../graph/DefaultScriptGraphStatement.java | 214 ----- .../core/graph/DseGraphRemoteConnection.java | 54 -- .../core/graph/DseGraphTraversal.java | 63 -- .../internal/core/graph/DsePredicate.java | 35 - .../internal/core/graph/EditDistance.java | 74 -- .../internal/core/graph/GeoPredicate.java | 111 --- .../driver/internal/core/graph/GeoUtils.java | 27 - .../internal/core/graph/GraphConversions.java | 410 -------- .../graph/GraphExecutionInfoConverter.java | 180 ---- .../internal/core/graph/GraphProtocol.java | 73 -- .../graph/GraphRequestAsyncProcessor.java | 104 -- .../core/graph/GraphRequestHandler.java | 908 ------------------ .../core/graph/GraphRequestSyncProcessor.java | 71 -- .../core/graph/GraphResultIterator.java | 79 -- .../internal/core/graph/GraphResultSets.java | 32 - .../internal/core/graph/GraphSON1SerdeTP.java | 346 ------- .../internal/core/graph/GraphSON2SerdeTP.java | 430 --------- .../internal/core/graph/GraphSONUtils.java | 136 --- .../core/graph/GraphStatementBase.java | 413 -------- .../core/graph/GraphSupportChecker.java | 176 ---- .../internal/core/graph/LegacyGraphNode.java | 323 ------- .../core/graph/MultiPageGraphResultSet.java | 123 --- .../internal/core/graph/ObjectGraphNode.java | 244 ----- .../internal/core/graph/SearchPredicate.java | 301 ------ .../internal/core/graph/SearchUtils.java | 143 --- .../core/graph/SinglePageGraphResultSet.java | 61 -- .../core/graph/TinkerpopBufferUtil.java | 32 - ...actDynamicGraphBinaryCustomSerializer.java | 74 -- ...ractSimpleGraphBinaryCustomSerializer.java | 153 --- .../binary/ComplexTypeSerializerUtil.java | 152 --- .../graph/binary/CqlDurationSerializer.java | 52 - .../core/graph/binary/DistanceSerializer.java | 48 - .../graph/binary/EditDistanceSerializer.java | 50 - .../core/graph/binary/GeometrySerializer.java | 47 - .../core/graph/binary/GraphBinaryModule.java | 95 -- .../core/graph/binary/GraphBinaryUtils.java | 57 -- .../graph/binary/LineStringSerializer.java | 33 - .../core/graph/binary/PairSerializer.java | 45 - .../core/graph/binary/PointSerializer.java | 34 - .../core/graph/binary/PolygonSerializer.java | 33 - .../graph/binary/TupleValueSerializer.java | 68 -- .../core/graph/binary/UdtValueSerializer.java | 66 -- .../graph/binary/buffer/DseNettyBuffer.java | 267 ----- .../binary/buffer/DseNettyBufferFactory.java | 126 --- .../reactive/DefaultReactiveGraphNode.java | 205 ---- .../DefaultReactiveGraphResultSet.java | 85 -- .../FailedReactiveGraphResultSet.java | 39 - .../ReactiveGraphRequestProcessor.java | 63 -- .../ReactiveGraphResultSetSubscription.java | 475 --------- .../insights/ExecutionProfilesInfoFinder.java | 26 +- .../schema/SpecificExecutionProfile.java | 24 +- .../TinkerpopBufferPrimitiveCodec.java | 292 ------ .../oss/driver/api/core/CqlSession.java | 23 +- .../driver/api/core/config/OptionsMap.java | 17 - .../api/core/config/TypedDriverOption.java | 106 -- .../driver/api/core/metrics/NodeMetric.java | 5 +- .../metrics/DropwizardNodeMetricUpdater.java | 8 - .../DropwizardSessionMetricUpdater.java | 7 - .../internal/core/metrics/MetricPaths.java | 7 +- .../session/BuiltInRequestProcessors.java | 32 - ...BuiltInRequestProcessorsSubstitutions.java | 40 +- .../driver/internal/core/util/Dependency.java | 5 - core/src/main/resources/reference.conf | 253 ----- .../com/datastax/dse/driver/Assertions.java | 26 - .../dse/driver/DseTestDataProviders.java | 49 - .../dse/driver/TinkerpopBufferAssert.java | 40 - .../graph/predicates/CqlCollectionTest.java | 88 -- .../api/core/graph/predicates/GeoTest.java | 108 --- .../api/core/graph/predicates/SearchTest.java | 116 --- .../core/data/geometry/DistanceTest.java | 131 --- .../data/geometry/SerializationUtils.java | 6 +- ...equestHandlerSpeculativeExecutionTest.java | 584 ----------- .../ContinuousGraphRequestHandlerTest.java | 260 ----- .../GraphExecutionInfoConverterTest.java | 124 --- .../internal/core/graph/GraphNodeTest.java | 299 ------ .../core/graph/GraphRequestHandlerTest.java | 622 ------------ .../graph/GraphRequestHandlerTestHarness.java | 232 ----- .../core/graph/GraphResultSetTestBase.java | 86 -- .../core/graph/GraphResultSetsTest.java | 99 -- .../graph/GraphStatementBuilderBaseTest.java | 58 -- .../core/graph/GraphSupportCheckerTest.java | 325 ------- .../internal/core/graph/GraphTestUtils.java | 189 ---- .../core/graph/binary/GraphDataTypesTest.java | 333 ------- .../ReactiveGraphRequestProcessorTest.java | 192 ---- .../refresh/GraphSchemaRefreshTest.java | 418 -------- .../insights/ExecutionProfileMockUtil.java | 8 - .../ExecutionProfilesInfoFinderTest.java | 36 +- .../core/insights/InsightsClientTest.java | 5 +- .../TinkerpopBufferPrimitiveCodecTest.java | 358 ------- distribution/pom.xml | 15 - integration-tests/pom.xml | 22 +- .../graph/ClassicGraphDataTypeITBase.java | 178 ---- .../graph/ClassicGraphGeoSearchIndexIT.java | 159 --- .../graph/ClassicGraphTextSearchIndexIT.java | 154 --- .../core/graph/CoreGraphDataTypeITBase.java | 271 ------ .../core/graph/CoreGraphGeoSearchIndexIT.java | 128 --- .../graph/CoreGraphTextSearchIndexIT.java | 133 --- .../api/core/graph/CqlCollectionIT.java | 235 ----- .../api/core/graph/GraphAuthenticationIT.java | 77 -- .../core/graph/GraphGeoSearchIndexITBase.java | 180 ---- .../driver/api/core/graph/GraphPagingIT.java | 510 ---------- .../graph/GraphSpeculativeExecutionIT.java | 107 --- .../api/core/graph/GraphTestSupport.java | 65 -- .../graph/GraphTextSearchIndexITBase.java | 229 ----- .../api/core/graph/GraphTimeoutsIT.java | 184 ---- .../api/core/graph/SampleGraphScripts.java | 64 -- .../api/core/graph/SocialTraversalDsl.java | 29 - .../core/graph/SocialTraversalSourceDsl.java | 60 -- .../api/core/graph/TinkerEdgeAssert.java | 49 - .../api/core/graph/TinkerElementAssert.java | 52 - .../api/core/graph/TinkerGraphAssertions.java | 47 - .../api/core/graph/TinkerPathAssert.java | 110 --- .../api/core/graph/TinkerTreeAssert.java | 45 - .../api/core/graph/TinkerVertexAssert.java | 46 - .../graph/TinkerVertexPropertyAssert.java | 46 - .../DefaultReactiveGraphResultSetIT.java | 118 --- .../remote/ClassicGraphDataTypeRemoteIT.java | 75 -- .../remote/ClassicGraphTraversalRemoteIT.java | 90 -- .../remote/CoreGraphDataTypeRemoteIT.java | 88 -- .../remote/CoreGraphTraversalRemoteIT.java | 85 -- .../GraphTraversalMetaPropertiesRemoteIT.java | 95 -- ...GraphTraversalMultiPropertiesRemoteIT.java | 96 -- .../remote/GraphTraversalRemoteITBase.java | 661 ------------- .../ClassicGraphDataTypeFluentIT.java | 76 -- .../ClassicGraphDataTypeScriptIT.java | 77 -- .../ClassicGraphTraversalBatchIT.java | 80 -- .../statement/ClassicGraphTraversalIT.java | 91 -- .../statement/CoreGraphDataTypeFluentIT.java | 86 -- .../statement/CoreGraphDataTypeScriptIT.java | 91 -- .../statement/CoreGraphTraversalBatchIT.java | 75 -- .../graph/statement/CoreGraphTraversalIT.java | 84 -- .../statement/GraphTraversalBatchITBase.java | 159 --- .../graph/statement/GraphTraversalITBase.java | 668 ------------- .../GraphTraversalMetaPropertiesIT.java | 95 -- .../GraphTraversalMultiPropertiesIT.java | 96 -- .../src/test/resources/application.conf | 4 - manual/core/graalvm/README.md | 54 +- manual/core/integration/README.md | 39 - manual/developer/request_execution/README.md | 2 - .../MicrometerNodeMetricUpdater.java | 19 - .../MicrometerSessionMetricUpdater.java | 21 - .../MicrometerNodeMetricUpdaterTest.java | 10 - .../MicrometerSessionMetricUpdaterTest.java | 8 - .../MicroProfileNodeMetricUpdater.java | 2 - .../MicroProfileSessionMetricUpdater.java | 2 - osgi-tests/pom.xml | 10 +- .../service/graph/GraphMailboxService.java | 29 - .../internal/osgi/MailboxActivator.java | 16 - .../graph/GraphMailboxServiceImpl.java | 103 -- .../src/main/resources/application.conf | 4 - .../driver/internal/osgi/OsgiDefaultIT.java | 2 +- .../oss/driver/internal/osgi/OsgiGraphIT.java | 69 -- .../osgi/checks/GraphServiceChecks.java | 44 - .../internal/osgi/support/BundleOptions.java | 47 - .../osgi/support/CcmStagedReactor.java | 11 +- pom.xml | 33 - test-infra/pom.xml | 5 - .../session/CqlSessionRuleBuilder.java | 67 +- .../api/testinfra/session/SessionRule.java | 89 +- .../testinfra/session/SessionRuleBuilder.java | 28 - .../gremlin/PatchedGremlinDslProcessor.java | 38 - upgrade_guide/README.md | 37 +- 202 files changed, 48 insertions(+), 24162 deletions(-) delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/AsyncGraphResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/BatchGraphStatement.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/BatchGraphStatementBuilder.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/DseGraph.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/DseGraphRemoteConnectionBuilder.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/FluentGraphStatement.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/FluentGraphStatementBuilder.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphExecutionInfo.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphNode.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphSession.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphStatement.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphStatementBuilderBase.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/PagingEnabledOptions.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/ScriptGraphStatement.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/ScriptGraphStatementBuilder.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/CqlCollection.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/Geo.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/Search.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphNode.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphSession.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseNodeMetric.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/data/geometry/Distance.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/data/geometry/DistanceSerializationProxy.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/ByteBufUtil.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/BytecodeGraphStatement.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/ContinuousAsyncGraphResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandler.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/CqlCollectionPredicate.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultAsyncGraphResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultBatchGraphStatement.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultDseRemoteConnectionBuilder.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultFluentGraphStatement.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultScriptGraphStatement.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/DseGraphRemoteConnection.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/DseGraphTraversal.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/DsePredicate.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/EditDistance.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GeoPredicate.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GeoUtils.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphConversions.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphExecutionInfoConverter.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphProtocol.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestAsyncProcessor.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandler.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestSyncProcessor.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphResultIterator.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphResultSets.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSON1SerdeTP.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSON2SerdeTP.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSONUtils.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphStatementBase.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSupportChecker.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/LegacyGraphNode.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/MultiPageGraphResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/ObjectGraphNode.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/SearchPredicate.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/SearchUtils.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/SinglePageGraphResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/TinkerpopBufferUtil.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/AbstractDynamicGraphBinaryCustomSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/AbstractSimpleGraphBinaryCustomSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/ComplexTypeSerializerUtil.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/CqlDurationSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/DistanceSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/EditDistanceSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GeometrySerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GraphBinaryModule.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GraphBinaryUtils.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/LineStringSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PairSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PointSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PolygonSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/TupleValueSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/UdtValueSerializer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/buffer/DseNettyBuffer.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/buffer/DseNettyBufferFactory.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/DefaultReactiveGraphNode.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/DefaultReactiveGraphResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/FailedReactiveGraphResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphRequestProcessor.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphResultSetSubscription.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/protocol/TinkerpopBufferPrimitiveCodec.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/Assertions.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/TinkerpopBufferAssert.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/CqlCollectionTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/GeoTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/SearchTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/data/geometry/DistanceTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandlerSpeculativeExecutionTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandlerTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphExecutionInfoConverterTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphNodeTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandlerTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandlerTestHarness.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphResultSetTestBase.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphResultSetsTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphStatementBuilderBaseTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphSupportCheckerTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphTestUtils.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/binary/GraphDataTypesTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphRequestProcessorTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/graph/schema/refresh/GraphSchemaRefreshTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/protocol/TinkerpopBufferPrimitiveCodecTest.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphDataTypeITBase.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphGeoSearchIndexIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphTextSearchIndexIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphDataTypeITBase.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphGeoSearchIndexIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphTextSearchIndexIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CqlCollectionIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphAuthenticationIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphGeoSearchIndexITBase.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphPagingIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphSpeculativeExecutionIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTestSupport.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTextSearchIndexITBase.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTimeoutsIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SampleGraphScripts.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SocialTraversalDsl.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SocialTraversalSourceDsl.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerEdgeAssert.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerElementAssert.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerGraphAssertions.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerPathAssert.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerTreeAssert.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerVertexAssert.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerVertexPropertyAssert.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/reactive/DefaultReactiveGraphResultSetIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/ClassicGraphDataTypeRemoteIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/ClassicGraphTraversalRemoteIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/CoreGraphDataTypeRemoteIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/CoreGraphTraversalRemoteIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalMetaPropertiesRemoteIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalMultiPropertiesRemoteIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalRemoteITBase.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphDataTypeFluentIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphDataTypeScriptIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphTraversalBatchIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphTraversalIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphDataTypeFluentIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphDataTypeScriptIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphTraversalBatchIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphTraversalIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalBatchITBase.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalITBase.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalMetaPropertiesIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalMultiPropertiesIT.java delete mode 100644 osgi-tests/src/main/java/com/datastax/oss/driver/api/osgi/service/graph/GraphMailboxService.java delete mode 100644 osgi-tests/src/main/java/com/datastax/oss/driver/internal/osgi/service/graph/GraphMailboxServiceImpl.java delete mode 100644 osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/OsgiGraphIT.java delete mode 100644 osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/checks/GraphServiceChecks.java delete mode 100644 test-infra/src/main/java/com/datastax/oss/driver/internal/gremlin/PatchedGremlinDslProcessor.java diff --git a/changelog/README.md b/changelog/README.md index b90979e2e71..e3d3ee58697 100644 --- a/changelog/README.md +++ b/changelog/README.md @@ -23,6 +23,7 @@ under the License. ### 4.19.2 +- [improvement] Remove unused DSE Graph support and TinkerPop integration (#1028) - [bug] CASSJAVA-116: Retry or Speculative Execution with RequestIdGenerator throws "Duplicate Key" ### 4.19.1 diff --git a/core-shaded/pom.xml b/core-shaded/pom.xml index 4d6ccfd8fad..f627c5f9c1d 100644 --- a/core-shaded/pom.xml +++ b/core-shaded/pom.xml @@ -99,16 +99,6 @@ esri-geometry-api true - - org.apache.tinkerpop - gremlin-core - true - - - org.apache.tinkerpop - tinkergraph-gremlin - true - org.reactivestreams reactive-streams @@ -316,16 +306,6 @@ lz4-java ${lz4.version} - - org.apache.tinkerpop - gremlin-core - ${tinkerpop.version} - - - org.apache.tinkerpop - tinkergraph-gremlin - ${tinkerpop.version} - com.esri.geometry esri-geometry-api @@ -375,7 +355,7 @@ Note: dependencies marked as optional are by default included with optional resolution in the manifest; we only need to manually set the resolution to optional for dependencies declared as non-optional in the pom files. - -->jnr.*;resolution:=optional, com.esri.core.geometry.*;resolution:=optional,org.reactivestreams.*;resolution:=optional, org.apache.tinkerpop.*;resolution:=optional, org.javatuples.*;resolution:=optional, reactor.blockhound.*;resolution:=optional, + -->jnr.*;resolution:=optional, com.esri.core.geometry.*;resolution:=optional,org.reactivestreams.*;resolution:=optional, reactor.blockhound.*;resolution:=optional, jnr.*;resolution:=optional, com.esri.core.geometry.*;resolution:=optional, org.reactivestreams.*;resolution:=optional, org.apache.tinkerpop.*;resolution:=optional, org.javatuples.*;resolution:=optional, reactor.blockhound.*;resolution:=optional, * + -->jnr.*;resolution:=optional, com.esri.core.geometry.*;resolution:=optional, org.reactivestreams.*;resolution:=optional, reactor.blockhound.*;resolution:=optional, * com.datastax.oss.driver.*.core.*, com.datastax.dse.driver.*.core.* diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/auth/ProxyAuthentication.java b/core/src/main/java/com/datastax/dse/driver/api/core/auth/ProxyAuthentication.java index a3624ba736d..0794f2da52f 100644 --- a/core/src/main/java/com/datastax/dse/driver/api/core/auth/ProxyAuthentication.java +++ b/core/src/main/java/com/datastax/dse/driver/api/core/auth/ProxyAuthentication.java @@ -17,7 +17,6 @@ */ package com.datastax.dse.driver.api.core.auth; -import com.datastax.dse.driver.api.core.graph.GraphStatement; import com.datastax.oss.driver.api.core.cql.Statement; import com.datastax.oss.driver.shaded.guava.common.base.Charsets; import com.datastax.oss.protocol.internal.util.collection.NullAllowingImmutableMap; @@ -52,18 +51,6 @@ public static > StatementT executeAs( addProxyExecuteEntry(statement.getCustomPayload(), userOrRole)); } - /** - * Adds proxy authentication information to a graph statement. - * - * @see #executeAs(String, Statement) - */ - @NonNull - public static > StatementT executeAs( - @NonNull String userOrRole, @NonNull StatementT statement) { - return statement.setCustomPayload( - addProxyExecuteEntry(statement.getCustomPayload(), userOrRole)); - } - private static Map addProxyExecuteEntry( Map currentPayload, @NonNull String userOrRole) { NullAllowingImmutableMap.Builder builder = diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/config/DseDriverOption.java b/core/src/main/java/com/datastax/dse/driver/api/core/config/DseDriverOption.java index 4d10501f6d2..612448cb99e 100644 --- a/core/src/main/java/com/datastax/dse/driver/api/core/config/DseDriverOption.java +++ b/core/src/main/java/com/datastax/dse/driver/api/core/config/DseDriverOption.java @@ -125,50 +125,6 @@ public enum DseDriverOption implements DriverOption { CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_INTERVAL( "advanced.metrics.session.continuous-cql-requests.refresh-interval"), - /** - * The read consistency level to use for graph statements. - * - *

Value type: {@link String} - */ - GRAPH_READ_CONSISTENCY_LEVEL("basic.graph.read-consistency-level"), - /** - * The write consistency level to use for graph statements. - * - *

Value type: {@link String} - */ - GRAPH_WRITE_CONSISTENCY_LEVEL("basic.graph.write-consistency-level"), - /** - * The traversal source to use for graph statements. - * - *

Value type: {@link String} - */ - GRAPH_TRAVERSAL_SOURCE("basic.graph.traversal-source"), - /** - * The sub-protocol the driver will use to communicate with DSE Graph, on top of the Cassandra - * native protocol. - * - *

Value type: {@link String} - */ - GRAPH_SUB_PROTOCOL("advanced.graph.sub-protocol"), - /** - * Whether a script statement represents a system query. - * - *

Value type: boolean - */ - GRAPH_IS_SYSTEM_QUERY("basic.graph.is-system-query"), - /** - * The name of the graph targeted by graph statements. - * - *

Value type: {@link String} - */ - GRAPH_NAME("basic.graph.name"), - /** - * How long the driver waits for a graph request to complete. - * - *

Value-type: {@link java.time.Duration Duration} - */ - GRAPH_TIMEOUT("basic.graph.timeout"), - /** * Whether to send events for Insights monitoring. * @@ -176,80 +132,6 @@ public enum DseDriverOption implements DriverOption { */ MONITOR_REPORTING_ENABLED("advanced.monitor-reporting.enabled"), - /** - * Whether to enable paging for Graph queries. - * - *

Value type: {@link String} - */ - GRAPH_PAGING_ENABLED("advanced.graph.paging-enabled"), - - /** - * The page size for Graph continuous paging. - * - *

Value type: int - */ - GRAPH_CONTINUOUS_PAGING_PAGE_SIZE("advanced.graph.paging-options.page-size"), - - /** - * The maximum number of Graph continuous pages to return. - * - *

Value type: int - */ - GRAPH_CONTINUOUS_PAGING_MAX_PAGES("advanced.graph.paging-options.max-pages"), - /** - * The maximum number of Graph continuous pages per second. - * - *

Value type: int - */ - GRAPH_CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND( - "advanced.graph.paging-options.max-pages-per-second"), - /** - * The maximum number of Graph continuous pages that can be stored in the local queue. - * - *

Value type: int - */ - GRAPH_CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES("advanced.graph.paging-options.max-enqueued-pages"), - /** - * The largest latency that we expect to record for graph requests. - * - *

Value-type: {@link java.time.Duration Duration} - */ - METRICS_SESSION_GRAPH_REQUESTS_HIGHEST("advanced.metrics.session.graph-requests.highest-latency"), - /** - * The number of significant decimal digits to which internal structures will maintain for graph - * requests. - * - *

Value-type: int - */ - METRICS_SESSION_GRAPH_REQUESTS_DIGITS( - "advanced.metrics.session.graph-requests.significant-digits"), - /** - * The interval at which percentile data is refreshed for graph requests. - * - *

Value-type: {@link java.time.Duration Duration} - */ - METRICS_SESSION_GRAPH_REQUESTS_INTERVAL( - "advanced.metrics.session.graph-requests.refresh-interval"), - /** - * The largest latency that we expect to record for graph requests. - * - *

Value-type: {@link java.time.Duration Duration} - */ - METRICS_NODE_GRAPH_MESSAGES_HIGHEST("advanced.metrics.node.graph-messages.highest-latency"), - /** - * The number of significant decimal digits to which internal structures will maintain for graph - * requests. - * - *

Value-type: int - */ - METRICS_NODE_GRAPH_MESSAGES_DIGITS("advanced.metrics.node.graph-messages.significant-digits"), - /** - * The interval at which percentile data is refreshed for graph requests. - * - *

Value-type: {@link java.time.Duration Duration} - */ - METRICS_NODE_GRAPH_MESSAGES_INTERVAL("advanced.metrics.node.graph-messages.refresh-interval"), - /** * The shortest latency that we expect to record for continuous requests. * @@ -265,49 +147,6 @@ public enum DseDriverOption implements DriverOption { CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_SLO( "advanced.metrics.session.continuous-cql-requests.slo"), - /** - * The shortest latency that we expect to record for graph requests. - * - *

Value-type: {@link java.time.Duration Duration} - */ - METRICS_SESSION_GRAPH_REQUESTS_LOWEST("advanced.metrics.session.graph-requests.lowest-latency"), - /** - * Optional service-level objectives to meet, as a list of latencies to track. - * - *

Value-type: {@link java.time.Duration Duration} - */ - METRICS_SESSION_GRAPH_REQUESTS_SLO("advanced.metrics.session.graph-requests.slo"), - - /** - * The shortest latency that we expect to record for graph requests. - * - *

Value-type: {@link java.time.Duration Duration} - */ - METRICS_NODE_GRAPH_MESSAGES_LOWEST("advanced.metrics.node.graph-messages.lowest-latency"), - /** - * Optional service-level objectives to meet, as a list of latencies to track. - * - *

Value-type: {@link java.time.Duration Duration} - */ - METRICS_NODE_GRAPH_MESSAGES_SLO("advanced.metrics.node.graph-messages.slo"), - /** - * Optional list of percentiles to publish for graph-requests metric. Produces an additional time - * series for each requested percentile. This percentile is computed locally, and so can't be - * aggregated with percentiles computed across other dimensions (e.g. in a different instance). - * - *

Value type: {@link java.util.List List}<{@link Double}> - */ - METRICS_SESSION_GRAPH_REQUESTS_PUBLISH_PERCENTILES( - "advanced.metrics.session.graph-requests.publish-percentiles"), - /** - * Optional list of percentiles to publish for node graph-messages metric. Produces an additional - * time series for each requested percentile. This percentile is computed locally, and so can't be - * aggregated with percentiles computed across other dimensions (e.g. in a different instance). - * - *

Value type: {@link java.util.List List}<{@link Double}> - */ - METRICS_NODE_GRAPH_MESSAGES_PUBLISH_PERCENTILES( - "advanced.metrics.node.graph-messages.publish-percentiles"), /** * Optional list of percentiles to publish for continuous paging requests metric. Produces an * additional time series for each requested percentile. This percentile is computed locally, and diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/AsyncGraphResultSet.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/AsyncGraphResultSet.java deleted file mode 100644 index 995de53959b..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/AsyncGraphResultSet.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.dse.driver.internal.core.graph.GraphExecutionInfoConverter; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Iterator; -import java.util.concurrent.CompletionStage; - -/** - * The result of an asynchronous graph query. - * - *

The default implementation returned by the driver is not thread-safe: the iterable - * returned by {@link #currentPage()} should only be iterated by a single thread. However, if - * subsequent pages are requested via {@link #fetchNextPage()}, it's safe to process those new - * instances in other threads (as long as each individual page of results is not accessed - * concurrently). - * - * @see GraphResultSet - */ -public interface AsyncGraphResultSet { - - /** The execution information for this page of results. */ - @NonNull - default ExecutionInfo getRequestExecutionInfo() { - return GraphExecutionInfoConverter.convert(getExecutionInfo()); - } - - /** - * The execution information for this page of results. - * - * @deprecated Use {@link #getRequestExecutionInfo()} instead. - */ - @Deprecated - @NonNull - com.datastax.dse.driver.api.core.graph.GraphExecutionInfo getExecutionInfo(); - - /** How many rows are left before the current page is exhausted. */ - int remaining(); - - /** - * The nodes in the current page. To keep iterating beyond that, use {@link #hasMorePages()} and - * {@link #fetchNextPage()}. - * - *

Note that this method always returns the same object, and that that object can only be - * iterated once: nodes are "consumed" as they are read. - */ - @NonNull - Iterable currentPage(); - - /** - * Returns the next node, or {@code null} if the result set is exhausted. - * - *

This is convenient for queries that are known to return exactly one node. - */ - @Nullable - default GraphNode one() { - Iterator iterator = currentPage().iterator(); - return iterator.hasNext() ? iterator.next() : null; - } - - /** - * Whether there are more pages of results. If so, call {@link #fetchNextPage()} to fetch the next - * one asynchronously. - */ - boolean hasMorePages(); - - /** - * Fetch the next page of results asynchronously. - * - * @throws IllegalStateException if there are no more pages. Use {@link #hasMorePages()} to check - * if you can call this method. - */ - @NonNull - CompletionStage fetchNextPage() throws IllegalStateException; - - /** - * Cancels the query and asks the server to stop sending results. - * - *

At this time, graph queries are not paginated and the server sends all the results at once; - * therefore this method has no effect. - */ - void cancel(); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/BatchGraphStatement.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/BatchGraphStatement.java deleted file mode 100644 index 2169dc5f053..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/BatchGraphStatement.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.dse.driver.internal.core.graph.DefaultBatchGraphStatement; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Collections; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; - -/** - * A graph statement that groups multiple mutating traversals together, to be executed in the - * same transaction. - * - *

It is reserved for graph mutations, and does not return any result. - * - *

All the mutations grouped in the batch will either all succeed, or they will all be discarded - * and return an error. - * - *

The default implementation returned by the driver is immutable and thread-safe. Each mutation - * operation returns a copy. If you chain many of those operations, it is recommended to use {@link - * #builder()} instead for better memory usage. - * - *

Typically used like so: - * - *

{@code
- * import static com.datastax.dse.driver.api.core.graph.DseGraph.g;
- *
- * BatchGraphStatement statement =
- *     BatchGraphStatement.builder()
- *         .addTraversal(
- *                 g.addV("person").property("name", "batch1").property("age", 1))
- *         .addTraversal(
- *                 g.addV("person").property("name", "batch2").property("age", 2))
- *         .build();
- *
- * GraphResultSet graphResultSet = dseSession.execute(statement);
- * }
- * - * @see DseGraph#g - */ -public interface BatchGraphStatement - extends GraphStatement, Iterable { - - /** - * Create a new, empty instance. - * - *

Traversals can be added with {@link #addTraversal(GraphTraversal)}. - */ - @NonNull - static BatchGraphStatement newInstance() { - return new DefaultBatchGraphStatement( - ImmutableList.of(), - null, - null, - null, - Statement.NO_DEFAULT_TIMESTAMP, - null, - null, - Collections.emptyMap(), - null, - null, - null, - null, - null, - null); - } - - /** Create a new instance from the given list of traversals. */ - @NonNull - static BatchGraphStatement newInstance(@NonNull Iterable traversals) { - return new DefaultBatchGraphStatement( - traversals, - null, - null, - null, - Statement.NO_DEFAULT_TIMESTAMP, - null, - null, - Collections.emptyMap(), - null, - null, - null, - null, - null, - null); - } - - /** Create a new instance from the given list of traversals. */ - @NonNull - static BatchGraphStatement newInstance(@NonNull GraphTraversal... traversals) { - return newInstance(ImmutableList.copyOf(traversals)); - } - - /** - * Create a builder helper object to start creating a new instance. - * - *

Note that this builder is mutable and not thread-safe. - */ - @NonNull - static BatchGraphStatementBuilder builder() { - return new BatchGraphStatementBuilder(); - } - - /** - * Create a builder helper object to start creating a new instance with an existing statement as a - * template. The traversals and options set on the template will be copied for the new statement - * at the moment this method is called. - * - *

Note that this builder is mutable and not thread-safe. - */ - @NonNull - static BatchGraphStatementBuilder builder(@NonNull BatchGraphStatement template) { - return new BatchGraphStatementBuilder(template); - } - - /** - * Add a traversal to this statement. If many traversals need to be added, use a {@link - * #builder()}, or the {@link #addTraversals(Iterable)} method instead to avoid intermediary - * copies. - */ - @NonNull - BatchGraphStatement addTraversal(@NonNull GraphTraversal traversal); - - /** - * Adds several traversals to this statement. If this method is to be called many times, consider - * using a {@link #builder()} instead to avoid intermediary copies. - */ - @NonNull - BatchGraphStatement addTraversals(@NonNull Iterable traversals); - - /** Get the number of traversals already added to this statement. */ - int size(); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/BatchGraphStatementBuilder.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/BatchGraphStatementBuilder.java deleted file mode 100644 index ac1b85bdc71..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/BatchGraphStatementBuilder.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.dse.driver.internal.core.graph.DefaultBatchGraphStatement; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import edu.umd.cs.findbugs.annotations.NonNull; -import net.jcip.annotations.NotThreadSafe; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; - -/** - * A builder to create a batch graph statement. - * - *

This class is mutable and not thread-safe. - */ -@NotThreadSafe -public class BatchGraphStatementBuilder - extends GraphStatementBuilderBase { - - private ImmutableList.Builder traversalsBuilder = ImmutableList.builder(); - private int traversalsCount; - - public BatchGraphStatementBuilder() { - // nothing to do - } - - public BatchGraphStatementBuilder(BatchGraphStatement template) { - super(template); - traversalsBuilder.addAll(template); - traversalsCount = template.size(); - } - - /** Add a traversal to this builder to include in the generated {@link BatchGraphStatement}. */ - @NonNull - public BatchGraphStatementBuilder addTraversal(@NonNull GraphTraversal traversal) { - traversalsBuilder.add(traversal); - traversalsCount += 1; - return this; - } - - /** - * Add several traversals to this builder to include in the generated {@link BatchGraphStatement}. - */ - @NonNull - public BatchGraphStatementBuilder addTraversals(@NonNull Iterable traversals) { - for (GraphTraversal traversal : traversals) { - traversalsBuilder.add(traversal); - traversalsCount += 1; - } - return this; - } - - /** - * Add several traversals to this builder to include in the generated {@link BatchGraphStatement}. - */ - @NonNull - public BatchGraphStatementBuilder addTraversals(@NonNull GraphTraversal... traversals) { - for (GraphTraversal traversal : traversals) { - traversalsBuilder.add(traversal); - traversalsCount += 1; - } - return this; - } - - /** Clears all the traversals previously added to this builder. */ - @NonNull - public BatchGraphStatementBuilder clearTraversals() { - traversalsBuilder = ImmutableList.builder(); - traversalsCount = 0; - return this; - } - - /** Returns the number of traversals added to this statement so far. */ - public int getTraversalsCount() { - return traversalsCount; - } - - @NonNull - @Override - public BatchGraphStatement build() { - return new DefaultBatchGraphStatement( - traversalsBuilder.build(), - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - buildCustomPayload(), - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/DseGraph.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/DseGraph.java deleted file mode 100644 index dd1dbe95bc8..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/DseGraph.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.dse.driver.internal.core.graph.DefaultDseRemoteConnectionBuilder; -import com.datastax.oss.driver.api.core.CqlSession; -import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; - -/** - * General purpose utility class for interaction with DSE Graph via the DataStax Enterprise Java - * driver. - */ -public class DseGraph { - - /** - * IMPORTANT: As of Tinkerpop 3.3.5, you should no longer use this shortcut if you intend - * to connect the traversal to DSE Graph using a {@linkplain - * org.apache.tinkerpop.gremlin.process.remote.RemoteConnection remote connection}, for example - * via the {@link #remoteConnectionBuilder} method declared below. Instead of: - * - *

{@code
-   * DseSession session = ...;
-   * RemoteConnection remoteConnection = DseGraph.remoteConnectionBuilder(session).build();
-   * GraphTraversalSource g = DseGraph.g.withRemote(remoteConnection);
-   * }
- * - * You should now use {@link AnonymousTraversalSource#traversal()}, and adopt the following idiom: - * - *
{@code
-   * DseSession session = ...;
-   * RemoteConnection remoteConnection = DseGraph.remoteConnectionBuilder(session).build();
-   * GraphTraversalSource g = AnonymousTraversalSource.traversal().withRemote(remoteConnection);
-   * }
- * - * A general-purpose shortcut for a non-connected TinkerPop {@link GraphTraversalSource} - * based on an immutable empty graph. This is really just a shortcut to {@code - * EmptyGraph.instance().traversal();}. - * - *

It can be used to create {@link FluentGraphStatement} instances (recommended); for ease of - * use you may statically import this variable. - * - *

Calling {@code g.getGraph()} will return a local immutable empty graph which is in no way - * connected to the DSE Graph server, it will not allow to modify a DSE Graph directly. To act on - * data stored in DSE Graph you must use {@linkplain - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal traversal}s such as - * {@code DseGraph.g.V()}, {@code DseGraph.g.addV/addE()}. - */ - public static final GraphTraversalSource g = EmptyGraph.instance().traversal(); - - /** - * Returns a builder helper class to help create {@link - * org.apache.tinkerpop.gremlin.process.remote.RemoteConnection} implementations that seamlessly - * connect to DSE Graph using the {@link CqlSession} in parameter. - */ - public static DseGraphRemoteConnectionBuilder remoteConnectionBuilder(CqlSession dseSession) { - return new DefaultDseRemoteConnectionBuilder(dseSession); - } - - private DseGraph() { - // nothing to do - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/DseGraphRemoteConnectionBuilder.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/DseGraphRemoteConnectionBuilder.java deleted file mode 100644 index c4210a5b3dd..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/DseGraphRemoteConnectionBuilder.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection; - -/** - * A builder helper to create a {@link RemoteConnection} that will be used to build - * implicitly-executing fluent traversals. - * - *

To create an instance of this, use the {@link DseGraph#remoteConnectionBuilder(CqlSession)} - * method: - * - *

{@code
- * DseSession dseSession = DseSession.builder().build();
- * GraphTraversalSource g = AnonymousTraversalSource.traversal().withRemote(DseGraph.remoteConnectionBuilder(dseSession).build());
- * List vertices = g.V().hasLabel("person").toList();
- * }
- * - * @see CqlSession - */ -public interface DseGraphRemoteConnectionBuilder { - - /** Build the remote connection that was configured with this builder. */ - RemoteConnection build(); - - /** - * Set a configuration profile that will be used for every traversal built using the remote - * connection. - * - *

For the list of options available for Graph requests, see the {@code reference.conf} - * configuration file. - */ - DseGraphRemoteConnectionBuilder withExecutionProfile(DriverExecutionProfile executionProfile); - - /** - * Set the name of an execution profile that will be used for every traversal using from the - * remote connection. Named profiles are pre-defined in the driver configuration. - * - *

For the list of options available for Graph requests, see the {@code reference.conf} - * configuration file. - */ - DseGraphRemoteConnectionBuilder withExecutionProfileName(String executionProfileName); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/FluentGraphStatement.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/FluentGraphStatement.java deleted file mode 100644 index 051c6501c65..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/FluentGraphStatement.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.dse.driver.internal.core.graph.DefaultFluentGraphStatement; -import com.datastax.oss.driver.api.core.cql.Statement; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Collections; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; - -/** - * A graph statement that uses a TinkerPop {@link GraphTraversal} as the query. - * - *

Typically used like so: - * - *

{@code
- * import static com.datastax.dse.driver.api.core.graph.DseGraph.g;
- *
- * FluentGraphStatement statement = FluentGraphStatement.newInstance(g.V().has("name", "marko"));
- *
- * GraphResultSet graphResultSet = dseSession.execute(statement);
- * }
- * - * @see DseGraph#g - */ -public interface FluentGraphStatement extends GraphStatement { - - /** - * Create a new instance from the given traversal. - * - *

Use {@link #builder(GraphTraversal)} if you want to set more options before building the - * final statement instance. - */ - @NonNull - static FluentGraphStatement newInstance(@NonNull GraphTraversal traversal) { - return new DefaultFluentGraphStatement( - traversal, - null, - null, - null, - Statement.NO_DEFAULT_TIMESTAMP, - null, - null, - Collections.emptyMap(), - null, - null, - null, - null, - null, - null); - } - - /** - * Create a builder object to start creating a new instance from the given traversal. - * - *

Note that this builder is mutable and not thread-safe. - */ - @NonNull - static FluentGraphStatementBuilder builder(@NonNull GraphTraversal traversal) { - return new FluentGraphStatementBuilder(traversal); - } - - /** - * Create a builder helper object to start creating a new instance with an existing statement as a - * template. The traversal and options set on the template will be copied for the new statement at - * the moment this method is called. - * - *

Note that this builder is mutable and not thread-safe. - */ - @NonNull - static FluentGraphStatementBuilder builder(@NonNull FluentGraphStatement template) { - return new FluentGraphStatementBuilder(template); - } - - /** The underlying TinkerPop object representing the traversal executed by this statement. */ - @NonNull - GraphTraversal getTraversal(); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/FluentGraphStatementBuilder.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/FluentGraphStatementBuilder.java deleted file mode 100644 index 59e588c564a..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/FluentGraphStatementBuilder.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.dse.driver.internal.core.graph.DefaultFluentGraphStatement; -import edu.umd.cs.findbugs.annotations.NonNull; -import net.jcip.annotations.NotThreadSafe; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; - -/** - * A builder to create a fluent graph statement. - * - *

This class is mutable and not thread-safe. - */ -@NotThreadSafe -public class FluentGraphStatementBuilder - extends GraphStatementBuilderBase { - - private GraphTraversal traversal; - - public FluentGraphStatementBuilder(@NonNull GraphTraversal traversal) { - this.traversal = traversal; - } - - public FluentGraphStatementBuilder(@NonNull FluentGraphStatement template) { - super(template); - this.traversal = template.getTraversal(); - } - - @NonNull - @Override - public FluentGraphStatement build() { - return new DefaultFluentGraphStatement( - this.traversal, - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - buildCustomPayload(), - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphExecutionInfo.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphExecutionInfo.java deleted file mode 100644 index 758f6b358ed..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphExecutionInfo.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.api.core.DefaultProtocolVersion; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.specex.SpeculativeExecutionPolicy; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.Map; - -/** - * Information about the execution of a graph statement. - * - * @deprecated This interface is not used by any driver component anymore; the driver now exposes - * instances of {@link com.datastax.oss.driver.api.core.cql.ExecutionInfo} for all Graph - * queries. - */ -@Deprecated -public interface GraphExecutionInfo { - - /** The statement that was executed. */ - GraphStatement getStatement(); - - /** The node that was used as a coordinator to successfully complete the query. */ - Node getCoordinator(); - - /** - * The number of speculative executions that were started for this query. - * - *

This does not include the initial, normal execution of the query. Therefore, if speculative - * executions are disabled, this will always be 0. If they are enabled and one speculative - * execution was triggered in addition to the initial execution, this will be 1, etc. - * - * @see SpeculativeExecutionPolicy - */ - int getSpeculativeExecutionCount(); - - /** - * The index of the execution that completed this query. - * - *

0 represents the initial, normal execution of the query, 1 the first speculative execution, - * etc. - * - * @see SpeculativeExecutionPolicy - */ - int getSuccessfulExecutionIndex(); - - /** - * The errors encountered on previous coordinators, if any. - * - *

The list is in chronological order, based on the time that the driver processed the error - * responses. If speculative executions are enabled, they run concurrently so their errors will be - * interleaved. A node can appear multiple times (if the retry policy decided to retry on the same - * node). - */ - List> getErrors(); - - /** - * The server-side warnings for this query, if any (otherwise the list will be empty). - * - *

This feature is only available with {@link DefaultProtocolVersion#V4} or above; with lower - * versions, this list will always be empty. - */ - List getWarnings(); - - /** - * The custom payload sent back by the server with the response, if any (otherwise the map will be - * empty). - * - *

This method returns a read-only view of the original map, but its values remain inherently - * mutable. If multiple clients will read these values, care should be taken not to corrupt the - * data (in particular, preserve the indices by calling {@link ByteBuffer#duplicate()}). - * - *

This feature is only available with {@link DefaultProtocolVersion#V4} or above; with lower - * versions, this map will always be empty. - */ - Map getIncomingPayload(); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphNode.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphNode.java deleted file mode 100644 index 97d48a6b04d..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphNode.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.apache.tinkerpop.gremlin.process.traversal.Path; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Property; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; - -/** - * A node in a tree-like structure representing a Graph or a Graph component. - * - *

It can be: - * - *

    - *
  • a scalar value of a primitive type (boolean, string, int, long, double); - *
  • a graph element (vertex, edge, path or property); - *
  • a list of nodes; - *
  • a set of nodes; - *
  • a map of nodes. - *
- * - * This interface provides test methods to find out what a node represents, and conversion methods - * to cast it to a particular Java type. Two generic methods {@link #as(Class)} and {@link - * #as(GenericType)} can produce any arbitrary Java type, provided that the underlying serialization - * runtime has been correctly configured to support the requested conversion. - */ -public interface GraphNode { - - /** Whether this node represents a {@code null} value. */ - boolean isNull(); - - /** - * Returns {@code true} if this node is a {@link Map}, and {@code false} otherwise. - * - *

If this method returns {@code true}, you can convert this node with {@link #asMap()}, or use - * {@link #keys()} and {@link #getByKey(Object)} to access the individual fields (note that - * entries are not ordered, so {@link #getByIndex(int)} does not work). - */ - boolean isMap(); - - /** The keys of this map node, or an empty iterator if it is not a map. */ - Iterable keys(); - - /** - * Returns the value for the given key as a node. - * - *

If this node is not a map, or does not contain the specified key, {@code null} is returned. - * - *

If the property value has been explicitly set to {@code null}, implementors may return a - * special "null node" instead of {@code null}. - */ - GraphNode getByKey(Object key); - - /** Deserializes and returns this node as a {@link Map}. */ - Map asMap(); - - /** - * Returns {@code true} if this node is a {@link List}, and {@code false} otherwise. - * - *

If this method returns {@code true}, you can convert this node with {@link #asList()}, or - * use {@link #size()} and {@link #getByIndex(int)} to access the individual fields. - */ - boolean isList(); - - /** The size of the current node, if it is a list or map, or {@code 0} otherwise. */ - int size(); - - /** - * Returns the element at the given index as a node. - * - *

If this node is not a list, or {@code index} is out of bounds (i.e. less than zero or {@code - * >= size()}, {@code null} is returned; no exception will be thrown. - * - *

If the requested element has been explicitly set to {@code null}, implementors may return a - * special "null node" instead of {@code null}. - */ - GraphNode getByIndex(int index); - - /** Deserializes and returns this node as a {@link List}. */ - List asList(); - - /** - * Returns {@code true} if this node is a simple scalar value, (i.e., string, boolean or number), - * and {@code false} otherwise. - * - *

If this method returns {@code true}, you can convert this node with {@link #asString()}, - * {@link #asBoolean()}, {@link #asInt()}, {@link #asLong()} or {@link #asDouble()}. - */ - boolean isValue(); - - /** - * Returns this node as an integer. - * - *

If the underlying object is not convertible to integer, implementors may choose to either - * throw {@link ClassCastException} or return [null | empty | some default value], whichever is - * deemed more appropriate. - */ - int asInt(); - - /** - * Returns this node as a boolean. - * - *

If the underlying object is not convertible to boolean, implementors may choose to either - * throw {@link ClassCastException} or return [null | empty | some default value], whichever is - * deemed more appropriate. - */ - boolean asBoolean(); - - /** - * Returns this node as a long integer. - * - *

If the underlying object is not convertible to long, implementors may choose to either throw - * {@link ClassCastException} or return [null | empty | some default value], whichever is deemed - * more appropriate. - */ - long asLong(); - - /** - * Returns this node as a long integer. - * - *

If the underlying object is not convertible to double, implementors may choose to either - * throw {@link ClassCastException} or return [null | empty | some default value], whichever is - * deemed more appropriate. - */ - double asDouble(); - - /** - * A valid string representation of this node. - * - *

If the underlying object is not convertible to a string, implementors may choose to either - * throw {@link ClassCastException} or return an empty string, whichever is deemed more - * appropriate. - */ - String asString(); - - /** - * Deserializes and returns this node as an instance of {@code clazz}. - * - *

Before attempting such a conversion, there must be an appropriate converter configured on - * the underlying serialization runtime. - */ - ResultT as(Class clazz); - - /** - * Deserializes and returns this node as an instance of the given {@link GenericType type}. - * - *

Before attempting such a conversion, there must be an appropriate converter configured on - * the underlying serialization runtime. - */ - ResultT as(GenericType type); - - /** - * Returns {@code true} if this node is a {@link Vertex}, and {@code false} otherwise. - * - *

If this method returns {@code true}, then {@link #asVertex()} can be safely called. - */ - boolean isVertex(); - - /** Returns this node as a Tinkerpop {@link Vertex}. */ - Vertex asVertex(); - - /** - * Returns {@code true} if this node is a {@link Edge}, and {@code false} otherwise. - * - *

If this method returns {@code true}, then {@link #asEdge()} can be safely called. - */ - boolean isEdge(); - - /** Returns this node as a Tinkerpop {@link Edge}. */ - Edge asEdge(); - - /** - * Returns {@code true} if this node is a {@link Path}, and {@code false} otherwise. - * - *

If this method returns {@code true}, then {@link #asPath()} can be safely called. - */ - boolean isPath(); - - /** Returns this node as a Tinkerpop {@link Path}. */ - Path asPath(); - - /** - * Returns {@code true} if this node is a {@link Property}, and {@code false} otherwise. - * - *

If this method returns {@code true}, then {@link #asProperty()} can be safely called. - */ - boolean isProperty(); - - /** Returns this node as a Tinkerpop {@link Property}. */ - Property asProperty(); - - /** - * Returns {@code true} if this node is a {@link VertexProperty}, and {@code false} otherwise. - * - *

If this method returns {@code true}, then {@link #asVertexProperty()} ()} can be safely - * called. - */ - boolean isVertexProperty(); - - /** Returns this node as a Tinkerpop {@link VertexProperty}. */ - VertexProperty asVertexProperty(); - - /** - * Returns {@code true} if this node is a {@link Set}, and {@code false} otherwise. - * - *

If this method returns {@code true}, you can convert this node with {@link #asSet()}, or use - * {@link #size()}. - */ - boolean isSet(); - - /** Deserializes and returns this node as a {@link Set}. */ - Set asSet(); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphResultSet.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphResultSet.java deleted file mode 100644 index d9c8d8fa460..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphResultSet.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.dse.driver.internal.core.graph.GraphExecutionInfoConverter; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -/** - * The result of a synchronous Graph query. - * - *

This object is a container for {@link GraphNode} objects that will contain the data returned - * by Graph queries. - * - *

Note that this object can only be iterated once: items are "consumed" as they are read, - * subsequent calls to {@code iterator()} will return the same iterator instance. - * - *

The default implementation returned by the driver is not thread-safe. It can only be - * iterated by the thread that invoked {@code dseSession.execute}. - * - * @see GraphNode - * @see GraphSession#execute(GraphStatement) - */ -public interface GraphResultSet extends Iterable { - - /** - * Returns the next node, or {@code null} if the result set is exhausted. - * - *

This is convenient for queries that are known to return exactly one row, for example count - * queries. - */ - @Nullable - default GraphNode one() { - Iterator graphNodeIterator = iterator(); - return graphNodeIterator.hasNext() ? graphNodeIterator.next() : null; - } - - /** - * Returns all the remaining nodes as a list; not recommended for paginated queries that return - * a large number of nodes. - * - *

At this time (DSE 6.0.0), graph queries are not paginated and the server sends all the - * results at once. - */ - @NonNull - default List all() { - if (!iterator().hasNext()) { - return Collections.emptyList(); - } - return ImmutableList.copyOf(this); - } - - /** - * Cancels the query and asks the server to stop sending results. - * - *

At this time (DSE 6.0.0), graph queries are not paginated and the server sends all the - * results at once; therefore this method has no effect. - */ - void cancel(); - - /** - * The execution information for the query that have been performed to assemble this result set. - */ - @NonNull - default ExecutionInfo getRequestExecutionInfo() { - return GraphExecutionInfoConverter.convert(getExecutionInfo()); - } - - /** @deprecated Use {@link #getRequestExecutionInfo()} instead. */ - @Deprecated - @NonNull - com.datastax.dse.driver.api.core.graph.GraphExecutionInfo getExecutionInfo(); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphSession.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphSession.java deleted file mode 100644 index b985bc56353..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphSession.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.session.Session; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Objects; -import java.util.concurrent.CompletionStage; - -/** - * A session that has the ability to execute DSE Graph requests. - * - *

Generally this interface won't be referenced directly in an application; instead, you should - * use {@link CqlSession}, which is a combination of this interface and many others for a more - * integrated usage of DataStax Enterprise's multi-model database via a single entry point. However, - * it is still possible to cast a {@code CqlSession} to a {@code GraphSession} to only expose the - * DSE Graph execution methods. - */ -public interface GraphSession extends Session { - - /** - * Executes a graph statement synchronously (the calling thread blocks until the result becomes - * available). - * - *

The driver provides different kinds of graph statements: - * - *

    - *
  • {@link FluentGraphStatement} (recommended): wraps a fluent TinkerPop {@linkplain - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal traversal}; - *
  • {@link BatchGraphStatement}: groups together multiple mutating traversals ({@code - * g.addV()/g.addE()}) inside a single transaction and avoids multiple client-server - * round-trips. Improves performance in data ingestion scenarios; - *
  • {@link ScriptGraphStatement}: wraps a Gremlin-groovy script provided as a plain Java - * string. Required for administrative queries such as creating/dropping a graph, - * configuration and schema. - *
- * - *

This feature is only available with DataStax Enterprise. Executing graph queries against an - * Apache Cassandra® cluster will result in a runtime error. - * - * @see GraphResultSet - * @param graphStatement the graph query to execute (that can be any {@code GraphStatement}). - * @return the result of the graph query. That result will never be null but can be empty. - */ - @NonNull - default GraphResultSet execute(@NonNull GraphStatement graphStatement) { - return Objects.requireNonNull( - execute(graphStatement, GraphStatement.SYNC), - "The graph processor should never return a null result"); - } - - /** - * Executes a graph statement asynchronously (the call returns as soon as the statement was sent, - * generally before the result is available). - * - *

This feature is only available with DataStax Enterprise. Executing graph queries against an - * Apache Cassandra® cluster will result in a runtime error. - * - * @see #execute(GraphStatement) - * @see AsyncGraphResultSet - * @param graphStatement the graph query to execute (that can be any {@code GraphStatement}). - * @return the {@code CompletionStage} on the result of the graph query. - */ - @NonNull - default CompletionStage executeAsync( - @NonNull GraphStatement graphStatement) { - return Objects.requireNonNull( - execute(graphStatement, GraphStatement.ASYNC), - "The graph processor should never return a null result"); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphStatement.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphStatement.java deleted file mode 100644 index f770469b824..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphStatement.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.api.core.ConsistencyLevel; -import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.NoNodeAvailableException; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.loadbalancing.LoadBalancingPolicy; -import com.datastax.oss.driver.api.core.loadbalancing.NodeDistance; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.metadata.token.Token; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.api.core.session.Session; -import com.datastax.oss.driver.api.core.specex.SpeculativeExecutionPolicy; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import edu.umd.cs.findbugs.annotations.CheckReturnValue; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.Map; -import java.util.concurrent.CompletionStage; - -/** - * A request to execute a DSE Graph query. - * - * @param the "self type" used for covariant returns in subtypes. - */ -public interface GraphStatement> extends Request { - - /** - * The type returned when a graph statement is executed synchronously. - * - *

Most users won't use this explicitly. It is needed for the generic execute method ({@link - * Session#execute(Request, GenericType)}), but graph statements will generally be run with one of - * the DSE driver's built-in helper methods (such as {@link CqlSession#execute(GraphStatement)}). - */ - GenericType SYNC = GenericType.of(GraphResultSet.class); - - /** - * The type returned when a graph statement is executed asynchronously. - * - *

Most users won't use this explicitly. It is needed for the generic execute method ({@link - * Session#execute(Request, GenericType)}), but graph statements will generally be run with one of - * the DSE driver's built-in helper methods (such as {@link - * CqlSession#executeAsync(GraphStatement)}). - */ - GenericType> ASYNC = - new GenericType>() {}; - - /** - * Set the idempotence to use for execution. - * - *

Idempotence defines whether it will be possible to speculatively re-execute the statement, - * based on a {@link SpeculativeExecutionPolicy}. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * - * @param idempotent a boolean instance to set a statement-specific value, or {@code null} to use - * the default idempotence defined in the configuration. - */ - @NonNull - @CheckReturnValue - SelfT setIdempotent(@Nullable Boolean idempotent); - - /** - * {@inheritDoc} - * - *

Note that, if this method returns {@code null}, graph statements fall back to a dedicated - * configuration option: {@code basic.graph.timeout}. See {@code reference.conf} in the DSE driver - * distribution for more details. - */ - @Nullable - @Override - Duration getTimeout(); - - /** - * Sets how long to wait for this request to complete. This is a global limit on the duration of a - * session.execute() call, including any retries the driver might do. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * - * @param newTimeout the timeout to use, or {@code null} to use the default value defined in the - * configuration. - * @see #getTimeout() - */ - @NonNull - @CheckReturnValue - SelfT setTimeout(@Nullable Duration newTimeout); - - /** - * Sets the {@link Node} that should handle this query. - * - *

In the general case, use of this method is heavily discouraged and should only be - * used in specific cases, such as applying a series of schema changes, which may be advantageous - * to execute in sequence on the same node. - * - *

Configuring a specific node causes the configured {@link LoadBalancingPolicy} to be - * completely bypassed. However, if the load balancing policy dictates that the node is at - * distance {@link NodeDistance#IGNORED} or there is no active connectivity to the node, the - * request will fail with a {@link NoNodeAvailableException}. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * - * @param newNode The node that should be used to handle executions of this statement or null to - * delegate to the configured load balancing policy. - */ - @NonNull - @CheckReturnValue - SelfT setNode(@Nullable Node newNode); - - /** - * Get the timestamp set on the statement. - * - *

By default, if left unset, the value returned by this is {@code Long.MIN_VALUE}, which means - * that the timestamp will be set via the Timestamp Generator. - * - * @return the timestamp set on this statement. - */ - long getTimestamp(); - - /** - * Set the timestamp to use for execution. - * - *

By default the timestamp generator (see reference config file) will be used for timestamps, - * unless set explicitly via this method. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - */ - @CheckReturnValue - SelfT setTimestamp(long timestamp); - - /** - * Sets the configuration profile to use for execution. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - */ - @NonNull - @CheckReturnValue - SelfT setExecutionProfile(@Nullable DriverExecutionProfile executionProfile); - - /** - * Sets the name of the driver configuration profile that will be used for execution. - * - *

For all the driver's built-in implementations, this method has no effect if {@link - * #setExecutionProfile} has been called with a non-null argument. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - */ - @NonNull - @CheckReturnValue - SelfT setExecutionProfileName(@Nullable String name); - - /** - * Sets the custom payload to use for execution. - * - *

This is intended for advanced use cases, such as tools with very advanced knowledge of DSE - * Graph, and reserved for internal settings like transaction settings. Note that the driver also - * adds graph-related options to the payload, in addition to the ones provided here; it won't - * override any option that is already present. - * - *

All the driver's built-in statement implementations are immutable, and return a new instance - * from this method. However custom implementations may choose to be mutable and return the same - * instance. - * - *

Note that it's your responsibility to provide a thread-safe map. This can be achieved with a - * concurrent or immutable implementation, or by making it effectively immutable (meaning that - * it's never modified after being set on the statement). - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - */ - @NonNull - @CheckReturnValue - SelfT setCustomPayload(@NonNull Map newCustomPayload); - - /** - * The name of the graph to use for this statement. - * - *

This is the programmatic equivalent of the configuration option {@code basic.graph.name}, - * and takes precedence over it. That is, if this property is non-null, then the configuration - * will be ignored. - */ - @Nullable - String getGraphName(); - - /** - * Sets the graph name. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * - * @see #getGraphName() - */ - @NonNull - @CheckReturnValue - SelfT setGraphName(@Nullable String newGraphName); - - /** - * The name of the traversal source to use for this statement. - * - *

This is the programmatic equivalent of the configuration option {@code - * basic.graph.traversal-source}, and takes precedence over it. That is, if this property is - * non-null, then the configuration will be ignored. - */ - @Nullable - String getTraversalSource(); - - /** - * Sets the traversal source. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * - * @see #getTraversalSource() - */ - @NonNull - @CheckReturnValue - SelfT setTraversalSource(@Nullable String newTraversalSource); - - /** - * The DSE graph sub-protocol to use for this statement. - * - *

This is the programmatic equivalent of the configuration option {@code - * advanced.graph.sub-protocol}, and takes precedence over it. That is, if this property is - * non-null, then the configuration will be ignored. - */ - @Nullable - String getSubProtocol(); - - /** - * Sets the sub-protocol. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * - * @see #getSubProtocol() - */ - @NonNull - @CheckReturnValue - SelfT setSubProtocol(@Nullable String newSubProtocol); - - /** - * Returns the consistency level to use for the statement. - * - *

This is the programmatic equivalent of the configuration option {@code - * basic.request.consistency}, and takes precedence over it. That is, if this property is - * non-null, then the configuration will be ignored. - */ - @Nullable - ConsistencyLevel getConsistencyLevel(); - - /** - * Sets the consistency level to use for this statement. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * - * @param newConsistencyLevel the consistency level to use, or null to use the default value - * defined in the configuration. - * @see #getConsistencyLevel() - */ - @CheckReturnValue - SelfT setConsistencyLevel(@Nullable ConsistencyLevel newConsistencyLevel); - - /** - * The consistency level to use for the internal read queries that will be produced by this - * statement. - * - *

This is the programmatic equivalent of the configuration option {@code - * basic.graph.read-consistency-level}, and takes precedence over it. That is, if this property is - * non-null, then the configuration will be ignored. - * - *

If this property isn't set here or in the configuration, the default consistency level will - * be used ({@link #getConsistencyLevel()} or {@code basic.request.consistency}). - */ - @Nullable - ConsistencyLevel getReadConsistencyLevel(); - - /** - * Sets the read consistency level. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * - * @see #getReadConsistencyLevel() - */ - @NonNull - @CheckReturnValue - SelfT setReadConsistencyLevel(@Nullable ConsistencyLevel newReadConsistencyLevel); - - /** - * The consistency level to use for the internal write queries that will be produced by this - * statement. - * - *

This is the programmatic equivalent of the configuration option {@code - * basic.graph.write-consistency-level}, and takes precedence over it. That is, if this property - * is non-null, then the configuration will be ignored. - * - *

If this property isn't set here or in the configuration, the default consistency level will - * be used ({@link #getConsistencyLevel()} or {@code basic.request.consistency}). - */ - @Nullable - ConsistencyLevel getWriteConsistencyLevel(); - - /** - * Sets the write consistency level. - * - *

All the driver's built-in implementations are immutable, and return a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * - * @see #getWriteConsistencyLevel() - */ - @NonNull - @CheckReturnValue - SelfT setWriteConsistencyLevel(@Nullable ConsistencyLevel newWriteConsistencyLevel); - - /** Graph statements do not have a per-query keyspace, this method always returns {@code null}. */ - @Nullable - @Override - default CqlIdentifier getKeyspace() { - return null; - } - - /** Graph statements can't be routed, this method always returns {@code null}. */ - @Nullable - @Override - default CqlIdentifier getRoutingKeyspace() { - return null; - } - - /** Graph statements can't be routed, this method always returns {@code null}. */ - @Nullable - @Override - default ByteBuffer getRoutingKey() { - return null; - } - - /** Graph statements can't be routed, this method always returns {@code null}. */ - @Nullable - @Override - default Token getRoutingToken() { - return null; - } - - /** - * Whether tracing information should be recorded for this statement. - * - *

This method is only exposed for future extensibility. At the time of writing, graph - * statements do not support tracing, and this always returns {@code false}. - */ - default boolean isTracing() { - return false; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphStatementBuilderBase.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphStatementBuilderBase.java deleted file mode 100644 index 5cb48613cf5..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/GraphStatementBuilderBase.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.api.core.ConsistencyLevel; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.protocol.internal.util.collection.NullAllowingImmutableMap; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.Map; -import net.jcip.annotations.NotThreadSafe; - -@NotThreadSafe -public abstract class GraphStatementBuilderBase< - SelfT extends GraphStatementBuilderBase, - StatementT extends GraphStatement> { - - @SuppressWarnings({"unchecked"}) - private final SelfT self = (SelfT) this; - - protected Boolean isIdempotent; - protected Duration timeout; - protected Node node; - protected long timestamp = Statement.NO_DEFAULT_TIMESTAMP; - protected DriverExecutionProfile executionProfile; - protected String executionProfileName; - private NullAllowingImmutableMap.Builder customPayloadBuilder; - protected String graphName; - protected String traversalSource; - protected String subProtocol; - protected ConsistencyLevel consistencyLevel; - protected ConsistencyLevel readConsistencyLevel; - protected ConsistencyLevel writeConsistencyLevel; - - protected GraphStatementBuilderBase() { - // nothing to do - } - - protected GraphStatementBuilderBase(StatementT template) { - this.isIdempotent = template.isIdempotent(); - this.timeout = template.getTimeout(); - this.node = template.getNode(); - this.timestamp = template.getTimestamp(); - this.executionProfile = template.getExecutionProfile(); - this.executionProfileName = template.getExecutionProfileName(); - if (!template.getCustomPayload().isEmpty()) { - this.customPayloadBuilder = - NullAllowingImmutableMap.builder() - .putAll(template.getCustomPayload()); - } - this.graphName = template.getGraphName(); - this.traversalSource = template.getTraversalSource(); - this.subProtocol = template.getSubProtocol(); - this.consistencyLevel = template.getConsistencyLevel(); - this.readConsistencyLevel = template.getReadConsistencyLevel(); - this.writeConsistencyLevel = template.getWriteConsistencyLevel(); - } - - /** @see GraphStatement#setIdempotent(Boolean) */ - @NonNull - public SelfT setIdempotence(@Nullable Boolean idempotent) { - this.isIdempotent = idempotent; - return self; - } - - /** @see GraphStatement#setTimeout(Duration) */ - @NonNull - public SelfT setTimeout(@Nullable Duration timeout) { - this.timeout = timeout; - return self; - } - - /** @see GraphStatement#setNode(Node) */ - @NonNull - public SelfT setNode(@Nullable Node node) { - this.node = node; - return self; - } - - /** @see GraphStatement#setTimestamp(long) */ - @NonNull - public SelfT setTimestamp(long timestamp) { - this.timestamp = timestamp; - return self; - } - - /** @see GraphStatement#setExecutionProfileName(String) */ - @NonNull - public SelfT setExecutionProfileName(@Nullable String executionProfileName) { - this.executionProfileName = executionProfileName; - return self; - } - - /** @see GraphStatement#setExecutionProfile(DriverExecutionProfile) */ - @NonNull - public SelfT setExecutionProfile(@Nullable DriverExecutionProfile executionProfile) { - this.executionProfile = executionProfile; - this.executionProfileName = null; - return self; - } - - /** @see GraphStatement#setCustomPayload(Map) */ - @NonNull - public SelfT addCustomPayload(@NonNull String key, @Nullable ByteBuffer value) { - if (customPayloadBuilder == null) { - customPayloadBuilder = NullAllowingImmutableMap.builder(); - } - customPayloadBuilder.put(key, value); - return self; - } - - /** @see GraphStatement#setCustomPayload(Map) */ - @NonNull - public SelfT clearCustomPayload() { - customPayloadBuilder = null; - return self; - } - - /** @see GraphStatement#setGraphName(String) */ - @NonNull - public SelfT setGraphName(@Nullable String graphName) { - this.graphName = graphName; - return self; - } - - /** @see GraphStatement#setTraversalSource(String) */ - @NonNull - public SelfT setTraversalSource(@Nullable String traversalSource) { - this.traversalSource = traversalSource; - return self; - } - - /** @see GraphStatement#setSubProtocol(String) */ - @NonNull - public SelfT setSubProtocol(@Nullable String subProtocol) { - this.subProtocol = subProtocol; - return self; - } - - /** @see GraphStatement#setConsistencyLevel(ConsistencyLevel) */ - @NonNull - public SelfT setConsistencyLevel(@Nullable ConsistencyLevel consistencyLevel) { - this.consistencyLevel = consistencyLevel; - return self; - } - - /** @see GraphStatement#setReadConsistencyLevel(ConsistencyLevel) */ - @NonNull - public SelfT setReadConsistencyLevel(@Nullable ConsistencyLevel readConsistencyLevel) { - this.readConsistencyLevel = readConsistencyLevel; - return self; - } - - /** @see GraphStatement#setWriteConsistencyLevel(ConsistencyLevel) */ - @NonNull - public SelfT setWriteConsistencyLevel(@Nullable ConsistencyLevel writeConsistencyLevel) { - this.writeConsistencyLevel = writeConsistencyLevel; - return self; - } - - @NonNull - protected Map buildCustomPayload() { - return (customPayloadBuilder == null) - ? NullAllowingImmutableMap.of() - : customPayloadBuilder.build(); - } - - /** Create the statement with the configuration defined by this builder object. */ - @NonNull - public abstract StatementT build(); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/PagingEnabledOptions.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/PagingEnabledOptions.java deleted file mode 100644 index f59d0e50e93..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/PagingEnabledOptions.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -public enum PagingEnabledOptions { - ENABLED, - DISABLED, - AUTO -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/ScriptGraphStatement.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/ScriptGraphStatement.java deleted file mode 100644 index 2ad7aafc232..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/ScriptGraphStatement.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.dse.driver.internal.core.graph.DefaultScriptGraphStatement; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.protocol.internal.util.collection.NullAllowingImmutableMap; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Collections; -import java.util.Map; - -/** - * A graph statement that uses a Gremlin-groovy script the query. - * - *

These statements are generally used for DSE Graph set-up queries, such as creating or dropping - * a graph, or defining a graph schema. For graph traversals, we recommend using {@link - * FluentGraphStatement} instead. To do bulk data ingestion in graph, we recommend using {@link - * BatchGraphStatement} instead. - * - *

Typical usage: - * - *

{@code
- * ScriptGraphStatement statement = ScriptGraphStatement.newInstance("schema.propertyKey('age').Int().create()");
- *
- * GraphResultSet graphResultSet = dseSession.execute(statement);
- * }
- */ -public interface ScriptGraphStatement extends GraphStatement { - - /** Create a new instance from the given script. */ - @NonNull - static ScriptGraphStatement newInstance(@NonNull String script) { - return new DefaultScriptGraphStatement( - script, - NullAllowingImmutableMap.of(), - null, - null, - null, - null, - Statement.NO_DEFAULT_TIMESTAMP, - null, - null, - Collections.emptyMap(), - null, - null, - null, - null, - null, - null); - } - - /** - * Create a builder object to start creating a new instance from the given script. - * - *

Note that this builder is mutable and not thread-safe. - */ - @NonNull - static ScriptGraphStatementBuilder builder(@NonNull String script) { - return new ScriptGraphStatementBuilder(script); - } - - /** - * Create a builder helper object to start creating a new instance with an existing statement as a - * template. The script and options set on the template will be copied for the new statement at - * the moment this method is called. - * - *

Note that this builder is mutable and not thread-safe. - */ - @NonNull - static ScriptGraphStatementBuilder builder(@NonNull ScriptGraphStatement template) { - return new ScriptGraphStatementBuilder(template); - } - - /** The Gremlin-groovy script representing the graph query. */ - @NonNull - String getScript(); - - /** - * Whether the statement is a system query, or {@code null} if it defaults to the value defined in - * the configuration. - * - * @see #setSystemQuery(Boolean) - */ - @Nullable - Boolean isSystemQuery(); - - /** - * Defines if this statement is a system query. - * - *

Script statements that access the {@code system} variable must not specify a graph - * name (otherwise {@code system} is not available). However, if your application executes a lot - * of non-system statements, it is convenient to configure the graph name in your configuration to - * avoid repeating it every time. This method allows you to ignore that global graph name for a - * specific statement. - * - *

This property is the programmatic equivalent of the configuration option {@code - * basic.graph.is-system-query}, and takes precedence over it. That is, if this property is - * non-null, then the configuration will be ignored. - * - *

The driver's built-in implementation is immutable, and returns a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * - * @param newValue {@code true} to mark this statement as a system query (the driver will ignore - * any graph name set on the statement or the configuration); {@code false} to mark it as a - * non-system query; {@code null} to default to the value defined in the configuration. - * @see #isSystemQuery() - */ - @NonNull - ScriptGraphStatement setSystemQuery(@Nullable Boolean newValue); - - /** - * The query parameters to send along the request. - * - * @see #setQueryParam(String, Object) - */ - @NonNull - Map getQueryParams(); - - /** - * Set a value for a parameter defined in the Groovy script. - * - *

The script engine in the DSE Graph server allows to define parameters in a Groovy script and - * set the values of these parameters as a binding. Defining parameters allows to re-use scripts - * and only change their parameters values, which improves the performance of the script executed, - * so defining parameters is encouraged; however, for optimal Graph traversal performance, we - * recommend either using {@link BatchGraphStatement}s for data ingestion, or {@link - * FluentGraphStatement} for normal traversals. - * - *

Parameters in a Groovy script are always named; unlike CQL, they are not prefixed by a - * column ({@code :}). - * - *

The driver's built-in implementation is immutable, and returns a new instance from this - * method. However custom implementations may choose to be mutable and return the same instance. - * If many parameters are to be set in a query, it is recommended to create the statement with - * {@link #builder(String)} instead. - * - * @param name the name of the parameter defined in the script. If the statement already had a - * binding for this name, it gets replaced. - * @param value the value that will be transmitted with the request. - */ - @NonNull - ScriptGraphStatement setQueryParam(@NonNull String name, @Nullable Object value); - - /** - * Removes a binding for the given name from this statement. - * - *

If the statement did not have such a binding, this method has no effect and returns the same - * statement instance. Otherwise, the driver's built-in implementation returns a new instance - * (however custom implementations may choose to be mutable and return the same instance). - * - * @see #setQueryParam(String, Object) - */ - @NonNull - ScriptGraphStatement removeQueryParam(@NonNull String name); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/ScriptGraphStatementBuilder.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/ScriptGraphStatementBuilder.java deleted file mode 100644 index 1985c58955f..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/ScriptGraphStatementBuilder.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.dse.driver.internal.core.graph.DefaultScriptGraphStatement; -import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; -import com.datastax.oss.driver.shaded.guava.common.collect.Maps; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Map; -import net.jcip.annotations.NotThreadSafe; - -/** - * A builder to create a script graph statement. - * - *

This class is mutable and not thread-safe. - */ -@NotThreadSafe -public class ScriptGraphStatementBuilder - extends GraphStatementBuilderBase { - - private String script; - private Boolean isSystemQuery; - private final Map queryParams; - - public ScriptGraphStatementBuilder() { - this.queryParams = Maps.newHashMap(); - } - - public ScriptGraphStatementBuilder(String script) { - this.script = script; - this.queryParams = Maps.newHashMap(); - } - - public ScriptGraphStatementBuilder(ScriptGraphStatement template) { - super(template); - this.script = template.getScript(); - this.queryParams = Maps.newHashMap(template.getQueryParams()); - this.isSystemQuery = template.isSystemQuery(); - } - - @NonNull - public ScriptGraphStatementBuilder setScript(@NonNull String script) { - this.script = script; - return this; - } - - /** @see ScriptGraphStatement#isSystemQuery() */ - @NonNull - public ScriptGraphStatementBuilder setSystemQuery(@Nullable Boolean isSystemQuery) { - this.isSystemQuery = isSystemQuery; - return this; - } - - /** - * Set a value for a parameter defined in the script query. - * - * @see ScriptGraphStatement#setQueryParam(String, Object) - */ - @NonNull - public ScriptGraphStatementBuilder setQueryParam(@NonNull String name, @Nullable Object value) { - this.queryParams.put(name, value); - return this; - } - - /** - * Set multiple values for named parameters defined in the script query. - * - * @see ScriptGraphStatement#setQueryParam(String, Object) - */ - @NonNull - public ScriptGraphStatementBuilder setQueryParams(@NonNull Map params) { - this.queryParams.putAll(params); - return this; - } - - /** - * Removes a parameter. - * - *

This is useful if the builder was {@linkplain - * ScriptGraphStatement#builder(ScriptGraphStatement) initialized with a template statement} that - * has more parameters than desired. - * - * @see ScriptGraphStatement#setQueryParam(String, Object) - * @see #clearQueryParams() - */ - @NonNull - public ScriptGraphStatementBuilder removeQueryParam(@NonNull String name) { - this.queryParams.remove(name); - return this; - } - - /** Clears all the parameters previously added to this builder. */ - public ScriptGraphStatementBuilder clearQueryParams() { - this.queryParams.clear(); - return this; - } - - @NonNull - @Override - public ScriptGraphStatement build() { - Preconditions.checkNotNull(this.script, "Script hasn't been defined in this builder."); - return new DefaultScriptGraphStatement( - this.script, - this.queryParams, - this.isSystemQuery, - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - buildCustomPayload(), - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/CqlCollection.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/CqlCollection.java deleted file mode 100644 index fdbf3fbe397..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/CqlCollection.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.predicates; - -import com.datastax.dse.driver.internal.core.graph.CqlCollectionPredicate; -import java.util.Collection; -import java.util.Map; -import org.apache.tinkerpop.gremlin.process.traversal.P; -import org.javatuples.Pair; - -/** - * Predicates that can be used on CQL collections (lists, sets and maps). - * - *

Note: CQL collection predicates are only available when using the binary subprotocol. - */ -public class CqlCollection { - - /** - * Checks if the target collection contains the given value. - * - * @param value the value to look for; cannot be {@code null}. - * @return a predicate to apply in a {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal}. - */ - @SuppressWarnings("unchecked") - public static , V> P contains(V value) { - return new P(CqlCollectionPredicate.contains, value); - } - - /** - * Checks if the target map contains the given key. - * - * @param key the key to look for; cannot be {@code null}. - * @return a predicate to apply in a {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal}. - */ - @SuppressWarnings("unchecked") - public static , K> P containsKey(K key) { - return new P(CqlCollectionPredicate.containsKey, key); - } - - /** - * Checks if the target map contains the given value. - * - * @param value the value to look for; cannot be {@code null}. - * @return a predicate to apply in a {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal}. - */ - @SuppressWarnings("unchecked") - public static , V> P containsValue(V value) { - return new P(CqlCollectionPredicate.containsValue, value); - } - - /** - * Checks if the target map contains the given entry. - * - * @param key the key to look for; cannot be {@code null}. - * @param value the value to look for; cannot be {@code null}. - * @return a predicate to apply in a {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal}. - */ - @SuppressWarnings("unchecked") - public static , K, V> P entryEq(K key, V value) { - return new P(CqlCollectionPredicate.entryEq, new Pair<>(key, value)); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/Geo.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/Geo.java deleted file mode 100644 index 65dd84d0076..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/Geo.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.predicates; - -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import com.datastax.dse.driver.internal.core.data.geometry.Distance; -import com.datastax.dse.driver.internal.core.graph.GeoPredicate; -import com.datastax.dse.driver.internal.core.graph.GeoUtils; -import edu.umd.cs.findbugs.annotations.NonNull; -import org.apache.tinkerpop.gremlin.process.traversal.P; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; - -public interface Geo { - - enum Unit { - MILES(GeoUtils.MILES_TO_KM * GeoUtils.KM_TO_DEG), - KILOMETERS(GeoUtils.KM_TO_DEG), - METERS(GeoUtils.KM_TO_DEG / 1000.0), - DEGREES(1); - - private final double multiplier; - - Unit(double multiplier) { - this.multiplier = multiplier; - } - - /** Convert distance to degrees (used internally only). */ - public double toDegrees(double distance) { - return distance * multiplier; - } - } - - /** - * Finds whether an entity is inside the given circular area using a geo coordinate system. - * - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P inside(Point center, double radius, Unit units) { - return new P<>(GeoPredicate.inside, new Distance(center, units.toDegrees(radius))); - } - - /** - * Finds whether an entity is inside the given circular area using a cartesian coordinate system. - * - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P inside(Point center, double radius) { - return new P<>(GeoPredicate.insideCartesian, new Distance(center, radius)); - } - - /** - * Finds whether an entity is inside the given polygon. - * - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P inside(Polygon polygon) { - return new P<>(GeoPredicate.insideCartesian, polygon); - } - - /** - * Creates a point from the given coordinates. - * - *

This is just a shortcut to {@link Point#fromCoordinates(double, double)}. It is duplicated - * here so that {@code Geo} can be used as a single entry point in Gremlin-groovy scripts. - */ - @NonNull - static Point point(double x, double y) { - return Point.fromCoordinates(x, y); - } - - /** - * Creates a line string from the given (at least 2) points. - * - *

This is just a shortcut to {@link LineString#fromPoints(Point, Point, Point...)}. It is - * duplicated here so that {@code Geo} can be used as a single entry point in Gremlin-groovy - * scripts. - */ - @NonNull - static LineString lineString( - @NonNull Point point1, @NonNull Point point2, @NonNull Point... otherPoints) { - return LineString.fromPoints(point1, point2, otherPoints); - } - - /** - * Creates a line string from the coordinates of its points. - * - *

This is provided for backward compatibility with previous DSE versions. We recommend {@link - * #lineString(Point, Point, Point...)} instead. - */ - @NonNull - static LineString lineString(double... coordinates) { - if (coordinates.length % 2 != 0) { - throw new IllegalArgumentException("lineString() must be passed an even number of arguments"); - } else if (coordinates.length < 4) { - throw new IllegalArgumentException( - "lineString() must be passed at least 4 arguments (2 points)"); - } - Point point1 = Point.fromCoordinates(coordinates[0], coordinates[1]); - Point point2 = Point.fromCoordinates(coordinates[2], coordinates[3]); - Point[] otherPoints = new Point[coordinates.length / 2 - 2]; - for (int i = 4; i < coordinates.length; i += 2) { - otherPoints[i / 2 - 2] = Point.fromCoordinates(coordinates[i], coordinates[i + 1]); - } - return LineString.fromPoints(point1, point2, otherPoints); - } - - /** - * Creates a polygon from the given (at least 3) points. - * - *

This is just a shortcut to {@link Polygon#fromPoints(Point, Point, Point, Point...)}. It is - * duplicated here so that {@code Geo} can be used as a single entry point in Gremlin-groovy - * scripts. - */ - @NonNull - static Polygon polygon( - @NonNull Point p1, @NonNull Point p2, @NonNull Point p3, @NonNull Point... otherPoints) { - return Polygon.fromPoints(p1, p2, p3, otherPoints); - } - - /** - * Creates a polygon from the coordinates of its points. - * - *

This is provided for backward compatibility with previous DSE versions. We recommend {@link - * #polygon(Point, Point, Point, Point...)} instead. - */ - @NonNull - static Polygon polygon(double... coordinates) { - if (coordinates.length % 2 != 0) { - throw new IllegalArgumentException("polygon() must be passed an even number of arguments"); - } else if (coordinates.length < 6) { - throw new IllegalArgumentException( - "polygon() must be passed at least 6 arguments (3 points)"); - } - Point point1 = Point.fromCoordinates(coordinates[0], coordinates[1]); - Point point2 = Point.fromCoordinates(coordinates[2], coordinates[3]); - Point point3 = Point.fromCoordinates(coordinates[4], coordinates[5]); - Point[] otherPoints = new Point[coordinates.length / 2 - 3]; - for (int i = 6; i < coordinates.length; i += 2) { - otherPoints[i / 2 - 3] = Point.fromCoordinates(coordinates[i], coordinates[i + 1]); - } - return Polygon.fromPoints(point1, point2, point3, otherPoints); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/Search.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/Search.java deleted file mode 100644 index e285c118c8a..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/predicates/Search.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.predicates; - -import com.datastax.dse.driver.internal.core.graph.EditDistance; -import com.datastax.dse.driver.internal.core.graph.SearchPredicate; -import org.apache.tinkerpop.gremlin.process.traversal.P; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; - -public interface Search { - - /** - * Search any instance of a certain token within the text property targeted (case insensitive). - * - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P token(String value) { - return new P<>(SearchPredicate.token, value); - } - - /** - * Search any instance of a certain token prefix within the text property targeted (case - * insensitive). - * - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P tokenPrefix(String value) { - return new P<>(SearchPredicate.tokenPrefix, value); - } - - /** - * Search any instance of the provided regular expression for the targeted property (case - * insensitive). - * - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P tokenRegex(String value) { - return new P<>(SearchPredicate.tokenRegex, value); - } - - /** - * Search for a specific prefix at the beginning of the text property targeted (case sensitive). - * - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P prefix(String value) { - return new P<>(SearchPredicate.prefix, value); - } - - /** - * Search for this regular expression inside the text property targeted (case sensitive). - * - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P regex(String value) { - return new P<>(SearchPredicate.regex, value); - } - - /** - * Supports finding words which are a within a specific distance away (case insensitive). - * - *

Example: the search expression is {@code phrase("Hello world", 2)} - * - *

    - *
  • the inserted value "Hello world" is found - *
  • the inserted value "Hello wild world" is found - *
  • the inserted value "Hello big wild world" is found - *
  • the inserted value "Hello the big wild world" is not found - *
  • the inserted value "Goodbye world" is not found. - *
- * - * @param query the string to look for in the value - * @param distance the number of terms allowed between two correct terms to find a value. - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P phrase(String query, int distance) { - return new P<>(SearchPredicate.phrase, new EditDistance(query, distance)); - } - - /** - * Supports fuzzy searches based on the Damerau-Levenshtein Distance, or Edit Distance algorithm - * (case sensitive). - * - *

Example: the search expression is {@code fuzzy("david", 1)} - * - *

    - *
  • the inserted value "david" is found - *
  • the inserted value "dawid" is found - *
  • the inserted value "davids" is found - *
  • the inserted value "dewid" is not found - *
- * - * @param query the string to look for in the value - * @param distance the number of "uncertainties" allowed for the Levenshtein algorithm. - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P fuzzy(String query, int distance) { - return new P<>(SearchPredicate.fuzzy, new EditDistance(query, distance)); - } - - /** - * Supports fuzzy searches based on the Damerau-Levenshtein Distance, or Edit Distance algorithm - * after having tokenized the data stored (case insensitive). - * - *

Example: the search expression is {@code tokenFuzzy("david", 1)} - * - *

    - *
  • the inserted value "david" is found - *
  • the inserted value "dawid" is found - *
  • the inserted value "hello-dawid" is found - *
  • the inserted value "dewid" is not found - *
- * - * @param query the string to look for in the value - * @param distance the number of "uncertainties" allowed for the Levenshtein algorithm. - * @return a predicate to apply in a {@link GraphTraversal}. - */ - static P tokenFuzzy(String query, int distance) { - return new P<>(SearchPredicate.tokenFuzzy, new EditDistance(query, distance)); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphNode.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphNode.java deleted file mode 100644 index ad7849633c6..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphNode.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.reactive; - -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import edu.umd.cs.findbugs.annotations.NonNull; - -/** - * A {@link GraphNode} produced by a {@linkplain ReactiveGraphResultSet reactive graph result set}. - * - *

This is essentially an extension of the driver's {@link GraphNode} object that also exposes - * useful information about {@linkplain #getExecutionInfo() request execution} (note however that - * this information is also exposed at result set level for convenience). - * - * @see ReactiveGraphSession - * @see ReactiveGraphResultSet - */ -public interface ReactiveGraphNode extends GraphNode { - - /** - * The execution information for the paged request that produced this result. - * - *

This object is the same for two rows pertaining to the same page, but differs for rows - * pertaining to different pages. - * - * @return the execution information for the paged request that produced this result. - * @see ReactiveGraphResultSet#getExecutionInfos() - */ - @NonNull - ExecutionInfo getExecutionInfo(); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphResultSet.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphResultSet.java deleted file mode 100644 index a0e3231750e..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphResultSet.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.reactive; - -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import edu.umd.cs.findbugs.annotations.NonNull; -import org.reactivestreams.Publisher; - -/** - * A {@link Publisher} of {@link ReactiveGraphNode}s returned by a {@link ReactiveGraphSession}. - * - *

By default, all implementations returned by the driver are cold, unicast, single-subscriber - * only publishers. In other words, they do not support multiple subscriptions; consider - * caching the results produced by such publishers if you need to consume them by more than one - * downstream subscriber. - * - *

Also, note that reactive graph result sets may emit items to their subscribers on an internal - * driver IO thread. Subscriber implementors are encouraged to abide by Reactive Streams - * Specification rule 2.2 and avoid performing heavy computations or blocking calls inside - * {@link org.reactivestreams.Subscriber#onNext(Object) onNext} calls, as doing so could slow down - * the driver and impact performance. Instead, they should asynchronously dispatch received signals - * to their processing logic. - * - *

This interface exists mainly to expose useful information about {@linkplain - * #getExecutionInfos() request execution}. This is particularly convenient for queries that do not - * return rows; for queries that do return rows, it is also possible, and oftentimes easier, to - * access that same information {@linkplain ReactiveGraphNode at node level}. - * - * @see ReactiveGraphSession#executeReactive(GraphStatement) - * @see ReactiveGraphNode - */ -public interface ReactiveGraphResultSet extends Publisher { - - /** - * Returns {@linkplain ExecutionInfo information about the execution} of all requests that have - * been performed so far to assemble this result set. - * - *

If the query is not paged, this publisher will emit exactly one item as soon as the response - * arrives, then complete. If the query is paged, it will emit multiple items, one per page; then - * it will complete when the last page arrives. If the query execution fails, then this publisher - * will fail with the same error. - * - *

By default, publishers returned by this method do not support multiple subscriptions. - * - * @see ReactiveGraphNode#getExecutionInfo() - */ - @NonNull - Publisher getExecutionInfos(); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphSession.java b/core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphSession.java deleted file mode 100644 index 88f0e5def61..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/graph/reactive/ReactiveGraphSession.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.reactive; - -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.internal.core.graph.reactive.ReactiveGraphRequestProcessor; -import com.datastax.oss.driver.api.core.session.Session; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Objects; - -/** - * A {@link Session} that offers utility methods to issue graph queries using reactive-style - * programming. - */ -public interface ReactiveGraphSession extends Session { - - /** - * Returns a {@link ReactiveGraphResultSet} that, once subscribed to, executes the given query and - * emits all the results. - * - *

See the javadocs of {@link ReactiveGraphResultSet} for important remarks anc caveats - * regarding the subscription to and consumption of reactive graph result sets. - * - * @param statement the statement to execute. - * @return The {@link ReactiveGraphResultSet} that will publish the returned results. - * @see ReactiveGraphResultSet - * @see ReactiveGraphNode - */ - @NonNull - default ReactiveGraphResultSet executeReactive(@NonNull GraphStatement statement) { - return Objects.requireNonNull( - execute(statement, ReactiveGraphRequestProcessor.REACTIVE_GRAPH_RESULT_SET)); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseNodeMetric.java b/core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseNodeMetric.java deleted file mode 100644 index cf4b4d0aa18..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseNodeMetric.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.metrics; - -import com.datastax.oss.driver.api.core.metrics.NodeMetric; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Map; - -/** See {@code reference.conf} for a description of each metric. */ -public enum DseNodeMetric implements NodeMetric { - GRAPH_MESSAGES("graph-messages"); - - private static final Map BY_PATH = sortByPath(); - - private final String path; - - DseNodeMetric(String path) { - this.path = path; - } - - @Override - @NonNull - public String getPath() { - return path; - } - - @NonNull - public static DseNodeMetric fromPath(@NonNull String path) { - DseNodeMetric metric = BY_PATH.get(path); - if (metric == null) { - throw new IllegalArgumentException("Unknown node metric path " + path); - } - return metric; - } - - private static Map sortByPath() { - ImmutableMap.Builder result = ImmutableMap.builder(); - for (DseNodeMetric value : values()) { - result.put(value.getPath(), value); - } - return result.build(); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseSessionMetric.java b/core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseSessionMetric.java index 79584f3c44a..1e0358a45cb 100644 --- a/core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseSessionMetric.java +++ b/core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseSessionMetric.java @@ -25,8 +25,6 @@ /** See {@code reference.conf} for a description of each metric. */ public enum DseSessionMetric implements SessionMetric { CONTINUOUS_CQL_REQUESTS("continuous-cql-requests"), - GRAPH_REQUESTS("graph-requests"), - GRAPH_CLIENT_TIMEOUTS("graph-client-timeouts"), ; private static final Map BY_PATH = sortByPath(); diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/data/geometry/Distance.java b/core/src/main/java/com/datastax/dse/driver/internal/core/data/geometry/Distance.java deleted file mode 100644 index 518f6aa1346..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/data/geometry/Distance.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.data.geometry; - -import static java.util.regex.Pattern.CASE_INSENSITIVE; - -import com.datastax.dse.driver.api.core.data.geometry.Geometry; -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import com.datastax.dse.driver.api.core.graph.predicates.Geo; -import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; -import com.esri.core.geometry.MultiPath; -import com.esri.core.geometry.ogc.OGCGeometry; -import com.esri.core.geometry.ogc.OGCPoint; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.nio.ByteBuffer; -import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import net.jcip.annotations.Immutable; - -/** - * The driver-side representation of DSE's {@code Geo.distance}. - * - *

This is a circle in a two-dimensional XY plane represented by its center point and radius. It - * is used as a search criteria to determine whether or not another geospatial object lies within a - * circular area. - * - *

Note that this shape has no equivalent in the OGC and GeoJSON standards: as a consequence, - * {@link #asWellKnownText()} returns a custom format, and {@link #getOgcGeometry()}, {@link - * #asWellKnownBinary()}, and {@link #asGeoJson()} throw {@link UnsupportedOperationException}. - * - *

Unlike other geo types, this class is never exposed directly to driver clients: it is used - * internally by {@linkplain Geo#inside(Point, double) geo predicates}, but cannot be a column type, - * nor appear in CQL or graph results. Therefore it doesn't have a public-facing interface, nor a - * built-in codec. - */ -@Immutable -public class Distance extends DefaultGeometry { - - private static final Pattern WKT_PATTERN = - Pattern.compile( - "distance *\\( *\\( *([\\d\\.-]+) *([\\d+\\.-]+) *\\) *([\\d+\\.-]+) *\\)", - CASE_INSENSITIVE); - - /** - * Creates a distance from its Well-known - * Text (WKT) representation. - * - * @param source the Well-known Text representation to parse. - * @return the point represented by the WKT. - * @throws IllegalArgumentException if the string does not contain a valid Well-known Text - * representation. - * @see Distance#asWellKnownText() - */ - @NonNull - public static Distance fromWellKnownText(@NonNull String source) { - Matcher matcher = WKT_PATTERN.matcher(source.trim()); - if (matcher.matches() && matcher.groupCount() == 3) { - try { - return new Distance( - new DefaultPoint( - Double.parseDouble(matcher.group(1)), Double.parseDouble(matcher.group(2))), - Double.parseDouble(matcher.group(3))); - } catch (NumberFormatException var3) { - throw new IllegalArgumentException(String.format("Unable to parse %s", source)); - } - } else { - throw new IllegalArgumentException(String.format("Unable to parse %s", source)); - } - } - - private final DefaultPoint center; - - private final double radius; - - /** - * Creates a new distance with the given center and radius. - * - * @param center The center point. - * @param radius The radius of the circle representing distance. - */ - public Distance(@NonNull Point center, double radius) { - super(((DefaultPoint) center).getOgcGeometry()); - Preconditions.checkNotNull(center); - Preconditions.checkArgument(radius >= 0.0D, "Radius must be >= 0 (got %s)", radius); - this.center = ((DefaultPoint) center); - this.radius = radius; - } - - /** @return The center point of the circle representing this distance. */ - @NonNull - public Point getCenter() { - return center; - } - - /** @return The radius of the circle representing this distance. */ - public double getRadius() { - return radius; - } - - /** - * Returns a Well-known Text (WKT) - * representation of this geospatial type. - * - *

Since there is no Well-known Text specification for Distance, this returns a custom format - * of: DISTANCE((center.x center.y) radius) - * - * @return a Well-known Text representation of this object. - */ - @NonNull - @Override - public String asWellKnownText() { - return String.format("DISTANCE((%s %s) %s)", this.center.X(), this.center.Y(), this.radius); - } - - /** - * The distance type has no equivalent in the OGC standard: this method throws an {@link - * UnsupportedOperationException}. - */ - @NonNull - @Override - public OGCGeometry getOgcGeometry() { - throw new UnsupportedOperationException(); - } - - /** - * The distance type has no equivalent in the OGC standard: this method throws an {@link - * UnsupportedOperationException}. - */ - @NonNull - @Override - public ByteBuffer asWellKnownBinary() { - throw new UnsupportedOperationException(); - } - - /** - * The distance type has no equivalent in the GeoJSON standard: this method throws an {@link - * UnsupportedOperationException}. - */ - @Override - @NonNull - public String asGeoJson() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } else if (other instanceof Distance) { - Distance that = (Distance) other; - return Objects.equals(this.center, that.center) && this.radius == that.radius; - } else { - return false; - } - } - - @Override - public int hashCode() { - return Objects.hash(center, radius); - } - - @SuppressWarnings("SimplifiableConditionalExpression") - @Override - public boolean contains(@NonNull Geometry geometry) { - return geometry instanceof Distance - ? this.containsDistance((Distance) geometry) - : geometry instanceof Point - ? this.containsPoint((Point) geometry) - : geometry instanceof LineString - ? this.containsLineString((LineString) geometry) - : geometry instanceof Polygon ? this.containsPolygon((Polygon) geometry) : false; - } - - private boolean containsDistance(Distance distance) { - return this.center.getOgcGeometry().distance(distance.center.getOgcGeometry()) + distance.radius - <= this.radius; - } - - private boolean containsPoint(Point point) { - return this.containsOGCPoint(((DefaultPoint) point).getOgcGeometry()); - } - - private boolean containsLineString(LineString lineString) { - MultiPath multiPath = - (MultiPath) ((DefaultLineString) lineString).getOgcGeometry().getEsriGeometry(); - return containsMultiPath(multiPath); - } - - private boolean containsPolygon(Polygon polygon) { - MultiPath multiPath = - (com.esri.core.geometry.Polygon) - ((DefaultPolygon) polygon).getOgcGeometry().getEsriGeometry(); - return containsMultiPath(multiPath); - } - - private boolean containsMultiPath(MultiPath multiPath) { - int numPoints = multiPath.getPointCount(); - for (int i = 0; i < numPoints; ++i) { - OGCPoint point = new OGCPoint(multiPath.getPoint(i), DefaultGeometry.SPATIAL_REFERENCE_4326); - if (!this.containsOGCPoint(point)) { - return false; - } - } - return true; - } - - private boolean containsOGCPoint(OGCPoint point) { - return this.center.getOgcGeometry().distance(point) <= this.radius; - } - - /** - * This object gets replaced by an internal proxy for serialization. - * - * @serialData Point (wkb) for center followed by double for radius - */ - private Object writeReplace() { - return new DistanceSerializationProxy(this); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/data/geometry/DistanceSerializationProxy.java b/core/src/main/java/com/datastax/dse/driver/internal/core/data/geometry/DistanceSerializationProxy.java deleted file mode 100644 index 515af121980..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/data/geometry/DistanceSerializationProxy.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.data.geometry; - -import com.datastax.dse.driver.api.core.data.geometry.Point; -import java.io.Serializable; - -/** - * A thin wrapper around {@link Distance}, that gets substituted during the serialization / - * deserialization process. This allows {@link Distance} to be immutable and reference centers' OGC - * counterpart. - */ -public class DistanceSerializationProxy implements Serializable { - - private static final long serialVersionUID = 1L; - - private final Point center; - private final double radius; - - public DistanceSerializationProxy(Distance distance) { - this.center = distance.getCenter(); - this.radius = distance.getRadius(); - } - - private Object readResolve() { - return new Distance(center, radius); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ByteBufUtil.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ByteBufUtil.java deleted file mode 100644 index 333ba6099d3..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ByteBufUtil.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import java.nio.ByteBuffer; - -public class ByteBufUtil { - - // Does not move the reader index of the ByteBuf parameter - public static ByteBuffer toByteBuffer(ByteBuf buffer) { - if (buffer.isDirect()) { - return buffer.nioBuffer(); - } - final byte[] bytes = new byte[buffer.readableBytes()]; - buffer.getBytes(buffer.readerIndex(), bytes); - return ByteBuffer.wrap(bytes); - } - - static ByteBuf toByteBuf(ByteBuffer buffer) { - return Unpooled.wrappedBuffer(buffer); - } - - // read a predefined amount of bytes from the netty buffer and move its readerIndex - public static ByteBuffer readBytes(ByteBuf nettyBuf, int size) { - ByteBuffer res = ByteBuffer.allocate(size); - nettyBuf.readBytes(res); - res.flip(); - return res; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/BytecodeGraphStatement.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/BytecodeGraphStatement.java deleted file mode 100644 index e8e4554e81f..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/BytecodeGraphStatement.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.oss.driver.api.core.ConsistencyLevel; -import com.datastax.oss.driver.api.core.RequestRoutingType; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.metadata.Node; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import org.apache.tinkerpop.gremlin.process.traversal.Bytecode; - -/** - * A dedicated statement implementation for implicit traversal execution via a {@link - * DseGraphRemoteConnection}. - * - *

This is a simplified version of {@link FluentGraphStatement} that exposes the bytecode - * directly instead of the traversal. - * - *

This class is for internal use only. - */ -public class BytecodeGraphStatement extends GraphStatementBase { - - private final Bytecode bytecode; - - public BytecodeGraphStatement( - Bytecode bytecode, DriverExecutionProfile executionProfile, String executionProfileName) { - this( - bytecode, - null, - null, - null, - Statement.NO_DEFAULT_TIMESTAMP, - executionProfile, - executionProfileName, - Collections.emptyMap(), - null, - null, - null, - null, - null, - null); - } - - private BytecodeGraphStatement( - Bytecode bytecode, - Boolean isIdempotent, - Duration timeout, - Node node, - long timestamp, - DriverExecutionProfile executionProfile, - String executionProfileName, - Map customPayload, - String graphName, - String traversalSource, - String subProtocol, - ConsistencyLevel consistencyLevel, - ConsistencyLevel readConsistencyLevel, - ConsistencyLevel writeConsistencyLevel) { - super( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - this.bytecode = bytecode; - } - - public Bytecode getBytecode() { - return bytecode; - } - - @Override - protected BytecodeGraphStatement newInstance( - Boolean isIdempotent, - Duration timeout, - Node node, - long timestamp, - DriverExecutionProfile executionProfile, - String executionProfileName, - Map customPayload, - String graphName, - String traversalSource, - String subProtocol, - ConsistencyLevel consistencyLevel, - ConsistencyLevel readConsistencyLevel, - ConsistencyLevel writeConsistencyLevel) { - return new BytecodeGraphStatement( - bytecode, - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @NonNull - @Override - public RequestRoutingType getRequestRoutingType() { - return RequestRoutingType.REGULAR; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ContinuousAsyncGraphResultSet.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ContinuousAsyncGraphResultSet.java deleted file mode 100644 index 9c7f773c3a2..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ContinuousAsyncGraphResultSet.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Collections; -import java.util.Queue; -import java.util.concurrent.CompletionStage; -import net.jcip.annotations.NotThreadSafe; - -@NotThreadSafe // wraps a mutable queue -public class ContinuousAsyncGraphResultSet implements AsyncGraphResultSet { - - private final CountingIterator iterator; - private final int pageNumber; - private final boolean hasMorePages; - private final ExecutionInfo executionInfo; - private final ContinuousGraphRequestHandler continuousGraphRequestHandler; - private final Iterable currentPage; - - public ContinuousAsyncGraphResultSet( - ExecutionInfo executionInfo, - Queue data, - int pageNumber, - boolean hasMorePages, - ContinuousGraphRequestHandler continuousGraphRequestHandler, - GraphProtocol graphProtocol) { - - this.iterator = new GraphResultIterator(data, graphProtocol); - this.pageNumber = pageNumber; - this.hasMorePages = hasMorePages; - this.executionInfo = executionInfo; - this.continuousGraphRequestHandler = continuousGraphRequestHandler; - this.currentPage = () -> iterator; - } - - @NonNull - @Override - public ExecutionInfo getRequestExecutionInfo() { - return executionInfo; - } - - @NonNull - @Override - @Deprecated - public com.datastax.dse.driver.api.core.graph.GraphExecutionInfo getExecutionInfo() { - return GraphExecutionInfoConverter.convert(executionInfo); - } - - @Override - public int remaining() { - return iterator.remaining(); - } - - @NonNull - @Override - public Iterable currentPage() { - return currentPage; - } - - @Override - public boolean hasMorePages() { - return hasMorePages; - } - - @NonNull - @Override - public CompletionStage fetchNextPage() throws IllegalStateException { - if (!hasMorePages()) { - throw new IllegalStateException( - "Can't call fetchNextPage() on the last page (use hasMorePages() to check)"); - } - return continuousGraphRequestHandler.fetchNextPage(); - } - - @Override - public void cancel() { - continuousGraphRequestHandler.cancel(); - } - - /** Returns the current page's number. Pages are numbered starting from 1. */ - public int pageNumber() { - return pageNumber; - } - - static AsyncGraphResultSet empty(ExecutionInfo executionInfo) { - - return new AsyncGraphResultSet() { - - @NonNull - @Override - public ExecutionInfo getRequestExecutionInfo() { - return executionInfo; - } - - @NonNull - @Override - @Deprecated - public com.datastax.dse.driver.api.core.graph.GraphExecutionInfo getExecutionInfo() { - return GraphExecutionInfoConverter.convert(executionInfo); - } - - @NonNull - @Override - public Iterable currentPage() { - return Collections.emptyList(); - } - - @Override - public int remaining() { - return 0; - } - - @Override - public boolean hasMorePages() { - return false; - } - - @NonNull - @Override - public CompletionStage fetchNextPage() throws IllegalStateException { - throw new IllegalStateException( - "Can't call fetchNextPage() on the last page (use hasMorePages() to check)"); - } - - @Override - public void cancel() { - // noop - } - }; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandler.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandler.java deleted file mode 100644 index 07d9e4c84a3..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandler.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; -import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousRequestHandlerBase; -import com.datastax.dse.driver.internal.core.graph.binary.GraphBinaryModule; -import com.datastax.dse.protocol.internal.response.result.DseRowsMetadata; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.cql.Conversions; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.shaded.guava.common.base.MoreObjects; -import com.datastax.oss.protocol.internal.Message; -import com.datastax.oss.protocol.internal.response.result.Rows; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.ArrayDeque; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import net.jcip.annotations.ThreadSafe; - -/** - * Handles a Graph request that supports multiple response messages (a.k.a. continuous paging - * request). - */ -@ThreadSafe -public class ContinuousGraphRequestHandler - extends ContinuousRequestHandlerBase, AsyncGraphResultSet> { - - private final GraphBinaryModule graphBinaryModule; - private final GraphSupportChecker graphSupportChecker; - private final Duration globalTimeout; - - ContinuousGraphRequestHandler( - @NonNull GraphStatement statement, - @NonNull DefaultSession session, - @NonNull InternalDriverContext context, - @NonNull String sessionLogPrefix, - @NonNull GraphBinaryModule graphBinaryModule, - @NonNull GraphSupportChecker graphSupportChecker) { - super( - statement, - session, - context, - sessionLogPrefix, - AsyncGraphResultSet.class, - true, - DseSessionMetric.GRAPH_CLIENT_TIMEOUTS, - DseSessionMetric.GRAPH_REQUESTS, - DseNodeMetric.GRAPH_MESSAGES); - this.graphBinaryModule = graphBinaryModule; - this.graphSupportChecker = graphSupportChecker; - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - globalTimeout = - MoreObjects.firstNonNull( - statement.getTimeout(), - executionProfile.getDuration(DseDriverOption.GRAPH_TIMEOUT, Duration.ZERO)); - // NOTE that ordering of the following statement matters. - // We should register this request after all fields have been initialized. - throttler.register(this); - } - - @NonNull - @Override - protected Duration getGlobalTimeout() { - return globalTimeout; - } - - @NonNull - @Override - protected Duration getPageTimeout(@NonNull GraphStatement statement, int pageNumber) { - return Duration.ZERO; - } - - @NonNull - @Override - protected Duration getReviseRequestTimeout(@NonNull GraphStatement statement) { - return Duration.ZERO; - } - - @Override - protected int getMaxEnqueuedPages(@NonNull GraphStatement statement) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - return executionProfile.getInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES); - } - - @Override - protected int getMaxPages(@NonNull GraphStatement statement) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - return executionProfile.getInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_PAGES); - } - - @NonNull - @Override - protected Message getMessage(@NonNull GraphStatement statement) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - GraphProtocol subProtocol = - graphSupportChecker.inferGraphProtocol(statement, executionProfile, context); - return GraphConversions.createContinuousMessageFromGraphStatement( - statement, subProtocol, executionProfile, context, graphBinaryModule); - } - - @Override - protected boolean isTracingEnabled(@NonNull GraphStatement statement) { - return statement.isTracing(); - } - - @NonNull - @Override - protected Map createPayload(@NonNull GraphStatement statement) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - GraphProtocol subProtocol = - graphSupportChecker.inferGraphProtocol(statement, executionProfile, context); - return GraphConversions.createCustomPayload( - statement, subProtocol, executionProfile, context, graphBinaryModule); - } - - @NonNull - @Override - protected AsyncGraphResultSet createEmptyResultSet(@NonNull ExecutionInfo executionInfo) { - return ContinuousAsyncGraphResultSet.empty(executionInfo); - } - - @NonNull - @Override - protected ContinuousAsyncGraphResultSet createResultSet( - @NonNull GraphStatement statement, - @NonNull Rows rows, - @NonNull ExecutionInfo executionInfo, - @NonNull ColumnDefinitions columnDefinitions) - throws IOException { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - GraphProtocol subProtocol = - graphSupportChecker.inferGraphProtocol(statement, executionProfile, context); - - Queue graphNodes = new ArrayDeque<>(); - for (List row : rows.getData()) { - if (subProtocol.isGraphBinary()) { - graphNodes.offer(GraphConversions.createGraphBinaryGraphNode(row, this.graphBinaryModule)); - } else { - graphNodes.offer(GraphSONUtils.createGraphNode(row, subProtocol)); - } - } - - DseRowsMetadata metadata = (DseRowsMetadata) rows.getMetadata(); - return new ContinuousAsyncGraphResultSet( - executionInfo, - graphNodes, - metadata.continuousPageNumber, - !metadata.isLastContinuousPage, - this, - subProtocol); - } - - @Override - protected int pageNumber(@NonNull AsyncGraphResultSet resultSet) { - return ((ContinuousAsyncGraphResultSet) resultSet).pageNumber(); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/CqlCollectionPredicate.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/CqlCollectionPredicate.java deleted file mode 100644 index 349321da0cf..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/CqlCollectionPredicate.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import org.javatuples.Pair; - -/** Predicates that can be used on CQL Collections. */ -public enum CqlCollectionPredicate implements DsePredicate { - contains { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - Preconditions.checkArgument(value instanceof Collection); - return ((Collection) value).contains(condition); - } - }, - - containsKey { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - Preconditions.checkArgument(value instanceof Map); - return ((Map) value).containsKey(condition); - } - }, - - containsValue { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - Preconditions.checkArgument(value instanceof Map); - return ((Map) value).containsValue(condition); - } - }, - - entryEq { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - Preconditions.checkArgument(condition instanceof Pair); - Preconditions.checkArgument(value instanceof Map); - Pair pair = (Pair) condition; - Map map = (Map) value; - return Objects.equals(map.get(pair.getValue0()), pair.getValue1()); - } - }; - - @Override - public boolean isValidCondition(Object condition) { - if (condition instanceof Pair) { - Pair pair = (Pair) condition; - return pair.getValue0() != null && pair.getValue1() != null; - } - return condition != null; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultAsyncGraphResultSet.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultAsyncGraphResultSet.java deleted file mode 100644 index abc7cc9514e..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultAsyncGraphResultSet.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Queue; -import java.util.concurrent.CompletionStage; -import net.jcip.annotations.NotThreadSafe; - -@NotThreadSafe // wraps a mutable queue -public class DefaultAsyncGraphResultSet implements AsyncGraphResultSet { - - private final ExecutionInfo executionInfo; - private final CountingIterator iterator; - private final Iterable currentPage; - - public DefaultAsyncGraphResultSet( - ExecutionInfo executionInfo, Queue data, GraphProtocol graphProtocol) { - this.executionInfo = executionInfo; - this.iterator = new GraphResultIterator(data, graphProtocol); - this.currentPage = () -> iterator; - } - - @NonNull - @Override - public ExecutionInfo getRequestExecutionInfo() { - return executionInfo; - } - - @NonNull - @Override - @Deprecated - public com.datastax.dse.driver.api.core.graph.GraphExecutionInfo getExecutionInfo() { - return GraphExecutionInfoConverter.convert(executionInfo); - } - - @Override - public int remaining() { - return iterator.remaining(); - } - - @NonNull - @Override - public Iterable currentPage() { - return currentPage; - } - - @Override - public boolean hasMorePages() { - return false; - } - - @NonNull - @Override - public CompletionStage fetchNextPage() throws IllegalStateException { - throw new IllegalStateException( - "No next page. Use #hasMorePages before calling this method to avoid this error."); - } - - @Override - public void cancel() { - // nothing to do - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultBatchGraphStatement.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultBatchGraphStatement.java deleted file mode 100644 index 632d45e61d6..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultBatchGraphStatement.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.BatchGraphStatement; -import com.datastax.oss.driver.api.core.ConsistencyLevel; -import com.datastax.oss.driver.api.core.RequestRoutingType; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import net.jcip.annotations.Immutable; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; - -@Immutable -public class DefaultBatchGraphStatement extends GraphStatementBase - implements BatchGraphStatement { - - private final List traversals; - - public DefaultBatchGraphStatement( - Iterable traversals, - Boolean isIdempotent, - Duration timeout, - Node node, - long timestamp, - DriverExecutionProfile executionProfile, - String executionProfileName, - Map customPayload, - String graphName, - String traversalSource, - String subProtocol, - ConsistencyLevel consistencyLevel, - ConsistencyLevel readConsistencyLevel, - ConsistencyLevel writeConsistencyLevel) { - super( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - this.traversals = ImmutableList.copyOf(traversals); - } - - @NonNull - @Override - public DefaultBatchGraphStatement addTraversal(@NonNull GraphTraversal newTraversal) { - return new DefaultBatchGraphStatement( - ImmutableList.builder().addAll(traversals).add(newTraversal).build(), - isIdempotent(), - getTimeout(), - getNode(), - getTimestamp(), - getExecutionProfile(), - getExecutionProfileName(), - getCustomPayload(), - getGraphName(), - getTraversalSource(), - getSubProtocol(), - getConsistencyLevel(), - getReadConsistencyLevel(), - getWriteConsistencyLevel()); - } - - @NonNull - @Override - public DefaultBatchGraphStatement addTraversals(@NonNull Iterable newTraversals) { - return new DefaultBatchGraphStatement( - ImmutableList.builder().addAll(traversals).addAll(newTraversals).build(), - isIdempotent(), - getTimeout(), - getNode(), - getTimestamp(), - getExecutionProfile(), - getExecutionProfileName(), - getCustomPayload(), - getGraphName(), - getTraversalSource(), - getSubProtocol(), - getConsistencyLevel(), - getReadConsistencyLevel(), - getWriteConsistencyLevel()); - } - - @Override - public int size() { - return this.traversals.size(); - } - - @Override - protected BatchGraphStatement newInstance( - Boolean isIdempotent, - Duration timeout, - Node node, - long timestamp, - DriverExecutionProfile executionProfile, - String executionProfileName, - Map customPayload, - String graphName, - String traversalSource, - String subProtocol, - ConsistencyLevel consistencyLevel, - ConsistencyLevel readConsistencyLevel, - ConsistencyLevel writeConsistencyLevel) { - return new DefaultBatchGraphStatement( - traversals, - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @NonNull - @Override - public Iterator iterator() { - return this.traversals.iterator(); - } - - @NonNull - @Override - public RequestRoutingType getRequestRoutingType() { - return RequestRoutingType.REGULAR; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultDseRemoteConnectionBuilder.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultDseRemoteConnectionBuilder.java deleted file mode 100644 index 146e8e17ea2..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultDseRemoteConnectionBuilder.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.DseGraphRemoteConnectionBuilder; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import net.jcip.annotations.NotThreadSafe; -import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection; - -@NotThreadSafe -public class DefaultDseRemoteConnectionBuilder implements DseGraphRemoteConnectionBuilder { - - private final CqlSession session; - private DriverExecutionProfile executionProfile; - private String executionProfileName; - - public DefaultDseRemoteConnectionBuilder(CqlSession session) { - this.session = session; - } - - @Override - public RemoteConnection build() { - return new DseGraphRemoteConnection(session, executionProfile, executionProfileName); - } - - @Override - public DseGraphRemoteConnectionBuilder withExecutionProfile( - DriverExecutionProfile executionProfile) { - this.executionProfile = executionProfile; - return this; - } - - @Override - public DseGraphRemoteConnectionBuilder withExecutionProfileName(String executionProfileName) { - this.executionProfileName = executionProfileName; - return this; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultFluentGraphStatement.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultFluentGraphStatement.java deleted file mode 100644 index 44fa9e41853..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultFluentGraphStatement.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.oss.driver.api.core.ConsistencyLevel; -import com.datastax.oss.driver.api.core.RequestRoutingType; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.metadata.Node; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.Map; -import net.jcip.annotations.Immutable; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; - -@Immutable -public class DefaultFluentGraphStatement extends GraphStatementBase - implements FluentGraphStatement { - - private final GraphTraversal traversal; - - public DefaultFluentGraphStatement( - GraphTraversal traversal, - Boolean isIdempotent, - Duration timeout, - Node node, - long timestamp, - DriverExecutionProfile executionProfile, - String executionProfileName, - Map customPayload, - String graphName, - String traversalSource, - String subProtocol, - ConsistencyLevel consistencyLevel, - ConsistencyLevel readConsistencyLevel, - ConsistencyLevel writeConsistencyLevel) { - super( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - this.traversal = traversal; - } - - @Override - protected FluentGraphStatement newInstance( - Boolean isIdempotent, - Duration timeout, - Node node, - long timestamp, - DriverExecutionProfile executionProfile, - String executionProfileName, - Map customPayload, - String graphName, - String traversalSource, - String subProtocol, - ConsistencyLevel consistencyLevel, - ConsistencyLevel readConsistencyLevel, - ConsistencyLevel writeConsistencyLevel) { - return new DefaultFluentGraphStatement( - traversal, - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @NonNull - @Override - public GraphTraversal getTraversal() { - return traversal; - } - - @NonNull - @Override - public RequestRoutingType getRequestRoutingType() { - return RequestRoutingType.REGULAR; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultScriptGraphStatement.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultScriptGraphStatement.java deleted file mode 100644 index 587e1221b41..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DefaultScriptGraphStatement.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.ConsistencyLevel; -import com.datastax.oss.driver.api.core.RequestRoutingType; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.protocol.internal.util.collection.NullAllowingImmutableMap; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.Map; -import net.jcip.annotations.Immutable; - -@Immutable -public class DefaultScriptGraphStatement extends GraphStatementBase - implements ScriptGraphStatement { - - private final String script; - private final Boolean isSystemQuery; - private final NullAllowingImmutableMap queryParams; - - public DefaultScriptGraphStatement( - String script, - Map queryParams, - Boolean isSystemQuery, - Boolean isIdempotent, - Duration timeout, - Node node, - long timestamp, - DriverExecutionProfile executionProfile, - String executionProfileName, - Map customPayload, - String graphName, - String traversalSource, - String subProtocol, - ConsistencyLevel consistencyLevel, - ConsistencyLevel readConsistencyLevel, - ConsistencyLevel writeConsistencyLevel) { - super( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - this.script = script; - this.isSystemQuery = isSystemQuery; - this.queryParams = NullAllowingImmutableMap.copyOf(queryParams); - } - - //// Script GraphStatement level options - - @NonNull - @Override - public String getScript() { - return script; - } - - @NonNull - @Override - public ScriptGraphStatement setSystemQuery(@Nullable Boolean newValue) { - return new DefaultScriptGraphStatement( - script, - queryParams, - newValue, - isIdempotent(), - getTimeout(), - getNode(), - getTimestamp(), - getExecutionProfile(), - getExecutionProfileName(), - getCustomPayload(), - getGraphName(), - getTraversalSource(), - getSubProtocol(), - getConsistencyLevel(), - getReadConsistencyLevel(), - getWriteConsistencyLevel()); - } - - @Nullable - @Override - public Boolean isSystemQuery() { - return isSystemQuery; - } - - @NonNull - @Override - public Map getQueryParams() { - return this.queryParams; - } - - @NonNull - @Override - public ScriptGraphStatement setQueryParam(@NonNull String name, @Nullable Object value) { - NullAllowingImmutableMap.Builder newQueryParamsBuilder = - NullAllowingImmutableMap.builder(); - for (Map.Entry entry : queryParams.entrySet()) { - if (!entry.getKey().equals(name)) { - newQueryParamsBuilder.put(entry.getKey(), entry.getValue()); - } - } - newQueryParamsBuilder.put(name, value); - return setQueryParams(newQueryParamsBuilder.build()); - } - - @NonNull - @Override - public ScriptGraphStatement removeQueryParam(@NonNull String name) { - if (!queryParams.containsKey(name)) { - return this; - } else { - NullAllowingImmutableMap.Builder newQueryParamsBuilder = - NullAllowingImmutableMap.builder(); - for (Map.Entry entry : queryParams.entrySet()) { - if (!entry.getKey().equals(name)) { - newQueryParamsBuilder.put(entry.getKey(), entry.getValue()); - } - } - return setQueryParams(newQueryParamsBuilder.build()); - } - } - - private ScriptGraphStatement setQueryParams(Map newQueryParams) { - return new DefaultScriptGraphStatement( - script, - newQueryParams, - isSystemQuery, - isIdempotent(), - getTimeout(), - getNode(), - getTimestamp(), - getExecutionProfile(), - getExecutionProfileName(), - getCustomPayload(), - getGraphName(), - getTraversalSource(), - getSubProtocol(), - getConsistencyLevel(), - getReadConsistencyLevel(), - getWriteConsistencyLevel()); - } - - @Override - protected ScriptGraphStatement newInstance( - Boolean isIdempotent, - Duration timeout, - Node node, - long timestamp, - DriverExecutionProfile executionProfile, - String executionProfileName, - Map customPayload, - String graphName, - String traversalSource, - String subProtocol, - ConsistencyLevel consistencyLevel, - ConsistencyLevel readConsistencyLevel, - ConsistencyLevel writeConsistencyLevel) { - return new DefaultScriptGraphStatement( - script, - queryParams, - isSystemQuery, - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Override - public String toString() { - return String.format("ScriptGraphStatement['%s', params: %s]", this.script, this.queryParams); - } - - @NonNull - @Override - public RequestRoutingType getRequestRoutingType() { - return RequestRoutingType.REGULAR; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DseGraphRemoteConnection.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DseGraphRemoteConnection.java deleted file mode 100644 index a5ec0a1d115..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DseGraphRemoteConnection.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import java.util.concurrent.CompletableFuture; -import net.jcip.annotations.Immutable; -import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection; -import org.apache.tinkerpop.gremlin.process.remote.traversal.RemoteTraversal; -import org.apache.tinkerpop.gremlin.process.traversal.Bytecode; - -@Immutable -public class DseGraphRemoteConnection implements RemoteConnection { - - private final CqlSession session; - private final DriverExecutionProfile executionProfile; - private final String executionProfileName; - - public DseGraphRemoteConnection( - CqlSession session, DriverExecutionProfile executionProfile, String executionProfileName) { - this.session = session; - this.executionProfile = executionProfile; - this.executionProfileName = executionProfileName; - } - - @Override - public CompletableFuture> submitAsync(Bytecode bytecode) { - return session - .executeAsync(new BytecodeGraphStatement(bytecode, executionProfile, executionProfileName)) - .toCompletableFuture() - .thenApply(DseGraphTraversal::new); - } - - @Override - public void close() throws Exception { - // do not close the DseSession here. - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DseGraphTraversal.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DseGraphTraversal.java deleted file mode 100644 index e0a5cf2d675..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DseGraphTraversal.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import java.util.Iterator; -import java.util.NoSuchElementException; -import net.jcip.annotations.NotThreadSafe; -import org.apache.tinkerpop.gremlin.process.remote.traversal.AbstractRemoteTraversal; -import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser; -import org.apache.tinkerpop.gremlin.process.traversal.Traverser; - -@NotThreadSafe -class DseGraphTraversal extends AbstractRemoteTraversal { - - private final Iterator graphNodeIterator; - - public DseGraphTraversal(AsyncGraphResultSet firstPage) { - this.graphNodeIterator = GraphResultSets.toSync(firstPage).iterator(); - } - - @Override - public boolean hasNext() { - return graphNodeIterator.hasNext(); - } - - @Override - public E next() { - return nextTraverser().get(); - } - - @Override - @SuppressWarnings("unchecked") - public Traverser.Admin nextTraverser() { - if (hasNext()) { - GraphNode nextGraphNode = graphNodeIterator.next(); - - // get the Raw object from the ObjectGraphNode, create a new remote Traverser - // with bulk = 1 because bulk is not supported yet. Casting should be ok - // because we have been able to deserialize into the right type. - return new DefaultRemoteTraverser<>((E) nextGraphNode.as(Object.class), 1); - } else { - // finished iterating/nothing to iterate. Normal behaviour. - throw new NoSuchElementException(); - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DsePredicate.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DsePredicate.java deleted file mode 100644 index b5f8c30fd8c..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/DsePredicate.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; -import java.util.function.BiPredicate; - -/** - * An extension of TinkerPop's {@link BiPredicate} adding simple pre-condition checking methods that - * have to be written in the implementations. - */ -public interface DsePredicate extends BiPredicate { - - default void preEvaluate(Object condition) { - Preconditions.checkArgument( - this.isValidCondition(condition), "Invalid condition provided: %s", condition); - } - - boolean isValidCondition(Object condition); -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/EditDistance.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/EditDistance.java deleted file mode 100644 index 5ab836babbf..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/EditDistance.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.oss.driver.shaded.guava.common.base.Objects; -import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; -import java.io.Serializable; -import net.jcip.annotations.Immutable; - -/** - * A container for a term and maximum edit distance. - * - *

The context in which this is used determines the semantics of the edit distance. For instance, - * it might indicate single-character edits if used with fuzzy search queries or whole word - * movements if used with phrase proximity queries. - */ -@Immutable -public class EditDistance implements Serializable { - - private static final long serialVersionUID = 1L; - - public static final int DEFAULT_EDIT_DISTANCE = 0; - - public final String query; - public final int distance; - - public EditDistance(String query) { - this(query, DEFAULT_EDIT_DISTANCE); - } - - public EditDistance(String query, int distance) { - Preconditions.checkNotNull(query, "Query cannot be null."); - Preconditions.checkArgument(distance >= 0, "Edit distance cannot be negative."); - this.query = query; - this.distance = distance; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof EditDistance)) { - return false; - } - EditDistance that = (EditDistance) o; - return distance == that.distance && Objects.equal(query, that.query); - } - - @Override - public int hashCode() { - return Objects.hashCode(query, distance); - } - - @Override - public String toString() { - return "EditDistance{" + "query='" + query + '\'' + ", distance=" + distance + '}'; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GeoPredicate.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GeoPredicate.java deleted file mode 100644 index 39949e97198..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GeoPredicate.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.data.geometry.Geometry; -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import com.datastax.dse.driver.api.core.graph.predicates.Geo; -import com.datastax.dse.driver.internal.core.data.geometry.Distance; -import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; - -/** - * List of predicates for geolocation usage with DseGraph and Search indexes. Should not be accessed - * directly but through the {@link Geo} static methods. - */ -public enum GeoPredicate implements DsePredicate { - - /** Matches values within the distance specified by the condition over a Haversine geometry. */ - inside { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - if (value == null) { - return false; - } - Preconditions.checkArgument(value instanceof Geometry); - Distance distance = (Distance) condition; - if (value instanceof Point) { - return haversineDistanceInDegrees(distance.getCenter(), (Point) value) - <= distance.getRadius(); - } else if (value instanceof Polygon) { - for (Point point : ((Polygon) value).getExteriorRing()) { - if (haversineDistanceInDegrees(distance.getCenter(), point) > distance.getRadius()) { - return false; - } - } - } else if (value instanceof LineString) { - for (Point point : ((LineString) value).getPoints()) { - if (haversineDistanceInDegrees(distance.getCenter(), point) > distance.getRadius()) { - return false; - } - } - } else { - throw new UnsupportedOperationException( - String.format("Value type '%s' unsupported", value.getClass().getName())); - } - - return true; - } - - @Override - public String toString() { - return "inside"; - } - }, - - /** - * Matches values contained in the geometric entity specified by the condition on a 2D Euclidean - * plane. - */ - insideCartesian { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - if (value == null) { - return false; - } - Preconditions.checkArgument(value instanceof Geometry); - return ((Geometry) condition).contains((Geometry) value); - } - - @Override - public String toString() { - return "insideCartesian"; - } - }; - - @Override - public boolean isValidCondition(Object condition) { - return condition != null; - } - - static double haversineDistanceInDegrees(Point p1, Point p2) { - double dLat = Math.toRadians(p2.Y() - p1.Y()); - double dLon = Math.toRadians(p2.X() - p1.X()); - double lat1 = Math.toRadians(p1.Y()); - double lat2 = Math.toRadians(p2.Y()); - - double a = - Math.pow(Math.sin(dLat / 2), 2) - + Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2); - double c = 2 * Math.asin(Math.sqrt(a)); - return Math.toDegrees(c); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GeoUtils.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GeoUtils.java deleted file mode 100644 index 80d55dac69d..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GeoUtils.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -public class GeoUtils { - private static final double DEGREES_TO_RADIANS = Math.PI / 180; - private static final double EARTH_MEAN_RADIUS_KM = 6371.0087714; - private static final double DEG_TO_KM = DEGREES_TO_RADIANS * EARTH_MEAN_RADIUS_KM; - private static final double KM_TO_MILES = 0.621371192; - public static final double KM_TO_DEG = 1 / DEG_TO_KM; - public static final double MILES_TO_KM = 1 / KM_TO_MILES; -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphConversions.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphConversions.java deleted file mode 100644 index c95b26b2e26..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphConversions.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.graph.BatchGraphStatement; -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.internal.core.graph.binary.GraphBinaryModule; -import com.datastax.dse.driver.internal.core.graph.binary.buffer.DseNettyBufferFactory; -import com.datastax.dse.protocol.internal.request.RawBytesQuery; -import com.datastax.dse.protocol.internal.request.query.ContinuousPagingOptions; -import com.datastax.dse.protocol.internal.request.query.DseQueryOptions; -import com.datastax.oss.driver.api.core.ConsistencyLevel; -import com.datastax.oss.driver.api.core.DefaultConsistencyLevel; -import com.datastax.oss.driver.api.core.ProtocolVersion; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.type.codec.TypeCodecs; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.cql.Conversions; -import com.datastax.oss.driver.shaded.guava.common.annotations.VisibleForTesting; -import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.Iterators; -import com.datastax.oss.protocol.internal.Message; -import com.datastax.oss.protocol.internal.ProtocolConstants; -import com.datastax.oss.protocol.internal.request.Query; -import com.datastax.oss.protocol.internal.util.collection.NullAllowingImmutableMap; -import io.netty.buffer.ByteBuf; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.apache.tinkerpop.gremlin.process.traversal.Traverser; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.BufferFactory; - -/** - * Utility class to move boilerplate out of {@link GraphRequestHandler}. - * - *

We extend {@link Conversions} only for methods that can be directly reused as-is; if something - * needs to be customized, it will be duplicated here instead of making the parent method - * "pluggable". - */ -public class GraphConversions extends Conversions { - - static final String GRAPH_LANG_OPTION_KEY = "graph-language"; - static final String GRAPH_NAME_OPTION_KEY = "graph-name"; - static final String GRAPH_SOURCE_OPTION_KEY = "graph-source"; - static final String GRAPH_READ_CONSISTENCY_LEVEL_OPTION_KEY = "graph-read-consistency"; - static final String GRAPH_WRITE_CONSISTENCY_LEVEL_OPTION_KEY = "graph-write-consistency"; - static final String GRAPH_RESULTS_OPTION_KEY = "graph-results"; - static final String GRAPH_TIMEOUT_OPTION_KEY = "request-timeout"; - static final String GRAPH_BINARY_QUERY_OPTION_KEY = "graph-binary-query"; - - static final String LANGUAGE_GROOVY = "gremlin-groovy"; - static final String LANGUAGE_BYTECODE = "bytecode-json"; - - private static final BufferFactory FACTORY = new DseNettyBufferFactory(); - - @VisibleForTesting static final byte[] EMPTY_STRING_QUERY = "".getBytes(UTF_8); - - public static Message createContinuousMessageFromGraphStatement( - GraphStatement statement, - GraphProtocol subProtocol, - DriverExecutionProfile config, - InternalDriverContext context, - GraphBinaryModule graphBinaryModule) { - - final List encodedQueryParams; - if (!(statement instanceof ScriptGraphStatement) - || ((ScriptGraphStatement) statement).getQueryParams().isEmpty()) { - encodedQueryParams = Collections.emptyList(); - } else { - try { - Map queryParams = ((ScriptGraphStatement) statement).getQueryParams(); - if (subProtocol.isGraphBinary()) { - Buffer graphBinaryParams = graphBinaryModule.serialize(queryParams); - encodedQueryParams = Collections.singletonList(graphBinaryParams.nioBuffer()); - graphBinaryParams.release(); - } else { - encodedQueryParams = - Collections.singletonList( - GraphSONUtils.serializeToByteBuffer(queryParams, subProtocol)); - } - } catch (IOException e) { - throw new UncheckedIOException( - "Couldn't serialize parameters for GraphStatement: " + statement, e); - } - } - - int consistencyLevel = - DefaultConsistencyLevel.valueOf(config.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .getProtocolCode(); - - long timestamp = statement.getTimestamp(); - if (timestamp == Statement.NO_DEFAULT_TIMESTAMP) { - timestamp = context.getTimestampGenerator().next(); - } - - int pageSize = config.getInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_PAGE_SIZE); - int maxPages = config.getInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_PAGES); - int maxPagesPerSecond = - config.getInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND); - int maxEnqueuedPages = - config.getInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES); - ContinuousPagingOptions options = - new ContinuousPagingOptions(maxPages, maxPagesPerSecond, maxEnqueuedPages); - - DseQueryOptions queryOptions = - new DseQueryOptions( - consistencyLevel, - encodedQueryParams, - Collections.emptyMap(), // ignored by the DSE Graph server - true, // also ignored - pageSize, - null, - ProtocolConstants.ConsistencyLevel.LOCAL_SERIAL, // also ignored - timestamp, - null, // also ignored - false, // graph CP does not support sizeInBytes - options); - - if (statement instanceof ScriptGraphStatement) { - return new Query(((ScriptGraphStatement) statement).getScript(), queryOptions); - } else { - return new RawBytesQuery(getQueryBytes(statement, subProtocol), queryOptions); - } - } - - static Message createMessageFromGraphStatement( - GraphStatement statement, - GraphProtocol subProtocol, - DriverExecutionProfile config, - InternalDriverContext context, - GraphBinaryModule graphBinaryModule) { - - final List encodedQueryParams; - if (!(statement instanceof ScriptGraphStatement) - || ((ScriptGraphStatement) statement).getQueryParams().isEmpty()) { - encodedQueryParams = Collections.emptyList(); - } else { - try { - Map queryParams = ((ScriptGraphStatement) statement).getQueryParams(); - if (subProtocol.isGraphBinary()) { - Buffer graphBinaryParams = graphBinaryModule.serialize(queryParams); - encodedQueryParams = Collections.singletonList(graphBinaryParams.nioBuffer()); - graphBinaryParams.release(); - } else { - encodedQueryParams = - Collections.singletonList( - GraphSONUtils.serializeToByteBuffer(queryParams, subProtocol)); - } - } catch (IOException e) { - throw new UncheckedIOException( - "Couldn't serialize parameters for GraphStatement: " + statement, e); - } - } - - ConsistencyLevel consistency = statement.getConsistencyLevel(); - int consistencyLevel = - (consistency == null) - ? context - .getConsistencyLevelRegistry() - .nameToCode(config.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - : consistency.getProtocolCode(); - - long timestamp = statement.getTimestamp(); - if (timestamp == Statement.NO_DEFAULT_TIMESTAMP) { - timestamp = context.getTimestampGenerator().next(); - } - - DseQueryOptions queryOptions = - new DseQueryOptions( - consistencyLevel, - encodedQueryParams, - Collections.emptyMap(), // ignored by the DSE Graph server - true, // also ignored - 50, // also ignored - null, // also ignored - ProtocolConstants.ConsistencyLevel.LOCAL_SERIAL, // also ignored - timestamp, - null, // also ignored - false, // also ignored - null // also ignored - ); - - if (statement instanceof ScriptGraphStatement) { - return new Query(((ScriptGraphStatement) statement).getScript(), queryOptions); - } else { - return new RawBytesQuery(getQueryBytes(statement, subProtocol), queryOptions); - } - } - - // This method returns either a Bytecode object, or a List if the statement is a - // BatchGraphStatement - @VisibleForTesting - public static Object bytecodeToSerialize(GraphStatement statement) { - Preconditions.checkArgument( - statement instanceof FluentGraphStatement - || statement instanceof BatchGraphStatement - || statement instanceof BytecodeGraphStatement, - "To serialize bytecode the query must be a fluent or batch statement, but was: %s", - statement.getClass()); - - Object toSerialize; - if (statement instanceof FluentGraphStatement) { - toSerialize = ((FluentGraphStatement) statement).getTraversal().asAdmin().getBytecode(); - } else if (statement instanceof BatchGraphStatement) { - // transform the Iterator to List - toSerialize = - ImmutableList.copyOf( - Iterators.transform( - ((BatchGraphStatement) statement).iterator(), - traversal -> traversal.asAdmin().getBytecode())); - } else { - toSerialize = ((BytecodeGraphStatement) statement).getBytecode(); - } - return toSerialize; - } - - private static byte[] getQueryBytes(GraphStatement statement, GraphProtocol graphSubProtocol) { - try { - return graphSubProtocol.isGraphBinary() - // if GraphBinary, the query is encoded in the custom payload, and not in the query field - // see GraphConversions#createCustomPayload() - ? EMPTY_STRING_QUERY - : GraphSONUtils.serializeToBytes(bytecodeToSerialize(statement), graphSubProtocol); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - public static Map createCustomPayload( - GraphStatement statement, - GraphProtocol subProtocol, - DriverExecutionProfile config, - InternalDriverContext context, - GraphBinaryModule graphBinaryModule) { - - ProtocolVersion protocolVersion = context.getProtocolVersion(); - - NullAllowingImmutableMap.Builder payload = - NullAllowingImmutableMap.builder(); - Map statementOptions = statement.getCustomPayload(); - payload.putAll(statementOptions); - - final String graphLanguage; - - // Don't override anything that's already provided at the statement level - if (!statementOptions.containsKey(GRAPH_LANG_OPTION_KEY)) { - graphLanguage = - statement instanceof ScriptGraphStatement ? LANGUAGE_GROOVY : LANGUAGE_BYTECODE; - payload.put(GRAPH_LANG_OPTION_KEY, TypeCodecs.TEXT.encode(graphLanguage, protocolVersion)); - } else { - graphLanguage = - TypeCodecs.TEXT.decode(statementOptions.get(GRAPH_LANG_OPTION_KEY), protocolVersion); - Preconditions.checkNotNull( - graphLanguage, "A null value was set for the graph-language custom payload key."); - } - - if (!isSystemQuery(statement, config)) { - if (!statementOptions.containsKey(GRAPH_NAME_OPTION_KEY)) { - String graphName = statement.getGraphName(); - if (graphName == null) { - graphName = config.getString(DseDriverOption.GRAPH_NAME, null); - } - if (graphName != null) { - payload.put(GRAPH_NAME_OPTION_KEY, TypeCodecs.TEXT.encode(graphName, protocolVersion)); - } - } - if (!statementOptions.containsKey(GRAPH_SOURCE_OPTION_KEY)) { - String traversalSource = statement.getTraversalSource(); - if (traversalSource == null) { - traversalSource = config.getString(DseDriverOption.GRAPH_TRAVERSAL_SOURCE, null); - } - if (traversalSource != null) { - payload.put( - GRAPH_SOURCE_OPTION_KEY, TypeCodecs.TEXT.encode(traversalSource, protocolVersion)); - } - } - } - - // the payload allows null entry values so doing a get directly here and checking for null - final ByteBuffer payloadInitialProtocol = statementOptions.get(GRAPH_RESULTS_OPTION_KEY); - if (payloadInitialProtocol == null) { - Preconditions.checkNotNull(subProtocol); - payload.put( - GRAPH_RESULTS_OPTION_KEY, - TypeCodecs.TEXT.encode(subProtocol.toInternalCode(), protocolVersion)); - } else { - subProtocol = - GraphProtocol.fromString(TypeCodecs.TEXT.decode(payloadInitialProtocol, protocolVersion)); - } - - if (subProtocol.isGraphBinary() && graphLanguage.equals(LANGUAGE_BYTECODE)) { - Object bytecodeQuery = bytecodeToSerialize(statement); - try { - Buffer bytecodeByteBuf = graphBinaryModule.serialize(bytecodeQuery); - payload.put(GRAPH_BINARY_QUERY_OPTION_KEY, bytecodeByteBuf.nioBuffer()); - bytecodeByteBuf.release(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - if (!statementOptions.containsKey(GRAPH_READ_CONSISTENCY_LEVEL_OPTION_KEY)) { - ConsistencyLevel readCl = statement.getReadConsistencyLevel(); - String readClString = - readCl != null - ? readCl.name() - : config.getString(DseDriverOption.GRAPH_READ_CONSISTENCY_LEVEL, null); - if (readClString != null) { - payload.put( - GRAPH_READ_CONSISTENCY_LEVEL_OPTION_KEY, - TypeCodecs.TEXT.encode(readClString, protocolVersion)); - } - } - - if (!statementOptions.containsKey(GRAPH_WRITE_CONSISTENCY_LEVEL_OPTION_KEY)) { - ConsistencyLevel writeCl = statement.getWriteConsistencyLevel(); - String writeClString = - writeCl != null - ? writeCl.name() - : config.getString(DseDriverOption.GRAPH_WRITE_CONSISTENCY_LEVEL, null); - if (writeClString != null) { - payload.put( - GRAPH_WRITE_CONSISTENCY_LEVEL_OPTION_KEY, - TypeCodecs.TEXT.encode(writeClString, protocolVersion)); - } - } - - if (!statementOptions.containsKey(GRAPH_TIMEOUT_OPTION_KEY)) { - Duration timeout = statement.getTimeout(); - if (timeout == null) { - timeout = config.getDuration(DseDriverOption.GRAPH_TIMEOUT, Duration.ZERO); - } - if (timeout != null && !timeout.isZero()) { - payload.put( - GRAPH_TIMEOUT_OPTION_KEY, - TypeCodecs.BIGINT.encode(timeout.toMillis(), protocolVersion)); - } - } - return payload.build(); - } - - private static boolean isSystemQuery(GraphStatement statement, DriverExecutionProfile config) { - if (statement instanceof ScriptGraphStatement) { - Boolean statementValue = ((ScriptGraphStatement) statement).isSystemQuery(); - if (statementValue != null) { - return statementValue; - } - } - return config.getBoolean(DseDriverOption.GRAPH_IS_SYSTEM_QUERY, false); - } - - public static GraphNode createGraphBinaryGraphNode( - List data, GraphBinaryModule graphBinaryModule) throws IOException { - // there should be only one column in the given row - Preconditions.checkArgument(data.size() == 1, "Invalid row given to deserialize"); - - Buffer toDeserialize = FACTORY.wrap(data.get(0)); - Object deserializedObject = graphBinaryModule.deserialize(toDeserialize); - toDeserialize.release(); - assert deserializedObject instanceof Traverser - : "Graph protocol error. Received object should be a Traverser but it is not."; - return new ObjectGraphNode(deserializedObject); - } - - public static Duration resolveGraphRequestTimeout( - GraphStatement statement, InternalDriverContext context) { - DriverExecutionProfile executionProfile = resolveExecutionProfile(statement, context); - return statement.getTimeout() != null - ? statement.getTimeout() - : executionProfile.getDuration(DseDriverOption.GRAPH_TIMEOUT); - } - - public static GraphProtocol resolveGraphSubProtocol( - GraphStatement statement, - GraphSupportChecker graphSupportChecker, - InternalDriverContext context) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - return graphSupportChecker.inferGraphProtocol(statement, executionProfile, context); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphExecutionInfoConverter.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphExecutionInfoConverter.java deleted file mode 100644 index b6472f690d3..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphExecutionInfoConverter.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.QueryTrace; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.CompletionStage; - -/** - * Handles conversions from / to GraphExecutionInfo and ExecutionInfo since GraphExecutionInfo has - * been deprecated by JAVA-2556. - */ -public class GraphExecutionInfoConverter { - - /** - * Called exclusively from default methods in API interfaces {@link - * com.datastax.dse.driver.api.core.graph.GraphResultSet} and {@link - * com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet}. Graph result set implementations - * do not use this method but rather the other one below. - */ - @SuppressWarnings("deprecation") - public static ExecutionInfo convert( - com.datastax.dse.driver.api.core.graph.GraphExecutionInfo graphExecutionInfo) { - return new ExecutionInfo() { - - @NonNull - @Override - public Request getRequest() { - return graphExecutionInfo.getStatement(); - } - - @NonNull - @Override - public Statement getStatement() { - throw new ClassCastException("GraphStatement cannot be cast to Statement"); - } - - @Nullable - @Override - public Node getCoordinator() { - return graphExecutionInfo.getCoordinator(); - } - - @Override - public int getSpeculativeExecutionCount() { - return graphExecutionInfo.getSpeculativeExecutionCount(); - } - - @Override - public int getSuccessfulExecutionIndex() { - return graphExecutionInfo.getSuccessfulExecutionIndex(); - } - - @NonNull - @Override - public List> getErrors() { - return graphExecutionInfo.getErrors(); - } - - @Nullable - @Override - public ByteBuffer getPagingState() { - return null; - } - - @NonNull - @Override - public List getWarnings() { - return graphExecutionInfo.getWarnings(); - } - - @NonNull - @Override - public Map getIncomingPayload() { - return graphExecutionInfo.getIncomingPayload(); - } - - @Override - public boolean isSchemaInAgreement() { - return true; - } - - @Nullable - @Override - public UUID getTracingId() { - return null; - } - - @NonNull - @Override - public CompletionStage getQueryTraceAsync() { - return CompletableFutures.failedFuture( - new IllegalStateException("Tracing was disabled for this request")); - } - - @Override - public int getResponseSizeInBytes() { - return -1; - } - - @Override - public int getCompressedResponseSizeInBytes() { - return -1; - } - }; - } - - /** - * Called from graph result set implementations, to convert the original {@link ExecutionInfo} - * produced by request handlers into the (deprecated) type GraphExecutionInfo. - */ - @SuppressWarnings("deprecation") - public static com.datastax.dse.driver.api.core.graph.GraphExecutionInfo convert( - ExecutionInfo executionInfo) { - return new com.datastax.dse.driver.api.core.graph.GraphExecutionInfo() { - - @Override - public GraphStatement getStatement() { - return (GraphStatement) executionInfo.getRequest(); - } - - @Override - public Node getCoordinator() { - return executionInfo.getCoordinator(); - } - - @Override - public int getSpeculativeExecutionCount() { - return executionInfo.getSpeculativeExecutionCount(); - } - - @Override - public int getSuccessfulExecutionIndex() { - return executionInfo.getSuccessfulExecutionIndex(); - } - - @Override - public List> getErrors() { - return executionInfo.getErrors(); - } - - @Override - public List getWarnings() { - return executionInfo.getWarnings(); - } - - @Override - public Map getIncomingPayload() { - return executionInfo.getIncomingPayload(); - } - }; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphProtocol.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphProtocol.java deleted file mode 100644 index 6b7a9f4c430..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphProtocol.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public enum GraphProtocol { - GRAPHSON_1_0("graphson-1.0"), - GRAPHSON_2_0("graphson-2.0"), - GRAPH_BINARY_1_0("graph-binary-1.0"), - ; - - private static final Map BY_CODE; - - static { - Map tmp = new HashMap<>(); - for (GraphProtocol value : values()) { - tmp.put(value.stringRepresentation, value); - } - BY_CODE = Collections.unmodifiableMap(tmp); - } - - private final String stringRepresentation; - - GraphProtocol(String stringRepresentation) { - this.stringRepresentation = stringRepresentation; - } - - @NonNull - public String toInternalCode() { - return stringRepresentation; - } - - @NonNull - public static GraphProtocol fromString(@Nullable String stringRepresentation) { - if (stringRepresentation == null || !BY_CODE.containsKey(stringRepresentation)) { - StringBuilder sb = - new StringBuilder( - String.format( - "Graph protocol used [\"%s\"] unknown. Possible values are: [ \"%s\"", - stringRepresentation, GraphProtocol.values()[0].toInternalCode())); - for (int i = 1; i < GraphProtocol.values().length; i++) { - sb.append(String.format(", \"%s\"", GraphProtocol.values()[i].toInternalCode())); - } - sb.append("]"); - throw new IllegalArgumentException(sb.toString()); - } - return BY_CODE.get(stringRepresentation); - } - - public boolean isGraphBinary() { - return this == GRAPH_BINARY_1_0; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestAsyncProcessor.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestAsyncProcessor.java deleted file mode 100644 index 050b03c66f4..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestAsyncProcessor.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.BatchGraphStatement; -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.internal.core.graph.binary.GraphBinaryModule; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.internal.core.session.RequestProcessor; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.concurrent.CompletionStage; -import net.jcip.annotations.ThreadSafe; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; -import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry; - -@ThreadSafe -public class GraphRequestAsyncProcessor - implements RequestProcessor, CompletionStage> { - - private final GraphBinaryModule graphBinaryModule; - private final GraphSupportChecker graphSupportChecker; - - public GraphRequestAsyncProcessor( - DefaultDriverContext context, GraphSupportChecker graphSupportChecker) { - TypeSerializerRegistry typeSerializerRegistry = - GraphBinaryModule.createDseTypeSerializerRegistry(context); - this.graphBinaryModule = - new GraphBinaryModule( - new GraphBinaryReader(typeSerializerRegistry), - new GraphBinaryWriter(typeSerializerRegistry)); - this.graphSupportChecker = graphSupportChecker; - } - - @NonNull - public GraphBinaryModule getGraphBinaryModule() { - return graphBinaryModule; - } - - @Override - public boolean canProcess(Request request, GenericType resultType) { - return (request instanceof ScriptGraphStatement - || request instanceof FluentGraphStatement - || request instanceof BatchGraphStatement - || request instanceof BytecodeGraphStatement) - && resultType.equals(GraphStatement.ASYNC); - } - - @Override - public CompletionStage process( - GraphStatement request, - DefaultSession session, - InternalDriverContext context, - String sessionLogPrefix) { - - if (graphSupportChecker.isPagingEnabled(request, context)) { - return new ContinuousGraphRequestHandler( - request, - session, - context, - sessionLogPrefix, - getGraphBinaryModule(), - graphSupportChecker) - .handle(); - } else { - return new GraphRequestHandler( - request, - session, - context, - sessionLogPrefix, - getGraphBinaryModule(), - graphSupportChecker) - .handle(); - } - } - - @Override - public CompletionStage newFailure(RuntimeException error) { - return CompletableFutures.failedFuture(error); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandler.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandler.java deleted file mode 100644 index cf6875dd362..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandler.java +++ /dev/null @@ -1,908 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static com.datastax.oss.driver.api.core.DriverTimeoutException.UNAVAILABLE; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; -import com.datastax.dse.driver.internal.core.graph.binary.GraphBinaryModule; -import com.datastax.oss.driver.api.core.AllNodesFailedException; -import com.datastax.oss.driver.api.core.DriverException; -import com.datastax.oss.driver.api.core.DriverTimeoutException; -import com.datastax.oss.driver.api.core.DriverTimeoutException.NodeDiagnostics; -import com.datastax.oss.driver.api.core.NodeUnavailableException; -import com.datastax.oss.driver.api.core.RequestThrottlingException; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.connection.FrameTooLongException; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; -import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; -import com.datastax.oss.driver.api.core.retry.RetryPolicy; -import com.datastax.oss.driver.api.core.retry.RetryVerdict; -import com.datastax.oss.driver.api.core.servererrors.BootstrappingException; -import com.datastax.oss.driver.api.core.servererrors.CoordinatorException; -import com.datastax.oss.driver.api.core.servererrors.FunctionFailureException; -import com.datastax.oss.driver.api.core.servererrors.ProtocolError; -import com.datastax.oss.driver.api.core.servererrors.QueryValidationException; -import com.datastax.oss.driver.api.core.servererrors.ReadTimeoutException; -import com.datastax.oss.driver.api.core.servererrors.UnavailableException; -import com.datastax.oss.driver.api.core.servererrors.WriteTimeoutException; -import com.datastax.oss.driver.api.core.session.throttling.RequestThrottler; -import com.datastax.oss.driver.api.core.session.throttling.Throttled; -import com.datastax.oss.driver.api.core.tracker.RequestTracker; -import com.datastax.oss.driver.internal.core.channel.DriverChannel; -import com.datastax.oss.driver.internal.core.channel.ResponseCallback; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.cql.Conversions; -import com.datastax.oss.driver.internal.core.cql.DefaultExecutionInfo; -import com.datastax.oss.driver.internal.core.metadata.DefaultNode; -import com.datastax.oss.driver.internal.core.metrics.NodeMetricUpdater; -import com.datastax.oss.driver.internal.core.metrics.SessionMetricUpdater; -import com.datastax.oss.driver.internal.core.pool.ChannelPool; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.internal.core.tracker.NoopRequestTracker; -import com.datastax.oss.driver.internal.core.tracker.RequestLogger; -import com.datastax.oss.driver.internal.core.util.Loggers; -import com.datastax.oss.driver.internal.core.util.collection.SimpleQueryPlan; -import com.datastax.oss.protocol.internal.Frame; -import com.datastax.oss.protocol.internal.Message; -import com.datastax.oss.protocol.internal.response.Error; -import com.datastax.oss.protocol.internal.response.Result; -import com.datastax.oss.protocol.internal.response.result.Rows; -import com.datastax.oss.protocol.internal.response.result.Void; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import io.netty.handler.codec.EncoderException; -import io.netty.util.Timeout; -import io.netty.util.Timer; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.AbstractMap; -import java.util.ArrayDeque; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import net.jcip.annotations.ThreadSafe; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ThreadSafe -public class GraphRequestHandler implements Throttled { - - private static final Logger LOG = LoggerFactory.getLogger(GraphRequestHandler.class); - - private static final long NANOTIME_NOT_MEASURED_YET = -1; - private static final int NO_SUCCESSFUL_EXECUTION = -1; - - private final long startTimeNanos; - private final String logPrefix; - private final GraphStatement initialStatement; - private final DefaultSession session; - private final InternalDriverContext context; - protected final CompletableFuture result; - private final Timer timer; - - /** - * How many speculative executions are currently running (including the initial execution). We - * track this in order to know when to fail the request if all executions have reached the end of - * the query plan. - */ - private final AtomicInteger activeExecutionsCount; - - /** - * How many speculative executions have started (excluding the initial execution), whether they - * have completed or not. We track this in order to fill {@link - * ExecutionInfo#getSpeculativeExecutionCount()}. - */ - private final AtomicInteger startedSpeculativeExecutionsCount; - - private final Timeout scheduledTimeout; - private final List scheduledExecutions; - private final List inFlightCallbacks; - private final RequestThrottler throttler; - private final RequestTracker requestTracker; - private final SessionMetricUpdater sessionMetricUpdater; - private final GraphBinaryModule graphBinaryModule; - private final GraphSupportChecker graphSupportChecker; - - // The errors on the nodes that were already tried (lazily initialized on the first error). - // We don't use a map because nodes can appear multiple times. - private volatile List> errors; - - GraphRequestHandler( - @NonNull GraphStatement statement, - @NonNull DefaultSession dseSession, - @NonNull InternalDriverContext context, - @NonNull String sessionLogPrefix, - @NonNull GraphBinaryModule graphBinaryModule, - @NonNull GraphSupportChecker graphSupportChecker) { - this.startTimeNanos = System.nanoTime(); - this.logPrefix = sessionLogPrefix + "|" + this.hashCode(); - LOG.trace("[{}] Creating new Graph request handler for request {}", logPrefix, statement); - this.initialStatement = statement; - this.session = dseSession; - this.context = context; - this.graphSupportChecker = graphSupportChecker; - this.result = new CompletableFuture<>(); - this.result.exceptionally( - t -> { - try { - if (t instanceof CancellationException) { - cancelScheduledTasks(); - context.getRequestThrottler().signalCancel(this); - } - } catch (Throwable t2) { - Loggers.warnWithException(LOG, "[{}] Uncaught exception", logPrefix, t2); - } - return null; - }); - this.graphBinaryModule = graphBinaryModule; - this.timer = context.getNettyOptions().getTimer(); - - this.activeExecutionsCount = new AtomicInteger(1); - this.startedSpeculativeExecutionsCount = new AtomicInteger(0); - this.scheduledExecutions = new CopyOnWriteArrayList<>(); - this.inFlightCallbacks = new CopyOnWriteArrayList<>(); - - this.requestTracker = context.getRequestTracker(); - this.sessionMetricUpdater = session.getMetricUpdater(); - - Duration timeout = GraphConversions.resolveGraphRequestTimeout(statement, context); - this.scheduledTimeout = scheduleTimeout(timeout); - - this.throttler = context.getRequestThrottler(); - this.throttler.register(this); - } - - @Override - public void onThrottleReady(boolean wasDelayed) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(initialStatement, context); - if (wasDelayed - // avoid call to nanoTime() if metric is disabled: - && sessionMetricUpdater.isEnabled( - DefaultSessionMetric.THROTTLING_DELAY, executionProfile.getName())) { - sessionMetricUpdater.updateTimer( - DefaultSessionMetric.THROTTLING_DELAY, - executionProfile.getName(), - System.nanoTime() - startTimeNanos, - TimeUnit.NANOSECONDS); - } - Queue queryPlan = - initialStatement.getNode() != null - ? new SimpleQueryPlan(initialStatement.getNode()) - : context - .getLoadBalancingPolicyWrapper() - .newQueryPlan(initialStatement, executionProfile.getName(), session); - sendRequest(initialStatement, null, queryPlan, 0, 0, true); - } - - public CompletionStage handle() { - return result; - } - - private Timeout scheduleTimeout(Duration timeoutDuration) { - if (timeoutDuration != null && timeoutDuration.toNanos() > 0) { - try { - return this.timer.newTimeout( - (Timeout timeout1) -> { - NodeDiagnostics diagnostics = buildNodeDiagnostics(); - setFinalError( - initialStatement, - new DriverTimeoutException( - "Query timed out after " + timeoutDuration, diagnostics), - null, - NO_SUCCESSFUL_EXECUTION); - }, - timeoutDuration.toNanos(), - TimeUnit.NANOSECONDS); - } catch (IllegalStateException e) { - // If we raced with session shutdown the timer might be closed already, rethrow with a more - // explicit message - result.completeExceptionally( - "cannot be started once stopped".equals(e.getMessage()) - ? new IllegalStateException("Session is closed") - : e); - } - } - return null; - } - - @Nullable - private NodeDiagnostics buildNodeDiagnostics() { - List callbacks = inFlightCallbacks; - if (callbacks.isEmpty()) { - return null; - } - NodeResponseCallback cb = callbacks.get(0); - int channelInFlight = cb.channel.getInFlight(); - ChannelPool pool = session.getPools().get(cb.node); - return NodeDiagnostics.of( - cb.node.getEndPoint(), - cb.node.getState(), - cb.node.getDistance(), - cb.node.getDatacenter(), - channelInFlight, - pool != null ? pool.size() : UNAVAILABLE, - pool != null ? pool.getInFlight() : UNAVAILABLE, - pool != null ? pool.getAvailableIds() : UNAVAILABLE, - pool != null ? pool.getOrphanedIds() : UNAVAILABLE); - } - - /** - * Sends the request to the next available node. - * - * @param retriedNode if not null, it will be attempted first before the rest of the query plan. - * @param queryPlan the list of nodes to try (shared with all other executions) - * @param currentExecutionIndex 0 for the initial execution, 1 for the first speculative one, etc. - * @param retryCount the number of times that the retry policy was invoked for this execution - * already (note that some internal retries don't go through the policy, and therefore don't - * increment this counter) - * @param scheduleNextExecution whether to schedule the next speculative execution - */ - private void sendRequest( - GraphStatement statement, - Node retriedNode, - Queue queryPlan, - int currentExecutionIndex, - int retryCount, - boolean scheduleNextExecution) { - if (result.isDone()) { - return; - } - Node node = retriedNode; - DriverChannel channel = null; - if (node == null || (channel = session.getChannel(node, logPrefix)) == null) { - while (!result.isDone() && (node = queryPlan.poll()) != null) { - channel = session.getChannel(node, logPrefix); - if (channel != null) { - break; - } else { - recordError(node, new NodeUnavailableException(node)); - } - } - } - if (channel == null) { - // We've reached the end of the query plan without finding any node to write to - if (!result.isDone() && activeExecutionsCount.decrementAndGet() == 0) { - // We're the last execution so fail the result - setFinalError( - statement, - AllNodesFailedException.fromErrors(this.errors), - null, - NO_SUCCESSFUL_EXECUTION); - } - } else { - boolean writeSubmitted = false; - try { - NodeResponseCallback nodeResponseCallback = - new NodeResponseCallback( - statement, - node, - queryPlan, - channel, - currentExecutionIndex, - retryCount, - scheduleNextExecution, - logPrefix); - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - GraphProtocol graphSubProtocol = - GraphConversions.resolveGraphSubProtocol(statement, graphSupportChecker, context); - Message message = - GraphConversions.createMessageFromGraphStatement( - statement, graphSubProtocol, executionProfile, context, graphBinaryModule); - Map customPayload = - GraphConversions.createCustomPayload( - statement, graphSubProtocol, executionProfile, context, graphBinaryModule); - Future writeFuture = - channel.write(message, statement.isTracing(), customPayload, nodeResponseCallback); - writeSubmitted = true; - writeFuture.addListener(nodeResponseCallback); - } finally { - if (!writeSubmitted) { - channel.cancelPreAcquireId(); - } - } - } - } - - private void recordError(Node node, Throwable error) { - // Use a local variable to do only a single single volatile read in the nominal case - List> errorsSnapshot = this.errors; - if (errorsSnapshot == null) { - synchronized (GraphRequestHandler.this) { - errorsSnapshot = this.errors; - if (errorsSnapshot == null) { - this.errors = errorsSnapshot = new CopyOnWriteArrayList<>(); - } - } - } - errorsSnapshot.add(new AbstractMap.SimpleEntry<>(node, error)); - } - - private void cancelScheduledTasks() { - if (this.scheduledTimeout != null) { - this.scheduledTimeout.cancel(); - } - if (scheduledExecutions != null) { - for (Timeout scheduledExecution : scheduledExecutions) { - scheduledExecution.cancel(); - } - } - for (NodeResponseCallback callback : inFlightCallbacks) { - callback.cancel(); - } - } - - private void setFinalResult( - Result resultMessage, Frame responseFrame, NodeResponseCallback callback) { - try { - ExecutionInfo executionInfo = buildExecutionInfo(callback, responseFrame); - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(callback.statement, context); - GraphProtocol subProtocol = - GraphConversions.resolveGraphSubProtocol( - callback.statement, graphSupportChecker, context); - Queue graphNodes = new ArrayDeque<>(); - for (List row : ((Rows) resultMessage).getData()) { - if (subProtocol.isGraphBinary()) { - graphNodes.offer( - GraphConversions.createGraphBinaryGraphNode( - row, GraphRequestHandler.this.graphBinaryModule)); - } else { - graphNodes.offer(GraphSONUtils.createGraphNode(row, subProtocol)); - } - } - - DefaultAsyncGraphResultSet resultSet = - new DefaultAsyncGraphResultSet(executionInfo, graphNodes, subProtocol); - if (result.complete(resultSet)) { - cancelScheduledTasks(); - throttler.signalSuccess(this); - - // Only call nanoTime() if we're actually going to use it - long completionTimeNanos = NANOTIME_NOT_MEASURED_YET, - totalLatencyNanos = NANOTIME_NOT_MEASURED_YET; - if (!(requestTracker instanceof NoopRequestTracker)) { - completionTimeNanos = System.nanoTime(); - totalLatencyNanos = completionTimeNanos - startTimeNanos; - long nodeLatencyNanos = completionTimeNanos - callback.nodeStartTimeNanos; - requestTracker.onNodeSuccess( - callback.statement, nodeLatencyNanos, executionProfile, callback.node, logPrefix); - requestTracker.onSuccess( - callback.statement, totalLatencyNanos, executionProfile, callback.node, logPrefix); - } - if (sessionMetricUpdater.isEnabled( - DseSessionMetric.GRAPH_REQUESTS, executionProfile.getName())) { - if (completionTimeNanos == NANOTIME_NOT_MEASURED_YET) { - completionTimeNanos = System.nanoTime(); - totalLatencyNanos = completionTimeNanos - startTimeNanos; - } - sessionMetricUpdater.updateTimer( - DseSessionMetric.GRAPH_REQUESTS, - executionProfile.getName(), - totalLatencyNanos, - TimeUnit.NANOSECONDS); - } - } - // log the warnings if they have NOT been disabled - if (!executionInfo.getWarnings().isEmpty() - && executionProfile.getBoolean(DefaultDriverOption.REQUEST_LOG_WARNINGS) - && LOG.isWarnEnabled()) { - logServerWarnings(callback.statement, executionInfo.getWarnings()); - } - } catch (Throwable error) { - setFinalError(callback.statement, error, callback.node, NO_SUCCESSFUL_EXECUTION); - } - } - - private void logServerWarnings(GraphStatement statement, List warnings) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - // use the RequestLogFormatter to format the query - StringBuilder statementString = new StringBuilder(); - context - .getRequestLogFormatter() - .appendRequest( - statement, - executionProfile.getInt( - DefaultDriverOption.REQUEST_LOGGER_MAX_QUERY_LENGTH, - RequestLogger.DEFAULT_REQUEST_LOGGER_MAX_QUERY_LENGTH), - executionProfile.getBoolean( - DefaultDriverOption.REQUEST_LOGGER_VALUES, - RequestLogger.DEFAULT_REQUEST_LOGGER_SHOW_VALUES), - executionProfile.getInt( - DefaultDriverOption.REQUEST_LOGGER_MAX_VALUES, - RequestLogger.DEFAULT_REQUEST_LOGGER_MAX_VALUES), - executionProfile.getInt( - DefaultDriverOption.REQUEST_LOGGER_MAX_VALUE_LENGTH, - RequestLogger.DEFAULT_REQUEST_LOGGER_MAX_VALUE_LENGTH), - statementString); - // log each warning separately - warnings.forEach( - (warning) -> - LOG.warn("Query '{}' generated server side warning(s): {}", statementString, warning)); - } - - private ExecutionInfo buildExecutionInfo(NodeResponseCallback callback, Frame responseFrame) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(callback.statement, context); - return new DefaultExecutionInfo( - callback.statement, - callback.node, - startedSpeculativeExecutionsCount.get(), - callback.execution, - errors, - null, - responseFrame, - true, - session, - context, - executionProfile); - } - - @Override - public void onThrottleFailure(@NonNull RequestThrottlingException error) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(initialStatement, context); - sessionMetricUpdater.incrementCounter( - DefaultSessionMetric.THROTTLING_ERRORS, executionProfile.getName()); - setFinalError(initialStatement, error, null, NO_SUCCESSFUL_EXECUTION); - } - - private void setFinalError( - GraphStatement statement, Throwable error, Node node, int execution) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - if (error instanceof DriverException) { - ((DriverException) error) - .setExecutionInfo( - new DefaultExecutionInfo( - statement, - node, - startedSpeculativeExecutionsCount.get(), - execution, - errors, - null, - null, - true, - session, - context, - executionProfile)); - } - if (result.completeExceptionally(error)) { - cancelScheduledTasks(); - if (!(requestTracker instanceof NoopRequestTracker)) { - long latencyNanos = System.nanoTime() - startTimeNanos; - requestTracker.onError(statement, error, latencyNanos, executionProfile, node, logPrefix); - } - if (error instanceof DriverTimeoutException) { - throttler.signalTimeout(this); - sessionMetricUpdater.incrementCounter( - DseSessionMetric.GRAPH_CLIENT_TIMEOUTS, executionProfile.getName()); - } else if (!(error instanceof RequestThrottlingException)) { - throttler.signalError(this, error); - } - } - } - - /** - * Handles the interaction with a single node in the query plan. - * - *

An instance of this class is created each time we (re)try a node. - */ - private class NodeResponseCallback - implements ResponseCallback, GenericFutureListener> { - - private final long nodeStartTimeNanos = System.nanoTime(); - private final GraphStatement statement; - private final Node node; - private final Queue queryPlan; - private final DriverChannel channel; - // The identifier of the current execution (0 for the initial execution, 1 for the first - // speculative execution, etc.) - private final int execution; - // How many times we've invoked the retry policy and it has returned a "retry" decision (0 for - // the first attempt of each execution). - private final int retryCount; - private final boolean scheduleNextExecution; - private final String logPrefix; - private final DriverExecutionProfile executionProfile; - - private NodeResponseCallback( - GraphStatement statement, - Node node, - Queue queryPlan, - DriverChannel channel, - int execution, - int retryCount, - boolean scheduleNextExecution, - String logPrefix) { - this.statement = statement; - this.node = node; - this.queryPlan = queryPlan; - this.channel = channel; - this.execution = execution; - this.retryCount = retryCount; - this.scheduleNextExecution = scheduleNextExecution; - this.logPrefix = logPrefix + "|" + execution; - this.executionProfile = Conversions.resolveExecutionProfile(statement, context); - } - - // this gets invoked once the write completes. - @Override - public void operationComplete(Future future) { - if (!future.isSuccess()) { - Throwable error = future.cause(); - if (error instanceof EncoderException - && error.getCause() instanceof FrameTooLongException) { - trackNodeError(node, error.getCause(), NANOTIME_NOT_MEASURED_YET); - setFinalError(statement, error.getCause(), node, execution); - } else { - LOG.trace( - "[{}] Failed to send request on {}, trying next node (cause: {})", - logPrefix, - channel, - error); - recordError(node, error); - trackNodeError(node, error, NANOTIME_NOT_MEASURED_YET); - ((DefaultNode) node) - .getMetricUpdater() - .incrementCounter(DefaultNodeMetric.UNSENT_REQUESTS, executionProfile.getName()); - sendRequest( - statement, - null, - queryPlan, - execution, - retryCount, - scheduleNextExecution); // try next node - } - } else { - LOG.trace("[{}] Request sent on {}", logPrefix, channel); - if (result.isDone()) { - // If the handler completed since the last time we checked, cancel directly because we - // don't know if cancelScheduledTasks() has run yet - cancel(); - } else { - inFlightCallbacks.add(this); - if (scheduleNextExecution - && Conversions.resolveIdempotence(statement, executionProfile)) { - int nextExecution = execution + 1; - long nextDelay; - try { - nextDelay = - Conversions.resolveSpeculativeExecutionPolicy(context, executionProfile) - .nextExecution(node, null, statement, nextExecution); - } catch (Throwable cause) { - // This is a bug in the policy, but not fatal since we have at least one other - // execution already running. Don't fail the whole request. - LOG.error( - "[{}] Unexpected error while invoking the speculative execution policy", - logPrefix, - cause); - return; - } - if (nextDelay >= 0) { - scheduleSpeculativeExecution(nextExecution, nextDelay); - } else { - LOG.trace( - "[{}] Speculative execution policy returned {}, no next execution", - logPrefix, - nextDelay); - } - } - } - } - } - - private void scheduleSpeculativeExecution(int index, long delay) { - LOG.trace("[{}] Scheduling speculative execution {} in {} ms", logPrefix, index, delay); - try { - scheduledExecutions.add( - timer.newTimeout( - (Timeout timeout1) -> { - if (!result.isDone()) { - LOG.trace( - "[{}] Starting speculative execution {}", - GraphRequestHandler.this.logPrefix, - index); - activeExecutionsCount.incrementAndGet(); - startedSpeculativeExecutionsCount.incrementAndGet(); - // Note that `node` is the first node of the execution, it might not be the - // "slow" one if there were retries, but in practice retries are rare. - ((DefaultNode) node) - .getMetricUpdater() - .incrementCounter( - DefaultNodeMetric.SPECULATIVE_EXECUTIONS, executionProfile.getName()); - sendRequest(statement, null, queryPlan, index, 0, true); - } - }, - delay, - TimeUnit.MILLISECONDS)); - } catch (IllegalStateException e) { - // If we're racing with session shutdown, the timer might be stopped already. We don't want - // to schedule more executions anyway, so swallow the error. - if (!"cannot be started once stopped".equals(e.getMessage())) { - Loggers.warnWithException( - LOG, "[{}] Error while scheduling speculative execution", logPrefix, e); - } - } - } - - @Override - public void onResponse(Frame responseFrame) { - long nodeResponseTimeNanos = NANOTIME_NOT_MEASURED_YET; - NodeMetricUpdater nodeMetricUpdater = ((DefaultNode) node).getMetricUpdater(); - if (nodeMetricUpdater.isEnabled(DseNodeMetric.GRAPH_MESSAGES, executionProfile.getName())) { - nodeResponseTimeNanos = System.nanoTime(); - long nodeLatency = System.nanoTime() - nodeStartTimeNanos; - nodeMetricUpdater.updateTimer( - DseNodeMetric.GRAPH_MESSAGES, - executionProfile.getName(), - nodeLatency, - TimeUnit.NANOSECONDS); - } - inFlightCallbacks.remove(this); - if (result.isDone()) { - return; - } - try { - Message responseMessage = responseFrame.message; - if (responseMessage instanceof Result) { - LOG.trace("[{}] Got result, completing", logPrefix); - setFinalResult((Result) responseMessage, responseFrame, this); - } else if (responseMessage instanceof Error) { - LOG.trace("[{}] Got error response, processing", logPrefix); - processErrorResponse((Error) responseMessage); - } else { - trackNodeError( - node, - new IllegalStateException("Unexpected response " + responseMessage), - nodeResponseTimeNanos); - setFinalError( - statement, - new IllegalStateException("Unexpected response " + responseMessage), - node, - execution); - } - } catch (Throwable t) { - trackNodeError(node, t, nodeResponseTimeNanos); - setFinalError(statement, t, node, execution); - } - } - - private void processErrorResponse(Error errorMessage) { - CoordinatorException error = Conversions.toThrowable(node, errorMessage, context); - NodeMetricUpdater metricUpdater = ((DefaultNode) node).getMetricUpdater(); - if (error instanceof BootstrappingException) { - LOG.trace("[{}] {} is bootstrapping, trying next node", logPrefix, node); - recordError(node, error); - trackNodeError(node, error, NANOTIME_NOT_MEASURED_YET); - sendRequest(statement, null, queryPlan, execution, retryCount, false); - } else if (error instanceof QueryValidationException - || error instanceof FunctionFailureException - || error instanceof ProtocolError) { - LOG.trace("[{}] Unrecoverable error, rethrowing", logPrefix); - metricUpdater.incrementCounter(DefaultNodeMetric.OTHER_ERRORS, executionProfile.getName()); - trackNodeError(node, error, NANOTIME_NOT_MEASURED_YET); - setFinalError(statement, error, node, execution); - } else { - RetryPolicy retryPolicy = Conversions.resolveRetryPolicy(context, executionProfile); - RetryVerdict verdict; - if (error instanceof ReadTimeoutException) { - ReadTimeoutException readTimeout = (ReadTimeoutException) error; - verdict = - retryPolicy.onReadTimeoutVerdict( - statement, - readTimeout.getConsistencyLevel(), - readTimeout.getBlockFor(), - readTimeout.getReceived(), - readTimeout.wasDataPresent(), - retryCount); - updateErrorMetrics( - metricUpdater, - verdict, - DefaultNodeMetric.READ_TIMEOUTS, - DefaultNodeMetric.RETRIES_ON_READ_TIMEOUT, - DefaultNodeMetric.IGNORES_ON_READ_TIMEOUT); - } else if (error instanceof WriteTimeoutException) { - WriteTimeoutException writeTimeout = (WriteTimeoutException) error; - verdict = - Conversions.resolveIdempotence(statement, executionProfile) - ? retryPolicy.onWriteTimeoutVerdict( - statement, - writeTimeout.getConsistencyLevel(), - writeTimeout.getWriteType(), - writeTimeout.getBlockFor(), - writeTimeout.getReceived(), - retryCount) - : RetryVerdict.RETHROW; - updateErrorMetrics( - metricUpdater, - verdict, - DefaultNodeMetric.WRITE_TIMEOUTS, - DefaultNodeMetric.RETRIES_ON_WRITE_TIMEOUT, - DefaultNodeMetric.IGNORES_ON_WRITE_TIMEOUT); - } else if (error instanceof UnavailableException) { - UnavailableException unavailable = (UnavailableException) error; - verdict = - retryPolicy.onUnavailableVerdict( - statement, - unavailable.getConsistencyLevel(), - unavailable.getRequired(), - unavailable.getAlive(), - retryCount); - updateErrorMetrics( - metricUpdater, - verdict, - DefaultNodeMetric.UNAVAILABLES, - DefaultNodeMetric.RETRIES_ON_UNAVAILABLE, - DefaultNodeMetric.IGNORES_ON_UNAVAILABLE); - } else { - verdict = - Conversions.resolveIdempotence(statement, executionProfile) - ? retryPolicy.onErrorResponseVerdict(statement, error, retryCount) - : RetryVerdict.RETHROW; - updateErrorMetrics( - metricUpdater, - verdict, - DefaultNodeMetric.OTHER_ERRORS, - DefaultNodeMetric.RETRIES_ON_OTHER_ERROR, - DefaultNodeMetric.IGNORES_ON_OTHER_ERROR); - } - processRetryVerdict(verdict, error); - } - } - - private void processRetryVerdict(RetryVerdict verdict, Throwable error) { - LOG.trace("[{}] Processing retry decision {}", logPrefix, verdict); - switch (verdict.getRetryDecision()) { - case RETRY_SAME: - recordError(node, error); - trackNodeError(node, error, NANOTIME_NOT_MEASURED_YET); - sendRequest( - verdict.getRetryRequest(statement), - node, - queryPlan, - execution, - retryCount + 1, - false); - break; - case RETRY_NEXT: - recordError(node, error); - trackNodeError(node, error, NANOTIME_NOT_MEASURED_YET); - sendRequest( - verdict.getRetryRequest(statement), - null, - queryPlan, - execution, - retryCount + 1, - false); - break; - case RETHROW: - trackNodeError(node, error, NANOTIME_NOT_MEASURED_YET); - setFinalError(statement, error, node, execution); - break; - case IGNORE: - setFinalResult(Void.INSTANCE, null, this); - break; - } - } - - private void updateErrorMetrics( - NodeMetricUpdater metricUpdater, - RetryVerdict verdict, - DefaultNodeMetric error, - DefaultNodeMetric retriesOnError, - DefaultNodeMetric ignoresOnError) { - metricUpdater.incrementCounter(error, executionProfile.getName()); - switch (verdict.getRetryDecision()) { - case RETRY_SAME: - case RETRY_NEXT: - metricUpdater.incrementCounter(DefaultNodeMetric.RETRIES, executionProfile.getName()); - metricUpdater.incrementCounter(retriesOnError, executionProfile.getName()); - break; - case IGNORE: - metricUpdater.incrementCounter(DefaultNodeMetric.IGNORES, executionProfile.getName()); - metricUpdater.incrementCounter(ignoresOnError, executionProfile.getName()); - break; - case RETHROW: - // nothing do do - } - } - - @Override - public void onFailure(Throwable error) { - inFlightCallbacks.remove(this); - if (result.isDone()) { - return; - } - LOG.trace("[{}] Request failure, processing: {}", logPrefix, error); - RetryVerdict verdict; - if (!Conversions.resolveIdempotence(statement, executionProfile) - || error instanceof FrameTooLongException) { - verdict = RetryVerdict.RETHROW; - } else { - try { - RetryPolicy retryPolicy = Conversions.resolveRetryPolicy(context, executionProfile); - verdict = retryPolicy.onRequestAbortedVerdict(statement, error, retryCount); - } catch (Throwable cause) { - setFinalError( - statement, - new IllegalStateException("Unexpected error while invoking the retry policy", cause), - node, - NO_SUCCESSFUL_EXECUTION); - return; - } - } - processRetryVerdict(verdict, error); - updateErrorMetrics( - ((DefaultNode) node).getMetricUpdater(), - verdict, - DefaultNodeMetric.ABORTED_REQUESTS, - DefaultNodeMetric.RETRIES_ON_ABORTED, - DefaultNodeMetric.IGNORES_ON_ABORTED); - } - - void cancel() { - try { - if (!channel.closeFuture().isDone()) { - this.channel.cancel(this); - } - } catch (Throwable t) { - Loggers.warnWithException(LOG, "[{}] Error cancelling", logPrefix, t); - } - } - - /** - * @param nodeResponseTimeNanos the time we received the response, if it's already been - * measured. If {@link #NANOTIME_NOT_MEASURED_YET}, it hasn't and we need to measure it now - * (this is to avoid unnecessary calls to System.nanoTime) - */ - private void trackNodeError(Node node, Throwable error, long nodeResponseTimeNanos) { - if (requestTracker instanceof NoopRequestTracker) { - return; - } - if (nodeResponseTimeNanos == NANOTIME_NOT_MEASURED_YET) { - nodeResponseTimeNanos = System.nanoTime(); - } - long latencyNanos = nodeResponseTimeNanos - this.nodeStartTimeNanos; - requestTracker.onNodeError(statement, error, latencyNanos, executionProfile, node, logPrefix); - } - - @Override - public String toString() { - return logPrefix; - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestSyncProcessor.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestSyncProcessor.java deleted file mode 100644 index bc2381482a8..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphRequestSyncProcessor.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.BatchGraphStatement; -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.dse.driver.api.core.graph.GraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.internal.core.session.RequestProcessor; -import com.datastax.oss.driver.internal.core.util.concurrent.BlockingOperation; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import net.jcip.annotations.ThreadSafe; - -@ThreadSafe -public class GraphRequestSyncProcessor - implements RequestProcessor, GraphResultSet> { - - private final GraphRequestAsyncProcessor asyncProcessor; - - public GraphRequestSyncProcessor(GraphRequestAsyncProcessor asyncProcessor) { - this.asyncProcessor = asyncProcessor; - } - - @Override - public boolean canProcess(Request request, GenericType resultType) { - return (request instanceof ScriptGraphStatement - || request instanceof FluentGraphStatement - || request instanceof BatchGraphStatement - || request instanceof BytecodeGraphStatement) - && resultType.equals(GraphStatement.SYNC); - } - - @Override - public GraphResultSet process( - GraphStatement request, - DefaultSession session, - InternalDriverContext context, - String sessionLogPrefix) { - BlockingOperation.checkNotDriverThread(); - AsyncGraphResultSet firstPage = - CompletableFutures.getUninterruptibly( - asyncProcessor.process(request, session, context, sessionLogPrefix)); - return GraphResultSets.toSync(firstPage); - } - - @Override - public GraphResultSet newFailure(RuntimeException error) { - throw error; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphResultIterator.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphResultIterator.java deleted file mode 100644 index 7e9043affec..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphResultIterator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; -import java.util.Queue; -import net.jcip.annotations.NotThreadSafe; -import org.apache.tinkerpop.gremlin.process.traversal.Traverser; - -@NotThreadSafe // wraps a mutable queue -class GraphResultIterator extends CountingIterator { - - private final Queue data; - private final GraphProtocol graphProtocol; - - // Sometimes a traversal can yield the same result multiple times consecutively. To avoid - // duplicating the data, DSE graph sends it only once with a counter indicating how many times - // it's repeated. - private long repeat = 0; - private GraphNode lastGraphNode = null; - - GraphResultIterator(Queue data, GraphProtocol graphProtocol) { - super(data.size()); - this.data = data; - this.graphProtocol = graphProtocol; - } - - @Override - protected GraphNode computeNext() { - if (repeat > 1) { - repeat -= 1; - // Note that we don't make a defensive copy, we assume the client won't mutate the node - return lastGraphNode; - } - - GraphNode container = data.poll(); - if (container == null) { - return endOfData(); - } - - if (graphProtocol.isGraphBinary()) { - // results are contained in a Traverser object and not a Map if the protocol - // is GraphBinary - Preconditions.checkState( - container.as(Object.class) instanceof Traverser, - "Graph protocol error. Received object should be a Traverser but it is not."); - Traverser t = container.as(Traverser.class); - this.repeat = t.bulk(); - this.lastGraphNode = new ObjectGraphNode(t.get()); - return lastGraphNode; - } else { - // The repeat counter is called "bulk" in the JSON payload - GraphNode b = container.getByKey("bulk"); - if (b != null) { - this.repeat = b.asLong(); - } - - lastGraphNode = container.getByKey("result"); - return lastGraphNode; - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphResultSets.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphResultSets.java deleted file mode 100644 index fb21f857cfa..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphResultSets.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphResultSet; - -public class GraphResultSets { - - public static GraphResultSet toSync(AsyncGraphResultSet firstPage) { - if (firstPage.hasMorePages()) { - return new MultiPageGraphResultSet(firstPage); - } else { - return new SinglePageGraphResultSet(firstPage); - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSON1SerdeTP.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSON1SerdeTP.java deleted file mode 100644 index f880bca3764..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSON1SerdeTP.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.data.geometry.Geometry; -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import com.datastax.oss.driver.shaded.guava.common.net.InetAddresses; -import java.io.IOException; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.util.List; -import java.util.Map; -import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator; -import org.apache.tinkerpop.shaded.jackson.core.JsonParseException; -import org.apache.tinkerpop.shaded.jackson.core.JsonParser; -import org.apache.tinkerpop.shaded.jackson.core.Version; -import org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext; -import org.apache.tinkerpop.shaded.jackson.databind.JsonDeserializer; -import org.apache.tinkerpop.shaded.jackson.databind.JsonSerializer; -import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider; -import org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer; -import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule; -import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer; - -public class GraphSON1SerdeTP { - - //////////////////////// DESERIALIZERS //////////////////////// - - /** - * Default deserializer used by the driver for {@link InetAddress} instances. The actual subclass - * returned by this deserializer depends on the type of address: {@link Inet4Address IPV4} or - * {@link Inet6Address IPV6}. - */ - static class DefaultInetAddressDeserializer extends StdDeserializer { - - private static final long serialVersionUID = 1L; - - private final Class inetClass; - - DefaultInetAddressDeserializer(Class inetClass) { - super(inetClass); - this.inetClass = inetClass; - } - - @Override - public T deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { - String ip = parser.readValueAs(String.class); - try { - InetAddress inet = InetAddresses.forString(ip); - return inetClass.cast(inet); - } catch (ClassCastException e) { - throw new JsonParseException( - parser, - String.format("Inet address cannot be cast to %s: %s", inetClass.getSimpleName(), ip), - e); - } catch (IllegalArgumentException e) { - throw new JsonParseException(parser, String.format("Expected inet address, got %s", ip), e); - } - } - } - - /** - * Default deserializer used by the driver for geospatial types. It deserializes such types into - * {@link Geometry} instances. The actual subclass depends on the type being deserialized. - */ - static class DefaultGeometryDeserializer extends StdDeserializer { - - private static final long serialVersionUID = 1L; - - private final Class geometryClass; - - DefaultGeometryDeserializer(Class geometryClass) { - super(geometryClass); - this.geometryClass = geometryClass; - } - - @Override - public T deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { - String wkt = parser.readValueAs(String.class); - Geometry geometry; - if (wkt.startsWith("POINT")) geometry = Point.fromWellKnownText(wkt); - else if (wkt.startsWith("LINESTRING")) geometry = LineString.fromWellKnownText(wkt); - else if (wkt.startsWith("POLYGON")) geometry = Polygon.fromWellKnownText(wkt); - else throw new JsonParseException(parser, "Unknown geometry type: " + wkt); - return geometryClass.cast(geometry); - } - } - - /** Base class for serializing the {@code java.time.*} types to ISO-8061 formats. */ - abstract static class AbstractJavaTimeSerializer extends StdSerializer { - - private static final long serialVersionUID = 1L; - - AbstractJavaTimeSerializer(final Class clazz) { - super(clazz); - } - - @Override - public void serialize( - final T value, final JsonGenerator gen, final SerializerProvider serializerProvider) - throws IOException { - gen.writeString(value.toString()); - } - } - - /** Base class for deserializing the {@code java.time.*} types from ISO-8061 formats. */ - abstract static class AbstractJavaTimeJacksonDeserializer extends StdDeserializer { - - private static final long serialVersionUID = 1L; - - AbstractJavaTimeJacksonDeserializer(final Class clazz) { - super(clazz); - } - - abstract T parse(final String val); - - @Override - public T deserialize( - final JsonParser jsonParser, final DeserializationContext deserializationContext) - throws IOException { - return parse(jsonParser.getText()); - } - } - - static final class DurationJacksonSerializer - extends AbstractJavaTimeSerializer { - - private static final long serialVersionUID = 1L; - - DurationJacksonSerializer() { - super(java.time.Duration.class); - } - } - - static final class DurationJacksonDeserializer - extends AbstractJavaTimeJacksonDeserializer { - - private static final long serialVersionUID = 1L; - - DurationJacksonDeserializer() { - super(java.time.Duration.class); - } - - @Override - public java.time.Duration parse(final String val) { - return java.time.Duration.parse(val); - } - } - - static final class InstantJacksonSerializer - extends AbstractJavaTimeSerializer { - - private static final long serialVersionUID = 1L; - - InstantJacksonSerializer() { - super(java.time.Instant.class); - } - } - - static final class InstantJacksonDeserializer - extends AbstractJavaTimeJacksonDeserializer { - - private static final long serialVersionUID = 1L; - - InstantJacksonDeserializer() { - super(java.time.Instant.class); - } - - @Override - public java.time.Instant parse(final String val) { - return java.time.Instant.parse(val); - } - } - - static final class LocalDateJacksonSerializer - extends AbstractJavaTimeSerializer { - - private static final long serialVersionUID = 1L; - - LocalDateJacksonSerializer() { - super(java.time.LocalDate.class); - } - } - - static final class LocalDateJacksonDeserializer - extends AbstractJavaTimeJacksonDeserializer { - - private static final long serialVersionUID = 1L; - - LocalDateJacksonDeserializer() { - super(java.time.LocalDate.class); - } - - @Override - public java.time.LocalDate parse(final String val) { - return java.time.LocalDate.parse(val); - } - } - - static final class LocalTimeJacksonSerializer - extends AbstractJavaTimeSerializer { - - private static final long serialVersionUID = 1L; - - LocalTimeJacksonSerializer() { - super(java.time.LocalTime.class); - } - } - - static final class LocalTimeJacksonDeserializer - extends AbstractJavaTimeJacksonDeserializer { - - private static final long serialVersionUID = 1L; - - LocalTimeJacksonDeserializer() { - super(java.time.LocalTime.class); - } - - @Override - public java.time.LocalTime parse(final String val) { - return java.time.LocalTime.parse(val); - } - } - - //////////////////////// SERIALIZERS //////////////////////// - - /** Default serializer used by the driver for {@link LegacyGraphNode} instances. */ - static class DefaultGraphNodeSerializer extends StdSerializer { - - private static final long serialVersionUID = 1L; - - DefaultGraphNodeSerializer() { - super(LegacyGraphNode.class); - } - - @Override - public void serialize( - LegacyGraphNode value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) - throws IOException { - jsonGenerator.writeTree(value.getDelegate()); - } - } - - /** - * Default serializer used by the driver for geospatial types. It serializes {@link Geometry} - * instances into their Well-Known Text (WKT) equivalent. - */ - static class DefaultGeometrySerializer extends StdSerializer { - - private static final long serialVersionUID = 1L; - - DefaultGeometrySerializer() { - super(Geometry.class); - } - - @Override - public void serialize( - Geometry value, JsonGenerator jsonGenerator, SerializerProvider serializers) - throws IOException { - jsonGenerator.writeString(value.asWellKnownText()); - } - } - - /** The default Jackson module used by DSE Graph. */ - static class GraphSON1DefaultModule extends SimpleModule { - - private static final long serialVersionUID = 1L; - - GraphSON1DefaultModule(String name, Version version) { - super(name, version, createDeserializers(), createSerializers()); - } - - private static Map, JsonDeserializer> createDeserializers() { - - return ImmutableMap., JsonDeserializer>builder() - - // Inet (there is no built-in deserializer for InetAddress and subclasses) - .put(InetAddress.class, new DefaultInetAddressDeserializer<>(InetAddress.class)) - .put(Inet4Address.class, new DefaultInetAddressDeserializer<>(Inet4Address.class)) - .put(Inet6Address.class, new DefaultInetAddressDeserializer<>(Inet6Address.class)) - - // Geospatial types - .put(Geometry.class, new DefaultGeometryDeserializer<>(Geometry.class)) - .put(Point.class, new DefaultGeometryDeserializer<>(Point.class)) - .put(LineString.class, new DefaultGeometryDeserializer<>(LineString.class)) - .put(Polygon.class, new DefaultGeometryDeserializer<>(Polygon.class)) - .build(); - } - - private static List> createSerializers() { - return ImmutableList.>builder() - .add(new DefaultGraphNodeSerializer()) - .add(new DefaultGeometrySerializer()) - .build(); - } - } - - /** Serializers and deserializers for JSR 310 {@code java.time.*}. */ - static class GraphSON1JavaTimeModule extends SimpleModule { - - private static final long serialVersionUID = 1L; - - GraphSON1JavaTimeModule(String name, Version version) { - super(name, version, createDeserializers(), createSerializers()); - } - - private static Map, JsonDeserializer> createDeserializers() { - - return ImmutableMap., JsonDeserializer>builder() - .put(java.time.Duration.class, new DurationJacksonDeserializer()) - .put(java.time.Instant.class, new InstantJacksonDeserializer()) - .put(java.time.LocalDate.class, new LocalDateJacksonDeserializer()) - .put(java.time.LocalTime.class, new LocalTimeJacksonDeserializer()) - .build(); - } - - private static List> createSerializers() { - return ImmutableList.>builder() - .add(new DurationJacksonSerializer()) - .add(new InstantJacksonSerializer()) - .add(new LocalDateJacksonSerializer()) - .add(new LocalTimeJacksonSerializer()) - .build(); - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSON2SerdeTP.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSON2SerdeTP.java deleted file mode 100644 index 05e09b018ab..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSON2SerdeTP.java +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.data.geometry.Geometry; -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import com.datastax.dse.driver.api.core.graph.predicates.Geo; -import com.datastax.dse.driver.api.core.graph.predicates.Search; -import com.datastax.dse.driver.internal.core.data.geometry.DefaultLineString; -import com.datastax.dse.driver.internal.core.data.geometry.DefaultPoint; -import com.datastax.dse.driver.internal.core.data.geometry.DefaultPolygon; -import com.datastax.dse.driver.internal.core.data.geometry.Distance; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.apache.tinkerpop.gremlin.process.traversal.P; -import org.apache.tinkerpop.gremlin.process.traversal.util.AndP; -import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP; -import org.apache.tinkerpop.gremlin.process.traversal.util.OrP; -import org.apache.tinkerpop.gremlin.structure.io.graphson.AbstractObjectDeserializer; -import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens; -import org.apache.tinkerpop.gremlin.structure.io.graphson.TinkerPopJacksonModule; -import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator; -import org.apache.tinkerpop.shaded.jackson.core.JsonParser; -import org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext; -import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider; -import org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer; -import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer; -import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule; -import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdScalarSerializer; -import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer; - -public class GraphSON2SerdeTP { - - /** - * A Jackson Module to use for TinkerPop serialization/deserialization. It extends {@link - * org.apache.tinkerpop.gremlin.structure.io.graphson.TinkerPopJacksonModule} because of the - * specific typing format used in GraphSON. - */ - public static class DseGraphModule extends TinkerPopJacksonModule { - - private static final long serialVersionUID = 1L; - - public DseGraphModule() { - super("dse-driver-2.0"); - addSerializer(DefaultPoint.class, new PointGeometrySerializer()); - addSerializer(DefaultLineString.class, new LineStringGeometrySerializer()); - addSerializer(DefaultPolygon.class, new PolygonGeometrySerializer()); - addSerializer(Distance.class, new DistanceGeometrySerializer()); - // override TinkerPop's P predicates because of DSE's Search and Geo predicates - addSerializer(P.class, new DsePJacksonSerializer()); - addSerializer(EditDistance.class, new EditDistanceSerializer()); - - addDeserializer(DefaultLineString.class, new LineStringGeometryDeserializer()); - addDeserializer(DefaultPoint.class, new PointGeometryDeserializer()); - addDeserializer(DefaultPolygon.class, new PolygonGeometryDeserializer()); - addDeserializer(Distance.class, new DistanceGeometryDeserializer()); - // override TinkerPop's P predicates because of DSE's Search and Geo predicates - addDeserializer(P.class, new DsePJacksonDeserializer()); - } - - @SuppressWarnings("rawtypes") - @Override - public Map getTypeDefinitions() { - Map definitions = new HashMap<>(); - definitions.put(DefaultLineString.class, "LineString"); - definitions.put(DefaultPoint.class, "Point"); - definitions.put(DefaultPolygon.class, "Polygon"); - definitions.put(byte[].class, "Blob"); - definitions.put(Distance.class, "Distance"); - definitions.put(P.class, "P"); - return definitions; - } - - @Override - public String getTypeNamespace() { - return "dse"; - } - - abstract static class AbstractGeometryJacksonDeserializer - extends StdDeserializer { - - private static final long serialVersionUID = 1L; - - AbstractGeometryJacksonDeserializer(final Class clazz) { - super(clazz); - } - - public abstract T parse(final String val); - - @Override - public T deserialize( - final JsonParser jsonParser, final DeserializationContext deserializationContext) - throws IOException { - return parse(jsonParser.getText()); - } - } - - abstract static class AbstractGeometryJacksonSerializer - extends StdScalarSerializer { - - private static final long serialVersionUID = 1L; - - AbstractGeometryJacksonSerializer(final Class clazz) { - super(clazz); - } - - @Override - public void serialize( - final T value, final JsonGenerator gen, final SerializerProvider serializerProvider) - throws IOException { - gen.writeString(value.asWellKnownText()); - } - } - - public static class LineStringGeometrySerializer - extends AbstractGeometryJacksonSerializer { - - private static final long serialVersionUID = 1L; - - LineStringGeometrySerializer() { - super(LineString.class); - } - } - - public static class LineStringGeometryDeserializer - extends AbstractGeometryJacksonDeserializer { - - private static final long serialVersionUID = 1L; - - LineStringGeometryDeserializer() { - super(DefaultLineString.class); - } - - @Override - public DefaultLineString parse(final String val) { - return (DefaultLineString) LineString.fromWellKnownText(val); - } - } - - public static class PolygonGeometrySerializer - extends AbstractGeometryJacksonSerializer { - - private static final long serialVersionUID = 1L; - - PolygonGeometrySerializer() { - super(Polygon.class); - } - } - - public static class PolygonGeometryDeserializer - extends AbstractGeometryJacksonDeserializer { - - private static final long serialVersionUID = 1L; - - PolygonGeometryDeserializer() { - super(DefaultPolygon.class); - } - - @Override - public DefaultPolygon parse(final String val) { - return (DefaultPolygon) Polygon.fromWellKnownText(val); - } - } - - public static class PointGeometrySerializer extends AbstractGeometryJacksonSerializer { - - private static final long serialVersionUID = 1L; - - PointGeometrySerializer() { - super(Point.class); - } - } - - public static class PointGeometryDeserializer - extends AbstractGeometryJacksonDeserializer { - - private static final long serialVersionUID = 1L; - - PointGeometryDeserializer() { - super(DefaultPoint.class); - } - - @Override - public DefaultPoint parse(final String val) { - return (DefaultPoint) Point.fromWellKnownText(val); - } - } - - public static class DistanceGeometrySerializer - extends AbstractGeometryJacksonSerializer { - - private static final long serialVersionUID = 1L; - - DistanceGeometrySerializer() { - super(Distance.class); - } - } - - public static class DistanceGeometryDeserializer - extends AbstractGeometryJacksonDeserializer { - - private static final long serialVersionUID = 1L; - - DistanceGeometryDeserializer() { - super(Distance.class); - } - - @Override - public Distance parse(final String val) { - return Distance.fromWellKnownText(val); - } - } - - @SuppressWarnings("rawtypes") - static final class DsePJacksonSerializer extends StdScalarSerializer

{ - - private static final long serialVersionUID = 1L; - - DsePJacksonSerializer() { - super(P.class); - } - - @Override - public void serialize( - final P p, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) - throws IOException { - jsonGenerator.writeStartObject(); - jsonGenerator.writeStringField("predicateType", getPredicateType(p)); - jsonGenerator.writeStringField( - GraphSONTokens.PREDICATE, - p instanceof ConnectiveP - ? p instanceof AndP ? GraphSONTokens.AND : GraphSONTokens.OR - : p.getBiPredicate().toString()); - if (p instanceof ConnectiveP) { - jsonGenerator.writeArrayFieldStart(GraphSONTokens.VALUE); - for (final P predicate : ((ConnectiveP) p).getPredicates()) { - jsonGenerator.writeObject(predicate); - } - jsonGenerator.writeEndArray(); - } else { - if (p.getValue() instanceof Collection) { - jsonGenerator.writeArrayFieldStart(GraphSONTokens.VALUE); - for (final Object object : (Collection) p.getValue()) { - jsonGenerator.writeObject(object); - } - jsonGenerator.writeEndArray(); - } else { - jsonGenerator.writeObjectField(GraphSONTokens.VALUE, p.getValue()); - } - } - jsonGenerator.writeEndObject(); - } - - private String getPredicateType(P p) { - if (p.getBiPredicate() instanceof SearchPredicate) { - return Search.class.getSimpleName(); - } else if (p.getBiPredicate() instanceof GeoPredicate) { - return Geo.class.getSimpleName(); - } else { - return P.class.getSimpleName(); - } - } - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - static final class DsePJacksonDeserializer extends AbstractObjectDeserializer

{ - - private static final long serialVersionUID = 1L; - - DsePJacksonDeserializer() { - super(P.class); - } - - @Override - public P createObject(final Map data) { - final String predicate = (String) data.get(GraphSONTokens.PREDICATE); - final String predicateType = (String) data.get("predicateType"); - final Object value = data.get(GraphSONTokens.VALUE); - if (predicate.equals(GraphSONTokens.AND) || predicate.equals(GraphSONTokens.OR)) { - return predicate.equals(GraphSONTokens.AND) - ? new AndP((List

) value) - : new OrP((List

) value); - } else { - try { - if (value instanceof Collection) { - if (predicate.equals("between")) { - return P.between(((List) value).get(0), ((List) value).get(1)); - } else if (predicateType.equals(P.class.getSimpleName()) - && predicate.equals("inside")) { - return P.between(((List) value).get(0), ((List) value).get(1)); - } else if (predicate.equals("outside")) { - return P.outside(((List) value).get(0), ((List) value).get(1)); - } else if (predicate.equals("within")) { - return P.within((Collection) value); - } else if (predicate.equals("without")) { - return P.without((Collection) value); - } else { - return (P) - P.class.getMethod(predicate, Collection.class).invoke(null, (Collection) value); - } - } else { - if (predicate.equals(SearchPredicate.prefix.name())) { - return Search.prefix((String) value); - } else if (predicate.equals(SearchPredicate.tokenPrefix.name())) { - return Search.tokenPrefix((String) value); - } else if (predicate.equals(SearchPredicate.regex.name())) { - return Search.regex((String) value); - } else if (predicate.equals(SearchPredicate.tokenRegex.name())) { - return Search.tokenRegex((String) value); - } else if (predicate.equals(SearchPredicate.token.name())) { - return Search.token((String) value); - } else if (predicate.equals(SearchPredicate.fuzzy.name())) { - Map arguments = (Map) value; - return Search.fuzzy( - (String) arguments.get("query"), (int) arguments.get("distance")); - } else if (predicate.equals(SearchPredicate.tokenFuzzy.name())) { - Map arguments = (Map) value; - return Search.tokenFuzzy( - (String) arguments.get("query"), (int) arguments.get("distance")); - } else if (predicate.equals(SearchPredicate.phrase.name())) { - Map arguments = (Map) value; - return Search.phrase( - (String) arguments.get("query"), (int) arguments.get("distance")); - } else if (predicateType.equals(Geo.class.getSimpleName()) - && predicate.equals(GeoPredicate.inside.name())) { - return Geo.inside( - ((Distance) value).getCenter(), - ((Distance) value).getRadius(), - Geo.Unit.DEGREES); - } else if (predicateType.equals(Geo.class.getSimpleName()) - && predicate.equals(GeoPredicate.insideCartesian.name())) { - return Geo.inside(((Distance) value).getCenter(), ((Distance) value).getRadius()); - } else { - return (P) P.class.getMethod(predicate, Object.class).invoke(null, value); - } - } - } catch (final Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - } - } - - public static class EditDistanceSerializer extends StdSerializer { - - private static final long serialVersionUID = 1L; - - EditDistanceSerializer() { - super(EditDistance.class); - } - - @Override - public void serialize( - EditDistance editDistance, JsonGenerator generator, SerializerProvider provider) - throws IOException { - generator.writeObject( - ImmutableMap.of("query", editDistance.query, "distance", editDistance.distance)); - } - - @Override - public void serializeWithType( - EditDistance editDistance, - JsonGenerator generator, - SerializerProvider provider, - TypeSerializer serializer) - throws IOException { - serialize(editDistance, generator, provider); - } - } - } - - public static class DriverObjectsModule extends SimpleModule { - - private static final long serialVersionUID = 1L; - - public DriverObjectsModule() { - super("datastax-driver-module"); - addSerializer(ObjectGraphNode.class, new ObjectGraphNodeGraphSON2Serializer()); - } - - static final class ObjectGraphNodeGraphSON2Serializer extends StdSerializer { - - private static final long serialVersionUID = 1L; - - ObjectGraphNodeGraphSON2Serializer() { - super(ObjectGraphNode.class); - } - - @Override - public void serialize( - ObjectGraphNode objectGraphNode, - JsonGenerator jsonGenerator, - SerializerProvider serializerProvider) - throws IOException { - jsonGenerator.writeObject(objectGraphNode.as(Object.class)); - } - - @Override - public void serializeWithType( - ObjectGraphNode objectGraphNode, - JsonGenerator jsonGenerator, - SerializerProvider serializerProvider, - TypeSerializer typeSerializer) - throws IOException { - serialize(objectGraphNode, jsonGenerator, serializerProvider); - } - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSONUtils.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSONUtils.java deleted file mode 100644 index 02b35f7ee36..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSONUtils.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.shaded.guava.common.base.Suppliers; -import com.datastax.oss.driver.shaded.guava.common.base.Throwables; -import com.datastax.oss.driver.shaded.guava.common.cache.CacheBuilder; -import com.datastax.oss.driver.shaded.guava.common.cache.CacheLoader; -import com.datastax.oss.driver.shaded.guava.common.cache.LoadingCache; -import com.datastax.oss.protocol.internal.util.Bytes; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.function.Supplier; -import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper; -import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONReader; -import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion; -import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV2d0; -import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV2d0; -import org.apache.tinkerpop.shaded.jackson.core.Version; -import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper; - -public class GraphSONUtils { - - private static final LoadingCache OBJECT_MAPPERS = - CacheBuilder.newBuilder() - .build( - new CacheLoader() { - @Override - public ObjectMapper load(@NonNull GraphProtocol graphSubProtocol) throws Exception { - switch (graphSubProtocol) { - case GRAPHSON_1_0: - com.datastax.oss.driver.api.core.Version driverVersion = - CqlSession.OSS_DRIVER_COORDINATES.getVersion(); - Version driverJacksonVersion = - new Version( - driverVersion.getMajor(), - driverVersion.getMinor(), - driverVersion.getPatch(), - driverVersion.getPreReleaseLabels() != null - && driverVersion.getPreReleaseLabels().contains("SNAPSHOT") - ? "SNAPSHOT" - : null, - "com.datastax.dse", - "dse-java-driver-core"); - - ObjectMapper mapper = - GraphSONMapper.build() - .version(GraphSONVersion.V1_0) - .create() - .createMapper(); - mapper.registerModule( - new GraphSON1SerdeTP.GraphSON1DefaultModule( - "graph-graphson1default", driverJacksonVersion)); - mapper.registerModule( - new GraphSON1SerdeTP.GraphSON1JavaTimeModule( - "graph-graphson1javatime", driverJacksonVersion)); - - return mapper; - case GRAPHSON_2_0: - return GraphSONMapper.build() - .version(GraphSONVersion.V2_0) - .addCustomModule(GraphSONXModuleV2d0.build().create(false)) - .addRegistry(TinkerIoRegistryV2d0.instance()) - .addCustomModule(new GraphSON2SerdeTP.DseGraphModule()) - .addCustomModule(new GraphSON2SerdeTP.DriverObjectsModule()) - .create() - .createMapper(); - - default: - throw new IllegalStateException( - String.format("GraphSON sub-protocol unknown: {%s}", graphSubProtocol)); - } - } - }); - - static final Supplier GRAPHSON1_READER = - Suppliers.memoize( - () -> - GraphSONReader.build() - .mapper(GraphSONMapper.build().version(GraphSONVersion.V1_0).create()) - .create()); - - public static ByteBuffer serializeToByteBuffer(Object object, GraphProtocol graphSubProtocol) - throws IOException { - return ByteBuffer.wrap(serializeToBytes(object, graphSubProtocol)); - } - - static byte[] serializeToBytes(Object object, GraphProtocol graphSubProtocol) throws IOException { - try { - return OBJECT_MAPPERS.get(graphSubProtocol).writeValueAsBytes(object); - } catch (ExecutionException e) { - Throwables.throwIfUnchecked(e); - throw new RuntimeException(e); - } - } - - public static GraphNode createGraphNode(List data, GraphProtocol graphSubProtocol) - throws IOException { - try { - ObjectMapper mapper = OBJECT_MAPPERS.get(graphSubProtocol); - switch (graphSubProtocol) { - case GRAPHSON_1_0: - return new LegacyGraphNode(mapper.readTree(Bytes.getArray(data.get(0))), mapper); - case GRAPHSON_2_0: - return new ObjectGraphNode(mapper.readValue(Bytes.getArray(data.get(0)), Object.class)); - default: - // Should already be caught when we lookup in the cache - throw new AssertionError( - String.format("Unknown GraphSON sub-protocol: {%s}", graphSubProtocol)); - } - } catch (ExecutionException e) { - Throwables.throwIfUnchecked(e); - throw new RuntimeException(e); - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphStatementBase.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphStatementBase.java deleted file mode 100644 index b8baa2f5e49..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphStatementBase.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.oss.driver.api.core.ConsistencyLevel; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.metadata.Node; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.Map; -import net.jcip.annotations.Immutable; - -@Immutable -public abstract class GraphStatementBase> - implements GraphStatement { - private final Boolean isIdempotent; - private final Duration timeout; - private final Node node; - private final long timestamp; - private final DriverExecutionProfile executionProfile; - private final String executionProfileName; - private final Map customPayload; - private final String graphName; - private final String traversalSource; - private final String subProtocol; - private final ConsistencyLevel consistencyLevel; - private final ConsistencyLevel readConsistencyLevel; - private final ConsistencyLevel writeConsistencyLevel; - - protected GraphStatementBase( - Boolean isIdempotent, - Duration timeout, - Node node, - long timestamp, - DriverExecutionProfile executionProfile, - String executionProfileName, - Map customPayload, - String graphName, - String traversalSource, - String subProtocol, - ConsistencyLevel consistencyLevel, - ConsistencyLevel readConsistencyLevel, - ConsistencyLevel writeConsistencyLevel) { - this.isIdempotent = isIdempotent; - this.timeout = timeout; - this.node = node; - this.timestamp = timestamp; - this.executionProfile = executionProfile; - this.executionProfileName = executionProfileName; - this.customPayload = customPayload; - this.graphName = graphName; - this.traversalSource = traversalSource; - this.subProtocol = subProtocol; - this.consistencyLevel = consistencyLevel; - this.readConsistencyLevel = readConsistencyLevel; - this.writeConsistencyLevel = writeConsistencyLevel; - } - - protected abstract SelfT newInstance( - Boolean isIdempotent, - Duration timeout, - Node node, - long timestamp, - DriverExecutionProfile executionProfile, - String executionProfileName, - Map customPayload, - String graphName, - String traversalSource, - String subProtocol, - ConsistencyLevel consistencyLevel, - ConsistencyLevel readConsistencyLevel, - ConsistencyLevel writeConsistencyLevel); - - @Override - public Boolean isIdempotent() { - return isIdempotent; - } - - @NonNull - @Override - public SelfT setIdempotent(@Nullable Boolean newIdempotence) { - return newInstance( - newIdempotence, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Nullable - @Override - public Duration getTimeout() { - return timeout; - } - - @NonNull - @Override - public SelfT setTimeout(@Nullable Duration newTimeout) { - return newInstance( - isIdempotent, - newTimeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Nullable - @Override - public Node getNode() { - return node; - } - - @NonNull - @Override - public SelfT setNode(@Nullable Node newNode) { - return newInstance( - isIdempotent, - timeout, - newNode, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Override - public long getTimestamp() { - return this.timestamp; - } - - @NonNull - @Override - public SelfT setTimestamp(long newTimestamp) { - return newInstance( - isIdempotent, - timeout, - node, - newTimestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Nullable - @Override - public DriverExecutionProfile getExecutionProfile() { - return executionProfile; - } - - @NonNull - @Override - public SelfT setExecutionProfile(@Nullable DriverExecutionProfile newExecutionProfile) { - return newInstance( - isIdempotent, - timeout, - node, - timestamp, - newExecutionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Nullable - @Override - public String getExecutionProfileName() { - return executionProfileName; - } - - @NonNull - @Override - public SelfT setExecutionProfileName(@Nullable String newExecutionProfileName) { - return newInstance( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - newExecutionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @NonNull - @Override - public Map getCustomPayload() { - return customPayload; - } - - @NonNull - @Override - public SelfT setCustomPayload(@NonNull Map newCustomPayload) { - return newInstance( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - newCustomPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Nullable - @Override - public String getGraphName() { - return graphName; - } - - @NonNull - @Override - public SelfT setGraphName(@Nullable String newGraphName) { - return newInstance( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - newGraphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Nullable - @Override - public String getTraversalSource() { - return traversalSource; - } - - @NonNull - @Override - public SelfT setTraversalSource(@Nullable String newTraversalSource) { - return newInstance( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - newTraversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Nullable - @Override - public String getSubProtocol() { - return subProtocol; - } - - @NonNull - @Override - public SelfT setSubProtocol(@Nullable String newSubProtocol) { - return newInstance( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - newSubProtocol, - consistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Nullable - @Override - public ConsistencyLevel getConsistencyLevel() { - return consistencyLevel; - } - - @Override - public SelfT setConsistencyLevel(@Nullable ConsistencyLevel newConsistencyLevel) { - return newInstance( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - newConsistencyLevel, - readConsistencyLevel, - writeConsistencyLevel); - } - - @Nullable - @Override - public ConsistencyLevel getReadConsistencyLevel() { - return readConsistencyLevel; - } - - @NonNull - @Override - public SelfT setReadConsistencyLevel(@Nullable ConsistencyLevel newReadConsistencyLevel) { - return newInstance( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - newReadConsistencyLevel, - writeConsistencyLevel); - } - - @Nullable - @Override - public ConsistencyLevel getWriteConsistencyLevel() { - return writeConsistencyLevel; - } - - @NonNull - @Override - public SelfT setWriteConsistencyLevel(@Nullable ConsistencyLevel newWriteConsistencyLevel) { - return newInstance( - isIdempotent, - timeout, - node, - timestamp, - executionProfile, - executionProfileName, - customPayload, - graphName, - traversalSource, - subProtocol, - consistencyLevel, - readConsistencyLevel, - newWriteConsistencyLevel); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSupportChecker.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSupportChecker.java deleted file mode 100644 index 6e586bbcf3f..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/GraphSupportChecker.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.graph.PagingEnabledOptions; -import com.datastax.dse.driver.api.core.metadata.DseNodeProperties; -import com.datastax.dse.driver.internal.core.DseProtocolFeature; -import com.datastax.oss.driver.api.core.ProtocolVersion; -import com.datastax.oss.driver.api.core.Version; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.cql.Conversions; -import com.datastax.oss.driver.shaded.guava.common.annotations.VisibleForTesting; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Collection; -import java.util.Objects; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class GraphSupportChecker { - - private static final Logger LOG = LoggerFactory.getLogger(GraphSupportChecker.class); - - /** - * The minimum DSE version supporting both graph paging and the GraphBinary sub-protocol is DSE - * 6.8. - */ - private static final Version MIN_DSE_VERSION_GRAPH_BINARY_AND_PAGING = - Objects.requireNonNull(Version.parse("6.8.0")); - - private volatile Boolean contextGraphPagingEnabled; - private volatile Boolean isDse68OrAbove; - - /** - * Checks whether graph paging is available. - * - *

Graph paging is available if: - * - *

    - *
  1. Continuous paging is generally available (this implies protocol version {@link - * com.datastax.dse.driver.api.core.DseProtocolVersion#DSE_V1 DSE_V1} or higher); - *
  2. Graph paging is set to ENABLED or AUTO in the configuration - * with {@link DseDriverOption#GRAPH_PAGING_ENABLED}; - *
  3. If graph paging is set to AUTO, then a check will be performed to verify - * that all hosts are running DSE 6.8+; if that is the case, then graph paging will be - * assumed to be available. - *
- * - * Note that the hosts check will be done only once, then memoized; if other hosts join the - * cluster later and do not support graph paging, the user has to manually disable graph paging. - */ - public boolean isPagingEnabled( - @NonNull GraphStatement graphStatement, @NonNull InternalDriverContext context) { - DriverExecutionProfile driverExecutionProfile = - Conversions.resolveExecutionProfile(graphStatement, context); - PagingEnabledOptions pagingEnabledOptions = - PagingEnabledOptions.valueOf( - driverExecutionProfile.getString(DseDriverOption.GRAPH_PAGING_ENABLED)); - if (LOG.isTraceEnabled()) { - LOG.trace("GRAPH_PAGING_ENABLED: {}", pagingEnabledOptions); - } - if (pagingEnabledOptions == PagingEnabledOptions.DISABLED) { - return false; - } else if (pagingEnabledOptions == PagingEnabledOptions.ENABLED) { - return true; - } else { - return isContextGraphPagingEnabled(context); - } - } - - /** - * Infers the {@link GraphProtocol} to use to execute the given statement. - * - *

The graph protocol is computed as follows: - * - *

    - *
  1. If the statement declares the protocol to use with {@link - * GraphStatement#getSubProtocol()}, then that protocol is returned. - *
  2. If the driver configuration explicitly defines the protocol to use (see {@link - * DseDriverOption#GRAPH_SUB_PROTOCOL} and reference.conf), then that protocol is returned. - *
  3. Otherwise, the graph protocol to use is determined by the DSE version of hosts in the - * cluster. If any host has DSE version 6.7.x or lower, the default graph protocol is {@link - * GraphProtocol#GRAPHSON_2_0}. If all hosts have DSE version 6.8.0 or higher, the default - * graph protocol is {@link GraphProtocol#GRAPH_BINARY_1_0}. - *
- * - * Note that the hosts check will be done only once, then memoized; if other hosts join the and do - * not support the computed graph protocol, the user has to manually set the graph protocol to - * use. - * - *

Also note that GRAPH_BINARY_1_0 can only be used with "core" graph engines; if - * you are targeting a "classic" graph engine instead, the user has to manually set the graph - * protocol to something else. - */ - @NonNull - public GraphProtocol inferGraphProtocol( - @NonNull GraphStatement statement, - @NonNull DriverExecutionProfile config, - @NonNull InternalDriverContext context) { - String graphProtocol = statement.getSubProtocol(); - if (graphProtocol == null) { - // use the protocol specified in configuration, otherwise get the default from the context - graphProtocol = - config.isDefined(DseDriverOption.GRAPH_SUB_PROTOCOL) - ? config.getString(DseDriverOption.GRAPH_SUB_PROTOCOL) - : getDefaultGraphProtocol(context).toInternalCode(); - } - // should not be null because we call config.getString() with a default value - Objects.requireNonNull( - graphProtocol, - "Could not determine the graph protocol for the query. This is a bug, please report."); - - return GraphProtocol.fromString(graphProtocol); - } - - private boolean isContextGraphPagingEnabled(InternalDriverContext context) { - if (contextGraphPagingEnabled == null) { - ProtocolVersion protocolVersion = context.getProtocolVersion(); - if (!context - .getProtocolVersionRegistry() - .supports(protocolVersion, DseProtocolFeature.CONTINUOUS_PAGING)) { - contextGraphPagingEnabled = false; - } else { - if (isDse68OrAbove == null) { - isDse68OrAbove = checkIsDse68OrAbove(context); - } - contextGraphPagingEnabled = isDse68OrAbove; - } - } - return contextGraphPagingEnabled; - } - - /** - * Determines the default {@link GraphProtocol} for the given context. - * - * @return The default GraphProtocol to used based on the provided context. - */ - @VisibleForTesting - GraphProtocol getDefaultGraphProtocol(@NonNull InternalDriverContext context) { - if (isDse68OrAbove == null) { - isDse68OrAbove = checkIsDse68OrAbove(context); - } - // if the DSE version can't be determined, default to GraphSON 2.0 - return isDse68OrAbove ? GraphProtocol.GRAPH_BINARY_1_0 : GraphProtocol.GRAPHSON_2_0; - } - - private boolean checkIsDse68OrAbove(@NonNull InternalDriverContext context) { - Collection nodes = context.getMetadataManager().getMetadata().getNodes().values(); - - for (Node node : nodes) { - Version dseVersion = (Version) node.getExtras().get(DseNodeProperties.DSE_VERSION); - if (dseVersion == null || dseVersion.compareTo(MIN_DSE_VERSION_GRAPH_BINARY_AND_PAGING) < 0) { - return false; - } - } - return true; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/LegacyGraphNode.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/LegacyGraphNode.java deleted file mode 100644 index 1749bf00873..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/LegacyGraphNode.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import com.datastax.oss.driver.shaded.guava.common.base.Objects; -import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; -import java.util.Set; -import net.jcip.annotations.Immutable; -import org.apache.tinkerpop.gremlin.process.traversal.Path; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Property; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; -import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens; -import org.apache.tinkerpop.gremlin.structure.util.Attachable; -import org.apache.tinkerpop.shaded.jackson.core.JsonParser; -import org.apache.tinkerpop.shaded.jackson.databind.JavaType; -import org.apache.tinkerpop.shaded.jackson.databind.JsonNode; -import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper; - -/** - * Legacy implementation for GraphSON 1 results. - * - *

The server returns plain JSON with no type information. The driver works with the JSON - * representation directly. - */ -@Immutable -public class LegacyGraphNode implements GraphNode { - private static final String TYPE = "type"; - private static final String VERTEX_TYPE = "vertex"; - private static final String EDGE_TYPE = "edge"; - - private static final GenericType> LIST_TYPE = GenericType.listOf(Object.class); - private static final GenericType> MAP_TYPE = - GenericType.mapOf(String.class, Object.class); - - private final JsonNode delegate; - private final ObjectMapper objectMapper; - - public LegacyGraphNode(JsonNode delegate, ObjectMapper objectMapper) { - Preconditions.checkNotNull(delegate); - Preconditions.checkNotNull(objectMapper); - this.delegate = delegate; - this.objectMapper = objectMapper; - } - - /** - * The underlying JSON representation. - * - *

This is an implementation detail, it's only exposed through the internal API. - */ - public JsonNode getDelegate() { - return delegate; - } - - /** - * The object mapper used to deserialize results in {@link #as(Class)} and {@link - * #as(GenericType)}. - * - *

This is an implementation detail, it's only exposed through the internal API. - */ - public ObjectMapper getObjectMapper() { - return objectMapper; - } - - @Override - public boolean isNull() { - return delegate.isNull(); - } - - @Override - public boolean isMap() { - return delegate.isObject(); - } - - @Override - public Iterable keys() { - return (Iterable) delegate::fieldNames; - } - - @Override - public LegacyGraphNode getByKey(Object key) { - if (!(key instanceof String)) { - return null; - } - JsonNode node = delegate.get(((String) key)); - if (node == null) { - return null; - } - return new LegacyGraphNode(node, objectMapper); - } - - @Override - @SuppressWarnings("unchecked") - public Map asMap() { - return (Map) as(MAP_TYPE); - } - - @Override - public boolean isList() { - return delegate.isArray(); - } - - @Override - public int size() { - return delegate.size(); - } - - @Override - public LegacyGraphNode getByIndex(int index) { - JsonNode node = delegate.get(index); - if (node == null) { - return null; - } - return new LegacyGraphNode(node, objectMapper); - } - - @Override - @SuppressWarnings("unchecked") - public List asList() { - return (List) as(LIST_TYPE); - } - - @Override - public boolean isValue() { - return delegate.isValueNode(); - } - - @Override - public int asInt() { - return delegate.asInt(); - } - - @Override - public boolean asBoolean() { - return delegate.asBoolean(); - } - - @Override - public long asLong() { - return delegate.asLong(); - } - - @Override - public double asDouble() { - return delegate.asDouble(); - } - - @Override - public String asString() { - return delegate.asText(); - } - - @Override - public boolean isVertex() { - return isType(VERTEX_TYPE); - } - - @Override - public Vertex asVertex() { - try { - return GraphSONUtils.GRAPHSON1_READER - .get() - .readVertex( - new ByteArrayInputStream(delegate.toString().getBytes(StandardCharsets.UTF_8)), - null, - null, - null); - } catch (IOException e) { - throw new UncheckedIOException("Could not deserialize node as Vertex.", e); - } - } - - @Override - public boolean isEdge() { - return isType(EDGE_TYPE); - } - - @Override - public Edge asEdge() { - try { - return GraphSONUtils.GRAPHSON1_READER - .get() - .readEdge( - new ByteArrayInputStream(delegate.toString().getBytes(StandardCharsets.UTF_8)), - Attachable::get); - } catch (IOException e) { - throw new UncheckedIOException("Could not deserialize node as Edge.", e); - } - } - - @Override - public boolean isPath() { - return false; - } - - @Override - public Path asPath() { - throw new UnsupportedOperationException( - "GraphSON1 does not support Path, use another Graph sub-protocol such as GraphSON2."); - } - - @Override - public boolean isProperty() { - return delegate.has(GraphSONTokens.KEY) && delegate.has(GraphSONTokens.VALUE); - } - - @Override - @SuppressWarnings("unchecked") - public Property asProperty() { - try { - return GraphSONUtils.GRAPHSON1_READER - .get() - .readProperty( - new ByteArrayInputStream(delegate.toString().getBytes(StandardCharsets.UTF_8)), - Attachable::get); - } catch (IOException e) { - throw new UncheckedIOException("Could not deserialize node as Property.", e); - } - } - - @Override - public boolean isVertexProperty() { - return delegate.has(GraphSONTokens.ID) - && delegate.has(GraphSONTokens.VALUE) - && delegate.has(GraphSONTokens.LABEL); - } - - @Override - @SuppressWarnings("unchecked") - public VertexProperty asVertexProperty() { - try { - return GraphSONUtils.GRAPHSON1_READER - .get() - .readVertexProperty( - new ByteArrayInputStream(delegate.toString().getBytes(StandardCharsets.UTF_8)), - Attachable::get); - } catch (IOException e) { - throw new UncheckedIOException("Could not deserialize node as VertexProperty.", e); - } - } - - @Override - public boolean isSet() { - return false; - } - - @Override - public Set asSet() { - throw new UnsupportedOperationException( - "GraphSON1 does not support Set, use another Graph sub-protocol such as GraphSON2."); - } - - @Override - public ResultT as(Class clazz) { - try { - return objectMapper.treeToValue(delegate, clazz); - } catch (IOException e) { - throw new UncheckedIOException("Could not deserialize node as: " + clazz, e); - } - } - - @Override - public ResultT as(GenericType type) { - try { - JsonParser parser = objectMapper.treeAsTokens(delegate); - JavaType javaType = objectMapper.constructType(type.__getToken().getType()); - return objectMapper.readValue(parser, javaType); - } catch (IOException e) { - throw new UncheckedIOException("Could not deserialize node as: " + type, e); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof LegacyGraphNode)) { - return false; - } - LegacyGraphNode that = (LegacyGraphNode) o; - return Objects.equal(delegate, that.delegate); - } - - @Override - public int hashCode() { - return Objects.hashCode(delegate); - } - - @Override - public String toString() { - return delegate.toString(); - } - - private boolean isType(String expectedTypeName) { - JsonNode type = delegate.get(TYPE); - return type != null && expectedTypeName.equals(type.asText()); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/MultiPageGraphResultSet.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/MultiPageGraphResultSet.java deleted file mode 100644 index fe81d73ba00..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/MultiPageGraphResultSet.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.GraphResultSet; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import com.datastax.oss.driver.internal.core.util.concurrent.BlockingOperation; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import com.datastax.oss.driver.shaded.guava.common.collect.Lists; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -public class MultiPageGraphResultSet implements GraphResultSet { - private final RowIterator iterator; - private final List executionInfos = new ArrayList<>(); - - public MultiPageGraphResultSet(AsyncGraphResultSet firstPage) { - iterator = new RowIterator(firstPage); - executionInfos.add(firstPage.getRequestExecutionInfo()); - } - - @Override - public void cancel() { - iterator.cancel(); - } - - @NonNull - @Override - public ExecutionInfo getRequestExecutionInfo() { - return executionInfos.get(executionInfos.size() - 1); - } - - @NonNull - @Override - @Deprecated - public com.datastax.dse.driver.api.core.graph.GraphExecutionInfo getExecutionInfo() { - return GraphExecutionInfoConverter.convert(getRequestExecutionInfo()); - } - - /** - * The execution information for all the queries that have been performed so far to assemble this - * iterable. - * - *

This will have multiple elements if the query is paged, since the driver performs blocking - * background queries to fetch additional pages transparently as the result set is being iterated. - */ - @NonNull - public List getRequestExecutionInfos() { - return executionInfos; - } - - /** @deprecated use {@link #getRequestExecutionInfos()} instead. */ - @NonNull - @Deprecated - public List getExecutionInfos() { - return Lists.transform(executionInfos, GraphExecutionInfoConverter::convert); - } - - @NonNull - @Override - public Iterator iterator() { - return iterator; - } - - public class RowIterator extends CountingIterator { - private AsyncGraphResultSet currentPage; - private Iterator currentRows; - private boolean cancelled = false; - - private RowIterator(AsyncGraphResultSet firstPage) { - super(firstPage.remaining()); - currentPage = firstPage; - currentRows = firstPage.currentPage().iterator(); - } - - @Override - protected GraphNode computeNext() { - maybeMoveToNextPage(); - return currentRows.hasNext() ? currentRows.next() : endOfData(); - } - - private void maybeMoveToNextPage() { - if (!cancelled && !currentRows.hasNext() && currentPage.hasMorePages()) { - BlockingOperation.checkNotDriverThread(); - AsyncGraphResultSet nextPage = - CompletableFutures.getUninterruptibly(currentPage.fetchNextPage()); - currentPage = nextPage; - remaining += currentPage.remaining(); - currentRows = nextPage.currentPage().iterator(); - executionInfos.add(nextPage.getRequestExecutionInfo()); - } - } - - private void cancel() { - currentPage.cancel(); - cancelled = true; - } - - public boolean isCancelled() { - return cancelled; - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ObjectGraphNode.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ObjectGraphNode.java deleted file mode 100644 index 56123799fdd..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/ObjectGraphNode.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import com.datastax.oss.driver.shaded.guava.common.base.Objects; -import java.util.List; -import java.util.Map; -import java.util.Set; -import net.jcip.annotations.Immutable; -import org.apache.tinkerpop.gremlin.process.traversal.Path; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Property; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; - -/** - * Modern implementation for GraphSON 2+ results. - * - *

The server returns results with type information. The driver works with the decoded objects - * directly. - */ -@Immutable -public class ObjectGraphNode implements GraphNode { - - private final Object delegate; - - public ObjectGraphNode(Object delegate) { - this.delegate = delegate; - } - - @Override - public boolean isNull() { - return delegate == null; - } - - @Override - public boolean isMap() { - return delegate instanceof Map; - } - - @Override - public Iterable keys() { - return ((Map) delegate).keySet(); - } - - @Override - public GraphNode getByKey(Object key) { - if (!isMap()) { - return null; - } - Map map = asMap(); - if (map.containsKey(key)) { - return new ObjectGraphNode(map.get(key)); - } - return null; - } - - @Override - @SuppressWarnings("unchecked") - public Map asMap() { - return (Map) delegate; - } - - @Override - public boolean isList() { - return delegate instanceof List; - } - - @Override - public int size() { - if (isList()) { - return asList().size(); - } else if (isMap()) { - return asMap().size(); - } else if (isSet()) { - return asSet().size(); - } else { - return 0; - } - } - - @Override - public GraphNode getByIndex(int index) { - if (!isList() || index < 0 || index >= size()) { - return null; - } - return new ObjectGraphNode(asList().get(index)); - } - - @Override - @SuppressWarnings("unchecked") - public List asList() { - return (List) delegate; - } - - @Override - public boolean isValue() { - return !(isList() - || isMap() - || isSet() - || isVertex() - || isEdge() - || isPath() - || isProperty() - || isVertexProperty()); - } - - @Override - public boolean isVertexProperty() { - return delegate instanceof VertexProperty; - } - - @Override - public boolean isProperty() { - return delegate instanceof Property; - } - - @Override - public boolean isPath() { - return delegate instanceof Path; - } - - @Override - public int asInt() { - return (Integer) delegate; - } - - @Override - public boolean asBoolean() { - return (Boolean) delegate; - } - - @Override - public long asLong() { - return (Long) delegate; - } - - @Override - public double asDouble() { - return (Double) delegate; - } - - @Override - public String asString() { - return (String) delegate; - } - - @Override - @SuppressWarnings("unchecked") - public T as(Class clazz) { - return (T) delegate; - } - - @Override - @SuppressWarnings("unchecked") - public T as(GenericType type) { - return (T) delegate; - } - - @Override - public boolean isVertex() { - return delegate instanceof Vertex; - } - - @Override - public Vertex asVertex() { - return (Vertex) delegate; - } - - @Override - public boolean isEdge() { - return delegate instanceof Edge; - } - - @Override - public Edge asEdge() { - return (Edge) delegate; - } - - @Override - public Path asPath() { - return (Path) delegate; - } - - @Override - @SuppressWarnings("unchecked") - public Property asProperty() { - return (Property) delegate; - } - - @Override - @SuppressWarnings("unchecked") - public VertexProperty asVertexProperty() { - return (VertexProperty) delegate; - } - - @Override - public boolean isSet() { - return delegate instanceof Set; - } - - @Override - @SuppressWarnings("unchecked") - public Set asSet() { - return (Set) delegate; - } - - @Override - public String toString() { - return this.delegate.toString(); - } - - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } - // Compare each others' delegates. - return other instanceof ObjectGraphNode - && Objects.equal(this.delegate, ((ObjectGraphNode) other).delegate); - } - - @Override - public int hashCode() { - return Objects.hashCode(delegate); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/SearchPredicate.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/SearchPredicate.java deleted file mode 100644 index b69c3a59cf0..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/SearchPredicate.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.oss.driver.shaded.guava.common.collect.Sets; -import java.util.List; -import java.util.Set; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * List of predicates for geolocation usage with DseGraph and Search indexes. Should not be accessed - * directly but through the {@link com.datastax.dse.driver.api.core.graph.predicates.Search} static - * methods. - */ -public enum SearchPredicate implements DsePredicate { - /** Whether the text contains a given term as a token in the text (case insensitive). */ - token { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - return value != null && evaluate(value.toString(), (String) condition); - } - - boolean evaluate(String value, String terms) { - Set tokens = Sets.newHashSet(tokenize(value.toLowerCase())); - terms = terms.trim(); - List tokenTerms = tokenize(terms.toLowerCase()); - if (!terms.isEmpty() && tokenTerms.isEmpty()) { - return false; - } - for (String term : tokenTerms) { - if (!tokens.contains(term)) { - return false; - } - } - return true; - } - - @Override - public boolean isValidCondition(Object condition) { - return condition != null && isNotBlank((String) condition); - } - - @Override - public String toString() { - return "token"; - } - }, - - /** Whether the text contains a token that starts with a given term (case insensitive). */ - tokenPrefix { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - return value != null && evaluate(value.toString(), (String) condition); - } - - boolean evaluate(String value, String prefix) { - for (String token : tokenize(value.toLowerCase())) { - if (token.startsWith(prefix.toLowerCase().trim())) { - return true; - } - } - return false; - } - - @Override - public boolean isValidCondition(Object condition) { - return condition != null; - } - - @Override - public String toString() { - return "tokenPrefix"; - } - }, - - /** Whether the text contains a token that matches a regular expression (case insensitive). */ - tokenRegex { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - return value != null && evaluate(value.toString(), (String) condition); - } - - boolean evaluate(String value, String regex) { - Pattern compiled = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); - for (String token : tokenize(value.toLowerCase())) { - if (compiled.matcher(token).matches()) { - return true; - } - } - return false; - } - - @Override - public boolean isValidCondition(Object condition) { - return condition != null && isNotBlank((String) condition); - } - - @Override - public String toString() { - return "tokenRegex"; - } - }, - - /** - * Whether some token in the text is within a given edit distance from the given term (case - * insensitive). - */ - tokenFuzzy { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - if (value == null) { - return false; - } - - EditDistance fuzzyCondition = (EditDistance) condition; - - for (String token : tokenize(value.toString().toLowerCase())) { - if (SearchUtils.getOptimalStringAlignmentDistance(token, fuzzyCondition.query.toLowerCase()) - <= fuzzyCondition.distance) { - return true; - } - } - - return false; - } - - @Override - public boolean isValidCondition(Object condition) { - return condition != null; - } - - @Override - public String toString() { - return "tokenFuzzy"; - } - }, - - /** Whether the text starts with a given prefix (case sensitive). */ - prefix { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - return value != null && value.toString().startsWith(((String) condition).trim()); - } - - @Override - public boolean isValidCondition(Object condition) { - return condition != null; - } - - @Override - public String toString() { - return "prefix"; - } - }, - - /** Whether the text matches a regular expression (case sensitive). */ - regex { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - return value != null - && Pattern.compile((String) condition, Pattern.DOTALL) - .matcher(value.toString()) - .matches(); - } - - @Override - public boolean isValidCondition(Object condition) { - return condition != null && isNotBlank((String) condition); - } - - @Override - public String toString() { - return "regex"; - } - }, - - /** Whether the text is within a given edit distance from the given term (case sensitive). */ - fuzzy { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - if (value == null) { - return false; - } - EditDistance fuzzyCondition = (EditDistance) condition; - return SearchUtils.getOptimalStringAlignmentDistance(value.toString(), fuzzyCondition.query) - <= fuzzyCondition.distance; - } - - @Override - public boolean isValidCondition(Object condition) { - return condition != null; - } - - @Override - public String toString() { - return "fuzzy"; - } - }, - - /** - * Whether tokenized text contains a given phrase, optionally within a given proximity (case - * insensitive). - */ - phrase { - @Override - public boolean test(Object value, Object condition) { - preEvaluate(condition); - if (value == null) { - return false; - } - - EditDistance phraseCondition = (EditDistance) condition; - - List valueTokens = tokenize(value.toString().toLowerCase()); - List phraseTokens = tokenize(phraseCondition.query.toLowerCase()); - - int valuePosition = 0; - int phrasePosition = 0; - int distance = 0; - - // Look for matches while phrase/value tokens and distance budget remain - while (phrasePosition < phraseTokens.size() - && valuePosition < valueTokens.size() - && distance <= phraseCondition.distance) { - - if (phraseTokens.get(phrasePosition).equals(valueTokens.get(valuePosition))) { - // Early return-true when we've matched the whole phrase (within the specified distance) - if (phrasePosition == phraseTokens.size() - 1) { - return true; - } - phrasePosition++; - } else if (0 < phrasePosition) { - // We've previously found at least one matching token in the input string, - // but the current token does not match the phrase. Increment distance. - distance++; - } - - valuePosition++; - } - - return false; - } - - @Override - public boolean isValidCondition(Object condition) { - return condition != null; - } - - @Override - public String toString() { - return "phrase"; - } - }; - - private static boolean isNotBlank(String str) { - if (str == null || str.isEmpty()) { - return false; - } - int strLen = str.length(); - for (int i = 0; i < strLen; i++) { - if (!Character.isWhitespace(str.charAt(i))) { - return true; - } - } - return false; - } - - // Match anything that is not either: - // 1) a unicode letter, regardless of subcategory (same as Character.isLetter), or - // 2) a unicode decimal digit number (same as Character.isDigit) - private static final Pattern TOKEN_SPLIT_PATTERN = Pattern.compile("[^\\p{L}\\p{Nd}]"); - - static List tokenize(String str) { - String[] rawTokens = TOKEN_SPLIT_PATTERN.split(str); // could contain empty strings - return Stream.of(rawTokens).filter(t -> 0 < t.length()).collect(Collectors.toList()); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/SearchUtils.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/SearchUtils.java deleted file mode 100644 index 3440c40e87a..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/SearchUtils.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -public class SearchUtils { - - /** - * Finds the Optimal - * string alignment distance – also referred to as the Damerau-Levenshtein distance – between - * two strings. - * - *

This is the number of changes needed to change one string into another (insertions, - * deletions or substitutions of a single character, or transpositions of two adjacent - * characters). - * - *

This implementation is based on the Apache Commons Lang implementation of the Levenshtein - * distance, only adding support for transpositions. - * - *

Note that this is the distance used in Lucene for {@code FuzzyTermsEnum}. Lucene itself has - * an implementation of this algorithm, but it is much less efficient in terms of space (also note - * that Lucene's implementation does not return the distance, but a similarity score based on it). - * - * @param s the first string, must not be {@code null}. - * @param t the second string, must not be {@code null}. - * @return The Optimal string alignment distance between the two strings. - * @throws IllegalArgumentException if either String input is {@code null}. - * @see org.apache.commons.lang.StringUtils#getLevenshteinDistance(String, String) - * @see - * LuceneLevenshteinDistance - */ - public static int getOptimalStringAlignmentDistance(String s, String t) { - - /* - * Code adapted from https://github.com/apache/commons-lang/blob/LANG_2_6/src/main/java/org/apache/commons/lang/StringUtils.java - * which was originally released under the Apache 2.0 license with the following copyright: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - if (s == null || t == null) { - throw new IllegalArgumentException("Strings must not be null"); - } - - int n = s.length(); // length of s - int m = t.length(); // length of t - - if (n == 0) { - return m; - } else if (m == 0) { - return n; - } - - if (n > m) { - // swap the input strings to consume less memory - String tmp = s; - s = t; - t = tmp; - n = m; - m = t.length(); - } - - // instead of maintaining the full matrix in memory, - // we use a sliding window containing 3 lines: - // the current line being written to, and - // the two previous ones. - - int d[] = new int[n + 1]; // current line in the cost matrix - int p1[] = new int[n + 1]; // first line above the current one in the cost matrix - int p2[] = new int[n + 1]; // second line above the current one in the cost matrix - int _d[]; // placeholder to assist in swapping p1, p2 and d - - // indexes into strings s and t - int i; // iterates through s - int j; // iterates through t - - for (i = 0; i <= n; i++) { - p1[i] = i; - } - - for (j = 1; j <= m; j++) { - - // jth character of t - char t_j = t.charAt(j - 1); - d[0] = j; - - for (i = 1; i <= n; i++) { - - char s_i = s.charAt(i - 1); - int cost = s_i == t_j ? 0 : 1; - - int deletion = d[i - 1] + 1; // cell to the left + 1 - int insertion = p1[i] + 1; // cell to the top + 1 - int substitution = p1[i - 1] + cost; // cell diagonally left and up + cost - - d[i] = Math.min(Math.min(deletion, insertion), substitution); - - // transposition - if (i > 1 && j > 1 && s_i == t.charAt(j - 2) && s.charAt(i - 2) == t_j) { - d[i] = Math.min(d[i], p2[i - 2] + cost); - } - } - - // swap arrays - _d = p2; - p2 = p1; - p1 = d; - d = _d; - } - - // our last action in the above loop was to switch d and p1, so p1 now - // actually has the most recent cost counts - return p1[n]; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/SinglePageGraphResultSet.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/SinglePageGraphResultSet.java deleted file mode 100644 index ff1d984d745..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/SinglePageGraphResultSet.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.GraphResultSet; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Iterator; -import net.jcip.annotations.NotThreadSafe; - -@NotThreadSafe -public class SinglePageGraphResultSet implements GraphResultSet { - - private final AsyncGraphResultSet onlyPage; - - public SinglePageGraphResultSet(AsyncGraphResultSet onlyPage) { - this.onlyPage = onlyPage; - assert !onlyPage.hasMorePages(); - } - - @NonNull - @Override - public ExecutionInfo getRequestExecutionInfo() { - return onlyPage.getRequestExecutionInfo(); - } - - @NonNull - @Override - @Deprecated - public com.datastax.dse.driver.api.core.graph.GraphExecutionInfo getExecutionInfo() { - return onlyPage.getExecutionInfo(); - } - - @NonNull - @Override - public Iterator iterator() { - return onlyPage.currentPage().iterator(); - } - - @Override - public void cancel() { - onlyPage.cancel(); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/TinkerpopBufferUtil.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/TinkerpopBufferUtil.java deleted file mode 100644 index 5650d904350..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/TinkerpopBufferUtil.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import java.nio.ByteBuffer; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; - -/** Mirror of {@link ByteBufUtil} for Tinkerpop Buffer's */ -public class TinkerpopBufferUtil { - - public static ByteBuffer readBytes(Buffer tinkerBuff, int size) { - ByteBuffer res = ByteBuffer.allocate(size); - tinkerBuff.readBytes(res); - res.flip(); - return res; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/AbstractDynamicGraphBinaryCustomSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/AbstractDynamicGraphBinaryCustomSerializer.java deleted file mode 100644 index 649f5310c5d..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/AbstractDynamicGraphBinaryCustomSerializer.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import java.io.IOException; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; - -/** - * Convenience class for dynamic types implemented as Custom types in GraphBinary. This class will - * take care of handling {value_length} automatically for implementing classes. {@link - * #writeDynamicCustomValue(Object, Buffer, GraphBinaryWriter)} and {@link - * #readDynamicCustomValue(Buffer, GraphBinaryReader)} only need to handle writing the internal - * components of the custom type. - * - * @param the java type the implementing classes will encode and decode. - */ -public abstract class AbstractDynamicGraphBinaryCustomSerializer - extends AbstractSimpleGraphBinaryCustomSerializer { - protected abstract void writeDynamicCustomValue(T value, Buffer buffer, GraphBinaryWriter context) - throws IOException; - - protected abstract T readDynamicCustomValue(Buffer buffer, GraphBinaryReader context) - throws IOException; - - @Override - protected T readCustomValue(int valueLength, Buffer buffer, GraphBinaryReader context) - throws IOException { - int initialIndex = buffer.readerIndex(); - - // read actual custom value - T read = readDynamicCustomValue(buffer, context); - - // make sure we didn't read more than what was input as {value_length} - checkValueSize(valueLength, (buffer.readerIndex() - initialIndex)); - - return read; - } - - @Override - protected void writeCustomValue(T value, Buffer buffer, GraphBinaryWriter context) - throws IOException { - // Store the current writer index - final int valueLengthIndex = buffer.writerIndex(); - - // Write a dummy length that will be overwritten at the end of this method - buffer.writeInt(0); - - // Custom type's writer logic - writeDynamicCustomValue(value, buffer, context); - - // value_length = diff written - 4 bytes for the dummy length - final int valueLength = buffer.writerIndex() - valueLengthIndex - GraphBinaryUtils.sizeOfInt(); - - // Go back, write the {value_length} and then reset back the writer index - buffer.markWriterIndex().writerIndex(valueLengthIndex).writeInt(valueLength).resetWriterIndex(); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/AbstractSimpleGraphBinaryCustomSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/AbstractSimpleGraphBinaryCustomSerializer.java deleted file mode 100644 index 6dd149707e8..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/AbstractSimpleGraphBinaryCustomSerializer.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; -import java.io.IOException; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.DataType; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; -import org.apache.tinkerpop.gremlin.structure.io.binary.types.CustomTypeSerializer; - -/** - * A base custom type serializer for DSE types that handles most of the boiler plate code associated - * with GraphBinary's custom types. - * - *

The full format of a custom type in GraphBinary is the following: - * - *

{type_code}{custom_type_name}{custom_type_info_length}{custom_type_info_bytes}{value_flag}{value_length}{value_bytes} - * - *

This class is made to handle - * {type_code}{custom_type_name}{custom_type_info_length}{custom_type_info_bytes}{value_flag} for - * DSE types. - * - *

Implementing classes are still in charge of encoding {value_length}{value_bytes} in the {@link - * #readCustomValue(int, Buffer, GraphBinaryReader)} implementations. - * - *

Implementing classes must override {@link CustomTypeSerializer#getTypeName()} with their own - * type name. - * - * @param the java type the implementing classes will encode and decode. - */ -abstract class AbstractSimpleGraphBinaryCustomSerializer implements CustomTypeSerializer { - AbstractSimpleGraphBinaryCustomSerializer() { - super(); - } - - protected static final String INCORRECT_VALUE_LENGTH_ERROR_MESSAGE = - "{value_length} read for this value does not correspond to the size of a '%s' value. [%s] bytes required but got [%s]"; - - protected abstract T readCustomValue(int valueLength, Buffer buffer, GraphBinaryReader context) - throws IOException; - - protected abstract void writeCustomValue(T value, Buffer buffer, GraphBinaryWriter context) - throws IOException; - - protected void checkValueSize(int lengthRequired, int lengthFound) { - Preconditions.checkArgument( - lengthFound == lengthRequired, - INCORRECT_VALUE_LENGTH_ERROR_MESSAGE, - getTypeName(), - lengthRequired, - lengthFound); - } - - @Override - public DataType getDataType() { - return DataType.CUSTOM; - } - - @Override - public T read(Buffer buffer, GraphBinaryReader context) throws IOException { - // the type serializer registry will take care of deserializing {custom_type_name} - // read {custom_type_info_length} and verify it is 0. - // See #write(T, ByteBuf, GraphBinaryWriter) for why it is set to 0 - if (context.readValue(buffer, Integer.class, false) != 0) { - throw new IOException("{custom_type_info} should not be provided for this custom type"); - } - - return readValue(buffer, context, true); - } - - @Override - public T readValue(Buffer buffer, GraphBinaryReader context, boolean nullable) - throws IOException { - if (nullable) { - // read {value_flag} - final byte valueFlag = buffer.readByte(); - - // if value is null and the value is nullable - if ((valueFlag & 1) == 1) { - return null; - } - // Note: we don't error out if the valueFlag == "value is null" and nullable == false because - // the serializer - // should have errored out at write time if that was the case. - } - - // Read the byte length of the value bytes - final int valueLength = buffer.readInt(); - - if (valueLength <= 0) { - throw new IOException(String.format("Unexpected value length: %d", valueLength)); - } - - if (valueLength > buffer.readableBytes()) { - throw new IOException( - String.format( - "Not enough readable bytes: %d bytes required for value (%d bytes available)", - valueLength, buffer.readableBytes())); - } - - // subclasses are responsible for reading {value} - return readCustomValue(valueLength, buffer, context); - } - - @Override - public void write(final T value, final Buffer buffer, final GraphBinaryWriter context) - throws IOException { - // the type serializer registry will take care of serializing {custom_type_name} - // write "{custom_type_info_length}" to 0 because we don't need it for the DSE types - context.writeValue(0, buffer, false); - writeValue(value, buffer, context, true); - } - - @Override - public void writeValue( - final T value, final Buffer buffer, final GraphBinaryWriter context, final boolean nullable) - throws IOException { - if (value == null) { - if (!nullable) { - throw new IOException("Unexpected null value when nullable is false"); - } - - // writes {value_flag} to "1" which means "the value is null" - context.writeValueFlagNull(buffer); - return; - } - - if (nullable) { - // writes {value_flag} to "0" which means "value is not null" - context.writeValueFlagNone(buffer); - } - - // sub classes will be responsible for writing {value_length} and {value_bytes} - writeCustomValue(value, buffer, context); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/ComplexTypeSerializerUtil.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/ComplexTypeSerializerUtil.java deleted file mode 100644 index bec3c78743a..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/ComplexTypeSerializerUtil.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.dse.driver.internal.core.graph.TinkerpopBufferUtil; -import com.datastax.dse.driver.internal.core.graph.binary.buffer.DseNettyBufferFactory; -import com.datastax.dse.driver.internal.core.protocol.TinkerpopBufferPrimitiveCodec; -import com.datastax.oss.driver.api.core.data.GettableByIndex; -import com.datastax.oss.driver.api.core.data.SettableByIndex; -import com.datastax.oss.driver.api.core.type.CustomType; -import com.datastax.oss.driver.api.core.type.DataType; -import com.datastax.oss.driver.api.core.type.ListType; -import com.datastax.oss.driver.api.core.type.MapType; -import com.datastax.oss.driver.api.core.type.SetType; -import com.datastax.oss.driver.api.core.type.TupleType; -import com.datastax.oss.driver.api.core.type.UserDefinedType; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import com.datastax.oss.driver.internal.core.type.DataTypeHelper; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import com.datastax.oss.protocol.internal.PrimitiveCodec; -import com.datastax.oss.protocol.internal.ProtocolConstants; -import com.datastax.oss.protocol.internal.response.result.RawType; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.Objects; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; - -class ComplexTypeSerializerUtil { - - private static final PrimitiveCodec codec = - new TinkerpopBufferPrimitiveCodec(new DseNettyBufferFactory()); - - static void encodeTypeDefinition( - DataType type, Buffer buffer, DefaultDriverContext driverContext) { - RawType protocolType = toProtocolSpec(type); - protocolType.encode(buffer, codec, driverContext.getProtocolVersion().getCode()); - } - - static DataType decodeTypeDefinition(Buffer buffer, DefaultDriverContext driverContext) { - RawType type = RawType.decode(buffer, codec, driverContext.getProtocolVersion().getCode()); - return DataTypeHelper.fromProtocolSpec(type, driverContext); - } - - /* Tinkerpop-based encoding of UDT values, based on the UdtCoded.encode() method, but using Tinkerpop buffers directly to avoid - unnecessary NIO ByteBuffer copies. */ - static void encodeValue(@Nullable GettableByIndex value, Buffer tinkerBuff) { - if (value == null) { - return; - } - - for (int i = 0; i < value.size(); i++) { - ByteBuffer fieldBuffer = value.getBytesUnsafe(i); - if (fieldBuffer == null) { - tinkerBuff.writeInt(-1); - } else { - tinkerBuff.writeInt(fieldBuffer.remaining()); - tinkerBuff.writeBytes(fieldBuffer.duplicate()); - } - } - } - - /* This method will move forward the Tinkerpop buffer given in parameter based on the UDT value read. - Content of the method is roughly equivalent to UdtCodec.decode(), but using Tinkerpop buffers directly to avoid - unnecessary NIO ByteBuffer copies. */ - static > T decodeValue(Buffer tinkerBuff, T val, int size) { - try { - for (int i = 0; i < size; i++) { - int fieldSize = tinkerBuff.readInt(); - if (fieldSize >= 0) { - // the reassignment is to shut down the error-prone warning about ignoring return values. - val = val.setBytesUnsafe(i, TinkerpopBufferUtil.readBytes(tinkerBuff, fieldSize)); - } - } - return val; - } catch (BufferUnderflowException e) { - throw new IllegalArgumentException("Not enough bytes to deserialize a UDT value", e); - } - } - - private static RawType toProtocolSpec(DataType dataType) { - int id = dataType.getProtocolCode(); - RawType type = RawType.PRIMITIVES.get(id); - if (type != null) { - return type; - } - - switch (id) { - case ProtocolConstants.DataType.CUSTOM: - CustomType customType = ((CustomType) dataType); - type = new RawType.RawCustom(customType.getClassName()); - break; - case ProtocolConstants.DataType.LIST: - ListType listType = ((ListType) dataType); - type = new RawType.RawList(toProtocolSpec(listType.getElementType())); - break; - case ProtocolConstants.DataType.SET: - SetType setType = ((SetType) dataType); - type = new RawType.RawSet(toProtocolSpec(setType.getElementType())); - break; - case ProtocolConstants.DataType.MAP: - MapType mapType = ((MapType) dataType); - type = - new RawType.RawMap( - toProtocolSpec(mapType.getKeyType()), toProtocolSpec(mapType.getValueType())); - break; - case ProtocolConstants.DataType.TUPLE: - TupleType tupleType = ((TupleType) dataType); - ImmutableList.Builder subTypesList = - ImmutableList.builderWithExpectedSize(tupleType.getComponentTypes().size()); - for (int i = 0; i < tupleType.getComponentTypes().size(); i++) { - subTypesList.add(toProtocolSpec(tupleType.getComponentTypes().get(i))); - } - type = new RawType.RawTuple(subTypesList.build()); - break; - case ProtocolConstants.DataType.UDT: - UserDefinedType userDefinedType = ((UserDefinedType) dataType); - ImmutableMap.Builder subTypesMap = - ImmutableMap.builderWithExpectedSize(userDefinedType.getFieldNames().size()); - for (int i = 0; i < userDefinedType.getFieldTypes().size(); i++) { - subTypesMap.put( - userDefinedType.getFieldNames().get(i).asInternal(), - toProtocolSpec(userDefinedType.getFieldTypes().get(i))); - } - type = - new RawType.RawUdt( - Objects.requireNonNull(userDefinedType.getKeyspace()).asInternal(), - userDefinedType.getName().asInternal(), - subTypesMap.build()); - break; - default: - throw new IllegalArgumentException("Unsupported type: " + dataType.asCql(true, true)); - } - return type; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/CqlDurationSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/CqlDurationSerializer.java deleted file mode 100644 index 1ac97de0ef4..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/CqlDurationSerializer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.oss.driver.api.core.data.CqlDuration; -import java.io.IOException; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; - -public class CqlDurationSerializer extends AbstractSimpleGraphBinaryCustomSerializer { - - @Override - public String getTypeName() { - return GraphBinaryModule.GRAPH_BINARY_DURATION_TYPE_NAME; - } - - @Override - protected CqlDuration readCustomValue( - final int valueLength, final Buffer buffer, final GraphBinaryReader context) - throws IOException { - checkValueSize(GraphBinaryUtils.sizeOfDuration(), valueLength); - return CqlDuration.newInstance( - context.readValue(buffer, Integer.class, false), - context.readValue(buffer, Integer.class, false), - context.readValue(buffer, Long.class, false)); - } - - @Override - protected void writeCustomValue(CqlDuration value, Buffer buffer, GraphBinaryWriter context) - throws IOException { - context.writeValue(GraphBinaryUtils.sizeOfDuration(), buffer, false); - context.writeValue(value.getMonths(), buffer, false); - context.writeValue(value.getDays(), buffer, false); - context.writeValue(value.getNanoseconds(), buffer, false); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/DistanceSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/DistanceSerializer.java deleted file mode 100644 index 9e281b2b84a..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/DistanceSerializer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.internal.core.data.geometry.Distance; -import java.io.IOException; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; - -public class DistanceSerializer extends AbstractSimpleGraphBinaryCustomSerializer { - @Override - public String getTypeName() { - return GraphBinaryModule.GRAPH_BINARY_DISTANCE_TYPE_NAME; - } - - @Override - protected Distance readCustomValue(int valueLength, Buffer buffer, GraphBinaryReader context) - throws IOException { - Point p = context.readValue(buffer, Point.class, false); - checkValueSize(GraphBinaryUtils.sizeOfDistance(p), valueLength); - return new Distance(p, context.readValue(buffer, Double.class, false)); - } - - @Override - protected void writeCustomValue(Distance value, Buffer buffer, GraphBinaryWriter context) - throws IOException { - context.writeValue(GraphBinaryUtils.sizeOfDistance(value.getCenter()), buffer, false); - context.writeValue(value.getCenter(), buffer, false); - context.writeValue(value.getRadius(), buffer, false); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/EditDistanceSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/EditDistanceSerializer.java deleted file mode 100644 index b2831040123..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/EditDistanceSerializer.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.dse.driver.internal.core.graph.EditDistance; -import java.io.IOException; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; - -public class EditDistanceSerializer - extends AbstractSimpleGraphBinaryCustomSerializer { - @Override - public String getTypeName() { - return GraphBinaryModule.GRAPH_BINARY_EDIT_DISTANCE_TYPE_NAME; - } - - @Override - protected EditDistance readCustomValue(int valueLength, Buffer buffer, GraphBinaryReader context) - throws IOException { - int distance = context.readValue(buffer, Integer.class, false); - String query = context.readValue(buffer, String.class, false); - checkValueSize(GraphBinaryUtils.sizeOfEditDistance(query), valueLength); - - return new EditDistance(query, distance); - } - - @Override - protected void writeCustomValue(EditDistance value, Buffer buffer, GraphBinaryWriter context) - throws IOException { - context.writeValue(GraphBinaryUtils.sizeOfEditDistance(value.query), buffer, false); - context.writeValue(value.distance, buffer, false); - context.writeValue(value.query, buffer, false); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GeometrySerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GeometrySerializer.java deleted file mode 100644 index 996e79c7693..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GeometrySerializer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.dse.driver.api.core.data.geometry.Geometry; -import com.datastax.dse.driver.internal.core.graph.TinkerpopBufferUtil; -import java.io.IOException; -import java.nio.ByteBuffer; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; - -public abstract class GeometrySerializer - extends AbstractSimpleGraphBinaryCustomSerializer { - public abstract T fromWellKnownBinary(ByteBuffer buffer); - - @Override - protected T readCustomValue(int valueLength, Buffer buffer, GraphBinaryReader context) - throws IOException { - return fromWellKnownBinary(TinkerpopBufferUtil.readBytes(buffer, valueLength)); - } - - @Override - protected void writeCustomValue(T value, Buffer buffer, GraphBinaryWriter context) - throws IOException { - ByteBuffer bb = value.asWellKnownBinary(); - - // writing the {value_length} - context.writeValue(bb.remaining(), buffer, false); - buffer.writeBytes(bb); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GraphBinaryModule.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GraphBinaryModule.java deleted file mode 100644 index 59f966a34c2..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GraphBinaryModule.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import com.datastax.dse.driver.internal.core.data.geometry.Distance; -import com.datastax.dse.driver.internal.core.graph.EditDistance; -import com.datastax.dse.driver.internal.core.graph.binary.buffer.DseNettyBufferFactory; -import com.datastax.oss.driver.api.core.data.CqlDuration; -import com.datastax.oss.driver.api.core.data.TupleValue; -import com.datastax.oss.driver.api.core.data.UdtValue; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.UnpooledByteBufAllocator; -import java.io.IOException; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.BufferFactory; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; -import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry; -import org.javatuples.Pair; - -public class GraphBinaryModule { - public static final UnpooledByteBufAllocator ALLOCATOR = new UnpooledByteBufAllocator(false); - private static final BufferFactory FACTORY = new DseNettyBufferFactory(); - - static final String GRAPH_BINARY_POINT_TYPE_NAME = "driver.dse.geometry.Point"; - static final String GRAPH_BINARY_LINESTRING_TYPE_NAME = "driver.dse.geometry.LineString"; - static final String GRAPH_BINARY_POLYGON_TYPE_NAME = "driver.dse.geometry.Polygon"; - static final String GRAPH_BINARY_DISTANCE_TYPE_NAME = "driver.dse.geometry.Distance"; - static final String GRAPH_BINARY_DURATION_TYPE_NAME = "driver.core.Duration"; - static final String GRAPH_BINARY_EDIT_DISTANCE_TYPE_NAME = "driver.dse.search.EditDistance"; - static final String GRAPH_BINARY_TUPLE_VALUE_TYPE_NAME = "driver.core.TupleValue"; - static final String GRAPH_BINARY_UDT_VALUE_TYPE_NAME = "driver.core.UDTValue"; - static final String GRAPH_BINARY_PAIR_TYPE_NAME = "org.javatuples.Pair"; - - private final GraphBinaryReader reader; - private final GraphBinaryWriter writer; - - public GraphBinaryModule(GraphBinaryReader reader, GraphBinaryWriter writer) { - this.reader = reader; - this.writer = writer; - } - - public static TypeSerializerRegistry createDseTypeSerializerRegistry( - DefaultDriverContext driverContext) { - return TypeSerializerRegistry.build() - .addCustomType(CqlDuration.class, new CqlDurationSerializer()) - .addCustomType(Point.class, new PointSerializer()) - .addCustomType(LineString.class, new LineStringSerializer()) - .addCustomType(Polygon.class, new PolygonSerializer()) - .addCustomType(Distance.class, new DistanceSerializer()) - .addCustomType(EditDistance.class, new EditDistanceSerializer()) - .addCustomType(TupleValue.class, new TupleValueSerializer(driverContext)) - .addCustomType(UdtValue.class, new UdtValueSerializer(driverContext)) - .addCustomType(Pair.class, new PairSerializer()) - .create(); - } - - @SuppressWarnings("TypeParameterUnusedInFormals") - public T deserialize(final Buffer buffer) throws IOException { - return reader.read(buffer); - } - - public Buffer serialize(final T value) throws IOException { - return serialize(value, FACTORY.create(ALLOCATOR.heapBuffer())); - } - - public Buffer serialize(final T value, final Buffer buffer) throws IOException { - try { - writer.write(value, buffer); - return buffer; - } catch (Exception e) { - buffer.release(); - throw e; - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GraphBinaryUtils.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GraphBinaryUtils.java deleted file mode 100644 index 42283cd5167..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/GraphBinaryUtils.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.dse.driver.api.core.data.geometry.Point; -import java.nio.charset.StandardCharsets; - -class GraphBinaryUtils { - static int sizeOfInt() { - return 4; - } - - static int sizeOfLong() { - return 8; - } - - static int sizeOfDouble() { - return 8; - } - - static int sizeOfPoint(Point point) { - return point.asWellKnownBinary().remaining(); - } - - /* assumes UTF8 */ - static int sizeOfString(String s) { - // length + data length - return sizeOfInt() + s.getBytes(StandardCharsets.UTF_8).length; - } - - static int sizeOfDuration() { - return sizeOfInt() + sizeOfInt() + sizeOfLong(); - } - - static int sizeOfDistance(Point point) { - return sizeOfPoint(point) + sizeOfDouble(); - } - - static int sizeOfEditDistance(String s) { - return sizeOfInt() + sizeOfString(s); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/LineStringSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/LineStringSerializer.java deleted file mode 100644 index 4dfa8f8f0f1..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/LineStringSerializer.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import java.nio.ByteBuffer; - -public class LineStringSerializer extends GeometrySerializer { - @Override - public String getTypeName() { - return GraphBinaryModule.GRAPH_BINARY_LINESTRING_TYPE_NAME; - } - - @Override - public LineString fromWellKnownBinary(ByteBuffer buffer) { - return LineString.fromWellKnownBinary(buffer); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PairSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PairSerializer.java deleted file mode 100644 index 3f13dd5b3a0..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PairSerializer.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import java.io.IOException; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; -import org.javatuples.Pair; - -public class PairSerializer extends AbstractDynamicGraphBinaryCustomSerializer { - - @Override - public String getTypeName() { - return GraphBinaryModule.GRAPH_BINARY_PAIR_TYPE_NAME; - } - - @Override - protected Pair readDynamicCustomValue(Buffer buffer, GraphBinaryReader context) - throws IOException { - return new Pair<>(context.read(buffer), context.read(buffer)); - } - - @Override - protected void writeDynamicCustomValue(Pair value, Buffer buffer, GraphBinaryWriter context) - throws IOException { - context.write(value.getValue0(), buffer); - context.write(value.getValue1(), buffer); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PointSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PointSerializer.java deleted file mode 100644 index 2204b0da073..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PointSerializer.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.dse.driver.api.core.data.geometry.Point; -import java.nio.ByteBuffer; - -public class PointSerializer extends GeometrySerializer { - - @Override - public String getTypeName() { - return GraphBinaryModule.GRAPH_BINARY_POINT_TYPE_NAME; - } - - @Override - public Point fromWellKnownBinary(ByteBuffer buffer) { - return Point.fromWellKnownBinary(buffer); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PolygonSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PolygonSerializer.java deleted file mode 100644 index 8e3bc67838a..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/PolygonSerializer.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import java.nio.ByteBuffer; - -public class PolygonSerializer extends GeometrySerializer { - @Override - public String getTypeName() { - return GraphBinaryModule.GRAPH_BINARY_POLYGON_TYPE_NAME; - } - - @Override - public Polygon fromWellKnownBinary(ByteBuffer buffer) { - return Polygon.fromWellKnownBinary(buffer); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/TupleValueSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/TupleValueSerializer.java deleted file mode 100644 index b7c6fc2098d..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/TupleValueSerializer.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.oss.driver.api.core.data.TupleValue; -import com.datastax.oss.driver.api.core.type.DataType; -import com.datastax.oss.driver.api.core.type.TupleType; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import java.io.IOException; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; - -public class TupleValueSerializer extends AbstractDynamicGraphBinaryCustomSerializer { - - private final DefaultDriverContext driverContext; - - public TupleValueSerializer(DefaultDriverContext driverContext) { - this.driverContext = driverContext; - } - - @Override - public String getTypeName() { - return GraphBinaryModule.GRAPH_BINARY_TUPLE_VALUE_TYPE_NAME; - } - - @Override - public TupleValue readDynamicCustomValue(Buffer buffer, GraphBinaryReader context) - throws IOException { - // read the type first - DataType type = ComplexTypeSerializerUtil.decodeTypeDefinition(buffer, driverContext); - - assert type instanceof TupleType - : "GraphBinary TupleValue deserializer was called on a value that is not encoded as a TupleValue."; - - TupleType tupleType = (TupleType) type; - TupleValue value = tupleType.newValue(); - - // then decode the values from the buffer - return ComplexTypeSerializerUtil.decodeValue( - buffer, value, tupleType.getComponentTypes().size()); - } - - @Override - public void writeDynamicCustomValue(TupleValue value, Buffer buffer, GraphBinaryWriter context) - throws IOException { - // write type first in native protocol - ComplexTypeSerializerUtil.encodeTypeDefinition(value.getType(), buffer, driverContext); - - // write value after - ComplexTypeSerializerUtil.encodeValue(value, buffer); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/UdtValueSerializer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/UdtValueSerializer.java deleted file mode 100644 index 3e617ebf926..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/UdtValueSerializer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import com.datastax.oss.driver.api.core.data.UdtValue; -import com.datastax.oss.driver.api.core.type.DataType; -import com.datastax.oss.driver.api.core.type.UserDefinedType; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import java.io.IOException; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; - -public class UdtValueSerializer extends AbstractDynamicGraphBinaryCustomSerializer { - private final DefaultDriverContext driverContext; - - public UdtValueSerializer(DefaultDriverContext driverContext) { - this.driverContext = driverContext; - } - - @Override - public String getTypeName() { - return GraphBinaryModule.GRAPH_BINARY_UDT_VALUE_TYPE_NAME; - } - - @Override - public UdtValue readDynamicCustomValue(Buffer buffer, GraphBinaryReader context) - throws IOException { - // read type definition first - DataType driverType = ComplexTypeSerializerUtil.decodeTypeDefinition(buffer, driverContext); - - assert driverType instanceof UserDefinedType - : "GraphBinary UdtValue deserializer was called on a value that is not encoded as a UdtValue."; - - UserDefinedType userDefinedType = (UserDefinedType) driverType; - UdtValue value = userDefinedType.newValue(); - - // then read values - return ComplexTypeSerializerUtil.decodeValue( - buffer, value, userDefinedType.getFieldTypes().size()); - } - - @Override - public void writeDynamicCustomValue(UdtValue value, Buffer buffer, GraphBinaryWriter context) - throws IOException { - // write type first in native protocol format - ComplexTypeSerializerUtil.encodeTypeDefinition(value.getType(), buffer, driverContext); - // write value after - ComplexTypeSerializerUtil.encodeValue(value, buffer); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/buffer/DseNettyBuffer.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/buffer/DseNettyBuffer.java deleted file mode 100644 index 590ac2e9be2..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/buffer/DseNettyBuffer.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary.buffer; - -import io.netty.buffer.ByteBuf; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; - -/** - * Internal impl of Tinkerpop Buffers. We implement an internal type here to allow for this class to - * use shaded Netty types (without bringing all of Tinkerpop into the shaded JAR). The impl is based - * on the initial impl of {@link NettyBuffer} but we don't guarantee that this class will mirror - * changes to that class over time. - */ -final class DseNettyBuffer implements Buffer { - private final ByteBuf buffer; - - /** - * Creates a new instance. - * - * @param buffer The buffer to wrap. - */ - DseNettyBuffer(ByteBuf buffer) { - if (buffer == null) { - throw new IllegalArgumentException("buffer can't be null"); - } - - this.buffer = buffer; - } - - @Override - public int readableBytes() { - return this.buffer.readableBytes(); - } - - @Override - public int readerIndex() { - return this.buffer.readerIndex(); - } - - @Override - public Buffer readerIndex(final int readerIndex) { - this.buffer.readerIndex(readerIndex); - return this; - } - - @Override - public int writerIndex() { - return this.buffer.writerIndex(); - } - - @Override - public Buffer writerIndex(final int writerIndex) { - this.buffer.writerIndex(writerIndex); - return this; - } - - @Override - public Buffer markWriterIndex() { - this.buffer.markWriterIndex(); - return this; - } - - @Override - public Buffer resetWriterIndex() { - this.buffer.resetWriterIndex(); - return this; - } - - @Override - public int capacity() { - return this.buffer.capacity(); - } - - @Override - public boolean isDirect() { - return this.buffer.isDirect(); - } - - @Override - public boolean readBoolean() { - return this.buffer.readBoolean(); - } - - @Override - public byte readByte() { - return this.buffer.readByte(); - } - - @Override - public short readShort() { - return this.buffer.readShort(); - } - - @Override - public int readInt() { - return this.buffer.readInt(); - } - - @Override - public long readLong() { - return this.buffer.readLong(); - } - - @Override - public float readFloat() { - return this.buffer.readFloat(); - } - - @Override - public double readDouble() { - return this.buffer.readDouble(); - } - - @Override - public Buffer readBytes(final byte[] destination) { - this.buffer.readBytes(destination); - return this; - } - - @Override - public Buffer readBytes(final byte[] destination, final int dstIndex, final int length) { - this.buffer.readBytes(destination, dstIndex, length); - return this; - } - - @Override - public Buffer readBytes(final ByteBuffer dst) { - this.buffer.readBytes(dst); - return this; - } - - @Override - public Buffer readBytes(final OutputStream out, final int length) throws IOException { - this.buffer.readBytes(out, length); - return this; - } - - @Override - public Buffer writeBoolean(final boolean value) { - this.buffer.writeBoolean(value); - return this; - } - - @Override - public Buffer writeByte(final int value) { - this.buffer.writeByte(value); - return this; - } - - @Override - public Buffer writeShort(final int value) { - this.buffer.writeShort(value); - return this; - } - - @Override - public Buffer writeInt(final int value) { - this.buffer.writeInt(value); - return this; - } - - @Override - public Buffer writeLong(final long value) { - this.buffer.writeLong(value); - return this; - } - - @Override - public Buffer writeFloat(final float value) { - this.buffer.writeFloat(value); - return this; - } - - @Override - public Buffer writeDouble(final double value) { - this.buffer.writeDouble(value); - return this; - } - - @Override - public Buffer writeBytes(final byte[] src) { - this.buffer.writeBytes(src); - return this; - } - - @Override - public Buffer writeBytes(final ByteBuffer src) { - this.buffer.writeBytes(src); - return this; - } - - @Override - public Buffer writeBytes(byte[] src, final int srcIndex, final int length) { - this.buffer.writeBytes(src, srcIndex, length); - return this; - } - - @Override - public boolean release() { - return this.buffer.release(); - } - - @Override - public Buffer retain() { - this.buffer.retain(); - return this; - } - - @Override - public int referenceCount() { - return this.buffer.refCnt(); - } - - @Override - public ByteBuffer[] nioBuffers() { - return this.buffer.nioBuffers(); - } - - @Override - public ByteBuffer nioBuffer() { - return this.buffer.nioBuffer(); - } - - @Override - public ByteBuffer nioBuffer(final int index, final int length) { - return this.buffer.nioBuffer(index, length); - } - - @Override - public ByteBuffer[] nioBuffers(final int index, final int length) { - return this.buffer.nioBuffers(index, length); - } - - @Override - public int nioBufferCount() { - return this.buffer.nioBufferCount(); - } - - @Override - public Buffer getBytes(final int index, final byte[] dst) { - this.buffer.getBytes(index, dst); - return this; - } - - /** Returns the underlying buffer. */ - public ByteBuf getUnderlyingBuffer() { - return this.buffer; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/buffer/DseNettyBufferFactory.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/buffer/DseNettyBufferFactory.java deleted file mode 100644 index 57ee3cb1a9d..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/binary/buffer/DseNettyBufferFactory.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary.buffer; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.CompositeByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.buffer.UnpooledByteBufAllocator; -import java.nio.ByteBuffer; -import java.util.function.Supplier; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.BufferFactory; - -/** - * Internal BufferFactory impl for creation of Tinkerpop buffers. We implement an internal type here - * to allow for this class to use shaded Netty types (without bringing all of Tinkerpop into the - * shaded JAR). The impl is based on the initial impl of {@code - * org.apache.tinkerpop.gremlin.driver.ser.NettyBufferFactory} but we don't guarantee that this - * class will mirror changes to that class over time. - */ -public class DseNettyBufferFactory implements BufferFactory { - - private static final ByteBufAllocator DEFAULT_ALLOCATOR = new UnpooledByteBufAllocator(false); - - private final ByteBufAllocator allocator; - - public DseNettyBufferFactory() { - this.allocator = DEFAULT_ALLOCATOR; - } - - public DseNettyBufferFactory(ByteBufAllocator allocator) { - this.allocator = allocator; - } - - @Override - public Buffer create(final ByteBuf value) { - return new DseNettyBuffer(value); - } - - @Override - public Buffer wrap(final ByteBuffer value) { - return create(Unpooled.wrappedBuffer(value)); - } - - public Buffer heap() { - return create(allocator.heapBuffer()); - } - - public Buffer heap(int initialSize) { - return create(allocator.heapBuffer(initialSize)); - } - - public Buffer heap(int initialSize, int maxSize) { - return create(allocator.heapBuffer(initialSize, maxSize)); - } - - public Buffer io() { - return create(allocator.ioBuffer()); - } - - public Buffer io(int initialSize) { - return create(allocator.ioBuffer(initialSize)); - } - - public Buffer io(int initialSize, int maxSize) { - return create(allocator.ioBuffer(initialSize, maxSize)); - } - - public Buffer direct() { - return create(allocator.directBuffer()); - } - - public Buffer direct(int initialSize) { - return create(allocator.directBuffer(initialSize)); - } - - public Buffer direct(int initialSize, int maxSize) { - return create(allocator.directBuffer(initialSize, maxSize)); - } - - public Buffer composite(ByteBuf... components) { - - CompositeByteBuf buff = allocator.compositeBuffer(components.length); - buff.addComponents(components); - return create(buff); - } - - public Buffer composite(Buffer... components) { - ByteBuf[] nettyBufs = new ByteBuf[components.length]; - for (int i = 0; i < components.length; ++i) { - if (!(components[i] instanceof DseNettyBuffer)) { - throw new IllegalArgumentException("Can only concatenate DseNettyBuffer instances"); - } - nettyBufs[i] = ((DseNettyBuffer) components[i]).getUnderlyingBuffer(); - } - return composite(nettyBufs); - } - - public Buffer withBytes(int... bytes) { - return withBytes(this::heap, bytes); - } - - public Buffer withBytes(Supplier supplier, int... bytes) { - Buffer buff = supplier.get(); - for (int val : bytes) { - buff.writeByte(val); - } - return buff; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/DefaultReactiveGraphNode.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/DefaultReactiveGraphNode.java deleted file mode 100644 index fda0eed5333..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/DefaultReactiveGraphNode.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.reactive; - -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.reactive.ReactiveGraphNode; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.List; -import java.util.Map; -import java.util.Set; -import net.jcip.annotations.NotThreadSafe; -import org.apache.tinkerpop.gremlin.process.traversal.Path; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Property; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; - -@NotThreadSafe -class DefaultReactiveGraphNode implements ReactiveGraphNode { - - private final GraphNode graphNode; - private final ExecutionInfo executionInfo; - - DefaultReactiveGraphNode(@NonNull GraphNode graphNode, @NonNull ExecutionInfo executionInfo) { - this.graphNode = graphNode; - this.executionInfo = executionInfo; - } - - @NonNull - @Override - public ExecutionInfo getExecutionInfo() { - return executionInfo; - } - - @Override - public boolean isNull() { - return graphNode.isNull(); - } - - @Override - public boolean isMap() { - return graphNode.isMap(); - } - - @Override - public Iterable keys() { - return graphNode.keys(); - } - - @Override - public GraphNode getByKey(Object key) { - return graphNode.getByKey(key); - } - - @Override - public Map asMap() { - return graphNode.asMap(); - } - - @Override - public boolean isList() { - return graphNode.isList(); - } - - @Override - public int size() { - return graphNode.size(); - } - - @Override - public GraphNode getByIndex(int index) { - return graphNode.getByIndex(index); - } - - @Override - public List asList() { - return graphNode.asList(); - } - - @Override - public boolean isValue() { - return graphNode.isValue(); - } - - @Override - public int asInt() { - return graphNode.asInt(); - } - - @Override - public boolean asBoolean() { - return graphNode.asBoolean(); - } - - @Override - public long asLong() { - return graphNode.asLong(); - } - - @Override - public double asDouble() { - return graphNode.asDouble(); - } - - @Override - public String asString() { - return graphNode.asString(); - } - - @Override - public ResultT as(Class clazz) { - return graphNode.as(clazz); - } - - @Override - public ResultT as(GenericType type) { - return graphNode.as(type); - } - - @Override - public boolean isVertex() { - return graphNode.isVertex(); - } - - @Override - public Vertex asVertex() { - return graphNode.asVertex(); - } - - @Override - public boolean isEdge() { - return graphNode.isEdge(); - } - - @Override - public Edge asEdge() { - return graphNode.asEdge(); - } - - @Override - public boolean isPath() { - return graphNode.isPath(); - } - - @Override - public Path asPath() { - return graphNode.asPath(); - } - - @Override - public boolean isProperty() { - return graphNode.isProperty(); - } - - @Override - public Property asProperty() { - return graphNode.asProperty(); - } - - @Override - public boolean isVertexProperty() { - return graphNode.isVertexProperty(); - } - - @Override - public VertexProperty asVertexProperty() { - return graphNode.asVertexProperty(); - } - - @Override - public boolean isSet() { - return graphNode.isSet(); - } - - @Override - public Set asSet() { - return graphNode.asSet(); - } - - @Override - public String toString() { - return "DefaultReactiveGraphNode{graphNode=" - + graphNode - + ", executionInfo=" - + executionInfo - + '}'; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/DefaultReactiveGraphResultSet.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/DefaultReactiveGraphResultSet.java deleted file mode 100644 index 137e44e4d95..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/DefaultReactiveGraphResultSet.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.reactive; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.reactive.ReactiveGraphNode; -import com.datastax.dse.driver.api.core.graph.reactive.ReactiveGraphResultSet; -import com.datastax.dse.driver.internal.core.cql.reactive.EmptySubscription; -import com.datastax.dse.driver.internal.core.cql.reactive.SimpleUnicastProcessor; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Objects; -import java.util.concurrent.Callable; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.atomic.AtomicBoolean; -import net.jcip.annotations.ThreadSafe; -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; - -@ThreadSafe -public class DefaultReactiveGraphResultSet implements ReactiveGraphResultSet { - - private final Callable> firstPage; - - private final AtomicBoolean alreadySubscribed = new AtomicBoolean(false); - - private final SimpleUnicastProcessor executionInfosPublisher = - new SimpleUnicastProcessor<>(); - - public DefaultReactiveGraphResultSet(Callable> firstPage) { - this.firstPage = firstPage; - } - - @Override - public void subscribe(@NonNull Subscriber subscriber) { - // As per rule 1.9, we need to throw an NPE if subscriber is null - Objects.requireNonNull(subscriber, "Subscriber cannot be null"); - // As per rule 1.11, this publisher is allowed to support only one subscriber. - if (alreadySubscribed.compareAndSet(false, true)) { - ReactiveGraphResultSetSubscription subscription = - new ReactiveGraphResultSetSubscription(subscriber, executionInfosPublisher); - try { - subscriber.onSubscribe(subscription); - // must be done after onSubscribe - subscription.start(firstPage); - } catch (Throwable t) { - // As per rule 2.13: In the case that this rule is violated, - // any associated Subscription to the Subscriber MUST be considered as - // cancelled, and the caller MUST raise this error condition in a fashion - // that is adequate for the runtime environment. - subscription.doOnError( - new IllegalStateException( - subscriber - + " violated the Reactive Streams rule 2.13 by throwing an exception from onSubscribe.", - t)); - } - } else { - subscriber.onSubscribe(EmptySubscription.INSTANCE); - subscriber.onError( - new IllegalStateException("This publisher does not support multiple subscriptions")); - } - // As per 2.13, this method must return normally (i.e. not throw) - } - - @NonNull - @Override - public Publisher getExecutionInfos() { - return executionInfosPublisher; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/FailedReactiveGraphResultSet.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/FailedReactiveGraphResultSet.java deleted file mode 100644 index 45bbd8c62b0..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/FailedReactiveGraphResultSet.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.reactive; - -import com.datastax.dse.driver.api.core.graph.reactive.ReactiveGraphNode; -import com.datastax.dse.driver.api.core.graph.reactive.ReactiveGraphResultSet; -import com.datastax.dse.driver.internal.core.cql.reactive.FailedPublisher; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import edu.umd.cs.findbugs.annotations.NonNull; -import org.reactivestreams.Publisher; - -public class FailedReactiveGraphResultSet extends FailedPublisher - implements ReactiveGraphResultSet { - - public FailedReactiveGraphResultSet(Throwable error) { - super(error); - } - - @NonNull - @Override - public Publisher getExecutionInfos() { - return new FailedPublisher<>(error); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphRequestProcessor.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphRequestProcessor.java deleted file mode 100644 index ed2cd28926c..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphRequestProcessor.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.reactive; - -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.graph.reactive.ReactiveGraphResultSet; -import com.datastax.dse.driver.internal.core.graph.GraphRequestAsyncProcessor; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.internal.core.session.RequestProcessor; -import edu.umd.cs.findbugs.annotations.NonNull; -import net.jcip.annotations.ThreadSafe; - -@ThreadSafe -public class ReactiveGraphRequestProcessor - implements RequestProcessor, ReactiveGraphResultSet> { - - public static final GenericType REACTIVE_GRAPH_RESULT_SET = - GenericType.of(ReactiveGraphResultSet.class); - - private final GraphRequestAsyncProcessor asyncGraphProcessor; - - public ReactiveGraphRequestProcessor(@NonNull GraphRequestAsyncProcessor asyncGraphProcessor) { - this.asyncGraphProcessor = asyncGraphProcessor; - } - - @Override - public boolean canProcess(Request request, GenericType resultType) { - return request instanceof GraphStatement && resultType.equals(REACTIVE_GRAPH_RESULT_SET); - } - - @Override - public ReactiveGraphResultSet process( - GraphStatement request, - DefaultSession session, - InternalDriverContext context, - String sessionLogPrefix) { - return new DefaultReactiveGraphResultSet( - () -> asyncGraphProcessor.process(request, session, context, sessionLogPrefix)); - } - - @Override - public ReactiveGraphResultSet newFailure(RuntimeException error) { - return new FailedReactiveGraphResultSet(error); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphResultSetSubscription.java b/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphResultSetSubscription.java deleted file mode 100644 index c3234d74ebc..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphResultSetSubscription.java +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.reactive; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.reactive.ReactiveGraphNode; -import com.datastax.dse.driver.internal.core.cql.reactive.ReactiveOperators; -import com.datastax.dse.driver.internal.core.util.concurrent.BoundedConcurrentQueue; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import com.datastax.oss.driver.shaded.guava.common.collect.Iterators; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Collections; -import java.util.Iterator; -import java.util.Objects; -import java.util.concurrent.Callable; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import net.jcip.annotations.ThreadSafe; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class is very similar to {@link - * com.datastax.dse.driver.internal.core.cql.reactive.ReactiveResultSetSubscription}. It exists - * merely because {@link AsyncGraphResultSet} is not a subtype of {@link - * com.datastax.oss.driver.api.core.AsyncPagingIterable} and thus it would be difficult to re-use - * ReactiveResultSetSubscription for graph result sets. - */ -@ThreadSafe -public class ReactiveGraphResultSetSubscription implements Subscription { - - private static final Logger LOG = - LoggerFactory.getLogger(ReactiveGraphResultSetSubscription.class); - - private static final int MAX_ENQUEUED_PAGES = 4; - - /** Tracks the number of items requested by the subscriber. */ - private final AtomicLong requested = new AtomicLong(0); - - /** The pages received so far, with a maximum of MAX_ENQUEUED_PAGES elements. */ - private final BoundedConcurrentQueue pages = - new BoundedConcurrentQueue<>(MAX_ENQUEUED_PAGES); - - /** - * Used to signal that a thread is currently draining, i.e., emitting items to the subscriber. - * When it is zero, that means there is no ongoing emission. This mechanism effectively serializes - * access to the drain() method, and also keeps track of missed attempts to enter it, since each - * thread that attempts to drain will increment this counter. - * - * @see #drain() - */ - private final AtomicInteger draining = new AtomicInteger(0); - - /** - * Waited upon by the driver and completed when the subscriber requests its first item. - * - *

Used to hold off emitting results until the subscriber issues its first request for items. - * Since this future is only completed from {@link #request(long)}, this effectively conditions - * the enqueueing of the first page to the reception of the subscriber's first request. - * - *

This mechanism avoids sending terminal signals before a request is made when the stream is - * empty. Note that as per 2.9, "a Subscriber MUST be prepared to receive an onComplete signal - * with or without a preceding Subscription.request(long n) call." However, the TCK considers it - * as unfair behavior. - * - * @see #start(Callable) - * @see #request(long) - */ - private final CompletableFuture firstSubscriberRequestArrived = new CompletableFuture<>(); - - /** non-final because it has to be de-referenced, see {@link #clear()}. */ - private volatile Subscriber mainSubscriber; - - private volatile Subscriber executionInfosSubscriber; - - /** - * Set to true when the subscription is cancelled, which happens when an error is encountered, - * when the result set is fully consumed and the subscription terminates, or when the subscriber - * manually calls {@link #cancel()}. - */ - private volatile boolean cancelled = false; - - ReactiveGraphResultSetSubscription( - @NonNull Subscriber mainSubscriber, - @NonNull Subscriber executionInfosSubscriber) { - this.mainSubscriber = mainSubscriber; - this.executionInfosSubscriber = executionInfosSubscriber; - } - - /** - * Starts the query execution. - * - *

Must be called immediately after creating the subscription, but after {@link - * Subscriber#onSubscribe(Subscription)}. - * - * @param firstPage The future that, when complete, will produce the first page. - */ - void start(@NonNull Callable> firstPage) { - firstSubscriberRequestArrived.thenAccept( - (aVoid) -> fetchNextPageAndEnqueue(new Page(firstPage))); - } - - @Override - public void request(long n) { - // As per 3.6: after the Subscription is cancelled, additional - // calls to request() MUST be NOPs. - if (!cancelled) { - if (n < 1) { - // Validate request as per rule 3.9 - doOnError( - new IllegalArgumentException( - mainSubscriber - + " violated the Reactive Streams rule 3.9 by requesting a non-positive number of elements.")); - } else { - // As per rule 3.17, when demand overflows Long.MAX_VALUE - // it can be treated as "effectively unbounded" - ReactiveOperators.addCap(requested, n); - // Set the first future to true if not done yet. - // This will make the first page of results ready for consumption, - // see start(). - // As per 2.7 it is the subscriber's responsibility to provide - // external synchronization when calling request(), - // so the check-then-act idiom below is good enough - // (and besides, complete() is idempotent). - if (!firstSubscriberRequestArrived.isDone()) { - firstSubscriberRequestArrived.complete(null); - } - drain(); - } - } - } - - @Override - public void cancel() { - // As per 3.5: Subscription.cancel() MUST respect the responsiveness of - // its caller by returning in a timely manner, MUST be idempotent and - // MUST be thread-safe. - if (!cancelled) { - cancelled = true; - if (draining.getAndIncrement() == 0) { - // If nobody is draining, clear now; - // otherwise, the draining thread will notice - // that the cancelled flag was set - // and will clear for us. - clear(); - } - } - } - - /** - * Attempts to drain available items, i.e. emit them to the subscriber. - * - *

Access to this method is serialized by the field {@link #draining}: only one thread at a - * time can drain, but threads that attempt to drain while other thread is already draining - * increment that field; the draining thread, before finishing its work, checks for such failed - * attempts and triggers another round of draining if that was the case. - * - *

The loop is interrupted when 1) the requested amount has been met or 2) when there are no - * more items readily available or 3) the subscription has been cancelled. - * - *

The loop also checks for stream exhaustion and emits a terminal {@code onComplete} signal in - * this case. - * - *

This method may run on a driver IO thread when invoked from {@link - * #fetchNextPageAndEnqueue(Page)}, or on a subscriber thread, when invoked from {@link - * #request(long)}. - */ - @SuppressWarnings("ConditionalBreakInInfiniteLoop") - private void drain() { - // As per 3.4: this method SHOULD respect the responsiveness - // of its caller by returning in a timely manner. - // We accomplish this by a wait-free implementation. - if (draining.getAndIncrement() != 0) { - // Someone else is already draining, so do nothing, - // the other thread will notice that we attempted to drain. - // This also allows to abide by rule 3.3 and avoid - // cycles such as request() -> onNext() -> request() etc. - return; - } - int missed = 1; - // Note: when termination is detected inside this loop, - // we MUST call clear() manually. - for (; ; ) { - // The requested number of items at this point - long r = requested.get(); - // The number of items emitted thus far - long emitted = 0L; - while (emitted != r) { - if (cancelled) { - clear(); - return; - } - Object result; - try { - result = tryNext(); - } catch (Throwable t) { - doOnError(t); - clear(); - return; - } - if (result == null) { - break; - } - if (result instanceof Throwable) { - doOnError((Throwable) result); - clear(); - return; - } - doOnNext((ReactiveGraphNode) result); - emitted++; - } - if (isExhausted()) { - doOnComplete(); - clear(); - return; - } - if (cancelled) { - clear(); - return; - } - if (emitted != 0) { - // if any item was emitted, adjust the requested field - ReactiveOperators.subCap(requested, emitted); - } - // if another thread tried to call drain() while we were busy, - // then we should do another drain round. - missed = draining.addAndGet(-missed); - if (missed == 0) { - break; - } - } - } - - /** - * Tries to return the next item, if one is readily available, and returns {@code null} otherwise. - * - *

Cannot run concurrently due to the {@link #draining} field. - */ - @Nullable - private Object tryNext() { - Page current = pages.peek(); - if (current != null) { - if (current.hasMoreRows()) { - return current.nextRow(); - } else if (current.hasMorePages()) { - // Discard current page as it is consumed. - // Don't discard the last page though as we need it - // to test isExhausted(). It will be GC'ed when a terminal signal - // is issued anyway, so that's no big deal. - if (pages.poll() == null) { - throw new AssertionError("Queue is empty, this should not happen"); - } - current = pages.peek(); - // if the next page is readily available, - // serve its first row now, no need to wait - // for the next drain. - if (current != null && current.hasMoreRows()) { - return current.nextRow(); - } - } - } - // No items available right now. - return null; - } - - /** - * Returns {@code true} when the entire stream has been consumed and no more items can be emitted. - * When that is the case, a terminal signal is sent. - * - *

Cannot run concurrently due to the draining field. - */ - private boolean isExhausted() { - Page current = pages.peek(); - // Note: current can only be null when: - // 1) we are waiting for the first page and it hasn't arrived yet; - // 2) we just discarded the current page, but the next page hasn't arrived yet. - // In any case, a null here means it is not the last page, since the last page - // stays in the queue until the very end of the operation. - return current != null && !current.hasMoreRows() && !current.hasMorePages(); - } - - /** - * Runs on a subscriber thread initially, see {@link #start(Callable)}. Subsequent executions run - * on the thread that completes the pair of futures [current.fetchNextPage, pages.offer] and - * enqueues. This can be a driver IO thread or a subscriber thread; in both cases, cannot run - * concurrently due to the fact that one can only fetch the next page when the current one is - * arrived and enqueued. - */ - private void fetchNextPageAndEnqueue(@NonNull Page current) { - current - .fetchNextPage() - // as soon as the response arrives, - // create the new page - .handle( - (rs, t) -> { - Page page; - if (t == null) { - page = toPage(rs); - executionInfosSubscriber.onNext(rs.getRequestExecutionInfo()); - if (!page.hasMorePages()) { - executionInfosSubscriber.onComplete(); - } - } else { - // Unwrap CompletionExceptions created by combined futures - if (t instanceof CompletionException) { - t = t.getCause(); - } - page = toErrorPage(t); - executionInfosSubscriber.onError(t); - } - return page; - }) - .thenCompose(pages::offer) - .thenAccept( - page -> { - if (page.hasMorePages() && !cancelled) { - // preemptively fetch the next page, if available - fetchNextPageAndEnqueue(page); - } - drain(); - }); - } - - private void doOnNext(@NonNull ReactiveGraphNode result) { - try { - mainSubscriber.onNext(result); - } catch (Throwable t) { - LOG.error( - mainSubscriber - + " violated the Reactive Streams rule 2.13 by throwing an exception from onNext.", - t); - cancel(); - } - } - - private void doOnComplete() { - try { - // Then we signal onComplete as per rules 1.2 and 1.5 - mainSubscriber.onComplete(); - } catch (Throwable t) { - LOG.error( - mainSubscriber - + " violated the Reactive Streams rule 2.13 by throwing an exception from onComplete.", - t); - } - // We need to consider this Subscription as cancelled as per rule 1.6 - cancel(); - } - - // package-private because it can be invoked by the publisher if the subscription handshake - // process fails. - void doOnError(@NonNull Throwable error) { - try { - // Then we signal the error downstream, as per rules 1.2 and 1.4. - mainSubscriber.onError(error); - } catch (Throwable t) { - t.addSuppressed(error); - LOG.error( - mainSubscriber - + " violated the Reactive Streams rule 2.13 by throwing an exception from onError.", - t); - } - // We need to consider this Subscription as cancelled as per rule 1.6 - cancel(); - } - - private void clear() { - // We don't need these pages anymore and should not hold references - // to them. - pages.clear(); - // As per 3.13, Subscription.cancel() MUST request the Publisher to - // eventually drop any references to the corresponding subscriber. - // Our own publishers do not keep references to this subscription, - // but downstream processors might do so, which is why we need to - // defensively clear the subscriber reference when we are done. - mainSubscriber = null; - executionInfosSubscriber = null; - } - - /** - * Converts the received result object into a {@link Page}. - * - * @param rs the result object to convert. - * @return a new page. - */ - @NonNull - private Page toPage(@NonNull AsyncGraphResultSet rs) { - ExecutionInfo executionInfo = rs.getRequestExecutionInfo(); - Iterator results = - Iterators.transform( - rs.currentPage().iterator(), - row -> new DefaultReactiveGraphNode(Objects.requireNonNull(row), executionInfo)); - return new Page(results, rs.hasMorePages() ? rs::fetchNextPage : null); - } - - /** Converts the given error into a {@link Page}, containing the error as its only element. */ - @NonNull - private Page toErrorPage(@NonNull Throwable t) { - return new Page(Iterators.singletonIterator(t), null); - } - - /** - * A page object comprises an iterator over the page's results, and a future pointing to the next - * page (or {@code null}, if it's the last page). - */ - static class Page { - - @NonNull final Iterator iterator; - - // A pointer to the next page, or null if this is the last page. - @Nullable final Callable> nextPage; - - /** called only from start() */ - Page(@NonNull Callable> nextPage) { - this.iterator = Collections.emptyIterator(); - this.nextPage = nextPage; - } - - Page( - @NonNull Iterator iterator, - @Nullable Callable> nextPage) { - this.iterator = iterator; - this.nextPage = nextPage; - } - - boolean hasMorePages() { - return nextPage != null; - } - - @NonNull - CompletionStage fetchNextPage() { - try { - return Objects.requireNonNull(nextPage).call(); - } catch (Exception e) { - // This is a synchronous failure in the driver. - // It can happen in rare cases when the driver throws an exception instead of returning a - // failed future; e.g. if someone tries to execute a continuous paging request but the - // protocol version in use does not support it. - // We treat it as a failed future. - return CompletableFutures.failedFuture(e); - } - } - - boolean hasMoreRows() { - return iterator.hasNext(); - } - - @NonNull - Object nextRow() { - return iterator.next(); - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfilesInfoFinder.java b/core/src/main/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfilesInfoFinder.java index a7c92d80d96..9459cd7636f 100644 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfilesInfoFinder.java +++ b/core/src/main/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfilesInfoFinder.java @@ -17,8 +17,6 @@ */ package com.datastax.dse.driver.internal.core.insights; -import static com.datastax.dse.driver.api.core.config.DseDriverOption.GRAPH_TRAVERSAL_SOURCE; - import com.datastax.dse.driver.internal.core.insights.PackageUtil.ClassSettingDetails; import com.datastax.dse.driver.internal.core.insights.schema.LoadBalancingInfo; import com.datastax.dse.driver.internal.core.insights.schema.SpecificExecutionProfile; @@ -26,7 +24,6 @@ import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Function; @@ -84,17 +81,8 @@ private SpecificExecutionProfile retainOnlyDifferentFieldsFromSpecificProfile( specificExecutionProfile, SpecificExecutionProfile::getSerialConsistency); - Map graphOptions = - getIfDifferentOrReturnNull( - defaultProfile, specificExecutionProfile, SpecificExecutionProfile::getGraphOptions); - return new SpecificExecutionProfile( - readTimeout, - loadBalancingInfo, - speculativeExecutionInfo, - consistency, - serialConsistency, - graphOptions); + readTimeout, loadBalancingInfo, speculativeExecutionInfo, consistency, serialConsistency); } private T getIfDifferentOrReturnNull( @@ -117,8 +105,7 @@ private SpecificExecutionProfile mapToSpecificProfile( getLoadBalancingInfo(driverExecutionProfile), getSpeculativeExecutionInfo(driverExecutionProfile), driverExecutionProfile.getString(DefaultDriverOption.REQUEST_CONSISTENCY), - driverExecutionProfile.getString(DefaultDriverOption.REQUEST_SERIAL_CONSISTENCY), - getGraphOptions(driverExecutionProfile)); + driverExecutionProfile.getString(DefaultDriverOption.REQUEST_SERIAL_CONSISTENCY)); } private SpeculativeExecutionInfo getSpeculativeExecutionInfo( @@ -172,13 +159,4 @@ private LoadBalancingInfo getLoadBalancingInfo(DriverExecutionProfile driverExec return new LoadBalancingInfo( loadBalancingDetails.getClassName(), options, loadBalancingDetails.getFullPackage()); } - - private Map getGraphOptions(DriverExecutionProfile driverExecutionProfile) { - Map graphOptionsMap = new HashMap<>(); - String graphTraversalSource = driverExecutionProfile.getString(GRAPH_TRAVERSAL_SOURCE, null); - if (graphTraversalSource != null) { - graphOptionsMap.put("source", graphTraversalSource); - } - return graphOptionsMap; - } } diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/insights/schema/SpecificExecutionProfile.java b/core/src/main/java/com/datastax/dse/driver/internal/core/insights/schema/SpecificExecutionProfile.java index 58652fdf885..b3e23ff0228 100644 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/insights/schema/SpecificExecutionProfile.java +++ b/core/src/main/java/com/datastax/dse/driver/internal/core/insights/schema/SpecificExecutionProfile.java @@ -20,7 +20,6 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; import java.util.Objects; @JsonInclude(JsonInclude.Include.NON_NULL) @@ -40,23 +39,18 @@ public class SpecificExecutionProfile { @JsonProperty("serialConsistency") private final String serialConsistency; - @JsonProperty("graphOptions") - private Map graphOptions; - @JsonCreator public SpecificExecutionProfile( @JsonProperty("readTimeout") Integer readTimeoutMillis, @JsonProperty("loadBalancing") LoadBalancingInfo loadBalancing, @JsonProperty("speculativeExecution") SpeculativeExecutionInfo speculativeExecutionInfo, @JsonProperty("consistency") String consistency, - @JsonProperty("serialConsistency") String serialConsistency, - @JsonProperty("graphOptions") Map graphOptions) { + @JsonProperty("serialConsistency") String serialConsistency) { readTimeout = readTimeoutMillis; this.loadBalancing = loadBalancing; this.speculativeExecution = speculativeExecutionInfo; this.consistency = consistency; this.serialConsistency = serialConsistency; - this.graphOptions = graphOptions; } public Integer getReadTimeout() { @@ -79,10 +73,6 @@ public String getSerialConsistency() { return serialConsistency; } - public Map getGraphOptions() { - return graphOptions; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -96,19 +86,13 @@ public boolean equals(Object o) { && Objects.equals(loadBalancing, that.loadBalancing) && Objects.equals(speculativeExecution, that.speculativeExecution) && Objects.equals(consistency, that.consistency) - && Objects.equals(serialConsistency, that.serialConsistency) - && Objects.equals(graphOptions, that.graphOptions); + && Objects.equals(serialConsistency, that.serialConsistency); } @Override public int hashCode() { return Objects.hash( - readTimeout, - loadBalancing, - speculativeExecution, - consistency, - serialConsistency, - graphOptions); + readTimeout, loadBalancing, speculativeExecution, consistency, serialConsistency); } @Override @@ -126,8 +110,6 @@ public String toString() { + ", serialConsistency='" + serialConsistency + '\'' - + ", graphOptions=" - + graphOptions + '}'; } } diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/protocol/TinkerpopBufferPrimitiveCodec.java b/core/src/main/java/com/datastax/dse/driver/internal/core/protocol/TinkerpopBufferPrimitiveCodec.java deleted file mode 100644 index 13238519e06..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/protocol/TinkerpopBufferPrimitiveCodec.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.protocol; - -import com.datastax.dse.driver.internal.core.graph.binary.buffer.DseNettyBufferFactory; -import com.datastax.oss.driver.internal.core.protocol.ByteBufPrimitiveCodec; -import com.datastax.oss.driver.shaded.guava.common.base.Charsets; -import com.datastax.oss.protocol.internal.PrimitiveCodec; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.zip.CRC32; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; - -/** - * Minimal implementation of {@link PrimitiveCodec} for Tinkerpop {@link Buffer} instances. - * - *

This approach represents a temporary design compromise. PrimitiveCodec is primarily used for - * handling data directly from Netty, a task satisfied by {@link ByteBufPrimitiveCodec}. But - * PrimitiveCodec is also used to implement graph serialization for some of the "dynamic" types - * (notably UDTs and tuples). Since we're converting graph serialization to use the new Tinkerpop - * Buffer API we need just enough of a PrimitiveCodec impl to satisfy the needs of graph - * serialization... and nothing more. - * - *

A more explicit approach would be to change graph serialization to use a different interface, - * some kind of subset of PrimitiveCodec.... and then make PrimitiveCodec extend this interface. - * This is left as future work for now since it involves changes to the native-protocol lib(s). - */ -public class TinkerpopBufferPrimitiveCodec implements PrimitiveCodec { - - private final DseNettyBufferFactory factory; - - public TinkerpopBufferPrimitiveCodec(DseNettyBufferFactory factory) { - this.factory = factory; - } - - @Override - public Buffer allocate(int size) { - // Note: we use io() here to match up to what ByteBufPrimitiveCodec does, but be warned that - // ByteBufs created in this way don't support the array() method used elsewhere in this codec - // (readString() specifically). As such usage of this method to create Buffer instances is - // discouraged; we have a factory for that. - return this.factory.io(size, size); - } - - @Override - public void release(Buffer toRelease) { - toRelease.release(); - } - - @Override - public int sizeOf(Buffer toMeasure) { - return toMeasure.readableBytes(); - } - - // TODO - @Override - public Buffer concat(Buffer left, Buffer right) { - boolean leftReadable = left.readableBytes() > 0; - boolean rightReadable = right.readableBytes() > 0; - if (!(leftReadable || rightReadable)) { - return factory.heap(); - } - if (!leftReadable) { - return right; - } - if (!rightReadable) { - return left; - } - Buffer rv = factory.composite(left, right); - // c.readerIndex() is 0, which is the first readable byte in left - rv.writerIndex( - left.writerIndex() - left.readerIndex() + right.writerIndex() - right.readerIndex()); - return rv; - } - - @Override - public void markReaderIndex(Buffer source) { - throw new UnsupportedOperationException(); - } - - @Override - public void resetReaderIndex(Buffer source) { - throw new UnsupportedOperationException(); - } - - @Override - public byte readByte(Buffer source) { - return source.readByte(); - } - - @Override - public int readInt(Buffer source) { - return source.readInt(); - } - - @Override - public int readInt(Buffer source, int offset) { - throw new UnsupportedOperationException(); - } - - @Override - public InetAddress readInetAddr(Buffer source) { - int length = readByte(source) & 0xFF; - byte[] bytes = new byte[length]; - source.readBytes(bytes); - return newInetAddress(bytes); - } - - @Override - public long readLong(Buffer source) { - return source.readLong(); - } - - @Override - public int readUnsignedShort(Buffer source) { - return source.readShort() & 0xFFFF; - } - - @Override - public ByteBuffer readBytes(Buffer source) { - int length = readInt(source); - if (length < 0) return null; - return source.nioBuffer(source.readerIndex(), length); - } - - @Override - public byte[] readShortBytes(Buffer source) { - try { - int length = readUnsignedShort(source); - byte[] bytes = new byte[length]; - source.readBytes(bytes); - return bytes; - } catch (IndexOutOfBoundsException e) { - throw new IllegalArgumentException( - "Not enough bytes to read a byte array preceded by its 2 bytes length"); - } - } - - // Copy of PrimitiveCodec impl - @Override - public String readString(Buffer source) { - int length = readUnsignedShort(source); - return readString(source, length); - } - - @Override - public String readLongString(Buffer source) { - int length = readInt(source); - return readString(source, length); - } - - @Override - public Buffer readRetainedSlice(Buffer source, int sliceLength) { - throw new UnsupportedOperationException(); - } - - @Override - public void updateCrc(Buffer source, CRC32 crc) { - throw new UnsupportedOperationException(); - } - - @Override - public void writeByte(byte b, Buffer dest) { - dest.writeByte(b); - } - - @Override - public void writeInt(int i, Buffer dest) { - dest.writeInt(i); - } - - @Override - public void writeInetAddr(InetAddress address, Buffer dest) { - byte[] bytes = address.getAddress(); - writeByte((byte) bytes.length, dest); - dest.writeBytes(bytes); - } - - @Override - public void writeLong(long l, Buffer dest) { - dest.writeLong(l); - } - - @Override - public void writeUnsignedShort(int i, Buffer dest) { - dest.writeShort(i); - } - - // Copy of PrimitiveCodec impl - @Override - public void writeString(String s, Buffer dest) { - - byte[] bytes = s.getBytes(Charsets.UTF_8); - writeUnsignedShort(bytes.length, dest); - dest.writeBytes(bytes); - } - - @Override - public void writeLongString(String s, Buffer dest) { - byte[] bytes = s.getBytes(Charsets.UTF_8); - writeInt(bytes.length, dest); - dest.writeBytes(bytes); - } - - @Override - public void writeBytes(ByteBuffer bytes, Buffer dest) { - if (bytes == null) { - writeInt(-1, dest); - } else { - writeInt(bytes.remaining(), dest); - dest.writeBytes(bytes.duplicate()); - } - } - - @Override - public void writeBytes(byte[] bytes, Buffer dest) { - if (bytes == null) { - writeInt(-1, dest); - } else { - writeInt(bytes.length, dest); - dest.writeBytes(bytes); - } - } - - @Override - public void writeShortBytes(byte[] bytes, Buffer dest) { - writeUnsignedShort(bytes.length, dest); - dest.writeBytes(bytes); - } - - // Based on PrimitiveCodec impl, although that method leverages some - // Netty built-ins which we have to do manually here - private static String readString(Buffer buff, int length) { - try { - - // Basically what io.netty.buffer.ByteBufUtil.decodeString() does minus some extra - // ByteBuf-specific ops - int offset; - byte[] bytes; - ByteBuffer byteBuff = buff.nioBuffer(); - if (byteBuff.hasArray()) { - - bytes = byteBuff.array(); - offset = byteBuff.arrayOffset(); - } else { - - bytes = new byte[length]; - byteBuff.get(bytes, 0, length); - offset = 0; - } - - String str = new String(bytes, offset, length, Charsets.UTF_8); - - // Ops against the NIO buffers don't impact the read/write indexes for he Buffer - // itself so we have to do that manually - buff.readerIndex(buff.readerIndex() + length); - return str; - } catch (IndexOutOfBoundsException e) { - throw new IllegalArgumentException( - "Not enough bytes to read an UTF-8 serialized string of size " + length, e); - } - } - - // TODO: Code below copied directly from ByteBufPrimitiveCodec, probably want to consolidate this - // somewhere - private static InetAddress newInetAddress(byte[] bytes) { - try { - return InetAddress.getByAddress(bytes); - } catch (UnknownHostException e) { - // Per the Javadoc, the only way this can happen is if the length is illegal - throw new IllegalArgumentException( - String.format("Invalid address length: %d (%s)", bytes.length, Arrays.toString(bytes))); - } - } -} diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/CqlSession.java b/core/src/main/java/com/datastax/oss/driver/api/core/CqlSession.java index ff096719f3e..0b075b4595f 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/CqlSession.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/CqlSession.java @@ -20,8 +20,6 @@ import com.datastax.dse.driver.api.core.cql.continuous.ContinuousSession; import com.datastax.dse.driver.api.core.cql.continuous.reactive.ContinuousReactiveSession; import com.datastax.dse.driver.api.core.cql.reactive.ReactiveSession; -import com.datastax.dse.driver.api.core.graph.GraphSession; -import com.datastax.dse.driver.api.core.graph.reactive.ReactiveGraphSession; import com.datastax.oss.driver.api.core.cql.AsyncCqlSession; import com.datastax.oss.driver.api.core.cql.SyncCqlSession; import com.datastax.oss.driver.api.core.session.Session; @@ -30,21 +28,12 @@ /** * The default session type built by the driver. * - *

It provides user-friendly execution methods for: + *

It provides user-friendly execution methods for synchronous, asynchronous, reactive, and + * continuous-paging CQL requests. * - *

    - *
  • CQL requests: synchronous, asynchronous or reactive mode; - *
  • requests specific to DataStax Enterprise: graph and continuous paging. - *
- * - * Client applications can use this interface even if they don't need all the features. In + *

Client applications can use this interface even if they don't need all the features. In * particular, it can be used with a regular Apache Cassandra ® cluster, as long as you don't - * call any of the DSE-specific execute methods. If you're in that situation, you might also want to - * exclude certain dependencies from your classpath (see the "Integration" page in the user manual). - * - *

Note that the name "CQL session" is no longer really accurate since this interface can now - * execute other request types; but it was preserved for backward compatibility with previous driver - * versions. + * call continuous-paging methods. */ public interface CqlSession extends Session, @@ -52,9 +41,7 @@ public interface CqlSession AsyncCqlSession, ReactiveSession, ContinuousSession, - GraphSession, - ContinuousReactiveSession, - ReactiveGraphSession { + ContinuousReactiveSession { /** * Returns a builder to create a new instance. diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java index c1a428b3524..3042013266f 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java @@ -264,7 +264,6 @@ protected static void fillWithDriverDefaults(OptionsMap map) { CQL4SkipMetadataResolveMethod.SMART.toString()); map.put(TypedDriverOption.REQUEST_SERIAL_CONSISTENCY, "SERIAL"); map.put(TypedDriverOption.REQUEST_DEFAULT_IDEMPOTENCE, false); - map.put(TypedDriverOption.GRAPH_TRAVERSAL_SOURCE, "g"); map.put(TypedDriverOption.LOAD_BALANCING_POLICY_CLASS, "DefaultLoadBalancingPolicy"); map.put(TypedDriverOption.LOAD_BALANCING_POLICY_SLOW_AVOIDANCE, true); map.put(TypedDriverOption.SESSION_LEAK_THRESHOLD, 4); @@ -299,14 +298,6 @@ protected static void fillWithDriverDefaults(OptionsMap map) { map.put(TypedDriverOption.REQUEST_TRACE_INTERVAL, Duration.ofMillis(3)); map.put(TypedDriverOption.REQUEST_TRACE_CONSISTENCY, "ONE"); map.put(TypedDriverOption.REQUEST_LOG_WARNINGS, true); - map.put(TypedDriverOption.GRAPH_PAGING_ENABLED, "AUTO"); - map.put(TypedDriverOption.GRAPH_CONTINUOUS_PAGING_PAGE_SIZE, requestPageSize); - map.put(TypedDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_PAGES, continuousMaxPages); - map.put( - TypedDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, - continuousMaxPagesPerSecond); - map.put( - TypedDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES, continuousMaxEnqueuedPages); map.put(TypedDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, requestPageSize); map.put(TypedDriverOption.CONTINUOUS_PAGING_PAGE_SIZE_BYTES, false); map.put(TypedDriverOption.CONTINUOUS_PAGING_MAX_PAGES, continuousMaxPages); @@ -336,19 +327,11 @@ protected static void fillWithDriverDefaults(OptionsMap map) { Duration.ofMinutes(5)); map.put(TypedDriverOption.METRICS_FACTORY_CLASS, "DefaultMetricsFactory"); map.put(TypedDriverOption.METRICS_ID_GENERATOR_CLASS, "DefaultMetricIdGenerator"); - map.put(TypedDriverOption.METRICS_SESSION_GRAPH_REQUESTS_HIGHEST, Duration.ofSeconds(12)); - map.put(TypedDriverOption.METRICS_SESSION_GRAPH_REQUESTS_LOWEST, Duration.ofMillis(1)); - map.put(TypedDriverOption.METRICS_SESSION_GRAPH_REQUESTS_DIGITS, 3); - map.put(TypedDriverOption.METRICS_SESSION_GRAPH_REQUESTS_INTERVAL, Duration.ofMinutes(5)); map.put(TypedDriverOption.METRICS_NODE_ENABLED, Collections.emptyList()); map.put(TypedDriverOption.METRICS_NODE_CQL_MESSAGES_HIGHEST, Duration.ofSeconds(3)); map.put(TypedDriverOption.METRICS_NODE_CQL_MESSAGES_LOWEST, Duration.ofMillis(1)); map.put(TypedDriverOption.METRICS_NODE_CQL_MESSAGES_DIGITS, 3); map.put(TypedDriverOption.METRICS_NODE_CQL_MESSAGES_INTERVAL, Duration.ofMinutes(5)); - map.put(TypedDriverOption.METRICS_NODE_GRAPH_MESSAGES_HIGHEST, Duration.ofSeconds(3)); - map.put(TypedDriverOption.METRICS_NODE_GRAPH_MESSAGES_LOWEST, Duration.ofMillis(1)); - map.put(TypedDriverOption.METRICS_NODE_GRAPH_MESSAGES_DIGITS, 3); - map.put(TypedDriverOption.METRICS_NODE_GRAPH_MESSAGES_INTERVAL, Duration.ofMinutes(5)); map.put(TypedDriverOption.METRICS_NODE_EXPIRE_AFTER, Duration.ofHours(1)); map.put(TypedDriverOption.SOCKET_TCP_NODELAY, true); map.put(TypedDriverOption.HEARTBEAT_INTERVAL, Duration.ofSeconds(30)); diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java index af93e734ef1..da5a474a31c 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java @@ -793,115 +793,9 @@ public String toString() { new TypedDriverOption<>( DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_INTERVAL, GenericType.DURATION); - /** The read consistency level to use for graph statements. */ - public static final TypedDriverOption GRAPH_READ_CONSISTENCY_LEVEL = - new TypedDriverOption<>(DseDriverOption.GRAPH_READ_CONSISTENCY_LEVEL, GenericType.STRING); - /** The write consistency level to use for graph statements. */ - public static final TypedDriverOption GRAPH_WRITE_CONSISTENCY_LEVEL = - new TypedDriverOption<>(DseDriverOption.GRAPH_WRITE_CONSISTENCY_LEVEL, GenericType.STRING); - /** The traversal source to use for graph statements. */ - public static final TypedDriverOption GRAPH_TRAVERSAL_SOURCE = - new TypedDriverOption<>(DseDriverOption.GRAPH_TRAVERSAL_SOURCE, GenericType.STRING); - /** - * The sub-protocol the driver will use to communicate with DSE Graph, on top of the Cassandra - * native protocol. - */ - public static final TypedDriverOption GRAPH_SUB_PROTOCOL = - new TypedDriverOption<>(DseDriverOption.GRAPH_SUB_PROTOCOL, GenericType.STRING); - /** Whether a script statement represents a system query. */ - public static final TypedDriverOption GRAPH_IS_SYSTEM_QUERY = - new TypedDriverOption<>(DseDriverOption.GRAPH_IS_SYSTEM_QUERY, GenericType.BOOLEAN); - /** The name of the graph targeted by graph statements. */ - public static final TypedDriverOption GRAPH_NAME = - new TypedDriverOption<>(DseDriverOption.GRAPH_NAME, GenericType.STRING); - /** How long the driver waits for a graph request to complete. */ - public static final TypedDriverOption GRAPH_TIMEOUT = - new TypedDriverOption<>(DseDriverOption.GRAPH_TIMEOUT, GenericType.DURATION); /** Whether to send events for Insights monitoring. */ public static final TypedDriverOption MONITOR_REPORTING_ENABLED = new TypedDriverOption<>(DseDriverOption.MONITOR_REPORTING_ENABLED, GenericType.BOOLEAN); - /** Whether to enable paging for Graph queries. */ - public static final TypedDriverOption GRAPH_PAGING_ENABLED = - new TypedDriverOption<>(DseDriverOption.GRAPH_PAGING_ENABLED, GenericType.STRING); - /** The page size for Graph continuous paging. */ - public static final TypedDriverOption GRAPH_CONTINUOUS_PAGING_PAGE_SIZE = - new TypedDriverOption<>( - DseDriverOption.GRAPH_CONTINUOUS_PAGING_PAGE_SIZE, GenericType.INTEGER); - /** The maximum number of Graph continuous pages to return. */ - public static final TypedDriverOption GRAPH_CONTINUOUS_PAGING_MAX_PAGES = - new TypedDriverOption<>( - DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_PAGES, GenericType.INTEGER); - /** The maximum number of Graph continuous pages per second. */ - public static final TypedDriverOption GRAPH_CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND = - new TypedDriverOption<>( - DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, GenericType.INTEGER); - /** The maximum number of Graph continuous pages that can be stored in the local queue. */ - public static final TypedDriverOption GRAPH_CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES = - new TypedDriverOption<>( - DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES, GenericType.INTEGER); - /** The largest latency that we expect to record for graph requests. */ - public static final TypedDriverOption METRICS_SESSION_GRAPH_REQUESTS_HIGHEST = - new TypedDriverOption<>( - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_HIGHEST, GenericType.DURATION); - /** The shortest latency that we expect to record for graph requests. */ - public static final TypedDriverOption METRICS_SESSION_GRAPH_REQUESTS_LOWEST = - new TypedDriverOption<>( - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_LOWEST, GenericType.DURATION); - /** Optional service-level objectives to meet, as a list of latencies to track. */ - public static final TypedDriverOption> METRICS_SESSION_GRAPH_REQUESTS_SLO = - new TypedDriverOption<>( - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_SLO, - GenericType.listOf(GenericType.DURATION)); - /** Optional pre-defined percentile of graph requests to publish, as a list of percentiles . */ - public static final TypedDriverOption> - METRICS_SESSION_GRAPH_REQUESTS_PUBLISH_PERCENTILES = - new TypedDriverOption<>( - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_PUBLISH_PERCENTILES, - GenericType.listOf(GenericType.DOUBLE)); - /** - * The number of significant decimal digits to which internal structures will maintain for graph - * requests. - */ - public static final TypedDriverOption METRICS_SESSION_GRAPH_REQUESTS_DIGITS = - new TypedDriverOption<>( - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_DIGITS, GenericType.INTEGER); - /** The interval at which percentile data is refreshed for graph requests. */ - public static final TypedDriverOption METRICS_SESSION_GRAPH_REQUESTS_INTERVAL = - new TypedDriverOption<>( - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_INTERVAL, GenericType.DURATION); - /** The largest latency that we expect to record for graph requests. */ - public static final TypedDriverOption METRICS_NODE_GRAPH_MESSAGES_HIGHEST = - new TypedDriverOption<>( - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_HIGHEST, GenericType.DURATION); - /** The shortest latency that we expect to record for graph requests. */ - public static final TypedDriverOption METRICS_NODE_GRAPH_MESSAGES_LOWEST = - new TypedDriverOption<>( - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_LOWEST, GenericType.DURATION); - /** Optional service-level objectives to meet, as a list of latencies to track. */ - public static final TypedDriverOption> METRICS_NODE_GRAPH_MESSAGES_SLO = - new TypedDriverOption<>( - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_SLO, - GenericType.listOf(GenericType.DURATION)); - /** - * Optional pre-defined percentile of node graph requests to publish, as a list of percentiles . - */ - public static final TypedDriverOption> - METRICS_NODE_GRAPH_MESSAGES_PUBLISH_PERCENTILES = - new TypedDriverOption<>( - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_PUBLISH_PERCENTILES, - GenericType.listOf(GenericType.DOUBLE)); - /** - * The number of significant decimal digits to which internal structures will maintain for graph - * requests. - */ - public static final TypedDriverOption METRICS_NODE_GRAPH_MESSAGES_DIGITS = - new TypedDriverOption<>( - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_DIGITS, GenericType.INTEGER); - /** The interval at which percentile data is refreshed for graph requests. */ - public static final TypedDriverOption METRICS_NODE_GRAPH_MESSAGES_INTERVAL = - new TypedDriverOption<>( - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_INTERVAL, GenericType.DURATION); - /** The time after which the node level metrics will be evicted. */ public static final TypedDriverOption METRICS_NODE_EXPIRE_AFTER = new TypedDriverOption<>(DefaultDriverOption.METRICS_NODE_EXPIRE_AFTER, GenericType.DURATION); diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/metrics/NodeMetric.java b/core/src/main/java/com/datastax/oss/driver/api/core/metrics/NodeMetric.java index b31c0ed8bcf..1c108fd6022 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/metrics/NodeMetric.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/metrics/NodeMetric.java @@ -23,9 +23,8 @@ /** * A node-level metric exposed through {@link Session#getMetrics()}. * - *

All metrics exposed out of the box by the driver are instances of {@link DefaultNodeMetric} or - * {@link com.datastax.dse.driver.api.core.metrics.DseNodeMetric DseNodeMetric} (this interface only - * exists to allow custom metrics in driver extensions). + *

All metrics exposed out of the box by the driver are instances of {@link DefaultNodeMetric} + * (this interface only exists to allow custom metrics in driver extensions). * * @see SessionMetric */ diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardNodeMetricUpdater.java b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardNodeMetricUpdater.java index 2e5e6c8db3d..b0ecfa147fc 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardNodeMetricUpdater.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardNodeMetricUpdater.java @@ -18,8 +18,6 @@ package com.datastax.oss.driver.internal.core.metrics; import com.codahale.metrics.MetricRegistry; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; import com.datastax.oss.driver.api.core.metadata.Node; @@ -78,12 +76,6 @@ public DropwizardNodeMetricUpdater( DefaultDriverOption.METRICS_NODE_CQL_MESSAGES_HIGHEST, DefaultDriverOption.METRICS_NODE_CQL_MESSAGES_DIGITS, DefaultDriverOption.METRICS_NODE_CQL_MESSAGES_INTERVAL); - initializeHdrTimer( - DseNodeMetric.GRAPH_MESSAGES, - profile, - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_HIGHEST, - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_DIGITS, - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_INTERVAL); } @Override diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java index 94e10ad6936..9a5e6aef3f8 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java @@ -45,7 +45,6 @@ public DropwizardSessionMetricUpdater( initializeCounter(DefaultSessionMetric.CQL_CLIENT_TIMEOUTS, profile); initializeCounter(DefaultSessionMetric.THROTTLING_ERRORS, profile); - initializeCounter(DseSessionMetric.GRAPH_CLIENT_TIMEOUTS, profile); initializeHdrTimer( DefaultSessionMetric.CQL_REQUESTS, @@ -65,12 +64,6 @@ public DropwizardSessionMetricUpdater( DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_HIGHEST, DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_DIGITS, DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_INTERVAL); - initializeHdrTimer( - DseSessionMetric.GRAPH_REQUESTS, - profile, - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_HIGHEST, - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_DIGITS, - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_INTERVAL); } @Override diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/MetricPaths.java b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/MetricPaths.java index 92b3fc569f7..3027b3f5b1f 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/MetricPaths.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/MetricPaths.java @@ -17,7 +17,6 @@ */ package com.datastax.oss.driver.internal.core.metrics; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; @@ -56,11 +55,7 @@ public static Set parseNodeMetricPaths(List paths, String lo try { result.add(DefaultNodeMetric.fromPath(path)); } catch (IllegalArgumentException e) { - try { - result.add(DseNodeMetric.fromPath(path)); - } catch (IllegalArgumentException e1) { - LOG.warn("[{}] Unknown node metric {}, skipping", logPrefix, path); - } + LOG.warn("[{}] Unknown node metric {}, skipping", logPrefix, path); } } return Collections.unmodifiableSet(result); diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessors.java b/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessors.java index dc6e6a295a1..1dce884c533 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessors.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessors.java @@ -18,16 +18,11 @@ package com.datastax.oss.driver.internal.core.session; import static com.datastax.oss.driver.internal.core.util.Dependency.REACTIVE_STREAMS; -import static com.datastax.oss.driver.internal.core.util.Dependency.TINKERPOP; import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousCqlRequestAsyncProcessor; import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousCqlRequestSyncProcessor; import com.datastax.dse.driver.internal.core.cql.continuous.reactive.ContinuousCqlRequestReactiveProcessor; import com.datastax.dse.driver.internal.core.cql.reactive.CqlRequestReactiveProcessor; -import com.datastax.dse.driver.internal.core.graph.GraphRequestAsyncProcessor; -import com.datastax.dse.driver.internal.core.graph.GraphRequestSyncProcessor; -import com.datastax.dse.driver.internal.core.graph.GraphSupportChecker; -import com.datastax.dse.driver.internal.core.graph.reactive.ReactiveGraphRequestProcessor; import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; import com.datastax.oss.driver.internal.core.cql.CqlPrepareAsyncProcessor; import com.datastax.oss.driver.internal.core.cql.CqlPrepareSyncProcessor; @@ -47,21 +42,12 @@ public class BuiltInRequestProcessors { public static List> createDefaultProcessors(DefaultDriverContext context) { List> processors = new ArrayList<>(); addBasicProcessors(processors, context); - if (DefaultDependencyChecker.isPresent(TINKERPOP)) { - addGraphProcessors(context, processors); - } else { - LOG.debug("Tinkerpop was not found on the classpath: graph extensions will not be available"); - } if (DefaultDependencyChecker.isPresent(REACTIVE_STREAMS)) { addReactiveProcessors(processors); } else { LOG.debug( "Reactive Streams was not found on the classpath: reactive extensions will not be available"); } - if (DefaultDependencyChecker.isPresent(REACTIVE_STREAMS) - && DefaultDependencyChecker.isPresent(TINKERPOP)) { - addGraphReactiveProcessors(context, processors); - } return processors; } @@ -91,16 +77,6 @@ public static void addBasicProcessors( processors.add(continuousCqlRequestSyncProcessor); } - public static void addGraphProcessors( - DefaultDriverContext context, List> processors) { - GraphRequestAsyncProcessor graphRequestAsyncProcessor = - new GraphRequestAsyncProcessor(context, new GraphSupportChecker()); - GraphRequestSyncProcessor graphRequestSyncProcessor = - new GraphRequestSyncProcessor(graphRequestAsyncProcessor); - processors.add(graphRequestAsyncProcessor); - processors.add(graphRequestSyncProcessor); - } - public static void addReactiveProcessors(List> processors) { CqlRequestReactiveProcessor cqlRequestReactiveProcessor = new CqlRequestReactiveProcessor(new CqlRequestAsyncProcessor()); @@ -109,12 +85,4 @@ public static void addReactiveProcessors(List> processors processors.add(cqlRequestReactiveProcessor); processors.add(continuousCqlRequestReactiveProcessor); } - - public static void addGraphReactiveProcessors( - DefaultDriverContext context, List> processors) { - ReactiveGraphRequestProcessor reactiveGraphRequestProcessor = - new ReactiveGraphRequestProcessor( - new GraphRequestAsyncProcessor(context, new GraphSupportChecker())); - processors.add(reactiveGraphRequestProcessor); - } } diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessorsSubstitutions.java b/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessorsSubstitutions.java index b8bca431228..4318de5395b 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessorsSubstitutions.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessorsSubstitutions.java @@ -18,7 +18,6 @@ package com.datastax.oss.driver.internal.core.session; import static com.datastax.oss.driver.internal.core.util.Dependency.REACTIVE_STREAMS; -import static com.datastax.oss.driver.internal.core.util.Dependency.TINKERPOP; import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; import com.datastax.oss.driver.internal.core.util.GraalDependencyChecker; @@ -31,8 +30,8 @@ @SuppressWarnings("unused") public class BuiltInRequestProcessorsSubstitutions { - @TargetClass(value = BuiltInRequestProcessors.class, onlyWith = GraphMissingReactiveMissing.class) - public static final class BuiltInRequestProcessorsGraphMissingReactiveMissing { + @TargetClass(value = BuiltInRequestProcessors.class, onlyWith = ReactiveMissing.class) + public static final class BuiltInRequestProcessorsReactiveMissing { @Substitute public static List> createDefaultProcessors( @@ -43,8 +42,8 @@ public static final class BuiltInRequestProcessorsGraphMissingReactiveMissing { } } - @TargetClass(value = BuiltInRequestProcessors.class, onlyWith = GraphMissingReactivePresent.class) - public static final class BuiltInRequestProcessorsGraphMissingReactivePresent { + @TargetClass(value = BuiltInRequestProcessors.class, onlyWith = ReactivePresent.class) + public static final class BuiltInRequestProcessorsReactivePresent { @Substitute public static List> createDefaultProcessors( @@ -56,40 +55,17 @@ public static final class BuiltInRequestProcessorsGraphMissingReactivePresent { } } - @TargetClass(value = BuiltInRequestProcessors.class, onlyWith = GraphPresentReactiveMissing.class) - public static final class BuiltInRequestProcessorsGraphPresentReactiveMissing { - - @Substitute - public static List> createDefaultProcessors( - DefaultDriverContext context) { - List> processors = new ArrayList<>(); - BuiltInRequestProcessors.addBasicProcessors(processors, context); - BuiltInRequestProcessors.addGraphProcessors(context, processors); - return processors; - } - } - - public static class GraphMissingReactiveMissing implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - return !GraalDependencyChecker.isPresent(TINKERPOP) - && !GraalDependencyChecker.isPresent(REACTIVE_STREAMS); - } - } - - public static class GraphMissingReactivePresent implements BooleanSupplier { + public static class ReactiveMissing implements BooleanSupplier { @Override public boolean getAsBoolean() { - return !GraalDependencyChecker.isPresent(TINKERPOP) - && GraalDependencyChecker.isPresent(REACTIVE_STREAMS); + return !GraalDependencyChecker.isPresent(REACTIVE_STREAMS); } } - public static class GraphPresentReactiveMissing implements BooleanSupplier { + public static class ReactivePresent implements BooleanSupplier { @Override public boolean getAsBoolean() { - return GraalDependencyChecker.isPresent(TINKERPOP) - && !GraalDependencyChecker.isPresent(REACTIVE_STREAMS); + return GraalDependencyChecker.isPresent(REACTIVE_STREAMS); } } } diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/util/Dependency.java b/core/src/main/java/com/datastax/oss/driver/internal/core/util/Dependency.java index 97cfa25d9af..cc5112e13e9 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/util/Dependency.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/util/Dependency.java @@ -37,11 +37,6 @@ public enum Dependency { SNAPPY("org.xerial.snappy.Snappy"), LZ4("net.jpountz.lz4.LZ4Compressor"), ESRI("com.esri.core.geometry.ogc.OGCGeometry"), - TINKERPOP( - // gremlin-core - "org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal", - // tinkergraph-gremlin - "org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0"), REACTIVE_STREAMS("org.reactivestreams.Publisher"), JACKSON( // jackson-core diff --git a/core/src/main/resources/reference.conf b/core/src/main/resources/reference.conf index 590784b70c5..1a9bf865658 100644 --- a/core/src/main/resources/reference.conf +++ b/core/src/main/resources/reference.conf @@ -301,100 +301,6 @@ datastax-java-driver { // version = } - # Graph (DataStax Enterprise only) - basic.graph { - # The name of the graph targeted by graph statements. - # - # This can also be overridden programmatically with GraphStatement.setGraphName(). If both are - # specified, the programmatic value takes precedence, and this option is ignored. - # - # Required: no. In particular, system queries -- such as creating or dropping a graph -- must be - # executed without a graph name (see also basic.graph.is-system-query). - # Modifiable at runtime: yes, the new value will be used for requests issued after the change. - # Overridable in a profile: yes - // name = your-graph-name - - # The traversal source to use for graph statements. - # - # This setting doesn't usually need to change, unless executing OLAP queries, which require the - # traversal source "a". - # - # This can also be overridden programmatically with GraphStatement.setTraversalSource(). If both - # are specified, the programmatic value takes precedence, and this option is ignored. - # - # Required: no - # Modifiable at runtime: yes, the new value will be used for requests issued after the change. - # Overridable in a profile: yes - traversal-source = "g" - - # Whether a script statement represents a system query. - # - # Script statements that access the `system` variable *must not* specify a graph name (otherwise - # `system` is not available). However, if your application executes a lot of non-system - # statements, it is convenient to configure basic.graph.name to avoid repeating it every time. - # This option allows you to ignore that global graph name, for example in a specific profile. - # - # This can also be overridden programmatically with ScriptGraphStatement.setSystemQuery(). If - # both are specified, the programmatic value takes precedence, and this option is ignored. - # - # Required: no (defaults to false) - # Modifiable at runtime: yes, the new value will be used for requests issued after the change. - # Overridable in a profile: yes - // is-system-query = false - - # The read consistency level to use for graph statements. - # - # DSE Graph is able to distinguish between read and write timeouts for the internal storage - # queries that will be produced by a traversal. Hence the consistency level for reads and writes - # can be set separately. - # - # This can also be overridden programmatically with GraphStatement.setReadConsistencyLevel(). If - # both are specified, the programmatic value takes precedence, and this option is ignored. - # - # Required: no (defaults to request.basic.consistency) - # Modifiable at runtime: yes, the new value will be used for requests issued after the change. - # Overridable in a profile: yes - // read-consistency-level = LOCAL_QUORUM - - # The write consistency level to use for graph statements. - # - # DSE Graph is able to distinguish between read and write timeouts for the internal storage - # queries that will be produced by a traversal. Hence the consistency level for reads and writes - # can be set separately. - # - # This can also be overridden programmatically with GraphStatement.setReadConsistencyLevel(). If - # both are specified, the programmatic value takes precedence, and this option is ignored. - # - # Required: no (defaults to request.basic.consistency) - # Modifiable at runtime: yes, the new value will be used for requests issued after the change. - # Overridable in a profile: yes - // write-consistency-level = LOCAL_ONE - - # How long the driver waits for a graph request to complete. This is a global limit on the - # duration of a session.execute() call, including any internal retries the driver might do. - # - # Graph statements behave a bit differently than regular CQL requests (hence this dedicated - # option instead of reusing basic.request.timeout): by default, the client timeout is not set, - # and the driver will just wait as long as needed until the server replies (which is itself - # governed by server-side timeout configuration). - # If you specify a client timeout with this option, then the driver will fail the request after - # the given time; note that the value is also sent along with the request, so that the server - # can also time out early and avoid wasting resources on a response that the client has already - # given up on. - # - # This can also be overridden programmatically with GraphStatement.setTimeout(). If both are - # specified, the programmatic value takes precedence, and this option is ignored. - # - # If this value is left unset (default) or is explicitly set to zero, no timeout will be - # applied. - # - # Required: no (defaults to zero - no timeout) - # Modifiable at runtime: yes, the new value will be used for requests issued after the change. - # Overridable in a profile: yes - // timeout = 10 seconds - } - - # ADVANCED OPTIONS ------------------------------------------------------------------------------- # The maximum number of live sessions that are allowed to coexist in a given VM. @@ -1369,100 +1275,6 @@ datastax-java-driver { log-warnings = true } - # Graph (DataStax Enterprise only) - advanced.graph { - # The sub-protocol the driver will use to communicate with DSE Graph, on top of the Cassandra - # native protocol. - # - # You should almost never have to change this: the driver sets it automatically, based on the - # information it has about the server. One exception is if you use the script API against a - # legacy DSE version (5.0.3 or older). In that case, you need to force the sub-protocol to - # "graphson-1.0". - # - # This can also be overridden programmatically with GraphStatement.setSubProtocol(). If both are - # specified, the programmatic value takes precedence, and this option is ignored. - # - # Possible values with built-in support in the driver are: - # [ "graphson-1.0", "graphson-2.0", "graph-binary-1.0"] - # - # IMPORTANT: The default value for the Graph sub-protocol is based only on the DSE - # version. If the version is DSE 6.7 and lower, "graphson-2.0" will be the default. For DSE 6.8 - # and higher, the default value is "graphson-binary-1.0". - # - # Required: no - # Modifiable at runtime: yes, the new value will be used for requests issued after the change. - # Overridable in a profile: yes - // sub-protocol = "graphson-2.0" - - # - # Whether or not Graph paging should be enabled or disabled for all queries. - # - #

If AUTO is set, the driver will decide whether or not to enable Graph paging - # based on the protocol version in use and the DSE version of all hosts. For this reason it is - # usually not necessary to change this setting. - # - #

IMPORTANT: Paging for DSE Graph is only available in DSE 6.8 and higher, and - # requires protocol version DSE_V1 or higher and graphs created with the Native engine; enabling - # paging for clusters and graphs that do not meet this requirement may result in query failures. - # - # Supported values are: ENABLED, DISABLED, AUTO - paging-enabled = "AUTO" - - - paging-options { - - # The page size. - # - # The value specified here can be interpreted in number of rows. - # Interpetation in number of bytes is not supported for graph continuous paging queries. - # - # It controls how many rows will be retrieved simultaneously in a single - # network roundtrip (the goal being to avoid loading too many results in memory at the same - # time). If there are more results, additional requests will be used to retrieve them (either - # automatically if you iterate with the sync API, or explicitly with the async API's - # fetchNextPage method). - # - # The default is the same as the driver's normal request page size, - # i.e., 5000 (rows). - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - page-size = ${datastax-java-driver.advanced.continuous-paging.page-size} - - # The maximum number of pages to return. - # - # The default is zero, which means retrieve all pages. - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - max-pages = ${datastax-java-driver.advanced.continuous-paging.max-pages} - - # Returns the maximum number of pages per second. - # - # The default is zero, which means no limit. - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - max-pages-per-second = ${datastax-java-driver.advanced.continuous-paging.max-pages-per-second} - - # Returns the maximum number of pages per second. - # - # The default is zero, which means no limit. - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - max-enqueued-pages = ${datastax-java-driver.advanced.continuous-paging.max-enqueued-pages} - } - } - # Continuous paging (DataStax Enterprise only) advanced.continuous-paging { @@ -1745,20 +1557,6 @@ datastax-java-driver { # - At session level: only 'continuous-cql-requests' is updated (this metric). // continuous-cql-requests, - # The throughput and latency percentiles of Graph requests (exposed as a Timer). - # - # This metric is a session-level metric and corresponds to the overall duration of the - # session.execute(GraphStatement) call, including any retry. - // graph-requests, - - # The number of graph requests that timed out -- that is, the - # session.execute(GraphStatement) call failed with a DriverTimeoutException (exposed as a - # Counter). - # - # Note that this metric is analogous to the OSS driver's 'cql-client-timeouts' metrics, but - # for Graph requests only. - // graph-client-timeouts - ] # Extra configuration (for the metrics that need it) @@ -1850,17 +1648,6 @@ datastax-java-driver { // publish-percentiles = [ 0.75, 0.95, 0.99 ] } - # Required: if the 'graph-requests' metric is enabled, and Dropwizard or Micrometer is used. - # Modifiable at runtime: no - # Overridable in a profile: no - graph-requests { - highest-latency = 12 seconds - lowest-latency = 1 millisecond - significant-digits = 3 - refresh-interval = 5 minutes - // slo = [ 100 milliseconds, 500 milliseconds, 1 second ] - // publish-percentiles = [ 0.75, 0.95, 0.99 ] - } } # The node-level metrics (all disabled by default). # @@ -2000,17 +1787,6 @@ datastax-java-driver { # Authentication errors are also logged at WARN level. // errors.connection.auth, - # The throughput and latency percentiles of individual graph messages sent to this node as - # part of an overall request (exposed as a Timer). - # - # Note that this does not necessarily correspond to the overall duration of the - # session.execute() call, since the driver might query multiple nodes because of retries - # and speculative executions. Therefore a single "request" (as seen from a client of the - # driver) can be composed of more than one of the "messages" measured by this metric. - # - # Therefore this metric is intended as an insight into the performance of this particular - # node. For statistics on overall request completion, use the session-level graph-requests. - // graph-messages, ] # See cql-requests in the `session` section @@ -2027,20 +1803,6 @@ datastax-java-driver { // publish-percentiles = [ 0.75, 0.95, 0.99 ] } - # See graph-requests in the `session` section - # - # Required: if the 'graph-messages' metric is enabled, and Dropwizard or Micrometer is used. - # Modifiable at runtime: no - # Overridable in a profile: no - graph-messages { - highest-latency = 3 seconds - lowest-latency = 1 millisecond - significant-digits = 3 - refresh-interval = 5 minutes - // slo = [ 100 milliseconds, 500 milliseconds, 1 second ] - // publish-percentiles = [ 0.75, 0.95, 0.99 ] - } - # The time after which the node level metrics will be evicted. # # This is used to unregister stale metrics if a node leaves the cluster or gets a new address. @@ -2580,20 +2342,5 @@ datastax-java-driver { # olap { # basic.request.timeout = 5 seconds # } - - # An example configuration profile for graph requests. - // my-graph-profile-example { - // graph { - // read-consistency-level = LOCAL_QUORUM - // write-consistency-level = LOCAL_ONE - // } - // } - - # An example pre-defined configuration profile for OLAP graph queries. - // graph-olap { - // graph { - // traversal-source = "a" // traversal source needs to be set to "a" for OLAP queries. - // } - // } } } diff --git a/core/src/test/java/com/datastax/dse/driver/Assertions.java b/core/src/test/java/com/datastax/dse/driver/Assertions.java deleted file mode 100644 index 09f7b281f84..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/Assertions.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver; - -import org.apache.tinkerpop.gremlin.structure.io.Buffer; - -public class Assertions extends org.assertj.core.api.Assertions { - public static TinkerpopBufferAssert assertThat(Buffer actual) { - return new TinkerpopBufferAssert(actual); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/DseTestDataProviders.java b/core/src/test/java/com/datastax/dse/driver/DseTestDataProviders.java index 7d9aecc28ed..4c732ccda83 100644 --- a/core/src/test/java/com/datastax/dse/driver/DseTestDataProviders.java +++ b/core/src/test/java/com/datastax/dse/driver/DseTestDataProviders.java @@ -17,13 +17,7 @@ */ package com.datastax.dse.driver; -import static com.datastax.dse.driver.internal.core.graph.GraphProtocol.GRAPHSON_1_0; -import static com.datastax.dse.driver.internal.core.graph.GraphProtocol.GRAPHSON_2_0; -import static com.datastax.dse.driver.internal.core.graph.GraphProtocol.GRAPH_BINARY_1_0; - import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.TestDataProviders; import com.datastax.oss.driver.api.core.DefaultProtocolVersion; import com.tngtech.java.junit.dataprovider.DataProvider; import edu.umd.cs.findbugs.annotations.NonNull; @@ -32,13 +26,6 @@ public class DseTestDataProviders { - private static final ScriptGraphStatement UNDEFINED_IDEMPOTENCE_STATEMENT = - ScriptGraphStatement.newInstance("undefined idempotence"); - private static final ScriptGraphStatement IDEMPOTENT_STATEMENT = - ScriptGraphStatement.builder("idempotent").setIdempotence(true).build(); - private static final ScriptGraphStatement NON_IDEMPOTENT_STATEMENT = - ScriptGraphStatement.builder("non idempotent").setIdempotence(false).build(); - @DataProvider public static Object[][] allDseProtocolVersions() { return concat(DseProtocolVersion.values()); @@ -54,42 +41,6 @@ public static Object[][] allDseAndOssProtocolVersions() { return concat(DefaultProtocolVersion.values(), DseProtocolVersion.values()); } - @DataProvider - public static Object[][] supportedGraphProtocols() { - return new Object[][] {{GRAPHSON_1_0}, {GRAPHSON_2_0}, {GRAPH_BINARY_1_0}}; - } - - /** - * The combination of the default idempotence option and statement setting that produce an - * idempotent statement. - */ - @DataProvider - public static Object[][] idempotentGraphConfig() { - return new Object[][] { - new Object[] {true, UNDEFINED_IDEMPOTENCE_STATEMENT}, - new Object[] {false, IDEMPOTENT_STATEMENT}, - new Object[] {true, IDEMPOTENT_STATEMENT}, - }; - } - - /** - * The combination of the default idempotence option and statement setting that produce a non - * idempotent statement. - */ - @DataProvider - public static Object[][] nonIdempotentGraphConfig() { - return new Object[][] { - new Object[] {false, UNDEFINED_IDEMPOTENCE_STATEMENT}, - new Object[] {true, NON_IDEMPOTENT_STATEMENT}, - new Object[] {false, NON_IDEMPOTENT_STATEMENT}, - }; - } - - @DataProvider - public static Object[][] allDseProtocolVersionsAndSupportedGraphProtocols() { - return TestDataProviders.combine(allDseProtocolVersions(), supportedGraphProtocols()); - } - @NonNull private static Object[][] concat(Object[]... values) { return Stream.of(values) diff --git a/core/src/test/java/com/datastax/dse/driver/TinkerpopBufferAssert.java b/core/src/test/java/com/datastax/dse/driver/TinkerpopBufferAssert.java deleted file mode 100644 index 278e5a65070..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/TinkerpopBufferAssert.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.oss.protocol.internal.util.Bytes; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.assertj.core.api.AbstractAssert; - -public class TinkerpopBufferAssert extends AbstractAssert { - public TinkerpopBufferAssert(Buffer actual) { - super(actual, TinkerpopBufferAssert.class); - } - - public TinkerpopBufferAssert containsExactly(String hexString) { - - byte[] expectedBytes = Bytes.fromHexString(hexString).array(); - byte[] actualBytes = new byte[expectedBytes.length]; - actual.readBytes(actualBytes); - assertThat(actualBytes).containsExactly(expectedBytes); - assertThat(actual.readableBytes()).isEqualTo(0); - return this; - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/CqlCollectionTest.java b/core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/CqlCollectionTest.java deleted file mode 100644 index a890720a3ef..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/CqlCollectionTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.predicates; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import com.datastax.oss.driver.shaded.guava.common.collect.Lists; -import com.datastax.oss.driver.shaded.guava.common.collect.Sets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import org.apache.tinkerpop.gremlin.process.traversal.P; -import org.junit.Test; - -public class CqlCollectionTest { - - @Test - public void should_evaluate_contains() { - P> contains = CqlCollection.contains("foo"); - assertThat(contains.test(new HashSet<>())).isFalse(); - assertThat(contains.test(new ArrayList<>())).isFalse(); - assertThat(contains.test(Sets.newHashSet("foo"))).isTrue(); - assertThat(contains.test(Lists.newArrayList("foo"))).isTrue(); - assertThat(contains.test(Sets.newHashSet("bar"))).isFalse(); - assertThat(contains.test(Lists.newArrayList("bar"))).isFalse(); - assertThatThrownBy(() -> contains.test(null)).isInstanceOf(IllegalArgumentException.class); - assertThatThrownBy(() -> CqlCollection.contains(null).test(Sets.newHashSet("foo"))) - .isInstanceOf(IllegalArgumentException.class); - } - - @Test - public void should_evaluate_containsKey() { - P> containsKey = CqlCollection.containsKey("foo"); - assertThat(containsKey.test(new HashMap<>())).isFalse(); - assertThat(containsKey.test(new LinkedHashMap<>())).isFalse(); - assertThat(containsKey.test(ImmutableMap.of("foo", "bar"))).isTrue(); - assertThat(containsKey.test(ImmutableMap.of("bar", "foo"))).isFalse(); - assertThatThrownBy(() -> containsKey.test(null)).isInstanceOf(IllegalArgumentException.class); - assertThatThrownBy(() -> CqlCollection.containsKey(null).test(ImmutableMap.of("foo", "bar"))) - .isInstanceOf(IllegalArgumentException.class); - } - - @Test - public void should_evaluate_containsValue() { - P> containsValue = CqlCollection.containsValue("foo"); - assertThat(containsValue.test(new HashMap<>())).isFalse(); - assertThat(containsValue.test(new LinkedHashMap<>())).isFalse(); - assertThat(containsValue.test(ImmutableMap.of("bar", "foo"))).isTrue(); - assertThat(containsValue.test(ImmutableMap.of("foo", "bar"))).isFalse(); - assertThatThrownBy(() -> containsValue.test(null)).isInstanceOf(IllegalArgumentException.class); - assertThatThrownBy(() -> CqlCollection.containsValue(null).test(ImmutableMap.of("foo", "bar"))) - .isInstanceOf(IllegalArgumentException.class); - } - - @Test - public void should_evaluate_entryEq() { - P> entryEq = CqlCollection.entryEq("foo", "bar"); - assertThat(entryEq.test(new HashMap<>())).isFalse(); - assertThat(entryEq.test(new LinkedHashMap<>())).isFalse(); - assertThat(entryEq.test(ImmutableMap.of("foo", "bar"))).isTrue(); - assertThat(entryEq.test(ImmutableMap.of("bar", "foo"))).isFalse(); - assertThatThrownBy(() -> entryEq.test(null)).isInstanceOf(IllegalArgumentException.class); - assertThatThrownBy(() -> CqlCollection.entryEq(null, "foo").test(ImmutableMap.of("foo", "bar"))) - .isInstanceOf(IllegalArgumentException.class); - assertThatThrownBy(() -> CqlCollection.entryEq("foo", null).test(ImmutableMap.of("foo", "bar"))) - .isInstanceOf(IllegalArgumentException.class); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/GeoTest.java b/core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/GeoTest.java deleted file mode 100644 index 143aec97b78..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/GeoTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.predicates; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import org.apache.tinkerpop.gremlin.process.traversal.P; -import org.junit.Test; - -public class GeoTest { - - @Test - public void should_convert_units_to_degrees() { - assertThat(Geo.Unit.DEGREES.toDegrees(100.0)).isEqualTo(100.0); - assertThat(Geo.Unit.MILES.toDegrees(68.9722)).isEqualTo(0.9982455747535043); - assertThat(Geo.Unit.KILOMETERS.toDegrees(111.0)).isEqualTo(0.9982456082154465); - assertThat(Geo.Unit.METERS.toDegrees(111000.0)).isEqualTo(0.9982456082154464); - } - - @Test - public void should_test_if_point_is_inside_circle_with_cartesian_coordinates() { - P inside = Geo.inside(Point.fromCoordinates(30, 30), 14.142135623730951); - assertThat(inside.test(Point.fromCoordinates(40, 40))).isTrue(); - assertThat(inside.test(Point.fromCoordinates(40.1, 40))).isFalse(); - } - - @Test - public void should_test_if_point_is_inside_circle_with_geo_coordinates() { - P inside = - Geo.inside(Point.fromCoordinates(30, 30), 12.908258700131379, Geo.Unit.DEGREES); - assertThat(inside.test(Point.fromCoordinates(40, 40))).isTrue(); - assertThat(inside.test(Point.fromCoordinates(40.1, 40))).isFalse(); - } - - @Test - public void should_test_if_point_is_inside_polygon() { - P inside = - Geo.inside( - Polygon.builder() - .addRing( - Point.fromCoordinates(30, 30), - Point.fromCoordinates(40, 40), - Point.fromCoordinates(40, 30)) - .build()); - assertThat(inside.test(Point.fromCoordinates(35, 32))).isTrue(); - assertThat(inside.test(Point.fromCoordinates(33, 37))).isFalse(); - } - - @Test - public void should_build_line_string_from_coordinates() { - LineString lineString = Geo.lineString(1, 2, 3, 4, 5, 6); - assertThat(lineString.getPoints()) - .hasSize(3) - .contains(Point.fromCoordinates(1, 2)) - .contains(Point.fromCoordinates(3, 4)) - .contains(Point.fromCoordinates(5, 6)); - } - - @Test(expected = IllegalArgumentException.class) - public void should_fail_to_build_line_string_if_not_enough_coordinates() { - Geo.lineString(1, 2); - } - - @Test(expected = IllegalArgumentException.class) - public void should_fail_to_build_line_string_if_uneven_number_of_coordinates() { - Geo.lineString(1, 2, 3, 4, 5); - } - - @Test - public void should_build_polygon_from_coordinates() { - Polygon polygon = Geo.polygon(1, 2, 3, 4, 5, 6, 7, 8); - assertThat(polygon.getExteriorRing()) - .hasSize(4) - .contains(Point.fromCoordinates(1, 2)) - .contains(Point.fromCoordinates(3, 4)) - .contains(Point.fromCoordinates(5, 6)) - .contains(Point.fromCoordinates(7, 8)); - assertThat(polygon.getInteriorRings()).isEmpty(); - } - - @Test(expected = IllegalArgumentException.class) - public void should_fail_to_build_polygon_if_not_enough_coordinates() { - Geo.polygon(1, 2, 3, 4); - } - - @Test(expected = IllegalArgumentException.class) - public void should_fail_to_build_polygon_if_uneven_number_of_coordinates() { - Geo.polygon(1, 2, 3, 4, 5, 6, 7); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/SearchTest.java b/core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/SearchTest.java deleted file mode 100644 index 591269e31ad..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/api/core/graph/predicates/SearchTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.predicates; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.apache.tinkerpop.gremlin.process.traversal.P; -import org.junit.Test; - -public class SearchTest { - - @Test - public void testToken() { - P p = Search.token("needle"); - assertThat(p.test("needle")).isTrue(); - assertThat(p.test("This is a needle in a haystack")).isTrue(); - assertThat(p.test("This is just the haystack")).isFalse(); - } - - @Test - public void testPrefix() { - P p = Search.prefix("abcd"); - assertThat(p.test("abcd")).isTrue(); - assertThat(p.test("abcdefg hijkl")).isTrue(); - assertThat(p.test("zabcd")).isFalse(); - } - - @Test - public void testTokenPrefix() { - P p = Search.tokenPrefix("abcd"); - assertThat(p.test("abcd")).isTrue(); - assertThat(p.test("abcdefg hijkl")).isTrue(); - assertThat(p.test("z abcd")).isTrue(); - assertThat(p.test("ab cd")).isFalse(); - } - - @Test - public void testRegex() { - P p = Search.regex("(foo|bar)"); - assertThat(p.test("foo")).isTrue(); - assertThat(p.test("bar")).isTrue(); - assertThat(p.test("foo bar")).isFalse(); - } - - @Test - public void testTokenRegex() { - P p = Search.tokenRegex("(foo|bar)"); - assertThat(p.test("foo")).isTrue(); - assertThat(p.test("bar")).isTrue(); - assertThat(p.test("foo bar")).isTrue(); - assertThat(p.test("foo bar qix")).isTrue(); - assertThat(p.test("qix")).isFalse(); - } - - @Test - public void testPhrase() { - P p = Search.phrase("Hello world", 2); - assertThat(p.test("Hello World")).isTrue(); - assertThat(p.test("Hello Big World")).isTrue(); - assertThat(p.test("Hello Big Wild World")).isTrue(); - assertThat(p.test("Hello The Big Wild World")).isFalse(); - assertThat(p.test("Goodbye world")).isFalse(); - } - - @Test - public void testPhraseFragment() { - // Tests JAVA-1744 - P p = Search.phrase("a b", 0); - assertThat(p.test("a b")).isTrue(); - assertThat(p.test("a")).isFalse(); - assertThat(p.test("b")).isFalse(); - } - - @Test - public void testFuzzy() { - P p = Search.fuzzy("abc", 1); - assertThat(p.test("abcd")).isTrue(); - assertThat(p.test("ab")).isTrue(); - assertThat(p.test("abce")).isTrue(); - assertThat(p.test("abdc")).isTrue(); - assertThat(p.test("badc")).isFalse(); - - // Make sure we do NOT calculate the Damerau–Levenshtein distance (2), but the optimal string - // alignment distance (3): - assertThat(Search.tokenFuzzy("ca", 2).test("abc")).isFalse(); - } - - @Test - public void testTokenFuzzy() { - P p = Search.tokenFuzzy("abc", 1); - assertThat(p.test("foo abcd")).isTrue(); - assertThat(p.test("foo ab")).isTrue(); - assertThat(p.test("foo abce")).isTrue(); - assertThat(p.test("foo abdc")).isTrue(); - assertThat(p.test("foo badc")).isFalse(); - - // Make sure we do NOT calculate the Damerau–Levenshtein distance (2), but the optimal string - // alignment distance (3): - assertThat(Search.tokenFuzzy("ca", 2).test("abc 123")).isFalse(); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/data/geometry/DistanceTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/data/geometry/DistanceTest.java deleted file mode 100644 index ba158288891..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/data/geometry/DistanceTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.data.geometry; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import org.junit.Test; - -public class DistanceTest { - - private final Point point = Point.fromCoordinates(1.1, 2.2); - private final Distance distance = new Distance(point, 7.0); - private final String wkt = "DISTANCE((1.1 2.2) 7.0)"; - - @Test - public void should_parse_valid_well_known_text() { - Distance fromWkt = Distance.fromWellKnownText(wkt); - assertThat(fromWkt.getRadius()).isEqualTo(7.0); - assertThat(fromWkt.getCenter()).isEqualTo(point); - assertThat(Distance.fromWellKnownText(wkt)).isEqualTo(distance); - // whitespace doesn't matter between distance and spec. - assertThat(Distance.fromWellKnownText("DISTANCE ((1.1 2.2) 7.0)")).isEqualTo(distance); - // case doesn't matter. - assertThat(Distance.fromWellKnownText("distance((1.1 2.2) 7.0)")).isEqualTo(distance); - } - - @Test(expected = IllegalArgumentException.class) - public void should_fail_to_parse_invalid_well_known_text() { - Distance.fromWellKnownText("dist((1.1 2.2) 3.3)"); - } - - @Test - public void should_convert_to_well_known_text() { - assertThat(distance.asWellKnownText()).isEqualTo(wkt); - } - - @Test - public void should_contain_point() { - assertThat(distance.contains(Point.fromCoordinates(2.0, 3.0))).isTrue(); - } - - @Test - public void should_not_contain_point() { - // y axis falls outside of distance - assertThat(distance.contains(Point.fromCoordinates(2.0, 9.3))).isFalse(); - } - - @Test - public void should_contain_linestring() { - assertThat( - distance.contains( - LineString.fromPoints( - Point.fromCoordinates(2.0, 3.0), - Point.fromCoordinates(3.1, 6.2), - Point.fromCoordinates(-1.0, -2.0)))) - .isTrue(); - } - - @Test - public void should_not_contain_linestring() { - // second point falls outside of distance at y axis. - assertThat( - distance.contains( - LineString.fromPoints( - Point.fromCoordinates(2.0, 3.0), - Point.fromCoordinates(3.1, 9.2), - Point.fromCoordinates(-1.0, -2.0)))) - .isFalse(); - } - - @Test - public void should_contain_polygon() { - Polygon polygon = - Polygon.fromPoints( - Point.fromCoordinates(3, 1), - Point.fromCoordinates(1, 2), - Point.fromCoordinates(2, 4), - Point.fromCoordinates(4, 4)); - assertThat(distance.contains(polygon)).isTrue(); - } - - @Test - public void should_not_contain_polygon() { - Polygon polygon = - Polygon.fromPoints( - Point.fromCoordinates(3, 1), - Point.fromCoordinates(1, 2), - Point.fromCoordinates(2, 4), - Point.fromCoordinates(10, 4)); - // final point falls outside of distance at x axis. - assertThat(distance.contains(polygon)).isFalse(); - } - - @Test(expected = UnsupportedOperationException.class) - public void should_fail_to_convert_to_ogc() { - distance.getOgcGeometry(); - } - - @Test(expected = UnsupportedOperationException.class) - public void should_fail_to_convert_to_wkb() { - distance.asWellKnownBinary(); - } - - @Test(expected = UnsupportedOperationException.class) - public void should_fail_to_convert_to_geo_json() { - distance.asGeoJson(); - } - - @Test - public void should_serialize_and_deserialize() throws Exception { - assertThat(SerializationUtils.serializeAndDeserialize(distance)).isEqualTo(distance); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/data/geometry/SerializationUtils.java b/core/src/test/java/com/datastax/dse/driver/internal/core/data/geometry/SerializationUtils.java index 84bd1dab343..50fdbc8e7df 100644 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/data/geometry/SerializationUtils.java +++ b/core/src/test/java/com/datastax/dse/driver/internal/core/data/geometry/SerializationUtils.java @@ -37,10 +37,8 @@ public static Object serializeAndDeserialize(Geometry geometry) out.writeObject(geometry); byte[] bytes = baos.toByteArray(); - if (!(geometry instanceof Distance)) { - byte[] wkb = Bytes.getArray(geometry.asWellKnownBinary()); - assertThat(bytes).containsSequence(wkb); - } + byte[] wkb = Bytes.getArray(geometry.asWellKnownBinary()); + assertThat(bytes).containsSequence(wkb); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); return in.readObject(); } diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandlerSpeculativeExecutionTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandlerSpeculativeExecutionTest.java deleted file mode 100644 index f9ef1ebf6f0..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandlerSpeculativeExecutionTest.java +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.createGraphBinaryModule; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.defaultDseFrameOf; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.singleGraphRow; -import static com.datastax.oss.driver.Assertions.assertThat; -import static com.datastax.oss.driver.Assertions.assertThatStage; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.DseTestDataProviders; -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; -import com.datastax.dse.driver.internal.core.graph.binary.GraphBinaryModule; -import com.datastax.oss.driver.api.core.AllNodesFailedException; -import com.datastax.oss.driver.api.core.NoNodeAvailableException; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; -import com.datastax.oss.driver.api.core.metrics.NodeMetric; -import com.datastax.oss.driver.api.core.servererrors.BootstrappingException; -import com.datastax.oss.driver.api.core.specex.SpeculativeExecutionPolicy; -import com.datastax.oss.driver.internal.core.cql.PoolBehavior; -import com.datastax.oss.driver.internal.core.metadata.DefaultNode; -import com.datastax.oss.driver.internal.core.metrics.NodeMetricUpdater; -import com.datastax.oss.driver.internal.core.util.concurrent.CapturingTimer.CapturedTimeout; -import com.datastax.oss.protocol.internal.ProtocolConstants; -import com.datastax.oss.protocol.internal.response.Error; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.time.Duration; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * These tests are almost exact copies of {@link - * com.datastax.oss.driver.internal.core.cql.CqlRequestHandlerSpeculativeExecutionTest}. - */ -@RunWith(DataProviderRunner.class) -public class ContinuousGraphRequestHandlerSpeculativeExecutionTest { - - @Mock DefaultNode node1; - @Mock DefaultNode node2; - @Mock DefaultNode node3; - - @Mock NodeMetricUpdater nodeMetricUpdater1; - @Mock NodeMetricUpdater nodeMetricUpdater2; - @Mock NodeMetricUpdater nodeMetricUpdater3; - - @Mock GraphSupportChecker graphSupportChecker; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - when(node1.getMetricUpdater()).thenReturn(nodeMetricUpdater1); - when(node2.getMetricUpdater()).thenReturn(nodeMetricUpdater2); - when(node3.getMetricUpdater()).thenReturn(nodeMetricUpdater3); - when(nodeMetricUpdater1.isEnabled(any(NodeMetric.class), anyString())).thenReturn(true); - when(nodeMetricUpdater2.isEnabled(any(NodeMetric.class), anyString())).thenReturn(true); - when(nodeMetricUpdater3.isEnabled(any(NodeMetric.class), anyString())).thenReturn(true); - when(graphSupportChecker.inferGraphProtocol(any(), any(), any())) - .thenReturn(GraphProtocol.GRAPH_BINARY_1_0); - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "nonIdempotentGraphConfig") - public void should_not_schedule_speculative_executions_if_not_idempotent( - boolean defaultIdempotence, GraphStatement statement) { - GraphRequestHandlerTestHarness.Builder harnessBuilder = - GraphRequestHandlerTestHarness.builder().withDefaultIdempotence(defaultIdempotence); - PoolBehavior node1Behavior = harnessBuilder.customBehavior(node1); - - try (GraphRequestHandlerTestHarness harness = harnessBuilder.build()) { - SpeculativeExecutionPolicy speculativeExecutionPolicy = - harness.getContext().getSpeculativeExecutionPolicy(DriverExecutionProfile.DEFAULT_NAME); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - new ContinuousGraphRequestHandler( - statement, - harness.getSession(), - harness.getContext(), - "test", - module, - graphSupportChecker) - .handle(); - - node1Behavior.verifyWrite(); - node1Behavior.setWriteSuccess(); - - // should not schedule any timeout - assertThat(harness.nextScheduledTimeout()).isNull(); - - verifyNoMoreInteractions(speculativeExecutionPolicy); - verifyNoMoreInteractions(nodeMetricUpdater1); - } - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "idempotentGraphConfig") - public void should_schedule_speculative_executions( - boolean defaultIdempotence, GraphStatement statement) throws Exception { - GraphRequestHandlerTestHarness.Builder harnessBuilder = - GraphRequestHandlerTestHarness.builder().withDefaultIdempotence(defaultIdempotence); - PoolBehavior node1Behavior = harnessBuilder.customBehavior(node1); - PoolBehavior node2Behavior = harnessBuilder.customBehavior(node2); - PoolBehavior node3Behavior = harnessBuilder.customBehavior(node3); - - try (GraphRequestHandlerTestHarness harness = harnessBuilder.build()) { - SpeculativeExecutionPolicy speculativeExecutionPolicy = - harness.getContext().getSpeculativeExecutionPolicy(DriverExecutionProfile.DEFAULT_NAME); - long firstExecutionDelay = 100L; - long secondExecutionDelay = 200L; - when(speculativeExecutionPolicy.nextExecution( - any(Node.class), eq(null), eq(statement), eq(1))) - .thenReturn(firstExecutionDelay); - when(speculativeExecutionPolicy.nextExecution( - any(Node.class), eq(null), eq(statement), eq(2))) - .thenReturn(secondExecutionDelay); - when(speculativeExecutionPolicy.nextExecution( - any(Node.class), eq(null), eq(statement), eq(3))) - .thenReturn(-1L); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - new ContinuousGraphRequestHandler( - statement, - harness.getSession(), - harness.getContext(), - "test", - module, - graphSupportChecker) - .handle(); - - node1Behavior.verifyWrite(); - node1Behavior.setWriteSuccess(); - - CapturedTimeout speculativeExecution1 = harness.nextScheduledTimeout(); - assertThat(speculativeExecution1.getDelay(TimeUnit.MILLISECONDS)) - .isEqualTo(firstExecutionDelay); - verifyNoMoreInteractions(nodeMetricUpdater1); - speculativeExecution1.task().run(speculativeExecution1); - verify(nodeMetricUpdater1) - .incrementCounter( - DefaultNodeMetric.SPECULATIVE_EXECUTIONS, DriverExecutionProfile.DEFAULT_NAME); - node2Behavior.verifyWrite(); - node2Behavior.setWriteSuccess(); - - CapturedTimeout speculativeExecution2 = harness.nextScheduledTimeout(); - assertThat(speculativeExecution2.getDelay(TimeUnit.MILLISECONDS)) - .isEqualTo(secondExecutionDelay); - verifyNoMoreInteractions(nodeMetricUpdater2); - speculativeExecution2.task().run(speculativeExecution2); - verify(nodeMetricUpdater2) - .incrementCounter( - DefaultNodeMetric.SPECULATIVE_EXECUTIONS, DriverExecutionProfile.DEFAULT_NAME); - node3Behavior.verifyWrite(); - node3Behavior.setWriteSuccess(); - - // No more scheduled tasks since the policy returns 0 on the third call. - assertThat(harness.nextScheduledTimeout()).isNull(); - - // Note that we don't need to complete any response, the test is just about checking that - // executions are started. - } - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "idempotentGraphConfig") - public void should_not_start_execution_if_result_complete( - boolean defaultIdempotence, GraphStatement statement) throws Exception { - GraphRequestHandlerTestHarness.Builder harnessBuilder = - GraphRequestHandlerTestHarness.builder() - .withGraphTimeout(Duration.ofSeconds(10)) - .withDefaultIdempotence(defaultIdempotence); - PoolBehavior node1Behavior = harnessBuilder.customBehavior(node1); - PoolBehavior node2Behavior = harnessBuilder.customBehavior(node2); - - try (GraphRequestHandlerTestHarness harness = harnessBuilder.build()) { - SpeculativeExecutionPolicy speculativeExecutionPolicy = - harness.getContext().getSpeculativeExecutionPolicy(DriverExecutionProfile.DEFAULT_NAME); - long firstExecutionDelay = 100L; - when(speculativeExecutionPolicy.nextExecution( - any(Node.class), eq(null), eq(statement), eq(1))) - .thenReturn(firstExecutionDelay); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - ContinuousGraphRequestHandler requestHandler = - new ContinuousGraphRequestHandler( - statement, - harness.getSession(), - harness.getContext(), - "test", - module, - graphSupportChecker); - CompletionStage resultSetFuture = requestHandler.handle(); - node1Behavior.verifyWrite(); - node1Behavior.setWriteSuccess(); - - // The first timeout scheduled should be the global timeout - CapturedTimeout globalTimeout = harness.nextScheduledTimeout(); - assertThat(globalTimeout.getDelay(TimeUnit.SECONDS)).isEqualTo(10); - - // Check that the first execution was scheduled but don't run it yet - CapturedTimeout speculativeExecution1 = harness.nextScheduledTimeout(); - assertThat(speculativeExecution1.getDelay(TimeUnit.MILLISECONDS)) - .isEqualTo(firstExecutionDelay); - - // Complete the request from the initial execution - node1Behavior.setResponseSuccess( - defaultDseFrameOf(singleGraphRow(GraphProtocol.GRAPH_BINARY_1_0, module))); - assertThatStage(resultSetFuture).isSuccess(); - - // Pending speculative executions should have been cancelled. However we don't check - // firstExecutionTask directly because the request handler's onResponse can sometimes be - // invoked before operationComplete (this is very unlikely in practice, but happens in our - // Travis CI build). When that happens, the speculative execution is not recorded yet when - // cancelScheduledTasks runs. - - // The fact that we missed the speculative execution is not a problem; even if it starts, it - // will eventually find out that the result is already complete and cancel itself: - speculativeExecution1.task().run(speculativeExecution1); - node2Behavior.verifyNoWrite(); - - verify(nodeMetricUpdater1) - .updateTimer( - eq(DseNodeMetric.GRAPH_MESSAGES), - eq(DriverExecutionProfile.DEFAULT_NAME), - anyLong(), - eq(TimeUnit.NANOSECONDS)); - verifyNoMoreInteractions(nodeMetricUpdater1); - } - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "idempotentGraphConfig") - public void should_cancel_pre_acquired_id_if_result_completes_after_channel_acquired( - boolean defaultIdempotence, GraphStatement statement) throws Exception { - GraphRequestHandlerTestHarness.Builder harnessBuilder = - GraphRequestHandlerTestHarness.builder().withDefaultIdempotence(defaultIdempotence); - PoolBehavior node1Behavior = harnessBuilder.customBehavior(node1); - PoolBehavior node2Behavior = harnessBuilder.customBehavior(node2); - - try (GraphRequestHandlerTestHarness harness = harnessBuilder.build()) { - SpeculativeExecutionPolicy speculativeExecutionPolicy = - harness.getContext().getSpeculativeExecutionPolicy(DriverExecutionProfile.DEFAULT_NAME); - long firstExecutionDelay = 100L; - when(speculativeExecutionPolicy.nextExecution( - any(Node.class), eq(null), eq(statement), eq(1))) - .thenReturn(firstExecutionDelay); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - CompletionStage resultSetFuture = - new ContinuousGraphRequestHandler( - statement, - harness.getSession(), - harness.getContext(), - "test", - module, - graphSupportChecker) - .handle(); - node1Behavior.verifyWrite(); - node1Behavior.setWriteSuccess(); - - CapturedTimeout speculativeExecution = harness.nextScheduledTimeout(); - assertThat(speculativeExecution.getDelay(TimeUnit.MILLISECONDS)) - .isEqualTo(firstExecutionDelay); - - // Simulate the initial execution winning after the speculative execution reserves an ID, - // but before it submits its write. - doAnswer( - invocation -> { - node1Behavior.setResponseSuccess( - defaultDseFrameOf(singleGraphRow(GraphProtocol.GRAPH_BINARY_1_0, module))); - return node2Behavior.getChannel(); - }) - .when(harness.getSession()) - .getChannel(eq(node2), anyString()); - - speculativeExecution.task().run(speculativeExecution); - - assertThatStage(resultSetFuture).isSuccess(); - node2Behavior.verifyNoWrite(); - node2Behavior.verifyPreAcquireCancelled(); - } - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "idempotentGraphConfig") - public void should_fail_if_no_nodes(boolean defaultIdempotence, GraphStatement statement) { - GraphRequestHandlerTestHarness.Builder harnessBuilder = - GraphRequestHandlerTestHarness.builder().withDefaultIdempotence(defaultIdempotence); - // No configured behaviors => will yield an empty query plan - - try (GraphRequestHandlerTestHarness harness = harnessBuilder.build()) { - SpeculativeExecutionPolicy speculativeExecutionPolicy = - harness.getContext().getSpeculativeExecutionPolicy(DriverExecutionProfile.DEFAULT_NAME); - long firstExecutionDelay = 100L; - when(speculativeExecutionPolicy.nextExecution( - any(Node.class), eq(null), eq(statement), eq(1))) - .thenReturn(firstExecutionDelay); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - CompletionStage resultSetFuture = - new ContinuousGraphRequestHandler( - statement, - harness.getSession(), - harness.getContext(), - "test", - module, - graphSupportChecker) - .handle(); - - assertThatStage(resultSetFuture) - .isFailed(error -> assertThat(error).isInstanceOf(NoNodeAvailableException.class)); - } - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "idempotentGraphConfig") - public void should_fail_if_no_more_nodes_and_initial_execution_is_last( - boolean defaultIdempotence, GraphStatement statement) throws Exception { - GraphRequestHandlerTestHarness.Builder harnessBuilder = - GraphRequestHandlerTestHarness.builder().withDefaultIdempotence(defaultIdempotence); - PoolBehavior node1Behavior = harnessBuilder.customBehavior(node1); - harnessBuilder.withResponse( - node2, - defaultDseFrameOf(new Error(ProtocolConstants.ErrorCode.IS_BOOTSTRAPPING, "mock message"))); - - try (GraphRequestHandlerTestHarness harness = harnessBuilder.build()) { - SpeculativeExecutionPolicy speculativeExecutionPolicy = - harness.getContext().getSpeculativeExecutionPolicy(DriverExecutionProfile.DEFAULT_NAME); - long firstExecutionDelay = 100L; - when(speculativeExecutionPolicy.nextExecution( - any(Node.class), eq(null), eq(statement), eq(1))) - .thenReturn(firstExecutionDelay); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - CompletionStage resultSetFuture = - new ContinuousGraphRequestHandler( - statement, - harness.getSession(), - harness.getContext(), - "test", - module, - graphSupportChecker) - .handle(); - node1Behavior.verifyWrite(); - node1Behavior.setWriteSuccess(); - // do not simulate a response from node1 yet - - // Run the next scheduled task to start the speculative execution. node2 will reply with a - // BOOTSTRAPPING error, causing a RETRY_NEXT; but the query plan is now empty so the - // speculative execution stops. - // next scheduled timeout should be the first speculative execution. Get it and run it. - CapturedTimeout speculativeExecution1 = harness.nextScheduledTimeout(); - assertThat(speculativeExecution1.getDelay(TimeUnit.MILLISECONDS)) - .isEqualTo(firstExecutionDelay); - speculativeExecution1.task().run(speculativeExecution1); - - // node1 now replies with the same response, that triggers a RETRY_NEXT - node1Behavior.setResponseSuccess( - defaultDseFrameOf( - new Error(ProtocolConstants.ErrorCode.IS_BOOTSTRAPPING, "mock message"))); - - // But again the query plan is empty so that should fail the request - assertThatStage(resultSetFuture) - .isFailed( - error -> { - assertThat(error).isInstanceOf(AllNodesFailedException.class); - Map> nodeErrors = - ((AllNodesFailedException) error).getAllErrors(); - assertThat(nodeErrors).containsOnlyKeys(node1, node2); - assertThat(nodeErrors.get(node1).get(0)).isInstanceOf(BootstrappingException.class); - assertThat(nodeErrors.get(node2).get(0)).isInstanceOf(BootstrappingException.class); - }); - } - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "idempotentGraphConfig") - public void should_fail_if_no_more_nodes_and_speculative_execution_is_last( - boolean defaultIdempotence, GraphStatement statement) throws Exception { - GraphRequestHandlerTestHarness.Builder harnessBuilder = - GraphRequestHandlerTestHarness.builder().withDefaultIdempotence(defaultIdempotence); - PoolBehavior node1Behavior = harnessBuilder.customBehavior(node1); - PoolBehavior node2Behavior = harnessBuilder.customBehavior(node2); - - try (GraphRequestHandlerTestHarness harness = harnessBuilder.build()) { - SpeculativeExecutionPolicy speculativeExecutionPolicy = - harness.getContext().getSpeculativeExecutionPolicy(DriverExecutionProfile.DEFAULT_NAME); - long firstExecutionDelay = 100L; - when(speculativeExecutionPolicy.nextExecution( - any(Node.class), eq(null), eq(statement), eq(1))) - .thenReturn(firstExecutionDelay); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - CompletionStage resultSetFuture = - new ContinuousGraphRequestHandler( - statement, - harness.getSession(), - harness.getContext(), - "test", - module, - graphSupportChecker) - .handle(); - node1Behavior.verifyWrite(); - node1Behavior.setWriteSuccess(); - // do not simulate a response from node1 yet - - // next scheduled timeout should be the first speculative execution. Get it and run it. - CapturedTimeout speculativeExecution1 = harness.nextScheduledTimeout(); - assertThat(speculativeExecution1.getDelay(TimeUnit.MILLISECONDS)) - .isEqualTo(firstExecutionDelay); - speculativeExecution1.task().run(speculativeExecution1); - - // node1 now replies with a BOOTSTRAPPING error that triggers a RETRY_NEXT - // but the query plan is empty so the initial execution stops - node1Behavior.setResponseSuccess( - defaultDseFrameOf( - new Error(ProtocolConstants.ErrorCode.IS_BOOTSTRAPPING, "mock message"))); - - // Same thing with node2, so the speculative execution should reach the end of the query plan - // and fail the request - node2Behavior.setResponseSuccess( - defaultDseFrameOf( - new Error(ProtocolConstants.ErrorCode.IS_BOOTSTRAPPING, "mock message"))); - - assertThatStage(resultSetFuture) - .isFailed( - error -> { - assertThat(error).isInstanceOf(AllNodesFailedException.class); - Map> nodeErrors = - ((AllNodesFailedException) error).getAllErrors(); - assertThat(nodeErrors).containsOnlyKeys(node1, node2); - assertThat(nodeErrors.get(node1).get(0)).isInstanceOf(BootstrappingException.class); - assertThat(nodeErrors.get(node2).get(0)).isInstanceOf(BootstrappingException.class); - }); - } - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "idempotentGraphConfig") - public void should_retry_in_speculative_executions( - boolean defaultIdempotence, GraphStatement statement) throws Exception { - GraphRequestHandlerTestHarness.Builder harnessBuilder = - GraphRequestHandlerTestHarness.builder().withDefaultIdempotence(defaultIdempotence); - PoolBehavior node1Behavior = harnessBuilder.customBehavior(node1); - PoolBehavior node2Behavior = harnessBuilder.customBehavior(node2); - PoolBehavior node3Behavior = harnessBuilder.customBehavior(node3); - - try (GraphRequestHandlerTestHarness harness = harnessBuilder.build()) { - SpeculativeExecutionPolicy speculativeExecutionPolicy = - harness.getContext().getSpeculativeExecutionPolicy(DriverExecutionProfile.DEFAULT_NAME); - long firstExecutionDelay = 100L; - when(speculativeExecutionPolicy.nextExecution( - any(Node.class), eq(null), eq(statement), eq(1))) - .thenReturn(firstExecutionDelay); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - CompletionStage resultSetFuture = - new ContinuousGraphRequestHandler( - statement, - harness.getSession(), - harness.getContext(), - "test", - module, - graphSupportChecker) - .handle(); - node1Behavior.verifyWrite(); - node1Behavior.setWriteSuccess(); - // do not simulate a response from node1. The request will stay hanging for the rest of this - // test - - // next scheduled timeout should be the first speculative execution. Get it and run it. - CapturedTimeout speculativeExecution1 = harness.nextScheduledTimeout(); - assertThat(speculativeExecution1.getDelay(TimeUnit.MILLISECONDS)) - .isEqualTo(firstExecutionDelay); - speculativeExecution1.task().run(speculativeExecution1); - - node2Behavior.verifyWrite(); - node2Behavior.setWriteSuccess(); - - // node2 replies with a response that triggers a RETRY_NEXT - node2Behavior.setResponseSuccess( - defaultDseFrameOf( - new Error(ProtocolConstants.ErrorCode.IS_BOOTSTRAPPING, "mock message"))); - - node3Behavior.setResponseSuccess( - defaultDseFrameOf(singleGraphRow(GraphProtocol.GRAPH_BINARY_1_0, module))); - - // The second execution should move to node3 and complete the request - assertThatStage(resultSetFuture).isSuccess(); - - // The request to node1 was still in flight, it should have been cancelled - node1Behavior.verifyCancellation(); - } - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "idempotentGraphConfig") - public void should_stop_retrying_other_executions_if_result_complete( - boolean defaultIdempotence, GraphStatement statement) throws Exception { - GraphRequestHandlerTestHarness.Builder harnessBuilder = - GraphRequestHandlerTestHarness.builder().withDefaultIdempotence(defaultIdempotence); - PoolBehavior node1Behavior = harnessBuilder.customBehavior(node1); - PoolBehavior node2Behavior = harnessBuilder.customBehavior(node2); - PoolBehavior node3Behavior = harnessBuilder.customBehavior(node3); - - try (GraphRequestHandlerTestHarness harness = harnessBuilder.build()) { - SpeculativeExecutionPolicy speculativeExecutionPolicy = - harness.getContext().getSpeculativeExecutionPolicy(DriverExecutionProfile.DEFAULT_NAME); - long firstExecutionDelay = 100L; - when(speculativeExecutionPolicy.nextExecution( - any(Node.class), eq(null), eq(statement), eq(1))) - .thenReturn(firstExecutionDelay); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - CompletionStage resultSetFuture = - new ContinuousGraphRequestHandler( - statement, - harness.getSession(), - harness.getContext(), - "test", - module, - graphSupportChecker) - .handle(); - node1Behavior.verifyWrite(); - node1Behavior.setWriteSuccess(); - - // next scheduled timeout should be the first speculative execution. Get it and run it. - CapturedTimeout speculativeExecution1 = harness.nextScheduledTimeout(); - assertThat(speculativeExecution1.getDelay(TimeUnit.MILLISECONDS)) - .isEqualTo(firstExecutionDelay); - speculativeExecution1.task().run(speculativeExecution1); - - node2Behavior.verifyWrite(); - node2Behavior.setWriteSuccess(); - - // Complete the request from the initial execution - node1Behavior.setResponseSuccess( - defaultDseFrameOf(singleGraphRow(GraphProtocol.GRAPH_BINARY_1_0, module))); - assertThatStage(resultSetFuture).isSuccess(); - - // node2 replies with a response that would trigger a RETRY_NEXT if the request was still - // running - node2Behavior.setResponseSuccess( - defaultDseFrameOf( - new Error(ProtocolConstants.ErrorCode.IS_BOOTSTRAPPING, "mock message"))); - - // The speculative execution should not move to node3 because it is stopped - node3Behavior.verifyNoWrite(); - } - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandlerTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandlerTest.java deleted file mode 100644 index b374539f12e..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/ContinuousGraphRequestHandlerTest.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.createGraphBinaryModule; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.defaultDseFrameOf; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.tenGraphRows; -import static com.datastax.oss.driver.Assertions.assertThat; -import static com.datastax.oss.driver.Assertions.assertThatStage; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.DseTestDataProviders; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; -import com.datastax.dse.driver.internal.core.graph.binary.GraphBinaryModule; -import com.datastax.oss.driver.api.core.DriverTimeoutException; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import com.datastax.oss.driver.internal.core.cql.PoolBehavior; -import com.datastax.oss.driver.internal.core.cql.RequestHandlerTestHarness; -import com.datastax.oss.driver.internal.core.metadata.DefaultNode; -import com.datastax.oss.driver.internal.core.metrics.NodeMetricUpdater; -import com.datastax.oss.driver.internal.core.util.concurrent.CapturingTimer.CapturedTimeout; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.io.IOException; -import java.time.Duration; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(DataProviderRunner.class) -public class ContinuousGraphRequestHandlerTest { - - @Mock DefaultDriverContext mockContext; - @Mock DefaultNode node; - @Mock NodeMetricUpdater nodeMetricUpdater1; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - when(node.getMetricUpdater()).thenReturn(nodeMetricUpdater1); - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "supportedGraphProtocols") - public void should_return_paged_results(GraphProtocol graphProtocol) throws IOException { - String profileName = "test-graph"; - when(nodeMetricUpdater1.isEnabled(DseNodeMetric.GRAPH_MESSAGES, profileName)).thenReturn(true); - - GraphBinaryModule module = createGraphBinaryModule(mockContext); - - GraphRequestHandlerTestHarness.Builder builder = - GraphRequestHandlerTestHarness.builder().withGraphProtocolForTestConfig(graphProtocol); - PoolBehavior node1Behavior = builder.customBehavior(node); - - try (RequestHandlerTestHarness harness = builder.build()) { - - GraphStatement graphStatement = - ScriptGraphStatement.newInstance("mockQuery").setExecutionProfileName(profileName); - - ContinuousGraphRequestHandler handler = - new ContinuousGraphRequestHandler( - graphStatement, - harness.getSession(), - harness.getContext(), - "test", - module, - new GraphSupportChecker()); - - // send the initial request - CompletionStage page1Future = handler.handle(); - - node1Behavior.setResponseSuccess( - defaultDseFrameOf(tenGraphRows(graphProtocol, module, 1, false))); - - assertThatStage(page1Future) - .isSuccess( - page1 -> { - assertThat(page1.hasMorePages()).isTrue(); - assertThat(page1.currentPage()).hasSize(10).allMatch(GraphNode::isVertex); - ExecutionInfo executionInfo = page1.getRequestExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node); - assertThat(executionInfo.getErrors()).isEmpty(); - assertThat(executionInfo.getIncomingPayload()).isEmpty(); - assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(executionInfo.getWarnings()).isEmpty(); - }); - - AsyncGraphResultSet page1 = CompletableFutures.getCompleted(page1Future); - CompletionStage page2Future = page1.fetchNextPage(); - - node1Behavior.setResponseSuccess( - defaultDseFrameOf(tenGraphRows(graphProtocol, module, 2, true))); - - assertThatStage(page2Future) - .isSuccess( - page2 -> { - assertThat(page2.hasMorePages()).isFalse(); - assertThat(page2.currentPage()).hasSize(10).allMatch(GraphNode::isVertex); - ExecutionInfo executionInfo = page2.getRequestExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node); - assertThat(executionInfo.getErrors()).isEmpty(); - assertThat(executionInfo.getIncomingPayload()).isEmpty(); - assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(executionInfo.getWarnings()).isEmpty(); - }); - - validateMetrics(profileName, harness); - } - } - - @Test - public void should_honor_default_timeout() throws Exception { - // given - GraphBinaryModule binaryModule = createGraphBinaryModule(mockContext); - Duration defaultTimeout = Duration.ofSeconds(1); - - RequestHandlerTestHarness.Builder builder = - GraphRequestHandlerTestHarness.builder().withGraphTimeout(defaultTimeout); - PoolBehavior node1Behavior = builder.customBehavior(node); - - try (RequestHandlerTestHarness harness = builder.build()) { - - DriverExecutionProfile profile = harness.getContext().getConfig().getDefaultProfile(); - when(profile.isDefined(DseDriverOption.GRAPH_SUB_PROTOCOL)).thenReturn(true); - when(profile.getString(DseDriverOption.GRAPH_SUB_PROTOCOL)) - .thenReturn(GraphProtocol.GRAPH_BINARY_1_0.toInternalCode()); - - GraphStatement graphStatement = ScriptGraphStatement.newInstance("mockQuery"); - - // when - ContinuousGraphRequestHandler handler = - new ContinuousGraphRequestHandler( - graphStatement, - harness.getSession(), - harness.getContext(), - "test", - binaryModule, - new GraphSupportChecker()); - - // send the initial request - CompletionStage page1Future = handler.handle(); - - // acknowledge the write, will set the global timeout - node1Behavior.verifyWrite(); - node1Behavior.setWriteSuccess(); - - CapturedTimeout globalTimeout = harness.nextScheduledTimeout(); - assertThat(globalTimeout.getDelay(TimeUnit.NANOSECONDS)).isEqualTo(defaultTimeout.toNanos()); - - // will trigger the global timeout and complete it exceptionally - globalTimeout.task().run(globalTimeout); - assertThat(page1Future.toCompletableFuture()).isCompletedExceptionally(); - - assertThatThrownBy(() -> page1Future.toCompletableFuture().get()) - .hasRootCauseExactlyInstanceOf(DriverTimeoutException.class) - .hasMessageContaining("Query timed out after " + defaultTimeout); - } - } - - @Test - public void should_honor_statement_timeout() throws Exception { - // given - GraphBinaryModule binaryModule = createGraphBinaryModule(mockContext); - Duration defaultTimeout = Duration.ofSeconds(1); - Duration statementTimeout = Duration.ofSeconds(2); - - RequestHandlerTestHarness.Builder builder = - GraphRequestHandlerTestHarness.builder().withGraphTimeout(defaultTimeout); - PoolBehavior node1Behavior = builder.customBehavior(node); - - try (RequestHandlerTestHarness harness = builder.build()) { - - DriverExecutionProfile profile = harness.getContext().getConfig().getDefaultProfile(); - when(profile.isDefined(DseDriverOption.GRAPH_SUB_PROTOCOL)).thenReturn(true); - when(profile.getString(DseDriverOption.GRAPH_SUB_PROTOCOL)) - .thenReturn(GraphProtocol.GRAPH_BINARY_1_0.toInternalCode()); - - GraphStatement graphStatement = - ScriptGraphStatement.newInstance("mockQuery").setTimeout(statementTimeout); - - // when - ContinuousGraphRequestHandler handler = - new ContinuousGraphRequestHandler( - graphStatement, - harness.getSession(), - harness.getContext(), - "test", - binaryModule, - new GraphSupportChecker()); - - // send the initial request - CompletionStage page1Future = handler.handle(); - - // acknowledge the write, will set the global timeout - node1Behavior.verifyWrite(); - node1Behavior.setWriteSuccess(); - - CapturedTimeout globalTimeout = harness.nextScheduledTimeout(); - assertThat(globalTimeout.getDelay(TimeUnit.NANOSECONDS)) - .isEqualTo(statementTimeout.toNanos()); - - // will trigger the global timeout and complete it exceptionally - globalTimeout.task().run(globalTimeout); - assertThat(page1Future.toCompletableFuture()).isCompletedExceptionally(); - - assertThatThrownBy(() -> page1Future.toCompletableFuture().get()) - .hasRootCauseExactlyInstanceOf(DriverTimeoutException.class) - .hasMessageContaining("Query timed out after " + statementTimeout); - } - } - - private void validateMetrics(String profileName, RequestHandlerTestHarness harness) { - // GRAPH_MESSAGES metrics update is invoked only for the first page - verify(nodeMetricUpdater1, times(1)) - .updateTimer( - eq(DseNodeMetric.GRAPH_MESSAGES), eq(profileName), anyLong(), eq(TimeUnit.NANOSECONDS)); - verifyNoMoreInteractions(nodeMetricUpdater1); - - verify(harness.getSession().getMetricUpdater()) - .updateTimer( - eq(DseSessionMetric.GRAPH_REQUESTS), eq(null), anyLong(), eq(TimeUnit.NANOSECONDS)); - verifyNoMoreInteractions(harness.getSession().getMetricUpdater()); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphExecutionInfoConverterTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphExecutionInfoConverterTest.java deleted file mode 100644 index 1814b12aa4e..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphExecutionInfoConverterTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.servererrors.ServerError; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import com.datastax.oss.protocol.internal.util.Bytes; -import java.nio.ByteBuffer; -import java.util.AbstractMap.SimpleEntry; -import java.util.Collections; -import java.util.List; -import java.util.Map.Entry; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.Strict.class) -@SuppressWarnings("deprecation") -public class GraphExecutionInfoConverterTest { - - @Mock GraphStatement request; - @Mock Node node; - - private List> errors; - private List warnings; - private ImmutableMap payload; - - @Before - public void setUp() { - errors = - Collections.singletonList( - new SimpleEntry<>(node, new ServerError(node, "this is a server error"))); - warnings = Collections.singletonList("this is a warning"); - payload = ImmutableMap.of("key", Bytes.fromHexString("0xcafebabe")); - } - - @Test - public void should_convert_to_graph_execution_info() { - - // given - ExecutionInfo executionInfo = mock(ExecutionInfo.class); - when(executionInfo.getRequest()).thenReturn(request); - when(executionInfo.getCoordinator()).thenReturn(node); - when(executionInfo.getSpeculativeExecutionCount()).thenReturn(42); - when(executionInfo.getSuccessfulExecutionIndex()).thenReturn(10); - when(executionInfo.getErrors()).thenReturn(errors); - when(executionInfo.getWarnings()).thenReturn(warnings); - when(executionInfo.getIncomingPayload()).thenReturn(payload); - - // when - com.datastax.dse.driver.api.core.graph.GraphExecutionInfo graphExecutionInfo = - GraphExecutionInfoConverter.convert(executionInfo); - - // then - assertThat(graphExecutionInfo.getStatement()).isSameAs(request); - assertThat(graphExecutionInfo.getCoordinator()).isSameAs(node); - assertThat(graphExecutionInfo.getSpeculativeExecutionCount()).isEqualTo(42); - assertThat(graphExecutionInfo.getSuccessfulExecutionIndex()).isEqualTo(10); - assertThat(graphExecutionInfo.getErrors()).isEqualTo(errors); - assertThat(graphExecutionInfo.getWarnings()).isEqualTo(warnings); - assertThat(graphExecutionInfo.getIncomingPayload()).isEqualTo(payload); - } - - @Test - public void should_convert_from_graph_execution_info() { - - // given - com.datastax.dse.driver.api.core.graph.GraphExecutionInfo graphExecutionInfo = - mock(com.datastax.dse.driver.api.core.graph.GraphExecutionInfo.class); - when(graphExecutionInfo.getStatement()).thenAnswer(args -> request); - when(graphExecutionInfo.getCoordinator()).thenReturn(node); - when(graphExecutionInfo.getSpeculativeExecutionCount()).thenReturn(42); - when(graphExecutionInfo.getSuccessfulExecutionIndex()).thenReturn(10); - when(graphExecutionInfo.getErrors()).thenReturn(errors); - when(graphExecutionInfo.getWarnings()).thenReturn(warnings); - when(graphExecutionInfo.getIncomingPayload()).thenReturn(payload); - - // when - ExecutionInfo executionInfo = GraphExecutionInfoConverter.convert(graphExecutionInfo); - - // then - assertThat(executionInfo.getRequest()).isSameAs(request); - assertThatThrownBy(executionInfo::getStatement).isInstanceOf(ClassCastException.class); - assertThat(executionInfo.getCoordinator()).isSameAs(node); - assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(42); - assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(10); - assertThat(executionInfo.getErrors()).isEqualTo(errors); - assertThat(executionInfo.getWarnings()).isEqualTo(warnings); - assertThat(executionInfo.getIncomingPayload()).isEqualTo(payload); - assertThat(executionInfo.getPagingState()).isNull(); - assertThat(executionInfo.isSchemaInAgreement()).isTrue(); - assertThat(executionInfo.getQueryTraceAsync()).isCompletedExceptionally(); - assertThatThrownBy(executionInfo::getQueryTrace) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Tracing was disabled for this request"); - assertThat(executionInfo.getResponseSizeInBytes()).isEqualTo(-1L); - assertThat(executionInfo.getCompressedResponseSizeInBytes()).isEqualTo(-1L); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphNodeTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphNodeTest.java deleted file mode 100644 index d7ded441e70..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphNodeTest.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static com.datastax.dse.driver.internal.core.graph.GraphProtocol.GRAPHSON_1_0; -import static com.datastax.dse.driver.internal.core.graph.GraphProtocol.GRAPHSON_2_0; -import static com.datastax.dse.driver.internal.core.graph.GraphProtocol.GRAPH_BINARY_1_0; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.internal.core.graph.binary.GraphBinaryModule; -import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableSet; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser; -import org.apache.tinkerpop.gremlin.process.traversal.Traverser; -import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyPath; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; -import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry; -import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge; -import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedProperty; -import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex; -import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(DataProviderRunner.class) -public class GraphNodeTest { - - private GraphBinaryModule graphBinaryModule; - - @Before - public void setup() { - DefaultDriverContext dseDriverContext = mock(DefaultDriverContext.class); - when(dseDriverContext.getCodecRegistry()).thenReturn(CodecRegistry.DEFAULT); - when(dseDriverContext.getProtocolVersion()).thenReturn(DseProtocolVersion.DSE_V2); - - TypeSerializerRegistry registry = - GraphBinaryModule.createDseTypeSerializerRegistry(dseDriverContext); - graphBinaryModule = - new GraphBinaryModule(new GraphBinaryReader(registry), new GraphBinaryWriter(registry)); - } - - @Test - public void should_not_support_set_for_graphson_2_0() throws IOException { - // when - GraphNode graphNode = serdeAndCreateGraphNode(ImmutableSet.of("value"), GRAPHSON_2_0); - - // then - assertThat(graphNode.isSet()).isFalse(); - } - - @Test - public void should_throw_for_set_for_graphson_1_0() throws IOException { - // when - GraphNode graphNode = serdeAndCreateGraphNode(ImmutableSet.of("value"), GRAPHSON_1_0); - - // then - assertThat(graphNode.isSet()).isFalse(); - assertThatThrownBy(graphNode::asSet).isExactlyInstanceOf(UnsupportedOperationException.class); - } - - @Test - @UseDataProvider(value = "allGraphProtocols") - public void should_create_graph_node_for_list(GraphProtocol graphVersion) throws IOException { - // when - GraphNode graphNode = serdeAndCreateGraphNode(ImmutableList.of("value"), graphVersion); - - // then - assertThat(graphNode.isList()).isTrue(); - List result = graphNode.asList(); - assertThat(result).isEqualTo(ImmutableList.of("value")); - } - - @Test - @UseDataProvider("allGraphProtocols") - public void should_create_graph_node_for_map(GraphProtocol graphProtocol) throws IOException { - // when - GraphNode graphNode = serdeAndCreateGraphNode(ImmutableMap.of("value", 1234), graphProtocol); - - // then - assertThat(graphNode.isMap()).isTrue(); - Map result = graphNode.asMap(); - assertThat(result).isEqualTo(ImmutableMap.of("value", 1234)); - } - - @Test - @UseDataProvider("graphson1_0and2_0") - public void should_create_graph_node_for_map_for_non_string_key(GraphProtocol graphProtocol) - throws IOException { - // when - GraphNode graphNode = serdeAndCreateGraphNode(ImmutableMap.of(12, 1234), graphProtocol); - - // then - assertThat(graphNode.isMap()).isTrue(); - Map result = graphNode.asMap(); - assertThat(result).isEqualTo(ImmutableMap.of("12", 1234)); - } - - @Test - @UseDataProvider(value = "allGraphProtocols") - public void should_calculate_size_of_collection_types(GraphProtocol graphProtocol) - throws IOException { - // when - GraphNode mapNode = serdeAndCreateGraphNode(ImmutableMap.of(12, 1234), graphProtocol); - GraphNode setNode = serdeAndCreateGraphNode(ImmutableSet.of(12, 1234), graphProtocol); - GraphNode listNode = serdeAndCreateGraphNode(ImmutableList.of(12, 1234, 99999), graphProtocol); - - // then - assertThat(mapNode.size()).isEqualTo(1); - assertThat(setNode.size()).isEqualTo(2); - assertThat(listNode.size()).isEqualTo(3); - } - - @Test - @UseDataProvider(value = "allGraphProtocols") - public void should_return_is_value_only_for_scalar_value(GraphProtocol graphProtocol) - throws IOException { - // when - GraphNode mapNode = serdeAndCreateGraphNode(ImmutableMap.of(12, 1234), graphProtocol); - GraphNode setNode = serdeAndCreateGraphNode(ImmutableMap.of(12, 1234), graphProtocol); - GraphNode listNode = serdeAndCreateGraphNode(ImmutableMap.of(12, 1234), graphProtocol); - GraphNode vertexNode = - serdeAndCreateGraphNode(new DetachedVertex("a", "l", null), graphProtocol); - GraphNode edgeNode = - serdeAndCreateGraphNode( - new DetachedEdge("a", "l", Collections.emptyMap(), "v1", "l1", "v2", "l2"), - graphProtocol); - GraphNode pathNode = serdeAndCreateGraphNode(EmptyPath.instance(), graphProtocol); - GraphNode propertyNode = serdeAndCreateGraphNode(new DetachedProperty<>("a", 1), graphProtocol); - GraphNode vertexPropertyNode = - serdeAndCreateGraphNode( - new DetachedVertexProperty<>("id", "l", "v", null, new DetachedVertex("a", "l", null)), - graphProtocol); - GraphNode scalarValueNode = serdeAndCreateGraphNode(true, graphProtocol); - - // then - assertThat(mapNode.isValue()).isFalse(); - assertThat(setNode.isValue()).isFalse(); - assertThat(listNode.isValue()).isFalse(); - assertThat(vertexNode.isValue()).isFalse(); - assertThat(edgeNode.isValue()).isFalse(); - assertThat(pathNode.isValue()).isFalse(); - assertThat(propertyNode.isValue()).isFalse(); - assertThat(vertexPropertyNode.isValue()).isFalse(); - assertThat(scalarValueNode.isValue()).isTrue(); - } - - @Test - @UseDataProvider("objectGraphNodeProtocols") - public void should_check_if_node_is_property_not_map(GraphProtocol graphProtocol) - throws IOException { - // when - GraphNode propertyNode = serdeAndCreateGraphNode(new DetachedProperty<>("a", 1), graphProtocol); - - // then - assertThat(propertyNode.isProperty()).isTrue(); - assertThat(propertyNode.isMap()).isFalse(); - assertThat(propertyNode.asProperty()).isNotNull(); - } - - @Test - public void should_check_if_node_is_property_or_map_for_1_0() throws IOException { - // when - GraphNode propertyNode = serdeAndCreateGraphNode(new DetachedProperty<>("a", 1), GRAPHSON_1_0); - - // then - assertThat(propertyNode.isProperty()).isTrue(); - assertThat(propertyNode.isMap()).isTrue(); - assertThat(propertyNode.asProperty()).isNotNull(); - } - - @Test - @UseDataProvider("allGraphProtocols") - public void should_check_if_node_is_vertex_property(GraphProtocol graphProtocol) - throws IOException { - // when - GraphNode vertexPropertyNode = - serdeAndCreateGraphNode( - new DetachedVertexProperty<>("id", "l", "v", null, new DetachedVertex("a", "l", null)), - graphProtocol); - - // then - assertThat(vertexPropertyNode.isVertexProperty()).isTrue(); - assertThat(vertexPropertyNode.isVertexProperty()).isNotNull(); - } - - @Test - public void should_check_if_node_is_path_for_graphson_1_0() throws IOException { - // when - GraphNode pathNode = serdeAndCreateGraphNode(EmptyPath.instance(), GRAPHSON_1_0); - - // then - assertThat(pathNode.isPath()).isFalse(); - assertThatThrownBy(pathNode::asPath).isExactlyInstanceOf(UnsupportedOperationException.class); - } - - @Test - @UseDataProvider("objectGraphNodeProtocols") - public void should_check_if_node_is_path(GraphProtocol graphProtocol) throws IOException { - // when - GraphNode pathNode = serdeAndCreateGraphNode(EmptyPath.instance(), graphProtocol); - - // then - assertThat(pathNode.isPath()).isTrue(); - assertThat(pathNode.asPath()).isNotNull(); - } - - @Test - @UseDataProvider("allGraphProtocols") - public void should_check_if_node_is_vertex(GraphProtocol graphProtocol) throws IOException { - // when - GraphNode vertexNode = - serdeAndCreateGraphNode(new DetachedVertex("a", "l", null), graphProtocol); - - // then - assertThat(vertexNode.isVertex()).isTrue(); - assertThat(vertexNode.asVertex()).isNotNull(); - } - - @Test - @UseDataProvider("allGraphProtocols") - public void should_check_if_node_is_edge(GraphProtocol graphProtocol) throws IOException { - // when - GraphNode edgeNode = - serdeAndCreateGraphNode( - new DetachedEdge("a", "l", Collections.emptyMap(), "v1", "l1", "v2", "l2"), - graphProtocol); - - // then - assertThat(edgeNode.isEdge()).isTrue(); - assertThat(edgeNode.asEdge()).isNotNull(); - } - - private GraphNode serdeAndCreateGraphNode(Object inputValue, GraphProtocol graphProtocol) - throws IOException { - if (graphProtocol.isGraphBinary()) { - Buffer tinkerBuf = graphBinaryModule.serialize(new DefaultRemoteTraverser<>(inputValue, 0L)); - ByteBuffer nioBuffer = tinkerBuf.nioBuffer(); - tinkerBuf.release(); - return new ObjectGraphNode( - GraphConversions.createGraphBinaryGraphNode( - ImmutableList.of(nioBuffer), graphBinaryModule) - .as(Traverser.class) - .get()); - } else { - return GraphSONUtils.createGraphNode( - ImmutableList.of(GraphSONUtils.serializeToByteBuffer(inputValue, graphProtocol)), - graphProtocol); - } - } - - @DataProvider - public static Object[][] allGraphProtocols() { - return new Object[][] {{GRAPHSON_1_0}, {GRAPHSON_2_0}, {GRAPH_BINARY_1_0}}; - } - - @DataProvider - public static Object[][] graphson1_0and2_0() { - return new Object[][] {{GRAPHSON_1_0}, {GRAPHSON_2_0}}; - } - - @DataProvider - public static Object[][] objectGraphNodeProtocols() { - return new Object[][] {{GRAPHSON_2_0}, {GRAPH_BINARY_1_0}}; - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandlerTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandlerTest.java deleted file mode 100644 index 852991b9607..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandlerTest.java +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static com.datastax.dse.driver.internal.core.graph.GraphProtocol.GRAPHSON_1_0; -import static com.datastax.dse.driver.internal.core.graph.GraphProtocol.GRAPHSON_2_0; -import static com.datastax.dse.driver.internal.core.graph.GraphProtocol.GRAPH_BINARY_1_0; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.createGraphBinaryModule; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.defaultDseFrameOf; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.serialize; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.singleGraphRow; -import static com.datastax.oss.driver.api.core.type.codec.TypeCodecs.BIGINT; -import static com.datastax.oss.driver.api.core.type.codec.TypeCodecs.TEXT; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.matches; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.DseTestDataProviders; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.graph.BatchGraphStatement; -import com.datastax.dse.driver.api.core.graph.DseGraph; -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.GraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; -import com.datastax.dse.driver.internal.core.graph.binary.GraphBinaryModule; -import com.datastax.dse.protocol.internal.request.RawBytesQuery; -import com.datastax.dse.protocol.internal.request.query.DseQueryOptions; -import com.datastax.oss.driver.api.core.DefaultConsistencyLevel; -import com.datastax.oss.driver.api.core.Version; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.tracker.RequestTracker; -import com.datastax.oss.driver.api.core.uuid.Uuids; -import com.datastax.oss.driver.internal.core.cql.Conversions; -import com.datastax.oss.driver.internal.core.cql.PoolBehavior; -import com.datastax.oss.driver.internal.core.metadata.DefaultNode; -import com.datastax.oss.driver.internal.core.metrics.NodeMetricUpdater; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import com.datastax.oss.protocol.internal.Message; -import com.datastax.oss.protocol.internal.request.Query; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.io.IOException; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.regex.Pattern; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -@RunWith(DataProviderRunner.class) -public class GraphRequestHandlerTest { - - private static final Pattern LOG_PREFIX_PER_REQUEST = Pattern.compile("test-graph\\|\\d+"); - - @Mock DefaultNode node; - - @Mock protected NodeMetricUpdater nodeMetricUpdater1; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - when(node.getMetricUpdater()).thenReturn(nodeMetricUpdater1); - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "supportedGraphProtocols") - public void should_create_query_message_from_script_statement(GraphProtocol graphProtocol) - throws IOException { - // initialization - GraphRequestHandlerTestHarness harness = GraphRequestHandlerTestHarness.builder().build(); - ScriptGraphStatement graphStatement = - ScriptGraphStatement.newInstance("mockQuery") - .setQueryParam("p1", 1L) - .setQueryParam("p2", Uuids.random()); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - // when - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(graphStatement, harness.getContext()); - - Message m = - GraphConversions.createMessageFromGraphStatement( - graphStatement, graphProtocol, executionProfile, harness.getContext(), module); - - // checks - assertThat(m).isInstanceOf(Query.class); - Query q = ((Query) m); - assertThat(q.query).isEqualTo("mockQuery"); - assertThat(q.options.positionalValues) - .containsExactly(serialize(graphStatement.getQueryParams(), graphProtocol, module)); - assertThat(q.options.namedValues).isEmpty(); - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "supportedGraphProtocols") - public void should_create_query_message_from_fluent_statement(GraphProtocol graphProtocol) - throws IOException { - // initialization - GraphRequestHandlerTestHarness harness = GraphRequestHandlerTestHarness.builder().build(); - GraphTraversal traversalTest = - DseGraph.g.V().has("person", "name", "marko").has("p1", 1L).has("p2", Uuids.random()); - GraphStatement graphStatement = FluentGraphStatement.newInstance(traversalTest); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - // when - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(graphStatement, harness.getContext()); - - Message m = - GraphConversions.createMessageFromGraphStatement( - graphStatement, graphProtocol, executionProfile, harness.getContext(), module); - - Map createdCustomPayload = - GraphConversions.createCustomPayload( - graphStatement, graphProtocol, executionProfile, harness.getContext(), module); - - // checks - assertThat(m).isInstanceOf(RawBytesQuery.class); - testQueryRequestAndPayloadContents( - ((RawBytesQuery) m), - createdCustomPayload, - GraphConversions.bytecodeToSerialize(graphStatement), - graphProtocol, - module); - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "supportedGraphProtocols") - public void should_create_query_message_from_batch_statement(GraphProtocol graphProtocol) - throws IOException { - // initialization - GraphRequestHandlerTestHarness harness = GraphRequestHandlerTestHarness.builder().build(); - @SuppressWarnings("rawtypes") - List traversalsTest = - ImmutableList.of( - // randomly testing some complex data types. Complete suite of data types test is in - // GraphDataTypesTest - DseGraph.g - .addV("person") - .property("p1", 2.3f) - .property("p2", LocalDateTime.now(ZoneOffset.UTC)), - DseGraph.g - .addV("software") - .property("p3", new BigInteger("123456789123456789123456789123456789")) - .property("p4", ImmutableList.of(Point.fromCoordinates(30.4, 25.63746284)))); - GraphStatement graphStatement = - BatchGraphStatement.builder().addTraversals(traversalsTest).build(); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - // when - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(graphStatement, harness.getContext()); - - Message m = - GraphConversions.createMessageFromGraphStatement( - graphStatement, graphProtocol, executionProfile, harness.getContext(), module); - - Map createdCustomPayload = - GraphConversions.createCustomPayload( - graphStatement, graphProtocol, executionProfile, harness.getContext(), module); - - // checks - assertThat(m).isInstanceOf(RawBytesQuery.class); - testQueryRequestAndPayloadContents( - ((RawBytesQuery) m), - createdCustomPayload, - GraphConversions.bytecodeToSerialize(graphStatement), - graphProtocol, - module); - } - - private void testQueryRequestAndPayloadContents( - RawBytesQuery q, - Map customPayload, - Object traversalTest, - GraphProtocol graphProtocol, - GraphBinaryModule module) - throws IOException { - if (graphProtocol.isGraphBinary()) { - assertThat(q.query).isEqualTo(GraphConversions.EMPTY_STRING_QUERY); - assertThat(customPayload).containsKey(GraphConversions.GRAPH_BINARY_QUERY_OPTION_KEY); - ByteBuffer encodedQuery = customPayload.get(GraphConversions.GRAPH_BINARY_QUERY_OPTION_KEY); - assertThat(encodedQuery).isNotNull(); - assertThat(encodedQuery).isEqualTo(serialize(traversalTest, graphProtocol, module)); - } else { - assertThat(q.query).isEqualTo(serialize(traversalTest, graphProtocol, module).array()); - assertThat(customPayload).doesNotContainKey(GraphConversions.GRAPH_BINARY_QUERY_OPTION_KEY); - } - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "supportedGraphProtocols") - public void should_set_correct_query_options_from_graph_statement(GraphProtocol subProtocol) - throws IOException { - // initialization - GraphRequestHandlerTestHarness harness = GraphRequestHandlerTestHarness.builder().build(); - GraphStatement graphStatement = - ScriptGraphStatement.newInstance("mockQuery").setQueryParam("name", "value"); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - // when - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(graphStatement, harness.getContext()); - Message m = - GraphConversions.createMessageFromGraphStatement( - graphStatement, subProtocol, executionProfile, harness.getContext(), module); - - // checks - Query query = ((Query) m); - DseQueryOptions options = ((DseQueryOptions) query.options); - assertThat(options.consistency) - .isEqualTo( - DefaultConsistencyLevel.valueOf( - executionProfile.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .getProtocolCode()); - // set by the mock timestamp generator - assertThat(options.defaultTimestamp).isEqualTo(-9223372036854775808L); - assertThat(options.positionalValues) - .isEqualTo( - ImmutableList.of(serialize(ImmutableMap.of("name", "value"), subProtocol, module))); - - m = - GraphConversions.createMessageFromGraphStatement( - graphStatement.setTimestamp(2L), - subProtocol, - executionProfile, - harness.getContext(), - module); - query = ((Query) m); - options = ((DseQueryOptions) query.options); - assertThat(options.defaultTimestamp).isEqualTo(2L); - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "supportedGraphProtocols") - public void should_create_payload_from_config_options(GraphProtocol subProtocol) { - // initialization - GraphRequestHandlerTestHarness harness = GraphRequestHandlerTestHarness.builder().build(); - GraphStatement graphStatement = - ScriptGraphStatement.newInstance("mockQuery").setExecutionProfileName("test-graph"); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - // when - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(graphStatement, harness.getContext()); - - Map requestPayload = - GraphConversions.createCustomPayload( - graphStatement, subProtocol, executionProfile, harness.getContext(), module); - - // checks - Mockito.verify(executionProfile).getString(DseDriverOption.GRAPH_TRAVERSAL_SOURCE, null); - Mockito.verify(executionProfile).getString(DseDriverOption.GRAPH_NAME, null); - Mockito.verify(executionProfile).getBoolean(DseDriverOption.GRAPH_IS_SYSTEM_QUERY, false); - Mockito.verify(executionProfile).getDuration(DseDriverOption.GRAPH_TIMEOUT, Duration.ZERO); - Mockito.verify(executionProfile).getString(DseDriverOption.GRAPH_READ_CONSISTENCY_LEVEL, null); - Mockito.verify(executionProfile).getString(DseDriverOption.GRAPH_WRITE_CONSISTENCY_LEVEL, null); - - assertThat(requestPayload.get(GraphConversions.GRAPH_SOURCE_OPTION_KEY)) - .isEqualTo(TEXT.encode("a", harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_RESULTS_OPTION_KEY)) - .isEqualTo( - TEXT.encode(subProtocol.toInternalCode(), harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_NAME_OPTION_KEY)) - .isEqualTo(TEXT.encode("mockGraph", harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_LANG_OPTION_KEY)) - .isEqualTo(TEXT.encode("gremlin-groovy", harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_TIMEOUT_OPTION_KEY)) - .isEqualTo(BIGINT.encode(2L, harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_READ_CONSISTENCY_LEVEL_OPTION_KEY)) - .isEqualTo(TEXT.encode("LOCAL_TWO", harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_WRITE_CONSISTENCY_LEVEL_OPTION_KEY)) - .isEqualTo(TEXT.encode("LOCAL_THREE", harness.getContext().getProtocolVersion())); - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "supportedGraphProtocols") - public void should_create_payload_from_statement_options(GraphProtocol subProtocol) { - // initialization - GraphRequestHandlerTestHarness harness = GraphRequestHandlerTestHarness.builder().build(); - GraphStatement graphStatement = - ScriptGraphStatement.builder("mockQuery") - .setGraphName("mockGraph") - .setTraversalSource("a") - .setTimeout(Duration.ofMillis(2)) - .setReadConsistencyLevel(DefaultConsistencyLevel.TWO) - .setWriteConsistencyLevel(DefaultConsistencyLevel.THREE) - .setSystemQuery(false) - .build(); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - // when - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(graphStatement, harness.getContext()); - - Map requestPayload = - GraphConversions.createCustomPayload( - graphStatement, subProtocol, executionProfile, harness.getContext(), module); - - // checks - Mockito.verify(executionProfile, never()) - .getString(DseDriverOption.GRAPH_TRAVERSAL_SOURCE, null); - Mockito.verify(executionProfile, never()).getString(DseDriverOption.GRAPH_NAME, null); - Mockito.verify(executionProfile, never()) - .getBoolean(DseDriverOption.GRAPH_IS_SYSTEM_QUERY, false); - Mockito.verify(executionProfile, never()) - .getDuration(DseDriverOption.GRAPH_TIMEOUT, Duration.ZERO); - Mockito.verify(executionProfile, never()) - .getString(DseDriverOption.GRAPH_READ_CONSISTENCY_LEVEL, null); - Mockito.verify(executionProfile, never()) - .getString(DseDriverOption.GRAPH_WRITE_CONSISTENCY_LEVEL, null); - - assertThat(requestPayload.get(GraphConversions.GRAPH_SOURCE_OPTION_KEY)) - .isEqualTo(TEXT.encode("a", harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_RESULTS_OPTION_KEY)) - .isEqualTo( - TEXT.encode(subProtocol.toInternalCode(), harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_NAME_OPTION_KEY)) - .isEqualTo(TEXT.encode("mockGraph", harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_LANG_OPTION_KEY)) - .isEqualTo(TEXT.encode("gremlin-groovy", harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_TIMEOUT_OPTION_KEY)) - .isEqualTo(BIGINT.encode(2L, harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_READ_CONSISTENCY_LEVEL_OPTION_KEY)) - .isEqualTo(TEXT.encode("TWO", harness.getContext().getProtocolVersion())); - assertThat(requestPayload.get(GraphConversions.GRAPH_WRITE_CONSISTENCY_LEVEL_OPTION_KEY)) - .isEqualTo(TEXT.encode("THREE", harness.getContext().getProtocolVersion())); - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "supportedGraphProtocols") - public void should_not_set_graph_name_on_system_queries(GraphProtocol subProtocol) { - // initialization - GraphRequestHandlerTestHarness harness = GraphRequestHandlerTestHarness.builder().build(); - GraphStatement graphStatement = - ScriptGraphStatement.newInstance("mockQuery").setSystemQuery(true); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - // when - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(graphStatement, harness.getContext()); - - Map requestPayload = - GraphConversions.createCustomPayload( - graphStatement, subProtocol, executionProfile, harness.getContext(), module); - - // checks - assertThat(requestPayload.get(GraphConversions.GRAPH_NAME_OPTION_KEY)).isNull(); - assertThat(requestPayload.get(GraphConversions.GRAPH_SOURCE_OPTION_KEY)).isNull(); - } - - @Test - @UseDataProvider("supportedGraphProtocolsWithDseVersions") - public void should_return_results_for_statements(GraphProtocol graphProtocol, Version dseVersion) - throws IOException { - - GraphRequestHandlerTestHarness.Builder builder = - GraphRequestHandlerTestHarness.builder() - .withGraphProtocolForTestConfig(graphProtocol) - .withDseVersionInMetadata(dseVersion); - PoolBehavior node1Behavior = builder.customBehavior(node); - GraphRequestHandlerTestHarness harness = builder.build(); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - // ideally we would be able to provide a function here to - // produce results instead of a static predefined response. - // Function to which we would pass the harness instance or a (mocked)DriverContext. - // Since that's not possible in the RequestHandlerTestHarness API at the moment, we - // have to use another DseDriverContext and GraphBinaryModule here, - // instead of reusing the one in the harness' DriverContext - node1Behavior.setResponseSuccess(defaultDseFrameOf(singleGraphRow(graphProtocol, module))); - - GraphSupportChecker graphSupportChecker = mock(GraphSupportChecker.class); - when(graphSupportChecker.isPagingEnabled(any(), any())).thenReturn(false); - when(graphSupportChecker.inferGraphProtocol(any(), any(), any())).thenReturn(graphProtocol); - - GraphRequestAsyncProcessor p = - Mockito.spy(new GraphRequestAsyncProcessor(harness.getContext(), graphSupportChecker)); - when(p.getGraphBinaryModule()).thenReturn(module); - - GraphStatement graphStatement = - ScriptGraphStatement.newInstance("mockQuery").setExecutionProfileName("test-graph"); - GraphResultSet grs = - new GraphRequestSyncProcessor(p) - .process(graphStatement, harness.getSession(), harness.getContext(), "test-graph"); - - List nodes = grs.all(); - assertThat(nodes.size()).isEqualTo(1); - - GraphNode graphNode = nodes.get(0); - assertThat(graphNode.isVertex()).isTrue(); - - Vertex vRead = graphNode.asVertex(); - assertThat(vRead.label()).isEqualTo("person"); - assertThat(vRead.id()).isEqualTo(1); - if (!graphProtocol.isGraphBinary()) { - // GraphBinary does not encode properties regardless of whether they are present in the - // parent element or not :/ - assertThat(vRead.property("name").id()).isEqualTo(11); - assertThat(vRead.property("name").value()).isEqualTo("marko"); - } - } - - @DataProvider - public static Object[][] supportedGraphProtocolsWithDseVersions() { - return new Object[][] { - {GRAPHSON_1_0, Version.parse("6.7.0")}, - {GRAPHSON_1_0, Version.parse("6.8.0")}, - {GRAPHSON_2_0, Version.parse("6.7.0")}, - {GRAPHSON_2_0, Version.parse("6.8.0")}, - {GRAPH_BINARY_1_0, Version.parse("6.7.0")}, - {GRAPH_BINARY_1_0, Version.parse("6.8.0")}, - }; - } - - @Test - @UseDataProvider("dseVersionsWithDefaultGraphProtocol") - public void should_invoke_request_tracker_and_update_metrics( - GraphProtocol graphProtocol, Version dseVersion) throws IOException { - when(nodeMetricUpdater1.isEnabled( - DseNodeMetric.GRAPH_MESSAGES, DriverExecutionProfile.DEFAULT_NAME)) - .thenReturn(true); - - GraphRequestHandlerTestHarness.Builder builder = - GraphRequestHandlerTestHarness.builder() - .withGraphProtocolForTestConfig(graphProtocol) - .withDseVersionInMetadata(dseVersion); - PoolBehavior node1Behavior = builder.customBehavior(node); - GraphRequestHandlerTestHarness harness = builder.build(); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - GraphSupportChecker graphSupportChecker = mock(GraphSupportChecker.class); - when(graphSupportChecker.isPagingEnabled(any(), any())).thenReturn(false); - when(graphSupportChecker.inferGraphProtocol(any(), any(), any())).thenReturn(graphProtocol); - - GraphRequestAsyncProcessor p = - Mockito.spy(new GraphRequestAsyncProcessor(harness.getContext(), graphSupportChecker)); - when(p.getGraphBinaryModule()).thenReturn(module); - - RequestTracker requestTracker = mock(RequestTracker.class); - when(harness.getContext().getRequestTracker()).thenReturn(requestTracker); - - GraphStatement graphStatement = ScriptGraphStatement.newInstance("mockQuery"); - - node1Behavior.setResponseSuccess(defaultDseFrameOf(singleGraphRow(graphProtocol, module))); - - GraphResultSet grs = - new GraphRequestSyncProcessor( - new GraphRequestAsyncProcessor(harness.getContext(), graphSupportChecker)) - .process(graphStatement, harness.getSession(), harness.getContext(), "test-graph"); - - List nodes = grs.all(); - assertThat(nodes.size()).isEqualTo(1); - - GraphNode graphNode = nodes.get(0); - assertThat(graphNode.isVertex()).isTrue(); - - Vertex actual = graphNode.asVertex(); - assertThat(actual.label()).isEqualTo("person"); - assertThat(actual.id()).isEqualTo(1); - if (!graphProtocol.isGraphBinary()) { - // GraphBinary does not encode properties regardless of whether they are present in the - // parent element or not :/ - assertThat(actual.property("name").id()).isEqualTo(11); - assertThat(actual.property("name").value()).isEqualTo("marko"); - } - - verify(requestTracker) - .onSuccess( - eq(graphStatement), - anyLong(), - any(DriverExecutionProfile.class), - eq(node), - matches(LOG_PREFIX_PER_REQUEST)); - verify(requestTracker) - .onNodeSuccess( - eq(graphStatement), - anyLong(), - any(DriverExecutionProfile.class), - eq(node), - matches(LOG_PREFIX_PER_REQUEST)); - verifyNoMoreInteractions(requestTracker); - - verify(nodeMetricUpdater1) - .isEnabled(DseNodeMetric.GRAPH_MESSAGES, DriverExecutionProfile.DEFAULT_NAME); - verify(nodeMetricUpdater1) - .updateTimer( - eq(DseNodeMetric.GRAPH_MESSAGES), - eq(DriverExecutionProfile.DEFAULT_NAME), - anyLong(), - eq(TimeUnit.NANOSECONDS)); - verifyNoMoreInteractions(nodeMetricUpdater1); - - verify(harness.getSession().getMetricUpdater()) - .isEnabled(DseSessionMetric.GRAPH_REQUESTS, DriverExecutionProfile.DEFAULT_NAME); - verify(harness.getSession().getMetricUpdater()) - .updateTimer( - eq(DseSessionMetric.GRAPH_REQUESTS), - eq(DriverExecutionProfile.DEFAULT_NAME), - anyLong(), - eq(TimeUnit.NANOSECONDS)); - verifyNoMoreInteractions(harness.getSession().getMetricUpdater()); - } - - @Test - public void should_honor_statement_consistency_level() { - // initialization - GraphRequestHandlerTestHarness harness = GraphRequestHandlerTestHarness.builder().build(); - ScriptGraphStatement graphStatement = - ScriptGraphStatement.builder("mockScript") - .setConsistencyLevel(DefaultConsistencyLevel.THREE) - .build(); - - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - // when - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(graphStatement, harness.getContext()); - - Message m = - GraphConversions.createMessageFromGraphStatement( - graphStatement, GRAPH_BINARY_1_0, executionProfile, harness.getContext(), module); - - // checks - assertThat(m).isInstanceOf(Query.class); - Query q = ((Query) m); - assertThat(q.options.consistency).isEqualTo(DefaultConsistencyLevel.THREE.getProtocolCode()); - } - - @Test - public void should_cancel_pre_acquired_id_if_graph_payload_conversion_fails() { - RuntimeException failure = new RuntimeException("mock failure"); - ScriptGraphStatement graphStatement = - Mockito.spy(ScriptGraphStatement.newInstance("mock query")); - doThrow(failure).when(graphStatement).getCustomPayload(); - - GraphRequestHandlerTestHarness.Builder builder = GraphRequestHandlerTestHarness.builder(); - PoolBehavior nodeBehavior = builder.customBehavior(node); - try (GraphRequestHandlerTestHarness harness = builder.build()) { - GraphSupportChecker graphSupportChecker = mock(GraphSupportChecker.class); - when(graphSupportChecker.inferGraphProtocol(any(), any(), any())) - .thenReturn(GRAPH_BINARY_1_0); - GraphBinaryModule module = createGraphBinaryModule(harness.getContext()); - - assertThatThrownBy( - () -> - new GraphRequestHandler( - graphStatement, - harness.getSession(), - harness.getContext(), - "test", - module, - graphSupportChecker)) - .isSameAs(failure); - - nodeBehavior.verifyNoWrite(); - nodeBehavior.verifyPreAcquireCancelled(); - } - } - - @DataProvider - public static Object[][] dseVersionsWithDefaultGraphProtocol() { - // Default GraphSON sub protocol version differs based on DSE version, so test with a version - // less than DSE 6.8 as well as DSE 6.8. - return new Object[][] { - {GRAPHSON_2_0, Version.parse("6.7.0")}, - {GRAPH_BINARY_1_0, Version.parse("6.8.0")}, - }; - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandlerTestHarness.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandlerTestHarness.java deleted file mode 100644 index 9ce5dee1e8c..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphRequestHandlerTestHarness.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.DseTestFixtures; -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.oss.driver.api.core.DefaultConsistencyLevel; -import com.datastax.oss.driver.api.core.ProtocolVersion; -import com.datastax.oss.driver.api.core.Version; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry; -import com.datastax.oss.driver.internal.core.DefaultConsistencyLevelRegistry; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import com.datastax.oss.driver.internal.core.cql.RequestHandlerTestHarness; -import com.datastax.oss.driver.internal.core.servererrors.DefaultWriteTypeRegistry; -import com.datastax.oss.driver.internal.core.session.throttling.PassThroughRequestThrottler; -import com.datastax.oss.driver.internal.core.tracker.NoopRequestTracker; -import com.datastax.oss.protocol.internal.Frame; -import edu.umd.cs.findbugs.annotations.Nullable; -import io.netty.channel.EventLoop; -import java.time.Duration; -import org.mockito.ArgumentMatchers; -import org.mockito.Mock; - -/** - * Provides the environment to test a request handler, where a query plan can be defined, and the - * behavior of each successive node simulated. - */ -public class GraphRequestHandlerTestHarness extends RequestHandlerTestHarness { - - @Mock DriverExecutionProfile testProfile; - - @Mock DriverExecutionProfile systemQueryExecutionProfile; - - @Mock DefaultDriverContext dseDriverContext; - - @Mock EventLoop eventLoop; - - protected GraphRequestHandlerTestHarness( - Builder builder, - @Nullable GraphProtocol graphProtocolForTestConfig, - Duration graphTimeout, - @Nullable Version dseVersionForTestMetadata) { - super(builder); - - // not mocked by RequestHandlerTestHarness, will be used when DseDriverOptions.GRAPH_TIMEOUT - // is not zero in the config - when(eventLoopGroup.next()).thenReturn(eventLoop); - - // default graph options as in the reference.conf file - when(defaultProfile.getString(DseDriverOption.GRAPH_TRAVERSAL_SOURCE, null)).thenReturn("g"); - when(defaultProfile.isDefined(DseDriverOption.GRAPH_SUB_PROTOCOL)).thenReturn(Boolean.FALSE); - when(defaultProfile.getBoolean(DseDriverOption.GRAPH_IS_SYSTEM_QUERY, false)).thenReturn(false); - when(defaultProfile.getString(DseDriverOption.GRAPH_NAME, null)).thenReturn("mockGraph"); - when(defaultProfile.getDuration(DseDriverOption.GRAPH_TIMEOUT, Duration.ZERO)) - .thenReturn(graphTimeout); - - when(testProfile.getName()).thenReturn("test-graph"); - when(testProfile.getDuration(DseDriverOption.GRAPH_TIMEOUT, Duration.ZERO)) - .thenReturn(Duration.ofMillis(2L)); - when(testProfile.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .thenReturn(DefaultConsistencyLevel.LOCAL_ONE.name()); - when(testProfile.getInt(DefaultDriverOption.REQUEST_PAGE_SIZE)).thenReturn(5000); - when(testProfile.getString(DefaultDriverOption.REQUEST_SERIAL_CONSISTENCY)) - .thenReturn(DefaultConsistencyLevel.SERIAL.name()); - when(testProfile.getBoolean(DefaultDriverOption.REQUEST_DEFAULT_IDEMPOTENCE)).thenReturn(false); - when(testProfile.getBoolean(DefaultDriverOption.PREPARE_ON_ALL_NODES)).thenReturn(true); - when(testProfile.getString(DseDriverOption.GRAPH_TRAVERSAL_SOURCE, null)).thenReturn("a"); - when(testProfile.isDefined(DseDriverOption.GRAPH_SUB_PROTOCOL)) - .thenReturn(graphProtocolForTestConfig != null); - // only mock the config if graphProtocolForTestConfig is not null - if (graphProtocolForTestConfig != null) { - when(testProfile.getString(DseDriverOption.GRAPH_SUB_PROTOCOL)) - .thenReturn(graphProtocolForTestConfig.toInternalCode()); - } - when(testProfile.getBoolean(DseDriverOption.GRAPH_IS_SYSTEM_QUERY, false)).thenReturn(false); - when(testProfile.getString(DseDriverOption.GRAPH_NAME, null)).thenReturn("mockGraph"); - when(testProfile.getString(DseDriverOption.GRAPH_READ_CONSISTENCY_LEVEL, null)) - .thenReturn("LOCAL_TWO"); - when(testProfile.getString(DseDriverOption.GRAPH_WRITE_CONSISTENCY_LEVEL, null)) - .thenReturn("LOCAL_THREE"); - when(config.getProfile("test-graph")).thenReturn(testProfile); - - when(systemQueryExecutionProfile.getName()).thenReturn("graph-system-query"); - when(systemQueryExecutionProfile.getDuration(DseDriverOption.GRAPH_TIMEOUT, Duration.ZERO)) - .thenReturn(Duration.ZERO); - when(systemQueryExecutionProfile.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .thenReturn(DefaultConsistencyLevel.LOCAL_ONE.name()); - when(systemQueryExecutionProfile.getInt(DefaultDriverOption.REQUEST_PAGE_SIZE)) - .thenReturn(5000); - when(systemQueryExecutionProfile.getString(DefaultDriverOption.REQUEST_SERIAL_CONSISTENCY)) - .thenReturn(DefaultConsistencyLevel.SERIAL.name()); - when(systemQueryExecutionProfile.getBoolean(DefaultDriverOption.REQUEST_DEFAULT_IDEMPOTENCE)) - .thenReturn(false); - when(systemQueryExecutionProfile.getBoolean(DefaultDriverOption.PREPARE_ON_ALL_NODES)) - .thenReturn(true); - when(systemQueryExecutionProfile.getName()).thenReturn("graph-system-query"); - when(systemQueryExecutionProfile.getDuration(DseDriverOption.GRAPH_TIMEOUT, Duration.ZERO)) - .thenReturn(Duration.ofMillis(2)); - when(systemQueryExecutionProfile.getBoolean(DseDriverOption.GRAPH_IS_SYSTEM_QUERY, false)) - .thenReturn(true); - when(systemQueryExecutionProfile.getString(DseDriverOption.GRAPH_READ_CONSISTENCY_LEVEL, null)) - .thenReturn("LOCAL_TWO"); - when(systemQueryExecutionProfile.getString(DseDriverOption.GRAPH_WRITE_CONSISTENCY_LEVEL, null)) - .thenReturn("LOCAL_THREE"); - - when(config.getProfile("graph-system-query")).thenReturn(systemQueryExecutionProfile); - - // need to re-mock everything on the context because the RequestHandlerTestHarness returns a - // InternalDriverContext and not a DseDriverContext. Couldn't figure out a way with mockito - // to say "mock this object (this.dseDriverContext), and delegate every call to that - // other object (this.context), except _this_ call and _this_ and so on" - // Spy wouldn't work because the spied object has to be of the same type as the final object - when(dseDriverContext.getConfig()).thenReturn(config); - when(dseDriverContext.getNettyOptions()).thenReturn(nettyOptions); - when(dseDriverContext.getLoadBalancingPolicyWrapper()).thenReturn(loadBalancingPolicyWrapper); - when(dseDriverContext.getRetryPolicy(ArgumentMatchers.anyString())).thenReturn(retryPolicy); - when(dseDriverContext.getSpeculativeExecutionPolicy(ArgumentMatchers.anyString())) - .thenReturn(speculativeExecutionPolicy); - when(dseDriverContext.getCodecRegistry()).thenReturn(CodecRegistry.DEFAULT); - when(dseDriverContext.getTimestampGenerator()).thenReturn(timestampGenerator); - when(dseDriverContext.getProtocolVersion()).thenReturn(DseProtocolVersion.DSE_V2); - when(dseDriverContext.getProtocolVersionRegistry()).thenReturn(protocolVersionRegistry); - when(dseDriverContext.getConsistencyLevelRegistry()) - .thenReturn(new DefaultConsistencyLevelRegistry()); - when(dseDriverContext.getWriteTypeRegistry()).thenReturn(new DefaultWriteTypeRegistry()); - when(dseDriverContext.getRequestThrottler()) - .thenReturn(new PassThroughRequestThrottler(dseDriverContext)); - when(dseDriverContext.getRequestTracker()).thenReturn(new NoopRequestTracker(dseDriverContext)); - // if DSE Version is specified for test metadata, then we need to mock that up on the context - if (dseVersionForTestMetadata != null) { - DseTestFixtures.mockNodesInMetadataWithVersions( - dseDriverContext, true, dseVersionForTestMetadata); - } - } - - @Override - public DefaultDriverContext getContext() { - return dseDriverContext; - } - - public static GraphRequestHandlerTestHarness.Builder builder() { - return new GraphRequestHandlerTestHarness.Builder(); - } - - public static class Builder extends RequestHandlerTestHarness.Builder { - - private GraphProtocol graphProtocolForTestConfig; - private Duration graphTimeout = Duration.ZERO; - private Version dseVersionForTestMetadata; - - public GraphRequestHandlerTestHarness.Builder withGraphProtocolForTestConfig( - GraphProtocol protocol) { - this.graphProtocolForTestConfig = protocol; - return this; - } - - public GraphRequestHandlerTestHarness.Builder withDseVersionInMetadata(Version dseVersion) { - this.dseVersionForTestMetadata = dseVersion; - return this; - } - - public GraphRequestHandlerTestHarness.Builder withGraphTimeout(Duration globalTimeout) { - this.graphTimeout = globalTimeout; - return this; - } - - @Override - public GraphRequestHandlerTestHarness.Builder withEmptyPool(Node node) { - super.withEmptyPool(node); - return this; - } - - @Override - public GraphRequestHandlerTestHarness.Builder withWriteFailure(Node node, Throwable cause) { - super.withWriteFailure(node, cause); - return this; - } - - @Override - public GraphRequestHandlerTestHarness.Builder withResponseFailure(Node node, Throwable cause) { - super.withResponseFailure(node, cause); - return this; - } - - @Override - public GraphRequestHandlerTestHarness.Builder withResponse(Node node, Frame response) { - super.withResponse(node, response); - return this; - } - - @Override - public GraphRequestHandlerTestHarness.Builder withDefaultIdempotence( - boolean defaultIdempotence) { - super.withDefaultIdempotence(defaultIdempotence); - return this; - } - - @Override - public GraphRequestHandlerTestHarness.Builder withProtocolVersion( - ProtocolVersion protocolVersion) { - super.withProtocolVersion(protocolVersion); - return this; - } - - @Override - public GraphRequestHandlerTestHarness build() { - return new GraphRequestHandlerTestHarness( - this, graphProtocolForTestConfig, graphTimeout, dseVersionForTestMetadata); - } - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphResultSetTestBase.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphResultSetTestBase.java deleted file mode 100644 index aed248675ae..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphResultSetTestBase.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import com.datastax.oss.driver.shaded.guava.common.collect.Lists; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Queue; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; - -public abstract class GraphResultSetTestBase { - - /** Mocks an async result set where column 0 has type INT, with rows with the provided data. */ - protected AsyncGraphResultSet mockPage(boolean nextPage, Integer... data) { - AsyncGraphResultSet page = mock(AsyncGraphResultSet.class); - - ExecutionInfo executionInfo = mock(ExecutionInfo.class); - when(page.getRequestExecutionInfo()).thenReturn(executionInfo); - - if (nextPage) { - when(page.hasMorePages()).thenReturn(true); - when(page.fetchNextPage()).thenReturn(spy(new CompletableFuture<>())); - } else { - when(page.hasMorePages()).thenReturn(false); - when(page.fetchNextPage()).thenThrow(new IllegalStateException()); - } - - // Emulate DefaultAsyncResultSet's internals (this is a bit sketchy, maybe it would be better - // to use real DefaultAsyncResultSet instances) - Queue queue = Lists.newLinkedList(Arrays.asList(data)); - CountingIterator iterator = - new CountingIterator(queue.size()) { - @Override - protected GraphNode computeNext() { - Integer index = queue.poll(); - return (index == null) ? endOfData() : mockRow(index); - } - }; - when(page.currentPage()).thenReturn(() -> iterator); - when(page.remaining()).thenAnswer(invocation -> iterator.remaining()); - - return page; - } - - private GraphNode mockRow(int index) { - GraphNode row = mock(GraphNode.class); - when(row.asInt()).thenReturn(index); - return row; - } - - protected static void complete( - CompletionStage stage, AsyncGraphResultSet result) { - stage.toCompletableFuture().complete(result); - } - - protected void assertNextRow(Iterator iterator, int expectedValue) { - assertThat(iterator.hasNext()).isTrue(); - GraphNode row = iterator.next(); - assertThat(row.asInt()).isEqualTo(expectedValue); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphResultSetsTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphResultSetsTest.java deleted file mode 100644 index fd5cffd2530..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphResultSetsTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.GraphResultSet; -import java.util.Iterator; -import org.junit.Test; - -public class GraphResultSetsTest extends GraphResultSetTestBase { - - @Test - public void should_create_result_set_from_single_page() { - // Given - AsyncGraphResultSet page1 = mockPage(false, 0, 1, 2); - - // When - GraphResultSet resultSet = GraphResultSets.toSync(page1); - - // Then - assertThat(resultSet.getRequestExecutionInfo()).isSameAs(page1.getRequestExecutionInfo()); - - Iterator iterator = resultSet.iterator(); - - assertNextRow(iterator, 0); - assertNextRow(iterator, 1); - assertNextRow(iterator, 2); - - assertThat(iterator.hasNext()).isFalse(); - } - - @Test - public void should_create_result_set_from_multiple_pages() { - // Given - AsyncGraphResultSet page1 = mockPage(true, 0, 1, 2); - AsyncGraphResultSet page2 = mockPage(true, 3, 4, 5); - AsyncGraphResultSet page3 = mockPage(false, 6, 7, 8); - - complete(page1.fetchNextPage(), page2); - complete(page2.fetchNextPage(), page3); - - // When - GraphResultSet resultSet = GraphResultSets.toSync(page1); - - // Then - assertThat(resultSet.iterator().hasNext()).isTrue(); - - assertThat(resultSet.getRequestExecutionInfo()).isSameAs(page1.getRequestExecutionInfo()); - assertThat(((MultiPageGraphResultSet) resultSet).getRequestExecutionInfos()) - .containsExactly(page1.getRequestExecutionInfo()); - - Iterator iterator = resultSet.iterator(); - - assertNextRow(iterator, 0); - assertNextRow(iterator, 1); - assertNextRow(iterator, 2); - - assertThat(iterator.hasNext()).isTrue(); - // This should have triggered the fetch of page2 - assertThat(resultSet.getRequestExecutionInfo()).isEqualTo(page2.getRequestExecutionInfo()); - assertThat(((MultiPageGraphResultSet) resultSet).getRequestExecutionInfos()) - .containsExactly(page1.getRequestExecutionInfo(), page2.getRequestExecutionInfo()); - - assertNextRow(iterator, 3); - assertNextRow(iterator, 4); - assertNextRow(iterator, 5); - - assertThat(iterator.hasNext()).isTrue(); - // This should have triggered the fetch of page3 - assertThat(resultSet.getRequestExecutionInfo()).isEqualTo(page3.getRequestExecutionInfo()); - assertThat(((MultiPageGraphResultSet) resultSet).getRequestExecutionInfos()) - .containsExactly( - page1.getRequestExecutionInfo(), - page2.getRequestExecutionInfo(), - page3.getRequestExecutionInfo()); - - assertNextRow(iterator, 6); - assertNextRow(iterator, 7); - assertNextRow(iterator, 8); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphStatementBuilderBaseTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphStatementBuilderBaseTest.java deleted file mode 100644 index 4799437e617..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphStatementBuilderBaseTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.dse.driver.api.core.graph.GraphStatementBuilderBase; -import com.datastax.oss.driver.api.core.cql.Statement; -import edu.umd.cs.findbugs.annotations.NonNull; -import org.junit.Test; - -public class GraphStatementBuilderBaseTest { - - private static class MockGraphStatementBuilder - extends GraphStatementBuilderBase { - - @NonNull - @Override - public FluentGraphStatement build() { - FluentGraphStatement rv = mock(FluentGraphStatement.class); - when(rv.getTimestamp()).thenReturn(this.timestamp); - return rv; - } - } - - @Test - public void should_use_timestamp_if_set() { - - MockGraphStatementBuilder builder = new MockGraphStatementBuilder(); - builder.setTimestamp(1); - assertThat(builder.build().getTimestamp()).isEqualTo(1); - } - - @Test - public void should_use_correct_default_timestamp_if_not_set() { - - MockGraphStatementBuilder builder = new MockGraphStatementBuilder(); - assertThat(builder.build().getTimestamp()).isEqualTo(Statement.NO_DEFAULT_TIMESTAMP); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphSupportCheckerTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphSupportCheckerTest.java deleted file mode 100644 index eda3bbed446..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphSupportCheckerTest.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static com.datastax.dse.driver.DseTestFixtures.mockNodesInMetadataWithVersions; -import static com.datastax.dse.driver.api.core.graph.PagingEnabledOptions.AUTO; -import static com.datastax.dse.driver.api.core.graph.PagingEnabledOptions.DISABLED; -import static com.datastax.dse.driver.api.core.graph.PagingEnabledOptions.ENABLED; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.DseTestDataProviders; -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.graph.PagingEnabledOptions; -import com.datastax.dse.driver.api.core.metadata.DseNodeProperties; -import com.datastax.dse.driver.internal.core.DseProtocolFeature; -import com.datastax.oss.driver.api.core.Version; -import com.datastax.oss.driver.api.core.config.DriverConfig; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.metadata.Metadata; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.internal.core.ProtocolVersionRegistry; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.metadata.MetadataManager; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(DataProviderRunner.class) -public class GraphSupportCheckerTest { - - @UseDataProvider("graphPagingEnabledAndDseVersions") - @Test - public void should_check_if_paging_is_supported( - boolean protocolWithPagingSupport, - PagingEnabledOptions statementGraphPagingEnabled, - PagingEnabledOptions contextGraphPagingEnabled, - List nodeDseVersions, - boolean expected) { - // given - GraphStatement graphStatement = mock(GraphStatement.class); - InternalDriverContext context = protocolWithPagingSupport(protocolWithPagingSupport); - statementGraphPagingEnabled(graphStatement, statementGraphPagingEnabled); - contextGraphPagingEnabled(context, contextGraphPagingEnabled); - addNodeWithDseVersion(context, nodeDseVersions); - - // when - boolean pagingEnabled = new GraphSupportChecker().isPagingEnabled(graphStatement, context); - - // then - assertThat(pagingEnabled).isEqualTo(expected); - } - - @Test - public void should_not_support_paging_when_statement_profile_not_present() { - // given - GraphStatement graphStatement = mock(GraphStatement.class); - InternalDriverContext context = protocolWithPagingSupport(true); - contextGraphPagingEnabled(context, DISABLED); - addNodeWithDseVersion(context, Collections.singletonList(Version.parse("6.8.0"))); - - // when - boolean pagingEnabled = new GraphSupportChecker().isPagingEnabled(graphStatement, context); - - // then - assertThat(pagingEnabled).isEqualTo(false); - } - - @Test - public void - should_support_paging_when_statement_profile_not_present_but_context_profile_has_paging_enabled() { - // given - GraphStatement graphStatement = mock(GraphStatement.class); - InternalDriverContext context = protocolWithPagingSupport(true); - contextGraphPagingEnabled(context, ENABLED); - addNodeWithDseVersion(context, Collections.singletonList(Version.parse("6.8.0"))); - - // when - boolean pagingEnabled = new GraphSupportChecker().isPagingEnabled(graphStatement, context); - - // then - assertThat(pagingEnabled).isEqualTo(true); - } - - @DataProvider() - public static Object[][] graphPagingEnabledAndDseVersions() { - List listWithGraphPagingNode = Collections.singletonList(Version.parse("6.8.0")); - List listWithoutGraphPagingNode = Collections.singletonList(Version.parse("6.7.0")); - List listWithNull = Collections.singletonList(null); - List listWithTwoNodesOneNotSupporting = - Arrays.asList(Version.parse("6.7.0"), Version.parse("6.8.0")); - - return new Object[][] { - {false, ENABLED, ENABLED, listWithGraphPagingNode, true}, - {true, ENABLED, ENABLED, listWithoutGraphPagingNode, true}, - {true, ENABLED, DISABLED, listWithGraphPagingNode, true}, - {true, ENABLED, ENABLED, listWithGraphPagingNode, true}, - {true, ENABLED, ENABLED, listWithNull, true}, - {true, ENABLED, ENABLED, listWithTwoNodesOneNotSupporting, true}, - {true, DISABLED, ENABLED, listWithGraphPagingNode, false}, - {true, DISABLED, AUTO, listWithGraphPagingNode, false}, - {true, DISABLED, DISABLED, listWithGraphPagingNode, false}, - {true, AUTO, AUTO, listWithGraphPagingNode, true}, - {true, AUTO, DISABLED, listWithGraphPagingNode, true}, - {false, AUTO, AUTO, listWithGraphPagingNode, false}, - {true, AUTO, AUTO, listWithTwoNodesOneNotSupporting, false}, - {true, AUTO, AUTO, listWithNull, false}, - }; - } - - private void addNodeWithDseVersion(InternalDriverContext context, List dseVersions) { - MetadataManager manager = mock(MetadataManager.class); - when(context.getMetadataManager()).thenReturn(manager); - Metadata metadata = mock(Metadata.class); - when(manager.getMetadata()).thenReturn(metadata); - Map nodes = new HashMap<>(); - for (Version v : dseVersions) { - Node node = mock(Node.class); - Map extras = new HashMap<>(); - extras.put(DseNodeProperties.DSE_VERSION, v); - when(node.getExtras()).thenReturn(extras); - nodes.put(UUID.randomUUID(), node); - } - when(metadata.getNodes()).thenReturn(nodes); - } - - private void contextGraphPagingEnabled( - InternalDriverContext context, PagingEnabledOptions option) { - DriverExecutionProfile driverExecutionProfile = mock(DriverExecutionProfile.class); - when(driverExecutionProfile.getString(DseDriverOption.GRAPH_PAGING_ENABLED)) - .thenReturn(option.name()); - DriverConfig config = mock(DriverConfig.class); - when(context.getConfig()).thenReturn(config); - when(config.getDefaultProfile()).thenReturn(driverExecutionProfile); - } - - private InternalDriverContext protocolWithPagingSupport(boolean pagingSupport) { - InternalDriverContext context = mock(InternalDriverContext.class); - when(context.getProtocolVersion()).thenReturn(DseProtocolVersion.DSE_V2); - ProtocolVersionRegistry protocolVersionRegistry = mock(ProtocolVersionRegistry.class); - when(protocolVersionRegistry.supports( - DseProtocolVersion.DSE_V2, DseProtocolFeature.CONTINUOUS_PAGING)) - .thenReturn(pagingSupport); - when(context.getProtocolVersionRegistry()).thenReturn(protocolVersionRegistry); - return context; - } - - private void statementGraphPagingEnabled( - GraphStatement graphStatement, PagingEnabledOptions option) { - DriverExecutionProfile driverExecutionProfile = mock(DriverExecutionProfile.class); - when(driverExecutionProfile.getString(DseDriverOption.GRAPH_PAGING_ENABLED)) - .thenReturn(option.name()); - when(graphStatement.getExecutionProfile()).thenReturn(driverExecutionProfile); - } - - @Test - @UseDataProvider("dseVersionsAndGraphProtocols") - public void should_determine_default_graph_protocol_from_dse_version( - Version[] dseVersions, GraphProtocol expectedProtocol) { - // mock up the metadata for the context - // using 'true' here will treat null test Versions as no DSE_VERSION info in the metadata - DefaultDriverContext context = - mockNodesInMetadataWithVersions(mock(DefaultDriverContext.class), true, dseVersions); - GraphProtocol graphProtocol = new GraphSupportChecker().getDefaultGraphProtocol(context); - assertThat(graphProtocol).isEqualTo(expectedProtocol); - } - - @Test - @UseDataProvider("dseVersionsAndGraphProtocols") - public void should_determine_default_graph_protocol_from_dse_version_with_null_versions( - Version[] dseVersions, GraphProtocol expectedProtocol) { - // mock up the metadata for the context - // using 'false' here will treat null test Versions as explicit NULL info for DSE_VERSION - DefaultDriverContext context = - mockNodesInMetadataWithVersions(mock(DefaultDriverContext.class), false, dseVersions); - GraphProtocol graphProtocol = new GraphSupportChecker().getDefaultGraphProtocol(context); - assertThat(graphProtocol).isEqualTo(expectedProtocol); - } - - @DataProvider - public static Object[][] dseVersionsAndGraphProtocols() { - return new Object[][] { - {new Version[] {Version.parse("5.0.3")}, GraphProtocol.GRAPHSON_2_0}, - {new Version[] {Version.parse("6.0.1")}, GraphProtocol.GRAPHSON_2_0}, - {new Version[] {Version.parse("6.7.4")}, GraphProtocol.GRAPHSON_2_0}, - {new Version[] {Version.parse("6.8.0")}, GraphProtocol.GRAPH_BINARY_1_0}, - {new Version[] {Version.parse("7.0.0")}, GraphProtocol.GRAPH_BINARY_1_0}, - {new Version[] {Version.parse("5.0.3"), Version.parse("6.8.0")}, GraphProtocol.GRAPHSON_2_0}, - {new Version[] {Version.parse("6.7.4"), Version.parse("6.8.0")}, GraphProtocol.GRAPHSON_2_0}, - {new Version[] {Version.parse("6.8.0"), Version.parse("6.7.4")}, GraphProtocol.GRAPHSON_2_0}, - { - new Version[] {Version.parse("6.8.0"), Version.parse("7.0.0")}, - GraphProtocol.GRAPH_BINARY_1_0 - }, - {new Version[] {Version.parse("6.7.4"), Version.parse("6.7.4")}, GraphProtocol.GRAPHSON_2_0}, - { - new Version[] {Version.parse("6.8.0"), Version.parse("6.8.0")}, - GraphProtocol.GRAPH_BINARY_1_0 - }, - {null, GraphProtocol.GRAPHSON_2_0}, - {new Version[] {null}, GraphProtocol.GRAPHSON_2_0}, - {new Version[] {null, Version.parse("6.8.0")}, GraphProtocol.GRAPHSON_2_0}, - { - new Version[] {Version.parse("6.8.0"), Version.parse("7.0.0"), null}, - GraphProtocol.GRAPHSON_2_0 - }, - }; - } - - @Test - @UseDataProvider(location = DseTestDataProviders.class, value = "supportedGraphProtocols") - public void should_pickup_graph_protocol_from_statement(GraphProtocol graphProtocol) { - GraphStatement graphStatement = mock(GraphStatement.class); - DriverExecutionProfile executionProfile = mock(DriverExecutionProfile.class); - when(graphStatement.getSubProtocol()).thenReturn(graphProtocol.toInternalCode()); - - GraphProtocol inferredProtocol = - new GraphSupportChecker() - .inferGraphProtocol( - graphStatement, executionProfile, mock(InternalDriverContext.class)); - - assertThat(inferredProtocol).isEqualTo(graphProtocol); - verifyNoInteractions(executionProfile); - } - - @Test - @UseDataProvider("graphProtocolStringsAndDseVersions") - public void should_pickup_graph_protocol_and_parse_from_string_config( - String stringConfig, Version dseVersion) { - GraphStatement graphStatement = mock(GraphStatement.class); - DriverExecutionProfile executionProfile = mock(DriverExecutionProfile.class); - when(executionProfile.isDefined(DseDriverOption.GRAPH_SUB_PROTOCOL)).thenReturn(Boolean.TRUE); - when(executionProfile.getString(eq(DseDriverOption.GRAPH_SUB_PROTOCOL))) - .thenReturn(stringConfig); - - DefaultDriverContext context = - mockNodesInMetadataWithVersions(mock(DefaultDriverContext.class), true, dseVersion); - GraphProtocol inferredProtocol = - new GraphSupportChecker().inferGraphProtocol(graphStatement, executionProfile, context); - assertThat(inferredProtocol.toInternalCode()).isEqualTo(stringConfig); - } - - @DataProvider - public static Object[][] graphProtocolStringsAndDseVersions() { - // putting manual strings here to be sure to be notified if a value in - // GraphProtocol ever changes - return new Object[][] { - {"graphson-1.0", Version.parse("6.7.0")}, - {"graphson-1.0", Version.parse("6.8.0")}, - {"graphson-2.0", Version.parse("6.7.0")}, - {"graphson-2.0", Version.parse("6.8.0")}, - {"graph-binary-1.0", Version.parse("6.7.0")}, - {"graph-binary-1.0", Version.parse("6.8.0")}, - }; - } - - @Test - @UseDataProvider("dseVersions6") - public void should_use_correct_default_protocol_when_parsing(Version dseVersion) { - GraphStatement graphStatement = mock(GraphStatement.class); - DriverExecutionProfile executionProfile = mock(DriverExecutionProfile.class); - DefaultDriverContext context = - mockNodesInMetadataWithVersions(mock(DefaultDriverContext.class), true, dseVersion); - GraphProtocol inferredProtocol = - new GraphSupportChecker().inferGraphProtocol(graphStatement, executionProfile, context); - // For DSE 6.8 and newer, the default should be GraphSON binary - // for DSE older than 6.8, the default should be GraphSON2 - assertThat(inferredProtocol) - .isEqualTo( - (dseVersion.compareTo(Version.parse("6.8.0")) < 0) - ? GraphProtocol.GRAPHSON_2_0 - : GraphProtocol.GRAPH_BINARY_1_0); - } - - @DataProvider - public static Object[][] dseVersions6() { - return new Object[][] {{Version.parse("6.7.0")}, {Version.parse("6.8.0")}}; - } - - @Test - public void should_fail_if_graph_protocol_used_is_invalid() { - assertThatThrownBy(() -> GraphProtocol.fromString("invalid")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage( - "Graph protocol used [\"invalid\"] unknown. Possible values are: [ \"graphson-1.0\", \"graphson-2.0\", \"graph-binary-1.0\"]"); - } - - @Test - public void should_fail_if_graph_protocol_used_is_graphson_3() { - assertThatThrownBy(() -> GraphProtocol.fromString("graphson-3.0")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage( - "Graph protocol used [\"graphson-3.0\"] unknown. Possible values are: [ \"graphson-1.0\", \"graphson-2.0\", \"graph-binary-1.0\"]"); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphTestUtils.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphTestUtils.java deleted file mode 100644 index f58fc54d8c7..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/GraphTestUtils.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.internal.core.graph.binary.GraphBinaryModule; -import com.datastax.dse.protocol.internal.response.result.DseRowsMetadata; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import com.datastax.oss.protocol.internal.Frame; -import com.datastax.oss.protocol.internal.Message; -import com.datastax.oss.protocol.internal.ProtocolConstants; -import com.datastax.oss.protocol.internal.response.result.ColumnSpec; -import com.datastax.oss.protocol.internal.response.result.DefaultRows; -import com.datastax.oss.protocol.internal.response.result.RawType; -import com.datastax.oss.protocol.internal.response.result.Rows; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser; -import org.apache.tinkerpop.gremlin.structure.Direction; -import org.apache.tinkerpop.gremlin.structure.T; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; -import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry; -import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex; -import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty; -import org.assertj.core.api.InstanceOfAssertFactories; - -public class GraphTestUtils { - - public static ByteBuffer serialize( - Object value, GraphProtocol graphProtocol, GraphBinaryModule graphBinaryModule) - throws IOException { - - Buffer tinkerBuf = graphBinaryModule.serialize(value); - ByteBuffer nioBuffer = tinkerBuf.nioBuffer(); - tinkerBuf.release(); - return graphProtocol.isGraphBinary() - ? nioBuffer - : GraphSONUtils.serializeToByteBuffer(value, graphProtocol); - } - - public static Frame defaultDseFrameOf(Message responseMessage) { - return Frame.forResponse( - DseProtocolVersion.DSE_V2.getCode(), - 0, - null, - Frame.NO_PAYLOAD, - Collections.emptyList(), - responseMessage); - } - - public static Message singleGraphRow(GraphProtocol graphProtocol, GraphBinaryModule module) - throws IOException { - Vertex value = - DetachedVertex.build() - .setId(1) - .setLabel("person") - .addProperty( - DetachedVertexProperty.build() - .setId(11) - .setLabel("name") - .setValue("marko") - .create()) - .create(); - DseRowsMetadata metadata = - new DseRowsMetadata( - ImmutableList.of( - new ColumnSpec( - "ks", - "table", - "gremlin", - 0, - graphProtocol.isGraphBinary() - ? RawType.PRIMITIVES.get(ProtocolConstants.DataType.BLOB) - : RawType.PRIMITIVES.get(ProtocolConstants.DataType.VARCHAR))), - null, - new int[] {}, - null, - 1, - true); - Queue> data = new ArrayDeque<>(); - data.add( - ImmutableList.of( - serialize( - graphProtocol.isGraphBinary() - // GraphBinary returns results directly inside a Traverser - ? new DefaultRemoteTraverser<>(value, 1) - : ImmutableMap.of("result", value), - graphProtocol, - module))); - return new DefaultRows(metadata, data); - } - - // Returns 10 rows, each with a vertex - public static Rows tenGraphRows( - GraphProtocol graphProtocol, GraphBinaryModule module, int page, boolean last) - throws IOException { - DseRowsMetadata metadata = - new DseRowsMetadata( - ImmutableList.of( - new ColumnSpec( - "ks", - "table", - "gremlin", - 0, - graphProtocol.isGraphBinary() - ? RawType.PRIMITIVES.get(ProtocolConstants.DataType.BLOB) - : RawType.PRIMITIVES.get(ProtocolConstants.DataType.VARCHAR))), - null, - new int[] {}, - null, - page, - last); - Queue> data = new ArrayDeque<>(); - int start = (page - 1) * 10; - for (int i = start; i < start + 10; i++) { - Vertex v = - DetachedVertex.build() - .setId("vertex" + i) - .setLabel("person") - .addProperty( - DetachedVertexProperty.build() - .setId("property" + i) - .setLabel("name") - .setValue("user" + i) - .create()) - .create(); - data.add( - ImmutableList.of( - serialize( - graphProtocol.isGraphBinary() - // GraphBinary returns results directly inside a Traverser - ? new DefaultRemoteTraverser<>(v, 1) - : ImmutableMap.of("result", v), - graphProtocol, - module))); - } - return new DefaultRows(metadata, data); - } - - public static GraphBinaryModule createGraphBinaryModule(DefaultDriverContext context) { - TypeSerializerRegistry registry = GraphBinaryModule.createDseTypeSerializerRegistry(context); - return new GraphBinaryModule(new GraphBinaryReader(registry), new GraphBinaryWriter(registry)); - } - - public static void assertThatContainsProperties( - Map properties, Object... propsToMatch) { - for (int i = 0; i < propsToMatch.length; i += 2) { - assertThat(properties).containsEntry(propsToMatch[i], propsToMatch[i + 1]); - } - } - - public static void assertThatContainsLabel( - Map properties, Direction direction, String label) { - assertThat(properties) - .hasEntrySatisfying( - direction, - value -> - assertThat(value) - .asInstanceOf(InstanceOfAssertFactories.MAP) - .containsEntry(T.label, label)); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/binary/GraphDataTypesTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/binary/GraphDataTypesTest.java deleted file mode 100644 index e36f7e97e5a..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/binary/GraphDataTypesTest.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.binary; - -import static com.datastax.oss.driver.api.core.type.DataTypes.BIGINT; -import static com.datastax.oss.driver.api.core.type.DataTypes.DOUBLE; -import static com.datastax.oss.driver.api.core.type.DataTypes.DURATION; -import static com.datastax.oss.driver.api.core.type.DataTypes.FLOAT; -import static com.datastax.oss.driver.api.core.type.DataTypes.INT; -import static com.datastax.oss.driver.api.core.type.DataTypes.TEXT; -import static com.datastax.oss.driver.api.core.type.DataTypes.listOf; -import static com.datastax.oss.driver.api.core.type.DataTypes.mapOf; -import static com.datastax.oss.driver.api.core.type.DataTypes.setOf; -import static com.datastax.oss.driver.api.core.type.DataTypes.tupleOf; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import com.datastax.dse.driver.api.core.graph.BatchGraphStatement; -import com.datastax.dse.driver.api.core.graph.DseGraph; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.type.DseDataTypes; -import com.datastax.dse.driver.api.core.type.codec.DseTypeCodecs; -import com.datastax.dse.driver.internal.core.data.geometry.Distance; -import com.datastax.dse.driver.internal.core.graph.EditDistance; -import com.datastax.dse.driver.internal.core.graph.GraphConversions; -import com.datastax.dse.driver.internal.core.graph.GraphProtocol; -import com.datastax.dse.driver.internal.core.graph.GraphSONUtils; -import com.datastax.oss.driver.TestDataProviders; -import com.datastax.oss.driver.api.core.data.CqlDuration; -import com.datastax.oss.driver.api.core.type.DataTypes; -import com.datastax.oss.driver.api.core.type.TupleType; -import com.datastax.oss.driver.api.core.type.UserDefinedType; -import com.datastax.oss.driver.api.core.type.codec.registry.MutableCodecRegistry; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import com.datastax.oss.driver.internal.core.type.UserDefinedTypeBuilder; -import com.datastax.oss.driver.internal.core.type.codec.registry.DefaultCodecRegistry; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableSet; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.ByteBuffer; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalTime; -import java.time.ZoneOffset; -import java.util.List; -import java.util.Set; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; -import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; -import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(DataProviderRunner.class) -public class GraphDataTypesTest { - - private GraphBinaryModule graphBinaryModule; - - @Mock private DefaultDriverContext context; - - private static final MutableCodecRegistry CODEC_REGISTRY = - new DefaultCodecRegistry("testDseRegistry"); - - static { - CODEC_REGISTRY.register(DseTypeCodecs.POINT, DseTypeCodecs.LINE_STRING, DseTypeCodecs.POLYGON); - } - - private static Object[][] graphsonOneDataTypes = - new Object[][] { - {"~’~^ää#123#ö"}, - {(byte) 34}, - {BigDecimal.TEN}, - {BigInteger.TEN}, - {Boolean.TRUE}, - {false}, - {23}, - {23L}, - {23.0d}, - {23f}, - {(short) 23}, - {LocalDate.now(ZoneOffset.UTC)}, - {LocalTime.now(ZoneOffset.UTC)}, - {java.util.UUID.randomUUID()}, - {Instant.now()}, - }; - - private static Object[][] graphsonTwoDataTypes = - new Object[][] { - {ImmutableList.of(1L, 2L, 3L)}, - {ImmutableSet.of(1L, 2L, 3L)}, - {ImmutableMap.of("a", 1, "b", 2)}, - {Point.fromCoordinates(3.3, 4.4)}, - { - LineString.fromPoints( - Point.fromCoordinates(1, 1), Point.fromCoordinates(2, 2), Point.fromCoordinates(3, 3)) - }, - { - Polygon.fromPoints( - Point.fromCoordinates(3, 4), Point.fromCoordinates(5, 4), Point.fromCoordinates(6, 6)) - }, - }; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - when(context.getCodecRegistry()).thenReturn(CODEC_REGISTRY); - when(context.getProtocolVersion()).thenReturn(DseProtocolVersion.DSE_V2); - - TypeSerializerRegistry registry = GraphBinaryModule.createDseTypeSerializerRegistry(context); - graphBinaryModule = - new GraphBinaryModule(new GraphBinaryReader(registry), new GraphBinaryWriter(registry)); - } - - @DataProvider - public static Object[][] graphsonOneDataProvider() { - - return graphsonOneDataTypes; - } - - @DataProvider - public static Object[][] graphsonTwoDataProvider() { - - return TestDataProviders.concat(graphsonOneDataTypes, graphsonTwoDataTypes); - } - - @DataProvider - public static Object[][] binaryDataProvider() throws UnknownHostException { - - Object[][] binaryDataTypes = - new Object[][] { - {InetAddress.getLocalHost()}, - {ImmutableList.of(ImmutableList.of(1L, 3L), ImmutableList.of(2L, 4L))}, - {ImmutableSet.of(ImmutableSet.of(1, 2, 3))}, - {ImmutableMap.of(ImmutableMap.of("a", 1), ImmutableMap.of(2, "b"))}, - {tupleOf(INT, TEXT, FLOAT).newValue(1, "2", 3.41f)}, - { - tupleOf(INT, TEXT, tupleOf(TEXT, DURATION)) - .newValue( - 1, "2", tupleOf(TEXT, DURATION).newValue("a", CqlDuration.newInstance(2, 1, 0))) - }, - { - tupleOf( - listOf(INT), - setOf(FLOAT), - DataTypes.mapOf(TEXT, BIGINT), - listOf(listOf(DOUBLE)), - setOf(setOf(FLOAT)), - listOf(tupleOf(INT, TEXT))) - .newValue( - ImmutableList.of(4, 8, 22, 34, 37, 59), - ImmutableSet.of(28f, 44f, 59f), - ImmutableMap.of("big10", 2345L), - ImmutableList.of( - ImmutableList.of(11.1d, 33.3d), ImmutableList.of(22.2d, 44.4d)), - ImmutableSet.of(ImmutableSet.of(55.5f)), - ImmutableList.of(tupleOf(INT, TEXT).newValue(3, "three"))) - }, - { - new UserDefinedTypeBuilder("ks", "udt1") - .withField("a", INT) - .withField("b", TEXT) - .build() - .newValue(1, "two") - }, - {new Distance(Point.fromCoordinates(3.4, 17.0), 2.5)}, - {new EditDistance("xyz", 3)}, - {DseGraph.g.V().has("name", "marko").asAdmin().getBytecode()}, - { - GraphConversions.bytecodeToSerialize( - BatchGraphStatement.builder() - .addTraversal(DseGraph.g.addV("person").property("name", "1")) - .addTraversal(DseGraph.g.addV("person").property("name", "1")) - .build()) - }, - }; - return TestDataProviders.concat(graphsonTwoDataProvider(), binaryDataTypes); - } - - @Test - @UseDataProvider("binaryDataProvider") - public void dataTypesTest(Object value) throws IOException { - verifySerDeBinary(value); - } - - @Test - @UseDataProvider("graphsonOneDataProvider") - public void dataTypesTestGraphsonOne(Object value) throws IOException { - verifySerDeGraphson(value, GraphProtocol.GRAPHSON_1_0); - } - - @Test - @UseDataProvider("graphsonTwoDataProvider") - public void dataTypesTestGraphsonTwo(Object value) throws IOException { - verifySerDeGraphson(value, GraphProtocol.GRAPHSON_2_0); - } - - @Test - public void complexUdtTests() throws IOException { - UserDefinedType type1 = - new UserDefinedTypeBuilder("ks", "udt1").withField("a", INT).withField("b", TEXT).build(); - verifySerDeBinary(type1.newValue(1, "2")); - - TupleType secondNested = tupleOf(BIGINT, listOf(BIGINT)); - TupleType firstNested = tupleOf(TEXT, secondNested); - - UserDefinedType type2 = - new UserDefinedTypeBuilder("ks", "udt2") - .withField("a", INT) - .withField("b", TEXT) - .withField("c", type1) - .withField("mylist", listOf(BIGINT)) - .withField("mytuple_withlist", firstNested) - .build(); - - verifySerDeBinary( - type2.newValue( - 1, - "2", - type1.newValue(3, "4"), - ImmutableList.of(5L), - firstNested.newValue("6", secondNested.newValue(7L, ImmutableList.of(8L))))); - - UserDefinedType type3 = - new UserDefinedTypeBuilder("ks", "udt3") - .withField("a", listOf(INT)) - .withField("b", setOf(FLOAT)) - .withField("c", mapOf(TEXT, BIGINT)) - .withField("d", listOf(listOf(DOUBLE))) - .withField("e", setOf(setOf(FLOAT))) - .withField("f", listOf(tupleOf(INT, TEXT))) - .build(); - - verifySerDeBinary( - type3.newValue( - ImmutableList.of(1), - ImmutableSet.of(2.1f), - ImmutableMap.of("3", 4L), - ImmutableList.of(ImmutableList.of(5.1d, 6.1d), ImmutableList.of(7.1d)), - ImmutableSet.of(ImmutableSet.of(8.1f), ImmutableSet.of(9.1f)), - ImmutableList.of(tupleOf(INT, TEXT).newValue(10, "11")))); - } - - @Test - public void complexTypesAndGeoTests() throws IOException { - - TupleType tuple = tupleOf(DseDataTypes.POINT, DseDataTypes.LINE_STRING, DseDataTypes.POLYGON); - tuple.attach(context); - - verifySerDeBinary( - tuple.newValue( - Point.fromCoordinates(3.3, 4.4), - LineString.fromPoints( - Point.fromCoordinates(1, 1), - Point.fromCoordinates(2, 2), - Point.fromCoordinates(3, 3)), - Polygon.fromPoints( - Point.fromCoordinates(3, 4), - Point.fromCoordinates(5, 4), - Point.fromCoordinates(6, 6)))); - - UserDefinedType udt = - new UserDefinedTypeBuilder("ks", "udt1") - .withField("a", DseDataTypes.POINT) - .withField("b", DseDataTypes.LINE_STRING) - .withField("c", DseDataTypes.POLYGON) - .build(); - udt.attach(context); - - verifySerDeBinary( - udt.newValue( - Point.fromCoordinates(3.3, 4.4), - LineString.fromPoints( - Point.fromCoordinates(1, 1), - Point.fromCoordinates(2, 2), - Point.fromCoordinates(3, 3)), - Polygon.fromPoints( - Point.fromCoordinates(3, 4), - Point.fromCoordinates(5, 4), - Point.fromCoordinates(6, 6)))); - } - - private void verifySerDeBinary(Object input) throws IOException { - Buffer result = graphBinaryModule.serialize(input); - Object deserialized = graphBinaryModule.deserialize(result); - result.release(); - assertThat(deserialized).isEqualTo(input); - } - - private void verifySerDeGraphson(Object input, GraphProtocol protocol) throws IOException { - ByteBuffer buffer = GraphSONUtils.serializeToByteBuffer(input, protocol); - Object deserialized = deserializeGraphson(buffer, protocol, input.getClass()); - - Object expected = (input instanceof Set) ? ImmutableList.copyOf((Set) input) : input; - assertThat(deserialized).isEqualTo(expected); - } - - private Object deserializeGraphson( - ByteBuffer buffer, GraphProtocol protocol, Class expectedClass) throws IOException { - List data = ImmutableList.of(buffer); - GraphNode node = GraphSONUtils.createGraphNode(data, protocol); - return node.as(expectedClass); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphRequestProcessorTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphRequestProcessorTest.java deleted file mode 100644 index 324c4ff4672..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/reactive/ReactiveGraphRequestProcessorTest.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.reactive; - -import static com.datastax.dse.driver.api.core.DseProtocolVersion.DSE_V1; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.createGraphBinaryModule; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.defaultDseFrameOf; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.tenGraphRows; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.DseTestDataProviders; -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.api.core.graph.reactive.ReactiveGraphNode; -import com.datastax.dse.driver.api.core.graph.reactive.ReactiveGraphResultSet; -import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousCqlRequestHandlerTestBase; -import com.datastax.dse.driver.internal.core.graph.GraphProtocol; -import com.datastax.dse.driver.internal.core.graph.GraphRequestAsyncProcessor; -import com.datastax.dse.driver.internal.core.graph.GraphRequestHandlerTestHarness; -import com.datastax.dse.driver.internal.core.graph.GraphSupportChecker; -import com.datastax.dse.driver.internal.core.graph.binary.GraphBinaryModule; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; -import com.datastax.oss.driver.internal.core.cql.PoolBehavior; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import io.reactivex.Flowable; -import java.io.IOException; -import java.util.List; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -public class ReactiveGraphRequestProcessorTest extends ContinuousCqlRequestHandlerTestBase { - - private GraphRequestAsyncProcessor asyncProcessor; - private GraphSupportChecker graphSupportChecker; - - @Before - public void setUp() { - DefaultDriverContext context = mock(DefaultDriverContext.class); - graphSupportChecker = mock(GraphSupportChecker.class); - asyncProcessor = Mockito.spy(new GraphRequestAsyncProcessor(context, graphSupportChecker)); - } - - @Test - public void should_be_able_to_process_graph_reactive_result_set() { - ReactiveGraphRequestProcessor processor = new ReactiveGraphRequestProcessor(asyncProcessor); - assertThat( - processor.canProcess( - ScriptGraphStatement.newInstance("g.V()"), - ReactiveGraphRequestProcessor.REACTIVE_GRAPH_RESULT_SET)) - .isTrue(); - } - - @Test - public void should_create_reactive_result_set() { - GraphRequestHandlerTestHarness.Builder builder = - GraphRequestHandlerTestHarness.builder().withProtocolVersion(DSE_V1); - try (GraphRequestHandlerTestHarness harness = builder.build()) { - ReactiveGraphRequestProcessor processor = new ReactiveGraphRequestProcessor(asyncProcessor); - GraphStatement graphStatement = ScriptGraphStatement.newInstance("g.V()"); - assertThat( - processor.process(graphStatement, harness.getSession(), harness.getContext(), "test")) - .isInstanceOf(DefaultReactiveGraphResultSet.class); - } - } - - @Test - @UseDataProvider( - value = "allDseProtocolVersionsAndSupportedGraphProtocols", - location = DseTestDataProviders.class) - public void should_complete_single_page_result( - DseProtocolVersion version, GraphProtocol graphProtocol) throws IOException { - when(graphSupportChecker.isPagingEnabled(any(), any())).thenReturn(false); - when(graphSupportChecker.inferGraphProtocol(any(), any(), any())).thenReturn(graphProtocol); - - GraphRequestHandlerTestHarness.Builder builder = - GraphRequestHandlerTestHarness.builder().withProtocolVersion(version); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (GraphRequestHandlerTestHarness harness = builder.build()) { - - DefaultSession session = harness.getSession(); - DefaultDriverContext context = harness.getContext(); - GraphStatement graphStatement = ScriptGraphStatement.newInstance("g.V()"); - - GraphBinaryModule graphBinaryModule = createGraphBinaryModule(context); - when(asyncProcessor.getGraphBinaryModule()).thenReturn(graphBinaryModule); - - ReactiveGraphResultSet publisher = - new ReactiveGraphRequestProcessor(asyncProcessor) - .process(graphStatement, session, context, "test"); - - Flowable rowsPublisher = Flowable.fromPublisher(publisher).cache(); - rowsPublisher.subscribe(); - - // emulate single page - node1Behavior.setResponseSuccess( - defaultDseFrameOf(tenGraphRows(graphProtocol, graphBinaryModule, 1, true))); - - List rows = rowsPublisher.toList().blockingGet(); - - assertThat(rows).hasSize(10); - checkResultSet(rows); - - Flowable execInfosFlowable = - Flowable.fromPublisher(publisher.getExecutionInfos()); - assertThat(execInfosFlowable.toList().blockingGet()) - .hasSize(1) - .containsExactly(rows.get(0).getExecutionInfo()); - } - } - - @Test - @UseDataProvider( - value = "allDseProtocolVersionsAndSupportedGraphProtocols", - location = DseTestDataProviders.class) - public void should_complete_multi_page_result( - DseProtocolVersion version, GraphProtocol graphProtocol) throws IOException { - when(graphSupportChecker.isPagingEnabled(any(), any())).thenReturn(true); - when(graphSupportChecker.inferGraphProtocol(any(), any(), any())).thenReturn(graphProtocol); - - GraphRequestHandlerTestHarness.Builder builder = - GraphRequestHandlerTestHarness.builder().withProtocolVersion(version); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (GraphRequestHandlerTestHarness harness = builder.build()) { - - DefaultSession session = harness.getSession(); - DefaultDriverContext context = harness.getContext(); - GraphStatement graphStatement = ScriptGraphStatement.newInstance("g.V()"); - - GraphBinaryModule graphBinaryModule = createGraphBinaryModule(context); - when(asyncProcessor.getGraphBinaryModule()).thenReturn(graphBinaryModule); - - ReactiveGraphResultSet publisher = - new ReactiveGraphRequestProcessor(asyncProcessor) - .process(graphStatement, session, context, "test"); - - Flowable rowsPublisher = Flowable.fromPublisher(publisher).cache(); - rowsPublisher.subscribe(); - - // emulate page 1 - node1Behavior.setResponseSuccess( - defaultDseFrameOf(tenGraphRows(graphProtocol, graphBinaryModule, 1, false))); - // emulate page 2 - node1Behavior.setResponseSuccess( - defaultDseFrameOf(tenGraphRows(graphProtocol, graphBinaryModule, 2, true))); - - List rows = rowsPublisher.toList().blockingGet(); - assertThat(rows).hasSize(20); - checkResultSet(rows); - - Flowable execInfosFlowable = - Flowable.fromPublisher(publisher.getExecutionInfos()); - assertThat(execInfosFlowable.toList().blockingGet()) - .hasSize(2) - .containsExactly(rows.get(0).getExecutionInfo(), rows.get(10).getExecutionInfo()); - } - } - - private void checkResultSet(List rows) { - for (ReactiveGraphNode row : rows) { - assertThat(row.isVertex()).isTrue(); - ExecutionInfo executionInfo = row.getExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node1); - assertThat(executionInfo.getErrors()).isEmpty(); - assertThat(executionInfo.getIncomingPayload()).isEmpty(); - assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(executionInfo.getWarnings()).isEmpty(); - } - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/schema/refresh/GraphSchemaRefreshTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/graph/schema/refresh/GraphSchemaRefreshTest.java deleted file mode 100644 index 0d05f129520..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/graph/schema/refresh/GraphSchemaRefreshTest.java +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.graph.schema.refresh; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.api.core.metadata.schema.DseEdgeMetadata; -import com.datastax.dse.driver.api.core.metadata.schema.DseGraphTableMetadata; -import com.datastax.dse.driver.api.core.metadata.schema.DseVertexMetadata; -import com.datastax.dse.driver.internal.core.metadata.schema.DefaultDseEdgeMetadata; -import com.datastax.dse.driver.internal.core.metadata.schema.DefaultDseKeyspaceMetadata; -import com.datastax.dse.driver.internal.core.metadata.schema.DefaultDseTableMetadata; -import com.datastax.dse.driver.internal.core.metadata.schema.DefaultDseVertexMetadata; -import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.metadata.schema.ColumnMetadata; -import com.datastax.oss.driver.api.core.metadata.schema.TableMetadata; -import com.datastax.oss.driver.api.core.type.DataTypes; -import com.datastax.oss.driver.internal.core.channel.ChannelFactory; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.metadata.DefaultMetadata; -import com.datastax.oss.driver.internal.core.metadata.MetadataRefresh; -import com.datastax.oss.driver.internal.core.metadata.schema.DefaultColumnMetadata; -import com.datastax.oss.driver.internal.core.metadata.schema.events.KeyspaceChangeEvent; -import com.datastax.oss.driver.internal.core.metadata.schema.events.TableChangeEvent; -import com.datastax.oss.driver.internal.core.metadata.schema.refresh.SchemaRefresh; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Collections; -import java.util.Map; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class GraphSchemaRefreshTest { - - private static final DefaultDseTableMetadata OLD_TABLE = - newTable( - CqlIdentifier.fromInternal("ks_with_engine"), - CqlIdentifier.fromInternal("tbl"), - null, - null); - private static final DefaultDseKeyspaceMetadata OLD_KS1 = newKeyspace("ks1", null); - private static final DefaultDseKeyspaceMetadata KS_WITH_ENGINE = - newKeyspace( - CqlIdentifier.fromInternal("ks_with_engine"), - "Core", - ImmutableMap.of(CqlIdentifier.fromInternal("tbl"), OLD_TABLE)); - - @Mock private InternalDriverContext context; - @Mock private ChannelFactory channelFactory; - private DefaultMetadata oldMetadata; - - @Before - public void setup() { - when(context.getChannelFactory()).thenReturn(channelFactory); - oldMetadata = - DefaultMetadata.EMPTY.withSchema( - ImmutableMap.of(OLD_KS1.getName(), OLD_KS1, KS_WITH_ENGINE.getName(), KS_WITH_ENGINE), - false, - context); - } - - @Test - public void should_detect_created_keyspace_without_graph_engine() { - DefaultDseKeyspaceMetadata ks2 = newKeyspace("ks2", null); - SchemaRefresh refresh = - new SchemaRefresh( - ImmutableMap.of( - OLD_KS1.getName(), - OLD_KS1, - KS_WITH_ENGINE.getName(), - KS_WITH_ENGINE, - ks2.getName(), - ks2)); - MetadataRefresh.Result result = refresh.compute(oldMetadata, false, context); - assertThat(result.newMetadata.getKeyspaces()).hasSize(3); - assertThat(result.events).containsExactly(KeyspaceChangeEvent.created(ks2)); - } - - @Test - public void should_detect_created_keyspace_with_graph_engine() { - DefaultDseKeyspaceMetadata ks2 = newKeyspace("ks2", "Core"); - SchemaRefresh refresh = - new SchemaRefresh( - ImmutableMap.of( - OLD_KS1.getName(), - OLD_KS1, - KS_WITH_ENGINE.getName(), - KS_WITH_ENGINE, - ks2.getName(), - ks2)); - MetadataRefresh.Result result = refresh.compute(oldMetadata, false, context); - assertThat(result.newMetadata.getKeyspaces()).hasSize(3); - assertThat(result.events).containsExactly(KeyspaceChangeEvent.created(ks2)); - } - - @Test - public void should_detect_top_level_graph_engine_update_in_keyspace() { - // Change only one top-level option (graph_engine) - DefaultDseKeyspaceMetadata newKs1 = newKeyspace("ks1", "Core"); - SchemaRefresh refresh = - new SchemaRefresh( - ImmutableMap.of(KS_WITH_ENGINE.getName(), KS_WITH_ENGINE, OLD_KS1.getName(), newKs1)); - MetadataRefresh.Result result = refresh.compute(oldMetadata, false, context); - assertThat(result.newMetadata.getKeyspaces()).hasSize(2); - assertThat(result.events).containsExactly(KeyspaceChangeEvent.updated(OLD_KS1, newKs1)); - } - - @Test - public void should_detect_adding_and_renaming_and_removing_vertex_label() { - DefaultDseTableMetadata newTable = - newTable( - KS_WITH_ENGINE.getName(), - CqlIdentifier.fromInternal("tbl"), - new DefaultDseVertexMetadata(CqlIdentifier.fromInternal("someLabel")), - null); - DefaultDseKeyspaceMetadata ks = - newKeyspace( - KS_WITH_ENGINE.getName(), - "Core", - ImmutableMap.of(CqlIdentifier.fromInternal("tbl"), newTable)); - SchemaRefresh refresh = - new SchemaRefresh( - ImmutableMap.of(KS_WITH_ENGINE.getName(), ks, OLD_KS1.getName(), OLD_KS1)); - MetadataRefresh.Result result = refresh.compute(oldMetadata, false, context); - assertThat(result.newMetadata.getKeyspaces()).hasSize(2); - assertThat(result.events).containsExactly(TableChangeEvent.updated(OLD_TABLE, newTable)); - assertThat(result.newMetadata.getKeyspaces().get(KS_WITH_ENGINE.getName())).isNotNull(); - assertThat( - ((DseGraphTableMetadata) - result - .newMetadata - .getKeyspaces() - .get(KS_WITH_ENGINE.getName()) - .getTable("tbl") - .get()) - .getVertex()) - .isNotNull(); - assertThat( - ((DseGraphTableMetadata) - result - .newMetadata - .getKeyspaces() - .get(KS_WITH_ENGINE.getName()) - .getTable("tbl") - .get()) - .getVertex() - .get() - .getLabelName() - .asInternal()) - .isEqualTo("someLabel"); - - // now rename the vertex label - newTable = - newTable( - KS_WITH_ENGINE.getName(), - CqlIdentifier.fromInternal("tbl"), - new DefaultDseVertexMetadata(CqlIdentifier.fromInternal("someNewLabel")), - null); - ks = - newKeyspace( - KS_WITH_ENGINE.getName(), - "Core", - ImmutableMap.of(CqlIdentifier.fromInternal("tbl"), newTable)); - refresh = - new SchemaRefresh( - ImmutableMap.of(KS_WITH_ENGINE.getName(), ks, OLD_KS1.getName(), OLD_KS1)); - result = refresh.compute(oldMetadata, false, context); - assertThat(result.newMetadata.getKeyspaces()).hasSize(2); - assertThat(result.events).containsExactly(TableChangeEvent.updated(OLD_TABLE, newTable)); - assertThat( - ((DseGraphTableMetadata) - result - .newMetadata - .getKeyspaces() - .get(KS_WITH_ENGINE.getName()) - .getTable("tbl") - .get()) - .getVertex() - .get() - .getLabelName() - .asInternal()) - .isEqualTo("someNewLabel"); - - // now remove the vertex label from the table - DefaultMetadata metadataWithVertexLabel = result.newMetadata; - DefaultDseTableMetadata tableWithRemovedLabel = - newTable(KS_WITH_ENGINE.getName(), CqlIdentifier.fromInternal("tbl"), null, null); - ks = - newKeyspace( - KS_WITH_ENGINE.getName(), - "Core", - ImmutableMap.of(CqlIdentifier.fromInternal("tbl"), tableWithRemovedLabel)); - refresh = - new SchemaRefresh( - ImmutableMap.of(KS_WITH_ENGINE.getName(), ks, OLD_KS1.getName(), OLD_KS1)); - result = refresh.compute(metadataWithVertexLabel, false, context); - assertThat(result.newMetadata.getKeyspaces()).hasSize(2); - assertThat(result.events) - .containsExactly(TableChangeEvent.updated(newTable, tableWithRemovedLabel)); - assertThat( - ((DseGraphTableMetadata) - result - .newMetadata - .getKeyspaces() - .get(KS_WITH_ENGINE.getName()) - .getTable("tbl") - .get()) - .getVertex() - .isPresent()) - .isFalse(); - } - - @Test - public void should_detect_adding_and_renaming_and_removing_edge_label() { - DefaultDseTableMetadata newTable = - newTable( - KS_WITH_ENGINE.getName(), - CqlIdentifier.fromInternal("tbl"), - null, - newEdgeMetadata( - CqlIdentifier.fromInternal("created"), - CqlIdentifier.fromInternal("person"), - CqlIdentifier.fromInternal("software"))); - DefaultDseKeyspaceMetadata ks = - newKeyspace( - KS_WITH_ENGINE.getName(), - "Core", - ImmutableMap.of(CqlIdentifier.fromInternal("tbl"), newTable)); - SchemaRefresh refresh = - new SchemaRefresh( - ImmutableMap.of(KS_WITH_ENGINE.getName(), ks, OLD_KS1.getName(), OLD_KS1)); - MetadataRefresh.Result result = refresh.compute(oldMetadata, false, context); - assertThat(result.newMetadata.getKeyspaces()).hasSize(2); - assertThat(result.events).containsExactly(TableChangeEvent.updated(OLD_TABLE, newTable)); - assertThat(result.newMetadata.getKeyspaces().get(KS_WITH_ENGINE.getName())).isNotNull(); - assertThat( - ((DseGraphTableMetadata) - result - .newMetadata - .getKeyspaces() - .get(KS_WITH_ENGINE.getName()) - .getTable("tbl") - .get()) - .getVertex()) - .isNotNull(); - assertThat( - ((DseGraphTableMetadata) - result - .newMetadata - .getKeyspaces() - .get(KS_WITH_ENGINE.getName()) - .getTable("tbl") - .get()) - .getEdge() - .get() - .getLabelName() - .asInternal()) - .isEqualTo("created"); - - // now rename the edge label - newTable = - newTable( - KS_WITH_ENGINE.getName(), - CqlIdentifier.fromInternal("tbl"), - null, - newEdgeMetadata( - CqlIdentifier.fromInternal("CHANGED"), - CqlIdentifier.fromInternal("person"), - CqlIdentifier.fromInternal("software"))); - ks = - newKeyspace( - KS_WITH_ENGINE.getName(), - "Core", - ImmutableMap.of(CqlIdentifier.fromInternal("tbl"), newTable)); - refresh = - new SchemaRefresh( - ImmutableMap.of(KS_WITH_ENGINE.getName(), ks, OLD_KS1.getName(), OLD_KS1)); - result = refresh.compute(oldMetadata, false, context); - assertThat(result.newMetadata.getKeyspaces()).hasSize(2); - assertThat(result.events).containsExactly(TableChangeEvent.updated(OLD_TABLE, newTable)); - assertThat( - ((DseGraphTableMetadata) - result - .newMetadata - .getKeyspaces() - .get(KS_WITH_ENGINE.getName()) - .getTable("tbl") - .get()) - .getEdge() - .get() - .getLabelName() - .asInternal()) - .isEqualTo("CHANGED"); - - // now remove the edge label from the table - DefaultMetadata metadataWithEdgeLabel = result.newMetadata; - DefaultDseTableMetadata tableWithRemovedLabel = - newTable(KS_WITH_ENGINE.getName(), CqlIdentifier.fromInternal("tbl"), null, null); - ks = - newKeyspace( - KS_WITH_ENGINE.getName(), - "Core", - ImmutableMap.of(CqlIdentifier.fromInternal("tbl"), tableWithRemovedLabel)); - refresh = - new SchemaRefresh( - ImmutableMap.of(KS_WITH_ENGINE.getName(), ks, OLD_KS1.getName(), OLD_KS1)); - result = refresh.compute(metadataWithEdgeLabel, false, context); - assertThat(result.newMetadata.getKeyspaces()).hasSize(2); - assertThat(result.events) - .containsExactly(TableChangeEvent.updated(newTable, tableWithRemovedLabel)); - assertThat( - ((DseGraphTableMetadata) - result - .newMetadata - .getKeyspaces() - .get(KS_WITH_ENGINE.getName()) - .getTable("tbl") - .get()) - .getEdge() - .isPresent()) - .isFalse(); - } - - private static DefaultDseKeyspaceMetadata newKeyspace(String name, String graphEngine) { - return new DefaultDseKeyspaceMetadata( - CqlIdentifier.fromInternal(name), - false, - false, - graphEngine, - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap()); - } - - private static DefaultDseKeyspaceMetadata newKeyspace( - CqlIdentifier name, String graphEngine, @NonNull Map tables) { - return new DefaultDseKeyspaceMetadata( - name, - false, - false, - graphEngine, - Collections.emptyMap(), - Collections.emptyMap(), - tables, - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap()); - } - - private static DefaultDseTableMetadata newTable( - @NonNull CqlIdentifier keyspace, - @NonNull CqlIdentifier name, - @Nullable DseVertexMetadata vertex, - @Nullable DseEdgeMetadata edge) { - ImmutableList cols = - ImmutableList.of( - new DefaultColumnMetadata( - keyspace, - CqlIdentifier.fromInternal("parent"), - CqlIdentifier.fromInternal("id"), - DataTypes.INT, - false)); - return new DefaultDseTableMetadata( - keyspace, - name, - null, - false, - false, - cols, - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - vertex, - edge); - } - - private static DefaultDseEdgeMetadata newEdgeMetadata( - @NonNull CqlIdentifier labelName, - @NonNull CqlIdentifier fromTable, - @NonNull CqlIdentifier toTable) { - return new DefaultDseEdgeMetadata( - labelName, - fromTable, - fromTable, - Collections.emptyList(), - Collections.emptyList(), - toTable, - toTable, - Collections.emptyList(), - Collections.emptyList()); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfileMockUtil.java b/core/src/test/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfileMockUtil.java index de0f3a9d60b..11dd1fbbf4c 100644 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfileMockUtil.java +++ b/core/src/test/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfileMockUtil.java @@ -17,7 +17,6 @@ */ package com.datastax.dse.driver.internal.core.insights; -import static com.datastax.dse.driver.api.core.config.DseDriverOption.GRAPH_TRAVERSAL_SOURCE; import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.AUTH_PROVIDER_CLASS; import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE; import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.CONNECTION_POOL_REMOTE_SIZE; @@ -70,7 +69,6 @@ static DriverExecutionProfile mockDefaultExecutionProfile() { when(profile.getDuration(RECONNECTION_BASE_DELAY)).thenReturn(Duration.ofMillis(100)); when(profile.isDefined(SSL_ENGINE_FACTORY_CLASS)).thenReturn(true); when(profile.getString(eq(AUTH_PROVIDER_CLASS), any())).thenReturn("AuthProviderImpl"); - when(profile.getString(GRAPH_TRAVERSAL_SOURCE, null)).thenReturn("src-graph"); return profile; } @@ -110,10 +108,4 @@ static DriverExecutionProfile mockNonDefaultSerialConsistency() { when(profile.getString(REQUEST_SERIAL_CONSISTENCY)).thenReturn("ONE"); return profile; } - - static DriverExecutionProfile mockNonDefaultGraphOptions() { - DriverExecutionProfile profile = mockDefaultExecutionProfile(); - when(profile.getString(GRAPH_TRAVERSAL_SOURCE, null)).thenReturn("non-default-graph"); - return profile; - } } diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfilesInfoFinderTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfilesInfoFinderTest.java index fc92ab20521..a0c972f368f 100644 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfilesInfoFinderTest.java +++ b/core/src/test/java/com/datastax/dse/driver/internal/core/insights/ExecutionProfilesInfoFinderTest.java @@ -22,7 +22,6 @@ import static com.datastax.dse.driver.internal.core.insights.ExecutionProfileMockUtil.SPECEX_MAX_DEFAULT; import static com.datastax.dse.driver.internal.core.insights.ExecutionProfileMockUtil.mockDefaultExecutionProfile; import static com.datastax.dse.driver.internal.core.insights.ExecutionProfileMockUtil.mockNonDefaultConsistency; -import static com.datastax.dse.driver.internal.core.insights.ExecutionProfileMockUtil.mockNonDefaultGraphOptions; import static com.datastax.dse.driver.internal.core.insights.ExecutionProfileMockUtil.mockNonDefaultLoadBalancingExecutionProfile; import static com.datastax.dse.driver.internal.core.insights.ExecutionProfileMockUtil.mockNonDefaultRequestTimeoutExecutionProfile; import static com.datastax.dse.driver.internal.core.insights.ExecutionProfileMockUtil.mockNonDefaultSerialConsistency; @@ -84,8 +83,7 @@ public void should_include_info_about_default_profile() { ImmutableMap.of("maxSpeculativeExecutions", 100, "delay", 20), DEFAULT_SPECULATIVE_EXECUTION_PACKAGE), "LOCAL_ONE", - "SERIAL", - ImmutableMap.of("source", "src-graph")))); + "SERIAL"))); } @Test @@ -120,8 +118,7 @@ public void should_include_info_about_default_profile_and_only_difference_for_sp ImmutableMap.of("maxSpeculativeExecutions", 100, "delay", 20), DEFAULT_SPECULATIVE_EXECUTION_PACKAGE), "LOCAL_ONE", - "SERIAL", - ImmutableMap.of("source", "src-graph")), + "SERIAL"), "non-default", expected)); } @@ -131,7 +128,7 @@ public static Object[][] executionProfileProvider() { return new Object[][] { { mockNonDefaultRequestTimeoutExecutionProfile(), - new SpecificExecutionProfile(50, null, null, null, null, null) + new SpecificExecutionProfile(50, null, null, null, null) }, { mockNonDefaultLoadBalancingExecutionProfile(), @@ -143,7 +140,6 @@ public static Object[][] executionProfileProvider() { DEFAULT_LOAD_BALANCING_PACKAGE), null, null, - null, null) }, { @@ -156,7 +152,6 @@ public static Object[][] executionProfileProvider() { DEFAULT_LOAD_BALANCING_PACKAGE), null, null, - null, null) }, { @@ -170,26 +165,14 @@ public static Object[][] executionProfileProvider() { "maxSpeculativeExecutions", SPECEX_MAX_DEFAULT, "delay", SPECEX_DELAY_DEFAULT), DEFAULT_SPECULATIVE_EXECUTION_PACKAGE), null, - null, null) }, - { - mockNonDefaultConsistency(), - new SpecificExecutionProfile(null, null, null, "ALL", null, null) - }, + {mockNonDefaultConsistency(), new SpecificExecutionProfile(null, null, null, "ALL", null)}, { mockNonDefaultSerialConsistency(), - new SpecificExecutionProfile(null, null, null, null, "ONE", null) + new SpecificExecutionProfile(null, null, null, null, "ONE") }, - { - mockNonDefaultGraphOptions(), - new SpecificExecutionProfile( - null, null, null, null, null, ImmutableMap.of("source", "non-default-graph")) - }, - { - mockDefaultExecutionProfile(), - new SpecificExecutionProfile(null, null, null, null, null, null) - } + {mockDefaultExecutionProfile(), new SpecificExecutionProfile(null, null, null, null, null)} }; } @@ -197,14 +180,13 @@ public static Object[][] executionProfileProvider() { public void should_not_include_null_fields_in_json() throws JsonProcessingException { // given SpecificExecutionProfile specificExecutionProfile = - new SpecificExecutionProfile(50, null, null, "ONE", null, ImmutableMap.of("a", "b")); + new SpecificExecutionProfile(50, null, null, "ONE", null); // when String result = new ObjectMapper().writeValueAsString(specificExecutionProfile); // then - assertThat(result) - .isEqualTo("{\"readTimeout\":50,\"consistency\":\"ONE\",\"graphOptions\":{\"a\":\"b\"}}"); + assertThat(result).isEqualTo("{\"readTimeout\":50,\"consistency\":\"ONE\"}"); } @Test @@ -212,7 +194,7 @@ public void should_include_empty_execution_profile_if_has_all_nulls() throws JsonProcessingException { // given Map executionProfiles = - ImmutableMap.of("p", new SpecificExecutionProfile(null, null, null, null, null, null)); + ImmutableMap.of("p", new SpecificExecutionProfile(null, null, null, null, null)); // when String result = new ObjectMapper().writeValueAsString(executionProfiles); diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/insights/InsightsClientTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/insights/InsightsClientTest.java index 5085432dbec..e9f878fa3f9 100644 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/insights/InsightsClientTest.java +++ b/core/src/test/java/com/datastax/dse/driver/internal/core/insights/InsightsClientTest.java @@ -190,10 +190,9 @@ public void should_construct_json_event_startup_message() throws IOException { ImmutableMap.of("maxSpeculativeExecutions", 100, "delay", 20), DEFAULT_SPECULATIVE_EXECUTION_PACKAGE), "LOCAL_ONE", - "SERIAL", - ImmutableMap.of("source", "src-graph")), + "SERIAL"), "non-default", - new SpecificExecutionProfile(50, null, null, null, null, null))); + new SpecificExecutionProfile(50, null, null, null, null))); assertThat(insightData.getPoolSizeByHostDistance()) .isEqualTo(new PoolSizeByHostDistance(2, 1, 0)); assertThat(insightData.getHeartbeatInterval()).isEqualTo(100); diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/protocol/TinkerpopBufferPrimitiveCodecTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/protocol/TinkerpopBufferPrimitiveCodecTest.java deleted file mode 100644 index 3ef89c78714..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/protocol/TinkerpopBufferPrimitiveCodecTest.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.protocol; - -import static com.datastax.dse.driver.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import com.datastax.dse.driver.Assertions; -import com.datastax.dse.driver.internal.core.graph.binary.buffer.DseNettyBufferFactory; -import com.datastax.oss.driver.internal.core.protocol.ByteBufPrimitiveCodecTest; -import com.datastax.oss.protocol.internal.util.Bytes; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.util.function.Supplier; -import org.apache.tinkerpop.gremlin.structure.io.Buffer; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Note: like {@link ByteBufPrimitiveCodecTest} we don't test trivial methods that simply delegate - * to the underlying Buffer, nor default implementations inherited from {@link - * com.datastax.oss.protocol.internal.PrimitiveCodec}. - */ -@RunWith(DataProviderRunner.class) -public class TinkerpopBufferPrimitiveCodecTest { - - private static final DseNettyBufferFactory factory = new DseNettyBufferFactory(); - private final TinkerpopBufferPrimitiveCodec codec = new TinkerpopBufferPrimitiveCodec(factory); - - @Test - public void should_concatenate() { - Buffer left = factory.withBytes(0xca, 0xfe); - Buffer right = factory.withBytes(0xba, 0xbe); - assertThat(codec.concat(left, right)).containsExactly("0xcafebabe"); - } - - @Test - public void should_read_inet_v4() { - Buffer source = - factory.withBytes( - // length (as a byte) - 0x04, - // address - 0x7f, - 0x00, - 0x00, - 0x01, - // port (as an int) - 0x00, - 0x00, - 0x23, - 0x52); - InetSocketAddress inet = codec.readInet(source); - assertThat(inet.getAddress().getHostAddress()).isEqualTo("127.0.0.1"); - assertThat(inet.getPort()).isEqualTo(9042); - } - - @Test - public void should_read_inet_v6() { - Buffer lengthAndAddress = factory.heap(17); - lengthAndAddress.writeByte(16); - lengthAndAddress.writeLong(0); - lengthAndAddress.writeLong(1); - Buffer source = - codec.concat( - lengthAndAddress, - // port (as an int) - factory.withBytes(0x00, 0x00, 0x23, 0x52)); - InetSocketAddress inet = codec.readInet(source); - assertThat(inet.getAddress().getHostAddress()).isEqualTo("0:0:0:0:0:0:0:1"); - assertThat(inet.getPort()).isEqualTo(9042); - } - - @Test - public void should_fail_to_read_inet_if_length_invalid() { - Buffer source = - factory.withBytes( - // length (as a byte) - 0x03, - // address - 0x7f, - 0x00, - 0x01, - // port (as an int) - 0x00, - 0x00, - 0x23, - 0x52); - assertThatThrownBy(() -> codec.readInet(source)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Invalid address length: 3 ([127, 0, 1])"); - } - - @Test - public void should_read_inetaddr_v4() { - Buffer source = - factory.withBytes( - // length (as a byte) - 0x04, - // address - 0x7f, - 0x00, - 0x00, - 0x01); - InetAddress inetAddr = codec.readInetAddr(source); - assertThat(inetAddr.getHostAddress()).isEqualTo("127.0.0.1"); - } - - @Test - public void should_read_inetaddr_v6() { - Buffer source = factory.heap(17); - source.writeByte(16); - source.writeLong(0); - source.writeLong(1); - InetAddress inetAddr = codec.readInetAddr(source); - assertThat(inetAddr.getHostAddress()).isEqualTo("0:0:0:0:0:0:0:1"); - } - - @Test - public void should_fail_to_read_inetaddr_if_length_invalid() { - Buffer source = - factory.withBytes( - // length (as a byte) - 0x03, - // address - 0x7f, - 0x00, - 0x01); - assertThatThrownBy(() -> codec.readInetAddr(source)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Invalid address length: 3 ([127, 0, 1])"); - } - - @Test - public void should_read_bytes() { - Buffer source = - factory.withBytes( - // length (as an int) - 0x00, - 0x00, - 0x00, - 0x04, - // contents - 0xca, - 0xfe, - 0xba, - 0xbe); - ByteBuffer bytes = codec.readBytes(source); - assertThat(Bytes.toHexString(bytes)).isEqualTo("0xcafebabe"); - } - - @Test - public void should_read_null_bytes() { - Buffer source = factory.withBytes(0xFF, 0xFF, 0xFF, 0xFF); // -1 (as an int) - assertThat(codec.readBytes(source)).isNull(); - } - - @Test - public void should_read_short_bytes() { - Buffer source = - factory.withBytes( - // length (as an unsigned short) - 0x00, - 0x04, - // contents - 0xca, - 0xfe, - 0xba, - 0xbe); - assertThat(Bytes.toHexString(codec.readShortBytes(source))).isEqualTo("0xcafebabe"); - } - - @DataProvider - public static Object[][] bufferTypes() { - return new Object[][] { - {(Supplier) factory::heap}, - {(Supplier) factory::io}, - {(Supplier) factory::direct} - }; - } - - @Test - @UseDataProvider("bufferTypes") - public void should_read_string(Supplier supplier) { - Buffer source = - factory.withBytes( - supplier, - // length (as an unsigned short) - 0x00, - 0x05, - // UTF-8 contents - 0x68, - 0x65, - 0x6c, - 0x6c, - 0x6f); - assertThat(codec.readString(source)).isEqualTo("hello"); - } - - @Test - public void should_fail_to_read_string_if_not_enough_characters() { - Buffer source = factory.heap(); - source.writeShort(4); - - assertThatThrownBy(() -> codec.readString(source)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Not enough bytes to read an UTF-8 serialized string of size 4"); - } - - @Test - public void should_read_long_string() { - Buffer source = - factory.withBytes( - // length (as an int) - 0x00, - 0x00, - 0x00, - 0x05, - // UTF-8 contents - 0x68, - 0x65, - 0x6c, - 0x6c, - 0x6f); - assertThat(codec.readLongString(source)).isEqualTo("hello"); - } - - @Test - public void should_fail_to_read_long_string_if_not_enough_characters() { - Buffer source = factory.heap(4, 4); - source.writeInt(4); - - assertThatThrownBy(() -> codec.readLongString(source)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Not enough bytes to read an UTF-8 serialized string of size 4"); - } - - @Test - public void should_write_inet_v4() throws Exception { - Buffer dest = factory.heap(1 + 4 + 4); - InetSocketAddress inet = new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9042); - codec.writeInet(inet, dest); - assertThat(dest) - .containsExactly( - "0x04" // size as a byte - + "7f000001" // address - + "00002352" // port - ); - } - - @Test - public void should_write_inet_v6() throws Exception { - Buffer dest = factory.heap(1 + 16 + 4); - InetSocketAddress inet = new InetSocketAddress(InetAddress.getByName("::1"), 9042); - codec.writeInet(inet, dest); - assertThat(dest) - .containsExactly( - "0x10" // size as a byte - + "00000000000000000000000000000001" // address - + "00002352" // port - ); - } - - @Test - public void should_write_inetaddr_v4() throws Exception { - Buffer dest = factory.heap(1 + 4); - InetAddress inetAddr = InetAddress.getByName("127.0.0.1"); - codec.writeInetAddr(inetAddr, dest); - assertThat(dest) - .containsExactly( - "0x04" // size as a byte - + "7f000001" // address - ); - } - - @Test - public void should_write_inetaddr_v6() throws Exception { - Buffer dest = factory.heap(1 + 16); - InetAddress inetAddr = InetAddress.getByName("::1"); - codec.writeInetAddr(inetAddr, dest); - Assertions.assertThat(dest) - .containsExactly( - "0x10" // size as a byte - + "00000000000000000000000000000001" // address - ); - } - - @Test - public void should_write_string() { - Buffer dest = factory.heap(); - codec.writeString("hello", dest); - assertThat(dest) - .containsExactly( - "0x0005" // size as an unsigned short - + "68656c6c6f" // UTF-8 contents - ); - } - - @Test - public void should_write_long_string() { - Buffer dest = factory.heap(9); - codec.writeLongString("hello", dest); - assertThat(dest) - .containsExactly( - "0x00000005" - + // size as an int - "68656c6c6f" // UTF-8 contents - ); - } - - @Test - public void should_write_bytes() { - Buffer dest = factory.heap(8); - codec.writeBytes(Bytes.fromHexString("0xcafebabe"), dest); - assertThat(dest) - .containsExactly( - "0x00000004" - + // size as an int - "cafebabe"); - } - - @Test - public void should_write_short_bytes() { - Buffer dest = factory.heap(6); - codec.writeShortBytes(new byte[] {(byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe}, dest); - assertThat(dest) - .containsExactly( - "0x0004" - + // size as an unsigned short - "cafebabe"); - } - - @Test - public void should_write_null_bytes() { - Buffer dest = factory.heap(4); - codec.writeBytes((ByteBuffer) null, dest); - assertThat(dest).containsExactly("0xFFFFFFFF"); - } -} diff --git a/distribution/pom.xml b/distribution/pom.xml index e3787c136d5..a04dbde8075 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -145,21 +145,6 @@ snappy-java ${snappy.version} - - org.apache.tinkerpop - gremlin-core - ${tinkerpop.version} - - - org.apache.tinkerpop - tinkergraph-gremlin - ${tinkerpop.version} - - - org.javatuples - javatuples - 1.2 - diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 7f481242fce..51e60393e92 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -133,16 +133,6 @@ rxjava test - - org.apache.tinkerpop - gremlin-core - test - - - org.apache.tinkerpop - tinkergraph-gremlin - test - org.apache.directory.server apacheds-core @@ -236,7 +226,7 @@ -processor - com.datastax.oss.driver.internal.mapper.processor.MapperProcessor,com.datastax.oss.driver.internal.gremlin.PatchedGremlinDslProcessor + com.datastax.oss.driver.internal.mapper.processor.MapperProcessor @@ -244,11 +234,6 @@ error_prone_core 2.31.0 - - com.scylladb - java-driver-test-infra - ${project.version} - com.scylladb java-driver-mapper-processor @@ -259,11 +244,6 @@ java-driver-mapper-runtime ${project.version} - - org.apache.tinkerpop - gremlin-core - ${tinkerpop.version} - diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphDataTypeITBase.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphDataTypeITBase.java deleted file mode 100644 index d42b156a8be..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphDataTypeITBase.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static com.datastax.dse.driver.api.core.graph.TinkerGraphAssertions.assertThat; - -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.Version; -import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.datastax.oss.driver.shaded.guava.common.base.Charsets; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableSet; -import com.datastax.oss.driver.shaded.guava.common.net.InetAddresses; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalTime; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicInteger; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.junit.AssumptionViolatedException; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(DataProviderRunner.class) -public abstract class ClassicGraphDataTypeITBase { - - private static final boolean IS_DSE50 = - CcmBridge.VERSION.compareTo(Objects.requireNonNull(Version.parse("5.1"))) < 0; - private static final Set TYPES_REQUIRING_DSE51 = - ImmutableSet.of("Date()", "Time()", "Point()", "Linestring()", "Polygon()"); - - private static final AtomicInteger SCHEMA_COUNTER = new AtomicInteger(); - - @DataProvider - public static Object[][] typeSamples() { - return new Object[][] { - // Types that DSE supports. - {"Boolean()", true}, - {"Boolean()", false}, - {"Smallint()", Short.MAX_VALUE}, - {"Smallint()", Short.MIN_VALUE}, - {"Smallint()", (short) 0}, - {"Smallint()", (short) 42}, - {"Int()", Integer.MAX_VALUE}, - {"Int()", Integer.MIN_VALUE}, - {"Int()", 0}, - {"Int()", 42}, - {"Bigint()", Long.MAX_VALUE}, - {"Bigint()", Long.MIN_VALUE}, - {"Bigint()", 0L}, - {"Double()", Double.MAX_VALUE}, - {"Double()", Double.MIN_VALUE}, - {"Double()", 0.0d}, - {"Double()", Math.PI}, - {"Float()", Float.MAX_VALUE}, - {"Float()", Float.MIN_VALUE}, - {"Float()", 0.0f}, - {"Text()", ""}, - {"Text()", "75"}, - {"Text()", "Lorem Ipsum"}, - // Inet, UUID, Date - {"Inet()", InetAddresses.forString("127.0.0.1")}, - {"Inet()", InetAddresses.forString("0:0:0:0:0:0:0:1")}, - {"Inet()", InetAddresses.forString("2001:db8:85a3:0:0:8a2e:370:7334")}, - {"Uuid()", UUID.randomUUID()}, - // Timestamps - {"Timestamp()", Instant.ofEpochMilli(123)}, - {"Timestamp()", Instant.ofEpochMilli(1488313909)}, - {"Duration()", java.time.Duration.parse("P2DT3H4M")}, - {"Date()", LocalDate.of(2016, 5, 12)}, - {"Time()", LocalTime.parse("18:30:41.554")}, - {"Time()", LocalTime.parse("18:30:41.554010034")}, - // Blob - {"Blob()", "Hello World!".getBytes(Charsets.UTF_8)}, - // BigDecimal/BigInteger - {"Decimal()", new BigDecimal("8675309.9998")}, - {"Varint()", new BigInteger("8675309")}, - // Geospatial types - {"Point().withBounds(-2, -2, 2, 2)", Point.fromCoordinates(0, 1)}, - {"Point().withBounds(-40, -40, 40, 40)", Point.fromCoordinates(-5, 20)}, - { - "Linestring().withGeoBounds()", - LineString.fromPoints( - Point.fromCoordinates(30, 10), - Point.fromCoordinates(10, 30), - Point.fromCoordinates(40, 40)) - }, - { - "Polygon().withGeoBounds()", - Polygon.builder() - .addRing( - Point.fromCoordinates(35, 10), - Point.fromCoordinates(45, 45), - Point.fromCoordinates(15, 40), - Point.fromCoordinates(10, 20), - Point.fromCoordinates(35, 10)) - .addRing( - Point.fromCoordinates(20, 30), - Point.fromCoordinates(35, 35), - Point.fromCoordinates(30, 20), - Point.fromCoordinates(20, 30)) - .build() - } - }; - } - - @UseDataProvider("typeSamples") - @Test - public void should_create_and_retrieve_vertex_property_with_correct_type( - String type, Object value) { - if (IS_DSE50 && requiresDse51(type)) { - throw new AssumptionViolatedException(type + " not supported in DSE " + CcmBridge.VERSION); - } - - int id = SCHEMA_COUNTER.getAndIncrement(); - - String vertexLabel = "vertex" + id; - String propertyName = "prop" + id; - GraphStatement addVertexLabelAndProperty = - ScriptGraphStatement.builder( - "schema.propertyKey(property)." - + type - + ".create()\n" - + "schema.vertexLabel(vertexLabel).properties(property).create()") - .setQueryParam("vertexLabel", vertexLabel) - .setQueryParam("property", propertyName) - .build(); - - session().execute(addVertexLabelAndProperty); - - Vertex v = insertVertexAndReturn(vertexLabel, propertyName, value); - - assertThat(v).hasProperty(propertyName, value); - } - - private boolean requiresDse51(String type) { - for (String prefix : TYPES_REQUIRING_DSE51) { - if (type.startsWith(prefix)) { - return true; - } - } - return false; - } - - public abstract Vertex insertVertexAndReturn( - String vertexLabel, String propertyName, Object value); - - /** - * Note that the {@link SessionRule} (and setupSchema method) must be redeclared in each subclass, - * since it depends on the CCM rule that can't be shared across serial tests. - */ - public abstract CqlSession session(); -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphGeoSearchIndexIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphGeoSearchIndexIT.java deleted file mode 100644 index 9878f1186e6..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphGeoSearchIndexIT.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.datastax.oss.driver.shaded.guava.common.base.Joiner; -import com.datastax.oss.driver.shaded.guava.common.collect.Lists; -import java.util.ArrayList; -import java.util.Collection; -import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.1", - description = "DSE 5.1 required for graph geo indexing") -public class ClassicGraphGeoSearchIndexIT extends GraphGeoSearchIndexITBase { - private static final CustomCcmRule CCM_RULE = - CustomCcmRule.builder().withDseWorkloads("graph", "solr").build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule public static TestRule chain = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - private final GraphTraversalSource g = - AnonymousTraversalSource.traversal() - .withRemote(DseGraph.remoteConnectionBuilder(SESSION_RULE.session()).build()); - - @Override - protected boolean isGraphBinary() { - return false; - } - - @Override - protected GraphTraversalSource graphTraversalSource() { - return g; - } - - @BeforeClass - public static void setup() { - for (String setupQuery : geoIndices()) { - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(setupQuery)); - } - - CCM_RULE.getCcmBridge().reloadCore(1, SESSION_RULE.getGraphName(), "user_p", true); - } - - /** - * A schema representing an address book with search enabled on name, description, and - * coordinates. - */ - public static Collection geoIndices() { - Object[][] providerIndexTypes = indexTypes(); - String[] indexTypes = new String[providerIndexTypes.length]; - for (int i = 0; i < providerIndexTypes.length; i++) { - indexTypes[i] = (String) providerIndexTypes[i][0]; - } - - StringBuilder schema = new StringBuilder("schema.propertyKey('full_name').Text().create()\n"); - StringBuilder propertyKeys = new StringBuilder(); - StringBuilder vertexLabel = new StringBuilder("schema.vertexLabel('user').properties("); - StringBuilder indices = new StringBuilder(); - StringBuilder vertex0 = - new StringBuilder("g.addV('user').property('full_name', 'Paul Thomas Joe')"); - StringBuilder vertex1 = - new StringBuilder("g.addV('user').property('full_name', 'George Bill Steve')"); - String vertex2 = "g.addV('user').property('full_name', 'James Paul Joe')"; - StringBuilder vertex3 = new StringBuilder("g.addV('user').property('full_name', 'Jill Alice')"); - - ArrayList propertyNames = new ArrayList<>(); - propertyNames.add("'full_name'"); - - for (String indexType : indexTypes) { - - propertyKeys.append( - String.format( - "schema.propertyKey('pointPropWithBounds_%s')." - + "Point().withBounds(0.000000, 0.000000, 100.000000, 100.000000).create()\n", - indexType)); - - propertyKeys.append( - String.format( - "schema.propertyKey('pointPropWithGeoBounds_%s').Point().withGeoBounds().create()\n", - indexType)); - - propertyNames.add("'pointPropWithBounds_" + indexType + "'"); - propertyNames.add("'pointPropWithGeoBounds_" + indexType + "'"); - - if (indexType.equals("search")) { - - indices.append( - String.format( - "schema.vertexLabel('user').index('search').search().by('pointPropWithBounds_%s').withError(0.00001, 0.0).by('pointPropWithGeoBounds_%s').withError(0.00001, 0.0).add()\n", - indexType, indexType)); - } else { - - indices.append( - String.format( - "schema.vertexLabel('user').index('by_pointPropWithBounds_%s').%s().by('pointPropWithBounds_%s').add()\n", - indexType, indexType, indexType)); - - indices.append( - String.format( - "schema.vertexLabel('user').index('by_pointPropWithGeoBounds_%s').%s().by('pointPropWithGeoBounds_%s').add()\n", - indexType, indexType, indexType)); - } - - vertex0.append( - String.format( - ".property('pointPropWithBounds_%s', 'POINT(40.0001 40)').property('pointPropWithGeoBounds_%s', 'POINT(40.0001 40)')", - indexType, indexType)); - vertex1.append( - String.format( - ".property('pointPropWithBounds_%s', 'POINT(40 40)').property('pointPropWithGeoBounds_%s', 'POINT(40 40)')", - indexType, indexType)); - vertex3.append( - String.format( - ".property('pointPropWithBounds_%s', 'POINT(30 30)').property('pointPropWithGeoBounds_%s', 'POINT(30 30)')", - indexType, indexType)); - } - - vertexLabel.append(Joiner.on(", ").join(propertyNames)); - vertexLabel.append(").create()\n"); - - schema.append(propertyKeys).append(vertexLabel).append(indices); - - return Lists.newArrayList( - SampleGraphScripts.MAKE_STRICT, - schema.toString(), - vertex0.toString(), - vertex1.toString(), - vertex2, - vertex3.toString()); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphTextSearchIndexIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphTextSearchIndexIT.java deleted file mode 100644 index 13d503d6b25..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/ClassicGraphTextSearchIndexIT.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.datastax.oss.driver.shaded.guava.common.base.Joiner; -import com.datastax.oss.driver.shaded.guava.common.collect.Lists; -import java.util.ArrayList; -import java.util.Collection; -import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.1", - description = "DSE 5.1 required for graph geo indexing") -public class ClassicGraphTextSearchIndexIT extends GraphTextSearchIndexITBase { - private static final CustomCcmRule CCM_RULE = - CustomCcmRule.builder().withDseWorkloads("graph", "solr").build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule public static TestRule chain = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - private final GraphTraversalSource g = - AnonymousTraversalSource.traversal() - .withRemote(DseGraph.remoteConnectionBuilder(SESSION_RULE.session()).build()); - - /** - * A schema representing an address book with 3 properties (full_name_*, description_*, alias_*) - * created for each type of index (search, secondary, materialized). - */ - public static Collection textIndices() { - Object[][] providerIndexTypes = indexTypes(); - String[] indexTypes = new String[providerIndexTypes.length]; - for (int i = 0; i < providerIndexTypes.length; i++) { - indexTypes[i] = (String) providerIndexTypes[i][0]; - } - - StringBuilder schema = new StringBuilder(); - StringBuilder propertyKeys = new StringBuilder(); - StringBuilder vertexLabel = new StringBuilder("schema.vertexLabel('user').properties("); - StringBuilder indices = new StringBuilder(); - StringBuilder vertex0 = new StringBuilder("g.addV('user')"); - StringBuilder vertex1 = new StringBuilder("g.addV('user')"); - StringBuilder vertex2 = new StringBuilder("g.addV('user')"); - StringBuilder vertex3 = new StringBuilder("g.addV('user')"); - - ArrayList propertyNames = new ArrayList<>(); - for (String indexType : indexTypes) { - propertyKeys.append( - String.format( - "schema.propertyKey('full_name_%s').Text().create()\n" - + "schema.propertyKey('description_%s').Text().create()\n" - + "schema.propertyKey('alias_%s').Text().create()\n", - indexType, indexType, indexType)); - - propertyNames.add("'full_name_" + indexType + "'"); - propertyNames.add("'description_" + indexType + "'"); - propertyNames.add("'alias_" + indexType + "'"); - - if (indexType.equals("search")) { - indices.append( - "schema.vertexLabel('user').index('search').search().by('full_name_search').asString().by('description_search').asText().by('alias_search').asString().add()\n"); - } else { - indices.append( - String.format( - "schema.vertexLabel('user').index('by_full_name_%s').%s().by('full_name_%s').add()\n", - indexType, indexType, indexType)); - indices.append( - String.format( - "schema.vertexLabel('user').index('by_description_%s').%s().by('description_%s').add()\n", - indexType, indexType, indexType)); - indices.append( - String.format( - "schema.vertexLabel('user').index('by_alias_name_%s').%s().by('alias_%s').add()\n", - indexType, indexType, indexType)); - } - - vertex0.append( - String.format( - ".property('full_name_%s', 'Paul Thomas Joe').property('description_%s', 'Lives by the hospital').property('alias_%s', 'mario')", - indexType, indexType, indexType)); - vertex1.append( - String.format( - ".property('full_name_%s', 'George Bill Steve').property('description_%s', 'A cold dude').property('alias_%s', 'wario')", - indexType, indexType, indexType)); - vertex2.append( - String.format( - ".property('full_name_%s', 'James Paul Joe').property('description_%s', 'Likes to hang out').property('alias_%s', 'bowser')", - indexType, indexType, indexType)); - vertex3.append( - String.format( - ".property('full_name_%s', 'Jill Alice').property('description_%s', 'Enjoys a very nice cold coca cola').property('alias_%s', 'peach')", - indexType, indexType, indexType)); - } - - vertexLabel.append(Joiner.on(", ").join(propertyNames)); - vertexLabel.append(").create()\n"); - - schema.append(propertyKeys).append(vertexLabel).append(indices); - - return Lists.newArrayList( - SampleGraphScripts.MAKE_STRICT, - schema.toString(), - vertex0.toString(), - vertex1.toString(), - vertex2.toString(), - vertex3.toString()); - } - - @BeforeClass - public static void setup() { - for (String setupQuery : textIndices()) { - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(setupQuery)); - } - - CCM_RULE.getCcmBridge().reloadCore(1, SESSION_RULE.getGraphName(), "user_p", true); - } - - @Override - protected boolean isGraphBinary() { - return false; - } - - @Override - protected GraphTraversalSource graphTraversalSource() { - return g; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphDataTypeITBase.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphDataTypeITBase.java deleted file mode 100644 index 7fe31a059d7..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphDataTypeITBase.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static com.datastax.oss.driver.api.core.type.DataTypes.BIGINT; -import static com.datastax.oss.driver.api.core.type.DataTypes.INT; -import static com.datastax.oss.driver.api.core.type.DataTypes.TEXT; -import static com.datastax.oss.driver.api.core.type.DataTypes.listOf; -import static com.datastax.oss.driver.api.core.type.DataTypes.tupleOf; -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.data.geometry.LineString; -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.data.geometry.Polygon; -import com.datastax.dse.driver.api.core.graph.predicates.Geo; -import com.datastax.dse.driver.api.core.type.DseDataTypes; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.data.CqlDuration; -import com.datastax.oss.driver.api.core.data.UdtValue; -import com.datastax.oss.driver.api.core.type.TupleType; -import com.datastax.oss.driver.api.core.type.UserDefinedType; -import com.datastax.oss.driver.api.core.uuid.Uuids; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalTime; -import java.time.ZoneId; -import java.time.temporal.ChronoUnit; -import java.util.Arrays; -import java.util.Map; -import org.junit.Test; - -public abstract class CoreGraphDataTypeITBase { - - protected abstract CqlSession session(); - - protected abstract String graphName(); - - @Test - public void should_create_and_retrieve_correct_data_with_types() { - CqlSession session = session(); - - // use CQL to create type for now because DSP-17567 is not in yet, so this is more stable - session.execute( - String.format( - "CREATE TYPE %s.udt_graphbinary(simple text, complex tuple, missing text)", - graphName())); - - session.execute( - String.format( - "CREATE TYPE %s.udt_graphbinarygeo(point 'PointType', line 'LineStringType', poly 'PolygonType')", - graphName())); - - ImmutableMap.Builder properties = - ImmutableMap.builder() - .put("Ascii", "test") - .put("Bigint", 5L) - .put("Boolean", true) - .put("Date", LocalDate.of(2007, 7, 7)) - .put("Decimal", BigDecimal.valueOf(2.3)) - .put("Double", 4.5d) - .put("Float", 4.8f) - .put("Int", 45) - .put("Smallint", (short) 1) - .put("Text", "test") - .put("Time", LocalTime.now(ZoneId.systemDefault())) - .put("Timeuuid", Uuids.timeBased()) - .put("Timestamp", Instant.now().truncatedTo(ChronoUnit.MILLIS)) - .put("Uuid", java.util.UUID.randomUUID()) - .put("Varint", BigInteger.valueOf(3234)) - .put("Blob", ByteBuffer.wrap(new byte[] {1, 2, 3})) - .put("Tinyint", (byte) 38) - .put("listOf(Int)", Arrays.asList(2, 3, 4)) - .put("setOf(Int)", Sets.newHashSet(2, 3, 4)) - .put("mapOf(Int, Text)", ImmutableMap.of(2, "two", 4, "four")) - .put("Duration", CqlDuration.newInstance(1, 2, 3)) - .put("LineString", Geo.lineString(1, 2, 3, 4, 5, 6)) - .put("Point", Geo.point(3, 4)) - .put("Polygon", Geo.polygon(Geo.point(3, 4), Geo.point(5, 4), Geo.point(6, 6))) - .put("tupleOf(Int, Text)", tupleOf(INT, TEXT).newValue(5, "Bar")) - .put( - "typeOf('udt_graphbinary')", - session - .getMetadata() - .getKeyspace(graphName()) - .flatMap(keyspace -> keyspace.getUserDefinedType("udt_graphbinary")) - .orElseThrow(IllegalStateException::new) - .newValue( - "some text", tupleOf(INT, TEXT).newValue(5, "Bar"), "some missing text")) - .put( - "typeOf('udt_graphbinarygeo')", - session - .getMetadata() - .getKeyspace(graphName()) - .flatMap( - keyspaceMetadata -> - keyspaceMetadata.getUserDefinedType("udt_graphbinarygeo")) - .orElseThrow(IllegalStateException::new) - .newValue( - Point.fromCoordinates(3.3, 4.4), - LineString.fromPoints( - Point.fromCoordinates(1, 1), - Point.fromCoordinates(2, 2), - Point.fromCoordinates(3, 3)), - Polygon.fromPoints( - Point.fromCoordinates(3, 4), - Point.fromCoordinates(5, 4), - Point.fromCoordinates(6, 6)))); - - TupleType tuple = tupleOf(DseDataTypes.POINT, DseDataTypes.LINE_STRING, DseDataTypes.POLYGON); - tuple.attach(session.getContext()); - - properties.put( - "tupleOf(Point, LineString, Polygon)", - tuple.newValue( - Point.fromCoordinates(3.3, 4.4), - LineString.fromPoints( - Point.fromCoordinates(1, 1), - Point.fromCoordinates(2, 2), - Point.fromCoordinates(3, 3)), - Polygon.fromPoints( - Point.fromCoordinates(3, 4), - Point.fromCoordinates(5, 4), - Point.fromCoordinates(6, 6)))); - - int vertexID = 1; - String vertexLabel = "graphBinaryAllTypes"; - - runTest(properties.build(), vertexLabel, vertexID); - } - - @Test - public void should_insert_and_retrieve_nested_UDTS_and_tuples() { - CqlSession session = session(); - - // use CQL to create type for now because DSP-17567 is not in yet, so this is more stable - session.execute(String.format("CREATE TYPE %s.udt1(a int, b text)", graphName())); - - session.execute( - String.format( - "CREATE TYPE %s.udt2(" - + "a int" - + ", b text" - + ", c frozen" - + ", mylist list" - + ", mytuple_withlist tuple>>>" - + ")", - graphName())); - - session.execute( - String.format( - "CREATE TYPE %s.udt3(" - + "a list" - + ", b set" - + ", c map" - + ", d list>>" - + ", e set>>" - + ", f list>>" - + ")", - graphName())); - - UserDefinedType udt1 = - session - .getMetadata() - .getKeyspace(graphName()) - .flatMap(keyspace -> keyspace.getUserDefinedType("udt1")) - .orElseThrow(IllegalStateException::new); - UdtValue udtValue1 = udt1.newValue(1, "2"); - - UserDefinedType udt2 = - session - .getMetadata() - .getKeyspace(graphName()) - .flatMap(keyspace -> keyspace.getUserDefinedType("udt2")) - .orElseThrow(IllegalStateException::new); - TupleType secondNested = tupleOf(BIGINT, listOf(BIGINT)); - TupleType firstNested = tupleOf(TEXT, secondNested); - UdtValue udtValue2 = - udt2.newValue( - 1, - "2", - udt1.newValue(3, "4"), - ImmutableList.of(5L), - firstNested.newValue("6", secondNested.newValue(7L, ImmutableList.of(8L)))); - - UserDefinedType udt3 = - session - .getMetadata() - .getKeyspace(graphName()) - .flatMap(keyspace -> keyspace.getUserDefinedType("udt3")) - .orElseThrow(IllegalStateException::new); - UdtValue udtValue3 = - udt3.newValue( - ImmutableList.of(1), - ImmutableSet.of(2.1f), - ImmutableMap.of("3", 4L), - ImmutableList.of(ImmutableList.of(5.1d, 6.1d), ImmutableList.of(7.1d)), - ImmutableSet.of(ImmutableSet.of(8.1f), ImmutableSet.of(9.1f)), - ImmutableList.of(tupleOf(INT, TEXT).newValue(10, "11"))); - - Map properties = - ImmutableMap.builder() - .put("frozen(typeOf('udt1'))", udtValue1) - .put("frozen(typeOf('udt2'))", udtValue2) - .put("frozen(typeOf('udt3'))", udtValue3) - .build(); - - int vertexID = 1; - String vertexLabel = "graphBinaryNestedTypes"; - - runTest(properties, vertexLabel, vertexID); - } - - private void runTest(Map properties, String vertexLabel, int vertexID) { - // setup schema - session().execute(createVertexLabelStatement(properties, vertexLabel)); - - // execute insert query and read query - Map results = insertVertexThenReadProperties(properties, vertexID, vertexLabel); - - // test valid properties are returned - properties.forEach((k, v) -> assertThat(results.get(formatPropertyName(k))).isEqualTo(v)); - } - - private static GraphStatement createVertexLabelStatement( - Map properties, String vertexLabel) { - StringBuilder ddl = - new StringBuilder("schema.vertexLabel(vertexLabel).ifNotExists().partitionBy('id', Int)"); - - for (Map.Entry entry : properties.entrySet()) { - String typeDefinition = entry.getKey(); - String propName = formatPropertyName(typeDefinition); - - ddl.append(String.format(".property('%s', %s)", propName, typeDefinition)); - } - ddl.append(".create()"); - - return ScriptGraphStatement.newInstance(ddl.toString()) - .setQueryParam("vertexLabel", vertexLabel); - } - - protected abstract Map insertVertexThenReadProperties( - Map properties, int vertexID, String vertexLabel); - - protected static String formatPropertyName(String originalName) { - return String.format( - "prop%s", - originalName.replace("(", "").replace(")", "").replace(", ", "").replace("'", "")); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphGeoSearchIndexIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphGeoSearchIndexIT.java deleted file mode 100644 index 12db8820117..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphGeoSearchIndexIT.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.datastax.oss.driver.shaded.guava.common.collect.Lists; -import java.util.Collection; -import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8.0", - description = "DSE 6.8.0 required for Core graph support") -public class CoreGraphGeoSearchIndexIT extends GraphGeoSearchIndexITBase { - - private static final CustomCcmRule CCM_RULE = - CustomCcmRule.builder().withDseWorkloads("graph", "solr").build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getCoreGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule public static TestRule chain = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - private final GraphTraversalSource g = - AnonymousTraversalSource.traversal() - .withRemote(DseGraph.remoteConnectionBuilder(SESSION_RULE.session()).build()) - .with("allow-filtering"); - - @Override - protected boolean isGraphBinary() { - return true; - } - - @Override - protected GraphTraversalSource graphTraversalSource() { - return g; - } - - @BeforeClass - public static void setup() { - for (String setupQuery : geoIndices()) { - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(setupQuery)); - } - - CCM_RULE.getCcmBridge().reloadCore(1, SESSION_RULE.getGraphName(), "user", true); - } - - /** - * A schema representing an address book with search enabled on name, description, and - * coordinates. - */ - public static Collection geoIndices() { - Object[][] providerIndexTypes = indexTypes(); - String[] indexTypes = new String[providerIndexTypes.length]; - for (int i = 0; i < providerIndexTypes.length; i++) { - indexTypes[i] = (String) providerIndexTypes[i][0]; - } - - StringBuilder schema = - new StringBuilder("schema.vertexLabel('user').partitionBy('full_name', Text)"); - StringBuilder propertyKeys = new StringBuilder(); - StringBuilder indices = new StringBuilder(); - StringBuilder vertex0 = - new StringBuilder("g.addV('user').property('full_name', 'Paul Thomas Joe')"); - StringBuilder vertex1 = - new StringBuilder("g.addV('user').property('full_name', 'George Bill Steve')"); - String vertex2 = "g.addV('user').property('full_name', 'James Paul Joe')"; - StringBuilder vertex3 = new StringBuilder("g.addV('user').property('full_name', 'Jill Alice')"); - - for (String indexType : indexTypes) { - propertyKeys.append(String.format(".property('pointPropWithBounds_%s', Point)\n", indexType)); - - propertyKeys.append( - String.format(".property('pointPropWithGeoBounds_%s', Point)\n", indexType)); - - if (indexType.equals("search")) { - indices.append( - String.format( - "schema.vertexLabel('user').searchIndex().by('pointPropWithBounds_%s').by('pointPropWithGeoBounds_%s').create()\n", - indexType, indexType)); - - } else { - throw new UnsupportedOperationException("IndexType other than search is not supported."); - } - - vertex0.append( - String.format( - ".property('pointPropWithBounds_%s', point(40.0001,40)).property('pointPropWithGeoBounds_%s', point(40.0001,40))", - indexType, indexType)); - vertex1.append( - String.format( - ".property('pointPropWithBounds_%s', point(40,40)).property('pointPropWithGeoBounds_%s', point(40,40))", - indexType, indexType)); - vertex3.append( - String.format( - ".property('pointPropWithBounds_%s', point(30,30)).property('pointPropWithGeoBounds_%s', point(30,30))", - indexType, indexType)); - } - - schema.append(propertyKeys).append(".create();\n").append(indices); - - return Lists.newArrayList( - schema.toString(), vertex0.toString(), vertex1.toString(), vertex2, vertex3.toString()); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphTextSearchIndexIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphTextSearchIndexIT.java deleted file mode 100644 index 5545c3c00ac..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CoreGraphTextSearchIndexIT.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.datastax.oss.driver.shaded.guava.common.collect.Lists; -import java.util.Collection; -import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8.0", - description = "DSE 6.8.0 required for Core graph support") -public class CoreGraphTextSearchIndexIT extends GraphTextSearchIndexITBase { - - private static final CustomCcmRule CCM_RULE = - CustomCcmRule.builder().withDseWorkloads("graph", "solr").build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getCoreGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule public static TestRule chain = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - private final GraphTraversalSource g = - AnonymousTraversalSource.traversal() - .withRemote(DseGraph.remoteConnectionBuilder(SESSION_RULE.session()).build()) - .with("allow-filtering"); - - @Override - protected boolean isGraphBinary() { - return true; - } - - @Override - protected GraphTraversalSource graphTraversalSource() { - return g; - } - - /** - * A schema representing an address book with 3 properties (full_name_*, description_*, alias_*) - * created for each type of index (search, secondary, materialized). - */ - public static Collection textIndices() { - Object[][] providerIndexTypes = indexTypes(); - String[] indexTypes = new String[providerIndexTypes.length]; - for (int i = 0; i < providerIndexTypes.length; i++) { - indexTypes[i] = (String) providerIndexTypes[i][0]; - } - - StringBuilder schema = new StringBuilder("schema.vertexLabel('user')"); - StringBuilder propertyKeys = new StringBuilder(); - StringBuilder indices = new StringBuilder(); - StringBuilder vertex0 = new StringBuilder("g.addV('user')"); - StringBuilder vertex1 = new StringBuilder("g.addV('user')"); - StringBuilder vertex2 = new StringBuilder("g.addV('user')"); - StringBuilder vertex3 = new StringBuilder("g.addV('user')"); - - for (String indexType : indexTypes) { - propertyKeys.append( - String.format( - ".partitionBy('full_name_%s', Text)" - + ".property('description_%s', Text)" - + ".property('alias_%s', Text)\n", - indexType, indexType, indexType)); - - if (indexType.equals("search")) { - indices.append( - "schema.vertexLabel('user').searchIndex().by('full_name_search').asString().by('description_search').asText().by('alias_search').asString().create()\n"); - } else { - throw new UnsupportedOperationException("IndexType other than search is not supported."); - } - - vertex0.append( - String.format( - ".property('full_name_%s', 'Paul Thomas Joe').property('description_%s', 'Lives by the hospital').property('alias_%s', 'mario')", - indexType, indexType, indexType)); - vertex1.append( - String.format( - ".property('full_name_%s', 'George Bill Steve').property('description_%s', 'A cold dude').property('alias_%s', 'wario')", - indexType, indexType, indexType)); - vertex2.append( - String.format( - ".property('full_name_%s', 'James Paul Joe').property('description_%s', 'Likes to hang out').property('alias_%s', 'bowser')", - indexType, indexType, indexType)); - vertex3.append( - String.format( - ".property('full_name_%s', 'Jill Alice').property('description_%s', 'Enjoys a very nice cold coca cola').property('alias_%s', 'peach')", - indexType, indexType, indexType)); - } - - schema.append(propertyKeys).append(".create();\n").append(indices); - - return Lists.newArrayList( - schema.toString(), - vertex0.toString(), - vertex1.toString(), - vertex2.toString(), - vertex3.toString()); - } - - @BeforeClass - public static void setup() { - for (String setupQuery : textIndices()) { - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(setupQuery)); - } - - CCM_RULE.getCcmBridge().reloadCore(1, SESSION_RULE.getGraphName(), "user", true); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CqlCollectionIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CqlCollectionIT.java deleted file mode 100644 index 8bc497c37db..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/CqlCollectionIT.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static com.datastax.dse.driver.api.core.graph.predicates.CqlCollection.contains; -import static com.datastax.dse.driver.api.core.graph.predicates.CqlCollection.containsKey; -import static com.datastax.dse.driver.api.core.graph.predicates.CqlCollection.entryEq; -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.graph.predicates.CqlCollection; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.CqlSessionRuleBuilder; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8", - description = "DSE 6.8.0 required for collection predicates support") -public class CqlCollectionIT { - - private static final CustomCcmRule CCM_RULE = - CustomCcmRule.builder().withDseWorkloads("graph").build(); - - private static final SessionRule SESSION_RULE = - new CqlSessionRuleBuilder(CCM_RULE) - .withCreateGraph() - .withCoreEngine() - .withGraphProtocol("graph-binary-1.0") - .build(); - - @ClassRule public static TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - private final GraphTraversalSource g = - AnonymousTraversalSource.traversal() - .withRemote(DseGraph.remoteConnectionBuilder(SESSION_RULE.session()).build()); - - @BeforeClass - public static void setup() { - for (String setupQuery : createSchema()) { - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(setupQuery)); - } - } - - private static Collection createSchema() { - return ImmutableList.of( - "schema.vertexLabel('software').ifNotExists().partitionBy('name', Varchar)" - + ".property('myList', listOf(Varchar))" - + ".property('mySet', setOf(Varchar))" - + ".property('myMapKeys', mapOf(Varchar, Int))" - + ".property('myMapValues', mapOf(Int, Varchar))" - + ".property('myMapEntries', mapOf(Int, Varchar))" - + ".property('myFrozenList', frozen(listOf(Varchar)))" - + ".property('myFrozenSet', frozen(setOf(Float)))" - + ".property('myFrozenMap', frozen(mapOf(Int, Varchar)))" - + ".create()", - "schema.vertexLabel('software').secondaryIndex('by_myList').ifNotExists().by('myList').create();" - + "schema.vertexLabel('software').secondaryIndex('by_mySet').ifNotExists().by('mySet').create();" - + "schema.vertexLabel('software').secondaryIndex('by_myMapKeys').ifNotExists().by('myMapKeys').indexKeys().create();" - + "schema.vertexLabel('software').secondaryIndex('by_myMapValues').ifNotExists().by('myMapValues').indexValues().create();" - + "schema.vertexLabel('software').secondaryIndex('by_myMapEntries').ifNotExists().by('myMapEntries').indexEntries().create();" - + "schema.vertexLabel('software').secondaryIndex('by_myFrozenList').ifNotExists().by('myFrozenList').indexFull().create();" - + "schema.vertexLabel('software').secondaryIndex('by_myFrozenSet').ifNotExists().by('myFrozenSet').indexFull().create();" - + "schema.vertexLabel('software').secondaryIndex('by_myFrozenMap').ifNotExists().by('myFrozenMap').indexFull().create()"); - } - - @Test - public void should_apply_contains_predicate_to_non_frozen_list() { - CqlSession session = SESSION_RULE.session(); - - List myList1 = com.google.common.collect.ImmutableList.of("apple", "banana"); - List myList2 = com.google.common.collect.ImmutableList.of("cranberry", "orange"); - - session.execute( - FluentGraphStatement.newInstance( - DseGraph.g - .addV("software") - .property("name", "dse list 1") - .property("myList", myList1))); - session.execute( - FluentGraphStatement.newInstance( - DseGraph.g - .addV("software") - .property("name", "dse list 2") - .property("myList", myList2))); - - assertThat(g.V().has("software", "myList", contains("apple")).values("myList").toList()) - .hasSize(1) - .contains(myList1) - .doesNotContain(myList2); - assertThat(g.V().has("software", "myList", contains("strawberry")).toList()).isEmpty(); - } - - @Test - public void should_apply_contains_predicate_to_non_frozen_set() { - CqlSession session = SESSION_RULE.session(); - - Set mySet1 = ImmutableSet.of("apple", "banana"); - Set mySet2 = ImmutableSet.of("cranberry", "orange"); - - session.execute( - FluentGraphStatement.newInstance( - DseGraph.g.addV("software").property("name", "dse set 1").property("mySet", mySet1))); - session.execute( - FluentGraphStatement.newInstance( - DseGraph.g.addV("software").property("name", "dse set 2").property("mySet", mySet2))); - - assertThat(g.V().has("software", "mySet", contains("apple")).values("mySet").toList()) - .hasSize(1) - .contains(mySet1) - .doesNotContain(mySet2); - assertThat(g.V().has("software", "mySet", contains("strawberry")).toList()).isEmpty(); - } - - @Test - public void should_apply_containsKey_predicate_to_non_frozen_map() { - CqlSession session = SESSION_RULE.session(); - - Map myMap1 = ImmutableMap.builder().put("id1", 1).build(); - Map myMap2 = ImmutableMap.builder().put("id2", 2).build(); - - session.execute( - FluentGraphStatement.newInstance( - DseGraph.g - .addV("software") - .property("name", "dse map containsKey 1") - .property("myMapKeys", myMap1))); - session.execute( - FluentGraphStatement.newInstance( - DseGraph.g - .addV("software") - .property("name", "dse map containsKey 2") - .property("myMapKeys", myMap2))); - - assertThat(g.V().has("software", "myMapKeys", containsKey("id1")).values("myMapKeys").toList()) - .hasSize(1) - .contains(myMap1) - .doesNotContain(myMap2); - assertThat(g.V().has("software", "myMapKeys", containsKey("id3")).toList()).isEmpty(); - } - - @Test - public void should_apply_containsValue_predicate_to_non_frozen_map() { - CqlSession session = SESSION_RULE.session(); - - Map myMap1 = ImmutableMap.builder().put(11, "abc").build(); - Map myMap2 = ImmutableMap.builder().put(22, "def").build(); - - session.execute( - FluentGraphStatement.newInstance( - DseGraph.g - .addV("software") - .property("name", "dse map containsValue 1") - .property("myMapValues", myMap1))); - session.execute( - FluentGraphStatement.newInstance( - DseGraph.g - .addV("software") - .property("name", "dse map containsValue 2") - .property("myMapValues", myMap2))); - assertThat( - g.V() - .has("software", "myMapValues", CqlCollection.containsValue("abc")) - .values("myMapValues") - .toList()) - .hasSize(1) - .contains(myMap1) - .doesNotContain(myMap2); - assertThat(g.V().has("software", "myMapValues", CqlCollection.containsValue("xyz")).toList()) - .isEmpty(); - } - - @Test - public void should_apply_entryEq_predicate_to_non_frozen_map() { - CqlSession session = SESSION_RULE.session(); - - Map myMap1 = ImmutableMap.builder().put(11, "abc").build(); - Map myMap2 = ImmutableMap.builder().put(22, "def").build(); - - session.execute( - FluentGraphStatement.newInstance( - DseGraph.g - .addV("software") - .property("name", "dse map entryEq 1") - .property("myMapEntries", myMap1))); - session.execute( - FluentGraphStatement.newInstance( - DseGraph.g - .addV("software") - .property("name", "dse map entryEq 2") - .property("myMapEntries", myMap2))); - assertThat( - g.V() - .has("software", "myMapEntries", entryEq(11, "abc")) - .values("myMapEntries") - .toList()) - .hasSize(1) - .contains(myMap1) - .doesNotContain(myMap2); - assertThat(g.V().has("software", "myMapEntries", entryEq(11, "xyz")).toList()).isEmpty(); - assertThat(g.V().has("software", "myMapEntries", entryEq(33, "abc")).toList()).isEmpty(); - assertThat(g.V().has("software", "myMapEntries", entryEq(33, "xyz")).toList()).isEmpty(); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphAuthenticationIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphAuthenticationIT.java deleted file mode 100644 index de1c23fd661..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphAuthenticationIT.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static com.datastax.dse.driver.api.core.graph.TinkerGraphAssertions.assertThat; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.Version; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverConfigLoader; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionUtils; -import com.datastax.oss.driver.internal.core.auth.PlainTextAuthProvider; -import com.datastax.oss.driver.shaded.guava.common.util.concurrent.Uninterruptibles; -import java.util.concurrent.TimeUnit; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.0", - description = "DSE 5 required for Graph") -public class GraphAuthenticationIT { - - @ClassRule - public static CustomCcmRule ccm = - CustomCcmRule.builder() - .withDseConfiguration("authentication_options.enabled", true) - .withJvmArgs("-Dcassandra.superuser_setup_delay_ms=0") - .withDseWorkloads("graph") - .build(); - - @BeforeClass - public static void sleepForAuth() { - if (ccm.getCassandraVersion().compareTo(Version.V2_2_0) < 0) { - // Sleep for 1 second to allow C* auth to do its work. This is only needed for 2.1 - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - } - } - - @Test - public void should_execute_graph_query_on_authenticated_connection() { - CqlSession dseSession = - SessionUtils.newSession( - ccm, - DriverConfigLoader.programmaticBuilder() - .withString(DseDriverOption.AUTH_PROVIDER_AUTHORIZATION_ID, "") - .withString(DefaultDriverOption.AUTH_PROVIDER_USER_NAME, "cassandra") - .withString(DefaultDriverOption.AUTH_PROVIDER_PASSWORD, "cassandra") - .withClass(DefaultDriverOption.AUTH_PROVIDER_CLASS, PlainTextAuthProvider.class) - .build()); - - GraphNode gn = - dseSession.execute(ScriptGraphStatement.newInstance("1+1").setSystemQuery(true)).one(); - assertThat(gn).isNotNull(); - assertThat(gn.asInt()).isEqualTo(2); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphGeoSearchIndexITBase.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphGeoSearchIndexITBase.java deleted file mode 100644 index 67d0cb34d43..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphGeoSearchIndexITBase.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static com.datastax.dse.driver.api.core.graph.TinkerGraphAssertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; - -import com.datastax.dse.driver.api.core.data.geometry.Point; -import com.datastax.dse.driver.api.core.graph.predicates.Geo; -import com.datastax.oss.driver.api.core.servererrors.InvalidQueryException; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.assertj.core.api.Assumptions; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(DataProviderRunner.class) -public abstract class GraphGeoSearchIndexITBase { - - protected abstract boolean isGraphBinary(); - - protected abstract GraphTraversalSource graphTraversalSource(); - - @DataProvider - public static Object[][] indexTypes() { - return new Object[][] {{"search"} - - // FIXME for some reason, materialized and secondary indices have decided not to work - // I get an exception saying "there is no index for this query, here is the defined - // indices: " and the list contains the indices that are needed. Mysterious. - // There may be something to do with differences in the CCMBridge adapter of the new - // driver, some changes make materialized views and secondary indices to be not - // considered for graph: - // - // , {"materialized"} - // , {"secondary"} - }; - } - - @UseDataProvider("indexTypes") - @Test - public void search_by_distance_cartesian_graphson(String indexType) { - // cartesian is not supported by graph_binary - Assumptions.assumeThat(isGraphBinary()).isFalse(); - // in cartesian geometry, the distance between POINT(30 30) and POINT(40 40) is exactly - // 14.142135623730951 - // any point further than that should be detected outside of the range. - // the vertex "Paul Thomas Joe" is at POINT(40.0001 40), and shouldn't be detected inside the - // range for classic. - - GraphTraversal traversal = - graphTraversalSource() - .V() - .has( - "user", - "pointPropWithBounds_" + indexType, - Geo.inside(Point.fromCoordinates(30, 30), 14.142135623730951)) - .values("full_name"); - assertThat(traversal.toList()).containsOnly("George Bill Steve", "Jill Alice"); - } - - @UseDataProvider("indexTypes") - @Test - public void search_by_distance_geodetic(String indexType) { - // in geodetic geometry, the distance between POINT(30 30) and POINT(40 40) is exactly - // 12.908258700131379 - // any point further than that should be detected outside of the range. - // the vertex "Paul Thomas Joe" is at POINT(40.0001 40), and shouldn't be detected inside the - // range. - GraphTraversal traversal = - graphTraversalSource() - .V() - .has( - "user", - "pointPropWithGeoBounds_" + indexType, - Geo.inside(Point.fromCoordinates(30, 30), 12.908258700131379, Geo.Unit.DEGREES)) - .values("full_name"); - assertThat(traversal.toList()).containsOnly("George Bill Steve", "Jill Alice"); - } - - @Test - public void - should_fail_if_geodetic_predicate_used_against_cartesian_property_with_search_index() { - - // for graph_binary cartesian properties are not supported, thus it does not fail - if (isGraphBinary()) { - assertThatCode( - () -> { - GraphTraversal traversal = - graphTraversalSource() - .V() - .has( - "user", - "pointPropWithBounds_search", - Geo.inside( - Point.fromCoordinates(30, 30), - 12.908258700131379, - Geo.Unit.DEGREES)) - .values("full_name"); - traversal.toList(); - }) - .doesNotThrowAnyException(); - } else { - try { - GraphTraversal traversal = - graphTraversalSource() - .V() - .has( - "user", - "pointPropWithBounds_search", - Geo.inside(Point.fromCoordinates(30, 30), 12.908258700131379, Geo.Unit.DEGREES)) - .values("full_name"); - traversal.toList(); - fail("Should have failed executing the traversal because the property type is incorrect"); - } catch (InvalidQueryException e) { - assertThat(e.getMessage()) - .contains("Distance units cannot be used in queries against non-geodetic points."); - } - } - } - - @Test - public void - should_fail_if_cartesian_predicate_used_against_geodetic_property_with_search_index() { - - if (isGraphBinary()) { - try { - GraphTraversal traversal = - graphTraversalSource() - .V() - .has( - "user", - "pointPropWithGeoBounds_search", - Geo.inside(Point.fromCoordinates(30, 30), 14.142135623730951)) - .values("full_name"); - traversal.toList(); - fail("Should have failed executing the traversal because the property type is incorrect"); - } catch (InvalidQueryException e) { - assertThat(e.getMessage()) - .contains("Predicate 'insideCartesian' is not supported on property"); - } - } else { - try { - GraphTraversal traversal = - graphTraversalSource() - .V() - .has( - "user", - "pointPropWithGeoBounds_search", - Geo.inside(Point.fromCoordinates(30, 30), 14.142135623730951)) - .values("full_name"); - traversal.toList(); - fail("Should have failed executing the traversal because the property type is incorrect"); - } catch (InvalidQueryException e) { - assertThat(e.getMessage()) - .contains("Distance units are required for queries against geodetic points."); - } - } - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphPagingIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphPagingIT.java deleted file mode 100644 index aa0ada7840c..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphPagingIT.java +++ /dev/null @@ -1,510 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static com.datastax.dse.driver.api.core.cql.continuous.ContinuousPagingITBase.Options; -import static org.assertj.core.api.Assertions.fail; -import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; - -import com.codahale.metrics.Timer; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousPagingITBase; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; -import com.datastax.dse.driver.internal.core.graph.MultiPageGraphResultSet; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.DriverTimeoutException; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.metrics.Metrics; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.datastax.oss.driver.api.testinfra.session.SessionUtils; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.net.SocketAddress; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.ExecutionException; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.RunWith; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8.0", - description = "Graph paging requires DSE 6.8+") -@RunWith(DataProviderRunner.class) -public class GraphPagingIT { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getCoreGraphSessionBuilder(CCM_RULE) - .withConfigLoader( - SessionUtils.configLoaderBuilder() - .withStringList( - DefaultDriverOption.METRICS_SESSION_ENABLED, - Collections.singletonList(DseSessionMetric.GRAPH_REQUESTS.getPath())) - .withStringList( - DefaultDriverOption.METRICS_NODE_ENABLED, - Collections.singletonList(DseNodeMetric.GRAPH_MESSAGES.getPath())) - .build()) - .build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - @BeforeClass - public static void setupSchema() { - SESSION_RULE - .session() - .execute( - ScriptGraphStatement.newInstance( - "schema.vertexLabel('person')" - + ".partitionBy('pk', Int)" - + ".clusterBy('cc', Int)" - + ".property('name', Text)" - + ".create();") - .setGraphName(SESSION_RULE.getGraphName())); - for (int i = 1; i <= 100; i++) { - SESSION_RULE - .session() - .execute( - ScriptGraphStatement.newInstance( - String.format( - "g.addV('person').property('pk',0).property('cc',%d).property('name', '%s');", - i, "user" + i)) - .setGraphName(SESSION_RULE.getGraphName())); - } - } - - @UseDataProvider(location = ContinuousPagingITBase.class, value = "pagingOptions") - @Test - public void synchronous_paging_with_options(Options options) { - // given - DriverExecutionProfile profile = enableGraphPaging(options, PagingEnabledOptions.ENABLED); - - if (options.sizeInBytes) { - // Page sizes in bytes are not supported with graph queries - return; - } - - // when - GraphResultSet result = - SESSION_RULE - .session() - .execute( - ScriptGraphStatement.newInstance("g.V().hasLabel('person').values('name')") - .setGraphName(SESSION_RULE.getGraphName()) - .setTraversalSource("g") - .setExecutionProfile(profile)); - - // then - List nodes = result.all(); - - assertThat(((CountingIterator) result.iterator()).remaining()).isZero(); - assertThat(nodes).hasSize(options.expectedRows); - for (int i = 1; i <= nodes.size(); i++) { - GraphNode node = nodes.get(i - 1); - assertThat(node.asString()).isEqualTo("user" + i); - } - assertThat(result.getRequestExecutionInfo()).isNotNull(); - assertThat(result.getRequestExecutionInfo().getCoordinator().getEndPoint().resolve()) - .isEqualTo(firstCcmNode()); - assertIfMultiPage(result, options.expectedPages); - validateMetrics(SESSION_RULE.session()); - } - - @UseDataProvider(location = ContinuousPagingITBase.class, value = "pagingOptions") - @Test - public void synchronous_paging_with_options_when_auto(Options options) { - // given - DriverExecutionProfile profile = enableGraphPaging(options, PagingEnabledOptions.AUTO); - - if (options.sizeInBytes) { - // Page sizes in bytes are not supported with graph queries - return; - } - - // when - GraphResultSet result = - SESSION_RULE - .session() - .execute( - ScriptGraphStatement.newInstance("g.V().hasLabel('person').values('name')") - .setGraphName(SESSION_RULE.getGraphName()) - .setTraversalSource("g") - .setExecutionProfile(profile)); - - // then - List nodes = result.all(); - - assertThat(((CountingIterator) result.iterator()).remaining()).isZero(); - assertThat(nodes).hasSize(options.expectedRows); - for (int i = 1; i <= nodes.size(); i++) { - GraphNode node = nodes.get(i - 1); - assertThat(node.asString()).isEqualTo("user" + i); - } - assertThat(result.getRequestExecutionInfo()).isNotNull(); - assertThat(result.getRequestExecutionInfo().getCoordinator().getEndPoint().resolve()) - .isEqualTo(firstCcmNode()); - - assertIfMultiPage(result, options.expectedPages); - validateMetrics(SESSION_RULE.session()); - } - - private void assertIfMultiPage(GraphResultSet result, int expectedPages) { - if (result instanceof MultiPageGraphResultSet) { - assertThat(((MultiPageGraphResultSet) result).getRequestExecutionInfos()) - .hasSize(expectedPages); - assertThat(result.getRequestExecutionInfo()) - .isSameAs( - ((MultiPageGraphResultSet) result).getRequestExecutionInfos().get(expectedPages - 1)); - } - } - - @UseDataProvider(location = ContinuousPagingITBase.class, value = "pagingOptions") - @Test - public void synchronous_options_with_paging_disabled_should_fallback_to_single_page( - Options options) { - // given - DriverExecutionProfile profile = enableGraphPaging(options, PagingEnabledOptions.DISABLED); - - if (options.sizeInBytes) { - // Page sizes in bytes are not supported with graph queries - return; - } - - // when - GraphResultSet result = - SESSION_RULE - .session() - .execute( - ScriptGraphStatement.newInstance("g.V().hasLabel('person').values('name')") - .setGraphName(SESSION_RULE.getGraphName()) - .setTraversalSource("g") - .setExecutionProfile(profile)); - - // then - List nodes = result.all(); - - assertThat(((CountingIterator) result.iterator()).remaining()).isZero(); - assertThat(nodes).hasSize(100); - for (int i = 1; i <= nodes.size(); i++) { - GraphNode node = nodes.get(i - 1); - assertThat(node.asString()).isEqualTo("user" + i); - } - assertThat(result.getRequestExecutionInfo()).isNotNull(); - assertThat(result.getRequestExecutionInfo().getCoordinator().getEndPoint().resolve()) - .isEqualTo(firstCcmNode()); - validateMetrics(SESSION_RULE.session()); - } - - @UseDataProvider(location = ContinuousPagingITBase.class, value = "pagingOptions") - @Test - public void asynchronous_paging_with_options(Options options) - throws ExecutionException, InterruptedException { - // given - DriverExecutionProfile profile = enableGraphPaging(options, PagingEnabledOptions.ENABLED); - - if (options.sizeInBytes) { - // Page sizes in bytes are not supported with graph queries - return; - } - - // when - CompletionStage result = - SESSION_RULE - .session() - .executeAsync( - ScriptGraphStatement.newInstance("g.V().hasLabel('person').values('name')") - .setGraphName(SESSION_RULE.getGraphName()) - .setTraversalSource("g") - .setExecutionProfile(profile)); - - // then - checkAsyncResult(result, options, 0, 1, new ArrayList<>()); - validateMetrics(SESSION_RULE.session()); - } - - @UseDataProvider(location = ContinuousPagingITBase.class, value = "pagingOptions") - @Test - public void asynchronous_paging_with_options_when_auto(Options options) - throws ExecutionException, InterruptedException { - // given - DriverExecutionProfile profile = enableGraphPaging(options, PagingEnabledOptions.AUTO); - - if (options.sizeInBytes) { - // Page sizes in bytes are not supported with graph queries - return; - } - - // when - CompletionStage result = - SESSION_RULE - .session() - .executeAsync( - ScriptGraphStatement.newInstance("g.V().hasLabel('person').values('name')") - .setGraphName(SESSION_RULE.getGraphName()) - .setTraversalSource("g") - .setExecutionProfile(profile)); - - // then - checkAsyncResult(result, options, 0, 1, new ArrayList<>()); - validateMetrics(SESSION_RULE.session()); - } - - @UseDataProvider(location = ContinuousPagingITBase.class, value = "pagingOptions") - @Test - public void asynchronous_options_with_paging_disabled_should_fallback_to_single_page( - Options options) throws ExecutionException, InterruptedException { - // given - DriverExecutionProfile profile = enableGraphPaging(options, PagingEnabledOptions.DISABLED); - - if (options.sizeInBytes) { - // Page sizes in bytes are not supported with graph queries - return; - } - - // when - CompletionStage result = - SESSION_RULE - .session() - .executeAsync( - ScriptGraphStatement.newInstance("g.V().hasLabel('person').values('name')") - .setGraphName(SESSION_RULE.getGraphName()) - .setTraversalSource("g") - .setExecutionProfile(profile)); - - // then - AsyncGraphResultSet asyncGraphResultSet = result.toCompletableFuture().get(); - for (int i = 1; i <= 100; i++, asyncGraphResultSet.remaining()) { - GraphNode node = asyncGraphResultSet.one(); - assertThat(node.asString()).isEqualTo("user" + i); - } - assertThat(asyncGraphResultSet.remaining()).isEqualTo(0); - validateMetrics(SESSION_RULE.session()); - } - - private void checkAsyncResult( - CompletionStage future, - Options options, - int rowsFetched, - int pageNumber, - List graphExecutionInfos) - throws ExecutionException, InterruptedException { - AsyncGraphResultSet result = future.toCompletableFuture().get(); - int remaining = result.remaining(); - rowsFetched += remaining; - assertThat(remaining).isLessThanOrEqualTo(options.pageSize); - - if (options.expectedRows == rowsFetched) { - assertThat(result.hasMorePages()).isFalse(); - } else { - assertThat(result.hasMorePages()).isTrue(); - } - - int first = (pageNumber - 1) * options.pageSize + 1; - int last = (pageNumber - 1) * options.pageSize + remaining; - - for (int i = first; i <= last; i++, remaining--) { - GraphNode node = result.one(); - assertThat(node.asString()).isEqualTo("user" + i); - assertThat(result.remaining()).isEqualTo(remaining - 1); - } - - assertThat(result.remaining()).isZero(); - assertThat(result.getRequestExecutionInfo()).isNotNull(); - assertThat(result.getRequestExecutionInfo().getCoordinator().getEndPoint().resolve()) - .isEqualTo(firstCcmNode()); - - graphExecutionInfos.add(result.getRequestExecutionInfo()); - - assertThat(graphExecutionInfos).hasSize(pageNumber); - assertThat(result.getRequestExecutionInfo()).isSameAs(graphExecutionInfos.get(pageNumber - 1)); - if (pageNumber == options.expectedPages) { - assertThat(result.hasMorePages()).isFalse(); - assertThat(options.expectedRows).isEqualTo(rowsFetched); - assertThat(options.expectedPages).isEqualTo(pageNumber); - } else { - assertThat(result.hasMorePages()).isTrue(); - checkAsyncResult( - result.fetchNextPage(), options, rowsFetched, pageNumber + 1, graphExecutionInfos); - } - } - - @Test - public void should_cancel_result_set() { - // given - DriverExecutionProfile profile = - enableGraphPaging() - .withInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES, 1) - .withInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_PAGE_SIZE, 10); - - // when - GraphStatement statement = - ScriptGraphStatement.newInstance("g.V().hasLabel('person').values('name')") - .setGraphName(SESSION_RULE.getGraphName()) - .setTraversalSource("g") - .setExecutionProfile(profile); - MultiPageGraphResultSet results = - (MultiPageGraphResultSet) SESSION_RULE.session().execute(statement); - - assertThat(((MultiPageGraphResultSet.RowIterator) results.iterator()).isCancelled()).isFalse(); - assertThat(((CountingIterator) results.iterator()).remaining()).isEqualTo(10); - results.cancel(); - - assertThat(((MultiPageGraphResultSet.RowIterator) results.iterator()).isCancelled()).isTrue(); - assertThat(((CountingIterator) results.iterator()).remaining()).isEqualTo(10); - for (int i = 0; i < 10; i++) { - results.one(); - } - } - - @Test - public void should_trigger_global_timeout_sync_from_config() { - // given - Duration timeout = Duration.ofMillis(100); - DriverExecutionProfile profile = - enableGraphPaging().withDuration(DseDriverOption.GRAPH_TIMEOUT, timeout); - - // when - try { - CCM_RULE.getCcmBridge().pause(1); - try { - SESSION_RULE - .session() - .execute( - ScriptGraphStatement.newInstance("g.V().hasLabel('person').values('name')") - .setGraphName(SESSION_RULE.getGraphName()) - .setTraversalSource("g") - .setExecutionProfile(profile)); - fail("Expecting DriverTimeoutException"); - } catch (DriverTimeoutException e) { - assertThat(e).hasMessageStartingWith("Query timed out after " + timeout); - } - } finally { - CCM_RULE.getCcmBridge().resume(1); - } - } - - @Test - public void should_trigger_global_timeout_sync_from_statement() { - // given - Duration timeout = Duration.ofMillis(100); - - // when - try { - CCM_RULE.getCcmBridge().pause(1); - try { - SESSION_RULE - .session() - .execute( - ScriptGraphStatement.newInstance("g.V().hasLabel('person').values('name')") - .setGraphName(SESSION_RULE.getGraphName()) - .setTraversalSource("g") - .setTimeout(timeout)); - fail("Expecting DriverTimeoutException"); - } catch (DriverTimeoutException e) { - assertThat(e).hasMessageStartingWith("Query timed out after " + timeout); - } - } finally { - CCM_RULE.getCcmBridge().resume(1); - } - } - - @Test - public void should_trigger_global_timeout_async() throws InterruptedException { - // given - Duration timeout = Duration.ofMillis(100); - DriverExecutionProfile profile = - enableGraphPaging().withDuration(DseDriverOption.GRAPH_TIMEOUT, timeout); - - // when - try { - CCM_RULE.getCcmBridge().pause(1); - CompletionStage result = - SESSION_RULE - .session() - .executeAsync( - ScriptGraphStatement.newInstance("g.V().hasLabel('person').values('name')") - .setGraphName(SESSION_RULE.getGraphName()) - .setTraversalSource("g") - .setExecutionProfile(profile)); - result.toCompletableFuture().get(); - fail("Expecting DriverTimeoutException"); - } catch (ExecutionException e) { - assertThat(e.getCause()).hasMessageStartingWith("Query timed out after " + timeout); - } finally { - CCM_RULE.getCcmBridge().resume(1); - } - } - - private DriverExecutionProfile enableGraphPaging() { - return SESSION_RULE - .session() - .getContext() - .getConfig() - .getDefaultProfile() - .withString(DseDriverOption.GRAPH_PAGING_ENABLED, PagingEnabledOptions.ENABLED.name()); - } - - private DriverExecutionProfile enableGraphPaging( - Options options, PagingEnabledOptions pagingEnabledOptions) { - return SESSION_RULE - .session() - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_PAGE_SIZE, options.pageSize) - .withInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_PAGES, options.maxPages) - .withInt( - DseDriverOption.GRAPH_CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, options.maxPagesPerSecond) - .withString(DseDriverOption.GRAPH_PAGING_ENABLED, pagingEnabledOptions.name()); - } - - private SocketAddress firstCcmNode() { - return CCM_RULE.getContactPoints().iterator().next().resolve(); - } - - private void validateMetrics(CqlSession session) { - Node node = session.getMetadata().getNodes().values().iterator().next(); - assertThat(session.getMetrics()).isPresent(); - Metrics metrics = session.getMetrics().get(); - assertThat(metrics.getNodeMetric(node, DseNodeMetric.GRAPH_MESSAGES)).isPresent(); - Timer messages = (Timer) metrics.getNodeMetric(node, DseNodeMetric.GRAPH_MESSAGES).get(); - assertThat(messages.getCount()).isGreaterThan(0); - assertThat(messages.getMeanRate()).isGreaterThan(0); - assertThat(metrics.getSessionMetric(DseSessionMetric.GRAPH_REQUESTS)).isPresent(); - Timer requests = (Timer) metrics.getSessionMetric(DseSessionMetric.GRAPH_REQUESTS).get(); - assertThat(requests.getCount()).isGreaterThan(0); - assertThat(requests.getMeanRate()).isGreaterThan(0); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphSpeculativeExecutionIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphSpeculativeExecutionIT.java deleted file mode 100644 index 130e9a17cc1..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphSpeculativeExecutionIT.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionUtils; -import com.datastax.oss.driver.internal.core.specex.ConstantSpeculativeExecutionPolicy; -import com.datastax.oss.driver.internal.core.specex.NoSpeculativeExecutionPolicy; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.time.Duration; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8.0", - description = "DSE 6.8 required for graph paging") -@RunWith(DataProviderRunner.class) -public class GraphSpeculativeExecutionIT { - - @ClassRule - public static CustomCcmRule ccmRule = CustomCcmRule.builder().withDseWorkloads("graph").build(); - - @Test - @UseDataProvider("idempotenceAndSpecExecs") - public void should_use_speculative_executions_when_enabled( - boolean defaultIdempotence, - Boolean statementIdempotence, - Class speculativeExecutionClass, - boolean expectSpeculativeExecutions) { - - try (CqlSession session = - CqlSession.builder() - .addContactEndPoints(ccmRule.getContactPoints()) - .withConfigLoader( - SessionUtils.configLoaderBuilder() - .withBoolean( - DefaultDriverOption.REQUEST_DEFAULT_IDEMPOTENCE, defaultIdempotence) - .withInt(DefaultDriverOption.SPECULATIVE_EXECUTION_MAX, 10) - .withClass( - DefaultDriverOption.SPECULATIVE_EXECUTION_POLICY_CLASS, - speculativeExecutionClass) - .withDuration( - DefaultDriverOption.SPECULATIVE_EXECUTION_DELAY, Duration.ofMillis(10)) - .withString(DseDriverOption.GRAPH_PAGING_ENABLED, "ENABLED") - .build()) - .build()) { - - ScriptGraphStatement statement = - ScriptGraphStatement.newInstance( - "java.util.concurrent.TimeUnit.MILLISECONDS.sleep(1000L);") - .setIdempotent(statementIdempotence); - - GraphResultSet result = session.execute(statement); - int speculativeExecutionCount = - result.getRequestExecutionInfo().getSpeculativeExecutionCount(); - if (expectSpeculativeExecutions) { - assertThat(speculativeExecutionCount).isGreaterThan(0); - } else { - assertThat(speculativeExecutionCount).isEqualTo(0); - } - } - } - - @DataProvider - public static Object[][] idempotenceAndSpecExecs() { - return new Object[][] { - new Object[] {false, false, NoSpeculativeExecutionPolicy.class, false}, - new Object[] {false, true, NoSpeculativeExecutionPolicy.class, false}, - new Object[] {false, null, NoSpeculativeExecutionPolicy.class, false}, - new Object[] {true, false, NoSpeculativeExecutionPolicy.class, false}, - new Object[] {true, true, NoSpeculativeExecutionPolicy.class, false}, - new Object[] {true, null, NoSpeculativeExecutionPolicy.class, false}, - new Object[] {false, false, ConstantSpeculativeExecutionPolicy.class, false}, - new Object[] {false, true, ConstantSpeculativeExecutionPolicy.class, true}, - new Object[] {false, null, ConstantSpeculativeExecutionPolicy.class, false}, - new Object[] {true, false, ConstantSpeculativeExecutionPolicy.class, false}, - new Object[] {true, true, ConstantSpeculativeExecutionPolicy.class, true}, - new Object[] {true, null, ConstantSpeculativeExecutionPolicy.class, true}, - }; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTestSupport.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTestSupport.java deleted file mode 100644 index 6508be38175..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTestSupport.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.dse.driver.internal.core.graph.GraphProtocol; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.session.CqlSessionRuleBuilder; - -/** Utility for creating commonly used Rule builders for tests. */ -public class GraphTestSupport { - - /** CCM Rule builder for Graph Data Type tests. */ - public static final CustomCcmRule.Builder CCM_BUILDER_WITH_GRAPH = - CustomCcmRule.builder() - .withDseWorkloads("graph") - .withDseConfiguration("graph.max_query_params", 32) - .withDseConfiguration( - "graph.gremlin_server.scriptEngines.gremlin-groovy.config.sandbox_enabled", "false"); - - /** CCM Rule builder for general Graph workload tests. */ - public static final CustomCcmRule.Builder GRAPH_CCM_RULE_BUILDER = - CustomCcmRule.builder().withDseWorkloads("graph"); - - /** - * Creates a session rule builder for Classic Graph workloads with the default Graph protocol. The - * default GraphProtocol for Classic Graph: GraphSON 2.0. - * - * @param ccmRule CustomCcmRule configured for Graph workloads - * @return A Session rule builder configured for Classic Graph workloads - */ - public static CqlSessionRuleBuilder getClassicGraphSessionBuilder(CustomCcmRule ccmRule) { - return new CqlSessionRuleBuilder(ccmRule) - .withCreateGraph() - .withGraphProtocol(GraphProtocol.GRAPHSON_2_0.toInternalCode()); - } - - /** - * Creates a session rule builder for Core Graph workloads with the default Graph protocol. The - * default GraphProtocol for Core Graph: Graph Binary 1.0. - * - * @param ccmRule CustomCcmRule configured for Graph workloads - * @return A Session rule builder configured for Core Graph workloads - */ - public static CqlSessionRuleBuilder getCoreGraphSessionBuilder(CustomCcmRule ccmRule) { - return new CqlSessionRuleBuilder(ccmRule) - .withCreateGraph() - .withCoreEngine() - .withGraphProtocol(GraphProtocol.GRAPH_BINARY_1_0.toInternalCode()); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTextSearchIndexITBase.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTextSearchIndexITBase.java deleted file mode 100644 index d70d206715e..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTextSearchIndexITBase.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.graph.predicates.Search; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(DataProviderRunner.class) -public abstract class GraphTextSearchIndexITBase { - - protected abstract boolean isGraphBinary(); - - protected abstract GraphTraversalSource graphTraversalSource(); - - @DataProvider - public static Object[][] indexTypes() { - return new Object[][] {{"search"} - - // FIXME for some reason, materialized and secondary indices have decided not to work - // I get an exception saying "there is no index for this query, here is the defined - // indices: " and the list contains the indices that are needed. Mysterious. - // There may be something to do with differences in the CCMBridge adapter of the new - // driver, some changes make materialized views and secondary indices to be not - // considered for graph: - // - // , {"materialized"} - // , {"secondary"} - }; - } - - /** - * Validates that a graph traversal can be made by using a Search prefix predicate on an indexed - * property of the given type. - * - *

Finds all 'user' vertices having a 'full_name' property beginning with 'Paul'. - * - * @test_category dse:graph - */ - @UseDataProvider("indexTypes") - @Test - public void search_by_prefix_search(String indexType) { - // Only one user with full_name starting with Paul. - GraphTraversal traversal = - graphTraversalSource() - .V() - .has("user", "full_name_" + indexType, Search.prefix("Paul")) - .values("full_name_" + indexType); - assertThat(traversal.toList()).containsOnly("Paul Thomas Joe"); - } - - /** - * Validates that a graph traversal can be made by using a Search regex predicate on an indexed - * property of the given type. - * - *

Finds all 'user' vertices having a 'full_name' property matching regex '.*Paul.*'. - * - * @test_category dse:graph - */ - @UseDataProvider("indexTypes") - @Test - public void search_by_regex(String indexType) { - // Only two people with names containing pattern for Paul. - GraphTraversal traversal = - graphTraversalSource() - .V() - .has("user", "full_name_" + indexType, Search.regex(".*Paul.*")) - .values("full_name_" + indexType); - assertThat(traversal.toList()).containsOnly("Paul Thomas Joe", "James Paul Joe"); - } - - /** - * Validates that a graph traversal can be made by using a Search fuzzy predicate on an indexed - * property of the given type. - * - *

Finds all 'user' vertices having a 'alias' property matching 'awrio' with a fuzzy distance - * of 1. - * - * @test_category dse:graph - */ - @UseDataProvider("indexTypes") - @Test - @BackendRequirement(type = BackendType.DSE, minInclusive = "5.1.0") - public void search_by_fuzzy(String indexType) { - // Alias matches 'awrio' fuzzy - GraphTraversal traversal = - graphTraversalSource() - .V() - .has("user", "alias_" + indexType, Search.fuzzy("awrio", 1)) - .values("full_name_" + indexType); - // Should not match 'Paul Thomas Joe' since alias is 'mario', which is at distance 2 of 'awrio' - // (a -> m, w -> a) - // Should match 'George Bill Steve' since alias is 'wario' witch matches 'awrio' within a - // distance of 1 (transpose w with a). - assertThat(traversal.toList()).containsOnly("George Bill Steve"); - } - - /** - * Validates that a graph traversal can be made by using a Search token predicate on an indexed - * property of the given type. - * - *

Finds all 'user' vertices having a 'description' property containing the token 'cold'. - * - * @test_category dse:graph - */ - @UseDataProvider("indexTypes") - @Test - public void search_by_token(String indexType) { - // Description containing token 'cold' - GraphTraversal traversal = - graphTraversalSource() - .V() - .has("user", "description_" + indexType, Search.token("cold")) - .values("full_name_" + indexType); - assertThat(traversal.toList()).containsOnly("Jill Alice", "George Bill Steve"); - } - - /** - * Validates that a graph traversal can be made by using a Search token prefix predicate on an - * indexed property of the given type. - * - *

Finds all 'user' vertices having a 'description' containing the token prefix 'h'. - */ - @UseDataProvider("indexTypes") - @Test - public void search_by_token_prefix(String indexType) { - // Description containing a token starting with h - GraphTraversal traversal = - graphTraversalSource() - .V() - .has("user", "description_" + indexType, Search.tokenPrefix("h")) - .values("full_name_" + indexType); - assertThat(traversal.toList()).containsOnly("Paul Thomas Joe", "James Paul Joe"); - } - - /** - * Validates that a graph traversal can be made by using a Search token regex predicate on an - * indexed property of the given type. - * - *

Finds all 'user' vertices having a 'description' containing the token regex - * '(nice|hospital)'. - */ - @UseDataProvider("indexTypes") - @Test - public void search_by_token_regex(String indexType) { - // Description containing nice or hospital - GraphTraversal traversal = - graphTraversalSource() - .V() - .has("user", "description_" + indexType, Search.tokenRegex("(nice|hospital)")) - .values("full_name_" + indexType); - assertThat(traversal.toList()).containsOnly("Paul Thomas Joe", "Jill Alice"); - } - - /** - * Validates that a graph traversal can be made by using a Search fuzzy predicate on an indexed - * property of the given type. - * - *

Finds all 'user' vertices having a 'description' property matching 'lieks' with a fuzzy - * distance of 1. - * - * @test_category dse:graph - */ - @UseDataProvider("indexTypes") - @Test - @BackendRequirement(type = BackendType.DSE, minInclusive = "5.1.0") - public void search_by_token_fuzzy(String indexType) { - // Description containing 'lives' fuzzy - GraphTraversal traversal = - graphTraversalSource() - .V() - .has("user", "description_" + indexType, Search.tokenFuzzy("lieks", 1)) - .values("full_name_" + indexType); - // Should not match 'Paul Thomas Joe' since description contains 'Lives' which is at distance of - // 2 (e -> v, k -> e) - // Should match 'James Paul Joe' since description contains 'Likes' (transpose e for k) - assertThat(traversal.toList()).containsOnly("James Paul Joe"); - } - - /** - * Validates that a graph traversal can be made by using a Search phrase predicate on an indexed - * property of the given type. - * - *

Finds all 'user' vertices having a 'description' property matching 'a cold' with a distance - * of 2. - * - * @test_category dse:graph - */ - @UseDataProvider("indexTypes") - @Test - @BackendRequirement(type = BackendType.DSE, minInclusive = "5.1.0") - public void search_by_phrase(String indexType) { - // Full name contains phrase "Paul Joe" - GraphTraversal traversal = - graphTraversalSource() - .V() - .has("user", "description_" + indexType, Search.phrase("a cold", 2)) - .values("full_name_" + indexType); - // Should match 'George Bill Steve' since 'A cold dude' is at distance of 0 for 'a cold'. - // Should match 'Jill Alice' since 'Enjoys a very nice cold coca cola' is at distance of 2 for - // 'a cold'. - assertThat(traversal.toList()).containsOnly("George Bill Steve", "Jill Alice"); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTimeoutsIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTimeoutsIT.java deleted file mode 100644 index edf398a4c3c..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/GraphTimeoutsIT.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static com.datastax.dse.driver.api.core.graph.ScriptGraphStatement.newInstance; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.DriverTimeoutException; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.servererrors.InvalidQueryException; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import java.time.Duration; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.0", - description = "DSE 5 required for Graph") -public class GraphTimeoutsIT { - - public static CustomCcmRule ccmRule = CustomCcmRule.builder().withDseWorkloads("graph").build(); - - public static SessionRule sessionRule = - SessionRule.builder(ccmRule).withCreateGraph().build(); - - @ClassRule public static TestRule chain = RuleChain.outerRule(ccmRule).around(sessionRule); - - @Test - public void should_have_driver_wait_indefinitely_by_default_and_server_return_timeout_response() { - Duration serverTimeout = Duration.ofSeconds(1); - - DriverExecutionProfile drivertest1 = - sessionRule - .session() - .getContext() - .getConfig() - .getDefaultProfile() - .withString(DseDriverOption.GRAPH_TRAVERSAL_SOURCE, "drivertest1"); - - // We could have done with the server's default but it's 30 secs so the test would have taken at - // least that time. So we simulate a server timeout change. - sessionRule - .session() - .execute( - newInstance( - "graph.schema().config().option(\"graph.traversal_sources.drivertest1.evaluation_timeout\").set('" - + serverTimeout.toMillis() - + " ms')") - .setExecutionProfile(drivertest1)); - - try { - // The driver should wait indefinitely, but the server should timeout first. - sessionRule - .session() - .execute( - newInstance("java.util.concurrent.TimeUnit.MILLISECONDS.sleep(35000L);1+1") - .setExecutionProfile(drivertest1)); - fail("The request should have timed out"); - } catch (InvalidQueryException e) { - assertThat(e) - .hasMessageContainingAll( - "evaluation exceeded", - "threshold of ", - Long.toString(serverTimeout.toMillis()), - "ms"); - } - } - - @Test - public void should_not_take_into_account_request_timeout_if_more_than_server_timeout() { - Duration serverTimeout = Duration.ofSeconds(1); - Duration clientTimeout = Duration.ofSeconds(10); - - DriverExecutionProfile drivertest2 = - sessionRule - .session() - .getContext() - .getConfig() - .getDefaultProfile() - .withString(DseDriverOption.GRAPH_TRAVERSAL_SOURCE, "drivertest2") - .withDuration(DseDriverOption.GRAPH_TIMEOUT, clientTimeout); - - sessionRule - .session() - .execute( - newInstance( - "graph.schema().config().option(\"graph.traversal_sources.drivertest2.evaluation_timeout\").set('" - + serverTimeout.toMillis() - + " ms')") - .setExecutionProfile(drivertest2)); - - try { - // The driver should wait 32 secs, but the server should timeout first. - sessionRule - .session() - .execute( - newInstance("java.util.concurrent.TimeUnit.MILLISECONDS.sleep(35000L);1+1") - .setExecutionProfile(drivertest2)); - fail("The request should have timed out"); - } catch (InvalidQueryException e) { - assertThat(e) - .hasMessageContainingAll( - "evaluation exceeded", - "threshold of ", - Long.toString(serverTimeout.toMillis()), - "ms"); - } - } - - @Test - public void should_take_into_account_request_timeout_if_less_than_server_timeout() { - Duration serverTimeout = Duration.ofSeconds(10); - Duration clientTimeout = Duration.ofSeconds(1); - - DriverExecutionProfile drivertest3 = - sessionRule - .session() - .getContext() - .getConfig() - .getDefaultProfile() - .withString(DseDriverOption.GRAPH_TRAVERSAL_SOURCE, "drivertest3"); - - // We could have done with the server's default but it's 30 secs so the test would have taken at - // least that time. Also, we don't want to rely on server's default. So we simulate a server - // timeout change. - sessionRule - .session() - .execute( - ScriptGraphStatement.newInstance( - "graph.schema().config().option(\"graph.traversal_sources.drivertest3.evaluation_timeout\").set('" - + serverTimeout.toMillis() - + " ms')") - .setExecutionProfile(drivertest3)); - - try { - // The timeout on the request is lower than what's defined server side, so it should be taken - // into account. - sessionRule - .session() - .execute( - ScriptGraphStatement.newInstance( - "java.util.concurrent.TimeUnit.MILLISECONDS.sleep(35000L);1+1") - .setExecutionProfile( - drivertest3.withDuration(DseDriverOption.GRAPH_TIMEOUT, clientTimeout))); - fail("The request should have timed out"); - // Since the driver sends its timeout in the request payload, server timeout will be equal to - // client timeout for this request. We cannot know for sure if it will be a client timeout - // error, or a server timeout, and during tests, both happened and not deterministically. - } catch (DriverTimeoutException e) { - assertThat(e).hasMessageStartingWith("Query timed out after " + clientTimeout); - } catch (InvalidQueryException e) { - assertThat(e) - .hasMessageContainingAll( - "evaluation exceeded", - "threshold of ", - Long.toString(clientTimeout.toMillis()), - "ms"); - } - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SampleGraphScripts.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SampleGraphScripts.java deleted file mode 100644 index 19ff957736a..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SampleGraphScripts.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -public class SampleGraphScripts { - - public static final String MAKE_STRICT = - "schema.config().option('graph.schema_mode').set('production');\n"; - - public static final String MAKE_NOT_STRICT = - "schema.config().option('graph.schema_mode').set('development');\n"; - - public static final String ALLOW_SCANS = - "schema.config().option('graph.allow_scan').set('true');\n"; - - private static final String CLASSIC_SCHEMA = - "schema.propertyKey('name').Text().ifNotExists().create();\n" - + "schema.propertyKey('age').Int().ifNotExists().create();\n" - + "schema.propertyKey('lang').Text().ifNotExists().create();\n" - + "schema.propertyKey('weight').Float().ifNotExists().create();\n" - + "schema.vertexLabel('person').properties('name', 'age').ifNotExists().create();\n" - + "schema.vertexLabel('software').properties('name', 'lang').ifNotExists().create();\n" - + "schema.edgeLabel('created').properties('weight').connection('person', 'software').ifNotExists().create();\n" - + "schema.edgeLabel('knows').properties('weight').connection('person', 'person').ifNotExists().create();\n"; - - private static final String INSERT_DATA = - "marko = g.addV('person').property('name', 'marko').property('age', 29).next();\n" - + "vadas = g.addV('person').property('name', 'vadas').property('age', 27).next();\n" - + "josh = g.addV('person').property('name', 'josh').property('age', 32).next();\n" - + "peter = g.addV('person').property('name', 'peter').property('age', 35).next();\n" - + "lop = g.addV('software').property('name', 'lop').property('lang', 'java').next();\n" - + "ripple = g.addV('software').property('name', 'ripple').property('lang', 'java').next();\n" - + "g.V().has('name', 'marko').as('marko').V().has('name', 'vadas').as('vadas').addE('knows').from('marko').property('weight', 0.5f).next();\n" - + "g.V().has('name', 'marko').as('marko').V().has('name', 'josh').as('josh').addE('knows').from('marko').property('weight', 1.0f).next();\n" - + "g.V().has('name', 'marko').as('marko').V().has('name', 'lop').as('lop').addE('created').from('marko').property('weight', 0.4f).next();\n" - + "g.V().has('name', 'josh').as('josh').V().has('name', 'ripple').as('ripple').addE('created').from('josh').property('weight', 1.0f).next();\n" - + "g.V().has('name', 'josh').as('josh').V().has('name', 'lop').as('lop').addE('created').from('josh').property('weight', 0.4f).next();\n" - + "g.V().has('name', 'peter').as('peter').V().has('name', 'lop').as('lop').addE('created').from('peter').property('weight', 0.2f);"; - - public static String CLASSIC_GRAPH = CLASSIC_SCHEMA + INSERT_DATA; - - private static final String CORE_SCHEMA = - "schema.vertexLabel('person').ifNotExists().partitionBy('name', Text).property('age', Int).create();\n" - + "schema.vertexLabel('software').ifNotExists().partitionBy('name', Text).property('lang', Text).create();\n" - + "schema.edgeLabel('created').ifNotExists().from('person').to('software').property('weight', Float).create();\n" - + "schema.edgeLabel('knows').ifNotExists().from('person').to('person').property('weight', Float).create();\n"; - - public static String CORE_GRAPH = CORE_SCHEMA + INSERT_DATA; -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SocialTraversalDsl.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SocialTraversalDsl.java deleted file mode 100644 index 327f32a240d..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SocialTraversalDsl.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import org.apache.tinkerpop.gremlin.process.traversal.dsl.GremlinDsl; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.structure.Vertex; - -@GremlinDsl(traversalSource = "com.datastax.dse.driver.api.core.graph.SocialTraversalSourceDsl") -public interface SocialTraversalDsl extends GraphTraversal.Admin { - public default GraphTraversal knows(String personName) { - return out("knows").hasLabel("person").has("name", personName).in(); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SocialTraversalSourceDsl.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SocialTraversalSourceDsl.java deleted file mode 100644 index e61b94e2d09..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/SocialTraversalSourceDsl.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection; -import org.apache.tinkerpop.gremlin.process.traversal.P; -import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep; -import org.apache.tinkerpop.gremlin.structure.Graph; -import org.apache.tinkerpop.gremlin.structure.Vertex; - -public class SocialTraversalSourceDsl extends GraphTraversalSource { - - public SocialTraversalSourceDsl( - final Graph graph, final TraversalStrategies traversalStrategies) { - super(graph, traversalStrategies); - } - - public SocialTraversalSourceDsl(final Graph graph) { - super(graph); - } - - public SocialTraversalSourceDsl(RemoteConnection connection) { - super(connection); - } - - public GraphTraversal persons(String... names) { - GraphTraversalSource clone = this.clone(); - - // Manually add a "start" step for the traversal in this case the equivalent of V(). GraphStep - // is marked - // as a "start" step by passing "true" in the constructor. - clone.getBytecode().addStep(GraphTraversal.Symbols.V); - GraphTraversal traversal = new DefaultGraphTraversal<>(clone); - traversal.asAdmin().addStep(new GraphStep(traversal.asAdmin(), Vertex.class, true)); - - traversal = traversal.hasLabel("person"); - if (names.length > 0) traversal = traversal.has("name", P.within(names)); - - return traversal; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerEdgeAssert.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerEdgeAssert.java deleted file mode 100644 index e3cc8cb687b..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerEdgeAssert.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import com.datastax.oss.driver.assertions.Assertions; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Vertex; - -public class TinkerEdgeAssert extends TinkerElementAssert { - - public TinkerEdgeAssert(Edge actual) { - super(actual, TinkerEdgeAssert.class); - } - - public TinkerEdgeAssert hasInVLabel(String label) { - Assertions.assertThat(actual.inVertex().label()).isEqualTo(label); - return myself; - } - - public TinkerEdgeAssert hasOutVLabel(String label) { - Assertions.assertThat(actual.outVertex().label()).isEqualTo(label); - return myself; - } - - public TinkerEdgeAssert hasOutV(Vertex vertex) { - Assertions.assertThat(actual.outVertex()).isEqualTo(vertex); - return myself; - } - - public TinkerEdgeAssert hasInV(Vertex vertex) { - Assertions.assertThat(actual.inVertex()).isEqualTo(vertex); - return myself; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerElementAssert.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerElementAssert.java deleted file mode 100644 index f54cec3065a..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerElementAssert.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.apache.tinkerpop.gremlin.structure.Element; -import org.assertj.core.api.AbstractAssert; - -public abstract class TinkerElementAssert, A extends Element> - extends AbstractAssert { - - protected TinkerElementAssert(A actual, Class selfType) { - super(actual, selfType); - } - - public S hasId(Object id) { - assertThat(actual.id()).isEqualTo(id); - return myself; - } - - public S hasLabel(String label) { - assertThat(actual.label()).isEqualTo(label); - return myself; - } - - public S hasProperty(String propertyName) { - assertThat(actual.property(propertyName).isPresent()).isTrue(); - return myself; - } - - public S hasProperty(String propertyName, Object value) { - hasProperty(propertyName); - assertThat(actual.property(propertyName).value()).isEqualTo(value); - return myself; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerGraphAssertions.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerGraphAssertions.java deleted file mode 100644 index 9c38a58db4c..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerGraphAssertions.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import org.apache.tinkerpop.gremlin.process.traversal.Path; -import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; - -public class TinkerGraphAssertions extends com.datastax.oss.driver.assertions.Assertions { - - public static TinkerEdgeAssert assertThat(Edge edge) { - return new TinkerEdgeAssert(edge); - } - - public static TinkerVertexAssert assertThat(Vertex vertex) { - return new TinkerVertexAssert(vertex); - } - - public static TinkerVertexPropertyAssert assertThat(VertexProperty vertexProperty) { - return new TinkerVertexPropertyAssert(vertexProperty); - } - - public static TinkerPathAssert assertThat(Path path) { - return new TinkerPathAssert(path); - } - - public static TinkerTreeAssert assertThat(Tree tree) { - return new TinkerTreeAssert<>(tree); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerPathAssert.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerPathAssert.java deleted file mode 100644 index 30f8f5fffa4..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerPathAssert.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.apache.tinkerpop.gremlin.process.traversal.Path; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.assertj.core.api.AbstractAssert; -import org.assertj.core.api.AbstractObjectAssert; - -public class TinkerPathAssert extends AbstractAssert { - - public TinkerPathAssert(Path actual) { - super(actual, TinkerPathAssert.class); - } - - /** - * Ensures that the given Path matches one of the exact traversals we'd expect for a person whom - * Marko knows that has created software and what software that is. - * - *

These paths should be: - * - *

    - *
  • marko -> knows -> josh -> created -> lop - *
  • marko -> knows -> josh -> created -> ripple - *
- */ - public static void validatePathObjects(Path path) { - - // marko should be the origin point. - TinkerGraphAssertions.assertThat(path).vertexAt(0).hasLabel("person"); - - // there should be a 'knows' outgoing relationship between marko and josh. - TinkerGraphAssertions.assertThat(path) - .edgeAt(1) - .hasLabel("knows") - .hasOutVLabel("person") - .hasOutV((Vertex) path.objects().get(0)) - .hasInVLabel("person") - .hasInV((Vertex) path.objects().get(2)); - - // josh... - TinkerGraphAssertions.assertThat(path).vertexAt(2).hasLabel("person"); - - // there should be a 'created' relationship between josh and lop. - TinkerGraphAssertions.assertThat(path) - .edgeAt(3) - .hasLabel("created") - .hasOutVLabel("person") - .hasOutV((Vertex) path.objects().get(2)) - .hasInVLabel("software") - .hasInV((Vertex) path.objects().get(4)); - - // lop.. - TinkerGraphAssertions.assertThat(path).vertexAt(4).hasLabel("software"); - } - - public AbstractObjectAssert objectAt(int i) { - assertThat(actual.size()).isGreaterThanOrEqualTo(i); - return assertThat(actual.objects().get(i)); - } - - public TinkerVertexAssert vertexAt(int i) { - assertThat(actual.size()).isGreaterThanOrEqualTo(i); - Object o = actual.objects().get(i); - assertThat(o).isInstanceOf(Vertex.class); - return new TinkerVertexAssert((Vertex) o); - } - - public TinkerEdgeAssert edgeAt(int i) { - assertThat(actual.size()).isGreaterThanOrEqualTo(i); - Object o = actual.objects().get(i); - assertThat(o).isInstanceOf(Edge.class); - return new TinkerEdgeAssert((Edge) o); - } - - public TinkerPathAssert hasLabel(int i, String... labels) { - assertThat(actual.labels().size()).isGreaterThanOrEqualTo(i); - assertThat(actual.labels().get(i)).containsExactly(labels); - return myself; - } - - public TinkerPathAssert hasNoLabel(int i) { - assertThat(actual.labels().size()).isGreaterThanOrEqualTo(i); - assertThat(actual.labels().get(i)).isEmpty(); - return myself; - } - - public TinkerPathAssert doesNotHaveLabel(String label) { - assertThat(actual.hasLabel(label)).isFalse(); - return myself; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerTreeAssert.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerTreeAssert.java deleted file mode 100644 index 6196e0a1021..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerTreeAssert.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; -import org.assertj.core.api.MapAssert; - -public class TinkerTreeAssert extends MapAssert> { - - public TinkerTreeAssert(Tree actual) { - super(actual); - } - - public TinkerTreeAssert hasTree(T key) { - assertThat(actual).containsKey(key); - return this; - } - - public TinkerTreeAssert isLeaf() { - assertThat(actual).hasSize(0); - return this; - } - - public TinkerTreeAssert tree(T key) { - hasTree(key); - return new TinkerTreeAssert<>(actual.get(key)); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerVertexAssert.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerVertexAssert.java deleted file mode 100644 index 3777fc8e96a..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerVertexAssert.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.apache.tinkerpop.gremlin.structure.Property; -import org.apache.tinkerpop.gremlin.structure.Vertex; - -public class TinkerVertexAssert extends TinkerElementAssert { - - public TinkerVertexAssert(Vertex actual) { - super(actual, TinkerVertexAssert.class); - } - - @Override - public TinkerVertexAssert hasProperty(String propertyName) { - assertThat(actual.properties(propertyName)).toIterable().isNotEmpty(); - return myself; - } - - @Override - public TinkerVertexAssert hasProperty(String propertyName, Object value) { - hasProperty(propertyName); - assertThat(actual.properties(propertyName)) - .toIterable() - .extracting(Property::value) - .contains(value); - return myself; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerVertexPropertyAssert.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerVertexPropertyAssert.java deleted file mode 100644 index 40bb8b5e239..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/TinkerVertexPropertyAssert.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.apache.tinkerpop.gremlin.structure.Element; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; - -public class TinkerVertexPropertyAssert - extends TinkerElementAssert, VertexProperty> { - - public TinkerVertexPropertyAssert(VertexProperty actual) { - super(actual, TinkerVertexPropertyAssert.class); - } - - public TinkerVertexPropertyAssert hasKey(String key) { - assertThat(actual.key()).isEqualTo(key); - return this; - } - - public TinkerVertexPropertyAssert hasParent(Element parent) { - assertThat(actual.element()).isEqualTo(parent); - return this; - } - - public TinkerVertexPropertyAssert hasValue(T value) { - assertThat(actual.value()).isEqualTo(value); - return this; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/reactive/DefaultReactiveGraphResultSetIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/reactive/DefaultReactiveGraphResultSetIT.java deleted file mode 100644 index b4c8bb05df4..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/reactive/DefaultReactiveGraphResultSetIT.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.reactive; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.internal.core.graph.GraphProtocol; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import io.reactivex.Flowable; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.RunWith; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8.0", - description = "Graph paging requires DSE 6.8+") -@RunWith(DataProviderRunner.class) -public class DefaultReactiveGraphResultSetIT { - - private static CustomCcmRule ccmRule = CustomCcmRule.builder().withDseWorkloads("graph").build(); - - private static SessionRule sessionRule = - SessionRule.builder(ccmRule) - .withCreateGraph() - .withCoreEngine() - .withGraphProtocol(GraphProtocol.GRAPH_BINARY_1_0.toInternalCode()) - .build(); - - @ClassRule public static TestRule chain = RuleChain.outerRule(ccmRule).around(sessionRule); - - @BeforeClass - public static void setupSchema() { - sessionRule - .session() - .execute( - ScriptGraphStatement.newInstance( - "schema.vertexLabel('person')" - + ".partitionBy('pk', Int)" - + ".clusterBy('cc', Int)" - + ".property('name', Text)" - + ".create();") - .setGraphName(sessionRule.getGraphName())); - for (int i = 1; i <= 1000; i++) { - sessionRule - .session() - .execute( - ScriptGraphStatement.newInstance( - String.format( - "g.addV('person').property('pk',0).property('cc',%d).property('name', '%s');", - i, "user" + i)) - .setGraphName(sessionRule.getGraphName())); - } - } - - @Test - @DataProvider( - value = {"1", "10", "100", "999", "1000", "1001", "2000"}, - format = "%m [page size %p[0]]") - public void should_retrieve_all_rows(int pageSize) { - DriverExecutionProfile profile = - sessionRule - .session() - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.GRAPH_CONTINUOUS_PAGING_PAGE_SIZE, pageSize); - ScriptGraphStatement statement = - ScriptGraphStatement.builder("g.V()").setExecutionProfile(profile).build(); - ReactiveGraphResultSet rs = sessionRule.session().executeReactive(statement); - List results = Flowable.fromPublisher(rs).toList().blockingGet(); - assertThat(results.size()).isEqualTo(1000); - Set expectedExecInfos = new LinkedHashSet<>(); - for (ReactiveGraphNode row : results) { - assertThat(row.getExecutionInfo()).isNotNull(); - assertThat(row.isVertex()).isTrue(); - expectedExecInfos.add(row.getExecutionInfo()); - } - List execInfos = - Flowable.fromPublisher(rs.getExecutionInfos()).toList().blockingGet(); - // DSE may send an empty page as it can't always know if it's done paging or not yet. - // See: CASSANDRA-8871. In this case, this page's execution info appears in - // rs.getExecutionInfos(), but is not present in expectedExecInfos since the page did not - // contain any rows. - assertThat(execInfos).containsAll(expectedExecInfos); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/ClassicGraphDataTypeRemoteIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/ClassicGraphDataTypeRemoteIT.java deleted file mode 100644 index b57d7a952bc..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/ClassicGraphDataTypeRemoteIT.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.remote; - -import com.datastax.dse.driver.api.core.graph.ClassicGraphDataTypeITBase; -import com.datastax.dse.driver.api.core.graph.DseGraph; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.SampleGraphScripts; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.3", - description = "DSE 5.0.3 required for remote TinkerPop support") -public class ClassicGraphDataTypeRemoteIT extends ClassicGraphDataTypeITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - @BeforeClass - public static void setupSchema() { - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.ALLOW_SCANS)); - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.MAKE_STRICT)); - } - - @Override - public CqlSession session() { - return SESSION_RULE.session(); - } - - private final GraphTraversalSource g = - AnonymousTraversalSource.traversal() - .withRemote(DseGraph.remoteConnectionBuilder(SESSION_RULE.session()).build()); - - @Override - public Vertex insertVertexAndReturn(String vertexLabel, String propertyName, Object value) { - return g.addV(vertexLabel).property(propertyName, value).next(); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/ClassicGraphTraversalRemoteIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/ClassicGraphTraversalRemoteIT.java deleted file mode 100644 index de85b6af267..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/ClassicGraphTraversalRemoteIT.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.remote; - -import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal; - -import com.datastax.dse.driver.api.core.graph.DseGraph; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.SampleGraphScripts; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.api.core.graph.SocialTraversalSource; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.9", - description = "DSE 5.0.9 required for inserting edges and vertices script.") -public class ClassicGraphTraversalRemoteIT extends GraphTraversalRemoteITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - @BeforeClass - public static void setupSchema() { - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.ALLOW_SCANS)); - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.CLASSIC_GRAPH)); - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.MAKE_STRICT)); - } - - @Override - protected CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - protected boolean isGraphBinary() { - return false; - } - - @Override - protected GraphTraversalSource graphTraversalSource() { - return traversal().withRemote(DseGraph.remoteConnectionBuilder(session()).build()); - } - - @Override - protected SocialTraversalSource socialTraversalSource() { - return traversal(SocialTraversalSource.class) - .withRemote(DseGraph.remoteConnectionBuilder(session()).build()); - } - - @Override - protected CustomCcmRule ccmRule() { - return CCM_RULE; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/CoreGraphDataTypeRemoteIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/CoreGraphDataTypeRemoteIT.java deleted file mode 100644 index 88b9cdc0433..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/CoreGraphDataTypeRemoteIT.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.remote; - -import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.unfold; - -import com.datastax.dse.driver.api.core.graph.CoreGraphDataTypeITBase; -import com.datastax.dse.driver.api.core.graph.DseGraph; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import java.util.Map; -import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.RunWith; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8.0", - description = "DSE 6.8.0 required for Core graph support") -@RunWith(DataProviderRunner.class) -public class CoreGraphDataTypeRemoteIT extends CoreGraphDataTypeITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.CCM_BUILDER_WITH_GRAPH.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getCoreGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - @Override - protected CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - protected String graphName() { - return SESSION_RULE.getGraphName(); - } - - private final GraphTraversalSource g = - AnonymousTraversalSource.traversal() - .withRemote(DseGraph.remoteConnectionBuilder(session()).build()); - - @Override - public Map insertVertexThenReadProperties( - Map properties, int vertexID, String vertexLabel) { - GraphTraversal traversal = g.addV(vertexLabel).property("id", vertexID); - - for (Map.Entry entry : properties.entrySet()) { - String typeDefinition = entry.getKey(); - String propName = formatPropertyName(typeDefinition); - Object value = entry.getValue(); - traversal = traversal.property(propName, value); - } - - // insert vertex - traversal.iterate(); - - // query properties - return g.V().has(vertexLabel, "id", vertexID).valueMap().by(unfold()).next(); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/CoreGraphTraversalRemoteIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/CoreGraphTraversalRemoteIT.java deleted file mode 100644 index 2bbdf1f6d45..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/CoreGraphTraversalRemoteIT.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.remote; - -import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal; - -import com.datastax.dse.driver.api.core.graph.DseGraph; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.SampleGraphScripts; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.api.core.graph.SocialTraversalSource; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8", - description = "DSE 6.8 required for Core graph support") -public class CoreGraphTraversalRemoteIT extends GraphTraversalRemoteITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getCoreGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - @BeforeClass - public static void setupSchema() { - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(SampleGraphScripts.CORE_GRAPH)); - } - - @Override - protected CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - protected boolean isGraphBinary() { - return true; - } - - @Override - protected GraphTraversalSource graphTraversalSource() { - return traversal() - .withRemote(DseGraph.remoteConnectionBuilder(session()).build()) - .with("allow-filtering"); - } - - @Override - protected SocialTraversalSource socialTraversalSource() { - return traversal(SocialTraversalSource.class) - .withRemote(DseGraph.remoteConnectionBuilder(session()).build()) - .with("allow-filtering"); - } - - @Override - protected CustomCcmRule ccmRule() { - return CCM_RULE; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalMetaPropertiesRemoteIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalMetaPropertiesRemoteIT.java deleted file mode 100644 index 2966fb44cf9..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalMetaPropertiesRemoteIT.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.remote; - -import static com.datastax.dse.driver.api.core.graph.SampleGraphScripts.ALLOW_SCANS; -import static com.datastax.dse.driver.api.core.graph.SampleGraphScripts.MAKE_STRICT; -import static com.datastax.dse.driver.api.core.graph.TinkerGraphAssertions.assertThat; - -import com.datastax.dse.driver.api.core.graph.DseGraph; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -// INFO: meta props are going away in NGDG - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.3", - description = "DSE 5.0.3 required for remote TinkerPop support") -public class GraphTraversalMetaPropertiesRemoteIT { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - private final GraphTraversalSource g = - AnonymousTraversalSource.traversal() - .withRemote(DseGraph.remoteConnectionBuilder(SESSION_RULE.session()).build()); - - /** Builds a simple schema that provides for a vertex with a property with sub properties. */ - public static final String META_PROPS = - MAKE_STRICT - + ALLOW_SCANS - + "schema.propertyKey('sub_prop').Text().create()\n" - + "schema.propertyKey('sub_prop2').Text().create()\n" - + "schema.propertyKey('meta_prop').Text().properties('sub_prop', 'sub_prop2').create()\n" - + "schema.vertexLabel('meta_v').properties('meta_prop').create()"; - - /** - * Ensures that a traversal that yields a vertex with a property that has its own properties that - * is appropriately parsed and made accessible via {@link VertexProperty#property}. - * - * @test_category dse:graph - */ - @Test - public void should_parse_meta_properties() { - // given a schema that defines meta properties. - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(META_PROPS)); - - // when adding a vertex with that meta property - Vertex v = - g.addV("meta_v") - .property("meta_prop", "hello", "sub_prop", "hi", "sub_prop2", "hi2") - .next(); - - // then the created vertex should have the meta prop present with its sub properties. - assertThat(v).hasProperty("meta_prop"); - VertexProperty metaProp = v.property("meta_prop"); - assertThat(metaProp) - .hasValue("hello") - .hasProperty("sub_prop", "hi") - .hasProperty("sub_prop2", "hi2"); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalMultiPropertiesRemoteIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalMultiPropertiesRemoteIT.java deleted file mode 100644 index c55a7b67c4a..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalMultiPropertiesRemoteIT.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.remote; - -import static com.datastax.dse.driver.api.core.graph.SampleGraphScripts.ALLOW_SCANS; -import static com.datastax.dse.driver.api.core.graph.SampleGraphScripts.MAKE_STRICT; -import static com.datastax.dse.driver.api.core.graph.TinkerGraphAssertions.assertThat; - -import com.datastax.dse.driver.api.core.graph.DseGraph; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import java.util.Iterator; -import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -// INFO: multi props are not supported in Core -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.3", - description = "DSE 5.0.3 required for remote TinkerPop support") -public class GraphTraversalMultiPropertiesRemoteIT { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - private final GraphTraversalSource g = - AnonymousTraversalSource.traversal() - .withRemote(DseGraph.remoteConnectionBuilder(SESSION_RULE.session()).build()); - - /** Builds a simple schema that provides for a vertex with a multi-cardinality property. */ - public static final String MULTI_PROPS = - MAKE_STRICT - + ALLOW_SCANS - + "schema.propertyKey('multi_prop').Text().multiple().create()\n" - + "schema.vertexLabel('multi_v').properties('multi_prop').create()\n"; - - /** - * Ensures that a traversal that yields a vertex with a property name that is present multiple - * times that the properties are parsed and made accessible via {@link - * Vertex#properties(String...)}. - * - * @test_category dse:graph - */ - @Test - public void should_parse_multiple_cardinality_properties() { - // given a schema that defines multiple cardinality properties. - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(MULTI_PROPS)); - - // when adding a vertex with a multiple cardinality property - Vertex v = - g.addV("multi_v") - .property("multi_prop", "Hello") - .property("multi_prop", "Sweet") - .property("multi_prop", "World") - .next(); - - // then the created vertex should have the multi-cardinality property present with its values. - assertThat(v).hasProperty("multi_prop"); - Iterator> multiProp = v.properties("multi_prop"); - assertThat(multiProp) - .toIterable() - .extractingResultOf("value") - .containsExactly("Hello", "Sweet", "World"); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalRemoteITBase.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalRemoteITBase.java deleted file mode 100644 index 3db8a7d1a12..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalRemoteITBase.java +++ /dev/null @@ -1,661 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.remote; - -import static com.datastax.dse.driver.api.core.graph.TinkerGraphAssertions.assertThat; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.assertThatContainsLabel; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.assertThatContainsProperties; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.fail; - -import com.datastax.dse.driver.Assertions; -import com.datastax.dse.driver.api.core.graph.SocialTraversalSource; -import com.datastax.dse.driver.api.core.graph.TinkerPathAssert; -import com.datastax.dse.driver.api.core.graph.__; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.Version; -import com.datastax.oss.driver.api.core.servererrors.InvalidQueryException; -import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; -import org.apache.tinkerpop.gremlin.process.traversal.Path; -import org.apache.tinkerpop.gremlin.process.traversal.Traversal; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; -import org.apache.tinkerpop.gremlin.structure.Direction; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Graph; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.assertj.core.api.Assumptions; -import org.junit.Test; - -public abstract class GraphTraversalRemoteITBase { - - protected abstract CqlSession session(); - - protected abstract boolean isGraphBinary(); - - protected abstract GraphTraversalSource graphTraversalSource(); - - protected abstract SocialTraversalSource socialTraversalSource(); - - protected abstract CustomCcmRule ccmRule(); - - /** - * Ensures that a previously returned {@link Vertex}'s {@link Vertex#id()} can be used as an input - * to {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource#V(Object...)} to - * retrieve the {@link Vertex} and that the returned {@link Vertex} is the same. - * - * @test_category dse:graph - */ - @Test - public void should_use_vertex_id_as_parameter() { - GraphTraversalSource g = graphTraversalSource(); - - // given an existing vertex - Vertex marko = g.V().hasLabel("person").has("name", "marko").next(); - if (isGraphBinary()) { - Map properties = - g.V().hasLabel("person").has("name", "marko").elementMap("name").next(); - - assertThat(properties).containsEntry("name", "marko"); - } else { - assertThat(marko).hasProperty("name", "marko"); - } - - // then should be able to retrieve that same vertex by id. - assertThat(g.V(marko.id()).next()).isEqualTo(marko); - } - - /** - * Ensures that a previously returned {@link Edge}'s {@link Edge#id()} can be used as an input to - * {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource#E(Object...)} to - * retrieve the {@link Edge} and that the returned {@link Edge} is the same. - * - * @test_category dse:graph - */ - @Test - public void should_use_edge_is_as_parameter() { - GraphTraversalSource g = graphTraversalSource(); - - // given an existing edge - Edge created = g.E().has("weight", 0.2f).next(); - - if (isGraphBinary()) { - List> properties = - g.E().has("weight").elementMap("weight", "software", "person").toList(); - - assertThat(properties) - .anySatisfy( - props -> { - assertThatContainsProperties(props, "weight", 0.2f); - assertThatContainsLabel(props, Direction.IN, "software"); - assertThatContainsLabel(props, Direction.OUT, "person"); - }); - - } else { - assertThat(created) - .hasProperty("weight", 0.2f) - .hasInVLabel("software") - .hasOutVLabel("person"); - } - - // should be able to retrieve incoming and outgoing vertices by edge id - if (isGraphBinary()) { - Map inProperties = g.E(created.id()).inV().elementMap("name", "lang").next(); - Map outProperties = g.E(created.id()).outV().elementMap("name").next(); - assertThatContainsProperties(inProperties, "name", "lop", "lang", "java"); - assertThatContainsProperties(outProperties, "name", "peter"); - - } else { - Vertex in = g.E(created.id()).inV().next(); - Vertex out = g.E(created.id()).outV().next(); - - // should resolve to lop - assertThat(in).hasLabel("software").hasProperty("name", "lop").hasProperty("lang", "java"); - - // should resolve to marko, josh and peter whom created lop. - assertThat(out).hasLabel("person").hasProperty("name", "peter"); - } - } - - /** - * A sanity check that a returned {@link Vertex}'s id is a {@link Map}. This test could break in - * the future if the format of a vertex ID changes from a Map to something else in DSE. - * - * @test_category dse:graph - */ - @Test - public void should_deserialize_vertex_id_as_map() { - GraphTraversalSource g = graphTraversalSource(); - // given an existing vertex - Vertex marko = g.V().hasLabel("person").has("name", "marko").next(); - - // then id should be a map with expected values. - // Note: this is pretty dependent on DSE Graphs underlying id structure which may vary in - // the future. - if (isGraphBinary()) { - assertThat(((String) marko.id())).contains("marko"); - assertThat(marko.label()).isEqualTo("person"); - } else { - @SuppressWarnings("unchecked") - Map id = (Map) marko.id(); - assertThat(id) - .hasSize(3) - .containsEntry("~label", "person") - .containsKey("community_id") - .containsKey("member_id"); - } - } - - /** - * Ensures that a traversal that returns a result of mixed types is interpreted as a {@link Map} - * with {@link Object} values. Also uses {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal#by(Traversal)} with an - * anonymous traversal to get inbound 'created' edges and folds them into a list. - * - *

Executes a vertex traversal that binds label 'a' and 'b' to vertex properties and label 'c' - * to vertices that have edges from that vertex. - * - * @test_category dse:graph - */ - @Test - public void should_handle_result_object_of_mixed_types() { - GraphTraversalSource g = graphTraversalSource(); - // find all software vertices and select name, language, and find all vertices that created - // such software. - List> results = - g.V() - .hasLabel("software") - .as("a", "b", "c") - .select("a", "b", "c") - .by("name") - .by("lang") - .by(__.in("created").fold()) - .toList(); - - // ensure that lop and ripple and their data are the results return. - assertThat(results).extracting(m -> m.get("a")).containsOnly("lop", "ripple"); - - for (Map result : results) { - assertThat(result).containsOnlyKeys("a", "b", "c"); - // both software are written in java. - assertThat(result.get("b")).isEqualTo("java"); - // ensure the created vertices match the creators of the software. - @SuppressWarnings("unchecked") - List vertices = (List) result.get("c"); - if (result.get("a").equals("lop")) { - if (isGraphBinary()) { - // should contain three vertices - assertThat(vertices.size()).isEqualTo(3); - } else { - // lop, 'c' should contain marko, josh, peter. - assertThat(vertices) - .extracting(vertex -> vertex.property("name").value()) - .containsOnly("marko", "josh", "peter"); - } - } else { - if (isGraphBinary()) { - // has only one label - assertThat(vertices.size()).isEqualTo(1); - } else { - assertThat(vertices) - .extracting(vertex -> vertex.property("name").value()) - .containsOnly("josh"); - } - } - } - } - - /** - * Ensures that a traversal that returns a sub graph can be retrieved. - * - *

The subgraph is all members in a knows relationship, thus is all people who marko knows and - * the edges that connect them. - */ - @Test - public void should_handle_subgraph_graphson() { - Assumptions.assumeThat(isGraphBinary()).isFalse(); - - GraphTraversalSource g = graphTraversalSource(); - // retrieve a subgraph on the knows relationship, this omits the created edges. - Graph graph = (Graph) g.E().hasLabel("knows").subgraph("subGraph").cap("subGraph").next(); - - // there should only be 2 edges (since there are are only 2 knows relationships) and 3 vertices - assertThat(graph.edges()).toIterable().hasSize(2); - assertThat(graph.vertices()).toIterable().hasSize(3); - } - - /** - * Ensures that a traversal that returns a sub graph can be retrieved. - * - *

The subgraph is all members in a knows relationship, thus is all people who marko knows and - * the edges that connect them. - */ - @Test - public void should_handle_subgraph_graph_binary() { - Assumptions.assumeThat(isGraphBinary()).isTrue(); - - GraphTraversalSource g = graphTraversalSource(); - // retrieve a subgraph on the knows relationship, this omits the created edges. - String graph = (String) g.E().hasLabel("knows").subgraph("subGraph").cap("subGraph").next(); - - // there should only be 2 edges (since there are are only 2 knows relationships) and 3 vertices - assertThat(graph).contains("vertices:3").contains("edges:2"); - } - - /** - * Ensures a traversal that yields no results is properly retrieved and is empty. - * - * @test_category dse:graph - */ - @Test - public void should_return_zero_results() { - if (isGraphBinary()) { - assertThatThrownBy(() -> graphTraversalSource().V().hasLabel("notALabel").toList()) - .isInstanceOf(InvalidQueryException.class) - .hasMessageContaining("Unknown vertex label 'notALabel'"); - } else { - assertThat(graphTraversalSource().V().hasLabel("notALabel").toList()).isEmpty(); - } - } - - /** - * Validates that a traversal returning a {@link Tree} structure is returned appropriately with - * the expected contents. - * - *

Retrieves trees of people marko knows and the software they created. - * - * @test_category dse:graph - */ - @Test - public void should_parse_tree() { - // Get a tree structure showing the paths from mark to people he knows to software they've - // created. - @SuppressWarnings("unchecked") - Tree tree = - graphTraversalSource() - .V() - .hasLabel("person") - .out("knows") - .out("created") - .tree() - .by("name") - .next(); - - // Marko knows josh who created lop and ripple. - assertThat(tree).tree("marko").tree("josh").tree("lop").isLeaf(); - - assertThat(tree).tree("marko").tree("josh").tree("ripple").isLeaf(); - } - - /** - * Validates that a traversal using lambda operations with anonymous traversals are applied - * appropriately and return the expected results. - * - *

Traversal that filters 'person'-labeled vertices by name 'marko' and flatMaps outgoing - * vertices on the 'knows' relationship by their outgoing 'created' vertices and then maps by - * their 'name' property and folds them into one list. - * - *

Note: This does not validate lambdas with functions as those can't be interpreted and - * sent remotely. - * - * @test_category dse:graph - */ - @Test - public void should_handle_lambdas() { - // Find all people marko knows and the software they created. - List software = - graphTraversalSource() - .V() - .hasLabel("person") - .filter(__.has("name", "marko")) - .out("knows") - .flatMap(__.out("created")) - .map(__.values("name")) - .fold() - .next(); - - // Marko only knows josh and vadas, of which josh created lop and ripple. - assertThat(software).containsOnly("lop", "ripple"); - } - - /** - * Validates that {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal#tryNext()} functions - * appropriate by returning an {@link Optional} of which the presence of the underlying data - * depends on whether or not remaining data is present. - * - *

This is more of a test of Tinkerpop than the protocol between the client and DSE graph. - * - * @test_category dse:graph - */ - @Test - public void should_handle_tryNext() { - GraphTraversal traversal = - graphTraversalSource().V().hasLabel("person").has("name", "marko"); - - // value present - Optional v0 = traversal.tryNext(); - assertThat(v0.isPresent()).isTrue(); - if (!isGraphBinary()) { - assertThat(v0.get()).hasProperty("name", "marko"); - } - - // value absent as there was only 1 matching vertex. - Optional v1 = traversal.tryNext(); - assertThat(v1.isPresent()).isFalse(); - } - - /** - * Validates that {@link GraphTraversal#toStream()} appropriately creates a stream from the - * underlying iterator on the traversal, and then an attempt to call toStream again yields no - * results. - * - *

This is more of a test of Tinkerpop than the protocol between the client and DSE graph. - * - * @test_category dse:graph - */ - @Test - public void should_handle_streaming_graphson() { - Assumptions.assumeThat(isGraphBinary()).isFalse(); - - GraphTraversal traversal = graphTraversalSource().V().hasLabel("person"); - // retrieve all person vertices to stream, and filter on client side all persons under age 30 - // and map to their name. - List under30 = - traversal - .toStream() - .filter(v -> v.property("age").value() < 30) - .map(v -> v.property("name").value()) - .collect(Collectors.toList()); - - assertThat(under30).containsOnly("marko", "vadas"); - - // attempt to get a stream again, which should be empty. - assertThat(traversal.toStream().collect(Collectors.toList())).isEmpty(); - } - - /** - * Validates that {@link GraphTraversal#toStream()} appropriately creates a stream from the - * underlying iterator on the traversal, and then an attempt to call toStream again yields no - * results. - * - *

This is more of a test of Tinkerpop than the protocol between the client and DSE graph. - * - * @test_category dse:graph - */ - @Test - public void should_handle_streaming_binary() { - Assumptions.assumeThat(isGraphBinary()).isTrue(); - - GraphTraversal> traversal = - graphTraversalSource().V().hasLabel("person").elementMap("age", "name"); - // retrieve all person vertices to stream, and filter on client side all persons under age 30 - // and map to their name. - List under30 = - traversal - .toStream() - .filter(v -> (Integer) v.get("age") < 30) - .map(v -> (String) v.get("name")) - .collect(Collectors.toList()); - - assertThat(under30).containsOnly("marko", "vadas"); - - // attempt to get a stream again, which should be empty. - assertThat(traversal.toStream().collect(Collectors.toList())).isEmpty(); - } - - /** - * Validates that when traversing a path and labeling some of the elements during the traversal - * that the output elements are properly labeled. - * - * @test_category dse:graph - */ - @Test - public void should_resolve_path_with_some_labels() { - // given a traversal where some objects have labels. - List paths = - graphTraversalSource() - .V() - .hasLabel("person") - .has("name", "marko") - .as("a") - .outE("knows") - .inV() - .as("c", "d") - .outE("created") - .as("e", "f", "g") - .inV() - .path() - .toList(); - - // then the paths returned should be labeled for the - // appropriate objects, and not labeled otherwise. - for (Path path : paths) { - TinkerPathAssert.validatePathObjects(path); - assertThat(path) - .hasLabel(0, "a") - .hasNoLabel(1) - .hasLabel(2, "c", "d") - .hasLabel(3, "e", "f", "g") - .hasNoLabel(4); - } - } - - /** - * Validates that when traversing a path and labeling all of the elements during the traversal - * that the output elements are properly labeled. - * - * @test_category dse:graph - */ - @Test - public void should_resolve_path_with_labels() { - // given a traversal where all objects have labels. - List paths = - graphTraversalSource() - .V() - .hasLabel("person") - .has("name", "marko") - .as("a") - .outE("knows") - .as("b") - .inV() - .as("c", "d") - .outE("created") - .as("e", "f", "g") - .inV() - .as("h") - .path() - .toList(); - - // then the paths returned should be labeled for all - // objects. - for (Path path : paths) { - TinkerPathAssert.validatePathObjects(path); - Assertions.assertThat(path.labels()).hasSize(5); - assertThat(path) - .hasLabel(0, "a") - .hasLabel(1, "b") - .hasLabel(2, "c", "d") - .hasLabel(3, "e", "f", "g") - .hasLabel(4, "h"); - } - } - - /** - * Validates that when traversing a path and labeling none of the elements during the traversal - * that all the labels are empty in the result. - * - * @test_category dse:graph - */ - @Test - public void should_resolve_path_without_labels() { - // given a traversal where no objects have labels. - List paths = - graphTraversalSource() - .V() - .hasLabel("person") - .has("name", "marko") - .outE("knows") - .inV() - .outE("created") - .inV() - .path() - .toList(); - - // then the paths returned should be labeled for - // all objects. - for (Path path : paths) { - TinkerPathAssert.validatePathObjects(path); - for (int i = 0; i < 5; i++) assertThat(path).hasNoLabel(i); - } - } - - @Test - public void should_handle_asynchronous_execution_graphson() { - Assumptions.assumeThat(isGraphBinary()).isFalse(); - - StringBuilder names = new StringBuilder(); - - CompletableFuture> future = - graphTraversalSource().V().hasLabel("person").promise(Traversal::toList); - try { - // dumb processing to make sure the completable future works correctly and correct results are - // returned - future - .thenAccept( - vertices -> vertices.forEach(vertex -> names.append((String) vertex.value("name")))) - .get(); - } catch (InterruptedException | ExecutionException e) { - fail("Shouldn't have thrown an exception waiting for the result to complete"); - } - - assertThat(names.toString()).contains("peter", "marko", "vadas", "josh"); - } - - @Test - public void should_handle_asynchronous_execution_graph_binary() { - Assumptions.assumeThat(isGraphBinary()).isTrue(); - - StringBuilder names = new StringBuilder(); - - CompletableFuture> future = - graphTraversalSource().V().hasLabel("person").promise(Traversal::toList); - try { - // dumb processing to make sure the completable future works correctly and correct results are - // returned - future.thenAccept(vertices -> vertices.forEach(vertex -> names.append(vertex.id()))).get(); - } catch (InterruptedException | ExecutionException e) { - fail("Shouldn't have thrown an exception waiting for the result to complete"); - } - - assertThat(names.toString()).contains("peter", "marko", "vadas", "josh"); - } - - /** - * Validates that if a traversal is made that encounters an error on the server side that the - * exception is set on the future. - * - * @test_category dse:graph - */ - @Test - @BackendRequirement(type = BackendType.DSE, minInclusive = "5.1.0") - public void should_fail_future_returned_from_promise_on_query_error() throws Exception { - CompletableFuture future = - graphTraversalSource().V("invalidid").peerPressure().promise(Traversal::next); - - try { - future.get(); - fail("Expected an ExecutionException"); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(InvalidQueryException.class); - } - } - - /** - * A simple smoke test to ensure that a user can supply a custom {@link GraphTraversalSource} for - * use with DSLs. - * - * @test_category dse:graph - */ - @Test - public void should_allow_use_of_dsl_graphson() { - Assumptions.assumeThat(isGraphBinary()).isFalse(); - - List vertices = socialTraversalSource().persons("marko").knows("vadas").toList(); - assertThat(vertices.size()).isEqualTo(1); - assertThat(vertices.get(0)) - .hasProperty("name", "marko") - .hasProperty("age", 29) - .hasLabel("person"); - } - - /** - * A simple smoke test to ensure that a user can supply a custom {@link GraphTraversalSource} for - * use with DSLs. - * - * @test_category dse:graph - */ - @Test - public void should_allow_use_of_dsl_graph_binary() { - Assumptions.assumeThat(isGraphBinary()).isTrue(); - - List> vertices = - socialTraversalSource().persons("marko").knows("vadas").elementMap("name", "age").toList(); - assertThat(vertices.size()).isEqualTo(1); - - assertThatContainsProperties(vertices.get(0), "name", "marko", "age", 29); - assertThat(vertices.get(0).values()).contains("person"); - } - - /** - * Ensures that traversals with barriers (which return results bulked) contain the correct amount - * of end results. - * - *

This will fail if ran against DSE < 5.0.9 or DSE < 5.1.2. - */ - @Test - public void should_return_correct_results_when_bulked() { - Assumptions.assumeThat( - CcmBridge.isDistributionOf( - BackendType.DSE, (dist, cass) -> dist.compareTo(Version.parse("5.1.2")) > 0)) - .isTrue(); - - List results = graphTraversalSource().E().label().barrier().toList(); - Collections.sort(results); - - List expected = - Arrays.asList("knows", "created", "created", "knows", "created", "created"); - Collections.sort(expected); - - assertThat(results).isEqualTo(expected); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphDataTypeFluentIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphDataTypeFluentIT.java deleted file mode 100644 index d1355100c4b..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphDataTypeFluentIT.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import com.datastax.dse.driver.api.core.graph.ClassicGraphDataTypeITBase; -import com.datastax.dse.driver.api.core.graph.DseGraph; -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.SampleGraphScripts; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.3", - description = "DSE 5.0.3 required for fluent API support") -public class ClassicGraphDataTypeFluentIT extends ClassicGraphDataTypeITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.CCM_BUILDER_WITH_GRAPH.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - @BeforeClass - public static void setupSchema() { - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.ALLOW_SCANS)); - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.MAKE_STRICT)); - } - - @Override - public CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - public Vertex insertVertexAndReturn(String vertexLabel, String propertyName, Object value) { - return SESSION_RULE - .session() - .execute( - FluentGraphStatement.newInstance( - DseGraph.g.addV(vertexLabel).property(propertyName, value))) - .one() - .asVertex(); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphDataTypeScriptIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphDataTypeScriptIT.java deleted file mode 100644 index 81f088d0c18..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphDataTypeScriptIT.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import com.datastax.dse.driver.api.core.graph.ClassicGraphDataTypeITBase; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.SampleGraphScripts; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.4", - description = "DSE 5.0.4 required for script API with GraphSON 2") -public class ClassicGraphDataTypeScriptIT extends ClassicGraphDataTypeITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.CCM_BUILDER_WITH_GRAPH.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - @BeforeClass - public static void setupSchema() { - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.ALLOW_SCANS)); - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.MAKE_STRICT)); - } - - @Override - public CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - public Vertex insertVertexAndReturn(String vertexLabel, String propertyName, Object value) { - return SESSION_RULE - .session() - .execute( - ScriptGraphStatement.builder("g.addV(labelP).property(nameP, valueP)") - .setQueryParam("labelP", vertexLabel) - .setQueryParam("nameP", propertyName) - .setQueryParam("valueP", value) - .build()) - .one() - .asVertex(); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphTraversalBatchIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphTraversalBatchIT.java deleted file mode 100644 index 81f39753856..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphTraversalBatchIT.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.SampleGraphScripts; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.0", - description = "DSE 6.0 required for BatchGraphStatement.") -public class ClassicGraphTraversalBatchIT extends GraphTraversalBatchITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - private final GraphTraversalSource g = EmptyGraph.instance().traversal(); - - @BeforeClass - public static void setupSchema() { - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.ALLOW_SCANS)); - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.MAKE_NOT_STRICT)); - } - - @Override - protected CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - protected boolean isGraphBinary() { - return false; - } - - @Override - protected CustomCcmRule ccmRule() { - return CCM_RULE; - } - - @Override - protected GraphTraversalSource graphTraversalSource() { - return g; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphTraversalIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphTraversalIT.java deleted file mode 100644 index 672e1b6f679..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/ClassicGraphTraversalIT.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.SampleGraphScripts; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.api.core.graph.SocialTraversalSource; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.9", - description = "DSE 5.0.9 required for inserting edges and vertices script.") -public class ClassicGraphTraversalIT extends GraphTraversalITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - private final GraphTraversalSource graphTraversalSource = EmptyGraph.instance().traversal(); - private final SocialTraversalSource socialTraversal = - EmptyGraph.instance().traversal(SocialTraversalSource.class); - - @BeforeClass - public static void setupSchema() { - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.ALLOW_SCANS)); - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.CLASSIC_GRAPH)); - SESSION_RULE - .session() - .execute(ScriptGraphStatement.newInstance(SampleGraphScripts.MAKE_STRICT)); - } - - @Override - protected CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - protected boolean isGraphBinary() { - return false; - } - - @Override - protected CustomCcmRule ccmRule() { - return CCM_RULE; - } - - @Override - protected GraphTraversalSource graphTraversalSource() { - return graphTraversalSource; - } - - @Override - protected SocialTraversalSource socialTraversalSource() { - return socialTraversal; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphDataTypeFluentIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphDataTypeFluentIT.java deleted file mode 100644 index 94e6415f471..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphDataTypeFluentIT.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import static com.datastax.dse.driver.api.core.graph.DseGraph.g; -import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.unfold; - -import com.datastax.dse.driver.api.core.graph.CoreGraphDataTypeITBase; -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import java.util.Map; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.RunWith; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8.0", - description = "DSE 6.8.0 required for Core graph support") -@RunWith(DataProviderRunner.class) -public class CoreGraphDataTypeFluentIT extends CoreGraphDataTypeITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.CCM_BUILDER_WITH_GRAPH.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getCoreGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - @Override - protected CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - protected String graphName() { - return SESSION_RULE.getGraphName(); - } - - @Override - public Map insertVertexThenReadProperties( - Map properties, int vertexID, String vertexLabel) { - GraphTraversal traversal = g.addV(vertexLabel).property("id", vertexID); - - for (Map.Entry entry : properties.entrySet()) { - String typeDefinition = entry.getKey(); - String propName = formatPropertyName(typeDefinition); - Object value = entry.getValue(); - traversal = traversal.property(propName, value); - } - - session().execute(FluentGraphStatement.newInstance(traversal)); - - return session() - .execute( - FluentGraphStatement.newInstance( - g.V().has(vertexLabel, "id", vertexID).valueMap().by(unfold()))) - .one() - .asMap(); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphDataTypeScriptIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphDataTypeScriptIT.java deleted file mode 100644 index b79aecf6c6a..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphDataTypeScriptIT.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import com.datastax.dse.driver.api.core.graph.CoreGraphDataTypeITBase; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatementBuilder; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import java.util.Map; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.RunWith; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8.0", - description = "DSE 6.8.0 required for Core graph support") -@RunWith(DataProviderRunner.class) -public class CoreGraphDataTypeScriptIT extends CoreGraphDataTypeITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.CCM_BUILDER_WITH_GRAPH.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getCoreGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - @Override - protected CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - protected String graphName() { - return SESSION_RULE.getGraphName(); - } - - @Override - protected Map insertVertexThenReadProperties( - Map properties, int vertexID, String vertexLabel) { - StringBuilder insert = new StringBuilder("g.addV(vertexLabel).property('id', vertexID)"); - - ScriptGraphStatementBuilder statementBuilder = - new ScriptGraphStatementBuilder() - .setQueryParam("vertexID", vertexID) - .setQueryParam("vertexLabel", vertexLabel); - - for (Map.Entry entry : properties.entrySet()) { - String typeDefinition = entry.getKey(); - String propName = formatPropertyName(typeDefinition); - Object value = entry.getValue(); - - insert.append(String.format(".property('%s', %s)", propName, propName)); - statementBuilder = statementBuilder.setQueryParam(propName, value); - } - - session().execute(statementBuilder.setScript(insert.toString()).build()); - - return session() - .execute( - ScriptGraphStatement.newInstance( - "g.V().has(vertexLabel, 'id', vertexID).valueMap().by(unfold())") - .setQueryParam("vertexID", vertexID) - .setQueryParam("vertexLabel", vertexLabel)) - .one() - .asMap(); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphTraversalBatchIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphTraversalBatchIT.java deleted file mode 100644 index be09ac1bfb2..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphTraversalBatchIT.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.SampleGraphScripts; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8.0", - description = "DSE 6.8.0 required for Core graph support") -public class CoreGraphTraversalBatchIT extends GraphTraversalBatchITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getCoreGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - private final GraphTraversalSource g = EmptyGraph.instance().traversal().with("allow-filtering"); - - @BeforeClass - public static void setupSchema() { - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(SampleGraphScripts.CORE_GRAPH)); - } - - @Override - protected CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - protected boolean isGraphBinary() { - return true; - } - - @Override - protected CustomCcmRule ccmRule() { - return CCM_RULE; - } - - @Override - protected GraphTraversalSource graphTraversalSource() { - return g; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphTraversalIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphTraversalIT.java deleted file mode 100644 index d97b0da958a..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/CoreGraphTraversalIT.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.SampleGraphScripts; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.api.core.graph.SocialTraversalSource; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8.0", - description = "DSE 6.8.0 required for Core graph support") -public class CoreGraphTraversalIT extends GraphTraversalITBase { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.CCM_BUILDER_WITH_GRAPH.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getCoreGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - private final GraphTraversalSource graphTraversalSource = - EmptyGraph.instance().traversal().with("allow-filtering"); - private final SocialTraversalSource socialTraversalSource = - EmptyGraph.instance().traversal(SocialTraversalSource.class).with("allow-filtering"); - - @BeforeClass - public static void setupSchema() { - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(SampleGraphScripts.CORE_GRAPH)); - } - - @Override - protected CqlSession session() { - return SESSION_RULE.session(); - } - - @Override - protected boolean isGraphBinary() { - return true; - } - - @Override - protected CustomCcmRule ccmRule() { - return CCM_RULE; - } - - @Override - protected GraphTraversalSource graphTraversalSource() { - return graphTraversalSource; - } - - @Override - protected SocialTraversalSource socialTraversalSource() { - return socialTraversalSource; - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalBatchITBase.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalBatchITBase.java deleted file mode 100644 index 0c8c3b8b5d4..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalBatchITBase.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import static com.datastax.dse.driver.api.core.graph.TinkerGraphAssertions.assertThat; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.assertThatContainsLabel; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.assertThatContainsProperties; -import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.addE; -import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.addV; -import static org.assertj.core.api.Assertions.fail; - -import com.datastax.dse.driver.api.core.graph.BatchGraphStatement; -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.servererrors.InvalidQueryException; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import java.util.Map; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; -import org.apache.tinkerpop.gremlin.structure.Direction; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.junit.Test; - -public abstract class GraphTraversalBatchITBase { - - protected abstract CqlSession session(); - - protected abstract boolean isGraphBinary(); - - protected abstract CustomCcmRule ccmRule(); - - protected abstract GraphTraversalSource graphTraversalSource(); - - @Test - public void should_allow_vertex_and_edge_insertions_in_batch() { - BatchGraphStatement batch = - BatchGraphStatement.builder() - .addTraversals( - ImmutableList.of( - addV("person").property("name", "batch1").property("age", 1), - addV("person").property("name", "batch2").property("age", 2))) - .build(); - - BatchGraphStatement batch2 = - BatchGraphStatement.builder() - .addTraversals(batch) - .addTraversal( - addE("knows") - .from(__.V().has("name", "batch1")) - .to(__.V().has("name", "batch2")) - .property("weight", 2.3f)) - .build(); - - assertThat(batch.size()).isEqualTo(2); - assertThat(batch2.size()).isEqualTo(3); - - session().execute(batch2); - - if (isGraphBinary()) { - Map properties = - session() - .execute( - FluentGraphStatement.newInstance( - graphTraversalSource().V().has("name", "batch1").elementMap("age"))) - .one() - .asMap(); - - assertThatContainsProperties(properties, "age", 1); - - properties = - session() - .execute( - FluentGraphStatement.newInstance( - graphTraversalSource().V().has("name", "batch2").elementMap("age"))) - .one() - .asMap(); - - assertThatContainsProperties(properties, "age", 2); - - properties = - session() - .execute( - FluentGraphStatement.newInstance( - graphTraversalSource() - .V() - .has("name", "batch1") - .bothE() - .elementMap("weight", "person"))) - .one() - .asMap(); - - assertThatContainsProperties(properties, "weight", 2.3f); - assertThatContainsLabel(properties, Direction.IN, "person"); - assertThatContainsLabel(properties, Direction.OUT, "person"); - - } else { - - assertThat( - session() - .execute( - FluentGraphStatement.newInstance( - graphTraversalSource().V().has("name", "batch1"))) - .one() - .asVertex()) - .hasProperty("age", 1); - - assertThat( - session() - .execute( - FluentGraphStatement.newInstance( - graphTraversalSource().V().has("name", "batch2"))) - .one() - .asVertex()) - .hasProperty("age", 2); - - assertThat( - session() - .execute( - FluentGraphStatement.newInstance( - graphTraversalSource().V().has("name", "batch1").bothE())) - .one() - .asEdge()) - .hasProperty("weight", 2.3f) - .hasOutVLabel("person") - .hasInVLabel("person"); - } - } - - @Test - public void should_fail_if_no_bytecode_in_batch() { - BatchGraphStatement batch = - BatchGraphStatement.builder().addTraversals(ImmutableList.of()).build(); - assertThat(batch.size()).isEqualTo(0); - try { - session().execute(batch); - fail( - "Should have thrown InvalidQueryException because batch does not contain any traversals."); - } catch (InvalidQueryException e) { - assertThat(e.getMessage()) - .contains("The batch statement sent does not contain any traversal"); - } - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalITBase.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalITBase.java deleted file mode 100644 index 5bcb01bc165..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalITBase.java +++ /dev/null @@ -1,668 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import static com.datastax.dse.driver.api.core.graph.FluentGraphStatement.newInstance; -import static com.datastax.dse.driver.api.core.graph.TinkerGraphAssertions.assertThat; -import static com.datastax.dse.driver.api.core.graph.TinkerPathAssert.validatePathObjects; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.assertThatContainsLabel; -import static com.datastax.dse.driver.internal.core.graph.GraphTestUtils.assertThatContainsProperties; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.fail; - -import com.datastax.dse.driver.api.core.graph.AsyncGraphResultSet; -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.GraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphStatement; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.dse.driver.api.core.graph.SocialTraversalSource; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.Version; -import com.datastax.oss.driver.api.core.servererrors.InvalidQueryException; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.Lists; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; -import org.apache.tinkerpop.gremlin.process.traversal.Path; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; -import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; -import org.apache.tinkerpop.gremlin.structure.Direction; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Graph; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.assertj.core.api.Assertions; -import org.assertj.core.api.Assumptions; -import org.junit.Test; - -public abstract class GraphTraversalITBase { - - protected abstract CqlSession session(); - - protected abstract boolean isGraphBinary(); - - protected abstract CustomCcmRule ccmRule(); - - protected abstract GraphTraversalSource graphTraversalSource(); - - protected abstract SocialTraversalSource socialTraversalSource(); - - /** - * Ensures that a previously returned {@link Vertex}'s {@link Vertex#id()} can be used as an input - * to {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource#V(Object...)} to - * retrieve the {@link Vertex} and that the returned {@link Vertex} is the same. - * - * @test_category dse:graph - */ - @Test - public void should_use_vertex_id_as_parameter() { - GraphTraversal query = - graphTraversalSource().V().hasLabel("person").has("name", "marko"); - GraphResultSet resultSet = session().execute(newInstance(query)); - - List results = resultSet.all(); - - assertThat(results.size()).isEqualTo(1); - Vertex marko = results.get(0).asVertex(); - if (isGraphBinary()) { - Map properties = - session().execute(newInstance(query.elementMap("name"))).one().asMap(); - assertThatContainsProperties(properties, "name", "marko"); - } else { - assertThat(marko).hasProperty("name", "marko"); - } - - resultSet = session().execute(newInstance(graphTraversalSource().V(marko.id()))); - - results = resultSet.all(); - assertThat(results.size()).isEqualTo(1); - Vertex marko2 = results.get(0).asVertex(); - // Ensure that the returned vertex is the same as the first. - assertThat(marko2).isEqualTo(marko); - } - - /** - * Ensures that a previously returned {@link Edge}'s {@link Edge#id()} can be used as an input to - * {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource#E(Object...)} to - * retrieve the {@link Edge} and that the returned {@link Edge} is the same. - * - * @test_category dse:graph - */ - @Test - public void should_use_edge_id_as_parameter() { - GraphTraversal query = graphTraversalSource().E().has("weight", 0.2f); - GraphResultSet resultSet = session().execute(newInstance(query)); - - List results = resultSet.all(); - assertThat(results.size()).isEqualTo(1); - - Edge created = results.get(0).asEdge(); - if (isGraphBinary()) { - Map properties = - session() - .execute(newInstance(query.elementMap("weight", "software", "person"))) - .one() - .asMap(); - - assertThatContainsProperties(properties, "weight", 0.2f); - assertThatContainsLabel(properties, Direction.IN, "software"); - assertThatContainsLabel(properties, Direction.OUT, "person"); - } else { - assertThat(created) - .hasProperty("weight", 0.2f) - .hasInVLabel("software") - .hasOutVLabel("person"); - } - - if (isGraphBinary()) { - Map inProperties = - session() - .execute( - newInstance( - graphTraversalSource().E(created.id()).inV().elementMap("name", "lang"))) - .one() - .asMap(); - assertThatContainsProperties(inProperties, "name", "lop", "lang", "java"); - } else { - resultSet = session().execute(newInstance(graphTraversalSource().E(created.id()).inV())); - results = resultSet.all(); - assertThat(results.size()).isEqualTo(1); - Vertex lop = results.get(0).asVertex(); - - assertThat(lop).hasLabel("software").hasProperty("name", "lop").hasProperty("lang", "java"); - } - } - - /** - * A sanity check that a returned {@link Vertex}'s id is a {@link Map}. This test could break in - * the future if the format of a vertex ID changes from a Map to something else in DSE. - * - * @test_category dse:graph - */ - @Test - public void should_deserialize_vertex_id_as_map() { - GraphResultSet resultSet = - session() - .execute( - newInstance(graphTraversalSource().V().hasLabel("person").has("name", "marko"))); - - List results = resultSet.all(); - assertThat(results.size()).isEqualTo(1); - - Vertex marko = results.get(0).asVertex(); - - if (isGraphBinary()) { - assertThat(((String) marko.id())).contains("marko"); - assertThat(marko.label()).isEqualTo("person"); - } else { - assertThat(marko).hasProperty("name", "marko"); - @SuppressWarnings("unchecked") - Map id = (Map) marko.id(); - assertThat(id) - .hasSize(3) - .containsEntry("~label", "person") - .containsKey("community_id") - .containsKey("member_id"); - } - } - - /** - * Ensures that a traversal that returns a result of mixed types is interpreted as a {@link Map} - * with {@link Object} values. Also uses {@link - * org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal#by(org.apache.tinkerpop.gremlin.process.traversal.Traversal)} - * with an anonymous traversal to get inbound 'created' edges and folds them into a list. - * - *

Executes a vertex traversal that binds label 'a' and 'b' to vertex properties and label 'c' - * to vertices that have edges from that vertex. - * - * @test_category dse:graph - */ - @Test - public void should_handle_result_object_of_mixed_types() { - // find all software vertices and select name, language, and find all vertices that created such - // software. - GraphResultSet rs = - session() - .execute( - newInstance( - graphTraversalSource() - .V() - .hasLabel("software") - .as("a", "b", "c") - .select("a", "b", "c") - .by("name") - .by("lang") - .by(__.in("created").fold()))); - - List results = rs.all(); - assertThat(results.size()).isEqualTo(2); - - // Ensure that we got 'lop' and 'ripple' for property a. - assertThat(results) - .extracting(m -> m.getByKey("a").as(Object.class)) - .containsOnly("lop", "ripple"); - - for (GraphNode result : results) { - // The row should represent a map with a, b, and c keys. - assertThat(ImmutableList.copyOf(result.keys())).containsOnlyOnce("a", "b", "c"); - // 'e' should not exist, thus it should be null. - assertThat(result.getByKey("e")).isNull(); - // both software are written in java. - assertThat(result.getByKey("b").isNull()).isFalse(); - assertThat(result.getByKey("b").asString()).isEqualTo("java"); - GraphNode c = result.getByKey("c"); - assertThat(c.isList()).isTrue(); - if (result.getByKey("a").asString().equals("lop")) { - if (isGraphBinary()) { - // should contain three vertices - Assertions.assertThat(c.size()).isEqualTo(3); - } else { - // 'c' should contain marko, josh, peter. - // Ensure we have three vertices. - assertThat(c.size()).isEqualTo(3); - List vertices = - Lists.newArrayList( - c.getByIndex(0).asVertex(), - c.getByIndex(1).asVertex(), - c.getByIndex(2).asVertex()); - assertThat(vertices) - .extracting(vertex -> vertex.property("name").value()) - .containsOnly("marko", "josh", "peter"); - } - } else { - if (isGraphBinary()) { - // has only one label - Assertions.assertThat(c.size()).isEqualTo(1); - } else { - // ripple, 'c' should contain josh. - // Ensure we have 1 vertex. - assertThat(c.size()).isEqualTo(1); - Vertex vertex = c.getByIndex(0).asVertex(); - assertThat(vertex).hasProperty("name", "josh"); - } - } - } - } - - /** - * Ensures a traversal that yields no results is properly retrieved and is empty. - * - * @test_category dse:graph - */ - @Test - public void should_return_zero_results() { - if (isGraphBinary()) { - assertThatThrownBy( - () -> - session().execute(newInstance(graphTraversalSource().V().hasLabel("notALabel")))) - .isInstanceOf(InvalidQueryException.class) - .hasMessageContaining("Unknown vertex label 'notALabel'"); - } else { - GraphResultSet rs = - session().execute(newInstance(graphTraversalSource().V().hasLabel("notALabel"))); - assertThat(rs.all().size()).isZero(); - } - } - - /** - * Ensures a traversal that yields no results is properly retrieved and is empty, using GraphSON2 - * and the TinkerPop transform results function. - * - * @test_category dse:graph - */ - @Test - public void should_return_zero_results_graphson_2() { - Assumptions.assumeThat(isGraphBinary()).isFalse(); - - GraphStatement simpleGraphStatement = - ScriptGraphStatement.newInstance("g.V().hasLabel('notALabel')"); - - GraphResultSet rs = session().execute(simpleGraphStatement); - assertThat(rs.one()).isNull(); - } - - /** - * Validates that a traversal using lambda operations with anonymous traversals are applied - * appropriately and return the expected results. - * - *

Traversal that filters 'person'-labeled vertices by name 'marko' and flatMaps outgoing - * vertices on the 'knows' relationship by their outgoing 'created' vertices and then maps by - * their 'name' property and folds them into one list. - * - *

Note: This does not validate lambdas with functions as those can't be interpreted and - * sent remotely. - * - * @test_category dse:graph - */ - @Test - public void should_handle_lambdas() { - // Find all people marko knows and the software they created. - GraphResultSet result = - session() - .execute( - newInstance( - graphTraversalSource() - .V() - .hasLabel("person") - .filter(__.has("name", "marko")) - .out("knows") - .flatMap(__.out("created")) - .map(__.values("name")) - .fold())); - - // Marko only knows josh and vadas, of which josh created lop and ripple. - List software = result.one().as(GenericType.listOf(String.class)); - assertThat(software).containsOnly("lop", "ripple"); - } - - /** - * Validates that when traversing a path and labeling some of the elements during the traversal - * that the output elements are properly labeled. - * - * @test_category dse:graph - */ - @Test - public void should_resolve_path_with_some_labels() { - GraphResultSet rs = - session() - .execute( - newInstance( - graphTraversalSource() - .V() - .hasLabel("person") - .has("name", "marko") - .as("a") - .outE("knows") - .inV() - .as("c", "d") - .outE("created") - .as("e", "f", "g") - .inV() - .path())); - - List results = rs.all(); - assertThat(results.size()).isEqualTo(2); - for (GraphNode result : results) { - Path path = result.asPath(); - validatePathObjects(path); - assertThat(path.labels()).hasSize(5); - assertThat(path) - .hasLabel(0, "a") - .hasNoLabel(1) - .hasLabel(2, "c", "d") - .hasLabel(3, "e", "f", "g") - .hasNoLabel(4); - } - } - - /** - * Validates that when traversing a path and labeling all of the elements during the traversal - * that the output elements are properly labeled. - * - * @test_category dse:graph - */ - @Test - public void should_resolve_path_with_labels() { - GraphResultSet rs = - session() - .execute( - newInstance( - graphTraversalSource() - .V() - .hasLabel("person") - .has("name", "marko") - .as("a") - .outE("knows") - .as("b") - .inV() - .as("c", "d") - .outE("created") - .as("e", "f", "g") - .inV() - .as("h") - .path())); - List results = rs.all(); - assertThat(results.size()).isEqualTo(2); - for (GraphNode result : results) { - Path path = result.asPath(); - validatePathObjects(path); - assertThat(path.labels()).hasSize(5); - assertThat(path) - .hasLabel(0, "a") - .hasLabel(1, "b") - .hasLabel(2, "c", "d") - .hasLabel(3, "e", "f", "g") - .hasLabel(4, "h"); - } - } - - /** - * Validates that when traversing a path and labeling none of the elements during the traversal - * that all the labels are empty in the result. - * - * @test_category dse:graph - */ - @Test - public void should_resolve_path_without_labels() { - GraphResultSet rs = - session() - .execute( - newInstance( - graphTraversalSource() - .V() - .hasLabel("person") - .has("name", "marko") - .outE("knows") - .inV() - .outE("created") - .inV() - .path())); - List results = rs.all(); - assertThat(results.size()).isEqualTo(2); - for (GraphNode result : results) { - Path path = result.asPath(); - validatePathObjects(path); - assertThat(path.labels()).hasSize(5); - for (int i = 0; i < 5; i++) assertThat(path).hasNoLabel(i); - } - } - - /** - * Validates that a traversal returning a Tree structure is returned appropriately with the - * expected contents. - * - *

Retrieves trees of people marko knows and the software they created. - * - * @test_category dse:graph - */ - @Test - public void should_parse_tree() { - // Get a tree structure showing the paths from mark to people he knows to software they've - // created. - GraphResultSet rs = - session() - .execute( - newInstance( - graphTraversalSource() - .V() - .hasLabel("person") - .out("knows") - .out("created") - .tree() - .by("name"))); - - List results = rs.all(); - assertThat(results.size()).isEqualTo(1); - - // [{key=marko, value=[{key=josh, value=[{key=ripple, value=[]}, {key=lop, value=[]}]}]}] - GraphNode result = results.get(0); - - @SuppressWarnings("unchecked") - Tree tree = result.as(Tree.class); - - assertThat(tree).tree("marko").tree("josh").tree("lop").isLeaf(); - - assertThat(tree).tree("marko").tree("josh").tree("ripple").isLeaf(); - } - - /** - * Ensures that a traversal that returns a sub graph can be retrieved. - * - *

The subgraph is all members in a knows relationship, thus is all people who marko knows and - * the edges that connect them. - */ - @Test - public void should_handle_subgraph_graphson() { - Assumptions.assumeThat(isGraphBinary()).isFalse(); - GraphResultSet rs = - session() - .execute( - newInstance( - graphTraversalSource() - .E() - .hasLabel("knows") - .subgraph("subGraph") - .cap("subGraph"))); - - List results = rs.all(); - assertThat(results.size()).isEqualTo(1); - - Graph graph = results.get(0).as(Graph.class); - - assertThat(graph.edges()).toIterable().hasSize(2); - assertThat(graph.vertices()).toIterable().hasSize(3); - } - - /** - * Ensures that a traversal that returns a sub graph can be retrieved. - * - *

The subgraph is all members in a knows relationship, thus is all people who marko knows and - * the edges that connect them. - */ - @Test - public void should_handle_subgraph_grap_binary() { - Assumptions.assumeThat(isGraphBinary()).isTrue(); - GraphResultSet rs = - session() - .execute( - newInstance( - graphTraversalSource() - .E() - .hasLabel("knows") - .subgraph("subGraph") - .cap("subGraph"))); - - List results = rs.all(); - assertThat(results.size()).isEqualTo(1); - - String graph = results.get(0).as(String.class); - - assertThat(graph).contains("vertices:3").contains("edges:2"); - } - - /** - * A simple smoke test to ensure that a user can supply a custom {@link GraphTraversalSource} for - * use with DSLs. - * - * @test_category dse:graph - */ - @Test - public void should_allow_use_of_dsl_graphson() throws Exception { - Assumptions.assumeThat(isGraphBinary()).isFalse(); - SocialTraversalSource gSocial = socialTraversalSource(); - - GraphStatement gs = newInstance(gSocial.persons("marko").knows("vadas")); - - GraphResultSet rs = session().execute(gs); - List results = rs.all(); - - assertThat(results.size()).isEqualTo(1); - assertThat(results.get(0).asVertex()) - .hasProperty("name", "marko") - .hasProperty("age", 29) - .hasLabel("person"); - } - - /** - * A simple smoke test to ensure that a user can supply a custom {@link GraphTraversalSource} for - * use with DSLs. - * - * @test_category dse:graph - */ - @Test - public void should_allow_use_of_dsl_graph_binary() throws Exception { - Assumptions.assumeThat(isGraphBinary()).isTrue(); - SocialTraversalSource gSocial = socialTraversalSource(); - - GraphStatement gs = - newInstance(gSocial.persons("marko").knows("vadas").elementMap("name", "age")); - - GraphResultSet rs = session().execute(gs); - List results = rs.all(); - - assertThat(results.size()).isEqualTo(1); - assertThatContainsProperties(results.get(0).asMap(), "name", "marko", "age", 29); - Assertions.assertThat(results.get(0).asMap().values()).contains("person"); - } - - /** - * Ensures that traversals with barriers (which return results bulked) contain the correct amount - * of end results. - * - *

This will fail if ran against DSE < 5.0.9 or DSE < 5.1.2. - */ - @Test - public void should_return_correct_results_when_bulked() { - Assumptions.assumeThat( - CcmBridge.isDistributionOf( - BackendType.DSE, (dist, cass) -> dist.compareTo(Version.parse("5.1.2")) > 0)) - .isTrue(); - - GraphResultSet rs = - session().execute(newInstance(graphTraversalSource().E().label().barrier())); - - List results = - rs.all().stream().map(GraphNode::asString).sorted().collect(Collectors.toList()); - - assertThat(results) - .hasSize(6) - .containsSequence("created", "created", "created", "created") - .containsSequence("knows", "knows"); - } - - @Test - public void should_handle_asynchronous_execution_graphson() { - Assumptions.assumeThat(isGraphBinary()).isFalse(); - StringBuilder names = new StringBuilder(); - - CompletionStage future = - session() - .executeAsync( - FluentGraphStatement.newInstance(graphTraversalSource().V().hasLabel("person"))); - - try { - // dumb processing to make sure the completable future works correctly and correct results are - // returned - Iterable results = - future.thenApply(AsyncGraphResultSet::currentPage).toCompletableFuture().get(); - for (GraphNode gn : results) { - names.append(gn.asVertex().property("name").value()); - } - } catch (InterruptedException | ExecutionException e) { - fail("Shouldn't have thrown an exception waiting for the result to complete"); - } - - assertThat(names.toString()).contains("peter", "marko", "vadas", "josh"); - } - - @Test - public void should_handle_asynchronous_execution_graph_binary() { - Assumptions.assumeThat(isGraphBinary()).isTrue(); - StringBuilder names = new StringBuilder(); - - CompletionStage future = - session() - .executeAsync( - FluentGraphStatement.newInstance(graphTraversalSource().V().hasLabel("person"))); - - try { - // dumb processing to make sure the completable future works correctly and correct results are - // returned - Iterable results = - future.thenApply(AsyncGraphResultSet::currentPage).toCompletableFuture().get(); - for (GraphNode gn : results) { - names.append(gn.asVertex().id()); - } - } catch (InterruptedException | ExecutionException e) { - fail("Shouldn't have thrown an exception waiting for the result to complete"); - } - - assertThat(names.toString()).contains("peter", "marko", "vadas", "josh"); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalMetaPropertiesIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalMetaPropertiesIT.java deleted file mode 100644 index d8058cbf59e..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalMetaPropertiesIT.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -// INFO: meta props are going away in NGDG - -import static com.datastax.dse.driver.api.core.graph.DseGraph.g; -import static com.datastax.dse.driver.api.core.graph.FluentGraphStatement.newInstance; -import static com.datastax.dse.driver.api.core.graph.SampleGraphScripts.ALLOW_SCANS; -import static com.datastax.dse.driver.api.core.graph.SampleGraphScripts.MAKE_STRICT; -import static com.datastax.dse.driver.api.core.graph.TinkerGraphAssertions.assertThat; - -import com.datastax.dse.driver.api.core.graph.GraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -// INFO: meta props are going away in NGDG - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.3", - description = "DSE 5.0.3 required for remote TinkerPop support") -public class GraphTraversalMetaPropertiesIT { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - /** Builds a simple schema that provides for a vertex with a property with sub properties. */ - private static final String META_PROPS = - MAKE_STRICT - + ALLOW_SCANS - + "schema.propertyKey('sub_prop').Text().create()\n" - + "schema.propertyKey('sub_prop2').Text().create()\n" - + "schema.propertyKey('meta_prop').Text().properties('sub_prop', 'sub_prop2').create()\n" - + "schema.vertexLabel('meta_v').properties('meta_prop').create()"; - - /** - * Ensures that a traversal that yields a vertex with a property that has its own properties that - * is appropriately parsed and made accessible via {@link VertexProperty#property(String)}. - * - * @test_category dse:graph - */ - @Test - public void should_parse_meta_properties() { - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(META_PROPS)); - - GraphResultSet result = - SESSION_RULE - .session() - .execute( - newInstance( - g.addV("meta_v") - .property("meta_prop", "hello", "sub_prop", "hi", "sub_prop2", "hi2"))); - - Vertex v = result.one().asVertex(); - assertThat(v).hasProperty("meta_prop"); - - VertexProperty metaProp = v.property("meta_prop"); - assertThat(metaProp) - .hasValue("hello") - .hasProperty("sub_prop", "hi") - .hasProperty("sub_prop2", "hi2"); - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalMultiPropertiesIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalMultiPropertiesIT.java deleted file mode 100644 index c30e770f40e..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalMultiPropertiesIT.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.graph.statement; - -import static com.datastax.dse.driver.api.core.graph.DseGraph.g; -import static com.datastax.dse.driver.api.core.graph.FluentGraphStatement.newInstance; -import static com.datastax.dse.driver.api.core.graph.SampleGraphScripts.ALLOW_SCANS; -import static com.datastax.dse.driver.api.core.graph.SampleGraphScripts.MAKE_STRICT; -import static com.datastax.dse.driver.api.core.graph.TinkerGraphAssertions.assertThat; - -import com.datastax.dse.driver.api.core.graph.GraphResultSet; -import com.datastax.dse.driver.api.core.graph.GraphTestSupport; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import java.util.Iterator; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; - -// INFO: multi props are not supported in Core -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0.3", - description = "DSE 5.0.3 required for remote TinkerPop support") -public class GraphTraversalMultiPropertiesIT { - - private static final CustomCcmRule CCM_RULE = GraphTestSupport.GRAPH_CCM_RULE_BUILDER.build(); - - private static final SessionRule SESSION_RULE = - GraphTestSupport.getClassicGraphSessionBuilder(CCM_RULE).build(); - - @ClassRule - public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - /** Builds a simple schema that provides for a vertex with a multi-cardinality property. */ - private static final String MULTI_PROPS = - MAKE_STRICT - + ALLOW_SCANS - + "schema.propertyKey('multi_prop').Text().multiple().create()\n" - + "schema.vertexLabel('multi_v').properties('multi_prop').create()\n"; - - /** - * Ensures that a traversal that yields a vertex with a property name that is present multiple - * times that the properties are parsed and made accessible via {@link - * Vertex#properties(String...)}. - * - * @test_category dse:graph - */ - @Test - public void should_parse_multiple_cardinality_properties() { - // given a schema that defines multiple cardinality properties. - SESSION_RULE.session().execute(ScriptGraphStatement.newInstance(MULTI_PROPS)); - - // when adding a vertex with a multiple cardinality property - GraphResultSet result = - SESSION_RULE - .session() - .execute( - newInstance( - g.addV("multi_v") - .property("multi_prop", "Hello") - .property("multi_prop", "Sweet") - .property("multi_prop", "World"))); - - Vertex v = result.one().asVertex(); - assertThat(v).hasProperty("multi_prop"); - - Iterator> multiProp = v.properties("multi_prop"); - assertThat(multiProp) - .toIterable() - .extractingResultOf("value") - .containsExactly("Hello", "Sweet", "World"); - } -} diff --git a/integration-tests/src/test/resources/application.conf b/integration-tests/src/test/resources/application.conf index f3ab31bcb76..61d06ec8456 100644 --- a/integration-tests/src/test/resources/application.conf +++ b/integration-tests/src/test/resources/application.conf @@ -27,7 +27,6 @@ datastax-java-driver { } config-reload-interval = 0 request.timeout = 10 seconds - graph.timeout = 10 seconds } advanced { connection { @@ -40,9 +39,6 @@ datastax-java-driver { trace.interval = 1 second warn-if-set-keyspace = false } - graph { - name = "demo" - } continuous-paging.timeout { first-page = 10 seconds other-pages = 10 seconds diff --git a/manual/core/graalvm/README.md b/manual/core/graalvm/README.md index a2fc20b0662..5a65b3e5813 100644 --- a/manual/core/graalvm/README.md +++ b/manual/core/graalvm/README.md @@ -28,9 +28,7 @@ under the License. * When using [Jackson](../integration#Jackson); * When using LZ4 [compression](../compression/); * Depending on the [logging backend](../logging) in use. -* DSE-specific features: - * Geospatial types are supported. - * DSE Graph is not officially supported, although it may work. +* DSE geospatial types require additional configuration. * The [shaded jar](../shaded_jar) is not officially supported, although it may work. ----- @@ -278,56 +276,6 @@ images, as stated above – replace the above entry with the below one: 2. When invoking the native image builder, add a `-H:ReflectionConfigurationFiles=reflection.json` flag and point it to the file created above. -#### DSE Graph - -**[DSE Graph](../dse/graph) is not officially supported on GraalVM native images.** - -The following configuration can be used as a starting point for users wishing to build a native -image for a DSE Graph application. DataStax does not guarantee however that the below configuration -will work in all cases. If the native image build fails, a good option is to use GraalVM's -[Tracing Agent](https://www.graalvm.org/reference-manual/native-image/Agent/) to understand why. - -1. Create the following reflection.json file, or add these entries to an existing file: - -```json -[ - { "name": "org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0" }, - { "name": "org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal" }, - { "name": "org.apache.tinkerpop.gremlin.structure.Graph", - "allDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredMethods": true, - "allPublicMethods": true - }, - { "name": "org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph", - "allDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredMethods": true, - "allPublicMethods": true - }, - { "name": " org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph", - "allDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredMethods": true, - "allPublicMethods": true - }, - { "name": "org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource", - "allDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredMethods": true, - "allPublicMethods": true - } -] -``` - -2. When invoking the native image builder, add the following flags: - -``` --H:ReflectionConfigurationFiles=reflection.json ---initialize-at-build-time=org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0 ---initialize-at-build-time=org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer -``` - ### Using the shaded jar **The [shaded jar](../shaded_jar) is not officially supported in a GraalVM native image.** diff --git a/manual/core/integration/README.md b/manual/core/integration/README.md index 964e8388347..b735946713a 100644 --- a/manual/core/integration/README.md +++ b/manual/core/integration/README.md @@ -538,45 +538,6 @@ In the dependency specification above you should use any 1.2.x version of Esri ( 1.2.1). These versions are older than the current 2.x versions of the library but they are guaranteed to be fully compatible with DSE. -#### TinkerPop - -[Apache TinkerPop™](http://tinkerpop.apache.org/) is used in the graph API. - -For driver versions ranging from 4.4.0 to 4.9.0 inclusive, TinkerPop is declared as a required -dependency, but the driver can operate normally without it. If you don't use the graph API at all, -you can exclude the TinkerPop dependencies: - -```xml - - com.scylladb - java-driver-core - ${driver.version} - - - org.apache.tinkerpop - * - - - -``` - -Starting with driver 4.10 however, TinkerPop switched to an optional dependency. Excluding TinkerPop -explicitly is not required anymore if you don't use it. _If you do use the graph API though, you now -need to explicitly include the dependencies below in your application_: - -```xml - - org.apache.tinkerpop - gremlin-core - ${tinkerpop.version} - - - org.apache.tinkerpop - tinkergraph-gremlin - ${tinkerpop.version} - -``` - #### Reactive Streams [Reactive Streams](https://www.reactive-streams.org/) types are referenced in our [reactive diff --git a/manual/developer/request_execution/README.md b/manual/developer/request_execution/README.md index 38a0a55fbd7..4b206af1558 100644 --- a/manual/developer/request_execution/README.md +++ b/manual/developer/request_execution/README.md @@ -178,8 +178,6 @@ ResultT)` combination defines an execution model, for example: | `Statement` | `ResultSet` | CQL, synchronous | | `Statement` | `CompletionStage` | CQL, asynchronous | | `Statement` | `ReactiveResultSet` | CQL, reactive | -| `GraphStatement` | `GraphResultSet` | DSE Graph, synchronous | -| `GraphStatement` | `CompletionStage` | DSE Graph, asynchronous | In general, regular client code doesn't use `Session.execute` directly. Instead, child interfaces expose more user-friendly shortcuts for a given result type: diff --git a/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerNodeMetricUpdater.java b/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerNodeMetricUpdater.java index cb8303de965..010ead90d75 100644 --- a/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerNodeMetricUpdater.java +++ b/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerNodeMetricUpdater.java @@ -17,8 +17,6 @@ */ package com.datastax.oss.driver.internal.metrics.micrometer; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; import com.datastax.oss.driver.api.core.metadata.Node; @@ -77,7 +75,6 @@ public MicrometerNodeMetricUpdater( initializeCounter(DefaultNodeMetric.AUTHENTICATION_ERRORS, profile); initializeTimer(DefaultNodeMetric.CQL_MESSAGES, profile); - initializeTimer(DseNodeMetric.GRAPH_MESSAGES, profile); } @Override @@ -116,22 +113,6 @@ protected Timer.Builder configureTimer(Timer.Builder builder, NodeMetric metric, configurePercentilesPublishIfDefined( builder, profile, DefaultDriverOption.METRICS_NODE_CQL_MESSAGES_PUBLISH_PERCENTILES); - } else if (metric == DseNodeMetric.GRAPH_MESSAGES) { - builder - .minimumExpectedValue( - profile.getDuration(DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_LOWEST)) - .maximumExpectedValue( - profile.getDuration(DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_HIGHEST)) - .serviceLevelObjectives( - profile.isDefined(DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_SLO) - ? profile - .getDurationList(DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_SLO) - .toArray(new Duration[0]) - : null) - .percentilePrecision(profile.getInt(DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_DIGITS)); - - configurePercentilesPublishIfDefined( - builder, profile, DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_PUBLISH_PERCENTILES); } return builder; } diff --git a/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java b/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java index 559054ab510..9e898d2ef3c 100644 --- a/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java +++ b/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java @@ -49,12 +49,10 @@ public MicrometerSessionMetricUpdater( initializeCounter(DefaultSessionMetric.CQL_CLIENT_TIMEOUTS, profile); initializeCounter(DefaultSessionMetric.THROTTLING_ERRORS, profile); - initializeCounter(DseSessionMetric.GRAPH_CLIENT_TIMEOUTS, profile); initializeTimer(DefaultSessionMetric.CQL_REQUESTS, profile); initializeTimer(DefaultSessionMetric.THROTTLING_DELAY, profile); initializeTimer(DseSessionMetric.CONTINUOUS_CQL_REQUESTS, profile); - initializeTimer(DseSessionMetric.GRAPH_REQUESTS, profile); } @Override @@ -130,25 +128,6 @@ protected Timer.Builder configureTimer(Timer.Builder builder, SessionMetric metr builder, profile, DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_PUBLISH_PERCENTILES); - } else if (metric == DseSessionMetric.GRAPH_REQUESTS) { - builder - .minimumExpectedValue( - profile.getDuration(DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_LOWEST)) - .maximumExpectedValue( - profile.getDuration(DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_HIGHEST)) - .serviceLevelObjectives( - profile.isDefined(DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_SLO) - ? profile - .getDurationList(DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_SLO) - .toArray(new Duration[0]) - : null) - .percentilePrecision( - profile.isDefined(DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_DIGITS) - ? profile.getInt(DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_DIGITS) - : null); - - configurePercentilesPublishIfDefined( - builder, profile, DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_PUBLISH_PERCENTILES); } return builder; } diff --git a/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerNodeMetricUpdaterTest.java b/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerNodeMetricUpdaterTest.java index 594c4166e98..de5d01a954e 100644 --- a/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerNodeMetricUpdaterTest.java +++ b/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerNodeMetricUpdaterTest.java @@ -25,8 +25,6 @@ import static org.mockito.Mockito.when; import ch.qos.logback.classic.Level; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.api.core.config.DriverConfig; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; @@ -265,14 +263,6 @@ public static Object[][] timerMetrics() { DefaultDriverOption.METRICS_NODE_CQL_MESSAGES_SLO, DefaultDriverOption.METRICS_NODE_CQL_MESSAGES_PUBLISH_PERCENTILES, }, - { - DseNodeMetric.GRAPH_MESSAGES, - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_LOWEST, - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_HIGHEST, - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_DIGITS, - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_SLO, - DseDriverOption.METRICS_NODE_GRAPH_MESSAGES_PUBLISH_PERCENTILES, - }, }; } } diff --git a/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java b/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java index 79f7c3a8ff7..6c77c7f5467 100644 --- a/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java +++ b/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java @@ -172,14 +172,6 @@ public static Object[][] timerMetrics() { DefaultDriverOption.METRICS_SESSION_CQL_REQUESTS_SLO, DefaultDriverOption.METRICS_SESSION_CQL_REQUESTS_PUBLISH_PERCENTILES, }, - { - DseSessionMetric.GRAPH_REQUESTS, - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_LOWEST, - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_HIGHEST, - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_DIGITS, - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_SLO, - DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_PUBLISH_PERCENTILES, - }, { DseSessionMetric.CONTINUOUS_CQL_REQUESTS, DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_LOWEST, diff --git a/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileNodeMetricUpdater.java b/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileNodeMetricUpdater.java index 8a2d235b59e..9aa055c2e75 100644 --- a/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileNodeMetricUpdater.java +++ b/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileNodeMetricUpdater.java @@ -17,7 +17,6 @@ */ package com.datastax.oss.driver.internal.metrics.microprofile; -import com.datastax.dse.driver.api.core.metrics.DseNodeMetric; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; import com.datastax.oss.driver.api.core.metadata.Node; import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; @@ -73,7 +72,6 @@ public MicroProfileNodeMetricUpdater( initializeCounter(DefaultNodeMetric.AUTHENTICATION_ERRORS, profile); initializeTimer(DefaultNodeMetric.CQL_MESSAGES, profile); - initializeTimer(DseNodeMetric.GRAPH_MESSAGES, profile); } @Override diff --git a/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java b/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java index f3c906e4422..9fef1240a1f 100644 --- a/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java +++ b/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java @@ -45,12 +45,10 @@ public MicroProfileSessionMetricUpdater( initializeCounter(DefaultSessionMetric.CQL_CLIENT_TIMEOUTS, profile); initializeCounter(DefaultSessionMetric.THROTTLING_ERRORS, profile); - initializeCounter(DseSessionMetric.GRAPH_CLIENT_TIMEOUTS, profile); initializeTimer(DefaultSessionMetric.CQL_REQUESTS, profile); initializeTimer(DefaultSessionMetric.THROTTLING_DELAY, profile); initializeTimer(DseSessionMetric.CONTINUOUS_CQL_REQUESTS, profile); - initializeTimer(DseSessionMetric.GRAPH_REQUESTS, profile); } @Override diff --git a/osgi-tests/pom.xml b/osgi-tests/pom.xml index 3b5c1f4dc81..87c401809e8 100644 --- a/osgi-tests/pom.xml +++ b/osgi-tests/pom.xml @@ -89,14 +89,6 @@ com.esri.geometry esri-geometry-api - - org.apache.tinkerpop - gremlin-core - - - org.apache.tinkerpop - tinkergraph-gremlin - org.osgi org.osgi.core @@ -227,7 +219,7 @@ com.datastax.oss.driver.internal.osgi.MailboxActivator com.datastax.oss.driver.api.osgi.* com.datastax.oss.driver.internal.osgi.* - !net.jcip.annotations.*,!edu.umd.cs.findbugs.annotations.*,org.apache.tinkerpop.*;resolution:=optional,* + !net.jcip.annotations.*,!edu.umd.cs.findbugs.annotations.*,* <_include>-osgi.bnd diff --git a/osgi-tests/src/main/java/com/datastax/oss/driver/api/osgi/service/graph/GraphMailboxService.java b/osgi-tests/src/main/java/com/datastax/oss/driver/api/osgi/service/graph/GraphMailboxService.java deleted file mode 100644 index 65999957066..00000000000 --- a/osgi-tests/src/main/java/com/datastax/oss/driver/api/osgi/service/graph/GraphMailboxService.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.oss.driver.api.osgi.service.graph; - -import com.datastax.oss.driver.api.osgi.service.MailboxException; -import com.datastax.oss.driver.api.osgi.service.MailboxMessage; -import com.datastax.oss.driver.api.osgi.service.MailboxService; - -public interface GraphMailboxService extends MailboxService { - - void sendGraphMessage(MailboxMessage message) throws MailboxException; - - Iterable getGraphMessages(String recipient) throws MailboxException; -} diff --git a/osgi-tests/src/main/java/com/datastax/oss/driver/internal/osgi/MailboxActivator.java b/osgi-tests/src/main/java/com/datastax/oss/driver/internal/osgi/MailboxActivator.java index 8dff11520af..8272db46eb3 100644 --- a/osgi-tests/src/main/java/com/datastax/oss/driver/internal/osgi/MailboxActivator.java +++ b/osgi-tests/src/main/java/com/datastax/oss/driver/internal/osgi/MailboxActivator.java @@ -17,8 +17,6 @@ */ package com.datastax.oss.driver.internal.osgi; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.internal.core.graph.GraphProtocol; import com.datastax.oss.driver.api.core.CqlIdentifier; import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.CqlSessionBuilder; @@ -28,7 +26,6 @@ import com.datastax.oss.driver.api.osgi.service.MailboxService; import com.datastax.oss.driver.internal.osgi.service.MailboxServiceImpl; import com.datastax.oss.driver.internal.osgi.service.geo.GeoMailboxServiceImpl; -import com.datastax.oss.driver.internal.osgi.service.graph.GraphMailboxServiceImpl; import com.datastax.oss.driver.internal.osgi.service.reactive.ReactiveMailboxServiceImpl; import java.net.InetSocketAddress; import java.util.Dictionary; @@ -49,7 +46,6 @@ public class MailboxActivator implements BundleActivator { private CqlSession session; private CqlIdentifier keyspace; - private String graphName; @Override public void start(BundleContext context) { @@ -128,16 +124,6 @@ private void buildSession(BundleContext context) { LOGGER.info("Compression: NONE"); } - graphName = context.getProperty("cassandra.graph.name"); - if (graphName != null) { - LOGGER.info("Graph name: {}", graphName); - configLoaderBuilder.withString(DseDriverOption.GRAPH_NAME, graphName); - configLoaderBuilder.withString( - DseDriverOption.GRAPH_SUB_PROTOCOL, GraphProtocol.GRAPH_BINARY_1_0.toInternalCode()); - } else { - LOGGER.info("Graph: NONE"); - } - builder.withConfigLoader(configLoaderBuilder.build()); LOGGER.info("Initializing session"); @@ -151,8 +137,6 @@ private void registerService(BundleContext context) { mailbox = new ReactiveMailboxServiceImpl(session, keyspace); } else if ("true".equalsIgnoreCase(context.getProperty("cassandra.geo"))) { mailbox = new GeoMailboxServiceImpl(session, keyspace); - } else if ("true".equalsIgnoreCase(context.getProperty("cassandra.graph"))) { - mailbox = new GraphMailboxServiceImpl(session, keyspace, graphName); } else { mailbox = new MailboxServiceImpl(session, keyspace); } diff --git a/osgi-tests/src/main/java/com/datastax/oss/driver/internal/osgi/service/graph/GraphMailboxServiceImpl.java b/osgi-tests/src/main/java/com/datastax/oss/driver/internal/osgi/service/graph/GraphMailboxServiceImpl.java deleted file mode 100644 index b4637a27258..00000000000 --- a/osgi-tests/src/main/java/com/datastax/oss/driver/internal/osgi/service/graph/GraphMailboxServiceImpl.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.oss.driver.internal.osgi.service.graph; - -import static com.datastax.dse.driver.api.core.graph.DseGraph.g; -import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.unfold; - -import com.datastax.dse.driver.api.core.graph.FluentGraphStatement; -import com.datastax.dse.driver.api.core.graph.GraphNode; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; -import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.osgi.service.MailboxException; -import com.datastax.oss.driver.api.osgi.service.MailboxMessage; -import com.datastax.oss.driver.api.osgi.service.graph.GraphMailboxService; -import com.datastax.oss.driver.internal.osgi.service.MailboxServiceImpl; -import java.time.Instant; -import java.util.stream.Collectors; - -public class GraphMailboxServiceImpl extends MailboxServiceImpl implements GraphMailboxService { - - private final String graphName; - - public GraphMailboxServiceImpl(CqlSession session, CqlIdentifier keyspace, String graphName) { - super(session, keyspace); - this.graphName = graphName; - } - - @Override - protected void createSchema() { - super.createSchema(); - session.execute( - ScriptGraphStatement.newInstance( - String.format("system.graph('%s').ifExists().drop()", graphName)) - .setSystemQuery(true), - ScriptGraphStatement.SYNC); - session.execute( - ScriptGraphStatement.newInstance( - String.format("system.graph('%s').ifNotExists().coreEngine().create()", graphName)) - .setSystemQuery(true), - ScriptGraphStatement.SYNC); - session.execute( - ScriptGraphStatement.newInstance( - "schema.vertexLabel('message')" - + ".partitionBy('recipient', Text)" - + ".clusterBy('timestamp', Timestamp)" - + ".property('sender', Text)" - + ".property('body', Text)" - + ".create();")); - } - - @Override - public Iterable getGraphMessages(String recipient) throws MailboxException { - FluentGraphStatement statement = - FluentGraphStatement.newInstance( - g.V().hasLabel("message").has("recipient", recipient).valueMap().by(unfold())); - try { - return session.execute(statement).all().stream() - .map(GraphNode::asMap) - .map( - vertex -> { - Instant timestamp = (Instant) vertex.get("timestamp"); - String sender = (String) vertex.get("sender"); - String body = (String) vertex.get("body"); - return new MailboxMessage(recipient, timestamp, sender, body); - }) - .collect(Collectors.toList()); - } catch (Exception e) { - throw new MailboxException(e); - } - } - - @Override - public void sendGraphMessage(MailboxMessage message) throws MailboxException { - FluentGraphStatement insertVertex = - FluentGraphStatement.newInstance( - g.addV("message") - .property("recipient", message.getRecipient()) - .property("timestamp", message.getTimestamp()) - .property("sender", message.getSender()) - .property("body", message.getBody())); - try { - session.execute(insertVertex); - } catch (Exception e) { - throw new MailboxException(e); - } - } -} diff --git a/osgi-tests/src/main/resources/application.conf b/osgi-tests/src/main/resources/application.conf index 0c3e8e76c98..414121fe4db 100644 --- a/osgi-tests/src/main/resources/application.conf +++ b/osgi-tests/src/main/resources/application.conf @@ -20,7 +20,6 @@ datastax-java-driver { basic { load-balancing-policy.class = DcInferringLoadBalancingPolicy request.timeout = 10 seconds - graph.timeout = 10 seconds } advanced { retry-policy.class = com.datastax.oss.driver.api.osgi.CustomRetryPolicy @@ -34,9 +33,6 @@ datastax-java-driver { trace.interval = 1 second warn-if-set-keyspace = false } - graph { - name = "demo" - } continuous-paging.timeout { first-page = 10 seconds other-pages = 10 seconds diff --git a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/OsgiDefaultIT.java b/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/OsgiDefaultIT.java index 1f98956e680..6523c8cb527 100644 --- a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/OsgiDefaultIT.java +++ b/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/OsgiDefaultIT.java @@ -47,7 +47,7 @@ public class OsgiDefaultIT { @Configuration public Option[] config() { // this configuration purposely excludes bundles whose resolution should be optional: - // ESRI, Reactive Streams and Tinkerpop. This allows to validate that the driver can still + // ESRI and Reactive Streams. This allows to validate that the driver can still // work properly in an OSGi container as long as the missing packages are not accessed. return CoreOptions.options( BundleOptions.applicationBundle(), diff --git a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/OsgiGraphIT.java b/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/OsgiGraphIT.java deleted file mode 100644 index be6997b9d02..00000000000 --- a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/OsgiGraphIT.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.oss.driver.internal.osgi; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.oss.driver.api.osgi.service.MailboxService; -import com.datastax.oss.driver.api.osgi.service.graph.GraphMailboxService; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.internal.osgi.checks.DefaultServiceChecks; -import com.datastax.oss.driver.internal.osgi.checks.GraphServiceChecks; -import com.datastax.oss.driver.internal.osgi.support.BundleOptions; -import com.datastax.oss.driver.internal.osgi.support.CcmExamReactorFactory; -import com.datastax.oss.driver.internal.osgi.support.CcmPaxExam; -import javax.inject.Inject; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.ops4j.pax.exam.Configuration; -import org.ops4j.pax.exam.CoreOptions; -import org.ops4j.pax.exam.Option; -import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; - -@RunWith(CcmPaxExam.class) -@ExamReactorStrategy(CcmExamReactorFactory.class) -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.8", - description = "Requires Core Graph") -public class OsgiGraphIT { - - @Inject MailboxService service; - - @Configuration - public Option[] config() { - return CoreOptions.options( - BundleOptions.applicationBundle(), - BundleOptions.driverCoreBundle(), - BundleOptions.driverQueryBuilderBundle(), - BundleOptions.driverMapperRuntimeBundle(), - BundleOptions.commonBundles(), - BundleOptions.nettyBundles(), - BundleOptions.jacksonBundles(), - BundleOptions.tinkerpopBundles(), - BundleOptions.testBundles()); - } - - @Test - public void test_graph() throws Exception { - DefaultServiceChecks.checkService(service); - assertThat(service).isInstanceOf(GraphMailboxService.class); - GraphServiceChecks.checkGraphService((GraphMailboxService) service); - } -} diff --git a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/checks/GraphServiceChecks.java b/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/checks/GraphServiceChecks.java deleted file mode 100644 index 40bda10900b..00000000000 --- a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/checks/GraphServiceChecks.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.oss.driver.internal.osgi.checks; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.oss.driver.api.osgi.service.MailboxException; -import com.datastax.oss.driver.api.osgi.service.MailboxMessage; -import com.datastax.oss.driver.api.osgi.service.graph.GraphMailboxService; -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; - -public class GraphServiceChecks { - - public static void checkGraphService(GraphMailboxService service) throws MailboxException { - // Insert some data into mailbox for a particular user. - String recipient = "user@datastax.com"; - List insertedMessages = new ArrayList<>(); - for (int i = 0; i < 30; i++) { - Instant timestamp = Instant.ofEpochMilli(i); - MailboxMessage message = new MailboxMessage(recipient, timestamp, "sender" + i, "body" + i); - insertedMessages.add(message); - service.sendGraphMessage(message); - } - Iterable retrievedMessages = service.getGraphMessages(recipient); - assertThat(retrievedMessages).containsExactlyElementsOf(insertedMessages); - } -} diff --git a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/BundleOptions.java b/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/BundleOptions.java index ffac828a0a8..218723997a6 100644 --- a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/BundleOptions.java +++ b/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/BundleOptions.java @@ -128,53 +128,6 @@ public static CompositeOption snappyBundle() { systemProperty("cassandra.compression").value("SNAPPY")); } - public static CompositeOption tinkerpopBundles() { - return () -> - options( - CoreOptions.wrappedBundle( - mavenBundle("org.apache.tinkerpop", "gremlin-core").versionAsInProject()) - .exports( - // avoid exporting 'org.apache.tinkerpop.gremlin.*' as other Tinkerpop jars have - // this root package as well - "org.apache.tinkerpop.gremlin.jsr223.*", - "org.apache.tinkerpop.gremlin.process.*", - "org.apache.tinkerpop.gremlin.structure.*", - "org.apache.tinkerpop.gremlin.util.*") - .bundleSymbolicName("org.apache.tinkerpop.gremlin-core") - .overwriteManifest(WrappedUrlProvisionOption.OverwriteMode.FULL), - CoreOptions.wrappedBundle( - mavenBundle("org.apache.tinkerpop", "tinkergraph-gremlin").versionAsInProject()) - .exports("org.apache.tinkerpop.gremlin.tinkergraph.*") - .bundleSymbolicName("org.apache.tinkerpop.tinkergraph-gremlin") - .overwriteManifest(WrappedUrlProvisionOption.OverwriteMode.FULL), - CoreOptions.wrappedBundle( - mavenBundle("org.apache.tinkerpop", "gremlin-shaded").versionAsInProject()) - .exports("org.apache.tinkerpop.shaded.*") - .bundleSymbolicName("org.apache.tinkerpop.gremlin-shaded") - .overwriteManifest(WrappedUrlProvisionOption.OverwriteMode.FULL), - // Note: the versions below are hard-coded because they shouldn't change very often, - // but if the tests fail because of them, we should consider parameterizing them - mavenBundle("com.sun.activation", "jakarta.activation", "2.0.1"), - mavenBundle("com.sun.mail", "mailapi", "2.0.1"), - mavenBundle("org.apache.commons", "commons-text", "1.8"), - mavenBundle("org.apache.commons", "commons-configuration2", "2.9.0"), - CoreOptions.wrappedBundle(mavenBundle("commons-logging", "commons-logging", "1.1.1")) - .exports("org.apache.commons.logging.*") - .bundleVersion("1.1.1") - .bundleSymbolicName("org.apache.commons.commons-logging") - .overwriteManifest(WrappedUrlProvisionOption.OverwriteMode.FULL), - mavenBundle("commons-collections", "commons-collections", "3.2.2"), - mavenBundle("org.apache.commons", "commons-lang3", "3.8.1"), - mavenBundle("commons-lang", "commons-lang", "2.6"), - CoreOptions.wrappedBundle(mavenBundle("org.javatuples", "javatuples", "1.2")) - .exports("org.javatuples.*") - .bundleVersion("1.2") - .bundleSymbolicName("org.javatuples") - .overwriteManifest(WrappedUrlProvisionOption.OverwriteMode.FULL), - systemProperty("cassandra.graph").value("true"), - systemProperty("cassandra.graph.name").value("test_osgi_graph")); - } - public static CompositeOption esriBundles() { return () -> options( diff --git a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/CcmStagedReactor.java b/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/CcmStagedReactor.java index ce4d9095361..85fa0e0da2e 100644 --- a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/CcmStagedReactor.java +++ b/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/CcmStagedReactor.java @@ -17,11 +17,8 @@ */ package com.datastax.oss.driver.internal.osgi.support; -import com.datastax.oss.driver.api.core.Version; import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; import java.util.List; -import java.util.Objects; import net.jcip.annotations.GuardedBy; import org.ops4j.pax.exam.TestContainer; import org.ops4j.pax.exam.TestProbeBuilder; @@ -35,14 +32,8 @@ public class CcmStagedReactor extends AllConfinedStagedReactor { public static final CcmBridge CCM_BRIDGE; - public static final Version DSE_5_0 = Objects.requireNonNull(Version.parse("5.0")); - static { - CcmBridge.Builder builder = CcmBridge.builder().withNodes(1); - if (CcmBridge.isDistributionOf(BackendType.DSE, (dist, cass) -> dist.compareTo(DSE_5_0) >= 0)) { - builder.withDseWorkloads("graph"); - } - CCM_BRIDGE = builder.build(); + CCM_BRIDGE = CcmBridge.builder().withNodes(1).build(); } @GuardedBy("this") diff --git a/pom.xml b/pom.xml index 76caea447cc..d4928f0addb 100644 --- a/pom.xml +++ b/pom.xml @@ -60,11 +60,6 @@ 4.2.38 4.1.136.Final 1.2.1 - - 3.5.6 2.0.18 @@ -243,34 +238,6 @@ json ${json.version} - - org.apache.tinkerpop - gremlin-core - ${tinkerpop.version} - - - org.yaml - snakeyaml - - - com.carrotsearch - hppc - - - com.jcabi - * - - - net.objecthunter - exp4j - - - - - org.apache.tinkerpop - tinkergraph-gremlin - ${tinkerpop.version} - org.reactivestreams reactive-streams diff --git a/test-infra/pom.xml b/test-infra/pom.xml index f4e5d93af34..ef38722861b 100644 --- a/test-infra/pom.xml +++ b/test-infra/pom.xml @@ -48,11 +48,6 @@ com.scylladb java-driver-core - - org.apache.tinkerpop - gremlin-core - provided - com.github.spotbugs spotbugs-annotations diff --git a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/CqlSessionRuleBuilder.java b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/CqlSessionRuleBuilder.java index 8f392dca0bf..e529a00b6b2 100644 --- a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/CqlSessionRuleBuilder.java +++ b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/CqlSessionRuleBuilder.java @@ -17,84 +17,21 @@ */ package com.datastax.oss.driver.api.testinfra.session; -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.config.DriverConfigLoader; import com.datastax.oss.driver.api.testinfra.CassandraResourceRule; import com.datastax.oss.driver.internal.core.config.typesafe.DefaultDriverConfigLoader; -import com.typesafe.config.Config; -import com.typesafe.config.ConfigValueFactory; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Supplier; public class CqlSessionRuleBuilder extends SessionRuleBuilder { - private static final AtomicInteger GRAPH_NAME_INDEX = new AtomicInteger(); - public CqlSessionRuleBuilder(CassandraResourceRule cassandraResource) { super(cassandraResource); } @Override public SessionRule build() { - - final String graphName; - final DriverConfigLoader actualLoader; - - Supplier actualSupplier; - - if (createGraph) { - graphName = "dsedrivertests_" + GRAPH_NAME_INDEX.getAndIncrement(); - - // Inject the generated graph name in the provided configuration, so that the test doesn't - // need to set it explicitly on every statement. - if (loader == null) { - // This would normally be handled in DseSessionBuilder, do it early because we need it now - loader = new DefaultDriverConfigLoader(); - } else { - // To keep this relatively simple we assume that if the config loader was provided in a - // test, it is the Typesafe-config based one. This is always true in our integration tests. - assertThat(loader).isInstanceOf(DefaultDriverConfigLoader.class); - } - Supplier originalSupplier = ((DefaultDriverConfigLoader) loader).getConfigSupplier(); - actualSupplier = - () -> - originalSupplier - .get() - .withValue( - DseDriverOption.GRAPH_NAME.getPath(), - ConfigValueFactory.fromAnyRef(graphName)); - } else { - graphName = null; - if (loader == null) { - loader = new DefaultDriverConfigLoader(); - } - - actualSupplier = ((DefaultDriverConfigLoader) loader).getConfigSupplier(); - } - - actualLoader = - new DefaultDriverConfigLoader( - () -> - graphProtocol != null - ? actualSupplier - .get() - .withValue( - DseDriverOption.GRAPH_SUB_PROTOCOL.getPath(), - ConfigValueFactory.fromAnyRef(graphProtocol)) - // will use the protocol from the config file (in application.conf if - // defined or in reference.conf) - : actualSupplier.get()); - + DriverConfigLoader actualLoader = loader == null ? new DefaultDriverConfigLoader() : loader; return new SessionRule<>( - cassandraResource, - createKeyspace, - nodeStateListener, - schemaChangeListener, - actualLoader, - graphName, - isCoreGraph); + cassandraResource, createKeyspace, nodeStateListener, schemaChangeListener, actualLoader); } } diff --git a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRule.java b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRule.java index 3b792374769..67072e29965 100644 --- a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRule.java +++ b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRule.java @@ -17,9 +17,7 @@ */ package com.datastax.oss.driver.api.testinfra.session; -import com.datastax.dse.driver.api.core.graph.ScriptGraphStatement; import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.Version; import com.datastax.oss.driver.api.core.config.DriverConfigLoader; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; import com.datastax.oss.driver.api.core.cql.SimpleStatement; @@ -28,12 +26,8 @@ import com.datastax.oss.driver.api.core.metadata.schema.SchemaChangeListener; import com.datastax.oss.driver.api.core.session.Session; import com.datastax.oss.driver.api.testinfra.CassandraResourceRule; -import com.datastax.oss.driver.api.testinfra.ccm.BaseCcmRule; -import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge; import com.datastax.oss.driver.api.testinfra.ccm.SchemaChangeSynchronizer; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; import com.datastax.oss.driver.api.testinfra.simulacron.SimulacronRule; -import java.util.Objects; import org.junit.rules.ExternalResource; /** @@ -63,16 +57,12 @@ */ public class SessionRule extends ExternalResource { - private static final Version V6_8_0 = Objects.requireNonNull(Version.parse("6.8.0")); - // the CCM or Simulacron rule to depend on private final CassandraResourceRule cassandraResource; private final NodeStateListener nodeStateListener; private final SchemaChangeListener schemaChangeListener; private final CqlIdentifier keyspace; private final DriverConfigLoader configLoader; - private final String graphName; - private final boolean isCoreGraph; // the session that is auto created for this rule and is tied to the given keyspace. private SessionT session; @@ -94,9 +84,7 @@ public SessionRule( boolean createKeyspace, NodeStateListener nodeStateListener, SchemaChangeListener schemaChangeListener, - DriverConfigLoader configLoader, - String graphName, - boolean isCoreGraph) { + DriverConfigLoader configLoader) { this.cassandraResource = cassandraResource; this.nodeStateListener = nodeStateListener; this.schemaChangeListener = schemaChangeListener; @@ -105,41 +93,6 @@ public SessionRule( ? null : SessionUtils.uniqueKeyspaceId(); this.configLoader = configLoader; - this.graphName = graphName; - this.isCoreGraph = isCoreGraph; - } - - public SessionRule( - CassandraResourceRule cassandraResource, - boolean createKeyspace, - NodeStateListener nodeStateListener, - SchemaChangeListener schemaChangeListener, - DriverConfigLoader configLoader, - String graphName) { - this( - cassandraResource, - createKeyspace, - nodeStateListener, - schemaChangeListener, - configLoader, - graphName, - false); - } - - public SessionRule( - CassandraResourceRule cassandraResource, - boolean createKeyspace, - NodeStateListener nodeStateListener, - SchemaChangeListener schemaChangeListener, - DriverConfigLoader configLoader) { - this( - cassandraResource, - createKeyspace, - nodeStateListener, - schemaChangeListener, - configLoader, - null, - false); } @Override @@ -154,46 +107,10 @@ protected void before() { SimpleStatement.newInstance(String.format("USE %s", keyspace.asCql(false))), Statement.SYNC); } - if (graphName != null) { - BaseCcmRule rule = - (cassandraResource instanceof BaseCcmRule) ? ((BaseCcmRule) cassandraResource) : null; - if (rule == null || !CcmBridge.isDistributionOf(BackendType.DSE)) { - throw new IllegalArgumentException("DseSessionRule should work with DSE."); - } - if (rule.getDistributionVersion().compareTo(V6_8_0) >= 0) { - session() - .execute( - ScriptGraphStatement.newInstance( - String.format( - "system.graph('%s').ifNotExists()%s.create()", - this.graphName, isCoreGraph ? ".coreEngine()" : ".classicEngine()")) - .setSystemQuery(true), - ScriptGraphStatement.SYNC); - } else { - if (isCoreGraph) { - throw new IllegalArgumentException( - "Core graph is not supported for DSE version < " + V6_8_0); - } - session() - .execute( - ScriptGraphStatement.newInstance( - String.format("system.graph('%s').ifNotExists().create()", this.graphName)) - .setSystemQuery(true), - ScriptGraphStatement.SYNC); - } - } } @Override protected void after() { - if (graphName != null) { - session() - .execute( - ScriptGraphStatement.newInstance( - String.format("system.graph('%s').drop()", this.graphName)) - .setSystemQuery(true), - ScriptGraphStatement.SYNC); - } if (keyspace != null) { SchemaChangeSynchronizer.withLock( () -> { @@ -217,10 +134,6 @@ public CqlIdentifier keyspace() { return keyspace; } - public String getGraphName() { - return graphName; - } - /** @return a config profile where the request timeout is 30 seconds. * */ public DriverExecutionProfile slowProfile() { return slowProfile; diff --git a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRuleBuilder.java b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRuleBuilder.java index 62c5babbf1d..b143ff4c7e9 100644 --- a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRuleBuilder.java +++ b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRuleBuilder.java @@ -33,9 +33,6 @@ public abstract class SessionRuleBuilder< protected NodeStateListener nodeStateListener; protected SchemaChangeListener schemaChangeListener; protected DriverConfigLoader loader; - protected boolean createGraph; - protected boolean isCoreGraph; - protected String graphProtocol; @SuppressWarnings("unchecked") protected final SelfT self = (SelfT) this; @@ -79,30 +76,5 @@ public SelfT withSchemaChangeListener(SchemaChangeListener listener) { return self; } - /** - * Configures the rule to create a new graph instance. - * - *

This assumes that the associated {@link CassandraResourceRule} is a DSE instance with the - * graph workload enabled. - * - *

The name of the graph will be injected in the session's configuration, so that all graph - * statements are automatically routed to it. It's also exposed via {@link - * SessionRule#getGraphName()}. - */ - public SelfT withCreateGraph() { - this.createGraph = true; - return self; - } - - public SelfT withCoreEngine() { - this.isCoreGraph = true; - return self; - } - - public SelfT withGraphProtocol(String graphProtocol) { - this.graphProtocol = graphProtocol; - return self; - } - public abstract SessionRule build(); } diff --git a/test-infra/src/main/java/com/datastax/oss/driver/internal/gremlin/PatchedGremlinDslProcessor.java b/test-infra/src/main/java/com/datastax/oss/driver/internal/gremlin/PatchedGremlinDslProcessor.java deleted file mode 100644 index e8639b2d396..00000000000 --- a/test-infra/src/main/java/com/datastax/oss/driver/internal/gremlin/PatchedGremlinDslProcessor.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.oss.driver.internal.gremlin; - -import java.util.Collections; -import java.util.Set; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.SourceVersion; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.GremlinDslProcessor; - -@SupportedAnnotationTypes("org.apache.tinkerpop.gremlin.process.traversal.dsl.GremlinDsl") -public class PatchedGremlinDslProcessor extends GremlinDslProcessor { - - @Override - public Set getSupportedAnnotationTypes() { - return Collections.singleton("org.apache.tinkerpop.gremlin.process.traversal.dsl.GremlinDsl"); - } - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } -} diff --git a/upgrade_guide/README.md b/upgrade_guide/README.md index 8c4bf110560..a976b60c051 100644 --- a/upgrade_guide/README.md +++ b/upgrade_guide/README.md @@ -510,37 +510,6 @@ token map for these keyspaces, you now must modify the following configuration o [Metadata.getKeyspaces()]: https://docs.datastax.com/en/drivers/java/4.11/com/datastax/oss/driver/api/core/metadata/Metadata.html#getKeyspaces-- [TokenMap]: https://docs.datastax.com/en/drivers/java/4.11/com/datastax/oss/driver/api/core/metadata/TokenMap.html -#### DSE Graph dependencies are now optional - -Until driver 4.9.0, the driver declared a mandatory dependency to Apache TinkerPop, a library -required only when connecting to DSE Graph. The vast majority of Apache Cassandra users did not need -that library, but were paying the price of having that heavy-weight library in their application's -classpath. - -_Starting with driver 4.10.0, TinkerPop is now considered an optional dependency_. - -Regular users of Apache Cassandra that do not use DSE Graph will not notice any disruption. - -DSE Graph users, however, will now have to explicitly declare a dependency to Apache TinkerPop. This -can be achieved with Maven by adding the following dependencies to the `` section of -your POM file: - -```xml - - org.apache.tinkerpop - gremlin-core - ${tinkerpop.version} - - - org.apache.tinkerpop - tinkergraph-gremlin - ${tinkerpop.version} - -``` - -See the [integration](../manual/core/integration/#tinker-pop) section in the manual for more details -as well as a driver vs. TinkerPop version compatibility matrix. - ### 4.5.x - 4.6.0 These versions are subject to [JAVA-2676](https://datastax-oss.atlassian.net/browse/JAVA-2676), a @@ -559,9 +528,9 @@ See the `CqlSession.executeReactive` methods. Apart from that, the only visible change is that DSE-specific features are now exposed in the API: -* new execution methods: `CqlSession.executeGraph`, `CqlSession.executeContinuously*`. They all - have default implementations so this doesn't break binary compatibility. You can just ignore them. -* new driver dependencies: TinkerPop, ESRI, Reactive Streams. If you want to keep your classpath +* new execution methods: `CqlSession.executeContinuously*`. They have default implementations so + this doesn't break binary compatibility. You can just ignore them. +* new driver dependencies: ESRI and Reactive Streams. If you want to keep your classpath lean, you can exclude some dependencies when you don't use the corresponding DSE features; see the [Integration>Driver dependencies](../manual/core/integration/#driver-dependencies) section. From 59b3f78b6b1eb0eb36a3fbe1607bdbc38f13da95 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Mon, 31 Aug 2026 11:53:46 -0400 Subject: [PATCH 2/2] Remove unused DSE protocol support --- changelog/README.md | 1 + .../driver/api/core/DseProtocolVersion.java | 70 - .../api/core/config/DseDriverOption.java | 92 - .../continuous/ContinuousAsyncResultSet.java | 79 - .../cql/continuous/ContinuousResultSet.java | 80 - .../cql/continuous/ContinuousSession.java | 116 -- .../reactive/ContinuousReactiveResultSet.java | 29 - .../reactive/ContinuousReactiveSession.java | 84 - .../api/core/metrics/DseSessionMetric.java | 60 - .../servererrors/UnfitClientException.java | 55 - .../internal/core/DseProtocolFeature.java | 38 - .../internal/core/cql/DseConversions.java | 163 -- .../ContinuousCqlRequestAsyncProcessor.java | 56 - .../ContinuousCqlRequestHandler.java | 171 -- .../ContinuousCqlRequestSyncProcessor.java | 67 - .../ContinuousRequestHandlerBase.java | 1724 ----------------- .../DefaultContinuousAsyncResultSet.java | 169 -- .../DefaultContinuousResultSet.java | 132 -- ...ContinuousCqlRequestReactiveProcessor.java | 63 - .../DefaultContinuousReactiveResultSet.java | 35 - .../cql/reactive/FailedReactiveResultSet.java | 5 +- .../ReactiveResultSetSubscription.java | 5 +- .../core/insights/InsightsClient.java | 4 +- .../oss/driver/api/core/CqlSession.java | 18 +- .../oss/driver/api/core/ProtocolVersion.java | 3 - .../driver/api/core/config/OptionsMap.java | 20 - .../api/core/config/TypedDriverOption.java | 70 - .../api/core/metrics/SessionMetric.java | 3 +- .../core/DefaultProtocolVersionRegistry.java | 207 +- .../core/context/DefaultDriverContext.java | 10 +- .../DropwizardSessionMetricUpdater.java | 8 - .../internal/core/metrics/MetricPaths.java | 7 +- .../session/BuiltInRequestProcessors.java | 14 - .../DriverBlockHoundIntegration.java | 27 - core/src/main/resources/reference.conf | 122 -- .../dse/driver/DseTestDataProviders.java | 11 - .../datastax/dse/driver/DseTestFixtures.java | 18 +- .../context/DseStartupOptionsBuilderTest.java | 1 - ...ousCqlRequestHandlerNodeTargetingTest.java | 182 -- ...tinuousCqlRequestHandlerReprepareTest.java | 197 -- .../ContinuousCqlRequestHandlerRetryTest.java | 600 ------ .../ContinuousCqlRequestHandlerTest.java | 560 ------ .../ContinuousCqlRequestHandlerTestBase.java | 50 - .../DefaultContinuousAsyncResultSetTest.java | 117 -- .../DefaultContinuousResultSetTest.java | 154 -- ...inuousCqlRequestReactiveProcessorTest.java | 173 -- .../CqlRequestReactiveProcessorTest.java | 8 +- .../core/insights/InsightsClientTest.java | 6 +- .../DefaultProtocolVersionRegistryTest.java | 90 +- .../composite/CompositeDriverConfigTest.java | 17 +- .../codec/extras/enums/EnumNameCodecTest.java | 2 - .../extras/enums/EnumOrdinalCodecTest.java | 2 - .../resources/config/customApplication.conf | 2 - .../resources/config/customApplication.json | 5 - .../config/customApplication.properties | 1 - .../cql/continuous/ContinuousPagingIT.java | 699 ------- .../continuous/ContinuousPagingITBase.java | 197 -- .../reactive/ContinuousPagingReactiveIT.java | 118 -- .../ProtocolVersionInitialNegotiationIT.java | 131 -- .../DriverConfigReportingSimulacronIT.java | 6 +- .../DriverBlockHoundIntegrationCcmIT.java | 131 -- .../src/test/resources/application.conf | 4 - manual/core/native_protocol/README.md | 12 - manual/core/non_blocking/README.md | 19 +- .../MicrometerSessionMetricUpdater.java | 29 - .../MicrometerSessionMetricUpdaterTest.java | 10 - .../MicroProfileSessionMetricUpdater.java | 2 - .../src/main/resources/application.conf | 4 - upgrade_guide/README.md | 10 +- 69 files changed, 99 insertions(+), 7276 deletions(-) delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/DseProtocolVersion.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousAsyncResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousSession.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousReactiveResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousReactiveSession.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseSessionMetric.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/api/core/servererrors/UnfitClientException.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/DseProtocolFeature.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/cql/DseConversions.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestAsyncProcessor.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandler.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestSyncProcessor.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousRequestHandlerBase.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousAsyncResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousResultSet.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/ContinuousCqlRequestReactiveProcessor.java delete mode 100644 core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/DefaultContinuousReactiveResultSet.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerNodeTargetingTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerReprepareTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerRetryTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerTestBase.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousAsyncResultSetTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousResultSetTest.java delete mode 100644 core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/ContinuousCqlRequestReactiveProcessorTest.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingITBase.java delete mode 100644 integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousPagingReactiveIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/oss/driver/internal/core/util/concurrent/DriverBlockHoundIntegrationCcmIT.java diff --git a/changelog/README.md b/changelog/README.md index e3d3ee58697..2a02b35123a 100644 --- a/changelog/README.md +++ b/changelog/README.md @@ -23,6 +23,7 @@ under the License. ### 4.19.2 +- [improvement] Remove unused DSE protocol and continuous paging support (#1032) - [improvement] Remove unused DSE Graph support and TinkerPop integration (#1028) - [bug] CASSJAVA-116: Retry or Speculative Execution with RequestIdGenerator throws "Duplicate Key" diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/DseProtocolVersion.java b/core/src/main/java/com/datastax/dse/driver/api/core/DseProtocolVersion.java deleted file mode 100644 index f5fe545c421..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/DseProtocolVersion.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -/* - * Copyright (C) 2018 ScyllaDB - * - * Modified by ScyllaDB - */ -package com.datastax.dse.driver.api.core; - -import com.datastax.dse.protocol.internal.DseProtocolConstants; -import com.datastax.oss.driver.api.core.DefaultProtocolVersion; -import com.datastax.oss.driver.api.core.ProtocolVersion; - -/** - * A DSE-specific protocol version. - * - *

Legacy DSE versions did not have a specific version, but instead reused a Cassandra protocol - * version: DSE 5.0 is supported via {@link DefaultProtocolVersion#V4}, and DSE 4.7 and 4.8 via - * {@link DefaultProtocolVersion#V3}. - * - *

DSE 4.6 and earlier are not supported by this version of the driver, use the 1.x series. - */ -public enum DseProtocolVersion implements ProtocolVersion { - - /** Version 1, supported by DSE 5.1.0 and above. */ - DSE_V1(DseProtocolConstants.Version.DSE_V1, false), - - /** Version 2, supported by DSE 6 and above. */ - DSE_V2(DseProtocolConstants.Version.DSE_V2, false), - ; - - private final int code; - private final boolean beta; - - DseProtocolVersion(int code, boolean beta) { - this.code = code; - this.beta = beta; - } - - @Override - public int getCode() { - return code; - } - - @Override - public boolean isBeta() { - return beta; - } - - @Override - public boolean supportsShardingInfo() { - return false; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/config/DseDriverOption.java b/core/src/main/java/com/datastax/dse/driver/api/core/config/DseDriverOption.java index 612448cb99e..0cf30b10a57 100644 --- a/core/src/main/java/com/datastax/dse/driver/api/core/config/DseDriverOption.java +++ b/core/src/main/java/com/datastax/dse/driver/api/core/config/DseDriverOption.java @@ -59,104 +59,12 @@ public enum DseDriverOption implements DriverOption { */ AUTH_PROVIDER_SASL_PROPERTIES("advanced.auth-provider.sasl-properties"), - /** - * The page size for continuous paging. - * - *

Value type: int - */ - CONTINUOUS_PAGING_PAGE_SIZE("advanced.continuous-paging.page-size"), - /** - * Whether {@link #CONTINUOUS_PAGING_PAGE_SIZE} should be interpreted in number of rows or bytes. - * - *

Value type: boolean - */ - CONTINUOUS_PAGING_PAGE_SIZE_BYTES("advanced.continuous-paging.page-size-in-bytes"), - /** - * The maximum number of continuous pages to return. - * - *

Value type: int - */ - CONTINUOUS_PAGING_MAX_PAGES("advanced.continuous-paging.max-pages"), - /** - * The maximum number of continuous pages per second. - * - *

Value type: int - */ - CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND("advanced.continuous-paging.max-pages-per-second"), - /** - * The maximum number of continuous pages that can be stored in the local queue. - * - *

Value type: int - */ - CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES("advanced.continuous-paging.max-enqueued-pages"), - /** - * How long to wait for the coordinator to send the first continuous page. - * - *

Value-type: {@link java.time.Duration Duration} - */ - CONTINUOUS_PAGING_TIMEOUT_FIRST_PAGE("advanced.continuous-paging.timeout.first-page"), - /** - * How long to wait for the coordinator to send subsequent continuous pages. - * - *

Value-type: {@link java.time.Duration Duration} - */ - CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES("advanced.continuous-paging.timeout.other-pages"), - - /** - * The largest latency that we expect to record for continuous requests. - * - *

Value-type: {@link java.time.Duration Duration} - */ - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_HIGHEST( - "advanced.metrics.session.continuous-cql-requests.highest-latency"), - /** - * The number of significant decimal digits to which internal structures will maintain for - * continuous requests. - * - *

Value-type: int - */ - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_DIGITS( - "advanced.metrics.session.continuous-cql-requests.significant-digits"), - /** - * The interval at which percentile data is refreshed for continuous requests. - * - *

Value-type: {@link java.time.Duration Duration} - */ - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_INTERVAL( - "advanced.metrics.session.continuous-cql-requests.refresh-interval"), - /** * Whether to send events for Insights monitoring. * *

Value type: boolean */ MONITOR_REPORTING_ENABLED("advanced.monitor-reporting.enabled"), - - /** - * The shortest latency that we expect to record for continuous requests. - * - *

Value-type: {@link java.time.Duration Duration} - */ - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_LOWEST( - "advanced.metrics.session.continuous-cql-requests.lowest-latency"), - /** - * Optional service-level objectives to meet, as a list of latencies to track. - * - *

Value-type: {@link java.time.Duration Duration} - */ - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_SLO( - "advanced.metrics.session.continuous-cql-requests.slo"), - - /** - * Optional list of percentiles to publish for continuous paging requests metric. Produces an - * additional time series for each requested percentile. This percentile is computed locally, and - * so can't be aggregated with percentiles computed across other dimensions (e.g. in a different - * instance). - * - *

Value type: {@link java.util.List List}<{@link Double}> - */ - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_PUBLISH_PERCENTILES( - "advanced.metrics.session.continuous-cql-requests.publish-percentiles"), ; private final String path; diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousAsyncResultSet.java b/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousAsyncResultSet.java deleted file mode 100644 index a9491ec2414..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousAsyncResultSet.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.cql.continuous; - -import com.datastax.oss.driver.api.core.AsyncPagingIterable; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.Row; -import com.datastax.oss.driver.api.core.cql.Statement; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.nio.ByteBuffer; -import java.util.concurrent.CancellationException; - -/** - * The result of an {@linkplain ContinuousSession#executeContinuouslyAsync(Statement) asynchronous - * continuous paging query}. - * - *

DSE replies to a continuous query with a stream of response frames. There is one instance of - * this class for each frame. - */ -public interface ContinuousAsyncResultSet - extends AsyncPagingIterable { - - /** Returns the current page's number. Pages are numbered starting from 1. */ - int pageNumber(); - - /** - * Cancels the continuous query. - * - *

There might still be rows available in the {@linkplain #currentPage() current page} after - * the cancellation; these rows can be retrieved normally. - * - *

Also, there might be more pages available in the driver's local page cache after the - * cancellation; these extra pages will be discarded. - * - *

Therefore, if you plan to resume the iteration later, the correct procedure is as follows: - * - *

    - *
  1. Cancel the operation by invoking this method, or by cancelling the {@linkplain - * #fetchNextPage() next page's future}; - *
  2. Keep iterating on the current page until it doesn't return any more rows; - *
  3. Retrieve the paging state with {@link #getExecutionInfo() - * getExecutionInfo().getPagingState()}; - *
  4. {@linkplain Statement#setPagingState(ByteBuffer) Re-inject the paging state} in the - * statement; - *
  5. Resume the operation by invoking {@link - * ContinuousSession#executeContinuouslyAsync(Statement) executeContinuouslyAsync} again. - *
- * - * After a cancellation, futures returned by {@link #fetchNextPage()} that are not yet complete - * will always complete exceptionally by throwing a {@link CancellationException}, even if - * they were obtained before the cancellation. - */ - void cancel(); - - /** - * {@inheritDoc} - * - *

Note: because the driver does not support query traces for continuous queries, {@link - * ExecutionInfo#getTracingId()} will always be {@code null}. - */ - @NonNull - @Override - ExecutionInfo getExecutionInfo(); -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousResultSet.java b/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousResultSet.java deleted file mode 100644 index a333801a59a..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousResultSet.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.cql.continuous; - -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.ResultSet; -import com.datastax.oss.driver.api.core.cql.Statement; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.nio.ByteBuffer; -import java.util.List; - -/** - * The result of a {@linkplain ContinuousSession#executeContinuously(Statement) synchronous - * continuous paging query}. - * - *

It uses {@linkplain ContinuousAsyncResultSet asynchronous calls} internally, but blocks on the - * results in order to provide a synchronous API to its clients. If the query is paged, only the - * first page will be fetched initially, and iteration will trigger background fetches of the next - * pages when necessary. - * - *

Note that this object can only be iterated once: rows are "consumed" as they are read, - * subsequent calls to {@code iterator()} will return the same iterator instance. - * - *

Implementations of this type are not thread-safe. They can only be iterated by the - * thread that invoked {@code session.executeContinuously}. - */ -public interface ContinuousResultSet extends ResultSet { - - /** - * Cancels the continuous query. - * - *

There might still be rows available in the current page after the cancellation; the - * iteration will only stop when such rows are fully iterated upon. - * - *

Also, there might be more pages available in the driver's local page cache after the - * cancellation; these extra pages will be discarded. - * - *

Therefore, if you plan to resume the iteration later, the correct procedure is as follows: - * - *

    - *
  1. Cancel the operation by invoking this method; - *
  2. Keep iterating on this object until it doesn't return any more rows; - *
  3. Retrieve the paging state with {@link #getExecutionInfo() - * getExecutionInfo().getPagingState()}; - *
  4. {@linkplain Statement#setPagingState(ByteBuffer) Re-inject the paging state} in the - * statement; - *
  5. Resume the operation by invoking {@link ContinuousSession#executeContinuously(Statement) - * executeContinuously} again. - *
- */ - void cancel(); - - /** - * {@inheritDoc} - * - *

Note: because the driver does not support query traces for continuous queries, {@link - * ExecutionInfo#getTracingId()} will always be {@code null}. - */ - @NonNull - @Override - default ExecutionInfo getExecutionInfo() { - List infos = getExecutionInfos(); - return infos.get(infos.size() - 1); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousSession.java b/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousSession.java deleted file mode 100644 index 1c647b33b92..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousSession.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.cql.continuous; - -import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousCqlRequestAsyncProcessor; -import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousCqlRequestSyncProcessor; -import com.datastax.oss.driver.api.core.DefaultConsistencyLevel; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.loadbalancing.LoadBalancingPolicy; -import com.datastax.oss.driver.api.core.metadata.token.Token; -import com.datastax.oss.driver.api.core.session.Session; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.nio.ByteBuffer; -import java.util.Objects; -import java.util.concurrent.CompletionStage; - -/** - * A session that has the ability to execute continuous paging queries. - * - *

Continuous paging is a new method of streaming bulk amounts of records from DataStax - * Enterprise (DSE) to the Java Driver, available since DSE 5.1. It is mainly intended to be - * leveraged by DSE - * Analytics and Apache Spark™, or by any similar analytics tool that needs to read large - * portions of a table in one single operation, as quick and reliably as possible. - * - *

Continuous paging provides the best performance improvement against regular paging when the - * following conditions are met: - * - *

    - *
  1. The statement must target a single partition or a token range owned by one single replica; - * in practice, this means that the statement must have either a {@linkplain - * Statement#setRoutingKey(ByteBuffer) routing key} or a {@linkplain - * Statement#setRoutingToken(Token) routing token} set; - *
  2. The coordinator must be a replica; in practice, this is usually achieved by using - * token-aware routing (if you are using the driver's default {@link LoadBalancingPolicy}, - * then this condition is met); - *
  3. The consistency level must be {@link DefaultConsistencyLevel#ONE ONE} (or {@link - * DefaultConsistencyLevel#LOCAL_ONE LOCAL_ONE}). - *
- * - *

If the above conditions are met, the coordinator will be able to optimize the read path and - * serve results from local data, thus significantly improving response times; if however these - * conditions cannot be met, continuous paging would still work, but response times wouldn't be - * significantly better than those of regular paging anymore. - * - * @see Continuous - * paging options in cassandra.yaml configuration file - * @see DSE - * Continuous Paging Tuning and Support Guide - */ -public interface ContinuousSession extends Session { - - /** - * Executes the provided query with continuous paging synchronously. - * - *

This method takes care of chaining the successive results into a convenient iterable, - * provided that you always access the result from the same thread. For more flexibility, consider - * using the {@linkplain #executeContinuouslyAsync(Statement) asynchronous variant} of this method - * instead. - * - *

See {@link ContinuousSession} for more explanations about continuous paging. - * - *

This feature is only available with DataStax Enterprise. Executing continuous queries - * against an Apache Cassandra© cluster will result in a runtime error. - * - * @param statement the query to execute. - * @return a synchronous iterable on the results. - */ - @NonNull - default ContinuousResultSet executeContinuously(@NonNull Statement statement) { - return Objects.requireNonNull( - execute(statement, ContinuousCqlRequestSyncProcessor.CONTINUOUS_RESULT_SYNC)); - } - - /** - * Executes the provided query with continuous paging asynchronously. - * - *

The server will push all requested pages asynchronously, according to the options defined in - * the current execution profile. The client should consume all pages as quickly as possible, to - * avoid blocking the server for too long. The server will adjust the rate according to the client - * speed, but it will give up if the client does not consume any pages in a period of time equal - * to the read request timeout. - * - *

See {@link ContinuousSession} for more explanations about continuous paging. - * - *

This feature is only available with DataStax Enterprise. Executing continuous queries - * against an Apache Cassandra© cluster will result in a runtime error. - * - * @param statement the query to execute. - * @return a future to the first asynchronous result. - */ - @NonNull - default CompletionStage executeContinuouslyAsync( - @NonNull Statement statement) { - return Objects.requireNonNull( - execute(statement, ContinuousCqlRequestAsyncProcessor.CONTINUOUS_RESULT_ASYNC)); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousReactiveResultSet.java b/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousReactiveResultSet.java deleted file mode 100644 index 6b645ad05bf..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousReactiveResultSet.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.cql.continuous.reactive; - -import com.datastax.dse.driver.api.core.cql.reactive.ReactiveResultSet; -import com.datastax.oss.driver.api.core.cql.Statement; - -/** - * A marker interface for publishers returned by {@link ContinuousReactiveSession}. - * - * @see ContinuousReactiveSession#executeContinuouslyReactive(String) - * @see ContinuousReactiveSession#executeContinuouslyReactive(Statement) - */ -public interface ContinuousReactiveResultSet extends ReactiveResultSet {} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousReactiveSession.java b/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousReactiveSession.java deleted file mode 100644 index d00013731cb..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousReactiveSession.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.cql.continuous.reactive; - -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousSession; -import com.datastax.dse.driver.api.core.cql.reactive.ReactiveRow; -import com.datastax.dse.driver.internal.core.cql.continuous.reactive.ContinuousCqlRequestReactiveProcessor; -import com.datastax.oss.driver.api.core.cql.SimpleStatement; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.session.Session; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Objects; -import org.reactivestreams.Publisher; - -/** - * A {@link Session} that offers utility methods to issue queries using reactive-style programming - * and continuous paging, combined together. - * - *

Methods in this interface all return {@link ContinuousReactiveResultSet} instances. All - * publishers support multiple subscriptions in a unicast fashion: each subscriber triggers an - * independent request execution and gets its own copy of the results. - * - *

Also, note that the publishers may emit items to their subscribers on an internal driver IO - * thread. Subscriber implementors are encouraged to abide by Reactive Streams - * Specification rule 2.2 and avoid performing heavy computations or blocking calls inside - * {@link org.reactivestreams.Subscriber#onNext(Object) onNext} calls, as doing so could slow down - * the driver and impact performance. Instead, they should asynchronously dispatch received signals - * to their processing logic. - * - * @see ReactiveRow - */ -public interface ContinuousReactiveSession extends Session { - - /** - * Returns a {@link Publisher} that, once subscribed to, executes the given query continuously and - * emits all the results. - * - *

See {@link ContinuousSession} for more explanations about continuous paging. - * - *

This feature is only available with DataStax Enterprise. Executing continuous queries - * against an Apache Cassandra® cluster will result in a runtime error. - * - * @param query the query to execute. - * @return The {@link Publisher} that will publish the returned results. - */ - @NonNull - default ContinuousReactiveResultSet executeContinuouslyReactive(@NonNull String query) { - return executeContinuouslyReactive(SimpleStatement.newInstance(query)); - } - - /** - * Returns a {@link Publisher} that, once subscribed to, executes the given query continuously and - * emits all the results. - * - *

See {@link ContinuousSession} for more explanations about continuous paging. - * - *

This feature is only available with DataStax Enterprise. Executing continuous queries - * against an Apache Cassandra® cluster will result in a runtime error. - * - * @param statement the statement to execute. - * @return The {@link Publisher} that will publish the returned results. - */ - @NonNull - default ContinuousReactiveResultSet executeContinuouslyReactive(@NonNull Statement statement) { - return Objects.requireNonNull( - execute(statement, ContinuousCqlRequestReactiveProcessor.CONTINUOUS_REACTIVE_RESULT_SET)); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseSessionMetric.java b/core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseSessionMetric.java deleted file mode 100644 index 1e0358a45cb..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/metrics/DseSessionMetric.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.metrics; - -import com.datastax.oss.driver.api.core.metrics.SessionMetric; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Map; - -/** See {@code reference.conf} for a description of each metric. */ -public enum DseSessionMetric implements SessionMetric { - CONTINUOUS_CQL_REQUESTS("continuous-cql-requests"), - ; - - private static final Map BY_PATH = sortByPath(); - - private final String path; - - DseSessionMetric(String path) { - this.path = path; - } - - @NonNull - @Override - public String getPath() { - return path; - } - - @NonNull - public static DseSessionMetric fromPath(@NonNull String path) { - DseSessionMetric metric = BY_PATH.get(path); - if (metric == null) { - throw new IllegalArgumentException("Unknown DSE session metric path " + path); - } - return metric; - } - - private static Map sortByPath() { - ImmutableMap.Builder result = ImmutableMap.builder(); - for (DseSessionMetric value : values()) { - result.put(value.getPath(), value); - } - return result.build(); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/api/core/servererrors/UnfitClientException.java b/core/src/main/java/com/datastax/dse/driver/api/core/servererrors/UnfitClientException.java deleted file mode 100644 index 8bf4d80699d..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/api/core/servererrors/UnfitClientException.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.servererrors; - -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.servererrors.CoordinatorException; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; - -/** - * A server-side error triggered when DSE can't send asynchronous results back to the client. - * - *

Currently, this is used when the client is unable to keep up with the rate during a continuous - * paging session. - * - *

Note that the protocol specification refers to this error as {@code CLIENT_WRITE_FAILURE}; we - * don't follow that terminology because it would be too misleading (this is not a client error, and - * it doesn't occur while writing data to DSE). - */ -public class UnfitClientException extends CoordinatorException { - - public UnfitClientException(@NonNull Node coordinator, @NonNull String message) { - this(coordinator, message, null, false); - } - - private UnfitClientException( - @NonNull Node coordinator, - @NonNull String message, - @Nullable ExecutionInfo executionInfo, - boolean writableStackTrace) { - super(coordinator, message, executionInfo, writableStackTrace); - } - - @Override - @NonNull - public UnfitClientException copy() { - return new UnfitClientException(getCoordinator(), getMessage(), getExecutionInfo(), true); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/DseProtocolFeature.java b/core/src/main/java/com/datastax/dse/driver/internal/core/DseProtocolFeature.java deleted file mode 100644 index 95f245061d2..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/DseProtocolFeature.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core; - -import com.datastax.oss.driver.internal.core.ProtocolFeature; - -/** - * Features that are supported by DataStax Enterprise (DSE) protocol versions. - * - * @see com.datastax.dse.driver.api.core.DseProtocolVersion - * @see com.datastax.oss.driver.internal.core.DefaultProtocolFeature - */ -public enum DseProtocolFeature implements ProtocolFeature { - - /** - * The ability to execute continuous paging requests. - * - * @see CASSANDRA-11521 - * @see com.datastax.dse.driver.api.core.cql.continuous.ContinuousSession - */ - CONTINUOUS_PAGING, - ; -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/DseConversions.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/DseConversions.java deleted file mode 100644 index bf20aa18036..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/DseConversions.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.servererrors.UnfitClientException; -import com.datastax.dse.protocol.internal.DseProtocolConstants; -import com.datastax.dse.protocol.internal.request.query.ContinuousPagingOptions; -import com.datastax.dse.protocol.internal.request.query.DseQueryOptions; -import com.datastax.oss.driver.api.core.ConsistencyLevel; -import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.ProtocolVersion; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.BoundStatement; -import com.datastax.oss.driver.api.core.cql.PreparedStatement; -import com.datastax.oss.driver.api.core.cql.SimpleStatement; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.servererrors.CoordinatorException; -import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry; -import com.datastax.oss.driver.internal.core.ConsistencyLevelRegistry; -import com.datastax.oss.driver.internal.core.DefaultProtocolFeature; -import com.datastax.oss.driver.internal.core.ProtocolVersionRegistry; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.cql.Conversions; -import com.datastax.oss.driver.internal.core.cql.DefaultPreparedStatement; -import com.datastax.oss.protocol.internal.Message; -import com.datastax.oss.protocol.internal.request.Execute; -import com.datastax.oss.protocol.internal.request.Query; -import com.datastax.oss.protocol.internal.response.Error; -import com.datastax.oss.protocol.internal.util.Bytes; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -public class DseConversions { - - public static Message toContinuousPagingMessage( - Statement statement, DriverExecutionProfile config, InternalDriverContext context) { - ConsistencyLevelRegistry consistencyLevelRegistry = context.getConsistencyLevelRegistry(); - ConsistencyLevel consistency = statement.getConsistencyLevel(); - int consistencyCode = - (consistency == null) - ? consistencyLevelRegistry.nameToCode( - config.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - : consistency.getProtocolCode(); - int pageSize = config.getInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE); - boolean pageSizeInBytes = config.getBoolean(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE_BYTES); - int maxPages = config.getInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES); - int maxPagesPerSecond = config.getInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND); - int maxEnqueuedPages = config.getInt(DseDriverOption.CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES); - ContinuousPagingOptions options = - new ContinuousPagingOptions(maxPages, maxPagesPerSecond, maxEnqueuedPages); - ConsistencyLevel serialConsistency = statement.getSerialConsistencyLevel(); - int serialConsistencyCode = - (serialConsistency == null) - ? consistencyLevelRegistry.nameToCode( - config.getString(DefaultDriverOption.REQUEST_SERIAL_CONSISTENCY)) - : serialConsistency.getProtocolCode(); - long timestamp = statement.getQueryTimestamp(); - if (timestamp == Statement.NO_DEFAULT_TIMESTAMP) { - timestamp = context.getTimestampGenerator().next(); - } - CodecRegistry codecRegistry = context.getCodecRegistry(); - ProtocolVersion protocolVersion = context.getProtocolVersion(); - ProtocolVersionRegistry protocolVersionRegistry = context.getProtocolVersionRegistry(); - CqlIdentifier keyspace = statement.getKeyspace(); - if (statement instanceof SimpleStatement) { - SimpleStatement simpleStatement = (SimpleStatement) statement; - List positionalValues = simpleStatement.getPositionalValues(); - Map namedValues = simpleStatement.getNamedValues(); - if (!positionalValues.isEmpty() && !namedValues.isEmpty()) { - throw new IllegalArgumentException( - "Can't have both positional and named values in a statement."); - } - if (keyspace != null - && !protocolVersionRegistry.supports( - protocolVersion, DefaultProtocolFeature.PER_REQUEST_KEYSPACE)) { - throw new IllegalArgumentException( - "Can't use per-request keyspace with protocol " + protocolVersion); - } - DseQueryOptions queryOptions = - new DseQueryOptions( - consistencyCode, - Conversions.encode(positionalValues, codecRegistry, protocolVersion), - Conversions.encode(namedValues, codecRegistry, protocolVersion), - false, - pageSize, - statement.getPagingState(), - serialConsistencyCode, - timestamp, - (keyspace == null) ? null : keyspace.asInternal(), - pageSizeInBytes, - options); - return new Query(simpleStatement.getQuery(), queryOptions); - } else if (statement instanceof BoundStatement) { - BoundStatement boundStatement = (BoundStatement) statement; - if (!protocolVersionRegistry.supports( - protocolVersion, DefaultProtocolFeature.UNSET_BOUND_VALUES)) { - Conversions.ensureAllSet(boundStatement); - } - - boolean skipMetadata; - if (boundStatement.getPreparedStatement() instanceof DefaultPreparedStatement) { - skipMetadata = - ((DefaultPreparedStatement) boundStatement.getPreparedStatement()).isSkipMetadata(); - } else { - skipMetadata = boundStatement.getPreparedStatement().getResultSetDefinitions().size() > 0; - ; - } - DseQueryOptions queryOptions = - new DseQueryOptions( - consistencyCode, - boundStatement.getValues(), - Collections.emptyMap(), - skipMetadata, - pageSize, - statement.getPagingState(), - serialConsistencyCode, - timestamp, - null, - pageSizeInBytes, - options); - PreparedStatement preparedStatement = boundStatement.getPreparedStatement(); - ByteBuffer id = preparedStatement.getId(); - ByteBuffer resultMetadataId = preparedStatement.getResultMetadataId(); - return new Execute( - Bytes.getArray(id), - (resultMetadataId == null) ? null : Bytes.getArray(resultMetadataId), - queryOptions); - } else { - throw new IllegalArgumentException( - "Unsupported statement type: " + statement.getClass().getName()); - } - } - - public static CoordinatorException toThrowable( - Node node, Error errorMessage, InternalDriverContext context) { - switch (errorMessage.code) { - case DseProtocolConstants.ErrorCode.CLIENT_WRITE_FAILURE: - return new UnfitClientException(node, errorMessage.message); - default: - return Conversions.toThrowable(node, errorMessage, context); - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestAsyncProcessor.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestAsyncProcessor.java deleted file mode 100644 index 8a098bf2895..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestAsyncProcessor.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.internal.core.session.RequestProcessor; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import java.util.concurrent.CompletionStage; -import net.jcip.annotations.ThreadSafe; - -@ThreadSafe -public class ContinuousCqlRequestAsyncProcessor - implements RequestProcessor, CompletionStage> { - - public static final GenericType> - CONTINUOUS_RESULT_ASYNC = new GenericType>() {}; - - @Override - public boolean canProcess(Request request, GenericType resultType) { - return request instanceof Statement && resultType.equals(CONTINUOUS_RESULT_ASYNC); - } - - @Override - public CompletionStage process( - Statement request, - DefaultSession session, - InternalDriverContext context, - String sessionLogPrefix) { - return new ContinuousCqlRequestHandler(request, session, context, sessionLogPrefix).handle(); - } - - @Override - public CompletionStage newFailure(RuntimeException error) { - return CompletableFutures.failedFuture(error); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandler.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandler.java deleted file mode 100644 index dd308c11854..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandler.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; -import com.datastax.dse.driver.internal.core.cql.DseConversions; -import com.datastax.dse.protocol.internal.response.result.DseRowsMetadata; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.Row; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; -import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.cql.Conversions; -import com.datastax.oss.driver.internal.core.cql.DefaultRow; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import com.datastax.oss.protocol.internal.Message; -import com.datastax.oss.protocol.internal.response.result.Rows; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import net.jcip.annotations.ThreadSafe; - -/** - * Handles a request that supports multiple response messages (a.k.a. continuous paging request). - */ -@ThreadSafe -public class ContinuousCqlRequestHandler - extends ContinuousRequestHandlerBase, ContinuousAsyncResultSet> { - - ContinuousCqlRequestHandler( - @NonNull Statement statement, - @NonNull DefaultSession session, - @NonNull InternalDriverContext context, - @NonNull String sessionLogPrefix) { - super( - statement, - session, - context, - sessionLogPrefix, - ContinuousAsyncResultSet.class, - false, - DefaultSessionMetric.CQL_CLIENT_TIMEOUTS, - DseSessionMetric.CONTINUOUS_CQL_REQUESTS, - DefaultNodeMetric.CQL_MESSAGES); - // NOTE that ordering of the following statement matters. - // We should register this request after all fields have been initialized. - throttler.register(this); - } - - @NonNull - @Override - protected Duration getGlobalTimeout() { - return Duration.ZERO; - } - - @NonNull - @Override - protected Duration getPageTimeout(@NonNull Statement statement, int pageNumber) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - if (pageNumber == 1) { - return executionProfile.getDuration(DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_FIRST_PAGE); - } else { - return executionProfile.getDuration(DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES); - } - } - - @NonNull - @Override - protected Duration getReviseRequestTimeout(@NonNull Statement statement) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - return executionProfile.getDuration(DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES); - } - - @Override - protected int getMaxEnqueuedPages(@NonNull Statement statement) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - return executionProfile.getInt(DseDriverOption.CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES); - } - - @Override - protected int getMaxPages(@NonNull Statement statement) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - return executionProfile.getInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES); - } - - @NonNull - @Override - protected Message getMessage(@NonNull Statement statement) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - return DseConversions.toContinuousPagingMessage(statement, executionProfile, context); - } - - @Override - protected boolean isTracingEnabled(@NonNull Statement statement) { - return false; - } - - @NonNull - @Override - protected Map createPayload(@NonNull Statement statement) { - return statement.getCustomPayload(); - } - - @NonNull - @Override - protected ContinuousAsyncResultSet createEmptyResultSet(@NonNull ExecutionInfo executionInfo) { - return DefaultContinuousAsyncResultSet.empty(executionInfo); - } - - @NonNull - @Override - protected DefaultContinuousAsyncResultSet createResultSet( - @NonNull Statement statement, - @NonNull Rows rows, - @NonNull ExecutionInfo executionInfo, - @NonNull ColumnDefinitions columnDefinitions) { - Queue> data = rows.getData(); - CountingIterator iterator = - new CountingIterator(data.size()) { - @Override - protected Row computeNext() { - List rowData = data.poll(); - return (rowData == null) - ? endOfData() - : new DefaultRow(columnDefinitions, rowData, context); - } - }; - DseRowsMetadata metadata = (DseRowsMetadata) rows.getMetadata(); - return new DefaultContinuousAsyncResultSet( - iterator, - columnDefinitions, - metadata.continuousPageNumber, - !metadata.isLastContinuousPage, - executionInfo, - this); - } - - @Override - protected int pageNumber(@NonNull ContinuousAsyncResultSet resultSet) { - return resultSet.pageNumber(); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestSyncProcessor.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestSyncProcessor.java deleted file mode 100644 index f151eb7eae2..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestSyncProcessor.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousResultSet; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.internal.core.session.RequestProcessor; -import com.datastax.oss.driver.internal.core.util.concurrent.BlockingOperation; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import net.jcip.annotations.ThreadSafe; - -@ThreadSafe -public class ContinuousCqlRequestSyncProcessor - implements RequestProcessor, ContinuousResultSet> { - - public static final GenericType CONTINUOUS_RESULT_SYNC = - GenericType.of(ContinuousResultSet.class); - - private final ContinuousCqlRequestAsyncProcessor asyncProcessor; - - public ContinuousCqlRequestSyncProcessor(ContinuousCqlRequestAsyncProcessor asyncProcessor) { - this.asyncProcessor = asyncProcessor; - } - - @Override - public boolean canProcess(Request request, GenericType resultType) { - return request instanceof Statement && resultType.equals(CONTINUOUS_RESULT_SYNC); - } - - @Override - public ContinuousResultSet process( - Statement request, - DefaultSession session, - InternalDriverContext context, - String sessionLogPrefix) { - BlockingOperation.checkNotDriverThread(); - ContinuousAsyncResultSet firstPage = - CompletableFutures.getUninterruptibly( - asyncProcessor.process(request, session, context, sessionLogPrefix)); - return new DefaultContinuousResultSet(firstPage); - } - - @Override - public ContinuousResultSet newFailure(RuntimeException error) { - throw error; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousRequestHandlerBase.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousRequestHandlerBase.java deleted file mode 100644 index c17ccd50ff8..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousRequestHandlerBase.java +++ /dev/null @@ -1,1724 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import static com.datastax.oss.driver.api.core.DriverTimeoutException.UNAVAILABLE; - -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.dse.driver.internal.core.DseProtocolFeature; -import com.datastax.dse.driver.internal.core.cql.DseConversions; -import com.datastax.dse.protocol.internal.request.Revise; -import com.datastax.dse.protocol.internal.response.result.DseRowsMetadata; -import com.datastax.oss.driver.api.core.AllNodesFailedException; -import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.DriverTimeoutException; -import com.datastax.oss.driver.api.core.DriverTimeoutException.NodeDiagnostics; -import com.datastax.oss.driver.api.core.NodeUnavailableException; -import com.datastax.oss.driver.api.core.ProtocolVersion; -import com.datastax.oss.driver.api.core.RequestThrottlingException; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.connection.FrameTooLongException; -import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; -import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; -import com.datastax.oss.driver.api.core.metrics.NodeMetric; -import com.datastax.oss.driver.api.core.metrics.SessionMetric; -import com.datastax.oss.driver.api.core.retry.RetryPolicy; -import com.datastax.oss.driver.api.core.retry.RetryVerdict; -import com.datastax.oss.driver.api.core.servererrors.BootstrappingException; -import com.datastax.oss.driver.api.core.servererrors.CoordinatorException; -import com.datastax.oss.driver.api.core.servererrors.FunctionFailureException; -import com.datastax.oss.driver.api.core.servererrors.ProtocolError; -import com.datastax.oss.driver.api.core.servererrors.QueryValidationException; -import com.datastax.oss.driver.api.core.servererrors.ReadTimeoutException; -import com.datastax.oss.driver.api.core.servererrors.UnavailableException; -import com.datastax.oss.driver.api.core.servererrors.WriteTimeoutException; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.api.core.session.throttling.RequestThrottler; -import com.datastax.oss.driver.api.core.session.throttling.Throttled; -import com.datastax.oss.driver.internal.core.adminrequest.ThrottledAdminRequestHandler; -import com.datastax.oss.driver.internal.core.adminrequest.UnexpectedResponseException; -import com.datastax.oss.driver.internal.core.channel.DriverChannel; -import com.datastax.oss.driver.internal.core.channel.ResponseCallback; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.cql.Conversions; -import com.datastax.oss.driver.internal.core.cql.DefaultExecutionInfo; -import com.datastax.oss.driver.internal.core.metadata.DefaultNode; -import com.datastax.oss.driver.internal.core.metrics.NodeMetricUpdater; -import com.datastax.oss.driver.internal.core.metrics.SessionMetricUpdater; -import com.datastax.oss.driver.internal.core.pool.ChannelPool; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.internal.core.session.RepreparePayload; -import com.datastax.oss.driver.internal.core.util.Loggers; -import com.datastax.oss.driver.internal.core.util.collection.SimpleQueryPlan; -import com.datastax.oss.driver.shaded.guava.common.annotations.VisibleForTesting; -import com.datastax.oss.protocol.internal.Frame; -import com.datastax.oss.protocol.internal.Message; -import com.datastax.oss.protocol.internal.ProtocolConstants; -import com.datastax.oss.protocol.internal.request.Prepare; -import com.datastax.oss.protocol.internal.response.Error; -import com.datastax.oss.protocol.internal.response.Result; -import com.datastax.oss.protocol.internal.response.error.Unprepared; -import com.datastax.oss.protocol.internal.response.result.Rows; -import com.datastax.oss.protocol.internal.response.result.Void; -import com.datastax.oss.protocol.internal.util.Bytes; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import io.netty.handler.codec.EncoderException; -import io.netty.util.Timeout; -import io.netty.util.Timer; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.AbstractMap; -import java.util.ArrayDeque; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.ReentrantLock; -import net.jcip.annotations.GuardedBy; -import net.jcip.annotations.ThreadSafe; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles a request that supports multiple response messages (a.k.a. continuous paging request). - */ -@ThreadSafe -public abstract class ContinuousRequestHandlerBase - implements Throttled { - - private static final Logger LOG = LoggerFactory.getLogger(ContinuousRequestHandlerBase.class); - - protected final String logPrefix; - protected final StatementT initialStatement; - protected final DefaultSession session; - private final CqlIdentifier keyspace; - protected final InternalDriverContext context; - private final Queue queryPlan; - protected final RequestThrottler throttler; - private final boolean protocolBackpressureAvailable; - private final Timer timer; - private final SessionMetricUpdater sessionMetricUpdater; - private final boolean specExecEnabled; - private final SessionMetric clientTimeoutsMetric; - private final SessionMetric continuousRequestsMetric; - private final NodeMetric messagesMetric; - private final List scheduledExecutions; - - // The errors on the nodes that were already tried. - // We don't use a map because nodes can appear multiple times. - protected final List> errors = new CopyOnWriteArrayList<>(); - - /** - * The list of in-flight executions, one per node. Executions may be triggered by speculative - * executions or retries. An execution is added to this list when the write operation completes. - * It is removed from this list when the callback has done reading responses. - */ - private final List inFlightCallbacks = new CopyOnWriteArrayList<>(); - - /** The callback selected to stream results back to the client. */ - private final CompletableFuture chosenCallback = new CompletableFuture<>(); - - /** - * How many speculative executions are currently running (including the initial execution). We - * track this in order to know when to fail the request if all executions have reached the end of - * the query plan. - */ - private final AtomicInteger activeExecutionsCount = new AtomicInteger(0); - - /** - * How many speculative executions have started (excluding the initial execution), whether they - * have completed or not. We track this in order to fill execution info objects with this - * information. - */ - protected final AtomicInteger startedSpeculativeExecutionsCount = new AtomicInteger(0); - - // Set when the execution starts, and is never modified after. - private final long startTimeNanos; - private volatile Timeout globalTimeout; - - private final Class resultSetClass; - - public ContinuousRequestHandlerBase( - @NonNull StatementT statement, - @NonNull DefaultSession session, - @NonNull InternalDriverContext context, - @NonNull String sessionLogPrefix, - @NonNull Class resultSetClass, - boolean specExecEnabled, - SessionMetric clientTimeoutsMetric, - SessionMetric continuousRequestsMetric, - NodeMetric messagesMetric) { - this.resultSetClass = resultSetClass; - - ProtocolVersion protocolVersion = context.getProtocolVersion(); - if (!context - .getProtocolVersionRegistry() - .supports(protocolVersion, DseProtocolFeature.CONTINUOUS_PAGING)) { - throw new IllegalStateException( - "Cannot execute continuous paging requests with protocol version " + protocolVersion); - } - this.clientTimeoutsMetric = clientTimeoutsMetric; - this.continuousRequestsMetric = continuousRequestsMetric; - this.messagesMetric = messagesMetric; - this.logPrefix = sessionLogPrefix + "|" + this.hashCode(); - LOG.trace("[{}] Creating new continuous handler for request {}", logPrefix, statement); - this.initialStatement = statement; - this.session = session; - this.keyspace = session.getKeyspace().orElse(null); - this.context = context; - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(statement, context); - this.queryPlan = - statement.getNode() != null - ? new SimpleQueryPlan(statement.getNode()) - : context - .getLoadBalancingPolicyWrapper() - .newQueryPlan(statement, executionProfile.getName(), session); - this.timer = context.getNettyOptions().getTimer(); - - this.protocolBackpressureAvailable = - protocolVersion.getCode() >= DseProtocolVersion.DSE_V2.getCode(); - this.throttler = context.getRequestThrottler(); - this.sessionMetricUpdater = session.getMetricUpdater(); - this.startTimeNanos = System.nanoTime(); - this.specExecEnabled = specExecEnabled; - this.scheduledExecutions = this.specExecEnabled ? new CopyOnWriteArrayList<>() : null; - } - - @NonNull - protected abstract Duration getGlobalTimeout(); - - @NonNull - protected abstract Duration getPageTimeout(@NonNull StatementT statement, int pageNumber); - - @NonNull - protected abstract Duration getReviseRequestTimeout(@NonNull StatementT statement); - - protected abstract int getMaxEnqueuedPages(@NonNull StatementT statement); - - protected abstract int getMaxPages(@NonNull StatementT statement); - - @NonNull - protected abstract Message getMessage(@NonNull StatementT statement); - - protected abstract boolean isTracingEnabled(@NonNull StatementT statement); - - @NonNull - protected abstract Map createPayload(@NonNull StatementT statement); - - @NonNull - protected abstract ResultSetT createEmptyResultSet(@NonNull ExecutionInfo executionInfo); - - protected abstract int pageNumber(@NonNull ResultSetT resultSet); - - @NonNull - protected abstract ResultSetT createResultSet( - @NonNull StatementT statement, - @NonNull Rows rows, - @NonNull ExecutionInfo executionInfo, - @NonNull ColumnDefinitions columnDefinitions) - throws IOException; - - // MAIN LIFECYCLE - - @Override - public void onThrottleReady(boolean wasDelayed) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(initialStatement, context); - if (wasDelayed - // avoid call to nanoTime() if metric is disabled: - && sessionMetricUpdater.isEnabled( - DefaultSessionMetric.THROTTLING_DELAY, executionProfile.getName())) { - session - .getMetricUpdater() - .updateTimer( - DefaultSessionMetric.THROTTLING_DELAY, - executionProfile.getName(), - System.nanoTime() - startTimeNanos, - TimeUnit.NANOSECONDS); - } - activeExecutionsCount.incrementAndGet(); - sendRequest(initialStatement, null, 0, 0, specExecEnabled); - } - - @Override - public void onThrottleFailure(@NonNull RequestThrottlingException error) { - DriverExecutionProfile executionProfile = - Conversions.resolveExecutionProfile(initialStatement, context); - session - .getMetricUpdater() - .incrementCounter(DefaultSessionMetric.THROTTLING_ERRORS, executionProfile.getName()); - abortGlobalRequestOrChosenCallback(error); - } - - private boolean abortGlobalRequestOrChosenCallback(@NonNull Throwable error) { - boolean completedChosenCallback = chosenCallback.completeExceptionally(error); - if (!completedChosenCallback) { - chosenCallback.thenAccept(callback -> callback.abort(error, false)); - } - return completedChosenCallback; - } - - public CompletionStage handle() { - globalTimeout = scheduleGlobalTimeout(); - return fetchNextPage(); - } - - /** - * Builds the future that will get returned to the user from the initial execute call or a - * fetchNextPage() on the async API. - */ - public CompletionStage fetchNextPage() { - CompletableFuture result = new CompletableFuture<>(); - - // This is equivalent to - // `chosenCallback.thenCompose(NodeResponseCallback::dequeueOrCreatePending)`, except - // that we need to cancel `result` if `resultSetError` is a CancellationException. - chosenCallback.whenComplete( - (callback, callbackError) -> { - if (callbackError != null) { - result.completeExceptionally(callbackError); - } else { - callback - .dequeueOrCreatePending() - .whenComplete( - (resultSet, resultSetError) -> { - if (resultSetError != null) { - result.completeExceptionally(resultSetError); - } else { - result.complete(resultSet); - } - }); - } - }); - - // If the user cancels the future, propagate to our internal components - result.whenComplete( - (rs, t) -> { - if (t instanceof CancellationException) { - cancel(); - } - }); - - return result; - } - - /** - * Sends the initial request to the next available node. - * - * @param node if not null, it will be attempted first before the rest of the query plan. It - * happens only when we retry on the same host. - * @param currentExecutionIndex 0 for the initial execution, 1 for the first speculative one, etc. - * @param retryCount the number of times that the retry policy was invoked for this execution - * already (note that some internal retries don't go through the policy, and therefore don't - * increment this counter) - * @param scheduleSpeculativeExecution whether to schedule the next speculative execution - */ - private void sendRequest( - StatementT statement, - @Nullable Node node, - int currentExecutionIndex, - int retryCount, - boolean scheduleSpeculativeExecution) { - DriverChannel channel = null; - if (node == null || (channel = session.getChannel(node, logPrefix)) == null) { - while ((node = queryPlan.poll()) != null) { - channel = session.getChannel(node, logPrefix); - if (channel != null) { - break; - } else { - recordError(node, new NodeUnavailableException(node)); - } - } - } - if (channel == null) { - // We've reached the end of the query plan without finding any node to write to; abort the - // continuous paging session. - if (activeExecutionsCount.decrementAndGet() == 0) { - abortGlobalRequestOrChosenCallback(AllNodesFailedException.fromErrors(errors)); - } - } else if (!chosenCallback.isDone()) { - boolean writeSubmitted = false; - Throwable terminalPreWriteFailure = null; - NodeResponseCallback nodeResponseCallback = null; - try { - nodeResponseCallback = - new NodeResponseCallback( - statement, - node, - channel, - currentExecutionIndex, - retryCount, - scheduleSpeculativeExecution, - logPrefix); - inFlightCallbacks.add(nodeResponseCallback); - Future writeFuture = - channel.write( - getMessage(statement), - isTracingEnabled(statement), - createPayload(statement), - nodeResponseCallback); - writeSubmitted = true; - writeFuture.addListener(nodeResponseCallback); - } catch (Throwable t) { - if (!writeSubmitted && activeExecutionsCount.decrementAndGet() == 0) { - if (abortGlobalRequestOrChosenCallback(t)) { - terminalPreWriteFailure = t; - } - } - throw t; - } finally { - if (!writeSubmitted) { - if (nodeResponseCallback != null) { - inFlightCallbacks.remove(nodeResponseCallback); - } - try { - channel.cancelPreAcquireId(); - } finally { - if (terminalPreWriteFailure != null) { - throttler.signalError(this, terminalPreWriteFailure); - } - } - } - } - } else { - channel.cancelPreAcquireId(); - } - } - - private Timeout scheduleGlobalTimeout() { - Duration globalTimeout = getGlobalTimeout(); - if (globalTimeout.toNanos() <= 0) { - return null; - } - LOG.trace("[{}] Scheduling global timeout for pages in {}", logPrefix, globalTimeout); - return timer.newTimeout( - timeout -> { - NodeDiagnostics diagnostics = buildNodeDiagnostics(); - abortGlobalRequestOrChosenCallback( - new DriverTimeoutException("Query timed out after " + globalTimeout, diagnostics)); - }, - globalTimeout.toNanos(), - TimeUnit.NANOSECONDS); - } - - @Nullable - private NodeDiagnostics buildNodeDiagnostics() { - List callbacks = inFlightCallbacks; - if (callbacks.isEmpty()) { - return null; - } - NodeResponseCallback cb = callbacks.get(0); - int channelInFlight = cb.channel.getInFlight(); - ChannelPool pool = session.getPools().get(cb.node); - return NodeDiagnostics.of( - cb.node.getEndPoint(), - cb.node.getState(), - cb.node.getDistance(), - cb.node.getDatacenter(), - channelInFlight, - pool != null ? pool.size() : UNAVAILABLE, - pool != null ? pool.getInFlight() : UNAVAILABLE, - pool != null ? pool.getAvailableIds() : UNAVAILABLE, - pool != null ? pool.getOrphanedIds() : UNAVAILABLE); - } - - /** - * Cancels the continuous paging request. - * - *

Called from user code, see {@link DefaultContinuousAsyncResultSet#cancel()}, or from a - * driver I/O thread. - */ - public void cancel() { - // If chosenCallback is already set, this is a no-op and the chosen callback will be handled by - // cancelScheduledTasks - chosenCallback.cancel(true); - - cancelScheduledTasks(null); - cancelGlobalTimeout(); - throttler.signalCancel(this); - } - - private void cancelGlobalTimeout() { - if (globalTimeout != null) { - globalTimeout.cancel(); - } - } - - /** - * Cancel all pending and scheduled executions, except the one passed as an argument to the - * method. - * - * @param toIgnore An optional execution to ignore (will not be cancelled). - */ - private void cancelScheduledTasks(@Nullable NodeResponseCallback toIgnore) { - if (scheduledExecutions != null) { - for (Timeout scheduledExecution : scheduledExecutions) { - scheduledExecution.cancel(); - } - } - for (NodeResponseCallback callback : inFlightCallbacks) { - if (toIgnore == null || toIgnore != callback) { - callback.cancel(); - } - } - } - - @VisibleForTesting - int getState() { - try { - return chosenCallback.get().getState(); - } catch (CancellationException e) { - // Happens if the test cancels before the callback was chosen - return NodeResponseCallback.STATE_FAILED; - } catch (InterruptedException | ExecutionException e) { - // We never interrupt or fail chosenCallback (other than canceling) - throw new AssertionError("Unexpected error", e); - } - } - - @VisibleForTesting - CompletableFuture getPendingResult() { - try { - return chosenCallback.get().getPendingResult(); - } catch (Exception e) { - // chosenCallback should always be complete by the time tests call this - throw new AssertionError("Expected callback to be chosen at this point"); - } - } - - @VisibleForTesting - int getActiveExecutionsCount() { - return activeExecutionsCount.get(); - } - - @VisibleForTesting - int getInFlightCallbackCount() { - return inFlightCallbacks.size(); - } - - private void recordError(@NonNull Node node, @NonNull Throwable error) { - errors.add(new AbstractMap.SimpleEntry<>(node, error)); - } - - /** - * Handles the interaction with a single node in the query plan. - * - *

An instance of this class is created each time we (re)try a node. The first callback that - * has something ready to enqueue will be allowed to stream results back to the client; the others - * will be cancelled. - */ - private class NodeResponseCallback - implements ResponseCallback, GenericFutureListener> { - - private final long messageStartTimeNanos = System.nanoTime(); - private final StatementT statement; - private final Node node; - private final DriverChannel channel; - // The identifier of the current execution (0 for the initial execution, 1 for the first - // speculative execution, etc.) - private final int executionIndex; - // How many times we've invoked the retry policy and it has returned a "retry" decision (0 for - // the first attempt of each execution). - private final String logPrefix; - private final boolean scheduleSpeculativeExecution; - - private final DriverExecutionProfile executionProfile; - - // Coordinates concurrent accesses between the client and I/O threads - private final ReentrantLock lock = new ReentrantLock(); - - // The page queue, storing responses that we have received and have not been consumed by the - // client yet. We instantiate it lazily to avoid unnecessary allocation; this is also used to - // check if the callback ever tried to enqueue something. - @GuardedBy("lock") - private Queue queue; - - // If the client requests a page and we can't serve it immediately (empty queue), then we create - // this future and have the client wait on it. Otherwise this field is null. - @GuardedBy("lock") - private CompletableFuture pendingResult; - - // How many pages were requested. This is the total number of pages requested from the - // beginning. - // It will be zero if the protocol does not support numPagesRequested (DSE_V1) - @GuardedBy("lock") - private int numPagesRequested; - - // An integer that represents the state of the continuous paging request: - // - if positive, it is the sequence number of the next expected page; - // - if negative, it is a terminal state, identified by the constants below. - @GuardedBy("lock") - private int state = 1; - - // Whether isLastResponse has returned true already - @GuardedBy("lock") - private boolean sawLastResponse; - - @GuardedBy("lock") - private boolean sentCancelRequest; - - private static final int STATE_FINISHED = -1; - private static final int STATE_FAILED = -2; - - @GuardedBy("lock") - private int streamId = -1; - - // These are set when the first page arrives, and are never modified after. - private volatile ColumnDefinitions columnDefinitions; - - private volatile Timeout pageTimeout; - - // How many times we've invoked the retry policy and it has returned a "retry" decision (0 for - // the first attempt, 1 for the first retry, etc.). - private final int retryCount; - - // SpeculativeExecution node metrics should be executed only for the first page (first - // invocation) - private final AtomicBoolean stopNodeMessageTimerReported = new AtomicBoolean(false); - private final AtomicBoolean nodeErrorReported = new AtomicBoolean(false); - private final AtomicBoolean nodeSuccessReported = new AtomicBoolean(false); - - public NodeResponseCallback( - StatementT statement, - Node node, - DriverChannel channel, - int executionIndex, - int retryCount, - boolean scheduleSpeculativeExecution, - String logPrefix) { - this.statement = statement; - this.node = node; - this.channel = channel; - this.executionIndex = executionIndex; - this.retryCount = retryCount; - this.scheduleSpeculativeExecution = scheduleSpeculativeExecution; - this.logPrefix = logPrefix + "|" + executionIndex; - this.executionProfile = Conversions.resolveExecutionProfile(statement, context); - } - - @Override - public void onStreamIdAssigned(int streamId) { - LOG.trace("[{}] Assigned streamId {} on node {}", logPrefix, streamId, node); - lock.lock(); - try { - this.streamId = streamId; - if (state < 0) { - // This happens if we were cancelled before getting the stream id, we have a request in - // flight that needs to be cancelled - releaseStreamId(); - } - } finally { - lock.unlock(); - } - } - - @Override - public boolean isLastResponse(@NonNull Frame responseFrame) { - lock.lock(); - try { - Message message = responseFrame.message; - boolean isLastResponse; - - if (sentCancelRequest) { - // The only response we accept is the SERVER_ERROR triggered by a successful cancellation. - // Otherwise we risk releasing and reusing the stream id while the cancel request is still - // in flight, and it might end up cancelling an unrelated request. - // Note that there is a chance that the request ends normally right after we send the - // cancel request. In that case this method never returns true and the stream id will - // remain orphaned forever. This should be very rare so this is acceptable. - if (message instanceof Error) { - Error error = (Error) message; - isLastResponse = - (error.code == ProtocolConstants.ErrorCode.SERVER_ERROR) - && error.message.contains("Session cancelled by the user"); - } else { - isLastResponse = false; - } - } else if (message instanceof Rows) { - Rows rows = (Rows) message; - DseRowsMetadata metadata = (DseRowsMetadata) rows.getMetadata(); - isLastResponse = metadata.isLastContinuousPage; - } else { - isLastResponse = message instanceof Error; - } - - if (isLastResponse) { - sawLastResponse = true; - } - return isLastResponse; - } finally { - lock.unlock(); - } - } - - /** - * Invoked when the write from {@link #sendRequest} completes. - * - * @param future The future representing the outcome of the write operation. - */ - @Override - public void operationComplete(@NonNull Future future) { - if (!future.isSuccess()) { - Throwable error = future.cause(); - if (error instanceof EncoderException - && error.getCause() instanceof FrameTooLongException) { - trackNodeError(node, error.getCause()); - lock.lock(); - try { - abort(error.getCause(), false); - } finally { - lock.unlock(); - } - } else { - LOG.trace( - "[{}] Failed to send request on {}, trying next node (cause: {})", - logPrefix, - channel, - error); - ((DefaultNode) node) - .getMetricUpdater() - .incrementCounter(DefaultNodeMetric.UNSENT_REQUESTS, executionProfile.getName()); - recordError(node, error); - trackNodeError(node, error.getCause()); - sendRequest(statement, null, executionIndex, retryCount, scheduleSpeculativeExecution); - } - } else { - LOG.trace("[{}] Request sent on {}", logPrefix, channel); - if (scheduleSpeculativeExecution - && Conversions.resolveIdempotence(statement, executionProfile)) { - int nextExecution = executionIndex + 1; - // Note that `node` is the first node of the execution, it might not be the "slow" one - // if there were retries, but in practice retries are rare. - long nextDelay = - Conversions.resolveSpeculativeExecutionPolicy(context, executionProfile) - .nextExecution(node, keyspace, statement, nextExecution); - if (nextDelay >= 0) { - scheduleSpeculativeExecution(nextExecution, nextDelay); - } else { - LOG.trace( - "[{}] Speculative execution policy returned {}, no next execution", - logPrefix, - nextDelay); - } - } - pageTimeout = schedulePageTimeout(1); - } - } - - private void scheduleSpeculativeExecution(int nextExecutionIndex, long delay) { - LOG.trace( - "[{}] Scheduling speculative execution {} in {} ms", - logPrefix, - nextExecutionIndex, - delay); - try { - scheduledExecutions.add( - timer.newTimeout( - (Timeout timeout) -> { - if (!chosenCallback.isDone()) { - LOG.trace( - "[{}] Starting speculative execution {}", logPrefix, nextExecutionIndex); - activeExecutionsCount.incrementAndGet(); - startedSpeculativeExecutionsCount.incrementAndGet(); - NodeMetricUpdater nodeMetricUpdater = ((DefaultNode) node).getMetricUpdater(); - if (nodeMetricUpdater.isEnabled( - DefaultNodeMetric.SPECULATIVE_EXECUTIONS, executionProfile.getName())) { - nodeMetricUpdater.incrementCounter( - DefaultNodeMetric.SPECULATIVE_EXECUTIONS, executionProfile.getName()); - } - sendRequest(statement, null, nextExecutionIndex, 0, true); - } - }, - delay, - TimeUnit.MILLISECONDS)); - } catch (IllegalStateException e) { - logTimeoutSchedulingError(e); - } - } - - private Timeout schedulePageTimeout(int expectedPage) { - if (expectedPage < 0) { - return null; - } - Duration timeout = getPageTimeout(statement, expectedPage); - if (timeout.toNanos() <= 0) { - return null; - } - LOG.trace("[{}] Scheduling timeout for page {} in {}", logPrefix, expectedPage, timeout); - return timer.newTimeout( - t -> onPageTimeout(expectedPage), timeout.toNanos(), TimeUnit.NANOSECONDS); - } - - private void onPageTimeout(int expectedPage) { - lock.lock(); - try { - if (state == expectedPage) { - int channelInFlight = channel.getInFlight(); - ChannelPool pool = session.getPools().get(node); - abort( - new DriverTimeoutException( - "Timed out waiting for page " + expectedPage, - NodeDiagnostics.of( - node.getEndPoint(), - node.getState(), - node.getDistance(), - node.getDatacenter(), - channelInFlight, - pool != null ? pool.size() : UNAVAILABLE, - pool != null ? pool.getInFlight() : UNAVAILABLE, - pool != null ? pool.getAvailableIds() : UNAVAILABLE, - pool != null ? pool.getOrphanedIds() : UNAVAILABLE)), - false); - } else { - // Ignore timeout if the request has moved on in the interim. - LOG.trace( - "[{}] Timeout fired for page {} but query already at state {}, skipping", - logPrefix, - expectedPage, - state); - } - } finally { - lock.unlock(); - } - } - - /** - * Invoked when a continuous paging response is received, either a successful or failed one. - * - *

Delegates further processing to appropriate methods: {@link #processResultResponse(Result, - * Frame)} if the response was successful, or {@link #processErrorResponse(Error)} if it wasn't. - * - * @param response the received {@link Frame}. - */ - @Override - public void onResponse(@NonNull Frame response) { - stopNodeMessageTimer(); - cancelTimeout(pageTimeout); - lock.lock(); - try { - if (state < 0) { - LOG.trace("[{}] Got result but the request has been cancelled, ignoring", logPrefix); - return; - } - try { - Message responseMessage = response.message; - if (responseMessage instanceof Result) { - LOG.trace("[{}] Got result", logPrefix); - processResultResponse((Result) responseMessage, response); - } else if (responseMessage instanceof Error) { - LOG.trace("[{}] Got error response", logPrefix); - processErrorResponse((Error) responseMessage); - } else { - IllegalStateException error = - new IllegalStateException("Unexpected response " + responseMessage); - trackNodeError(node, error); - abort(error, false); - } - } catch (Throwable t) { - trackNodeError(node, t); - abort(t, false); - } - } finally { - lock.unlock(); - } - } - - /** - * Invoked when a continuous paging request hits an unexpected error. - * - *

Delegates further processing to to the retry policy ({@link - * #processRetryVerdict(RetryVerdict, Throwable)}. - * - * @param error the error encountered, usually a network problem. - */ - @Override - public void onFailure(@NonNull Throwable error) { - cancelTimeout(pageTimeout); - LOG.trace(String.format("[%s] Request failure", logPrefix), error); - RetryVerdict verdict; - if (!Conversions.resolveIdempotence(statement, executionProfile) - || error instanceof FrameTooLongException) { - verdict = RetryVerdict.RETHROW; - } else { - try { - RetryPolicy retryPolicy = Conversions.resolveRetryPolicy(context, executionProfile); - verdict = retryPolicy.onRequestAbortedVerdict(statement, error, retryCount); - } catch (Throwable cause) { - abort( - new IllegalStateException("Unexpected error while invoking the retry policy", cause), - false); - return; - } - } - updateErrorMetrics( - ((DefaultNode) node).getMetricUpdater(), - verdict, - DefaultNodeMetric.ABORTED_REQUESTS, - DefaultNodeMetric.RETRIES_ON_ABORTED, - DefaultNodeMetric.IGNORES_ON_ABORTED); - lock.lock(); - try { - processRetryVerdict(verdict, error); - } finally { - lock.unlock(); - } - } - - // PROCESSING METHODS - - /** - * Processes a new result response, creating the corresponding {@link ResultSetT} object and - * then enqueuing it or serving it directly to the user if he was waiting for it. - * - * @param result the result to process. It is normally a {@link Rows} object, but may be a - * {@link Void} object if the retry policy decided to ignore an error. - * @param frame the {@link Frame} (used to create the {@link ExecutionInfo} the first time). - */ - @SuppressWarnings("GuardedBy") // this method is only called with the lock held - private void processResultResponse(@NonNull Result result, @Nullable Frame frame) { - assert lock.isHeldByCurrentThread(); - try { - ExecutionInfo executionInfo = createExecutionInfo(result, frame); - if (result instanceof Rows) { - DseRowsMetadata rowsMetadata = (DseRowsMetadata) ((Rows) result).getMetadata(); - if (columnDefinitions == null) { - // Contrary to ROWS responses from regular queries, - // the first page always includes metadata so we use this - // regardless of whether or not the query was from a prepared statement. - columnDefinitions = Conversions.toColumnDefinitions(rowsMetadata, context); - } - int pageNumber = rowsMetadata.continuousPageNumber; - int currentPage = state; - if (pageNumber != currentPage) { - abort( - new IllegalStateException( - String.format( - "Received page %d but was expecting %d", pageNumber, currentPage)), - false); - } else { - int pageSize = ((Rows) result).getData().size(); - ResultSetT resultSet = - createResultSet(statement, (Rows) result, executionInfo, columnDefinitions); - if (rowsMetadata.isLastContinuousPage) { - LOG.trace("[{}] Received last page ({} - {} rows)", logPrefix, pageNumber, pageSize); - state = STATE_FINISHED; - reenableAutoReadIfNeeded(); - enqueueOrCompletePending(resultSet); - stopGlobalRequestTimer(); - cancelTimeout(globalTimeout); - } else { - LOG.trace("[{}] Received page {} ({} rows)", logPrefix, pageNumber, pageSize); - if (currentPage > 0) { - state = currentPage + 1; - } - enqueueOrCompletePending(resultSet); - } - } - } else { - // Void responses happen only when the retry decision is ignore. - assert result instanceof Void; - ResultSetT resultSet = createEmptyResultSet(executionInfo); - LOG.trace( - "[{}] Continuous paging interrupted by retry policy decision to ignore error", - logPrefix); - state = STATE_FINISHED; - reenableAutoReadIfNeeded(); - enqueueOrCompletePending(resultSet); - stopGlobalRequestTimer(); - cancelTimeout(globalTimeout); - } - } catch (Throwable error) { - abort(error, false); - } - } - - /** - * Processes an unsuccessful response. - * - *

Depending on the error, may trigger: - * - *

    - *
  1. a re-prepare cycle, see {@link #processUnprepared(Unprepared)}; - *
  2. an immediate retry on the next host, bypassing the retry policy, if the host was - * bootstrapping; - *
  3. an immediate abortion if the error is unrecoverable; - *
  4. further processing if the error is recoverable, see {@link - * #processRecoverableError(CoordinatorException)} - *
- * - * @param errorMessage the error message received. - */ - @SuppressWarnings("GuardedBy") // this method is only called with the lock held - private void processErrorResponse(@NonNull Error errorMessage) { - assert lock.isHeldByCurrentThread(); - if (errorMessage instanceof Unprepared) { - processUnprepared((Unprepared) errorMessage); - } else { - CoordinatorException error = DseConversions.toThrowable(node, errorMessage, context); - if (error instanceof BootstrappingException) { - LOG.trace("[{}] {} is bootstrapping, trying next node", logPrefix, node); - recordError(node, error); - trackNodeError(node, error); - sendRequest(statement, null, executionIndex, retryCount, false); - } else if (error instanceof QueryValidationException - || error instanceof FunctionFailureException - || error instanceof ProtocolError - || state > 1) { - // we only process recoverable errors for the first page, - // errors on subsequent pages will always trigger an immediate abortion - LOG.trace("[{}] Unrecoverable error, rethrowing", logPrefix); - NodeMetricUpdater metricUpdater = ((DefaultNode) node).getMetricUpdater(); - metricUpdater.incrementCounter( - DefaultNodeMetric.OTHER_ERRORS, executionProfile.getName()); - trackNodeError(node, error); - abort(error, true); - } else { - try { - processRecoverableError(error); - } catch (Throwable cause) { - abort(cause, false); - } - } - } - } - - /** - * Processes a recoverable error. - * - *

In most cases, delegates to the retry policy and its decision, see {@link - * #processRetryVerdict(RetryVerdict, Throwable)}. - * - * @param error the recoverable error. - */ - private void processRecoverableError(@NonNull CoordinatorException error) { - assert lock.isHeldByCurrentThread(); - NodeMetricUpdater metricUpdater = ((DefaultNode) node).getMetricUpdater(); - RetryVerdict verdict; - RetryPolicy retryPolicy = Conversions.resolveRetryPolicy(context, executionProfile); - if (error instanceof ReadTimeoutException) { - ReadTimeoutException readTimeout = (ReadTimeoutException) error; - verdict = - retryPolicy.onReadTimeoutVerdict( - statement, - readTimeout.getConsistencyLevel(), - readTimeout.getBlockFor(), - readTimeout.getReceived(), - readTimeout.wasDataPresent(), - retryCount); - updateErrorMetrics( - metricUpdater, - verdict, - DefaultNodeMetric.READ_TIMEOUTS, - DefaultNodeMetric.RETRIES_ON_READ_TIMEOUT, - DefaultNodeMetric.IGNORES_ON_READ_TIMEOUT); - } else if (error instanceof WriteTimeoutException) { - WriteTimeoutException writeTimeout = (WriteTimeoutException) error; - if (Conversions.resolveIdempotence(statement, executionProfile)) { - verdict = - retryPolicy.onWriteTimeoutVerdict( - statement, - writeTimeout.getConsistencyLevel(), - writeTimeout.getWriteType(), - writeTimeout.getBlockFor(), - writeTimeout.getReceived(), - retryCount); - } else { - verdict = RetryVerdict.RETHROW; - } - updateErrorMetrics( - metricUpdater, - verdict, - DefaultNodeMetric.WRITE_TIMEOUTS, - DefaultNodeMetric.RETRIES_ON_WRITE_TIMEOUT, - DefaultNodeMetric.IGNORES_ON_WRITE_TIMEOUT); - } else if (error instanceof UnavailableException) { - UnavailableException unavailable = (UnavailableException) error; - verdict = - retryPolicy.onUnavailableVerdict( - statement, - unavailable.getConsistencyLevel(), - unavailable.getRequired(), - unavailable.getAlive(), - retryCount); - updateErrorMetrics( - metricUpdater, - verdict, - DefaultNodeMetric.UNAVAILABLES, - DefaultNodeMetric.RETRIES_ON_UNAVAILABLE, - DefaultNodeMetric.IGNORES_ON_UNAVAILABLE); - } else { - verdict = - Conversions.resolveIdempotence(statement, executionProfile) - ? retryPolicy.onErrorResponseVerdict(statement, error, retryCount) - : RetryVerdict.RETHROW; - updateErrorMetrics( - metricUpdater, - verdict, - DefaultNodeMetric.OTHER_ERRORS, - DefaultNodeMetric.RETRIES_ON_OTHER_ERROR, - DefaultNodeMetric.IGNORES_ON_OTHER_ERROR); - } - processRetryVerdict(verdict, error); - } - - /** - * Processes an {@link Unprepared} error by re-preparing then retrying on the same host. - * - * @param errorMessage the unprepared error message. - */ - @SuppressWarnings("GuardedBy") // this method is only called with the lock held - private void processUnprepared(@NonNull Unprepared errorMessage) { - assert lock.isHeldByCurrentThread(); - ByteBuffer idToReprepare = ByteBuffer.wrap(errorMessage.id); - LOG.trace( - "[{}] Statement {} is not prepared on {}, re-preparing", - logPrefix, - Bytes.toHexString(idToReprepare), - node); - RepreparePayload repreparePayload = session.getRepreparePayloads().get(idToReprepare); - if (repreparePayload == null) { - throw new IllegalStateException( - String.format( - "Tried to execute unprepared query %s but we don't have the data to re-prepare it", - Bytes.toHexString(idToReprepare))); - } - Prepare prepare = repreparePayload.toMessage(); - Duration timeout = executionProfile.getDuration(DefaultDriverOption.REQUEST_TIMEOUT); - ThrottledAdminRequestHandler.prepare( - channel, - true, - prepare, - repreparePayload.customPayload, - timeout, - throttler, - sessionMetricUpdater, - logPrefix) - .start() - .whenComplete( - (repreparedId, exception) -> { - // If we run into an unrecoverable error, surface it to the client instead of - // retrying - Throwable fatalError = null; - if (exception == null) { - if (!repreparedId.equals(idToReprepare)) { - IllegalStateException illegalStateException = - new IllegalStateException( - String.format( - "ID mismatch while trying to reprepare (expected %s, got %s). " - + "This prepared statement won't work anymore. " - + "This usually happens when you run a 'USE...' query after " - + "the statement was prepared.", - Bytes.toHexString(idToReprepare), Bytes.toHexString(repreparedId))); - trackNodeError(node, illegalStateException); - fatalError = illegalStateException; - } else { - LOG.trace( - "[{}] Re-prepare successful, retrying on the same node ({})", - logPrefix, - node); - sendRequest(statement, node, executionIndex, retryCount, false); - } - } else { - if (exception instanceof UnexpectedResponseException) { - Message prepareErrorMessage = ((UnexpectedResponseException) exception).message; - if (prepareErrorMessage instanceof Error) { - CoordinatorException prepareError = - DseConversions.toThrowable(node, (Error) prepareErrorMessage, context); - if (prepareError instanceof QueryValidationException - || prepareError instanceof FunctionFailureException - || prepareError instanceof ProtocolError) { - LOG.trace("[{}] Unrecoverable error on re-prepare, rethrowing", logPrefix); - trackNodeError(node, prepareError); - fatalError = prepareError; - } - } - } else if (exception instanceof RequestThrottlingException) { - trackNodeError(node, exception); - fatalError = exception; - } - if (fatalError == null) { - LOG.trace("[{}] Re-prepare failed, trying next node", logPrefix); - recordError(node, exception); - trackNodeError(node, exception); - sendRequest(statement, null, executionIndex, retryCount, false); - } - } - if (fatalError != null) { - lock.lock(); - try { - abort(fatalError, true); - } finally { - lock.unlock(); - } - } - }); - } - - /** - * Processes the retry decision by triggering a retry, aborting or ignoring; also records the - * failures for further access. - * - * @param verdict the verdict to process. - * @param error the original error. - */ - private void processRetryVerdict(@NonNull RetryVerdict verdict, @NonNull Throwable error) { - assert lock.isHeldByCurrentThread(); - LOG.trace("[{}] Processing retry decision {}", logPrefix, verdict); - switch (verdict.getRetryDecision()) { - case RETRY_SAME: - recordError(node, error); - trackNodeError(node, error); - sendRequest( - verdict.getRetryRequest(statement), node, executionIndex, retryCount + 1, false); - break; - case RETRY_NEXT: - recordError(node, error); - trackNodeError(node, error); - sendRequest( - verdict.getRetryRequest(statement), null, executionIndex, retryCount + 1, false); - break; - case RETHROW: - trackNodeError(node, error); - abort(error, true); - break; - case IGNORE: - processResultResponse(Void.INSTANCE, null); - break; - } - } - - // PAGE HANDLING - - /** - * Enqueues a response or, if the client was already waiting for it, completes the pending - * future. - * - *

Guarded by {@link #lock}. - * - * @param pageOrError the next page, or an error. - */ - @SuppressWarnings("GuardedBy") // this method is only called with the lock held - private void enqueueOrCompletePending(@NonNull Object pageOrError) { - assert lock.isHeldByCurrentThread(); - - if (queue == null) { - // This is the first time this callback tries to stream something back to the client, check - // if it can be selected - if (!chosenCallback.complete(this)) { - if (LOG.isTraceEnabled()) { - LOG.trace( - "[{}] Trying to enqueue {} but another callback was already chosen, aborting", - logPrefix, - asTraceString(pageOrError)); - } - // Discard the data, this callback will be canceled shortly since the chosen callback - // invoked cancelScheduledTasks - return; - } - - queue = new ArrayDeque<>(getMaxEnqueuedPages(statement)); - numPagesRequested = protocolBackpressureAvailable ? getMaxEnqueuedPages(statement) : 0; - cancelScheduledTasks(this); - } - - if (pendingResult != null) { - if (LOG.isTraceEnabled()) { - LOG.trace( - "[{}] Client was waiting on empty queue, completing with {}", - logPrefix, - asTraceString(pageOrError)); - } - CompletableFuture tmp = pendingResult; - // null out pendingResult before completing it because its completion - // may trigger a call to fetchNextPage -> dequeueOrCreatePending, - // which expects pendingResult to be null. - pendingResult = null; - completeResultSetFuture(tmp, pageOrError); - } else { - if (LOG.isTraceEnabled()) { - LOG.trace("[{}] Enqueuing {}", logPrefix, asTraceString(pageOrError)); - } - queue.add(pageOrError); - // Backpressure without protocol support: if the queue grows too large, - // disable auto-read so that the channel eventually becomes - // non-writable on the server side (causing it to back off for a while) - if (!protocolBackpressureAvailable - && queue.size() == getMaxEnqueuedPages(statement) - && state > 0) { - LOG.trace( - "[{}] Exceeded {} queued response pages, disabling auto-read", - logPrefix, - queue.size()); - channel.config().setAutoRead(false); - } - } - } - - /** - * Dequeue a response or, if the queue is empty, create the future that will get notified of the - * next response, when it arrives. - * - *

Called from user code, see {@link ContinuousAsyncResultSet#fetchNextPage()}. - * - * @return the next page's future; never null. - */ - @NonNull - public CompletableFuture dequeueOrCreatePending() { - lock.lock(); - try { - // If the client was already waiting for a page, there's no way it can call this method - // again - // (this is guaranteed by our public API because in order to ask for the next page, - // you need the reference to the previous page). - assert pendingResult == null; - - Object head = null; - if (queue != null) { - head = queue.poll(); - if (!protocolBackpressureAvailable - && head != null - && queue.size() == getMaxEnqueuedPages(statement) - 1) { - LOG.trace( - "[{}] Back to {} queued response pages, re-enabling auto-read", - logPrefix, - queue.size()); - channel.config().setAutoRead(true); - } - maybeRequestMore(); - } - - if (head != null) { - if (state == STATE_FAILED && !(head instanceof Throwable)) { - LOG.trace( - "[{}] Client requested next page on cancelled queue, discarding page and returning cancelled future", - logPrefix); - return cancelledResultSetFuture(); - } else { - if (LOG.isTraceEnabled()) { - LOG.trace( - "[{}] Client requested next page on non-empty queue, returning immediate future of {}", - logPrefix, - asTraceString(head)); - } - return immediateResultSetFuture(head); - } - } else { - if (state == STATE_FAILED) { - LOG.trace( - "[{}] Client requested next page on cancelled empty queue, returning cancelled future", - logPrefix); - return cancelledResultSetFuture(); - } else { - LOG.trace( - "[{}] Client requested next page but queue is empty, installing future", logPrefix); - pendingResult = new CompletableFuture<>(); - // Only schedule a timeout if we're past the first page (the first page's timeout is - // handled in sendRequest). - if (state > 1) { - pageTimeout = schedulePageTimeout(state); - // Note: each new timeout is cancelled when the next response arrives, see - // onResponse(Frame). - } - return pendingResult; - } - } - } finally { - lock.unlock(); - } - } - - /** - * If the total number of results in the queue and in-flight (requested - received) is less than - * half the queue size, then request more pages, unless the {@link #state} is failed, we're - * still waiting for the first page (so maybe still throttled or in the middle of a retry), or - * we don't support backpressure at the protocol level. - */ - @SuppressWarnings("GuardedBy") - private void maybeRequestMore() { - assert lock.isHeldByCurrentThread(); - if (state < 2 || streamId == -1 || !protocolBackpressureAvailable) { - return; - } - // if we have already requested more than the client needs, then no need to request some more - int maxPages = getMaxPages(statement); - if (maxPages > 0 && numPagesRequested >= maxPages) { - return; - } - // the pages received so far, which is the state minus one - int received = state - 1; - int requested = numPagesRequested; - // the pages that fit in the queue, which is the queue free space minus the requests in flight - int freeSpace = getMaxEnqueuedPages(statement) - queue.size(); - int inFlight = requested - received; - int numPagesFittingInQueue = freeSpace - inFlight; - if (numPagesFittingInQueue > 0 - && numPagesFittingInQueue >= getMaxEnqueuedPages(statement) / 2) { - LOG.trace("[{}] Requesting more {} pages", logPrefix, numPagesFittingInQueue); - numPagesRequested = requested + numPagesFittingInQueue; - sendMorePagesRequest(numPagesFittingInQueue); - } - } - - /** - * Sends a request for more pages (a.k.a. backpressure request). - * - * @param nextPages the number of extra pages to request. - */ - @SuppressWarnings("GuardedBy") - private void sendMorePagesRequest(int nextPages) { - assert lock.isHeldByCurrentThread(); - assert channel != null : "expected valid connection in order to request more pages"; - assert protocolBackpressureAvailable; - assert streamId != -1; - - LOG.trace("[{}] Sending request for more pages", logPrefix); - ThrottledAdminRequestHandler.query( - channel, - true, - Revise.requestMoreContinuousPages(streamId, nextPages), - statement.getCustomPayload(), - getReviseRequestTimeout(statement), - throttler, - session.getMetricUpdater(), - logPrefix, - "request " + nextPages + " more pages for id " + streamId) - .start() - .handle( - (result, error) -> { - if (error != null) { - Loggers.warnWithException( - LOG, "[{}] Error requesting more pages, aborting.", logPrefix, error); - lock.lock(); - try { - // Set fromServer to false because we want the callback to still cancel the - // session if possible or else the server will wait on a timeout. - abort(error, false); - } finally { - lock.unlock(); - } - } - return null; - }); - } - - /** Cancels the given timeout, if non null. */ - private void cancelTimeout(Timeout timeout) { - if (timeout != null) { - LOG.trace("[{}] Cancelling timeout", logPrefix); - timeout.cancel(); - } - } - - // CANCELLATION - - public void cancel() { - lock.lock(); - try { - if (state < 0) { - return; - } else { - LOG.trace( - "[{}] Cancelling continuous paging session with state {} on node {}", - logPrefix, - state, - node); - state = STATE_FAILED; - if (pendingResult != null) { - pendingResult.cancel(true); - } - releaseStreamId(); - } - } finally { - lock.unlock(); - } - reenableAutoReadIfNeeded(); - } - - @SuppressWarnings("GuardedBy") - private void releaseStreamId() { - assert lock.isHeldByCurrentThread(); - // If we saw the last response already, InFlightHandler will release the id so no need to - // cancel explicitly - if (streamId >= 0 && !sawLastResponse && !channel.closeFuture().isDone()) { - // This orphans the stream id, but it will still be held until we see the last response: - channel.cancel(this); - // This tells the server to stop streaming, and send a terminal response: - sendCancelRequest(); - } - } - - @SuppressWarnings("GuardedBy") - private void sendCancelRequest() { - assert lock.isHeldByCurrentThread(); - LOG.trace("[{}] Sending cancel request", logPrefix); - ThrottledAdminRequestHandler.query( - channel, - true, - Revise.cancelContinuousPaging(streamId), - statement.getCustomPayload(), - getReviseRequestTimeout(statement), - throttler, - session.getMetricUpdater(), - logPrefix, - "cancel request") - .start() - .handle( - (result, error) -> { - if (error != null) { - Loggers.warnWithException( - LOG, - "[{}] Error sending cancel request. " - + "This is not critical (the request will eventually time out server-side).", - logPrefix, - error); - } else { - LOG.trace("[{}] Continuous paging session cancelled successfully", logPrefix); - } - return null; - }); - sentCancelRequest = true; - } - - // TERMINATION - - private void reenableAutoReadIfNeeded() { - // Make sure we don't leave the channel unreadable - LOG.trace("[{}] Re-enabling auto-read", logPrefix); - if (!protocolBackpressureAvailable) { - channel.config().setAutoRead(true); - } - } - - // ERROR HANDLING - - private void trackNodeError(@NonNull Node node, @NonNull Throwable error) { - if (nodeErrorReported.compareAndSet(false, true)) { - long latencyNanos = System.nanoTime() - this.messageStartTimeNanos; - context - .getRequestTracker() - .onNodeError(this.statement, error, latencyNanos, executionProfile, node, logPrefix); - } - } - - /** - * Aborts the continuous paging session due to an error that can be either from the server or - * the client. - * - * @param error the error that causes the abortion. - * @param fromServer whether the error was triggered by the coordinator or by the driver. - */ - @SuppressWarnings("GuardedBy") // this method is only called with the lock held - private void abort(@NonNull Throwable error, boolean fromServer) { - assert lock.isHeldByCurrentThread(); - LOG.trace( - "[{}] Aborting due to {} ({})", - logPrefix, - error.getClass().getSimpleName(), - error.getMessage()); - if (channel == null) { - // This only happens when sending the initial request, if no host was available - // or if the iterator returned by the LBP threw an exception. - // In either case the write was not even attempted, and - // we set the state right now. - enqueueOrCompletePending(error); - state = STATE_FAILED; - } else if (state > 0) { - enqueueOrCompletePending(error); - if (fromServer) { - // We can safely assume the server won't send any more responses, - // so set the state and call release() right now. - state = STATE_FAILED; - reenableAutoReadIfNeeded(); - } else { - // attempt to cancel first, i.e. ask server to stop sending responses, - // and only then release. - cancel(); - } - } - stopGlobalRequestTimer(); - cancelTimeout(globalTimeout); - } - - // METRICS - - private void stopNodeMessageTimer() { - if (stopNodeMessageTimerReported.compareAndSet(false, true)) { - ((DefaultNode) node) - .getMetricUpdater() - .updateTimer( - messagesMetric, - executionProfile.getName(), - System.nanoTime() - messageStartTimeNanos, - TimeUnit.NANOSECONDS); - } - } - - private void stopGlobalRequestTimer() { - session - .getMetricUpdater() - .updateTimer( - continuousRequestsMetric, - null, - System.nanoTime() - startTimeNanos, - TimeUnit.NANOSECONDS); - } - - private void updateErrorMetrics( - @NonNull NodeMetricUpdater metricUpdater, - @NonNull RetryVerdict verdict, - @NonNull DefaultNodeMetric error, - @NonNull DefaultNodeMetric retriesOnError, - @NonNull DefaultNodeMetric ignoresOnError) { - metricUpdater.incrementCounter(error, executionProfile.getName()); - switch (verdict.getRetryDecision()) { - case RETRY_SAME: - case RETRY_NEXT: - metricUpdater.incrementCounter(DefaultNodeMetric.RETRIES, executionProfile.getName()); - metricUpdater.incrementCounter(retriesOnError, executionProfile.getName()); - break; - case IGNORE: - metricUpdater.incrementCounter(DefaultNodeMetric.IGNORES, executionProfile.getName()); - metricUpdater.incrementCounter(ignoresOnError, executionProfile.getName()); - break; - case RETHROW: - // nothing do do - } - } - - // UTILITY METHODS - - @NonNull - private CompletableFuture immediateResultSetFuture(@NonNull Object pageOrError) { - CompletableFuture future = new CompletableFuture<>(); - completeResultSetFuture(future, pageOrError); - return future; - } - - @NonNull - private CompletableFuture cancelledResultSetFuture() { - return immediateResultSetFuture( - new CancellationException( - "Can't get more results because the continuous query has failed already. " - + "Most likely this is because the query was cancelled")); - } - - private void completeResultSetFuture( - @NonNull CompletableFuture future, @NonNull Object pageOrError) { - long now = System.nanoTime(); - long totalLatencyNanos = now - startTimeNanos; - long nodeLatencyNanos = now - messageStartTimeNanos; - if (resultSetClass.isInstance(pageOrError)) { - if (future.complete(resultSetClass.cast(pageOrError))) { - throttler.signalSuccess(ContinuousRequestHandlerBase.this); - if (nodeSuccessReported.compareAndSet(false, true)) { - context - .getRequestTracker() - .onNodeSuccess(statement, nodeLatencyNanos, executionProfile, node, logPrefix); - } - context - .getRequestTracker() - .onSuccess(statement, totalLatencyNanos, executionProfile, node, logPrefix); - } - } else { - Throwable error = (Throwable) pageOrError; - if (future.completeExceptionally(error)) { - context - .getRequestTracker() - .onError(statement, error, totalLatencyNanos, executionProfile, node, logPrefix); - if (error instanceof DriverTimeoutException) { - throttler.signalTimeout(ContinuousRequestHandlerBase.this); - session - .getMetricUpdater() - .incrementCounter(clientTimeoutsMetric, executionProfile.getName()); - } else if (!(error instanceof RequestThrottlingException)) { - throttler.signalError(ContinuousRequestHandlerBase.this, error); - } - } - } - } - - @NonNull - private ExecutionInfo createExecutionInfo(@NonNull Result result, @Nullable Frame response) { - ByteBuffer pagingState = - result instanceof Rows ? ((Rows) result).getMetadata().pagingState : null; - return new DefaultExecutionInfo( - statement, - node, - startedSpeculativeExecutionsCount.get(), - executionIndex, - errors, - pagingState, - response, - true, - session, - context, - executionProfile); - } - - private void logTimeoutSchedulingError(IllegalStateException timeoutError) { - // If we're racing with session shutdown, the timer might be stopped already. We don't want - // to schedule more executions anyway, so swallow the error. - if (!"cannot be started once stopped".equals(timeoutError.getMessage())) { - Loggers.warnWithException( - LOG, "[{}] Error while scheduling timeout", logPrefix, timeoutError); - } - } - - @NonNull - private String asTraceString(@NonNull Object pageOrError) { - return resultSetClass.isInstance(pageOrError) - ? "page " + pageNumber(resultSetClass.cast(pageOrError)) - : ((Exception) pageOrError).getClass().getSimpleName(); - } - - private int getState() { - lock.lock(); - try { - return state; - } finally { - lock.unlock(); - } - } - - private CompletableFuture getPendingResult() { - lock.lock(); - try { - return pendingResult; - } finally { - lock.unlock(); - } - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousAsyncResultSet.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousAsyncResultSet.java deleted file mode 100644 index 8562fde5905..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousAsyncResultSet.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.Row; -import com.datastax.oss.driver.internal.core.cql.EmptyColumnDefinitions; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Collections; -import java.util.concurrent.CompletionStage; -import net.jcip.annotations.NotThreadSafe; - -@NotThreadSafe // wraps a mutable queue -public class DefaultContinuousAsyncResultSet implements ContinuousAsyncResultSet { - - private final Iterable currentPage; - private final ColumnDefinitions columnDefinitions; - private final int pageNumber; - private final boolean hasMorePages; - private final ExecutionInfo executionInfo; - private final ContinuousCqlRequestHandler handler; - private final CountingIterator iterator; - - public DefaultContinuousAsyncResultSet( - CountingIterator iterator, - ColumnDefinitions columnDefinitions, - int pageNumber, - boolean hasMorePages, - ExecutionInfo executionInfo, - ContinuousCqlRequestHandler handler) { - this.columnDefinitions = columnDefinitions; - this.pageNumber = pageNumber; - this.hasMorePages = hasMorePages; - this.executionInfo = executionInfo; - this.handler = handler; - this.iterator = iterator; - this.currentPage = () -> iterator; - } - - @NonNull - @Override - public ColumnDefinitions getColumnDefinitions() { - return columnDefinitions; - } - - @Override - public boolean wasApplied() { - // always return true for non-conditional updates - return true; - } - - @NonNull - @Override - public ExecutionInfo getExecutionInfo() { - return executionInfo; - } - - @Override - public int pageNumber() { - return pageNumber; - } - - @Override - public boolean hasMorePages() { - return hasMorePages; - } - - @NonNull - @Override - public Iterable currentPage() { - return currentPage; - } - - @Override - public int remaining() { - return iterator.remaining(); - } - - @NonNull - @Override - public CompletionStage fetchNextPage() throws IllegalStateException { - if (!hasMorePages()) { - throw new IllegalStateException( - "Can't call fetchNextPage() on the last page (use hasMorePages() to check)"); - } - return handler.fetchNextPage(); - } - - @Override - public void cancel() { - handler.cancel(); - } - - public static ContinuousAsyncResultSet empty(ExecutionInfo executionInfo) { - - return new ContinuousAsyncResultSet() { - - @NonNull - @Override - public ColumnDefinitions getColumnDefinitions() { - return EmptyColumnDefinitions.INSTANCE; - } - - @NonNull - @Override - public ExecutionInfo getExecutionInfo() { - return executionInfo; - } - - @NonNull - @Override - public Iterable currentPage() { - return Collections.emptyList(); - } - - @Override - public int remaining() { - return 0; - } - - @Override - public boolean hasMorePages() { - return false; - } - - @Override - public int pageNumber() { - return 1; - } - - @NonNull - @Override - public CompletionStage fetchNextPage() - throws IllegalStateException { - throw new IllegalStateException( - "Can't call fetchNextPage() on the last page (use hasMorePages() to check)"); - } - - @Override - public void cancel() { - // noop - } - - @Override - public boolean wasApplied() { - // always true - return true; - } - }; - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousResultSet.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousResultSet.java deleted file mode 100644 index 929400bc7a6..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousResultSet.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousResultSet; -import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.Row; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import com.datastax.oss.driver.internal.core.util.concurrent.BlockingOperation; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import net.jcip.annotations.NotThreadSafe; - -/** - * This class is roughly equivalent to {@link - * com.datastax.oss.driver.internal.core.cql.MultiPageResultSet}, except that {@link - * RowIterator#maybeMoveToNextPage()} needs to check for cancellation before fetching the next page. - */ -@NotThreadSafe -public class DefaultContinuousResultSet implements ContinuousResultSet { - - private final RowIterator iterator; - private final List executionInfos = new ArrayList<>(); - private final ColumnDefinitions columnDefinitions; - - public DefaultContinuousResultSet(ContinuousAsyncResultSet firstPage) { - iterator = new RowIterator(firstPage); - columnDefinitions = firstPage.getColumnDefinitions(); - executionInfos.add(firstPage.getExecutionInfo()); - } - - @Override - public void cancel() { - iterator.cancel(); - } - - @NonNull - @Override - public ColumnDefinitions getColumnDefinitions() { - return columnDefinitions; - } - - @NonNull - @Override - public List getExecutionInfos() { - return executionInfos; - } - - @NonNull - @Override - public Iterator iterator() { - return iterator; - } - - @Override - public boolean isFullyFetched() { - return iterator.isFullyFetched(); - } - - @Override - public int getAvailableWithoutFetching() { - return iterator.remaining(); - } - - @Override - public boolean wasApplied() { - return iterator.wasApplied(); - } - - private class RowIterator extends CountingIterator { - private ContinuousAsyncResultSet currentPage; - private Iterator currentRows; - private boolean cancelled = false; - - private RowIterator(ContinuousAsyncResultSet firstPage) { - super(firstPage.remaining()); - currentPage = firstPage; - currentRows = firstPage.currentPage().iterator(); - } - - @Override - protected Row computeNext() { - maybeMoveToNextPage(); - return currentRows.hasNext() ? currentRows.next() : endOfData(); - } - - private void maybeMoveToNextPage() { - if (!cancelled && !currentRows.hasNext() && currentPage.hasMorePages()) { - BlockingOperation.checkNotDriverThread(); - ContinuousAsyncResultSet nextPage = - CompletableFutures.getUninterruptibly(currentPage.fetchNextPage()); - currentPage = nextPage; - remaining += currentPage.remaining(); - currentRows = nextPage.currentPage().iterator(); - executionInfos.add(nextPage.getExecutionInfo()); - } - } - - private boolean isFullyFetched() { - return !currentPage.hasMorePages(); - } - - private boolean wasApplied() { - return currentPage.wasApplied(); - } - - private void cancel() { - currentPage.cancel(); - cancelled = true; - } - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/ContinuousCqlRequestReactiveProcessor.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/ContinuousCqlRequestReactiveProcessor.java deleted file mode 100644 index afe0e864181..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/ContinuousCqlRequestReactiveProcessor.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous.reactive; - -import com.datastax.dse.driver.api.core.cql.continuous.reactive.ContinuousReactiveResultSet; -import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousCqlRequestAsyncProcessor; -import com.datastax.dse.driver.internal.core.cql.reactive.FailedReactiveResultSet; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.internal.core.session.RequestProcessor; -import net.jcip.annotations.ThreadSafe; - -@ThreadSafe -public class ContinuousCqlRequestReactiveProcessor - implements RequestProcessor, ContinuousReactiveResultSet> { - - public static final GenericType CONTINUOUS_REACTIVE_RESULT_SET = - GenericType.of(ContinuousReactiveResultSet.class); - - private final ContinuousCqlRequestAsyncProcessor asyncProcessor; - - public ContinuousCqlRequestReactiveProcessor(ContinuousCqlRequestAsyncProcessor asyncProcessor) { - this.asyncProcessor = asyncProcessor; - } - - @Override - public boolean canProcess(Request request, GenericType resultType) { - return request instanceof Statement && resultType.equals(CONTINUOUS_REACTIVE_RESULT_SET); - } - - @Override - public ContinuousReactiveResultSet process( - Statement request, - DefaultSession session, - InternalDriverContext context, - String sessionLogPrefix) { - return new DefaultContinuousReactiveResultSet( - () -> asyncProcessor.process(request, session, context, sessionLogPrefix)); - } - - @Override - public ContinuousReactiveResultSet newFailure(RuntimeException error) { - return new FailedReactiveResultSet(error); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/DefaultContinuousReactiveResultSet.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/DefaultContinuousReactiveResultSet.java deleted file mode 100644 index b3f301edea6..00000000000 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/DefaultContinuousReactiveResultSet.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous.reactive; - -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.dse.driver.api.core.cql.continuous.reactive.ContinuousReactiveResultSet; -import com.datastax.dse.driver.internal.core.cql.reactive.ReactiveResultSetBase; -import java.util.concurrent.Callable; -import java.util.concurrent.CompletionStage; -import net.jcip.annotations.ThreadSafe; - -@ThreadSafe -public class DefaultContinuousReactiveResultSet - extends ReactiveResultSetBase implements ContinuousReactiveResultSet { - - public DefaultContinuousReactiveResultSet( - Callable> firstPage) { - super(firstPage); - } -} diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/reactive/FailedReactiveResultSet.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/reactive/FailedReactiveResultSet.java index 31c34d649aa..4926725214f 100644 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/reactive/FailedReactiveResultSet.java +++ b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/reactive/FailedReactiveResultSet.java @@ -17,10 +17,8 @@ */ package com.datastax.dse.driver.internal.core.cql.reactive; -import com.datastax.dse.driver.api.core.cql.continuous.reactive.ContinuousReactiveResultSet; import com.datastax.dse.driver.api.core.cql.reactive.ReactiveResultSet; import com.datastax.dse.driver.api.core.cql.reactive.ReactiveRow; -import com.datastax.dse.driver.internal.core.cql.continuous.reactive.ContinuousCqlRequestReactiveProcessor; import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; import com.datastax.oss.driver.api.core.cql.ExecutionInfo; import edu.umd.cs.findbugs.annotations.NonNull; @@ -31,10 +29,9 @@ * subscribers. * * @see CqlRequestReactiveProcessor#newFailure(java.lang.RuntimeException) - * @see ContinuousCqlRequestReactiveProcessor#newFailure(java.lang.RuntimeException) */ public class FailedReactiveResultSet extends FailedPublisher - implements ReactiveResultSet, ContinuousReactiveResultSet { + implements ReactiveResultSet { public FailedReactiveResultSet(Throwable error) { super(error); diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/reactive/ReactiveResultSetSubscription.java b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/reactive/ReactiveResultSetSubscription.java index 500a291e9d2..0297066c7f1 100644 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/cql/reactive/ReactiveResultSetSubscription.java +++ b/core/src/main/java/com/datastax/dse/driver/internal/core/cql/reactive/ReactiveResultSetSubscription.java @@ -44,8 +44,6 @@ /** * A single-subscriber subscription that executes one single query and emits all the returned rows. - * - *

This class can handle both continuous and non-continuous result sets. */ @ThreadSafe public class ReactiveResultSetSubscription> @@ -474,8 +472,7 @@ CompletionStage fetchNextPage() { } catch (Exception e) { // This is a synchronous failure in the driver. // It can happen in rare cases when the driver throws an exception instead of returning a - // failed future; e.g. if someone tries to execute a continuous paging request but the - // protocol version in use does not support it. + // failed future; e.g. if the next page supplier fails before returning its future. // We treat it as a failed future. return CompletableFutures.failedFuture(e); } diff --git a/core/src/main/java/com/datastax/dse/driver/internal/core/insights/InsightsClient.java b/core/src/main/java/com/datastax/dse/driver/internal/core/insights/InsightsClient.java index 168477894ed..6178e63252d 100644 --- a/core/src/main/java/com/datastax/dse/driver/internal/core/insights/InsightsClient.java +++ b/core/src/main/java/com/datastax/dse/driver/internal/core/insights/InsightsClient.java @@ -25,7 +25,6 @@ import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.SSL_ENGINE_FACTORY_CLASS; import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.SSL_HOSTNAME_VALIDATION; -import com.datastax.dse.driver.api.core.DseProtocolVersion; import com.datastax.dse.driver.internal.core.insights.PackageUtil.ClassSettingDetails; import com.datastax.dse.driver.internal.core.insights.configuration.InsightsConfiguration; import com.datastax.dse.driver.internal.core.insights.exceptions.InsightEventFormatException; @@ -38,6 +37,7 @@ import com.datastax.dse.driver.internal.core.insights.schema.PoolSizeByHostDistance; import com.datastax.dse.driver.internal.core.insights.schema.SSL; import com.datastax.dse.driver.internal.core.insights.schema.SessionStateForNode; +import com.datastax.oss.driver.api.core.DefaultProtocolVersion; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.api.core.metadata.Node; import com.datastax.oss.driver.api.core.session.SessionBuilder; @@ -229,7 +229,7 @@ private CompletionStage sendJsonMessage(String jsonMessage) { private QueryOptions createQueryOptionsWithJson(String json) { TypeCodec codec = driverContext.getCodecRegistry().codecFor(DataTypes.TEXT, String.class); - ByteBuffer startupMessageSerialized = codec.encode(json, DseProtocolVersion.DSE_V2); + ByteBuffer startupMessageSerialized = codec.encode(json, DefaultProtocolVersion.V5); return new QueryOptions( QueryOptions.DEFAULT.consistency, Collections.singletonList(startupMessageSerialized), diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/CqlSession.java b/core/src/main/java/com/datastax/oss/driver/api/core/CqlSession.java index 0b075b4595f..0d03fd98b0f 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/CqlSession.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/CqlSession.java @@ -17,8 +17,6 @@ */ package com.datastax.oss.driver.api.core; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousSession; -import com.datastax.dse.driver.api.core.cql.continuous.reactive.ContinuousReactiveSession; import com.datastax.dse.driver.api.core.cql.reactive.ReactiveSession; import com.datastax.oss.driver.api.core.cql.AsyncCqlSession; import com.datastax.oss.driver.api.core.cql.SyncCqlSession; @@ -28,20 +26,10 @@ /** * The default session type built by the driver. * - *

It provides user-friendly execution methods for synchronous, asynchronous, reactive, and - * continuous-paging CQL requests. - * - *

Client applications can use this interface even if they don't need all the features. In - * particular, it can be used with a regular Apache Cassandra ® cluster, as long as you don't - * call continuous-paging methods. + *

It provides user-friendly execution methods for synchronous, asynchronous, and reactive CQL + * requests. */ -public interface CqlSession - extends Session, - SyncCqlSession, - AsyncCqlSession, - ReactiveSession, - ContinuousSession, - ContinuousReactiveSession { +public interface CqlSession extends Session, SyncCqlSession, AsyncCqlSession, ReactiveSession { /** * Returns a builder to create a new instance. diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/ProtocolVersion.java b/core/src/main/java/com/datastax/oss/driver/api/core/ProtocolVersion.java index f999d217b2b..a8a659525dc 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/ProtocolVersion.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/ProtocolVersion.java @@ -23,7 +23,6 @@ */ package com.datastax.oss.driver.api.core; -import com.datastax.dse.driver.api.core.DseProtocolVersion; import com.datastax.oss.driver.api.core.detach.Detachable; import edu.umd.cs.findbugs.annotations.NonNull; @@ -40,8 +39,6 @@ public interface ProtocolVersion { ProtocolVersion V4 = DefaultProtocolVersion.V4; ProtocolVersion V5 = DefaultProtocolVersion.V5; ProtocolVersion V6 = DefaultProtocolVersion.V6; - ProtocolVersion DSE_V1 = DseProtocolVersion.DSE_V1; - ProtocolVersion DSE_V2 = DseProtocolVersion.DSE_V2; /** The default version used for {@link Detachable detached} objects. */ // Implementation note: we can't use the ProtocolVersionRegistry here, this has to be a diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java index 3042013266f..a0eadf2781c 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java @@ -249,9 +249,6 @@ protected static void fillWithDriverDefaults(OptionsMap map) { Duration initQueryTimeout = Duration.ofSeconds(5); Duration requestTimeout = Duration.ofSeconds(2); int requestPageSize = 5000; - int continuousMaxPages = 0; - int continuousMaxPagesPerSecond = 0; - int continuousMaxEnqueuedPages = 4; // Sorted by order of appearance in reference.conf: @@ -298,13 +295,6 @@ protected static void fillWithDriverDefaults(OptionsMap map) { map.put(TypedDriverOption.REQUEST_TRACE_INTERVAL, Duration.ofMillis(3)); map.put(TypedDriverOption.REQUEST_TRACE_CONSISTENCY, "ONE"); map.put(TypedDriverOption.REQUEST_LOG_WARNINGS, true); - map.put(TypedDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, requestPageSize); - map.put(TypedDriverOption.CONTINUOUS_PAGING_PAGE_SIZE_BYTES, false); - map.put(TypedDriverOption.CONTINUOUS_PAGING_MAX_PAGES, continuousMaxPages); - map.put(TypedDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, continuousMaxPagesPerSecond); - map.put(TypedDriverOption.CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES, continuousMaxEnqueuedPages); - map.put(TypedDriverOption.CONTINUOUS_PAGING_TIMEOUT_FIRST_PAGE, Duration.ofSeconds(2)); - map.put(TypedDriverOption.CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES, Duration.ofSeconds(1)); map.put(TypedDriverOption.MONITOR_REPORTING_ENABLED, true); map.put(TypedDriverOption.METRICS_SESSION_ENABLED, Collections.emptyList()); map.put(TypedDriverOption.METRICS_SESSION_CQL_REQUESTS_HIGHEST, Duration.ofSeconds(3)); @@ -315,16 +305,6 @@ protected static void fillWithDriverDefaults(OptionsMap map) { map.put(TypedDriverOption.METRICS_SESSION_THROTTLING_LOWEST, Duration.ofMillis(1)); map.put(TypedDriverOption.METRICS_SESSION_THROTTLING_DIGITS, 3); map.put(TypedDriverOption.METRICS_SESSION_THROTTLING_INTERVAL, Duration.ofMinutes(5)); - map.put( - TypedDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_HIGHEST, - Duration.ofMinutes(2)); - map.put( - TypedDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_LOWEST, - Duration.ofMillis(10)); - map.put(TypedDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_DIGITS, 3); - map.put( - TypedDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_INTERVAL, - Duration.ofMinutes(5)); map.put(TypedDriverOption.METRICS_FACTORY_CLASS, "DefaultMetricsFactory"); map.put(TypedDriverOption.METRICS_ID_GENERATOR_CLASS, "DefaultMetricIdGenerator"); map.put(TypedDriverOption.METRICS_NODE_ENABLED, Collections.emptyList()); diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java index da5a474a31c..1e38da36f48 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java @@ -723,76 +723,6 @@ public String toString() { new TypedDriverOption<>( DseDriverOption.AUTH_PROVIDER_SASL_PROPERTIES, GenericType.mapOf(GenericType.STRING, GenericType.STRING)); - /** The page size for continuous paging. */ - public static final TypedDriverOption CONTINUOUS_PAGING_PAGE_SIZE = - new TypedDriverOption<>(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, GenericType.INTEGER); - /** - * Whether {@link #CONTINUOUS_PAGING_PAGE_SIZE} should be interpreted in number of rows or bytes. - */ - public static final TypedDriverOption CONTINUOUS_PAGING_PAGE_SIZE_BYTES = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE_BYTES, GenericType.BOOLEAN); - /** The maximum number of continuous pages to return. */ - public static final TypedDriverOption CONTINUOUS_PAGING_MAX_PAGES = - new TypedDriverOption<>(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES, GenericType.INTEGER); - /** The maximum number of continuous pages per second. */ - public static final TypedDriverOption CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, GenericType.INTEGER); - /** The maximum number of continuous pages that can be stored in the local queue. */ - public static final TypedDriverOption CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES, GenericType.INTEGER); - /** How long to wait for the coordinator to send the first continuous page. */ - public static final TypedDriverOption CONTINUOUS_PAGING_TIMEOUT_FIRST_PAGE = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_FIRST_PAGE, GenericType.DURATION); - /** How long to wait for the coordinator to send subsequent continuous pages. */ - public static final TypedDriverOption CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES, GenericType.DURATION); - /** The largest latency that we expect to record for continuous requests. */ - public static final TypedDriverOption - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_HIGHEST = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_HIGHEST, - GenericType.DURATION); - /** The shortest latency that we expect to record for continuous requests. */ - public static final TypedDriverOption - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_LOWEST = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_LOWEST, - GenericType.DURATION); - /** Optional service-level objectives to meet, as a list of latencies to track. */ - public static final TypedDriverOption> - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_SLO = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_SLO, - GenericType.listOf(GenericType.DURATION)); - /** - * Optional pre-defined percentile of continuous paging cql requests to publish, as a list of - * percentiles . - */ - public static final TypedDriverOption> - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_PUBLISH_PERCENTILES = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_PUBLISH_PERCENTILES, - GenericType.listOf(GenericType.DOUBLE)); - /** - * The number of significant decimal digits to which internal structures will maintain for - * continuous requests. - */ - public static final TypedDriverOption - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_DIGITS = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_DIGITS, - GenericType.INTEGER); - /** The interval at which percentile data is refreshed for continuous requests. */ - public static final TypedDriverOption - CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_INTERVAL = - new TypedDriverOption<>( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_INTERVAL, - GenericType.DURATION); /** Whether to send events for Insights monitoring. */ public static final TypedDriverOption MONITOR_REPORTING_ENABLED = new TypedDriverOption<>(DseDriverOption.MONITOR_REPORTING_ENABLED, GenericType.BOOLEAN); diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/metrics/SessionMetric.java b/core/src/main/java/com/datastax/oss/driver/api/core/metrics/SessionMetric.java index 2a1ee599754..a76f3b269da 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/metrics/SessionMetric.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/metrics/SessionMetric.java @@ -24,8 +24,7 @@ * A session-level metric exposed through {@link Session#getMetrics()}. * *

All metrics exposed out of the box by the driver are instances of {@link DefaultSessionMetric} - * or {@link com.datastax.dse.driver.api.core.metrics.DseSessionMetric DseSessionMetric} (this - * interface only exists to allow custom metrics in driver extensions). + * (this interface only exists to allow custom metrics in driver extensions). * * @see NodeMetric */ diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/DefaultProtocolVersionRegistry.java b/core/src/main/java/com/datastax/oss/driver/internal/core/DefaultProtocolVersionRegistry.java index 80850e8e95a..9899af80199 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/DefaultProtocolVersionRegistry.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/DefaultProtocolVersionRegistry.java @@ -1,11 +1,11 @@ /* * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file + * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file + * regarding copyright ownership. The ASF licenses this file * to you 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 + * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -17,54 +17,28 @@ */ package com.datastax.oss.driver.internal.core; -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.metadata.DseNodeProperties; -import com.datastax.dse.driver.internal.core.DseProtocolFeature; import com.datastax.oss.driver.api.core.DefaultProtocolVersion; import com.datastax.oss.driver.api.core.ProtocolVersion; import com.datastax.oss.driver.api.core.UnsupportedProtocolVersionException; import com.datastax.oss.driver.api.core.Version; import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.shaded.guava.common.annotations.VisibleForTesting; import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; -import java.util.Objects; import java.util.Optional; import java.util.Set; import net.jcip.annotations.ThreadSafe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** - * Built-in implementation of the protocol version registry, supports all Cassandra and DSE - * versions. - */ +/** Built-in implementation of the protocol version registry. */ @ThreadSafe public class DefaultProtocolVersionRegistry implements ProtocolVersionRegistry { private static final Logger LOG = LoggerFactory.getLogger(DefaultProtocolVersionRegistry.class); - private static final List allVersions = - ImmutableList.builder() - .add(DefaultProtocolVersion.values()) - .add(DseProtocolVersion.values()) - .build(); - - @VisibleForTesting - static final Version DSE_4_7_0 = Objects.requireNonNull(Version.parse("4.7.0")); - - @VisibleForTesting - static final Version DSE_5_0_0 = Objects.requireNonNull(Version.parse("5.0.0")); - - @VisibleForTesting - static final Version DSE_5_1_0 = Objects.requireNonNull(Version.parse("5.1.0")); - - @VisibleForTesting - static final Version DSE_6_0_0 = Objects.requireNonNull(Version.parse("6.0.0")); - - @VisibleForTesting - static final Version DSE_7_0_0 = Objects.requireNonNull(Version.parse("7.0.0")); + private static final List ALL_VERSIONS = + ImmutableList.copyOf(DefaultProtocolVersion.values()); private final String logPrefix; @@ -76,39 +50,30 @@ public DefaultProtocolVersionRegistry(String logPrefix) { public ProtocolVersion fromName(String name) { try { return DefaultProtocolVersion.valueOf(name); - } catch (IllegalArgumentException noOssVersion) { - try { - return DseProtocolVersion.valueOf(name); - } catch (IllegalArgumentException noDseVersion) { - throw new IllegalArgumentException("Unknown protocol version name: " + name); - } + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Unknown protocol version name: " + name); } } @Override public ProtocolVersion highestNonBeta() { - ProtocolVersion highest = allVersions.get(allVersions.size() - 1); - if (!highest.isBeta()) { - return highest; - } else { - return downgrade(highest) - .orElseThrow(() -> new AssertionError("There should be at least one non-beta version")); - } + ProtocolVersion highest = ALL_VERSIONS.get(ALL_VERSIONS.size() - 1); + return highest.isBeta() + ? downgrade(highest) + .orElseThrow(() -> new AssertionError("There should be at least one non-beta version")) + : highest; } @Override public Optional downgrade(ProtocolVersion version) { - int index = allVersions.indexOf(version); + int index = ALL_VERSIONS.indexOf(version); if (index < 0) { - // This method is called with a value obtained from fromName, so this should never happen throw new AssertionError(version + " is not a known version"); } else if (index == 0) { return Optional.empty(); - } else { - ProtocolVersion previousVersion = allVersions.get(index - 1); - // Beta versions are skipped during negotiation - return previousVersion.isBeta() ? downgrade(previousVersion) : Optional.of(previousVersion); } + ProtocolVersion previousVersion = ALL_VERSIONS.get(index - 1); + return previousVersion.isBeta() ? downgrade(previousVersion) : Optional.of(previousVersion); } @Override @@ -117,96 +82,54 @@ public ProtocolVersion highestCommon(Collection nodes) { throw new IllegalArgumentException("Expected at least one node"); } - // Start with all non-beta versions (beta versions are always forced, and we don't call this - // method if the version was forced). Set candidates = new LinkedHashSet<>(); - for (ProtocolVersion version : allVersions) { + for (ProtocolVersion version : ALL_VERSIONS) { if (!version.isBeta()) { candidates.add(version); } } - // Keep an unfiltered copy in case we need to throw an exception below ImmutableList initialCandidates = ImmutableList.copyOf(candidates); - // For each node, remove the versions it doesn't support for (Node node : nodes) { - - // We can't trust the Cassandra version reported by DSE to infer the maximum OSS protocol - // supported. For example DSE 6 reports release_version 4.0-SNAPSHOT, but only supports OSS - // protocol v4 (while Cassandra 4 will support v5). So we treat DSE separately. - Version dseVersion = (Version) node.getExtras().get(DseNodeProperties.DSE_VERSION); - if (dseVersion != null) { - LOG.debug("[{}] Node {} reports DSE version {}", logPrefix, node.getEndPoint(), dseVersion); - dseVersion = dseVersion.nextStable(); - if (dseVersion.compareTo(DSE_4_7_0) < 0) { - throw new UnsupportedProtocolVersionException( - node.getEndPoint(), - String.format( - "Node %s reports DSE version %s, " - + "but the driver only supports 4.7.0 and above", - node.getEndPoint(), dseVersion), - initialCandidates); - } else if (dseVersion.compareTo(DSE_5_0_0) < 0) { - // DSE 4.7.x, 4.8.x - removeHigherThan(DefaultProtocolVersion.V3, null, candidates); - } else if (dseVersion.compareTo(DSE_5_1_0) < 0) { - // DSE 5.0 - removeHigherThan(DefaultProtocolVersion.V4, null, candidates); - } else if (dseVersion.compareTo(DSE_6_0_0) < 0) { - // DSE 5.1 - removeHigherThan(DefaultProtocolVersion.V4, DseProtocolVersion.DSE_V1, candidates); - } else if (dseVersion.compareTo(DSE_7_0_0) < 0) { - // DSE 6 - removeHigherThan(DefaultProtocolVersion.V4, DseProtocolVersion.DSE_V2, candidates); - } else { - // DSE 7.0 - removeHigherThan(DefaultProtocolVersion.V5, DseProtocolVersion.DSE_V2, candidates); - } - } else { // not DSE - Version cassandraVersion = node.getCassandraVersion(); - if (cassandraVersion == null) { - LOG.warn( - "[{}] Node {} reports neither DSE version nor Cassandra version, " - + "ignoring it from optimal protocol version computation", - logPrefix, - node.getEndPoint()); - continue; - } - cassandraVersion = cassandraVersion.nextStable(); - LOG.debug( - "[{}] Node {} reports Cassandra version {}", + Version cassandraVersion = node.getCassandraVersion(); + if (cassandraVersion == null) { + LOG.warn( + "[{}] Node {} does not report a Cassandra version, " + + "ignoring it from optimal protocol version computation", logPrefix, + node.getEndPoint()); + continue; + } + cassandraVersion = cassandraVersion.nextStable(); + LOG.debug( + "[{}] Node {} reports Cassandra version {}", + logPrefix, + node.getEndPoint(), + cassandraVersion); + if (cassandraVersion.compareTo(Version.V2_1_0) < 0) { + throw new UnsupportedProtocolVersionException( node.getEndPoint(), - cassandraVersion); - if (cassandraVersion.compareTo(Version.V2_1_0) < 0) { - throw new UnsupportedProtocolVersionException( - node.getEndPoint(), - String.format( - "Node %s reports Cassandra version %s, " - + "but the driver only supports 2.1.0 and above", - node.getEndPoint(), cassandraVersion), - ImmutableList.of(DefaultProtocolVersion.V3, DefaultProtocolVersion.V4)); - } else if (cassandraVersion.compareTo(Version.V2_2_0) < 0) { - // 2.1.0 - removeHigherThan(DefaultProtocolVersion.V3, null, candidates); - } else if (cassandraVersion.compareTo(Version.V4_0_0) < 0) { - // 2.2, 3.x - removeHigherThan(DefaultProtocolVersion.V4, null, candidates); - } else { - // 4.0 - removeHigherThan(DefaultProtocolVersion.V5, null, candidates); - } + String.format( + "Node %s reports Cassandra version %s, " + + "but the driver only supports 2.1.0 and above", + node.getEndPoint(), cassandraVersion), + ImmutableList.of(DefaultProtocolVersion.V3, DefaultProtocolVersion.V4)); + } else if (cassandraVersion.compareTo(Version.V2_2_0) < 0) { + removeHigherThan(DefaultProtocolVersion.V3, candidates); + } else if (cassandraVersion.compareTo(Version.V4_0_0) < 0) { + removeHigherThan(DefaultProtocolVersion.V4, candidates); + } else { + removeHigherThan(DefaultProtocolVersion.V5, candidates); } } - // If we have versions left, return the highest one ProtocolVersion max = null; for (ProtocolVersion candidate : candidates) { if (max == null || max.getCode() < candidate.getCode()) { max = candidate; } } - if (max == null) { // Note: with the current algorithm, this never happens + if (max == null) { throw new UnsupportedProtocolVersionException( null, String.format( @@ -214,26 +137,15 @@ public ProtocolVersion highestCommon(Collection nodes) { + "enable DEBUG logs for '%s' for more details", LOG.getName()), initialCandidates); - } else { - return max; } + return max; } - // Removes all versions strictly higher than the given versions from candidates. A null - // maxDseVersion means "remove all DSE versions". private void removeHigherThan( - DefaultProtocolVersion maxOssVersion, - DseProtocolVersion maxDseVersion, - Set candidates) { - for (DefaultProtocolVersion ossVersion : DefaultProtocolVersion.values()) { - if (ossVersion.compareTo(maxOssVersion) > 0 && candidates.remove(ossVersion)) { - LOG.debug("[{}] Excluding protocol {}", logPrefix, ossVersion); - } - } - for (DseProtocolVersion dseVersion : DseProtocolVersion.values()) { - if ((maxDseVersion == null || dseVersion.compareTo(maxDseVersion) > 0) - && candidates.remove(dseVersion)) { - LOG.debug("[{}] Excluding protocol {}", logPrefix, dseVersion); + DefaultProtocolVersion maxVersion, Set candidates) { + for (DefaultProtocolVersion version : DefaultProtocolVersion.values()) { + if (version.compareTo(maxVersion) > 0 && candidates.remove(version)) { + LOG.debug("[{}] Excluding protocol {}", logPrefix, version); } } } @@ -244,23 +156,12 @@ public boolean supports(ProtocolVersion version, ProtocolFeature feature) { if (DefaultProtocolFeature.SMALLINT_AND_TINYINT_TYPES.equals(feature) || DefaultProtocolFeature.DATE_TYPE.equals(feature) || DefaultProtocolFeature.UNSET_BOUND_VALUES.equals(feature)) { - // All DSE versions and all OSS V4+ return DefaultProtocolVersion.V4.getCode() <= code; - } else if (DefaultProtocolFeature.PER_REQUEST_KEYSPACE.equals(feature)) { - // Only DSE_V2+ and OSS V5+ - return (DefaultProtocolVersion.V5.getCode() <= code - && code < DseProtocolVersion.DSE_V1.getCode()) - || DseProtocolVersion.DSE_V2.getCode() <= code; - } else if (DefaultProtocolFeature.NOW_IN_SECONDS.equals(feature) + } else if (DefaultProtocolFeature.PER_REQUEST_KEYSPACE.equals(feature) + || DefaultProtocolFeature.NOW_IN_SECONDS.equals(feature) || DefaultProtocolFeature.MODERN_FRAMING.equals(feature)) { - // OSS only, V5+ - return DefaultProtocolVersion.V5.getCode() <= code - && code < DseProtocolVersion.DSE_V1.getCode(); - } else if (DseProtocolFeature.CONTINUOUS_PAGING.equals(feature)) { - // All DSE versions - return DseProtocolVersion.DSE_V1.getCode() <= code; - } else { - throw new IllegalArgumentException("Unhandled protocol feature: " + feature); + return DefaultProtocolVersion.V5.getCode() <= code; } + throw new IllegalArgumentException("Unhandled protocol feature: " + feature); } } diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java b/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java index e6323b6b84c..910e5a9c5b6 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java @@ -22,9 +22,6 @@ import com.datastax.dse.driver.api.core.config.DseDriverOption; import com.datastax.dse.driver.internal.core.InsightsClientLifecycleListener; import com.datastax.dse.driver.internal.core.type.codec.DseTypeCodecsRegistrar; -import com.datastax.dse.protocol.internal.DseProtocolV1ClientCodecs; -import com.datastax.dse.protocol.internal.DseProtocolV2ClientCodecs; -import com.datastax.dse.protocol.internal.ProtocolV4ClientCodecsForDse; import com.datastax.oss.driver.api.core.ProtocolVersion; import com.datastax.oss.driver.api.core.addresstranslation.AddressTranslator; import com.datastax.oss.driver.api.core.auth.AuthProvider; @@ -105,6 +102,7 @@ import com.datastax.oss.protocol.internal.FrameCodec; import com.datastax.oss.protocol.internal.PrimitiveCodec; import com.datastax.oss.protocol.internal.ProtocolV3ClientCodecs; +import com.datastax.oss.protocol.internal.ProtocolV4ClientCodecs; import com.datastax.oss.protocol.internal.ProtocolV5ClientCodecs; import com.datastax.oss.protocol.internal.ProtocolV6ClientCodecs; import com.datastax.oss.protocol.internal.SegmentCodec; @@ -630,11 +628,9 @@ protected FrameCodec buildFrameCodec() { getPrimitiveCodec(), getCompressor(), new ProtocolV3ClientCodecs(), - new ProtocolV4ClientCodecsForDse(), + new ProtocolV4ClientCodecs(), new ProtocolV5ClientCodecs(), - new ProtocolV6ClientCodecs(), - new DseProtocolV1ClientCodecs(), - new DseProtocolV2ClientCodecs()); + new ProtocolV6ClientCodecs()); } protected SegmentCodec buildSegmentCodec() { diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java index 9a5e6aef3f8..f43b34d42fb 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java @@ -18,8 +18,6 @@ package com.datastax.oss.driver.internal.core.metrics; import com.codahale.metrics.MetricRegistry; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; @@ -58,12 +56,6 @@ public DropwizardSessionMetricUpdater( DefaultDriverOption.METRICS_SESSION_THROTTLING_HIGHEST, DefaultDriverOption.METRICS_SESSION_THROTTLING_DIGITS, DefaultDriverOption.METRICS_SESSION_THROTTLING_INTERVAL); - initializeHdrTimer( - DseSessionMetric.CONTINUOUS_CQL_REQUESTS, - profile, - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_HIGHEST, - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_DIGITS, - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_INTERVAL); } @Override diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/MetricPaths.java b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/MetricPaths.java index 3027b3f5b1f..fb086f4a3ac 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/MetricPaths.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/MetricPaths.java @@ -17,7 +17,6 @@ */ package com.datastax.oss.driver.internal.core.metrics; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; import com.datastax.oss.driver.api.core.metrics.NodeMetric; @@ -39,11 +38,7 @@ public static Set parseSessionMetricPaths(List paths, Str try { result.add(DefaultSessionMetric.fromPath(path)); } catch (IllegalArgumentException e) { - try { - result.add(DseSessionMetric.fromPath(path)); - } catch (IllegalArgumentException e1) { - LOG.warn("[{}] Unknown session metric {}, skipping", logPrefix, path); - } + LOG.warn("[{}] Unknown session metric {}, skipping", logPrefix, path); } } return Collections.unmodifiableSet(result); diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessors.java b/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessors.java index 1dce884c533..dbf13e391da 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessors.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/session/BuiltInRequestProcessors.java @@ -19,9 +19,6 @@ import static com.datastax.oss.driver.internal.core.util.Dependency.REACTIVE_STREAMS; -import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousCqlRequestAsyncProcessor; -import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousCqlRequestSyncProcessor; -import com.datastax.dse.driver.internal.core.cql.continuous.reactive.ContinuousCqlRequestReactiveProcessor; import com.datastax.dse.driver.internal.core.cql.reactive.CqlRequestReactiveProcessor; import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; import com.datastax.oss.driver.internal.core.cql.CqlPrepareAsyncProcessor; @@ -67,22 +64,11 @@ public static void addBasicProcessors( new CqlPrepareSyncProcessor(cqlPrepareAsyncProcessor); processors.add(cqlPrepareAsyncProcessor); processors.add(cqlPrepareSyncProcessor); - - // continuous requests (sync and async) - ContinuousCqlRequestAsyncProcessor continuousCqlRequestAsyncProcessor = - new ContinuousCqlRequestAsyncProcessor(); - ContinuousCqlRequestSyncProcessor continuousCqlRequestSyncProcessor = - new ContinuousCqlRequestSyncProcessor(continuousCqlRequestAsyncProcessor); - processors.add(continuousCqlRequestAsyncProcessor); - processors.add(continuousCqlRequestSyncProcessor); } public static void addReactiveProcessors(List> processors) { CqlRequestReactiveProcessor cqlRequestReactiveProcessor = new CqlRequestReactiveProcessor(new CqlRequestAsyncProcessor()); - ContinuousCqlRequestReactiveProcessor continuousCqlRequestReactiveProcessor = - new ContinuousCqlRequestReactiveProcessor(new ContinuousCqlRequestAsyncProcessor()); processors.add(cqlRequestReactiveProcessor); - processors.add(continuousCqlRequestReactiveProcessor); } } diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/util/concurrent/DriverBlockHoundIntegration.java b/core/src/main/java/com/datastax/oss/driver/internal/core/util/concurrent/DriverBlockHoundIntegration.java index 68e59e89c3b..698f3ab500d 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/util/concurrent/DriverBlockHoundIntegration.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/util/concurrent/DriverBlockHoundIntegration.java @@ -70,33 +70,6 @@ public void applyTo(BlockHound.Builder builder) { // protect the whole Uuids.timeBased method. "com.datastax.oss.driver.api.core.uuid.Uuids", "timeBased"); - // continuous paging - - builder.allowBlockingCallsInside( - "com.datastax.dse.driver.internal.core.cql.continuous.ContinuousRequestHandlerBase$NodeResponseCallback", - "cancel"); - builder.allowBlockingCallsInside( - "com.datastax.dse.driver.internal.core.cql.continuous.ContinuousRequestHandlerBase$NodeResponseCallback", - "dequeueOrCreatePending"); - builder.allowBlockingCallsInside( - "com.datastax.dse.driver.internal.core.cql.continuous.ContinuousRequestHandlerBase$NodeResponseCallback", - "isLastResponse"); - builder.allowBlockingCallsInside( - "com.datastax.dse.driver.internal.core.cql.continuous.ContinuousRequestHandlerBase$NodeResponseCallback", - "onFailure"); - builder.allowBlockingCallsInside( - "com.datastax.dse.driver.internal.core.cql.continuous.ContinuousRequestHandlerBase$NodeResponseCallback", - "onPageTimeout"); - builder.allowBlockingCallsInside( - "com.datastax.dse.driver.internal.core.cql.continuous.ContinuousRequestHandlerBase$NodeResponseCallback", - "onResponse"); - builder.allowBlockingCallsInside( - "com.datastax.dse.driver.internal.core.cql.continuous.ContinuousRequestHandlerBase$NodeResponseCallback", - "onStreamIdAssigned"); - builder.allowBlockingCallsInside( - "com.datastax.dse.driver.internal.core.cql.continuous.ContinuousRequestHandlerBase$NodeResponseCallback", - "operationComplete"); - // Netty extra exceptions // see https://github.com/netty/netty/pull/10810 diff --git a/core/src/main/resources/reference.conf b/core/src/main/resources/reference.conf index 1a9bf865658..082e41c3349 100644 --- a/core/src/main/resources/reference.conf +++ b/core/src/main/resources/reference.conf @@ -1275,98 +1275,6 @@ datastax-java-driver { log-warnings = true } - # Continuous paging (DataStax Enterprise only) - advanced.continuous-paging { - - # The page size. - # - # The value specified here can be interpreted in number of rows - # or in number of bytes, depending on the unit defined with page-unit (see below). - # - # It controls how many rows (or how much data) will be retrieved simultaneously in a single - # network roundtrip (the goal being to avoid loading too many results in memory at the same - # time). If there are more results, additional requests will be used to retrieve them (either - # automatically if you iterate with the sync API, or explicitly with the async API's - # fetchNextPage method). - # - # The default is the same as the driver's normal request page size, - # i.e., 5000 (rows). - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - page-size = ${datastax-java-driver.basic.request.page-size} - - # Whether the page-size option should be interpreted in number of rows or bytes. - # - # The default is false, i.e., the page size will be interpreted in number of rows. - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - page-size-in-bytes = false - - # The maximum number of pages to return. - # - # The default is zero, which means retrieve all pages. - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - max-pages = 0 - - # Returns the maximum number of pages per second. - # - # The default is zero, which means no limit. - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - max-pages-per-second = 0 - - # The maximum number of pages that can be stored in the local queue. - # - # This value must be positive. The default is 4. - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - max-enqueued-pages = 4 - - # Timeouts for continuous paging. - # - # Note that there is no global timeout for continuous paging as there is - # for regular queries, because continuous paging queries can take an arbitrarily - # long time to complete. - # - # Instead, timeouts are applied to each exchange between the driver and the coordinator. In - # other words, if the driver decides to retry, all timeouts are reset. - timeout { - - # How long to wait for the coordinator to send the first page. - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - first-page = 2 seconds - - # How long to wait for the coordinator to send subsequent pages. - # - # Required: yes - # Modifiable at runtime: yes, the new value will be used for continuous requests issued after - # the change - # Overridable in a profile: yes - other-pages = 1 second - - } - } - # DataStax Insights advanced.monitor-reporting { # Whether to send monitoring events. @@ -1540,23 +1448,6 @@ datastax-java-driver { # a Counter) // throttling.errors, - # The throughput and latency percentiles of DSE continuous CQL requests (exposed as a - # Timer). - # - # This metric is a session-level metric and corresponds to the overall duration of the - # session.executeContinuously() call, including any retry. - # - # Note that this metric is analogous to the OSS driver's 'cql-requests' metrics, but for - # continuous paging requests only. Continuous paging requests do not update the - # 'cql-requests' metric, because they are usually much longer. Only the following metrics - # are updated during a continuous paging request: - # - # - At node level: all the usual metrics available for normal CQL requests, such as - # 'cql-messages' and error-related metrics (but these are only updated for the first - # page of results); - # - At session level: only 'continuous-cql-requests' is updated (this metric). - // continuous-cql-requests, - ] # Extra configuration (for the metrics that need it) @@ -1635,19 +1526,6 @@ datastax-java-driver { // publish-percentiles = [ 0.75, 0.95, 0.99 ] } - # Required: if the 'continuous-cql-requests' metric is enabled, and Dropwizard or Micrometer - # is used. - # Modifiable at runtime: no - # Overridable in a profile: no - continuous-cql-requests { - highest-latency = 120 seconds - lowest-latency = 10 milliseconds - significant-digits = 3 - refresh-interval = 5 minutes - // slo = [ 100 milliseconds, 500 milliseconds, 1 second ] - // publish-percentiles = [ 0.75, 0.95, 0.99 ] - } - } # The node-level metrics (all disabled by default). # diff --git a/core/src/test/java/com/datastax/dse/driver/DseTestDataProviders.java b/core/src/test/java/com/datastax/dse/driver/DseTestDataProviders.java index 4c732ccda83..009d8380785 100644 --- a/core/src/test/java/com/datastax/dse/driver/DseTestDataProviders.java +++ b/core/src/test/java/com/datastax/dse/driver/DseTestDataProviders.java @@ -17,7 +17,6 @@ */ package com.datastax.dse.driver; -import com.datastax.dse.driver.api.core.DseProtocolVersion; import com.datastax.oss.driver.api.core.DefaultProtocolVersion; import com.tngtech.java.junit.dataprovider.DataProvider; import edu.umd.cs.findbugs.annotations.NonNull; @@ -26,21 +25,11 @@ public class DseTestDataProviders { - @DataProvider - public static Object[][] allDseProtocolVersions() { - return concat(DseProtocolVersion.values()); - } - @DataProvider public static Object[][] allOssProtocolVersions() { return concat(DefaultProtocolVersion.values()); } - @DataProvider - public static Object[][] allDseAndOssProtocolVersions() { - return concat(DefaultProtocolVersion.values(), DseProtocolVersion.values()); - } - @NonNull private static Object[][] concat(Object[]... values) { return Stream.of(values) diff --git a/core/src/test/java/com/datastax/dse/driver/DseTestFixtures.java b/core/src/test/java/com/datastax/dse/driver/DseTestFixtures.java index 7992dde4fea..049084e158c 100644 --- a/core/src/test/java/com/datastax/dse/driver/DseTestFixtures.java +++ b/core/src/test/java/com/datastax/dse/driver/DseTestFixtures.java @@ -21,7 +21,6 @@ import static org.mockito.Mockito.when; import com.datastax.dse.driver.api.core.metadata.DseNodeProperties; -import com.datastax.dse.protocol.internal.response.result.DseRowsMetadata; import com.datastax.oss.driver.api.core.Version; import com.datastax.oss.driver.api.core.metadata.Metadata; import com.datastax.oss.driver.api.core.metadata.Node; @@ -33,6 +32,7 @@ import com.datastax.oss.protocol.internal.response.result.DefaultRows; import com.datastax.oss.protocol.internal.response.result.RawType; import com.datastax.oss.protocol.internal.response.result.Rows; +import com.datastax.oss.protocol.internal.response.result.RowsMetadata; import com.datastax.oss.protocol.internal.util.Bytes; import java.nio.ByteBuffer; import java.util.ArrayDeque; @@ -46,8 +46,8 @@ public class DseTestFixtures { // Returns a single row, with a single "message" column with the value "hello, world" public static Rows singleDseRow() { - DseRowsMetadata metadata = - new DseRowsMetadata( + RowsMetadata metadata = + new RowsMetadata( ImmutableList.of( new ColumnSpec( "ks", @@ -57,9 +57,7 @@ public static Rows singleDseRow() { RawType.PRIMITIVES.get(ProtocolConstants.DataType.VARCHAR))), null, new int[] {}, - null, - 1, - true); + null); Queue> data = new ArrayDeque<>(); data.add(ImmutableList.of(Bytes.fromHexString("0x68656C6C6F2C20776F726C64"))); return new DefaultRows(metadata, data); @@ -67,8 +65,8 @@ public static Rows singleDseRow() { // Returns 10 rows, each with a single "message" column with the value "hello, world" public static Rows tenDseRows(int page, boolean last) { - DseRowsMetadata metadata = - new DseRowsMetadata( + RowsMetadata metadata = + new RowsMetadata( ImmutableList.of( new ColumnSpec( "ks", @@ -78,9 +76,7 @@ public static Rows tenDseRows(int page, boolean last) { RawType.PRIMITIVES.get(ProtocolConstants.DataType.VARCHAR))), last ? null : ByteBuffer.wrap(new byte[] {(byte) page}), new int[] {}, - null, - page, - last); + null); Queue> data = new ArrayDeque<>(); for (int i = 0; i < 10; i++) { data.add(ImmutableList.of(Bytes.fromHexString("0x68656C6C6F2C20776F726C64"))); diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/context/DseStartupOptionsBuilderTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/context/DseStartupOptionsBuilderTest.java index 81df53af9a3..4d513e270bc 100644 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/context/DseStartupOptionsBuilderTest.java +++ b/core/src/test/java/com/datastax/dse/driver/internal/core/context/DseStartupOptionsBuilderTest.java @@ -57,7 +57,6 @@ public void before() { initMocks(this); when(configLoader.getInitialConfig()).thenReturn(driverConfig); when(driverConfig.getDefaultProfile()).thenReturn(defaultProfile); - when(defaultProfile.isDefined(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE)).thenReturn(true); } private void buildContext(UUID clientId, String applicationName, String applicationVersion) { diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerNodeTargetingTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerNodeTargetingTest.java deleted file mode 100644 index 1edb7c183bf..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerNodeTargetingTest.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import static com.datastax.oss.driver.Assertions.assertThatStage; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.never; - -import com.datastax.dse.driver.DseTestDataProviders; -import com.datastax.dse.driver.DseTestFixtures; -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.oss.driver.api.core.AllNodesFailedException; -import com.datastax.oss.driver.api.core.NodeUnavailableException; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.api.core.session.Session; -import com.datastax.oss.driver.internal.core.cql.RequestHandlerTestHarness; -import com.datastax.oss.driver.internal.core.metadata.LoadBalancingPolicyWrapper; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletionStage; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mockito; - -public class ContinuousCqlRequestHandlerNodeTargetingTest - extends ContinuousCqlRequestHandlerTestBase { - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_fail_if_targeted_node_not_available(DseProtocolVersion version) { - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withResponse(node1, defaultFrameOf(DseTestFixtures.singleDseRow())) - .withResponse(node2, defaultFrameOf(DseTestFixtures.singleDseRow())) - .withEmptyPool(node3) - .withProtocolVersion(version) - .build()) { - - LoadBalancingPolicyWrapper loadBalancingPolicy = - harness.getContext().getLoadBalancingPolicyWrapper(); - InOrder invocations = Mockito.inOrder(loadBalancingPolicy); - - // target node3, which should be unavailable - CompletionStage resultSetFuture = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT.setNode(node3), - harness.getSession(), - harness.getContext(), - "target node 3, unavailable") - .handle(); - - assertThatStage(resultSetFuture) - .isFailed( - error -> { - assertThat(error).isInstanceOf(AllNodesFailedException.class); - Map> errors = - ((AllNodesFailedException) error).getAllErrors(); - assertThat(errors).hasSize(1); - List nodeErrors = errors.values().iterator().next(); - assertThat(nodeErrors).singleElement().isInstanceOf(NodeUnavailableException.class); - invocations - .verify(loadBalancingPolicy, never()) - .newQueryPlan(any(Request.class), anyString(), any(Session.class)); - }); - - resultSetFuture = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "no node targeting, should use node 1") - .handle(); - - assertThatStage(resultSetFuture) - .isSuccess( - resultSet -> { - assertThat(resultSet.getExecutionInfo().getCoordinator()).isEqualTo(node1); - invocations - .verify(loadBalancingPolicy) - .newQueryPlan( - UNDEFINED_IDEMPOTENCE_STATEMENT, - DriverExecutionProfile.DEFAULT_NAME, - harness.getSession()); - }); - - resultSetFuture = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "no node targeting, should use node 2") - .handle(); - - assertThatStage(resultSetFuture) - .isSuccess( - resultSet -> { - assertThat(resultSet.getExecutionInfo().getCoordinator()).isEqualTo(node2); - invocations - .verify(loadBalancingPolicy) - .newQueryPlan( - UNDEFINED_IDEMPOTENCE_STATEMENT, - DriverExecutionProfile.DEFAULT_NAME, - harness.getSession()); - }); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_target_node(DseProtocolVersion version) { - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withResponse(node1, defaultFrameOf(DseTestFixtures.singleDseRow())) - .withResponse(node2, defaultFrameOf(DseTestFixtures.singleDseRow())) - .withResponse(node3, defaultFrameOf(DseTestFixtures.singleDseRow())) - .withProtocolVersion(version) - .build()) { - - LoadBalancingPolicyWrapper loadBalancingPolicy = - harness.getContext().getLoadBalancingPolicyWrapper(); - InOrder invocations = Mockito.inOrder(loadBalancingPolicy); - - CompletionStage resultSetFuture = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT.setNode(node3), - harness.getSession(), - harness.getContext(), - "target node 3") - .handle(); - - assertThatStage(resultSetFuture) - .isSuccess( - resultSet -> { - assertThat(resultSet.getExecutionInfo().getCoordinator()).isEqualTo(node3); - invocations - .verify(loadBalancingPolicy, never()) - .newQueryPlan(any(Request.class), anyString(), any(Session.class)); - }); - - resultSetFuture = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "no node targeting") - .handle(); - - assertThatStage(resultSetFuture) - .isSuccess( - resultSet -> { - assertThat(resultSet.getExecutionInfo().getCoordinator()).isEqualTo(node1); - invocations - .verify(loadBalancingPolicy) - .newQueryPlan( - UNDEFINED_IDEMPOTENCE_STATEMENT, - DriverExecutionProfile.DEFAULT_NAME, - harness.getSession()); - }); - } - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerReprepareTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerReprepareTest.java deleted file mode 100644 index fd8d0ea1f98..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerReprepareTest.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import static com.datastax.oss.driver.Assertions.assertThat; -import static com.datastax.oss.driver.Assertions.assertThatStage; -import static com.datastax.oss.protocol.internal.Frame.NO_PAYLOAD; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyMap; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.DseTestDataProviders; -import com.datastax.dse.driver.DseTestFixtures; -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.servererrors.SyntaxError; -import com.datastax.oss.driver.internal.core.adminrequest.AdminRequestHandler; -import com.datastax.oss.driver.internal.core.adminrequest.UnexpectedResponseException; -import com.datastax.oss.driver.internal.core.cql.RequestHandlerTestHarness; -import com.datastax.oss.driver.internal.core.session.RepreparePayload; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import com.datastax.oss.protocol.internal.ProtocolConstants; -import com.datastax.oss.protocol.internal.ProtocolConstants.ErrorCode; -import com.datastax.oss.protocol.internal.request.Prepare; -import com.datastax.oss.protocol.internal.request.Query; -import com.datastax.oss.protocol.internal.response.Error; -import com.datastax.oss.protocol.internal.response.error.Unprepared; -import com.datastax.oss.protocol.internal.response.result.Prepared; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import io.netty.util.concurrent.Future; -import java.nio.ByteBuffer; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import org.junit.Test; -import org.mockito.Mock; - -public class ContinuousCqlRequestHandlerReprepareTest extends ContinuousCqlRequestHandlerTestBase { - - private final byte[] preparedId = {1, 2, 3}; - private final ByteBuffer preparedIdBuf = ByteBuffer.wrap(preparedId); - - private final RepreparePayload repreparePayload = - new RepreparePayload(preparedIdBuf, "irrelevant", CqlIdentifier.fromCql("ks"), NO_PAYLOAD); - - private final ConcurrentMap repreparePayloads = - new ConcurrentHashMap<>(ImmutableMap.of(preparedIdBuf, repreparePayload)); - - private final Unprepared unprepared = new Unprepared("test", preparedId); - private final Prepared prepared = new Prepared(preparedId, null, null, null); - private final Error unrecoverable = - new Error(ProtocolConstants.ErrorCode.SYNTAX_ERROR, "bad query"); - private final Error recoverable = new Error(ErrorCode.SERVER_ERROR, "sorry"); - - @Mock private Future future; - - @Override - public void setup() { - super.setup(); - when(future.isSuccess()).thenReturn(true); - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_prepare_and_retry_on_same_node(DseProtocolVersion version) { - - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withResponse(node1, defaultFrameOf(unprepared)) - .withProtocolVersion(version) - .build()) { - - when(harness.getSession().getRepreparePayloads()).thenReturn(repreparePayloads); - when(harness.getChannel(node1).write(any(Prepare.class), anyBoolean(), anyMap(), any())) - .then( - invocation -> { - AdminRequestHandler admin = invocation.getArgument(3); - admin.onResponse(defaultFrameOf(prepared)); - return future; - }); - - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, harness.getSession(), harness.getContext(), "test") - .handle(); - - verify(harness.getChannel(node1)).write(any(Prepare.class), anyBoolean(), anyMap(), any()); - // should have attempted to execute the query twice on the same node - verify(harness.getChannel(node1), times(2)) - .write(any(Query.class), anyBoolean(), anyMap(), any()); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_abort_when_prepare_fails_with_unrecoverable_error(DseProtocolVersion version) { - - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withResponse(node1, defaultFrameOf(unprepared)) - .withProtocolVersion(version) - .build()) { - - when(harness.getSession().getRepreparePayloads()).thenReturn(repreparePayloads); - when(harness.getChannel(node1).write(any(Prepare.class), anyBoolean(), anyMap(), any())) - .then( - invocation -> { - AdminRequestHandler admin = invocation.getArgument(3); - admin.onResponse(defaultFrameOf(unrecoverable)); - return future; - }); - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, harness.getSession(), harness.getContext(), "test"); - CompletionStage page1Future = handler.handle(); - - verify(harness.getChannel(node1)).write(any(Query.class), anyBoolean(), anyMap(), any()); - verify(harness.getChannel(node1)).write(any(Prepare.class), anyBoolean(), anyMap(), any()); - - assertThat(handler.getState()).isEqualTo(-2); - assertThat(page1Future).isCompletedExceptionally(); - Throwable t = catchThrowable(() -> page1Future.toCompletableFuture().get()); - assertThat(t).hasRootCauseInstanceOf(SyntaxError.class).hasMessageContaining("bad query"); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_try_next_node_when_prepare_fails_with_recoverable_error( - DseProtocolVersion version) { - - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withResponse(node1, defaultFrameOf(unprepared)) - .withResponse(node2, defaultFrameOf(DseTestFixtures.singleDseRow())) - .withProtocolVersion(version) - .build()) { - - when(harness.getSession().getRepreparePayloads()).thenReturn(repreparePayloads); - when(harness.getChannel(node1).write(any(Prepare.class), anyBoolean(), anyMap(), any())) - .then( - invocation -> { - AdminRequestHandler admin = invocation.getArgument(3); - admin.onResponse(defaultFrameOf(recoverable)); - return future; - }); - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, harness.getSession(), harness.getContext(), "test"); - CompletionStage page1Future = handler.handle(); - - verify(harness.getChannel(node1)).write(any(Query.class), anyBoolean(), anyMap(), any()); - verify(harness.getChannel(node1)).write(any(Prepare.class), anyBoolean(), anyMap(), any()); - // should have tried the next host - verify(harness.getChannel(node2)).write(any(Query.class), anyBoolean(), anyMap(), any()); - - assertThat(handler.getState()).isEqualTo(-1); - assertThatStage(page1Future) - .isSuccess( - rs -> { - assertThat(rs.currentPage()).hasSize(1); - assertThat(rs.hasMorePages()).isFalse(); - assertThat(rs.getExecutionInfo().getCoordinator()).isEqualTo(node2); - assertThat(rs.getExecutionInfo().getErrors()) - .hasSize(1) - .allSatisfy( - entry -> { - assertThat(entry.getKey()).isEqualTo(node1); - assertThat(entry.getValue()) - .isInstanceOf(UnexpectedResponseException.class) - .hasMessageContaining(recoverable.toString()); - }); - }); - } - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerRetryTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerRetryTest.java deleted file mode 100644 index 97fe82985de..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerRetryTest.java +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import static com.datastax.dse.driver.DseTestDataProviders.allDseProtocolVersions; -import static com.datastax.oss.driver.Assertions.assertThat; -import static com.datastax.oss.driver.Assertions.assertThatStage; -import static com.datastax.oss.driver.TestDataProviders.combine; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.atMost; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.DseTestFixtures; -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.oss.driver.TestDataProviders; -import com.datastax.oss.driver.api.core.DefaultConsistencyLevel; -import com.datastax.oss.driver.api.core.connection.HeartbeatException; -import com.datastax.oss.driver.api.core.cql.BatchStatement; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.Row; -import com.datastax.oss.driver.api.core.cql.SimpleStatement; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; -import com.datastax.oss.driver.api.core.retry.RetryPolicy; -import com.datastax.oss.driver.api.core.retry.RetryVerdict; -import com.datastax.oss.driver.api.core.servererrors.BootstrappingException; -import com.datastax.oss.driver.api.core.servererrors.DefaultWriteType; -import com.datastax.oss.driver.api.core.servererrors.InvalidQueryException; -import com.datastax.oss.driver.api.core.servererrors.ReadTimeoutException; -import com.datastax.oss.driver.api.core.servererrors.ServerError; -import com.datastax.oss.driver.api.core.servererrors.UnavailableException; -import com.datastax.oss.driver.api.core.servererrors.WriteTimeoutException; -import com.datastax.oss.driver.internal.core.cql.RequestHandlerTestHarness; -import com.datastax.oss.protocol.internal.ProtocolConstants; -import com.datastax.oss.protocol.internal.response.Error; -import com.datastax.oss.protocol.internal.response.error.ReadTimeout; -import com.datastax.oss.protocol.internal.response.error.Unavailable; -import com.datastax.oss.protocol.internal.response.error.WriteTimeout; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.mockito.Mockito; - -public class ContinuousCqlRequestHandlerRetryTest extends ContinuousCqlRequestHandlerTestBase { - - @Test - @UseDataProvider("allIdempotenceConfigs") - public void should_always_try_next_node_if_bootstrapping( - boolean defaultIdempotence, Statement statement, DseProtocolVersion version) { - - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withProtocolVersion(version) - .withDefaultIdempotence(defaultIdempotence) - .withResponse( - node1, - defaultFrameOf( - new Error(ProtocolConstants.ErrorCode.IS_BOOTSTRAPPING, "mock message"))) - .withResponse(node2, defaultFrameOf(DseTestFixtures.singleDseRow())) - .build()) { - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - statement, harness.getSession(), harness.getContext(), "test"); - CompletionStage resultSetFuture = handler.handle(); - - assertThat(handler.getState()).isEqualTo(-1); - - assertThatStage(resultSetFuture) - .isSuccess( - resultSet -> { - Iterator rows = resultSet.currentPage().iterator(); - assertThat(rows.hasNext()).isTrue(); - assertThat(rows.next().getString("message")).isEqualTo("hello, world"); - - ExecutionInfo executionInfo = resultSet.getExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node2); - assertThat(executionInfo.getErrors()).hasSize(1); - assertThat(executionInfo.getErrors().get(0).getKey()).isEqualTo(node1); - assertThat(executionInfo.getErrors().get(0).getValue()) - .isInstanceOf(BootstrappingException.class); - assertThat(executionInfo.getIncomingPayload()).isEmpty(); - assertThat(executionInfo.getPagingState()).isNull(); - assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(executionInfo.getWarnings()).isEmpty(); - - Mockito.verifyNoMoreInteractions(harness.getContext().getRetryPolicy(anyString())); - }); - } - } - - @Test - @UseDataProvider("allIdempotenceConfigs") - public void should_always_rethrow_query_validation_error( - boolean defaultIdempotence, Statement statement, DseProtocolVersion version) { - - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withProtocolVersion(version) - .withDefaultIdempotence(defaultIdempotence) - .withResponse( - node1, - defaultFrameOf(new Error(ProtocolConstants.ErrorCode.INVALID, "mock message"))) - .build()) { - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - statement, harness.getSession(), harness.getContext(), "test"); - CompletionStage resultSetFuture = handler.handle(); - - assertThat(handler.getState()).isEqualTo(-2); - - assertThatStage(resultSetFuture) - .isFailed( - error -> { - assertThat(error) - .isInstanceOf(InvalidQueryException.class) - .hasMessage("mock message"); - Mockito.verifyNoMoreInteractions(harness.getContext().getRetryPolicy(anyString())); - - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(DefaultNodeMetric.OTHER_ERRORS), anyString()); - Mockito.verify(nodeMetricUpdater1) - .updateTimer( - eq(DefaultNodeMetric.CQL_MESSAGES), - anyString(), - anyLong(), - eq(TimeUnit.NANOSECONDS)); - Mockito.verifyNoMoreInteractions(nodeMetricUpdater1); - }); - } - } - - @Test - @UseDataProvider("failureAndIdempotent") - public void should_try_next_node_if_idempotent_and_retry_policy_decides_so( - FailureScenario failureScenario, - boolean defaultIdempotence, - Statement statement, - DseProtocolVersion version) { - - RequestHandlerTestHarness.Builder harnessBuilder = - continuousHarnessBuilder() - .withProtocolVersion(version) - .withDefaultIdempotence(defaultIdempotence); - failureScenario.mockRequestError(harnessBuilder, node1); - harnessBuilder.withResponse(node2, defaultFrameOf(DseTestFixtures.singleDseRow())); - - try (RequestHandlerTestHarness harness = harnessBuilder.build()) { - failureScenario.mockRetryPolicyVerdict( - harness.getContext().getRetryPolicy(anyString()), RetryVerdict.RETRY_NEXT); - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - statement, harness.getSession(), harness.getContext(), "test"); - CompletionStage resultSetFuture = handler.handle(); - - assertThat(handler.getState()).isEqualTo(-1); - - assertThatStage(resultSetFuture) - .isSuccess( - resultSet -> { - Iterator rows = resultSet.currentPage().iterator(); - assertThat(rows.hasNext()).isTrue(); - assertThat(rows.next().getString("message")).isEqualTo("hello, world"); - - ExecutionInfo executionInfo = resultSet.getExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node2); - assertThat(executionInfo.getErrors()).hasSize(1); - assertThat(executionInfo.getErrors().get(0).getKey()).isEqualTo(node1); - - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(failureScenario.errorMetric), anyString()); - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(DefaultNodeMetric.RETRIES), anyString()); - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(failureScenario.retryMetric), anyString()); - Mockito.verify(nodeMetricUpdater1, atMost(1)) - .updateTimer( - eq(DefaultNodeMetric.CQL_MESSAGES), - anyString(), - anyLong(), - eq(TimeUnit.NANOSECONDS)); - Mockito.verifyNoMoreInteractions(nodeMetricUpdater1); - }); - } - } - - @Test - @UseDataProvider("failureAndIdempotent") - public void should_try_same_node_if_idempotent_and_retry_policy_decides_so( - FailureScenario failureScenario, - boolean defaultIdempotence, - Statement statement, - DseProtocolVersion version) { - - RequestHandlerTestHarness.Builder harnessBuilder = - continuousHarnessBuilder() - .withProtocolVersion(version) - .withDefaultIdempotence(defaultIdempotence); - failureScenario.mockRequestError(harnessBuilder, node1); - harnessBuilder.withResponse(node1, defaultFrameOf(DseTestFixtures.singleDseRow())); - - try (RequestHandlerTestHarness harness = harnessBuilder.build()) { - failureScenario.mockRetryPolicyVerdict( - harness.getContext().getRetryPolicy(anyString()), RetryVerdict.RETRY_SAME); - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - statement, harness.getSession(), harness.getContext(), "test"); - CompletionStage resultSetFuture = handler.handle(); - - assertThat(handler.getState()).isEqualTo(-1); - - assertThatStage(resultSetFuture) - .isSuccess( - resultSet -> { - Iterator rows = resultSet.currentPage().iterator(); - assertThat(rows.hasNext()).isTrue(); - assertThat(rows.next().getString("message")).isEqualTo("hello, world"); - - ExecutionInfo executionInfo = resultSet.getExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node1); - assertThat(executionInfo.getErrors()).hasSize(1); - assertThat(executionInfo.getErrors().get(0).getKey()).isEqualTo(node1); - - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(failureScenario.errorMetric), anyString()); - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(DefaultNodeMetric.RETRIES), anyString()); - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(failureScenario.retryMetric), anyString()); - Mockito.verify(nodeMetricUpdater1, atMost(2)) - .updateTimer( - eq(DefaultNodeMetric.CQL_MESSAGES), - anyString(), - anyLong(), - eq(TimeUnit.NANOSECONDS)); - Mockito.verifyNoMoreInteractions(nodeMetricUpdater1); - }); - } - } - - @Test - @UseDataProvider("failureAndIdempotent") - public void should_ignore_error_if_idempotent_and_retry_policy_decides_so( - FailureScenario failureScenario, - boolean defaultIdempotence, - Statement statement, - DseProtocolVersion version) { - - RequestHandlerTestHarness.Builder harnessBuilder = - continuousHarnessBuilder() - .withProtocolVersion(version) - .withDefaultIdempotence(defaultIdempotence); - failureScenario.mockRequestError(harnessBuilder, node1); - - try (RequestHandlerTestHarness harness = harnessBuilder.build()) { - failureScenario.mockRetryPolicyVerdict( - harness.getContext().getRetryPolicy(anyString()), RetryVerdict.IGNORE); - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - statement, harness.getSession(), harness.getContext(), "test"); - CompletionStage resultSetFuture = handler.handle(); - - assertThat(handler.getState()).isEqualTo(-1); - - assertThatStage(resultSetFuture) - .isSuccess( - resultSet -> { - Iterator rows = resultSet.currentPage().iterator(); - assertThat(rows.hasNext()).isFalse(); - - ExecutionInfo executionInfo = resultSet.getExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node1); - assertThat(executionInfo.getErrors()).hasSize(0); - - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(failureScenario.errorMetric), anyString()); - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(DefaultNodeMetric.IGNORES), anyString()); - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(failureScenario.ignoreMetric), anyString()); - Mockito.verify(nodeMetricUpdater1, atMost(1)) - .updateTimer( - eq(DefaultNodeMetric.CQL_MESSAGES), - anyString(), - anyLong(), - eq(TimeUnit.NANOSECONDS)); - Mockito.verifyNoMoreInteractions(nodeMetricUpdater1); - }); - } - } - - @Test - @UseDataProvider("failureAndIdempotent") - public void should_rethrow_error_if_idempotent_and_retry_policy_decides_so( - FailureScenario failureScenario, - boolean defaultIdempotence, - Statement statement, - DseProtocolVersion version) { - - RequestHandlerTestHarness.Builder harnessBuilder = - continuousHarnessBuilder() - .withProtocolVersion(version) - .withDefaultIdempotence(defaultIdempotence); - failureScenario.mockRequestError(harnessBuilder, node1); - - try (RequestHandlerTestHarness harness = harnessBuilder.build()) { - - failureScenario.mockRetryPolicyVerdict( - harness.getContext().getRetryPolicy(anyString()), RetryVerdict.RETHROW); - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - statement, harness.getSession(), harness.getContext(), "test"); - CompletionStage resultSetFuture = handler.handle(); - - assertThat(handler.getState()).isEqualTo(-2); - - assertThatStage(resultSetFuture) - .isFailed( - error -> { - assertThat(error).isInstanceOf(failureScenario.expectedExceptionClass); - - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(failureScenario.errorMetric), anyString()); - Mockito.verify(nodeMetricUpdater1, atMost(1)) - .updateTimer( - eq(DefaultNodeMetric.CQL_MESSAGES), - anyString(), - anyLong(), - eq(TimeUnit.NANOSECONDS)); - Mockito.verifyNoMoreInteractions(nodeMetricUpdater1); - }); - } - } - - @Test - @UseDataProvider("failureAndNotIdempotent") - public void should_rethrow_error_if_not_idempotent_and_error_unsafe_or_policy_rethrows( - FailureScenario failureScenario, - boolean defaultIdempotence, - Statement statement, - DseProtocolVersion version) { - - // For two of the possible exceptions, the retry policy is called even if the statement is not - // idempotent - boolean shouldCallRetryPolicy = - (failureScenario.expectedExceptionClass.equals(UnavailableException.class) - || failureScenario.expectedExceptionClass.equals(ReadTimeoutException.class)); - - RequestHandlerTestHarness.Builder harnessBuilder = - continuousHarnessBuilder() - .withProtocolVersion(version) - .withDefaultIdempotence(defaultIdempotence); - failureScenario.mockRequestError(harnessBuilder, node1); - harnessBuilder.withResponse(node2, defaultFrameOf(DseTestFixtures.singleDseRow())); - - try (RequestHandlerTestHarness harness = harnessBuilder.build()) { - - if (shouldCallRetryPolicy) { - failureScenario.mockRetryPolicyVerdict( - harness.getContext().getRetryPolicy(anyString()), RetryVerdict.RETHROW); - } - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - statement, harness.getSession(), harness.getContext(), "test"); - CompletionStage resultSetFuture = handler.handle(); - - assertThat(handler.getState()).isEqualTo(-2); - - assertThatStage(resultSetFuture) - .isFailed( - error -> { - assertThat(error).isInstanceOf(failureScenario.expectedExceptionClass); - // When non idempotent, the policy is bypassed completely: - if (!shouldCallRetryPolicy) { - Mockito.verifyNoMoreInteractions( - harness.getContext().getRetryPolicy(anyString())); - } - - Mockito.verify(nodeMetricUpdater1) - .incrementCounter(eq(failureScenario.errorMetric), anyString()); - Mockito.verify(nodeMetricUpdater1, atMost(1)) - .updateTimer( - eq(DefaultNodeMetric.CQL_MESSAGES), - anyString(), - anyLong(), - eq(TimeUnit.NANOSECONDS)); - Mockito.verifyNoMoreInteractions(nodeMetricUpdater1); - }); - } - } - - /** - * Sets up the mocks to simulate an error from a node, and make the retry policy return a given - * decision for that error. - */ - private abstract static class FailureScenario { - private final Class expectedExceptionClass; - final DefaultNodeMetric errorMetric; - final DefaultNodeMetric retryMetric; - final DefaultNodeMetric ignoreMetric; - - FailureScenario( - Class expectedExceptionClass, - DefaultNodeMetric errorMetric, - DefaultNodeMetric retryMetric, - DefaultNodeMetric ignoreMetric) { - this.expectedExceptionClass = expectedExceptionClass; - this.errorMetric = errorMetric; - this.retryMetric = retryMetric; - this.ignoreMetric = ignoreMetric; - } - - abstract void mockRequestError(RequestHandlerTestHarness.Builder builder, Node node); - - abstract void mockRetryPolicyVerdict(RetryPolicy policy, RetryVerdict verdict); - } - - @DataProvider - public static Object[][] failure() { - return TestDataProviders.fromList( - new FailureScenario( - ReadTimeoutException.class, - DefaultNodeMetric.READ_TIMEOUTS, - DefaultNodeMetric.RETRIES_ON_READ_TIMEOUT, - DefaultNodeMetric.IGNORES_ON_READ_TIMEOUT) { - @Override - public void mockRequestError(RequestHandlerTestHarness.Builder builder, Node node) { - builder.withResponse( - node, - defaultFrameOf( - new ReadTimeout( - "mock message", ProtocolConstants.ConsistencyLevel.LOCAL_ONE, 1, 2, true))); - } - - @Override - public void mockRetryPolicyVerdict(RetryPolicy policy, RetryVerdict verdict) { - when(policy.onReadTimeoutVerdict( - any(SimpleStatement.class), - eq(DefaultConsistencyLevel.LOCAL_ONE), - eq(2), - eq(1), - eq(true), - eq(0))) - .thenReturn(verdict); - } - }, - new FailureScenario( - WriteTimeoutException.class, - DefaultNodeMetric.WRITE_TIMEOUTS, - DefaultNodeMetric.RETRIES_ON_WRITE_TIMEOUT, - DefaultNodeMetric.IGNORES_ON_WRITE_TIMEOUT) { - @Override - public void mockRequestError(RequestHandlerTestHarness.Builder builder, Node node) { - builder.withResponse( - node, - defaultFrameOf( - new WriteTimeout( - "mock message", - ProtocolConstants.ConsistencyLevel.LOCAL_ONE, - 1, - 2, - ProtocolConstants.WriteType.SIMPLE))); - } - - @Override - public void mockRetryPolicyVerdict(RetryPolicy policy, RetryVerdict verdict) { - when(policy.onWriteTimeoutVerdict( - any(SimpleStatement.class), - eq(DefaultConsistencyLevel.LOCAL_ONE), - eq(DefaultWriteType.SIMPLE), - eq(2), - eq(1), - eq(0))) - .thenReturn(verdict); - } - }, - new FailureScenario( - UnavailableException.class, - DefaultNodeMetric.UNAVAILABLES, - DefaultNodeMetric.RETRIES_ON_UNAVAILABLE, - DefaultNodeMetric.IGNORES_ON_UNAVAILABLE) { - @Override - public void mockRequestError(RequestHandlerTestHarness.Builder builder, Node node) { - builder.withResponse( - node, - defaultFrameOf( - new Unavailable( - "mock message", ProtocolConstants.ConsistencyLevel.LOCAL_ONE, 2, 1))); - } - - @Override - public void mockRetryPolicyVerdict(RetryPolicy policy, RetryVerdict verdict) { - when(policy.onUnavailableVerdict( - any(SimpleStatement.class), - eq(DefaultConsistencyLevel.LOCAL_ONE), - eq(2), - eq(1), - eq(0))) - .thenReturn(verdict); - } - }, - new FailureScenario( - ServerError.class, - DefaultNodeMetric.OTHER_ERRORS, - DefaultNodeMetric.RETRIES_ON_OTHER_ERROR, - DefaultNodeMetric.IGNORES_ON_OTHER_ERROR) { - @Override - public void mockRequestError(RequestHandlerTestHarness.Builder builder, Node node) { - builder.withResponse( - node, - defaultFrameOf( - new Error(ProtocolConstants.ErrorCode.SERVER_ERROR, "mock server error"))); - } - - @Override - public void mockRetryPolicyVerdict(RetryPolicy policy, RetryVerdict verdict) { - when(policy.onErrorResponseVerdict( - any(SimpleStatement.class), any(ServerError.class), eq(0))) - .thenReturn(verdict); - } - }, - new FailureScenario( - HeartbeatException.class, - DefaultNodeMetric.ABORTED_REQUESTS, - DefaultNodeMetric.RETRIES_ON_ABORTED, - DefaultNodeMetric.IGNORES_ON_ABORTED) { - @Override - public void mockRequestError(RequestHandlerTestHarness.Builder builder, Node node) { - builder.withResponseFailure(node, Mockito.mock(HeartbeatException.class)); - } - - @Override - public void mockRetryPolicyVerdict(RetryPolicy policy, RetryVerdict verdict) { - when(policy.onRequestAbortedVerdict( - any(SimpleStatement.class), any(HeartbeatException.class), eq(0))) - .thenReturn(verdict); - } - }); - } - - @DataProvider - public static Object[][] failureAndIdempotent() { - return combine(failure(), excludeBatchStatements(idempotentConfig()), allDseProtocolVersions()); - } - - @DataProvider - public static Object[][] failureAndNotIdempotent() { - return combine( - failure(), excludeBatchStatements(nonIdempotentConfig()), allDseProtocolVersions()); - } - - @DataProvider - public static Object[][] allIdempotenceConfigs() { - return combine( - excludeBatchStatements(ContinuousCqlRequestHandlerTestBase.allIdempotenceConfigs()), - allDseProtocolVersions()); - } - - private static Object[][] excludeBatchStatements(Object[][] configs) { - List result = new ArrayList<>(); - for (Object[] config : configs) { - if (!(config[1] instanceof BatchStatement)) { - result.add(config); - } - } - return result.toArray(new Object[][] {}); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerTest.java deleted file mode 100644 index e24579e7fe6..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerTest.java +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import static com.datastax.dse.driver.api.core.DseProtocolVersion.DSE_V1; -import static com.datastax.dse.driver.api.core.DseProtocolVersion.DSE_V2; -import static com.datastax.dse.protocol.internal.DseProtocolConstants.RevisionType.CANCEL_CONTINUOUS_PAGING; -import static com.datastax.dse.protocol.internal.DseProtocolConstants.RevisionType.MORE_CONTINUOUS_PAGES; -import static com.datastax.oss.driver.Assertions.assertThat; -import static com.datastax.oss.driver.Assertions.assertThatStage; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyMap; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.matches; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import com.datastax.dse.driver.DseTestDataProviders; -import com.datastax.dse.driver.DseTestFixtures; -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.dse.protocol.internal.request.Revise; -import com.datastax.oss.driver.api.core.DefaultProtocolVersion; -import com.datastax.oss.driver.api.core.DriverTimeoutException; -import com.datastax.oss.driver.api.core.NoNodeAvailableException; -import com.datastax.oss.driver.api.core.ProtocolVersion; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.Row; -import com.datastax.oss.driver.api.core.cql.SimpleStatement; -import com.datastax.oss.driver.api.core.servererrors.BootstrappingException; -import com.datastax.oss.driver.api.core.session.throttling.RequestThrottler; -import com.datastax.oss.driver.api.core.tracker.RequestTracker; -import com.datastax.oss.driver.internal.core.ProtocolFeature; -import com.datastax.oss.driver.internal.core.cql.PoolBehavior; -import com.datastax.oss.driver.internal.core.cql.RequestHandlerTestHarness; -import com.datastax.oss.driver.internal.core.util.concurrent.CapturingTimer.CapturedTimeout; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import com.datastax.oss.protocol.internal.Message; -import com.datastax.oss.protocol.internal.ProtocolConstants; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.util.Iterator; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; -import java.util.regex.Pattern; -import org.junit.Test; -import org.mockito.Mockito; - -public class ContinuousCqlRequestHandlerTest extends ContinuousCqlRequestHandlerTestBase { - - private static final Pattern LOG_PREFIX_PER_REQUEST = Pattern.compile("test\\|\\d*\\|\\d"); - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_complete_single_page_result(DseProtocolVersion version) { - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withProtocolVersion(version) - .withResponse(node1, defaultFrameOf(DseTestFixtures.singleDseRow())) - .build()) { - - CompletionStage resultSetFuture = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "test") - .handle(); - - assertThatStage(resultSetFuture) - .isSuccess( - resultSet -> { - Iterator rows = resultSet.currentPage().iterator(); - assertThat(rows.hasNext()).isTrue(); - assertThat(rows.next().getString("message")).isEqualTo("hello, world"); - ExecutionInfo executionInfo = resultSet.getExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node1); - assertThat(executionInfo.getErrors()).isEmpty(); - assertThat(executionInfo.getIncomingPayload()).isEmpty(); - assertThat(executionInfo.getPagingState()).isNull(); - assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(executionInfo.getWarnings()).isEmpty(); - }); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_complete_multi_page_result(DseProtocolVersion version) { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(version); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (RequestHandlerTestHarness harness = builder.build()) { - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, harness.getSession(), harness.getContext(), "test"); - CompletionStage page1Future = handler.handle(); - - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(1, false))); - - assertThatStage(page1Future) - .isSuccess( - page1 -> { - assertThat(page1.hasMorePages()).isTrue(); - assertThat(page1.pageNumber()).isEqualTo(1); - Iterator rows = page1.currentPage().iterator(); - assertThat(rows.hasNext()).isTrue(); - assertThat(rows).toIterable().hasSize(10); - ExecutionInfo executionInfo = page1.getExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node1); - assertThat(executionInfo.getErrors()).isEmpty(); - assertThat(executionInfo.getIncomingPayload()).isEmpty(); - assertThat(executionInfo.getPagingState()).isNotNull(); - assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(executionInfo.getWarnings()).isEmpty(); - }); - - ContinuousAsyncResultSet page1 = CompletableFutures.getCompleted(page1Future); - assertThat(handler.getPendingResult()).isNull(); - CompletionStage page2Future = page1.fetchNextPage(); - assertThat(handler.getPendingResult()).isNotNull(); - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(2, true))); - - assertThatStage(page2Future) - .isSuccess( - page2 -> { - assertThat(page2.hasMorePages()).isFalse(); - assertThat(page2.pageNumber()).isEqualTo(2); - Iterator rows = page2.currentPage().iterator(); - assertThat(rows.hasNext()).isTrue(); - assertThat(rows).toIterable().hasSize(10); - ExecutionInfo executionInfo = page2.getExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node1); - assertThat(executionInfo.getErrors()).isEmpty(); - assertThat(executionInfo.getIncomingPayload()).isEmpty(); - assertThat(executionInfo.getPagingState()).isNull(); - assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(executionInfo.getWarnings()).isEmpty(); - }); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_fail_if_no_node_available(DseProtocolVersion version) { - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withProtocolVersion(version) - // Mock no responses => this will produce an empty query plan - .build()) { - - CompletionStage resultSetFuture = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "test") - .handle(); - - assertThatStage(resultSetFuture) - .isFailed(error -> assertThat(error).isInstanceOf(NoNodeAvailableException.class)); - } - } - - @Test - @UseDataProvider(value = "allOssProtocolVersions", location = DseTestDataProviders.class) - public void should_throw_if_protocol_version_does_not_support_continuous_paging( - ProtocolVersion version) { - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder().withProtocolVersion(version).build()) { - Mockito.when( - harness - .getContext() - .getProtocolVersionRegistry() - .supports(any(DefaultProtocolVersion.class), any(ProtocolFeature.class))) - .thenReturn(false); - assertThatThrownBy( - () -> - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "test") - .handle()) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Cannot execute continuous paging requests with protocol version " + version); - } - } - - @Test - public void should_unwind_execution_if_request_setup_fails_before_write() { - RuntimeException failure = new RuntimeException("mock failure"); - SimpleStatement statement = Mockito.spy(SimpleStatement.newInstance("mock query")); - doThrow(failure).when(statement).getCustomPayload(); - RequestThrottler throttler = mock(RequestThrottler.class); - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(DSE_V2); - PoolBehavior node1Behavior = builder.customBehavior(node1); - - try (RequestHandlerTestHarness harness = builder.build()) { - when(harness.getContext().getRequestThrottler()).thenReturn(throttler); - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - statement, harness.getSession(), harness.getContext(), "test"); - CompletionStage resultSetFuture = handler.handle(); - - assertThatThrownBy(() -> handler.onThrottleReady(false)).isSameAs(failure); - - assertThatStage(resultSetFuture).isFailed(error -> assertThat(error).isSameAs(failure)); - assertThat(handler.getActiveExecutionsCount()).isZero(); - assertThat(handler.getInFlightCallbackCount()).isZero(); - node1Behavior.verifyNoWrite(); - node1Behavior.verifyPreAcquireCancelled(); - verify(throttler).signalError(handler, failure); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_time_out_if_first_page_takes_too_long(DseProtocolVersion version) - throws Exception { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(version); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (RequestHandlerTestHarness harness = builder.build()) { - - CompletionStage resultSetFuture = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "test") - .handle(); - - // mark the initial request as successful, which should schedule a timeout for the first page - node1Behavior.setWriteSuccess(); - CapturedTimeout page1Timeout = harness.nextScheduledTimeout(); - assertThat(page1Timeout.getDelay(TimeUnit.NANOSECONDS)) - .isEqualTo(TIMEOUT_FIRST_PAGE.toNanos()); - - page1Timeout.task().run(page1Timeout); - - assertThatStage(resultSetFuture) - .isFailed( - t -> - assertThat(t) - .isInstanceOf(DriverTimeoutException.class) - .hasMessageContaining("Timed out waiting for page 1")); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_time_out_if_other_page_takes_too_long(DseProtocolVersion version) - throws Exception { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(version); - PoolBehavior node1Behavior = builder.customBehavior(node1); - - try (RequestHandlerTestHarness harness = builder.build()) { - - CompletionStage page1Future = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "test") - .handle(); - - // mark the initial request as successful, which should schedule a timeout for the first page - node1Behavior.setWriteSuccess(); - CapturedTimeout page1Timeout = harness.nextScheduledTimeout(); - assertThat(page1Timeout.getDelay(TimeUnit.NANOSECONDS)) - .isEqualTo(TIMEOUT_FIRST_PAGE.toNanos()); - - // the server replies with page 1, the corresponding timeout should be cancelled - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(1, false))); - assertThat(page1Timeout.isCancelled()).isTrue(); - - // request page 2, the queue is empty so this should request more pages and schedule another - // timeout - ContinuousAsyncResultSet page1 = CompletableFutures.getUninterruptibly(page1Future); - CompletionStage page2Future = page1.fetchNextPage(); - CapturedTimeout page2Timeout = harness.nextScheduledTimeout(); - assertThat(page2Timeout.getDelay(TimeUnit.NANOSECONDS)) - .isEqualTo(TIMEOUT_OTHER_PAGES.toNanos()); - - page2Timeout.task().run(page2Timeout); - - assertThatStage(page2Future) - .isFailed( - t -> - assertThat(t) - .isInstanceOf(DriverTimeoutException.class) - .hasMessageContaining("Timed out waiting for page 2")); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_cancel_future_if_session_cancelled(DseProtocolVersion version) { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(version); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (RequestHandlerTestHarness harness = builder.build()) { - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, harness.getSession(), harness.getContext(), "test"); - CompletionStage page1Future = handler.handle(); - - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(1, false))); - // will be discarded - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(2, false))); - - ContinuousAsyncResultSet page1 = CompletableFutures.getUninterruptibly(page1Future); - page1.cancel(); - - assertThat(handler.getState()).isEqualTo(-2); - assertThat(page1.fetchNextPage()).isCancelled(); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_cancel_session_if_future_cancelled(DseProtocolVersion version) { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(version); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (RequestHandlerTestHarness harness = builder.build()) { - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, harness.getSession(), harness.getContext(), "test"); - CompletionStage page1Future = handler.handle(); - - page1Future.toCompletableFuture().cancel(true); - // this should be ignored - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(1, false))); - assertThat(handler.getState()).isEqualTo(-2); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_not_cancel_session_if_future_cancelled_but_already_done( - DseProtocolVersion version) { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(version); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (RequestHandlerTestHarness harness = builder.build()) { - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, harness.getSession(), harness.getContext(), "test"); - CompletionStage page1Future = handler.handle(); - - // this will complete page 1 future - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(1, true))); - - // to late - page1Future.toCompletableFuture().cancel(true); - assertThat(handler.getState()).isEqualTo(-1); - } - } - - @Test - public void should_send_cancel_request_if_dse_v2() { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(DSE_V2); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (RequestHandlerTestHarness harness = builder.build()) { - - ContinuousCqlRequestHandler handler = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, harness.getSession(), harness.getContext(), "test"); - CompletionStage page1Future = handler.handle(); - - page1Future.toCompletableFuture().cancel(true); - assertThat(handler.getState()).isEqualTo(-2); - verify(node1Behavior.getChannel()) - .write(argThat(this::isCancelRequest), anyBoolean(), anyMap(), any()); - } - } - - @Test - public void should_toggle_channel_autoread_if_dse_v1() { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(DSE_V1); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (RequestHandlerTestHarness harness = builder.build()) { - - CompletionStage page1Future = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "test") - .handle(); - - // simulate the arrival of 5 pages, the first one will complete page1 future above, - // the following 4 will be enqueued and should trigger autoread off - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(1, false))); - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(2, false))); - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(3, false))); - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(4, false))); - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(5, false))); - - verify(node1Behavior.getChannel().config()).setAutoRead(false); - - // simulate the retrieval of 2 pages, this should dequeue page 2 - // and trigger autoread on - ContinuousAsyncResultSet page1 = CompletableFutures.getCompleted(page1Future); - CompletableFutures.getCompleted(page1.fetchNextPage()); - - verify(node1Behavior.getChannel().config()).setAutoRead(true); - - // in DSE_V1, the backpressure request should not have been sent - verify(node1Behavior.getChannel(), never()) - .write(any(Revise.class), anyBoolean(), anyMap(), any()); - } - } - - @Test - public void should_send_backpressure_request_if_dse_v2() { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(DSE_V2); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (RequestHandlerTestHarness harness = builder.build()) { - - CompletionStage page1Future = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "test") - .handle(); - - // simulate the arrival of 4 pages, the first one will complete page1 future above, - // the following 3 will be enqueued - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(1, false))); - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(2, false))); - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(3, false))); - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(4, false))); - - // simulate the retrieval of 2 pages, this should dequeue page 2 - // and trigger a backpressure request as the queue is now half empty (2/4) - ContinuousAsyncResultSet page1 = CompletableFutures.getCompleted(page1Future); - CompletableFutures.getCompleted(page1.fetchNextPage()); - - verify(node1Behavior.getChannel()) - .write(argThat(this::isBackpressureRequest), anyBoolean(), anyMap(), any()); - // should not mess with autoread in dse v2 - verify(node1Behavior.getChannel().config(), never()).setAutoRead(anyBoolean()); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_invoke_request_tracker(DseProtocolVersion version) { - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withProtocolVersion(version) - .withResponse( - node1, - defaultFrameOf( - new com.datastax.oss.protocol.internal.response.Error( - ProtocolConstants.ErrorCode.IS_BOOTSTRAPPING, "mock message"))) - .withResponse(node2, defaultFrameOf(DseTestFixtures.singleDseRow())) - .build()) { - - RequestTracker requestTracker = mock(RequestTracker.class); - when(harness.getContext().getRequestTracker()).thenReturn(requestTracker); - - CompletionStage resultSetFuture = - new ContinuousCqlRequestHandler( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "test") - .handle(); - - assertThatStage(resultSetFuture) - .isSuccess( - resultSet -> { - Iterator rows = resultSet.currentPage().iterator(); - assertThat(rows.hasNext()).isTrue(); - assertThat(rows.next().getString("message")).isEqualTo("hello, world"); - ExecutionInfo executionInfo = resultSet.getExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node2); - assertThat(executionInfo.getErrors()).isNotEmpty(); - assertThat(executionInfo.getIncomingPayload()).isEmpty(); - assertThat(executionInfo.getPagingState()).isNull(); - assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(executionInfo.getWarnings()).isEmpty(); - - verify(requestTracker) - .onNodeError( - eq(UNDEFINED_IDEMPOTENCE_STATEMENT), - any(BootstrappingException.class), - anyLong(), - any(DriverExecutionProfile.class), - eq(node1), - matches(LOG_PREFIX_PER_REQUEST)); - verify(requestTracker) - .onNodeSuccess( - eq(UNDEFINED_IDEMPOTENCE_STATEMENT), - anyLong(), - any(DriverExecutionProfile.class), - eq(node2), - matches(LOG_PREFIX_PER_REQUEST)); - verify(requestTracker) - .onSuccess( - eq(UNDEFINED_IDEMPOTENCE_STATEMENT), - anyLong(), - any(DriverExecutionProfile.class), - eq(node2), - matches(LOG_PREFIX_PER_REQUEST)); - verifyNoMoreInteractions(requestTracker); - }); - } - } - - private boolean isBackpressureRequest(Message argument) { - return argument instanceof Revise && ((Revise) argument).revisionType == MORE_CONTINUOUS_PAGES; - } - - private boolean isCancelRequest(Message argument) { - return argument instanceof Revise - && ((Revise) argument).revisionType == CANCEL_CONTINUOUS_PAGING; - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerTestBase.java b/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerTestBase.java deleted file mode 100644 index 04195f5faf0..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/ContinuousCqlRequestHandlerTestBase.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import static com.datastax.dse.driver.api.core.config.DseDriverOption.CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES; -import static com.datastax.dse.driver.api.core.config.DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_FIRST_PAGE; -import static com.datastax.dse.driver.api.core.config.DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES; -import static org.mockito.Mockito.when; - -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.internal.core.cql.CqlRequestHandlerTestBase; -import com.datastax.oss.driver.internal.core.cql.RequestHandlerTestHarness; -import java.time.Duration; - -public abstract class ContinuousCqlRequestHandlerTestBase extends CqlRequestHandlerTestBase { - - static final Duration TIMEOUT_FIRST_PAGE = Duration.ofSeconds(2); - static final Duration TIMEOUT_OTHER_PAGES = Duration.ofSeconds(1); - - protected RequestHandlerTestHarness.Builder continuousHarnessBuilder() { - return new RequestHandlerTestHarness.Builder() { - @Override - public RequestHandlerTestHarness build() { - RequestHandlerTestHarness harness = super.build(); - DriverExecutionProfile config = harness.getContext().getConfig().getDefaultProfile(); - when(config.getDuration(CONTINUOUS_PAGING_TIMEOUT_FIRST_PAGE)) - .thenReturn(TIMEOUT_FIRST_PAGE); - when(config.getDuration(CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES)) - .thenReturn(TIMEOUT_OTHER_PAGES); - when(config.getInt(CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES)).thenReturn(4); - return harness; - } - }; - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousAsyncResultSetTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousAsyncResultSetTest.java deleted file mode 100644 index 1e59559013f..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousAsyncResultSetTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import static com.datastax.oss.driver.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.Row; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.assertj.core.api.ThrowableAssert.ThrowingCallable; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -public class DefaultContinuousAsyncResultSetTest { - - @Mock private ColumnDefinitions columnDefinitions; - @Mock private ExecutionInfo executionInfo; - @Mock private ContinuousCqlRequestHandler handler; - @Mock private CountingIterator rows; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void should_fail_to_fetch_next_page_if_last() { - // Given - given(executionInfo.getPagingState()).willReturn(null); - DefaultContinuousAsyncResultSet resultSet = - new DefaultContinuousAsyncResultSet( - rows, columnDefinitions, 1, false, executionInfo, handler); - - // When - boolean hasMorePages = resultSet.hasMorePages(); - ThrowingCallable nextPage = resultSet::fetchNextPage; - - // Then - assertThat(hasMorePages).isFalse(); - assertThatThrownBy(nextPage) - .isInstanceOf(IllegalStateException.class) - .hasMessageContaining("Can't call fetchNextPage() on the last page"); - } - - @Test - public void should_invoke_handler_to_fetch_next_page() { - // Given - CompletableFuture mockResultFuture = new CompletableFuture<>(); - given(handler.fetchNextPage()).willReturn(mockResultFuture); - DefaultContinuousAsyncResultSet resultSet = - new DefaultContinuousAsyncResultSet( - rows, columnDefinitions, 1, true, executionInfo, handler); - - // When - boolean hasMorePages = resultSet.hasMorePages(); - CompletionStage nextPageFuture = resultSet.fetchNextPage(); - - // Then - assertThat(hasMorePages).isTrue(); - verify(handler).fetchNextPage(); - assertThat(nextPageFuture).isEqualTo(mockResultFuture); - } - - @Test - public void should_invoke_handler_to_cancel() { - // Given - DefaultContinuousAsyncResultSet resultSet = - new DefaultContinuousAsyncResultSet( - rows, columnDefinitions, 1, true, executionInfo, handler); - // When - resultSet.cancel(); - - // Then - verify(handler).cancel(); - } - - @Test - public void should_report_remaining_rows() { - // Given - given(rows.remaining()).willReturn(42); - DefaultContinuousAsyncResultSet resultSet = - new DefaultContinuousAsyncResultSet( - rows, columnDefinitions, 1, true, executionInfo, handler); - - // When - int remaining = resultSet.remaining(); - Iterable currentPage = resultSet.currentPage(); - - // Then - assertThat(remaining).isEqualTo(42); - assertThat(currentPage.iterator()).isSameAs(rows); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousResultSetTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousResultSetTest.java deleted file mode 100644 index 2bfb4768e49..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/DefaultContinuousResultSetTest.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.ResultSet; -import com.datastax.oss.driver.api.core.cql.Row; -import com.datastax.oss.driver.internal.core.util.CountingIterator; -import java.util.Arrays; -import java.util.Iterator; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.Test; -import org.mockito.Mockito; - -public class DefaultContinuousResultSetTest { - - @Test - public void should_create_result_set_from_single_page() { - // Given - ContinuousAsyncResultSet page1 = mockPage(false, 0, 1, 2); - - // When - ResultSet resultSet = new DefaultContinuousResultSet(page1); - - // Then - assertThat(resultSet.getColumnDefinitions()).isSameAs(page1.getColumnDefinitions()); - assertThat(resultSet.getExecutionInfo()).isSameAs(page1.getExecutionInfo()); - assertThat(resultSet.getExecutionInfos()).containsExactly(page1.getExecutionInfo()); - - Iterator iterator = resultSet.iterator(); - - assertNextRow(iterator, 0); - assertNextRow(iterator, 1); - assertNextRow(iterator, 2); - - assertThat(iterator.hasNext()).isFalse(); - } - - @Test - public void should_create_result_set_from_multiple_pages() { - // Given - ContinuousAsyncResultSet page1 = mockPage(true, 0, 1, 2); - ContinuousAsyncResultSet page2 = mockPage(true, 3, 4, 5); - ContinuousAsyncResultSet page3 = mockPage(false, 6, 7, 8); - - complete(page1.fetchNextPage(), page2); - complete(page2.fetchNextPage(), page3); - - // When - ResultSet resultSet = new DefaultContinuousResultSet(page1); - - // Then - assertThat(resultSet.iterator().hasNext()).isTrue(); - - assertThat(resultSet.getColumnDefinitions()).isSameAs(page1.getColumnDefinitions()); - assertThat(resultSet.getExecutionInfo()).isSameAs(page1.getExecutionInfo()); - assertThat(resultSet.getExecutionInfos()).containsExactly(page1.getExecutionInfo()); - - Iterator iterator = resultSet.iterator(); - - assertNextRow(iterator, 0); - assertNextRow(iterator, 1); - assertNextRow(iterator, 2); - - assertThat(iterator.hasNext()).isTrue(); - // This should have triggered the fetch of page2 - assertThat(resultSet.getExecutionInfo()).isEqualTo(page2.getExecutionInfo()); - assertThat(resultSet.getExecutionInfos()) - .containsExactly(page1.getExecutionInfo(), page2.getExecutionInfo()); - - assertNextRow(iterator, 3); - assertNextRow(iterator, 4); - assertNextRow(iterator, 5); - - assertThat(iterator.hasNext()).isTrue(); - // This should have triggered the fetch of page3 - assertThat(resultSet.getExecutionInfo()).isEqualTo(page3.getExecutionInfo()); - assertThat(resultSet.getExecutionInfos()) - .containsExactly( - page1.getExecutionInfo(), page2.getExecutionInfo(), page3.getExecutionInfo()); - - assertNextRow(iterator, 6); - assertNextRow(iterator, 7); - assertNextRow(iterator, 8); - } - - private static ContinuousAsyncResultSet mockPage(boolean nextPage, Integer... data) { - ContinuousAsyncResultSet page = Mockito.mock(ContinuousAsyncResultSet.class); - - ColumnDefinitions columnDefinitions = Mockito.mock(ColumnDefinitions.class); - Mockito.when(page.getColumnDefinitions()).thenReturn(columnDefinitions); - - ExecutionInfo executionInfo = Mockito.mock(ExecutionInfo.class); - Mockito.when(page.getExecutionInfo()).thenReturn(executionInfo); - - if (nextPage) { - Mockito.when(page.hasMorePages()).thenReturn(true); - Mockito.when(page.fetchNextPage()).thenReturn(Mockito.spy(new CompletableFuture<>())); - } else { - Mockito.when(page.hasMorePages()).thenReturn(false); - Mockito.when(page.fetchNextPage()).thenThrow(new IllegalStateException()); - } - - Iterator rows = Arrays.asList(data).iterator(); - CountingIterator iterator = - new CountingIterator(data.length) { - @Override - protected Row computeNext() { - return rows.hasNext() ? mockRow(rows.next()) : endOfData(); - } - }; - Mockito.when(page.currentPage()).thenReturn(() -> iterator); - Mockito.when(page.remaining()).thenAnswer(invocation -> iterator.remaining()); - - return page; - } - - private static Row mockRow(int index) { - Row row = Mockito.mock(Row.class); - Mockito.when(row.getInt(0)).thenReturn(index); - return row; - } - - private static void complete( - CompletionStage stage, ContinuousAsyncResultSet result) { - stage.toCompletableFuture().complete(result); - } - - private static void assertNextRow(Iterator iterator, int expectedValue) { - assertThat(iterator.hasNext()).isTrue(); - Row row0 = iterator.next(); - assertThat(row0.getInt(0)).isEqualTo(expectedValue); - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/ContinuousCqlRequestReactiveProcessorTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/ContinuousCqlRequestReactiveProcessorTest.java deleted file mode 100644 index 0bfb00695d3..00000000000 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/continuous/reactive/ContinuousCqlRequestReactiveProcessorTest.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.internal.core.cql.continuous.reactive; - -import static com.datastax.dse.driver.api.core.DseProtocolVersion.DSE_V1; -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.DseTestDataProviders; -import com.datastax.dse.driver.DseTestFixtures; -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.cql.continuous.reactive.ContinuousReactiveResultSet; -import com.datastax.dse.driver.api.core.cql.reactive.ReactiveRow; -import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousCqlRequestAsyncProcessor; -import com.datastax.dse.driver.internal.core.cql.continuous.ContinuousCqlRequestHandlerTestBase; -import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.datastax.oss.driver.internal.core.cql.PoolBehavior; -import com.datastax.oss.driver.internal.core.cql.RequestHandlerTestHarness; -import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import io.reactivex.Flowable; -import java.util.List; -import org.junit.Test; - -public class ContinuousCqlRequestReactiveProcessorTest extends ContinuousCqlRequestHandlerTestBase { - - @Test - public void should_be_able_to_process_reactive_result_set() { - ContinuousCqlRequestReactiveProcessor processor = - new ContinuousCqlRequestReactiveProcessor(new ContinuousCqlRequestAsyncProcessor()); - assertThat( - processor.canProcess( - UNDEFINED_IDEMPOTENCE_STATEMENT, - ContinuousCqlRequestReactiveProcessor.CONTINUOUS_REACTIVE_RESULT_SET)) - .isTrue(); - } - - @Test - public void should_create_request_handler() { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(DSE_V1); - try (RequestHandlerTestHarness harness = builder.build()) { - ContinuousCqlRequestReactiveProcessor processor = - new ContinuousCqlRequestReactiveProcessor(new ContinuousCqlRequestAsyncProcessor()); - assertThat( - processor.process( - UNDEFINED_IDEMPOTENCE_STATEMENT, - harness.getSession(), - harness.getContext(), - "test")) - .isInstanceOf(DefaultContinuousReactiveResultSet.class); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_complete_single_page_result(DseProtocolVersion version) { - try (RequestHandlerTestHarness harness = - continuousHarnessBuilder() - .withProtocolVersion(version) - .withResponse(node1, defaultFrameOf(DseTestFixtures.singleDseRow())) - .build()) { - - DefaultSession session = harness.getSession(); - InternalDriverContext context = harness.getContext(); - - ContinuousReactiveResultSet publisher = - new ContinuousCqlRequestReactiveProcessor(new ContinuousCqlRequestAsyncProcessor()) - .process(UNDEFINED_IDEMPOTENCE_STATEMENT, session, context, "test"); - - List rows = Flowable.fromPublisher(publisher).toList().blockingGet(); - - assertThat(rows).hasSize(1); - ReactiveRow row = rows.get(0); - assertThat(row.getString("message")).isEqualTo("hello, world"); - ExecutionInfo executionInfo = row.getExecutionInfo(); - assertThat(executionInfo.getCoordinator()).isEqualTo(node1); - assertThat(executionInfo.getErrors()).isEmpty(); - assertThat(executionInfo.getIncomingPayload()).isEmpty(); - assertThat(executionInfo.getPagingState()).isNull(); - assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(executionInfo.getWarnings()).isEmpty(); - - Flowable execInfosFlowable = - Flowable.fromPublisher(publisher.getExecutionInfos()); - assertThat(execInfosFlowable.toList().blockingGet()).containsExactly(executionInfo); - - Flowable colDefsFlowable = - Flowable.fromPublisher(publisher.getColumnDefinitions()); - assertThat(colDefsFlowable.toList().blockingGet()) - .containsExactly(row.getColumnDefinitions()); - - Flowable wasAppliedFlowable = Flowable.fromPublisher(publisher.wasApplied()); - assertThat(wasAppliedFlowable.toList().blockingGet()).containsExactly(row.wasApplied()); - } - } - - @Test - @UseDataProvider(value = "allDseProtocolVersions", location = DseTestDataProviders.class) - public void should_complete_multi_page_result(DseProtocolVersion version) { - RequestHandlerTestHarness.Builder builder = - continuousHarnessBuilder().withProtocolVersion(version); - PoolBehavior node1Behavior = builder.customBehavior(node1); - try (RequestHandlerTestHarness harness = builder.build()) { - - DefaultSession session = harness.getSession(); - InternalDriverContext context = harness.getContext(); - - ContinuousReactiveResultSet publisher = - new ContinuousCqlRequestReactiveProcessor(new ContinuousCqlRequestAsyncProcessor()) - .process(UNDEFINED_IDEMPOTENCE_STATEMENT, session, context, "test"); - - Flowable rowsPublisher = Flowable.fromPublisher(publisher).cache(); - rowsPublisher.subscribe(); - - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(1, false))); - node1Behavior.setResponseSuccess(defaultFrameOf(DseTestFixtures.tenDseRows(2, true))); - - List rows = rowsPublisher.toList().blockingGet(); - assertThat(rows).hasSize(20); - - ReactiveRow first = rows.get(0); - ExecutionInfo firstExecutionInfo = first.getExecutionInfo(); - assertThat(firstExecutionInfo.getCoordinator()).isEqualTo(node1); - assertThat(firstExecutionInfo.getErrors()).isEmpty(); - assertThat(firstExecutionInfo.getIncomingPayload()).isEmpty(); - assertThat(firstExecutionInfo.getPagingState()).isNotNull(); - assertThat(firstExecutionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(firstExecutionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(firstExecutionInfo.getWarnings()).isEmpty(); - - ReactiveRow inSecondPage = rows.get(10); - ExecutionInfo secondExecutionInfo = inSecondPage.getExecutionInfo(); - assertThat(secondExecutionInfo.getCoordinator()).isEqualTo(node1); - assertThat(secondExecutionInfo.getErrors()).isEmpty(); - assertThat(secondExecutionInfo.getIncomingPayload()).isEmpty(); - assertThat(secondExecutionInfo.getPagingState()).isNull(); - assertThat(secondExecutionInfo.getSpeculativeExecutionCount()).isEqualTo(0); - assertThat(secondExecutionInfo.getSuccessfulExecutionIndex()).isEqualTo(0); - assertThat(secondExecutionInfo.getWarnings()).isEmpty(); - - Flowable execInfosFlowable = - Flowable.fromPublisher(publisher.getExecutionInfos()); - assertThat(execInfosFlowable.toList().blockingGet()) - .containsExactly(firstExecutionInfo, secondExecutionInfo); - - Flowable colDefsFlowable = - Flowable.fromPublisher(publisher.getColumnDefinitions()); - assertThat(colDefsFlowable.toList().blockingGet()) - .containsExactly(first.getColumnDefinitions()); - - Flowable wasAppliedFlowable = Flowable.fromPublisher(publisher.wasApplied()); - assertThat(wasAppliedFlowable.toList().blockingGet()).containsExactly(first.wasApplied()); - } - } -} diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/reactive/CqlRequestReactiveProcessorTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/cql/reactive/CqlRequestReactiveProcessorTest.java index a7a6bced9e8..4eb29a400dc 100644 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/cql/reactive/CqlRequestReactiveProcessorTest.java +++ b/core/src/test/java/com/datastax/dse/driver/internal/core/cql/reactive/CqlRequestReactiveProcessorTest.java @@ -18,7 +18,7 @@ package com.datastax.dse.driver.internal.core.cql.reactive; import static com.datastax.dse.driver.DseTestFixtures.singleDseRow; -import static com.datastax.dse.driver.api.core.DseProtocolVersion.DSE_V1; +import static com.datastax.oss.driver.api.core.ProtocolVersion.V4; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -61,7 +61,7 @@ public void should_be_able_to_process_reactive_result_set() { @Test public void should_create_request_handler() { RequestHandlerTestHarness.Builder builder = - RequestHandlerTestHarness.builder().withProtocolVersion(DSE_V1); + RequestHandlerTestHarness.builder().withProtocolVersion(V4); try (RequestHandlerTestHarness harness = builder.build()) { CqlRequestReactiveProcessor processor = new CqlRequestReactiveProcessor(new CqlRequestAsyncProcessor()); @@ -76,7 +76,7 @@ public void should_create_request_handler() { } @Test - @UseDataProvider(value = "allDseAndOssProtocolVersions", location = DseTestDataProviders.class) + @UseDataProvider(value = "allOssProtocolVersions", location = DseTestDataProviders.class) public void should_complete_single_page_result(ProtocolVersion version) { try (RequestHandlerTestHarness harness = RequestHandlerTestHarness.builder() @@ -120,7 +120,7 @@ public void should_complete_single_page_result(ProtocolVersion version) { } @Test - @UseDataProvider(value = "allDseAndOssProtocolVersions", location = DseTestDataProviders.class) + @UseDataProvider(value = "allOssProtocolVersions", location = DseTestDataProviders.class) public void should_complete_multi_page_result(ProtocolVersion version) { RequestHandlerTestHarness.Builder builder = RequestHandlerTestHarness.builder().withProtocolVersion(version); diff --git a/core/src/test/java/com/datastax/dse/driver/internal/core/insights/InsightsClientTest.java b/core/src/test/java/com/datastax/dse/driver/internal/core/insights/InsightsClientTest.java index e9f878fa3f9..9372212b9cf 100644 --- a/core/src/test/java/com/datastax/dse/driver/internal/core/insights/InsightsClientTest.java +++ b/core/src/test/java/com/datastax/dse/driver/internal/core/insights/InsightsClientTest.java @@ -17,12 +17,12 @@ */ package com.datastax.dse.driver.internal.core.insights; -import static com.datastax.dse.driver.api.core.DseProtocolVersion.DSE_V2; import static com.datastax.dse.driver.internal.core.insights.ExecutionProfileMockUtil.mockDefaultExecutionProfile; import static com.datastax.dse.driver.internal.core.insights.ExecutionProfileMockUtil.mockNonDefaultRequestTimeoutExecutionProfile; import static com.datastax.dse.driver.internal.core.insights.PackageUtil.DEFAULT_AUTH_PROVIDER_PACKAGE; import static com.datastax.dse.driver.internal.core.insights.PackageUtil.DEFAULT_LOAD_BALANCING_PACKAGE; import static com.datastax.dse.driver.internal.core.insights.PackageUtil.DEFAULT_SPECULATIVE_EXECUTION_PACKAGE; +import static com.datastax.oss.driver.api.core.DefaultProtocolVersion.V5; import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; @@ -174,7 +174,7 @@ public void should_construct_json_event_startup_message() throws IOException { assertThat(insightData.getInitialControlConnection()).isEqualTo("127.0.0.1:10"); assertThat(insightData.getLocalAddress()).isEqualTo("127.0.0.1"); assertThat(insightData.getHostName()).isNotEmpty(); - assertThat(insightData.getProtocolVersion()).isEqualTo(DSE_V2.getCode()); + assertThat(insightData.getProtocolVersion()).isEqualTo(V5.getCode()); assertThat(insightData.getExecutionProfiles()) .isEqualTo( ImmutableMap.of( @@ -481,7 +481,7 @@ private DefaultDriverContext mockDefaultDriverContext() throws UnknownHostExcept startupOptions.put(StartupOptionsBuilder.DRIVER_NAME_KEY, "DataStax Enterprise Java Driver"); when(context.getStartupOptions()).thenReturn(startupOptions); - when(context.getProtocolVersion()).thenReturn(DSE_V2); + when(context.getProtocolVersion()).thenReturn(V5); DefaultNode contactPoint = mock(DefaultNode.class); EndPoint contactEndPoint = mock(EndPoint.class); when(contactEndPoint.resolve()).thenReturn(new InetSocketAddress("127.0.0.1", 9999)); diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/DefaultProtocolVersionRegistryTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/DefaultProtocolVersionRegistryTest.java index 1d7cc65d1f2..15c0ee5327b 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/DefaultProtocolVersionRegistryTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/DefaultProtocolVersionRegistryTest.java @@ -17,8 +17,6 @@ */ package com.datastax.oss.driver.internal.core; -import static com.datastax.dse.driver.api.core.DseProtocolVersion.DSE_V1; -import static com.datastax.dse.driver.api.core.DseProtocolVersion.DSE_V2; import static com.datastax.oss.driver.api.core.ProtocolVersion.V3; import static com.datastax.oss.driver.api.core.ProtocolVersion.V4; import static com.datastax.oss.driver.api.core.ProtocolVersion.V5; @@ -28,14 +26,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.datastax.dse.driver.api.core.DseProtocolVersion; -import com.datastax.dse.driver.api.core.metadata.DseNodeProperties; import com.datastax.oss.driver.api.core.ProtocolVersion; import com.datastax.oss.driver.api.core.UnsupportedProtocolVersionException; import com.datastax.oss.driver.api.core.Version; import com.datastax.oss.driver.api.core.metadata.Node; import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; import java.util.Optional; import org.junit.Test; import org.mockito.Mockito; @@ -51,17 +46,12 @@ public class DefaultProtocolVersionRegistryTest { @Test public void should_find_version_by_name() { assertThat(registry.fromName("V4")).isEqualTo(ProtocolVersion.V4); - assertThat(registry.fromName("DSE_V1")).isEqualTo(DseProtocolVersion.DSE_V1); } @Test public void should_fail_to_find_version_by_name_different_case() { assertThatThrownBy(() -> registry.fromName("v4")).isInstanceOf(IllegalArgumentException.class); - assertThatThrownBy(() -> registry.fromName("dse_v1")) - .isInstanceOf(IllegalArgumentException.class); - assertThatThrownBy(() -> registry.fromName("dDSE_v1")) - .isInstanceOf(IllegalArgumentException.class); - assertThatThrownBy(() -> registry.fromName("dse_v1")) + assertThatThrownBy(() -> registry.fromName("DSE_V1")) .isInstanceOf(IllegalArgumentException.class); } @@ -77,51 +67,6 @@ public void should_not_downgrade_if_no_lower_version() { assertThat(downgraded.isPresent()).isFalse(); } - @Test - public void should_downgrade_from_dse_to_oss() { - assertThat(registry.downgrade(DseProtocolVersion.DSE_V1).get()).isEqualTo(ProtocolVersion.V5); - } - - @Test - public void should_pick_dse_v2_as_highest_common_when_all_nodes_are_dse_7() { - assertThat(registry.highestCommon(ImmutableList.of(mockDseNode("7.0"), mockDseNode("7.1")))) - .isEqualTo(DseProtocolVersion.DSE_V2); - } - - @Test - public void should_pick_dse_v2_as_highest_common_when_all_nodes_are_dse_6() { - assertThat(registry.highestCommon(ImmutableList.of(mockDseNode("6.0"), mockDseNode("6.1")))) - .isEqualTo(DseProtocolVersion.DSE_V2); - } - - @Test - public void should_pick_dse_v1_as_highest_common_when_all_nodes_are_dse_5_1_or_more() { - assertThat(registry.highestCommon(ImmutableList.of(mockDseNode("5.1"), mockDseNode("6.1")))) - .isEqualTo(DseProtocolVersion.DSE_V1); - } - - @Test - public void should_pick_oss_v4_as_highest_common_when_all_nodes_are_dse_5_or_more() { - assertThat( - registry.highestCommon( - ImmutableList.of(mockDseNode("5.0"), mockDseNode("5.1"), mockDseNode("6.1")))) - .isEqualTo(ProtocolVersion.V4); - } - - @Test - public void should_pick_oss_v3_as_highest_common_when_all_nodes_are_dse_4_7_or_more() { - assertThat( - registry.highestCommon( - ImmutableList.of(mockDseNode("4.7"), mockDseNode("5.1"), mockDseNode("6.1")))) - .isEqualTo(ProtocolVersion.V3); - } - - @Test(expected = UnsupportedProtocolVersionException.class) - public void should_fail_to_pick_highest_common_when_one_node_is_dse_4_6() { - registry.highestCommon( - ImmutableList.of(mockDseNode("4.6"), mockDseNode("5.1"), mockDseNode("6.1"))); - } - @Test(expected = UnsupportedProtocolVersionException.class) public void should_fail_to_pick_highest_common_when_one_node_is_2_0() { registry.highestCommon( @@ -133,8 +78,8 @@ public void should_pick_oss_v3_as_highest_common_when_one_node_is_cassandra_2_1( assertThat( registry.highestCommon( ImmutableList.of( - mockDseNode("5.1"), // oss v4 - mockDseNode("6.1"), // oss v4 + mockCassandraNode("3.11"), // oss v4 + mockCassandraNode("4.0"), // oss v5 mockCassandraNode("2.1") // oss v3 ))) .isEqualTo(ProtocolVersion.V3); @@ -146,8 +91,6 @@ public void should_support_date_type_on_oss_v4_and_later() { assertThat(registry.supports(V4, DATE_TYPE)).isTrue(); assertThat(registry.supports(V5, DATE_TYPE)).isTrue(); assertThat(registry.supports(V6, DATE_TYPE)).isTrue(); - assertThat(registry.supports(DSE_V1, DATE_TYPE)).isTrue(); - assertThat(registry.supports(DSE_V2, DATE_TYPE)).isTrue(); } @Test @@ -156,8 +99,6 @@ public void should_support_smallint_and_tinyint_types_on_oss_v4_and_later() { assertThat(registry.supports(V4, SMALLINT_AND_TINYINT_TYPES)).isTrue(); assertThat(registry.supports(V5, SMALLINT_AND_TINYINT_TYPES)).isTrue(); assertThat(registry.supports(V6, SMALLINT_AND_TINYINT_TYPES)).isTrue(); - assertThat(registry.supports(DSE_V1, SMALLINT_AND_TINYINT_TYPES)).isTrue(); - assertThat(registry.supports(DSE_V2, SMALLINT_AND_TINYINT_TYPES)).isTrue(); } private Node mockCassandraNode(String rawVersion) { @@ -167,29 +108,4 @@ private Node mockCassandraNode(String rawVersion) { } return node; } - - private Node mockDseNode(String rawDseVersion) { - Node node = Mockito.mock(Node.class); - Version dseVersion = Version.parse(rawDseVersion); - Mockito.when(node.getExtras()) - .thenReturn(ImmutableMap.of(DseNodeProperties.DSE_VERSION, dseVersion)); - - Version cassandraVersion; - if (dseVersion.compareTo(DefaultProtocolVersionRegistry.DSE_7_0_0) >= 0) { - cassandraVersion = Version.parse("5.0"); - } else if (dseVersion.compareTo(DefaultProtocolVersionRegistry.DSE_6_0_0) >= 0) { - cassandraVersion = Version.parse("4.0"); - } else if (dseVersion.compareTo(DefaultProtocolVersionRegistry.DSE_5_1_0) >= 0) { - cassandraVersion = Version.parse("3.11"); - } else if (dseVersion.compareTo(DefaultProtocolVersionRegistry.DSE_5_0_0) >= 0) { - cassandraVersion = Version.parse("3.0"); - } else if (dseVersion.compareTo(DefaultProtocolVersionRegistry.DSE_4_7_0) >= 0) { - cassandraVersion = Version.parse("2.1"); - } else { - cassandraVersion = Version.parse("2.0"); - } - Mockito.when(node.getCassandraVersion()).thenReturn(cassandraVersion); - - return node; - } } diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/config/composite/CompositeDriverConfigTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/config/composite/CompositeDriverConfigTest.java index e5d5ffcdf83..e138b33f58b 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/config/composite/CompositeDriverConfigTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/config/composite/CompositeDriverConfigTest.java @@ -20,7 +20,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; -import com.datastax.dse.driver.api.core.config.DseDriverOption; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.api.core.config.DriverConfig; import com.datastax.oss.driver.api.core.config.DriverConfigLoader; @@ -43,10 +42,10 @@ public void setup() { // We need at least one option so that the default profile exists. Do it now to avoid having to // do it in every test. We use an option that we won't reuse in the tests so that there are no // unwanted interactions. - primaryMap.put(TypedDriverOption.CONTINUOUS_PAGING_MAX_PAGES, 1); + primaryMap.put(TypedDriverOption.REQUEST_PAGE_SIZE, 1); fallbackMap = new OptionsMap(); - fallbackMap.put(TypedDriverOption.CONTINUOUS_PAGING_MAX_PAGES, 1); + fallbackMap.put(TypedDriverOption.REQUEST_PAGE_SIZE, 1); DriverConfigLoader compositeLoader = DriverConfigLoader.compose( @@ -66,7 +65,7 @@ public void should_use_value_from_primary_config() { assertThat(compositeDefaultProfile.entrySet()) .containsExactly( entry(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE.getPath(), 1), - entry(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES.getPath(), 1)); + entry(DefaultDriverOption.REQUEST_PAGE_SIZE.getPath(), 1)); } @Test @@ -81,7 +80,7 @@ public void should_ignore_value_from_fallback_config_if_defined_in_both() { assertThat(compositeDefaultProfile.entrySet()) .containsExactly( entry(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE.getPath(), 1), - entry(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES.getPath(), 1)); + entry(DefaultDriverOption.REQUEST_PAGE_SIZE.getPath(), 1)); } @Test @@ -95,7 +94,7 @@ public void should_use_value_from_fallback_config_if_not_defined_in_primary() { assertThat(compositeDefaultProfile.entrySet()) .containsExactly( entry(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE.getPath(), 1), - entry(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES.getPath(), 1)); + entry(DefaultDriverOption.REQUEST_PAGE_SIZE.getPath(), 1)); } @Test @@ -132,16 +131,16 @@ public void should_merge_profiles() { assertThat(compositeConfig.getProfile("onlyInPrimary").entrySet()) .containsExactly( entry(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE.getPath(), 1), - entry(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES.getPath(), 1)); + entry(DefaultDriverOption.REQUEST_PAGE_SIZE.getPath(), 1)); assertThat(compositeConfig.getProfile("inBoth").entrySet()) .containsExactly( entry(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE.getPath(), 2), - entry(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES.getPath(), 1)); + entry(DefaultDriverOption.REQUEST_PAGE_SIZE.getPath(), 1)); assertThat(compositeConfig.getProfile("onlyInFallback").entrySet()) .containsExactly( entry(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE.getPath(), 4), - entry(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES.getPath(), 1)); + entry(DefaultDriverOption.REQUEST_PAGE_SIZE.getPath(), 1)); } } diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/extras/enums/EnumNameCodecTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/extras/enums/EnumNameCodecTest.java index 093ec8a0be8..8d3e022d21f 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/extras/enums/EnumNameCodecTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/extras/enums/EnumNameCodecTest.java @@ -19,7 +19,6 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.datastax.dse.driver.api.core.DseProtocolVersion; import com.datastax.oss.driver.api.core.DefaultProtocolVersion; import com.datastax.oss.driver.api.core.type.codec.ExtraTypeCodecs; import com.datastax.oss.driver.api.core.type.reflect.GenericType; @@ -87,6 +86,5 @@ public void should_accept_raw_type() { @Test public void should_accept_object() { assertThat(codec.accepts(DefaultProtocolVersion.V3)).isTrue(); - assertThat(codec.accepts(DseProtocolVersion.DSE_V1)).isFalse(); } } diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/extras/enums/EnumOrdinalCodecTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/extras/enums/EnumOrdinalCodecTest.java index 7162bc51ff2..c236aeb66b9 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/extras/enums/EnumOrdinalCodecTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/extras/enums/EnumOrdinalCodecTest.java @@ -19,7 +19,6 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.datastax.dse.driver.api.core.DseProtocolVersion; import com.datastax.oss.driver.api.core.DefaultProtocolVersion; import com.datastax.oss.driver.api.core.type.codec.ExtraTypeCodecs; import com.datastax.oss.driver.api.core.type.reflect.GenericType; @@ -92,6 +91,5 @@ public void should_accept_raw_type() { @Test public void should_accept_object() { assertThat(codec.accepts(DefaultProtocolVersion.V3)).isTrue(); - assertThat(codec.accepts(DseProtocolVersion.DSE_V1)).isFalse(); } } diff --git a/core/src/test/resources/config/customApplication.conf b/core/src/test/resources/config/customApplication.conf index c3e3dc7b468..a9681d79563 100644 --- a/core/src/test/resources/config/customApplication.conf +++ b/core/src/test/resources/config/customApplication.conf @@ -18,6 +18,4 @@ datastax-java-driver { // Check that references to other options in `reference.conf` are correctly resolved basic.request.timeout = ${datastax-java-driver.advanced.connection.init-query-timeout} - - advanced.continuous-paging.max-pages = 10 } diff --git a/core/src/test/resources/config/customApplication.json b/core/src/test/resources/config/customApplication.json index 4988a72cd9a..2527d9908d8 100644 --- a/core/src/test/resources/config/customApplication.json +++ b/core/src/test/resources/config/customApplication.json @@ -4,11 +4,6 @@ "request": { "page-size": "2000" } - }, - "advanced": { - "continuous-paging": { - "page-size": 2000 - } } } } diff --git a/core/src/test/resources/config/customApplication.properties b/core/src/test/resources/config/customApplication.properties index 4c1d1ea0647..25fcc5cd058 100644 --- a/core/src/test/resources/config/customApplication.properties +++ b/core/src/test/resources/config/customApplication.properties @@ -17,4 +17,3 @@ # datastax-java-driver.basic.request.consistency=ONE -datastax-java-driver.advanced.continuous-paging.max-enqueued-pages = 8 \ No newline at end of file diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingIT.java deleted file mode 100644 index 45cc84f0719..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingIT.java +++ /dev/null @@ -1,699 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.cql.continuous; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Fail.fail; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.DriverTimeoutException; -import com.datastax.oss.driver.api.core.Version; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.PreparedStatement; -import com.datastax.oss.driver.api.core.cql.Row; -import com.datastax.oss.driver.api.core.cql.SimpleStatement; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; -import com.datastax.oss.driver.api.testinfra.ccm.CcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.datastax.oss.driver.api.testinfra.session.SessionUtils; -import com.datastax.oss.driver.categories.ParallelizableTests; -import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; -import com.datastax.oss.driver.shaded.guava.common.util.concurrent.Uninterruptibles; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.Collections; -import java.util.Iterator; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.RunWith; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.1.0", - description = "Continuous paging is only available from 5.1.0 onwards") -@Category(ParallelizableTests.class) -@RunWith(DataProviderRunner.class) -public class ContinuousPagingIT extends ContinuousPagingITBase { - - private static CcmRule ccmRule = CcmRule.getInstance(); - - private static SessionRule sessionRule = - SessionRule.builder(ccmRule) - .withConfigLoader( - SessionUtils.configLoaderBuilder() - .withStringList( - DefaultDriverOption.METRICS_SESSION_ENABLED, - Collections.singletonList(DseSessionMetric.CONTINUOUS_CQL_REQUESTS.getPath())) - .withStringList( - DefaultDriverOption.METRICS_NODE_ENABLED, - Collections.singletonList(DefaultNodeMetric.CQL_MESSAGES.getPath())) - .build()) - .build(); - - @ClassRule public static TestRule chain = RuleChain.outerRule(ccmRule).around(sessionRule); - - @BeforeClass - public static void setUp() { - initialize(sessionRule.session(), sessionRule.slowProfile()); - } - - /** - * Validates {@link ContinuousSession#executeContinuously(Statement)} with a variety of paging - * options and ensures in all cases the expected number of rows come back. - * - * @test_category queries - * @jira_ticket JAVA-1322 - * @since 1.2.0 - */ - @Test - @UseDataProvider("pagingOptions") - public void should_execute_synchronously(Options options) { - CqlSession session = sessionRule.session(); - SimpleStatement statement = SimpleStatement.newInstance("SELECT v from test where k=?", KEY); - DriverExecutionProfile profile = options.asProfile(session); - ContinuousResultSet result = - session.executeContinuously(statement.setExecutionProfile(profile)); - int i = 0; - for (Row row : result) { - assertThat(row.getInt("v")).isEqualTo(i); - i++; - } - assertThat(i).isEqualTo(options.expectedRows); - validateMetrics(session); - } - - /** - * Validates {@link ContinuousSession#executeContinuously(Statement)} with a variety of paging - * options using a prepared statement and ensures in all cases the expected number of rows come - * back. - * - * @test_category queries - * @jira_ticket JAVA-1322 - * @since 1.2.0 - */ - @Test - @UseDataProvider("pagingOptions") - public void should_execute_prepared_statement_synchronously(Options options) { - CqlSession session = sessionRule.session(); - DriverExecutionProfile profile = options.asProfile(session); - ContinuousResultSet result = - session.executeContinuously(prepared.bind(KEY).setExecutionProfile(profile)); - int i = 0; - for (Row row : result) { - assertThat(row.getInt("v")).isEqualTo(i); - i++; - } - assertThat(i).isEqualTo(options.expectedRows); - validateMetrics(session); - } - - /** - * Validates {@link ContinuousSession#executeContinuouslyAsync(Statement)} with a variety of - * paging options and ensures in all cases the expected number of rows come back and the expected - * number of pages are received. - * - * @test_category queries - * @jira_ticket JAVA-1322 - * @since 1.2.0 - */ - @Test - @UseDataProvider("pagingOptions") - public void should_execute_asynchronously(Options options) { - CqlSession session = sessionRule.session(); - SimpleStatement statement = SimpleStatement.newInstance("SELECT v from test where k=?", KEY); - DriverExecutionProfile profile = options.asProfile(session); - PageStatistics stats = - CompletableFutures.getUninterruptibly( - session - .executeContinuouslyAsync(statement.setExecutionProfile(profile)) - .thenCompose(new AsyncContinuousPagingFunction())); - assertThat(stats.rows).isEqualTo(options.expectedRows); - assertThat(stats.pages).isEqualTo(options.expectedPages); - validateMetrics(session); - } - - /** - * Validates that continuous paging is resilient to a schema change being made in the middle of - * producing pages for the driver if the query was a simple statement. - * - *

Adds a column 'b' after paging the first row in. This column should not be present in the - * in-flight queries' rows, but should be present for subsequent queries. - * - * @test_category queries - * @jira_ticket JAVA-1653 - * @since 1.2.0 - */ - @Test - public void simple_statement_paging_should_be_resilient_to_schema_change() { - CqlSession session = sessionRule.session(); - SimpleStatement simple = SimpleStatement.newInstance("select * from test_prepare"); - DriverExecutionProfile profile = - session - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES, 1) - .withInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, 1) - .withDuration( - DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_FIRST_PAGE, Duration.ofSeconds(30)) - .withDuration( - DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES, Duration.ofSeconds(30)); - ContinuousResultSet result = session.executeContinuously(simple.setExecutionProfile(profile)); - Iterator it = result.iterator(); - // First row should have a non-null values. - Row row0 = it.next(); - assertThat(row0.getString("k")).isNotNull(); - assertThat(row0.isNull("v")).isFalse(); - // Make schema change to add b, its metadata should NOT be present in subsequent rows. - CqlSession schemaChangeSession = - SessionUtils.newSession( - ccmRule, session.getKeyspace().orElseThrow(IllegalStateException::new)); - SimpleStatement statement = - SimpleStatement.newInstance("ALTER TABLE test_prepare add b int") - .setExecutionProfile(sessionRule.slowProfile()); - schemaChangeSession.execute(statement); - schemaChangeSession.checkSchemaAgreement(); - while (it.hasNext()) { - // Each row should have a value for k and v, but b should not be present as it was not part - // of the original metadata. - Row row = it.next(); - assertThat(row.getString("k")).isNotNull(); - assertThat(row.isNull("v")).isFalse(); - assertThat(row.getColumnDefinitions().contains("b")).isFalse(); - } - // Subsequent queries should contain b in metadata since its a new query. - result = session.executeContinuously(simple); - it = result.iterator(); - while (it.hasNext()) { - Row row = it.next(); - assertThat(row.getString("k")).isNotNull(); - assertThat(row.isNull("v")).isFalse(); - // b should be null, but present in metadata. - assertThat(row.isNull("b")).isTrue(); - assertThat(row.getColumnDefinitions().contains("b")).isTrue(); - } - } - - /** - * Validates that continuous paging is resilient to a schema change being made in the middle of - * producing pages for the driver if the query was prepared. - * - *

Drops column 'v' after paging the first row in. This column should still be present in the - * in-flight queries' rows, but it's value should be null. The column should not be present in - * subsequent queries. - * - * @test_category queries - * @jira_ticket JAVA-1653 - * @since 1.2.0 - */ - @Test - public void prepared_statement_paging_should_be_resilient_to_schema_change() { - CqlSession session = sessionRule.session(); - // Create table and prepare select * query against it. - session.execute( - SimpleStatement.newInstance("CREATE TABLE test_prep (k text PRIMARY KEY, v int)") - .setExecutionProfile(SessionUtils.slowProfile(session))); - for (int i = 0; i < 100; i++) { - session.execute(String.format("INSERT INTO test_prep (k, v) VALUES ('foo', %d)", i)); - } - PreparedStatement prepared = session.prepare("SELECT * FROM test_prep WHERE k = ?"); - DriverExecutionProfile profile = - session - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES, 1) - .withInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, 1) - .withDuration( - DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_FIRST_PAGE, Duration.ofSeconds(30)) - .withDuration( - DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES, Duration.ofSeconds(30)); - ContinuousResultSet result = - session.executeContinuously(prepared.bind("foo").setExecutionProfile(profile)); - Iterator it = result.iterator(); - // First row should have a non-null value for v. - Row row0 = it.next(); - assertThat(row0.getString("k")).isNotNull(); - assertThat(row0.isNull("v")).isFalse(); - // Make schema change to drop v, its metadata should be present, values will be null. - CqlSession schemaChangeSession = - SessionUtils.newSession( - ccmRule, session.getKeyspace().orElseThrow(IllegalStateException::new)); - schemaChangeSession.execute( - SimpleStatement.newInstance("ALTER TABLE test_prep DROP v;") - .setExecutionProfile(SessionUtils.slowProfile(schemaChangeSession))); - while (it.hasNext()) { - // Each row should have a value for k, v should still be present, but null since column was - // dropped. - Row row = it.next(); - assertThat(row.getString("k")).isNotNull(); - if (ccmRule.isDistributionOf( - BackendType.DSE, (dist, cass) -> dist.compareTo(Version.parse("6.0.0")) >= 0)) { - // DSE 6 only, v should be null here since dropped. - // Not reliable for 5.1 since we may have gotten page queued before schema changed. - assertThat(row.isNull("v")).isTrue(); - } - assertThat(row.getColumnDefinitions().contains("v")).isTrue(); - } - // Subsequent queries should lack v from metadata as it was dropped. - prepared = session.prepare("SELECT * FROM test_prep WHERE k = ?"); - result = session.executeContinuously(prepared.bind("foo").setExecutionProfile(profile)); - it = result.iterator(); - while (it.hasNext()) { - Row row = it.next(); - assertThat(row.getString("k")).isNotNull(); - assertThat(row.getColumnDefinitions().contains("v")).isFalse(); - } - } - - /** - * Validates that {@link ContinuousResultSet#cancel()} will cancel a continuous paging session by - * setting maxPagesPerSecond to 1 and sending a cancel immediately and ensuring the total number - * of rows iterated over is equal to the size of pageSize. - * - *

Also validates that it is possible to resume the operation using the paging state, as - * described in the javadocs of {@link ContinuousResultSet#cancel()}. - * - * @test_category queries - * @jira_ticket JAVA-1322 - * @since 1.2.0 - */ - @Test - public void should_cancel_with_synchronous_paging() { - CqlSession session = sessionRule.session(); - SimpleStatement statement = SimpleStatement.newInstance("SELECT v from test where k=?", KEY); - // create options and throttle at a page per second so - // cancel can go out before the next page is sent. - // Note that this might not be perfect if there are pauses - // in the JVM and cancel isn't sent soon enough. - DriverExecutionProfile profile = - session - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_ENQUEUED_PAGES, 1) - .withInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, 10) - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, 1); - ContinuousResultSet pagingResult = - session.executeContinuously(statement.setExecutionProfile(profile)); - pagingResult.cancel(); - int i = 0; - for (Row row : pagingResult) { - assertThat(row.getInt("v")).isEqualTo(i); - i++; - } - // Expect only 10 rows as paging was cancelled immediately. - assertThat(i).isEqualTo(10); - // attempt to resume the operation from where we left - ByteBuffer pagingState = pagingResult.getExecutionInfo().getPagingState(); - ContinuousResultSet pagingResultResumed = - session.executeContinuously( - statement - .setExecutionProfile( - profile.withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, 0)) - .setPagingState(pagingState)); - for (Row row : pagingResultResumed) { - assertThat(row.getInt("v")).isEqualTo(i); - i++; - } - assertThat(i).isEqualTo(100); - } - - /** - * Validates that {@link ContinuousAsyncResultSet#cancel()} will cancel a continuous paging - * session by setting maxPagesPerSecond to 1 and sending a cancel after the first page is received - * and then ensuring that the future returned from {@link - * ContinuousAsyncResultSet#fetchNextPage()} fails. - * - *

Also validates that it is possible to resume the operation using the paging state, as - * described in the javadocs of {@link ContinuousAsyncResultSet#cancel()}. - * - * @test_category queries - * @jira_ticket JAVA-1322 - * @since 1.2.0 - */ - @Test - public void should_cancel_with_asynchronous_paging() { - CqlSession session = sessionRule.session(); - SimpleStatement statement = SimpleStatement.newInstance("SELECT v from test where k=?", KEY); - // create options and throttle at a page per second so - // cancel can go out before the next page is sent. - // Note that this might not be perfect if there are pauses - // in the JVM and cancel isn't sent soon enough. - DriverExecutionProfile profile = - session - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, 10) - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, 1); - CompletionStage future = - session.executeContinuouslyAsync(statement.setExecutionProfile(profile)); - ContinuousAsyncResultSet pagingResult = CompletableFutures.getUninterruptibly(future); - // Calling cancel on the previous result should cause the next future to timeout. - pagingResult.cancel(); - CompletionStage fetchNextPageFuture = pagingResult.fetchNextPage(); - try { - // Expect future to fail since it was cancelled. - CompletableFutures.getUninterruptibly(fetchNextPageFuture); - fail("Expected an execution exception since paging was cancelled."); - } catch (CancellationException e) { - assertThat(e) - .hasMessageContaining("Can't get more results") - .hasMessageContaining("query was cancelled"); - } - int i = 0; - for (Row row : pagingResult.currentPage()) { - assertThat(row.getInt("v")).isEqualTo(i); - i++; - } - // Expect only 10 rows as this is the defined page size. - assertThat(i).isEqualTo(10); - // attempt to resume the operation from where we left - ByteBuffer pagingState = pagingResult.getExecutionInfo().getPagingState(); - future = - session.executeContinuouslyAsync( - statement - .setExecutionProfile( - profile.withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, 0)) - .setPagingState(pagingState)); - ContinuousAsyncResultSet pagingResultResumed; - do { - pagingResultResumed = CompletableFutures.getUninterruptibly(future); - for (Row row : pagingResultResumed.currentPage()) { - assertThat(row.getInt("v")).isEqualTo(i); - i++; - } - if (pagingResultResumed.hasMorePages()) { - future = pagingResultResumed.fetchNextPage(); - } - } while (pagingResultResumed.hasMorePages()); - // expect 10 more rows - assertThat(i).isEqualTo(100); - } - - /** - * Validates that {@link ContinuousAsyncResultSet#cancel()} will cancel a continuous paging - * session and current tracked {@link CompletionStage} tied to the paging session. - * - *

Also validates that it is possible to resume the operation using the paging state, as - * described in the javadocs of {@link ContinuousAsyncResultSet#cancel()}. - * - * @test_category queries - * @jira_ticket JAVA-1322 - * @since 1.2.0 - */ - @Test - public void should_cancel_future_when_cancelling_previous_result() { - CqlSession session = sessionRule.session(); - SimpleStatement statement = SimpleStatement.newInstance("SELECT v from test where k=?", KEY); - // create options and throttle at a page per second so - // cancel can go out before the next page is sent. - // Note that this might not be perfect if there are pauses - // in the JVM and cancel isn't sent soon enough. - DriverExecutionProfile profile = - session - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, 10) - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, 1); - CompletionStage future = - session.executeContinuouslyAsync(statement.setExecutionProfile(profile)); - ContinuousAsyncResultSet pagingResult = CompletableFutures.getUninterruptibly(future); - CompletionStage fetchNextPageFuture = pagingResult.fetchNextPage(); - // Calling cancel on the previous result should cause the current future to be cancelled. - pagingResult.cancel(); - assertThat(fetchNextPageFuture.toCompletableFuture().isCancelled()).isTrue(); - try { - // Expect future to be cancelled since the previous result was cancelled. - CompletableFutures.getUninterruptibly(fetchNextPageFuture); - fail("Expected a cancellation exception since previous result was cancelled."); - } catch (CancellationException ce) { - // expected - } - int i = 0; - for (Row row : pagingResult.currentPage()) { - assertThat(row.getInt("v")).isEqualTo(i); - i++; - } - // Expect only 10 rows as this is the defined page size. - assertThat(i).isEqualTo(10); - // attempt to resume the operation from where we left - ByteBuffer pagingState = pagingResult.getExecutionInfo().getPagingState(); - future = - session.executeContinuouslyAsync( - statement - .setExecutionProfile( - profile.withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, 0)) - .setPagingState(pagingState)); - ContinuousAsyncResultSet pagingResultResumed; - do { - pagingResultResumed = CompletableFutures.getUninterruptibly(future); - for (Row row : pagingResultResumed.currentPage()) { - assertThat(row.getInt("v")).isEqualTo(i); - i++; - } - if (pagingResultResumed.hasMorePages()) { - future = pagingResultResumed.fetchNextPage(); - } - } while (pagingResultResumed.hasMorePages()); - // expect 10 more rows - assertThat(i).isEqualTo(100); - } - - /** - * Validates that {@link CompletableFuture#cancel(boolean)} will cancel a continuous paging - * session by setting maxPagesPerSecond to 1 and sending a cancel after the first page is received - * and then ensuring that the future returned from {@link - * ContinuousAsyncResultSet#fetchNextPage()} is cancelled. - * - *

Also validates that it is possible to resume the operation using the paging state, as - * described in the javadocs of {@link ContinuousAsyncResultSet#cancel()}. - * - * @test_category queries - * @jira_ticket JAVA-1322 - * @since 1.2.0 - */ - @Test - public void should_cancel_when_future_is_cancelled() { - CqlSession session = sessionRule.session(); - SimpleStatement statement = SimpleStatement.newInstance("SELECT v from test where k=?", KEY); - // create options and throttle at a page per second so - // cancel can go out before the next page is sent. - // Note that this might not be perfect if there are pauses - // in the JVM and cancel isn't sent soon enough. - DriverExecutionProfile profile = - session - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, 10) - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, 1); - CompletionStage future = - session.executeContinuouslyAsync(statement.setExecutionProfile(profile)); - ContinuousAsyncResultSet pagingResult = CompletableFutures.getUninterruptibly(future); - CompletableFuture fetchNextPageFuture = pagingResult.fetchNextPage().toCompletableFuture(); - fetchNextPageFuture.cancel(false); - assertThat(fetchNextPageFuture.isCancelled()).isTrue(); - try { - // Expect cancellation. - CompletableFutures.getUninterruptibly(fetchNextPageFuture); - fail("Expected a cancellation exception since future was cancelled."); - } catch (CancellationException ce) { - // expected - } - int i = 0; - for (Row row : pagingResult.currentPage()) { - assertThat(row.getInt("v")).isEqualTo(i); - i++; - } - // Expect only 10 rows as this is the defined page size. - assertThat(i).isEqualTo(10); - // attempt to resume the operation from where we left - ByteBuffer pagingState = pagingResult.getExecutionInfo().getPagingState(); - future = - session.executeContinuouslyAsync( - statement - .setExecutionProfile( - profile.withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, 0)) - .setPagingState(pagingState)); - ContinuousAsyncResultSet pagingResultResumed; - do { - pagingResultResumed = CompletableFutures.getUninterruptibly(future); - for (Row row : pagingResultResumed.currentPage()) { - assertThat(row.getInt("v")).isEqualTo(i); - i++; - } - if (pagingResultResumed.hasMorePages()) { - future = pagingResultResumed.fetchNextPage(); - } - } while (pagingResultResumed.hasMorePages()); - // expect 10 more rows - assertThat(i).isEqualTo(100); - } - - /** - * Validates that a client-side timeout is correctly reported to the caller. - * - * @test_category queries - * @jira_ticket JAVA-1390 - * @since 1.2.0 - */ - @Test - public void should_time_out_when_server_does_not_produce_pages_fast_enough() throws Exception { - CqlSession session = sessionRule.session(); - SimpleStatement statement = SimpleStatement.newInstance("SELECT v from test where k=?", KEY); - // Throttle server at a page per second and set client timeout much lower so that the client - // will experience a timeout. - // Note that this might not be perfect if there are pauses in the JVM and the timeout - // doesn't fire soon enough. - DriverExecutionProfile profile = - session - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, 10) - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, 1) - .withDuration( - DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES, Duration.ofMillis(100)); - CompletionStage future = - session.executeContinuouslyAsync(statement.setExecutionProfile(profile)); - ContinuousAsyncResultSet pagingResult = CompletableFutures.getUninterruptibly(future); - try { - pagingResult.fetchNextPage().toCompletableFuture().get(); - fail("Expected a timeout"); - } catch (ExecutionException e) { - assertThat(e.getCause()) - .isInstanceOf(DriverTimeoutException.class) - .hasMessageContaining("Timed out waiting for page 2"); - } - } - - /** - * Validates that the driver behaves appropriately when the client gets behind while paging rows - * in a continuous paging session. The driver should set autoread to false on the channel for that - * connection until the client consumes enough pages, at which point it will reenable autoread and - * continue reading. - * - *

There is not really a direct way to verify that autoread is disabled, but delaying - * immediately after executing a continuous paging query should produce this effect. - * - * @test_category queries - * @jira_ticket JAVA-1375 - * @since 1.2.0 - */ - @Test - public void should_resume_reading_when_client_catches_up() { - CqlSession session = sessionRule.session(); - SimpleStatement statement = - SimpleStatement.newInstance("SELECT * from test_autoread where k=?", KEY); - DriverExecutionProfile profile = - session - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, 100); - CompletionStage result = - session.executeContinuouslyAsync(statement.setExecutionProfile(profile)); - // Defer consuming of rows for a second, this should cause autoread to be disabled. - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - // Start consuming rows, this should cause autoread to be reenabled once we consume some pages. - PageStatistics stats = - CompletableFutures.getUninterruptibly( - result.thenCompose(new AsyncContinuousPagingFunction())); - // 20k rows in this table. - assertThat(stats.rows).isEqualTo(20000); - // 200 * 100 = 20k. - assertThat(stats.pages).isEqualTo(200); - } - - private static class PageStatistics { - int rows; - int pages; - - PageStatistics(int rows, int pages) { - this.rows = rows; - this.pages = pages; - } - } - - /** - * A function that when invoked, will return a transformed future with another {@link - * AsyncContinuousPagingFunction} wrapping {@link ContinuousAsyncResultSet#fetchNextPage()} if - * there are more pages, otherwise returns an immediate future that shares {@link PageStatistics} - * about how many rows were returned and how many pages were encountered. - * - *

Note that if observe that data is not parsed in order this future fails with an Exception. - */ - private static class AsyncContinuousPagingFunction - implements Function> { - - private final int rowsSoFar; - - AsyncContinuousPagingFunction() { - this(0); - } - - AsyncContinuousPagingFunction(int rowsSoFar) { - this.rowsSoFar = rowsSoFar; - } - - @Override - public CompletionStage apply(ContinuousAsyncResultSet input) { - int rows = rowsSoFar; - // Iterate over page and ensure data is in order. - for (Row row : input.currentPage()) { - int v = row.getInt("v"); - if (v != rows) { - fail(String.format("Expected v == %d, got %d.", rows, v)); - } - rows++; - } - // If on last page, complete future, otherwise keep iterating. - if (!input.hasMorePages()) { - // DSE may send an empty page as it can't always know if it's done paging or not yet. - // See: CASSANDRA-8871. In this case, don't count this page. - int pages = rows == rowsSoFar ? input.pageNumber() - 1 : input.pageNumber(); - CompletableFuture future = new CompletableFuture<>(); - future.complete(new PageStatistics(rows, pages)); - return future; - } else { - return input.fetchNextPage().thenCompose(new AsyncContinuousPagingFunction(rows)); - } - } - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingITBase.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingITBase.java deleted file mode 100644 index 4a68454d559..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingITBase.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.cql.continuous; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; - -import com.codahale.metrics.Timer; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.BatchStatement; -import com.datastax.oss.driver.api.core.cql.DefaultBatchType; -import com.datastax.oss.driver.api.core.cql.PreparedStatement; -import com.datastax.oss.driver.api.core.cql.SimpleStatement; -import com.datastax.oss.driver.api.core.metadata.Node; -import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; -import com.datastax.oss.driver.api.core.metrics.Metrics; -import com.tngtech.java.junit.dataprovider.DataProvider; -import java.time.Duration; -import java.util.UUID; - -public abstract class ContinuousPagingITBase { - - protected static final String KEY = "k"; - - static PreparedStatement prepared; - - protected static void initialize(CqlSession session, DriverExecutionProfile slowProfile) { - session.execute( - SimpleStatement.newInstance("CREATE TABLE test (k text, v int, PRIMARY KEY (k, v))") - .setExecutionProfile(slowProfile)); - // Load enough rows to cause TCP Zero Window. Default window size is 65535 bytes, each row - // is at least 48 bytes, so it would take ~1365 enqueued rows to zero window. - // Conservatively load 20k rows. - session.execute( - SimpleStatement.newInstance( - "CREATE TABLE test_autoread (k text, v int, v0 uuid, v1 uuid, PRIMARY KEY (k, v, v0))") - .setExecutionProfile(slowProfile)); - session.execute( - SimpleStatement.newInstance("CREATE TABLE test_prepare (k text PRIMARY KEY, v int)") - .setExecutionProfile(slowProfile)); - session.checkSchemaAgreement(); - prepared = session.prepare("SELECT v from test where k = ?"); - for (int i = 0; i < 100; i++) { - session.execute(String.format("INSERT INTO test (k, v) VALUES ('%s', %d)", KEY, i)); - } - int count = 0; - for (int i = 0; i < 200; i++) { - BatchStatement batch = BatchStatement.newInstance(DefaultBatchType.UNLOGGED); - for (int j = 0; j < 100; j++) { - batch = - batch.add( - SimpleStatement.newInstance( - "INSERT INTO test_autoread (k, v, v0, v1) VALUES (?, ?, ?, ?)", - KEY, - count++, - UUID.randomUUID(), - UUID.randomUUID())); - } - session.execute(batch); - } - for (int i = 0; i < 100; i++) { - session.execute(String.format("INSERT INTO test_prepare (k, v) VALUES ('%d', %d)", i, i)); - } - } - - @DataProvider(format = "%m[%p[0]]") - public static Object[][] pagingOptions() { - return new Object[][] { - // exact # of rows. - {new Options(100, false, 0, 0, 100, 1)}, - // # of rows - 1. - {new Options(99, false, 0, 0, 100, 2)}, - // # of rows / 2. - {new Options(50, false, 0, 0, 100, 2)}, - // # 1 row per page. - {new Options(1, false, 0, 0, 100, 100)}, - // 10 rows per page, 10 pages overall = 100 (exact). - {new Options(10, false, 10, 0, 100, 10)}, - // 10 rows per page, 9 pages overall = 90 (less than exact number of pages). - {new Options(10, false, 9, 0, 90, 9)}, - // 10 rows per page, 2 pages per second should take ~5secs. - {new Options(10, false, 0, 2, 100, 10)}, - // 8 bytes per page == 1 row per page as len(4) + int(4) for each row. - {new Options(8, true, 0, 0, 100, 100)}, - // 16 bytes per page == 2 rows page per page. - {new Options(16, true, 0, 0, 100, 50)}, - // 32 bytes per page == 4 rows per page. - {new Options(32, true, 0, 0, 100, 25)} - }; - } - - protected void validateMetrics(CqlSession session) { - Node node = session.getMetadata().getNodes().values().iterator().next(); - assertThat(session.getMetrics()).as("assert session.getMetrics() present").isPresent(); - Metrics metrics = session.getMetrics().get(); - assertThat(metrics.getNodeMetric(node, DefaultNodeMetric.CQL_MESSAGES)) - .as("assert metrics.getNodeMetric(node, DefaultNodeMetric.CQL_MESSAGES) present") - .isPresent(); - Timer messages = (Timer) metrics.getNodeMetric(node, DefaultNodeMetric.CQL_MESSAGES).get(); - await() - .atMost(Duration.ofSeconds(5)) - .untilAsserted( - () -> { - assertThat(messages.getCount()) - .as("assert messages.getCount() >= 0") - .isGreaterThan(0); - assertThat(messages.getMeanRate()) - .as("assert messages.getMeanRate() >= 0") - .isGreaterThan(0); - }); - assertThat(metrics.getSessionMetric(DseSessionMetric.CONTINUOUS_CQL_REQUESTS)) - .as("assert metrics.getSessionMetric(DseSessionMetric.CONTINUOUS_CQL_REQUESTS) present") - .isPresent(); - Timer requests = - (Timer) metrics.getSessionMetric(DseSessionMetric.CONTINUOUS_CQL_REQUESTS).get(); - await() - .atMost(Duration.ofSeconds(5)) - .untilAsserted( - () -> { - assertThat(requests.getCount()) - .as("assert requests.getCount() >= 0") - .isGreaterThan(0); - assertThat(requests.getMeanRate()) - .as("assert requests.getMeanRate() >= 0") - .isGreaterThan(0); - }); - } - - public static class Options { - public int pageSize; - public boolean sizeInBytes; - public int maxPages; - public int maxPagesPerSecond; - public int expectedRows; - public int expectedPages; - - Options( - int pageSize, - boolean sizeInBytes, - int maxPages, - int maxPagesPerSecond, - int expectedRows, - int expectedPages) { - this.pageSize = pageSize; - this.sizeInBytes = sizeInBytes; - this.maxPages = maxPages; - this.maxPagesPerSecond = maxPagesPerSecond; - this.expectedRows = expectedRows; - this.expectedPages = expectedPages; - } - - public DriverExecutionProfile asProfile(CqlSession session) { - return session - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, pageSize) - .withBoolean(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE_BYTES, sizeInBytes) - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES, maxPages) - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, maxPagesPerSecond); - } - - @Override - public String toString() { - return "pageSize=" - + pageSize - + ", sizeInBytes=" - + sizeInBytes - + ", maxPages=" - + maxPages - + ", maxPagesPerSecond=" - + maxPagesPerSecond - + ", expectedRows=" - + expectedRows - + ", expectedPages=" - + expectedPages; - } - } -} diff --git a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousPagingReactiveIT.java b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousPagingReactiveIT.java deleted file mode 100644 index f2a28d72597..00000000000 --- a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousPagingReactiveIT.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.dse.driver.api.core.cql.continuous.reactive; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousPagingITBase; -import com.datastax.dse.driver.api.core.cql.reactive.ReactiveRow; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.cql.SimpleStatement; -import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; -import com.datastax.oss.driver.api.testinfra.ccm.CcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.datastax.oss.driver.api.testinfra.session.SessionUtils; -import com.datastax.oss.driver.categories.ParallelizableTests; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import io.reactivex.Flowable; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.RunWith; - -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.1.0", - description = "Continuous paging is only available from 5.1.0 onwards") -@Category(ParallelizableTests.class) -@RunWith(DataProviderRunner.class) -public class ContinuousPagingReactiveIT extends ContinuousPagingITBase { - - private static CcmRule ccmRule = CcmRule.getInstance(); - - private static SessionRule sessionRule = - SessionRule.builder(ccmRule) - .withConfigLoader( - SessionUtils.configLoaderBuilder() - .withStringList( - DefaultDriverOption.METRICS_SESSION_ENABLED, - Collections.singletonList(DseSessionMetric.CONTINUOUS_CQL_REQUESTS.getPath())) - .withStringList( - DefaultDriverOption.METRICS_NODE_ENABLED, - Collections.singletonList(DefaultNodeMetric.CQL_MESSAGES.getPath())) - .build()) - .build(); - - @ClassRule public static TestRule chain = RuleChain.outerRule(ccmRule).around(sessionRule); - - @BeforeClass - public static void setUp() { - initialize(sessionRule.session(), sessionRule.slowProfile()); - } - - @Test - @UseDataProvider("pagingOptions") - public void should_execute_reactively(Options options) { - CqlSession session = sessionRule.session(); - SimpleStatement statement = SimpleStatement.newInstance("SELECT v from test where k=?", KEY); - DriverExecutionProfile profile = options.asProfile(session); - ContinuousReactiveResultSet rs = - session.executeContinuouslyReactive(statement.setExecutionProfile(profile)); - List results = Flowable.fromPublisher(rs).toList().blockingGet(); - assertThat(results).hasSize(options.expectedRows); - Set expectedExecInfos = new LinkedHashSet<>(); - for (int i = 0; i < results.size(); i++) { - ReactiveRow row = results.get(i); - assertThat(row.getInt("v")).isEqualTo(i); - expectedExecInfos.add(row.getExecutionInfo()); - } - - List execInfos = - Flowable.fromPublisher(rs.getExecutionInfos()).toList().blockingGet(); - // DSE may send an empty page as it can't always know if it's done paging or not yet. - // See: CASSANDRA-8871. In this case, this page's execution info appears in - // rs.getExecutionInfos(), but is not present in expectedExecInfos since the page did not - // contain any rows. - assertThat(execInfos).containsAll(expectedExecInfos); - - List colDefs = - Flowable.fromPublisher(rs.getColumnDefinitions()).toList().blockingGet(); - ReactiveRow first = results.get(0); - assertThat(colDefs).hasSize(1).containsExactly(first.getColumnDefinitions()); - - List wasApplied = Flowable.fromPublisher(rs.wasApplied()).toList().blockingGet(); - assertThat(wasApplied).hasSize(1).containsExactly(first.wasApplied()); - - validateMetrics(session); - } -} diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/core/ProtocolVersionInitialNegotiationIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/core/ProtocolVersionInitialNegotiationIT.java index a05eff528af..8ae8d4a6cb9 100644 --- a/integration-tests/src/test/java/com/datastax/oss/driver/core/ProtocolVersionInitialNegotiationIT.java +++ b/integration-tests/src/test/java/com/datastax/oss/driver/core/ProtocolVersionInitialNegotiationIT.java @@ -26,7 +26,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; -import com.datastax.dse.driver.api.core.DseProtocolVersion; import com.datastax.oss.driver.api.core.AllNodesFailedException; import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.DefaultProtocolVersion; @@ -54,10 +53,6 @@ public class ProtocolVersionInitialNegotiationIT { minInclusive = "2.1", maxExclusive = "2.2", description = "Only C* in [2.1,2.2[ has V3 as its highest version") - @BackendRequirement( - type = BackendType.DSE, - maxExclusive = "5.0", - description = "Only DSE in [*,5.0[ has V3 as its highest version") @Test public void should_downgrade_to_v3() { try (CqlSession session = SessionUtils.newSession(ccm)) { @@ -71,11 +66,6 @@ public void should_downgrade_to_v3() { minInclusive = "2.2", maxExclusive = "4.0-rc1", description = "Only C* in [2.2,4.0-rc1[ has V4 as its highest version") - @BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0", - maxExclusive = "5.1", - description = "Only DSE in [5.0,5.1[ has V4 as its highest version") @BackendRequirement(type = BackendType.SCYLLA) @Test public void should_downgrade_to_v4() { @@ -97,27 +87,10 @@ public void should_downgrade_to_v5_oss() { } } - @BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.1", - maxExclusive = "6.0", - description = "Only DSE in [5.1,6.0[ has DSE_V1 as its highest version") - @Test - public void should_downgrade_to_dse_v1() { - try (CqlSession session = SessionUtils.newSession(ccm)) { - assertThat(session.getContext().getProtocolVersion()).isEqualTo(DseProtocolVersion.DSE_V1); - session.execute("select * from system.local where key='local'"); - } - } - @BackendRequirement( type = BackendType.CASSANDRA, maxExclusive = "2.2", description = "Only C* in [*,2.2[ has V4 unsupported") - @BackendRequirement( - type = BackendType.DSE, - maxExclusive = "5.0", - description = "Only DSE in [*,5.0[ has V4 unsupported") @Test public void should_fail_if_provided_v4_is_not_supported() { DriverConfigLoader loader = @@ -141,10 +114,6 @@ public void should_fail_if_provided_v4_is_not_supported() { minInclusive = "2.1", maxExclusive = "4.0-rc1", description = "Only C* in [2.1,4.0-rc1[ has V5 unsupported or supported as beta") - @BackendRequirement( - type = BackendType.DSE, - maxExclusive = "7.0", - description = "Only DSE in [*,7.0[ has V5 unsupported or supported as beta") @Test public void should_fail_if_provided_v5_is_not_supported() { DriverConfigLoader loader = @@ -163,50 +132,6 @@ public void should_fail_if_provided_v5_is_not_supported() { } } - @BackendRequirement( - type = BackendType.DSE, - maxExclusive = "5.1", - description = "Only DSE in [*,5.1[ has DSE_V1 unsupported") - @Test - public void should_fail_if_provided_dse_v1_is_not_supported() { - DriverConfigLoader loader = - SessionUtils.configLoaderBuilder() - .withString(DefaultDriverOption.PROTOCOL_VERSION, "DSE_V1") - .build(); - try (CqlSession ignored = SessionUtils.newSession(ccm, loader)) { - fail("Expected an AllNodesFailedException"); - } catch (AllNodesFailedException anfe) { - Throwable cause = anfe.getAllErrors().values().iterator().next().get(0); - assertThat(cause).isInstanceOf(UnsupportedProtocolVersionException.class); - UnsupportedProtocolVersionException unsupportedException = - (UnsupportedProtocolVersionException) cause; - assertThat(unsupportedException.getAttemptedVersions()) - .containsOnly(DseProtocolVersion.DSE_V1); - } - } - - @BackendRequirement( - type = BackendType.DSE, - maxExclusive = "6.0", - description = "Only DSE in [*,6.0[ has DSE_V2 unsupported") - @Test - public void should_fail_if_provided_dse_v2_is_not_supported() { - DriverConfigLoader loader = - SessionUtils.configLoaderBuilder() - .withString(DefaultDriverOption.PROTOCOL_VERSION, "DSE_V2") - .build(); - try (CqlSession ignored = SessionUtils.newSession(ccm, loader)) { - fail("Expected an AllNodesFailedException"); - } catch (AllNodesFailedException anfe) { - Throwable cause = anfe.getAllErrors().values().iterator().next().get(0); - assertThat(cause).isInstanceOf(UnsupportedProtocolVersionException.class); - UnsupportedProtocolVersionException unsupportedException = - (UnsupportedProtocolVersionException) cause; - assertThat(unsupportedException.getAttemptedVersions()) - .containsOnly(DseProtocolVersion.DSE_V2); - } - } - /** Note that this test will need to be updated as new protocol versions are introduced. */ @BackendRequirement( type = BackendType.CASSANDRA, @@ -221,26 +146,10 @@ public void should_not_downgrade_if_server_supports_latest_version() { } /** Note that this test will need to be updated as new protocol versions are introduced. */ - @BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.0", - description = "Only DSE in [6.0,*[ has DSE_V2 supported") - @Test - public void should_not_downgrade_if_server_supports_latest_version_dse() { - try (CqlSession session = SessionUtils.newSession(ccm)) { - assertThat(session.getContext().getProtocolVersion()).isEqualTo(ProtocolVersion.DSE_V2); - session.execute("select * from system.local where key='local'"); - } - } - @BackendRequirement( type = BackendType.CASSANDRA, minInclusive = "2.1", description = "Only C* in [2.1,*[ has V3 supported") - @BackendRequirement( - type = BackendType.DSE, - minInclusive = "4.8", - description = "Only DSE in [4.8,*[ has V3 supported") @BackendRequirement(type = BackendType.SCYLLA) @Test public void should_use_explicitly_provided_v3() { @@ -258,10 +167,6 @@ public void should_use_explicitly_provided_v3() { type = BackendType.CASSANDRA, minInclusive = "2.2", description = "Only C* in [2.2,*[ has V4 supported") - @BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.0", - description = "Only DSE in [5.0,*[ has V4 supported") @BackendRequirement(type = BackendType.SCYLLA) @Test public void should_use_explicitly_provided_v4() { @@ -279,10 +184,6 @@ public void should_use_explicitly_provided_v4() { type = BackendType.CASSANDRA, minInclusive = "4.0", description = "Only C* in [4.0,*[ has V5 supported") - @BackendRequirement( - type = BackendType.DSE, - minInclusive = "7.0", - description = "Only DSE in [7.0,*[ has V5 supported") @Test public void should_use_explicitly_provided_v5() { DriverConfigLoader loader = @@ -294,36 +195,4 @@ public void should_use_explicitly_provided_v5() { session.execute("select * from system.local where key='local'"); } } - - @BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.1", - description = "Only DSE in [5.1,*[ has DSE_V1 supported") - @Test - public void should_use_explicitly_provided_dse_v1() { - DriverConfigLoader loader = - SessionUtils.configLoaderBuilder() - .withString(DefaultDriverOption.PROTOCOL_VERSION, "DSE_V1") - .build(); - try (CqlSession session = SessionUtils.newSession(ccm, loader)) { - assertThat(session.getContext().getProtocolVersion()).isEqualTo(DseProtocolVersion.DSE_V1); - session.execute("select * from system.local where key='local'"); - } - } - - @BackendRequirement( - type = BackendType.DSE, - minInclusive = "6.0", - description = "Only DSE in [6.0,*[ has DSE_V2 supported") - @Test - public void should_use_explicitly_provided_dse_v2() { - DriverConfigLoader loader = - SessionUtils.configLoaderBuilder() - .withString(DefaultDriverOption.PROTOCOL_VERSION, "DSE_V2") - .build(); - try (CqlSession session = SessionUtils.newSession(ccm, loader)) { - assertThat(session.getContext().getProtocolVersion()).isEqualTo(DseProtocolVersion.DSE_V2); - session.execute("select * from system.local where key='local'"); - } - } } diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/core/config/DriverConfigReportingSimulacronIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/core/config/DriverConfigReportingSimulacronIT.java index 262459f84a4..579ca96847a 100644 --- a/integration-tests/src/test/java/com/datastax/oss/driver/core/config/DriverConfigReportingSimulacronIT.java +++ b/integration-tests/src/test/java/com/datastax/oss/driver/core/config/DriverConfigReportingSimulacronIT.java @@ -66,9 +66,9 @@ *

Assertions are scoped to the session's real connections, identified by the {@code CLIENT_ID} * startup option that the driver always sends (independently of config reporting). This excludes * the short-lived connections opened by protocol-version negotiation: when the protocol version is - * not pinned (the default), the driver first tries higher versions (DSE_V2, DSE_V1, V5) that - * ScyllaDB rejects before the handshake completes, and Simulacron records each such rejected - * attempt as a bare {@code STARTUP} ({@code CQL_VERSION} only) that carries no driver identity. + * not pinned (the default), the driver first tries V5, which ScyllaDB rejects before the handshake + * completes, and Simulacron records each such rejected attempt as a bare {@code STARTUP} ({@code + * CQL_VERSION} only) that carries no driver identity. */ @Category(ParallelizableTests.class) public class DriverConfigReportingSimulacronIT { diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/internal/core/util/concurrent/DriverBlockHoundIntegrationCcmIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/internal/core/util/concurrent/DriverBlockHoundIntegrationCcmIT.java deleted file mode 100644 index e0f058b00d0..00000000000 --- a/integration-tests/src/test/java/com/datastax/oss/driver/internal/core/util/concurrent/DriverBlockHoundIntegrationCcmIT.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.datastax.oss.driver.internal.core.util.concurrent; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Fail.fail; - -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousAsyncResultSet; -import com.datastax.dse.driver.api.core.cql.continuous.ContinuousPagingITBase; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.DriverTimeoutException; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.cql.Row; -import com.datastax.oss.driver.api.core.cql.SimpleStatement; -import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; -import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement; -import com.datastax.oss.driver.api.testinfra.requirement.BackendType; -import com.datastax.oss.driver.api.testinfra.session.SessionRule; -import com.datastax.oss.driver.categories.IsolatedTests; -import java.time.Duration; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.ExecutionException; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import reactor.blockhound.BlockHound; -import reactor.core.publisher.Flux; -import reactor.core.scheduler.Schedulers; -import reactor.test.StepVerifier; - -/** - * This test exercises the driver with BlockHound installed and tests that the rules defined in - * {@link DriverBlockHoundIntegration} are being applied, and especially when continuous paging is - * used. - */ -@BackendRequirement( - type = BackendType.DSE, - minInclusive = "5.1.0", - description = "Continuous paging is only available from 5.1.0 onwards") -@Category(IsolatedTests.class) -public class DriverBlockHoundIntegrationCcmIT extends ContinuousPagingITBase { - - private static final Logger LOGGER = - LoggerFactory.getLogger(DriverBlockHoundIntegrationCcmIT.class); - - private static final CustomCcmRule CCM_RULE = CustomCcmRule.builder().build(); - - // Note: Insights monitoring will be detected by BlockHound, but the error is swallowed and - // logged by DefaultSession.SingleThreaded.notifyListeners, so it's not necessary to explicitly - // disable Insights here. - private static final SessionRule SESSION_RULE = SessionRule.builder(CCM_RULE).build(); - - @ClassRule public static TestRule chain = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); - - @BeforeClass - public static void setUp() { - try { - BlockHound.install(); - } catch (Throwable t) { - LOGGER.error("BlockHound could not be installed", t); - fail("BlockHound could not be installed", t); - } - initialize(SESSION_RULE.session(), SESSION_RULE.slowProfile()); - } - - @Test - public void should_not_detect_blocking_call_with_continuous_paging() { - CqlSession session = SESSION_RULE.session(); - SimpleStatement statement = SimpleStatement.newInstance("SELECT v from test where k=?", KEY); - Flux rows = - Flux.range(0, 10) - .flatMap( - i -> - Flux.fromIterable(session.executeContinuously(statement)) - .subscribeOn(Schedulers.parallel())); - StepVerifier.create(rows).expectNextCount(1000).expectComplete().verify(); - } - - /** Copied from com.datastax.dse.driver.api.core.cql.continuous.ContinuousPagingIT. */ - @Test - public void should_not_detect_blocking_call_with_continuous_paging_when_timeout() - throws Exception { - CqlSession session = SESSION_RULE.session(); - SimpleStatement statement = SimpleStatement.newInstance("SELECT v from test where k=?", KEY); - // Throttle server at a page per second and set client timeout much lower so that the client - // will experience a timeout. - // Note that this might not be perfect if there are pauses in the JVM and the timeout - // doesn't fire soon enough. - DriverExecutionProfile profile = - session - .getContext() - .getConfig() - .getDefaultProfile() - .withInt(DseDriverOption.CONTINUOUS_PAGING_PAGE_SIZE, 10) - .withInt(DseDriverOption.CONTINUOUS_PAGING_MAX_PAGES_PER_SECOND, 1) - .withDuration( - DseDriverOption.CONTINUOUS_PAGING_TIMEOUT_OTHER_PAGES, Duration.ofMillis(100)); - CompletionStage future = - session.executeContinuouslyAsync(statement.setExecutionProfile(profile)); - ContinuousAsyncResultSet pagingResult = CompletableFutures.getUninterruptibly(future); - try { - pagingResult.fetchNextPage().toCompletableFuture().get(); - fail("Expected a timeout"); - } catch (ExecutionException e) { - assertThat(e.getCause()) - .isInstanceOf(DriverTimeoutException.class) - .hasMessageContaining("Timed out waiting for page 2"); - } - } -} diff --git a/integration-tests/src/test/resources/application.conf b/integration-tests/src/test/resources/application.conf index 61d06ec8456..93ef32ccf97 100644 --- a/integration-tests/src/test/resources/application.conf +++ b/integration-tests/src/test/resources/application.conf @@ -39,10 +39,6 @@ datastax-java-driver { trace.interval = 1 second warn-if-set-keyspace = false } - continuous-paging.timeout { - first-page = 10 seconds - other-pages = 10 seconds - } metrics { // Raise histogram bounds because the tests execute DDL queries with a higher timeout session.cql_requests.highest_latency = 30 seconds diff --git a/manual/core/native_protocol/README.md b/manual/core/native_protocol/README.md index 42146e63f42..2793445f568 100644 --- a/manual/core/native_protocol/README.md +++ b/manual/core/native_protocol/README.md @@ -52,18 +52,6 @@ first node the driver connects to: *(1) for previous driver versions, see the [3.x documentation][driver3]* -Since version 4.5.0, the driver can also use DSE protocols when all nodes are running a version of -DSE. The table below shows the protocol matrix for these cases: - -| DSE version | Negotiated protocol version with driver 4 | -|---------------------|-------------------------------------------------| -| 4.7/4.8 | v3 | -| 5.0 | v4 | -| 5.1 | DSE_V1 ² | -| 6.0/6.7/6.8 | DSE_V2 ² | - -*(2) DSE Protocols are chosen before other Cassandra native protocols.* - ### Controlling the protocol version To find out which version you're currently using, use the following: diff --git a/manual/core/non_blocking/README.md b/manual/core/non_blocking/README.md index d6b98081645..ddbd603ba81 100644 --- a/manual/core/non_blocking/README.md +++ b/manual/core/non_blocking/README.md @@ -85,22 +85,6 @@ the subscriber. [`ReactiveSession`]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/dse/driver/api/core/cql/reactive/ReactiveSession.html [`executeReactive`]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/dse/driver/api/core/cql/reactive/ReactiveSession.html#executeReactive-com.datastax.oss.driver.api.core.cql.Statement- -There is one exception though: continuous paging queries (a feature specific to DSE) have a special -execution model which uses internal locks for coordination. Although such locks are only held for -extremely brief periods of time, and never under high contention, this execution model doesn't -qualify as lock-free. - -As a consequence, all methods declared in [`ContinuousSession`] and [`ContinuousReactiveSession`] -cannot be considered as implemented 100% lock-free, even those built on top of the asynchronous or -reactive APIs like [`executeContinuouslyAsync`] and [`executeContinuouslyReactive`]. In practice -though, continuous paging is extremely efficient and can safely be used in most non-blocking -contexts, unless they require strict lock-freedom. - -[`ContinuousSession`]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/dse/driver/api/core/cql/continuous/ContinuousSession.html -[`ContinuousReactiveSession`]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousReactiveSession.html -[`executeContinuouslyAsync`]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/dse/driver/api/core/cql/continuous/ContinuousSession.html#executeContinuouslyAsync-com.datastax.oss.driver.api.core.cql.Statement- -[`executeContinuouslyReactive`]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/dse/driver/api/core/cql/continuous/reactive/ContinuousReactiveSession.html#executeContinuouslyReactive-com.datastax.oss.driver.api.core.cql.Statement- - #### Driver lock-free guarantees per session lifecycle phases The guarantees vary according to three possible session states: initializing, running, and closing. @@ -288,9 +272,8 @@ More specifically, the following items are currently declared to be allowed: * Loading of native libraries during startup (`TimestampGenerator`); * Locks held during startup only (`DefaultNettyOptions`, `LazyReference`, `ReplayingEventFilter`); -* Locks held during startup and topology and status events processing (`ChannelSet`, +* Locks held during startup and topology and status events processing (`ChannelSet`, `DistanceReporter`); -* Locks held when executing continuous paging queries; * Locks held during calls to `MutableCodecRegistry.register()` and `Uuids.timeBased()`. The following items are NOT declared to be allowed and are likely to be reported by BlockHound if diff --git a/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java b/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java index 9e898d2ef3c..cf9cf2826c8 100644 --- a/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java +++ b/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java @@ -17,8 +17,6 @@ */ package com.datastax.oss.driver.internal.metrics.micrometer; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; @@ -52,7 +50,6 @@ public MicrometerSessionMetricUpdater( initializeTimer(DefaultSessionMetric.CQL_REQUESTS, profile); initializeTimer(DefaultSessionMetric.THROTTLING_DELAY, profile); - initializeTimer(DseSessionMetric.CONTINUOUS_CQL_REQUESTS, profile); } @Override @@ -102,32 +99,6 @@ protected Timer.Builder configureTimer(Timer.Builder builder, SessionMetric metr configurePercentilesPublishIfDefined( builder, profile, DefaultDriverOption.METRICS_SESSION_THROTTLING_PUBLISH_PERCENTILES); - } else if (metric == DseSessionMetric.CONTINUOUS_CQL_REQUESTS) { - builder - .minimumExpectedValue( - profile.getDuration( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_LOWEST)) - .maximumExpectedValue( - profile.getDuration( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_HIGHEST)) - .serviceLevelObjectives( - profile.isDefined(DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_SLO) - ? profile - .getDurationList( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_SLO) - .toArray(new Duration[0]) - : null) - .percentilePrecision( - profile.isDefined( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_DIGITS) - ? profile.getInt( - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_DIGITS) - : null); - - configurePercentilesPublishIfDefined( - builder, - profile, - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_PUBLISH_PERCENTILES); } return builder; } diff --git a/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java b/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java index 6c77c7f5467..78cab7b830c 100644 --- a/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java +++ b/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java @@ -22,8 +22,6 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; -import com.datastax.dse.driver.api.core.config.DseDriverOption; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.api.core.config.DriverConfig; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; @@ -172,14 +170,6 @@ public static Object[][] timerMetrics() { DefaultDriverOption.METRICS_SESSION_CQL_REQUESTS_SLO, DefaultDriverOption.METRICS_SESSION_CQL_REQUESTS_PUBLISH_PERCENTILES, }, - { - DseSessionMetric.CONTINUOUS_CQL_REQUESTS, - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_LOWEST, - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_HIGHEST, - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_DIGITS, - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_SLO, - DseDriverOption.CONTINUOUS_PAGING_METRICS_SESSION_CQL_REQUESTS_PUBLISH_PERCENTILES - }, { DefaultSessionMetric.THROTTLING_DELAY, DefaultDriverOption.METRICS_SESSION_THROTTLING_LOWEST, diff --git a/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java b/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java index 9fef1240a1f..df0e84c5af6 100644 --- a/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java +++ b/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java @@ -17,7 +17,6 @@ */ package com.datastax.oss.driver.internal.metrics.microprofile; -import com.datastax.dse.driver.api.core.metrics.DseSessionMetric; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; import com.datastax.oss.driver.api.core.metrics.SessionMetric; @@ -48,7 +47,6 @@ public MicroProfileSessionMetricUpdater( initializeTimer(DefaultSessionMetric.CQL_REQUESTS, profile); initializeTimer(DefaultSessionMetric.THROTTLING_DELAY, profile); - initializeTimer(DseSessionMetric.CONTINUOUS_CQL_REQUESTS, profile); } @Override diff --git a/osgi-tests/src/main/resources/application.conf b/osgi-tests/src/main/resources/application.conf index 414121fe4db..c600784dbd3 100644 --- a/osgi-tests/src/main/resources/application.conf +++ b/osgi-tests/src/main/resources/application.conf @@ -33,10 +33,6 @@ datastax-java-driver { trace.interval = 1 second warn-if-set-keyspace = false } - continuous-paging.timeout { - first-page = 10 seconds - other-pages = 10 seconds - } metrics { session.enabled = [cql-requests] // Raise histogram bounds because the tests execute DDL queries with a higher timeout diff --git a/upgrade_guide/README.md b/upgrade_guide/README.md index a976b60c051..af173090012 100644 --- a/upgrade_guide/README.md +++ b/upgrade_guide/README.md @@ -526,13 +526,9 @@ separate DSE driver. The great news is that [reactive execution](../manual/core/reactive/) is now available for everyone. See the `CqlSession.executeReactive` methods. -Apart from that, the only visible change is that DSE-specific features are now exposed in the API: - -* new execution methods: `CqlSession.executeContinuously*`. They have default implementations so - this doesn't break binary compatibility. You can just ignore them. -* new driver dependencies: ESRI and Reactive Streams. If you want to keep your classpath - lean, you can exclude some dependencies when you don't use the corresponding DSE features; see the - [Integration>Driver dependencies](../manual/core/integration/#driver-dependencies) section. +The main visible change is the Reactive Streams dependency. If you want to keep your classpath +lean, you can exclude it when you don't use reactive execution; see the +[Integration>Driver dependencies](../manual/core/integration/#driver-dependencies) section. #### For DataStax Enterprise users