diff --git a/arangod/Aql/ExecutionEngine.cpp b/arangod/Aql/ExecutionEngine.cpp index ea30d8680bfd..c21a22bd3741 100644 --- a/arangod/Aql/ExecutionEngine.cpp +++ b/arangod/Aql/ExecutionEngine.cpp @@ -632,6 +632,7 @@ void ExecutionEngine::instantiateFromPlan(Query& query, ExecutionEngine* engine = nullptr; #ifdef USE_ENTERPRISE bool const pushToSingleServer = plan.hasAppliedRule( + // Feature HybridSmartGraphs: Check here. static_cast(OptimizerRule::RuleLevel::clusterOneShardRule)); #else bool const pushToSingleServer = false; diff --git a/tests/Mocks/MockGraph.cpp b/tests/Mocks/MockGraph.cpp index 7dba1cc3273e..221fba80f046 100644 --- a/tests/Mocks/MockGraph.cpp +++ b/tests/Mocks/MockGraph.cpp @@ -88,7 +88,9 @@ void MockGraph::addEdge(size_t from, size_t to, double weight) { } void MockGraph::storeData(TRI_vocbase_t& vocbase, std::string const& vertexCollectionName, - std::string const& edgeCollectionName) const { + std::string const& edgeCollectionName, + std::string const& edgeCollectionSecondName, + std::vector const& secondEdges) const { { // Insert vertices arangodb::OperationOptions options; @@ -111,28 +113,36 @@ void MockGraph::storeData(TRI_vocbase_t& vocbase, std::string const& vertexColle EXPECT_TRUE(added == vertices().size()); } - { - // Insert edges - arangodb::OperationOptions options; - arangodb::SingleCollectionTransaction trx(arangodb::transaction::StandaloneContext::Create(vocbase), - edgeCollectionName, - arangodb::AccessMode::Type::WRITE); - EXPECT_TRUE((trx.begin().ok())); - size_t added = 0; - velocypack::Builder b; - for (auto& edge : edges()) { - b.clear(); - edge.addToBuilder(b); - auto res = trx.insert(edgeCollectionName, b.slice(), options); - if (res.fail()) { - LOG_DEVEL << res.errorMessage() << " " << b.toJson(); + auto insertEdges = [&](std::string const& edgeCollectionToInsert, + std::vector const& edges) -> void { + { + // Insert edges + arangodb::OperationOptions options; + arangodb::SingleCollectionTransaction trx( + arangodb::transaction::StandaloneContext::Create(vocbase), + edgeCollectionToInsert, arangodb::AccessMode::Type::WRITE); + EXPECT_TRUE((trx.begin().ok())); + size_t added = 0; + velocypack::Builder b; + for (auto& edge : edges) { + b.clear(); + edge.addToBuilder(b); + auto res = trx.insert(edgeCollectionToInsert, b.slice(), options); + if (res.fail()) { + LOG_DEVEL << res.errorMessage() << " " << b.toJson(); + } + EXPECT_TRUE((res.ok())); + added++; } - EXPECT_TRUE((res.ok())); - added++; + + EXPECT_TRUE((trx.commit().ok())); + EXPECT_TRUE(added == edges.size()); } + }; - EXPECT_TRUE((trx.commit().ok())); - EXPECT_TRUE(added == edges().size()); + insertEdges(edgeCollectionName, edges()); + if (!edgeCollectionSecondName.empty()) { + insertEdges(edgeCollectionSecondName, secondEdges); } } @@ -166,8 +176,6 @@ void MockGraph::prepareServer(MockCoordinator& server) const { getEdgeShardNameServerPairs(), TRI_COL_TYPE_EDGE); } - - template <> // Future: Also engineID's need to be returned here. std::pair, uint64_t> MockGraph::simulateApi( @@ -184,15 +192,15 @@ std::pair, uint64_t> MockG { // init restaqlhandler arangodb::tests::PreparedRequestResponse prep{server.getSystemDatabase()}; - + // generate and add body here VPackBuilder builder; builder.openObject(); builder.add("lockInfo", VPackValue(VPackValueType::Object)); builder.add("read", VPackValue(VPackValueType::Array)); - // append here the collection names (?) <-- TODO: Check RestAqlHandler.cpp:230 - // builder.add(VPackValue(_vertexCollectionName)); + // append here the collection names (?) <-- TODO: Check + // RestAqlHandler.cpp:230 builder.add(VPackValue(_vertexCollectionName)); // builder.add(VPackValue(_edgeCollectionName)); // appending collection shard ids for (auto const& vShard : _vertexShards) { @@ -201,8 +209,8 @@ std::pair, uint64_t> MockG for (auto const& eShard : _edgeShards) { builder.add(VPackValue(eShard.first)); } - builder.close(); // array READ - builder.close(); // object lockInfo + builder.close(); // array READ + builder.close(); // object lockInfo builder.add("options", VPackValue(VPackValueType::Object)); builder.add("ttl", VPackValue(120)); @@ -216,7 +224,7 @@ std::pair, uint64_t> MockG builder.add("traverserEngines", VPackValue(VPackValueType::Array)); - builder.openObject(); // main container + builder.openObject(); // main container builder.add(VPackValue("options")); @@ -228,25 +236,25 @@ std::pair, uint64_t> MockG builder.add(VPackValue("vertices")); builder.openObject(); - for (auto const& vertexTuple: getVertexShardNameServerPairs()) { + for (auto const& vertexTuple : getVertexShardNameServerPairs()) { builder.add(_vertexCollectionName, VPackValue(VPackValueType::Array)); - builder.add(VPackValue(vertexTuple.first)); // shardID - builder.close(); // inner array + builder.add(VPackValue(vertexTuple.first)); // shardID + builder.close(); // inner array } - builder.close(); // vertices + builder.close(); // vertices builder.add(VPackValue("edges")); builder.openArray(); - for (auto const& edgeTuple: getEdgeShardNameServerPairs()) { + for (auto const& edgeTuple : getEdgeShardNameServerPairs()) { builder.openArray(); - builder.add(VPackValue(edgeTuple.first)); // shardID - builder.close(); // inner array + builder.add(VPackValue(edgeTuple.first)); // shardID + builder.close(); // inner array } - builder.close(); // edges - builder.close(); // shards - builder.close(); // main container - builder.close(); // array traverserEngines + builder.close(); // edges + builder.close(); // shards + builder.close(); // main container + builder.close(); // array traverserEngines builder.close(); // object (outer) prep.addBody(builder.slice()); diff --git a/tests/Mocks/MockGraph.h b/tests/Mocks/MockGraph.h index 3ea12b4cdc9f..5305e9ff3519 100644 --- a/tests/Mocks/MockGraph.h +++ b/tests/Mocks/MockGraph.h @@ -121,9 +121,11 @@ class MockGraph { arangodb::graph::BaseOptions& opts) const; void storeData(TRI_vocbase_t& vocbase, std::string const& vertexCollectionName, - std::string const& edgeCollectionName) const; + std::string const& edgeCollectionName, + std::string const& edgeCollectionSecondName = "", + std::vector const& secondEdges = {}) const; - private: + protected: std::vector> const& getVertexShardNameServerPairs() const { return _vertexShards; } @@ -131,13 +133,13 @@ class MockGraph { return _edgeShards; } - private: + protected: std::vector _edges; std::unordered_set _vertices; - std::string _vertexCollectionName{"v"}; std::string _edgeCollectionName{"e"}; + private: std::vector> _vertexShards{ {"s9870", "PRMR_0001"}}; std::vector> _edgeShards{ diff --git a/tests/Mocks/Servers.cpp b/tests/Mocks/Servers.cpp index a471ddf1d71c..1186a089f54d 100644 --- a/tests/Mocks/Servers.cpp +++ b/tests/Mocks/Servers.cpp @@ -594,23 +594,10 @@ void MockClusterServer::agencyDropDatabase(std::string const& name) { .wait(); } -// Create a clusterWide Collection. -// This does NOT create Shards. -std::shared_ptr MockClusterServer::createCollection( - std::string const& dbName, std::string collectionName, - std::vector> shardNameToServerNamePairs, - TRI_col_type_e type) { - /* - std::string cID, uint64_t shards, - uint64_t replicationFactor, uint64_t writeConcern, - bool waitForRep, velocypack::Slice const& slice, - std::string coordinatorId, RebootId rebootId */ - // This is unsafe - std::string cid = "98765" + basics::StringUtils::itoa(type); - auto& databaseFeature = _server.getFeature(); - auto vocbase = databaseFeature.lookupDatabase(dbName); - - VPackBuilder props; +void MockClusterServer::buildCollectionProperties(VPackBuilder& props, + std::string const& collectionName, + std::string const& cid, TRI_col_type_e type, + VPackSlice additionalProperties) { { // This is hand-crafted unfortunately the code does not exist... VPackObjectBuilder guard(&props); @@ -638,24 +625,18 @@ std::shared_ptr MockClusterServer::createCollection( props.add(toIndex->slice()); } } - } - LogicalCollection dummy(*vocbase, props.slice(), true); - auto shards = std::make_shared(); - for (auto const& [shard, server] : shardNameToServerNamePairs) { - shards->emplace(shard, std::vector{server}); + if (additionalProperties.isObject()) { + props.add(VPackObjectIterator(additionalProperties)); + } } - dummy.setShardMap(shards); - - std::unordered_set const ignoreKeys{ - "allowUserKeys", "cid", "globallyUniqueId", "count", - "planId", "version", "objectId"}; - dummy.setStatus(TRI_VOC_COL_STATUS_LOADED); - VPackBuilder velocy = - dummy.toVelocyPackIgnore(ignoreKeys, LogicalDataSource::Serialization::List); +} +void MockClusterServer::injectCollectionToAgency( + std::string const& dbName, VPackBuilder& velocy, DataSourceId const& planId, + std::vector> shardNameToServerNamePairs) { agencyTrx("/arango/Plan/Collections/" + dbName + "/" + - basics::StringUtils::itoa(dummy.planId().id()), + basics::StringUtils::itoa(planId.id()), velocy.toJson()); { /* Hard-Coded section to inject the CURRENT counter part. @@ -685,7 +666,7 @@ std::shared_ptr MockClusterServer::createCollection( } } agencyTrx("/arango/Current/Collections/" + dbName + "/" + - basics::StringUtils::itoa(dummy.planId().id()), + basics::StringUtils::itoa(planId.id()), current.toJson()); } @@ -698,6 +679,35 @@ std::shared_ptr MockClusterServer::createCollection( .clusterInfo() .waitForCurrent(agencyTrx("/arango/Current/Version", R"=({"op":"increment"})=")) .wait(); +} + +// Create a clusterWide Collection. +// This does NOT create Shards. +std::shared_ptr MockClusterServer::createCollection( + std::string const& dbName, std::string collectionName, + std::vector> shardNameToServerNamePairs, + TRI_col_type_e type, VPackSlice additionalProperties) { + std::string cid = std::to_string(_server.getFeature().clusterInfo().uniqid()); + auto& databaseFeature = _server.getFeature(); + auto vocbase = databaseFeature.lookupDatabase(dbName); + + VPackBuilder props; + buildCollectionProperties(props, collectionName, cid, type, additionalProperties); + LogicalCollection dummy(*vocbase, props.slice(), true); + + auto shards = std::make_shared(); + for (auto const& [shard, server] : shardNameToServerNamePairs) { + shards->emplace(shard, std::vector{server}); + } + dummy.setShardMap(shards); + + std::unordered_set const ignoreKeys{ + "allowUserKeys", "cid", "globallyUniqueId", "count", + "planId", "version", "objectId"}; + dummy.setStatus(TRI_VOC_COL_STATUS_LOADED); + VPackBuilder velocy = + dummy.toVelocyPackIgnore(ignoreKeys, LogicalDataSource::Serialization::List); + injectCollectionToAgency(dbName, velocy, dummy.planId(), shardNameToServerNamePairs); ClusterInfo& clusterInfo = server().getFeature().clusterInfo(); return clusterInfo.getCollection(dbName, collectionName); diff --git a/tests/Mocks/Servers.h b/tests/Mocks/Servers.h index a5133c2a4ac6..2a8c2c94465b 100644 --- a/tests/Mocks/Servers.h +++ b/tests/Mocks/Servers.h @@ -202,7 +202,16 @@ class MockClusterServer : public MockServer, std::shared_ptr createCollection( std::string const& dbName, std::string collectionName, std::vector> shardNameToServerNamePairs, - TRI_col_type_e type); + TRI_col_type_e type, + VPackSlice additionalProperties = VPackSlice{VPackSlice::nullSlice()}); + + void buildCollectionProperties(VPackBuilder& props, std::string const& collectionName, + std::string const& cid, TRI_col_type_e type, + VPackSlice additionalProperties); + + void injectCollectionToAgency(std::string const& dbName, VPackBuilder& velocy, + DataSourceId const& planId, + std::vector> shardNameToServerNamePairs); // You can only create specialized types protected: @@ -213,17 +222,16 @@ class MockClusterServer : public MockServer, // Implementation knows the place when all features are included consensus::index_t agencyTrx(std::string const& key, std::string const& value); void agencyCreateDatabase(std::string const& name); - + // creation of collection is separated // as for DBerver at first maintenance should // create database and only after collections // will be populated in plan. void agencyCreateCollections(std::string const& name); - void agencyDropDatabase(std::string const& name); -protected: + + protected: std::unique_ptr _pool; - private: bool _useAgencyMockPool; arangodb::ServerState::RoleEnum _oldRole; int _dummy;