1
0
Fork 0
arangodb/lib/ApplicationFeatures/ApplicationFeature.h

236 lines
7.3 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// 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 <unordered_set>
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();
enum class State {
UNINITIALIZED,
INITIALIZED,
VALIDATED,
PREPARED,
STARTED,
STOPPED,
UNPREPARED
};
// return the feature's name
std::string const& name() const { return _name; }
bool isOptional() const { return _optional; }
bool isRequired() const { return !_optional; }
State 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<std::string> 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<options::ProgramOptions>);
// load options from somewhere. this method will only be called for enabled
// features
virtual void loadOptions(std::shared_ptr<options::ProgramOptions>, 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<options::ProgramOptions>);
// 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<std::string> const& startsAfter() const {
return _startsAfter;
}
// return startup dependencies for feature
std::unordered_set<std::string> 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<std::string> 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<std::string> const& onlyEnabledWith() const {
return _onlyEnabledWith;
}
private:
// set a feature's state. this method should be called by the
// application server only
void state(State 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<std::string> _requires;
// a list of start dependencies for the feature
std::unordered_set<std::string> _startsAfter;
// a list of start dependencies for the feature
std::unordered_set<std::string> _startsBefore;
// list of direct and indirect ancestors of the feature
std::unordered_set<std::string> _ancestors;
// enable this feature only if the following other features are enabled
std::unordered_set<std::string> _onlyEnabledWith;
// state of feature
State _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