//////////////////////////////////////////////////////////////////////////////// /// DISCLAIMER /// /// Copyright 2016 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 Jan Steemann //////////////////////////////////////////////////////////////////////////////// #ifndef ARANGODB_APPLICATION_FEATURES_APPLICATION_FEATURE_H #define ARANGODB_APPLICATION_FEATURES_APPLICATION_FEATURE_H 1 #include "Basics/Common.h" #include "ApplicationFeatures/ApplicationServer.h" #include "Basics/Exceptions.h" #include namespace arangodb { namespace application_features { class ApplicationFeature { friend class ApplicationServer; public: ApplicationFeature() = delete; ApplicationFeature(ApplicationFeature const&) = delete; ApplicationFeature& operator=(ApplicationFeature const&) = delete; ApplicationFeature(ApplicationServer& server, std::string const& name); virtual ~ApplicationFeature(); // return the feature's name std::string const& name() const { return _name; } bool isOptional() const { return _optional; } bool isRequired() const { return !_optional; } ApplicationServer::FeatureState state() const { return _state; } // whether or not the feature is enabled bool isEnabled() const { return _enabled; } // enable the feature void enable() { setEnabled(true); } // disable the feature entirely. if disabled, the feature's options will be // ignored and no methods apart from `collectOptions` will be called for the // feature void disable() { setEnabled(false); } // disable the feature, and perform no checks if it's optional void forceDisable() { _enabled = false; } // enable or disable a feature void setEnabled(bool value) { if (!value && !isOptional()) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "cannot disable non-optional feature '" + name() + "'"); } _enabled = value; } // names of features required to be enabled for this feature to be enabled std::vector const& requires() const { return _requires; } // register whether the feature requires elevated privileges void requiresElevatedPrivileges(bool value) { _requiresElevatedPrivileges = value; } // test whether the feature requires elevated privileges bool requiresElevatedPrivileges() const { return _requiresElevatedPrivileges; } // whether the feature starts before another bool doesStartBefore(std::string const& other) const; // whether the feature starts after another bool doesStartAfter(std::string const& other) const { return !doesStartBefore(other); } // add the feature's options to the global list of options. this method will // be called regardless of whether to feature is enabled or disabled virtual void collectOptions(std::shared_ptr); // load options from somewhere. this method will only be called for enabled // features virtual void loadOptions(std::shared_ptr, char const* binaryPath); // validate the feature's options. this method will only be called for active // features, after the ApplicationServer has determined which features should // be turned off globally. in order to abort further processing in case of // invalid parameter values, the feature should bail out by calling // FATAL_ERROR_EXIT. virtual void validateOptions(std::shared_ptr); // allows process control virtual void daemonize(); // preparation phase for feature in the preparation phase, the features must // not start any threads. furthermore, they must not write any files under // elevated privileges if they want other features to access them, or if they // want to access these files with dropped privileges virtual void prepare(); // start the feature virtual void start(); // notify the feature about a shutdown request virtual void beginShutdown(); // stop the feature virtual void stop(); // shut down the feature virtual void unprepare(); // return startup dependencies for feature std::unordered_set const& startsAfter() const { return _startsAfter; } // return startup dependencies for feature std::unordered_set const& startsBefore() const { return _startsBefore; } protected: // return the ApplicationServer instance ApplicationServer* server() const { return &_server; } void setOptional() { setOptional(true); } // make the feature optional (or not) void setOptional(bool value) { _optional = value; } // note that this feature requires another to be present void requires(std::string const& other) { _requires.emplace_back(other); } // register a start dependency upon another feature void startsAfter(std::string const& other) { _startsAfter.emplace(other); } // register a start dependency upon another feature void startsBefore(std::string const& other) { _startsBefore.emplace(other); } // determine all direct and indirect ancestors of a feature std::unordered_set ancestors() const; void onlyEnabledWith(std::string const& other) { _onlyEnabledWith.emplace(other); } // return the list of other features that this feature depends on std::unordered_set const& onlyEnabledWith() const { return _onlyEnabledWith; } private: // set a feature's state. this method should be called by the // application server only void state(ApplicationServer::FeatureState state) { _state = state; } // determine all direct and indirect ancestors of a feature void determineAncestors(); // pointer to application server ApplicationServer& _server; // name of feature std::string const _name; // names of other features required to be enabled if this feature // is enabled std::vector _requires; // a list of start dependencies for the feature std::unordered_set _startsAfter; // a list of start dependencies for the feature std::unordered_set _startsBefore; // list of direct and indirect ancestors of the feature std::unordered_set _ancestors; // enable this feature only if the following other features are enabled std::unordered_set _onlyEnabledWith; // state of feature ApplicationServer::FeatureState _state; // whether or not the feature is enabled bool _enabled; // whether or not the feature is optional bool _optional; // whether or not the feature requires elevated privileges bool _requiresElevatedPrivileges; bool _ancestorsDetermined; }; } // namespace application_features } // namespace arangodb #endif