//////////////////////////////////////////////////////////////////////////////// /// DISCLAIMER /// /// Copyright 2018 ArangoDB GmbH, Cologne, Germany /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// /// @author Tobias Gödderz //////////////////////////////////////////////////////////////////////////////// #ifndef ARANGOD_GRAPH_GRAPH_H #define ARANGOD_GRAPH_GRAPH_H #include #include #include #include #include "Aql/Query.h" #include "Aql/VariableGenerator.h" #include "Basics/ReadWriteLock.h" #include "Cluster/ClusterInfo.h" #include "Cluster/ResultT.h" #include "Transaction/Methods.h" #include "Transaction/StandaloneContext.h" #include "Utils/OperationResult.h" namespace arangodb { namespace graph { class EdgeDefinition { public: EdgeDefinition(std::string edgeCollection_, std::set&& from_, std::set&& to_) : _edgeCollection(std::move(edgeCollection_)), _from(std::move(from_)), _to(std::move(to_)) {} std::string const& getName() const { return _edgeCollection; } void setName(std::string const& newName) { _edgeCollection = newName; } std::set const& getFrom() const { return _from; } std::set const& getTo() const { return _to; } /// @brief Adds the edge definition as a new object {collection, from, to} /// to the builder. void addToBuilder(velocypack::Builder& builder) const; bool hasFrom(std::string const& vertexCollection) const; bool hasTo(std::string const& vertexCollection) const; /// @brief validate the structure of edgeDefinition, i.e. /// that it contains the correct attributes, and that they contain the correct /// types of values. static Result validateEdgeDefinition(const velocypack::Slice& edgeDefinition); static ResultT createFromVelocypack(velocypack::Slice edgeDefinition); void toVelocyPack(velocypack::Builder&) const; bool operator==(EdgeDefinition const& other) const; bool operator!=(EdgeDefinition const& other) const; bool isVertexCollectionUsed(std::string const& collectionName) const; bool isFromVertexCollectionUsed(std::string const& collectionName) const; bool isToVertexCollectionUsed(std::string const& collectionName) const; bool renameCollection(std::string const& oldName, std::string const& newName); private: std::string _edgeCollection; std::set _from; std::set _to; }; class Graph { public: /** * @brief Create graph from persistence. * * @param document The stored document * * @return A graph object corresponding to this document */ static std::unique_ptr fromPersistence(velocypack::Slice document, TRI_vocbase_t& vocbase); /** * @brief Create graph from user input. * NOTE: This is purely in memory and will NOT persist anything. * * @param name The name of the Graph * @param collectionInformation Collection information about relations and * orphans * @param options The collection creation options. * * @return A graph object corresponding to the user input */ static std::unique_ptr fromUserInput(std::string&& name, velocypack::Slice collectionInformation, velocypack::Slice options); // Wrapper for Move constructor static std::unique_ptr fromUserInput(std::string const& name, velocypack::Slice collectionInformation, velocypack::Slice options); protected: /** * @brief Create graph from persistence. * * @param info The stored document */ explicit Graph(velocypack::Slice const& info); /** * @brief Create graph from user input. * * @param graphName The name of the graph * @param info Collection information, including relations and orphans * @param options The options to be used for collections */ Graph(std::string&& graphName, velocypack::Slice const& info, velocypack::Slice const& options); public: virtual ~Graph() = default; static Result validateOrphanCollection(const velocypack::Slice& orphanDefinition); virtual void createCollectionOptions(VPackBuilder& builder, bool waitForSync) const; public: /// @brief get the cids of all vertexCollections std::set const& vertexCollections() const; /// @brief get the cids of all orphanCollections std::set const& orphanCollections() const; /// @brief get the cids of all edgeCollections std::set const& edgeCollections() const; /// @brief get the cids of all edgeCollections std::map const& edgeDefinitions() const; /// @brief get the cids of all edgeCollections as reference std::map& edgeDefinitions(); bool hasEdgeCollection(std::string const& collectionName) const; bool hasVertexCollection(std::string const& collectionName) const; bool hasOrphanCollection(std::string const& collectionName) const; bool renameCollections(std::string const& oldName, std::string const& newName); boost::optional getEdgeDefinition(std::string const& collectionName) const; virtual bool isSmart() const; uint64_t numberOfShards() const; uint64_t replicationFactor() const; uint64_t minReplicationFactor() const; std::string const id() const; std::string const& rev() const; std::string const& name() const { return _graphName; } /// @brief return a VelocyPack representation of the graph void toVelocyPack(velocypack::Builder&) const; /** * @brief Create the GraphDocument to be stored in the database. * * @param builder The builder the result should be written in. Expects an open * object. */ virtual void toPersistence(velocypack::Builder& builder) const; /** * @brief Create the Graph Json Representation to be given to the client. * Uses toPersistence, but also includes _rev and _id values and * encapsulates the date into a graph attribute. * * @param builder The builder the result should be written in. Expects an open * object. */ void graphForClient(VPackBuilder& builder) const; /** * @brief Check if the collection is allowed to be used * within this graph * * @param col The collection * * @return TRUE if we are safe to use it. */ virtual Result validateCollection(LogicalCollection& col) const; void edgesToVpack(VPackBuilder& builder) const; void verticesToVpack(VPackBuilder& builder) const; virtual void enhanceEngineInfo(velocypack::Builder&) const; /// @brief adds one edge definition. Returns an error if the edgeDefinition /// is already added to this graph. ResultT addEdgeDefinition(velocypack::Slice const& edgeDefinitionSlice); /// @brief adds one edge definition. Returns an error if the edgeDefinition /// is already added to this graph. ResultT addEdgeDefinition(EdgeDefinition const& edgeDefinition); /// @brief removes one edge definition. Returns an error if the edgeDefinition /// is not included in this graph. bool removeEdgeDefinition(std::string const& edgeDefinitionName); /// @brief replaces one edge definition. Returns an error if the /// edgeDefinition /// is not included in this graph. Result replaceEdgeDefinition(EdgeDefinition const& edgeDefinition); /// @brief Rebuild orphan collections. Needs to be called after every /// removal or change of an existing an edgeDefinition. void rebuildOrphans(EdgeDefinition const& oldEdgeDefinition); /// @brief Removes an orphan vertex collection from the graphs definition Result removeOrphanCollection(std::string&&); /// @brief Add an orphan vertex collection to this graphs definition Result addOrphanCollection(std::string&&); std::ostream& operator<<(std::ostream& ostream); private: /// @brief Parse the edgeDefinition slice and inject it into this graph void parseEdgeDefinitions(velocypack::Slice edgeDefs); /// @brief Add a vertex collection to this graphs definition void addVertexCollection(std::string const&); /// @brief Add orphanCollections to the object void insertOrphanCollections(velocypack::Slice arr); /// @brief Set numberOfShards to the graph definition void setNumberOfShards(uint64_t numberOfShards); /// @brief Set replicationFactor to the graph definition void setReplicationFactor(uint64_t setReplicationFactor); /// @brief Set minReplicationFactor to the graph definition void setMinReplicationFactor(uint64_t setMinReplicationFactor); /// @brief Set rev to the graph definition void setRev(std::string&& rev); ///////////////////////////////////////////////////////////////////////////////// // // SECTION: Variables // ///////////////////////////////////////////////////////////////////////////////// protected: /// @brief name of this graph std::string const _graphName; /// @brief the names of all vertexCollections /// This includes orphans. std::set _vertexColls; /// @brief the names of all orphanCollections std::set _orphanColls; /// @brief the names of all edgeCollections std::set _edgeColls; /// @brief edge definitions of this graph std::map _edgeDefs; /// @brief number of shards of this graph uint64_t _numberOfShards; /// @brief replication factor of this graph uint64_t _replicationFactor; /// @brief minimal replication factor of this graph uint64_t _minReplicationFactor; /// @brief revision of this graph std::string _rev; }; // helper functions template void setUnion(std::set& set, C const& container) { for (auto const& it : container) { set.insert(it); } } } // namespace graph } // namespace arangodb #endif // ARANGOD_GRAPH_GRAPH_H