源码 ServerParameter

总结 

1、

服务器参数类型和设置时刻

 

 

https://github.com/mongodb/mongo/blob/master/src/mongo/db/server_parameters.h

 

// server_parameters.h


/**
 *    Copyright (C) 2018-present MongoDB, Inc.
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the Server Side Public License, version 1,
 *    as published by MongoDB, Inc.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    Server Side Public License for more details.
 *
 *    You should have received a copy of the Server Side Public License
 *    along with this program. If not, see
 *    <http://www.mongodb.com/licensing/server-side-public-license>.
 *
 *    As a special exception, the copyright holders give permission to link the
 *    code of portions of this program with the OpenSSL library under certain
 *    conditions as described in each individual source file and distribute
 *    linked combinations including the program with the OpenSSL library. You
 *    must comply with the Server Side Public License in all respects for
 *    all of the code used other than as permitted herein. If you modify file(s)
 *    with this exception, you may extend this exception to your version of the
 *    file(s), but you are not obligated to do so. If you do not wish to do so,
 *    delete this exception statement from your version. If you delete this
 *    exception statement from all source files in the program, then also delete
 *    it in the license file.
 */

#pragma once

#include <map>
#include <string>
#include <vector>

#include "mongo/base/static_assert.h"
#include "mongo/base/status.h"
#include "mongo/db/jsobj.h"
#include "mongo/platform/atomic_proxy.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/platform/compiler.h"
#include "mongo/stdx/functional.h"
#include "mongo/stdx/mutex.h"
#include "mongo/util/stringutils.h"

namespace mongo {

class ServerParameterSet;
class OperationContext;

/**
 * Lets you make server level settings easily configurable.
 * Hooks into (set|get)Parameter, as well as command line processing
 *
 * NOTE: ServerParameters set at runtime can be read or written to at anytime, and are not
 * thread-safe without atomic types or other concurrency techniques.
 */
class ServerParameter {
public:
    typedef std::map<std::string, ServerParameter*> Map;

    ServerParameter(ServerParameterSet* sps,
                    StringData name,
                    bool allowedToChangeAtStartup,
                    bool allowedToChangeAtRuntime);
    ServerParameter(ServerParameterSet* sps, StringData name);
    virtual ~ServerParameter();

    std::string name() const {
        return _name;
    }

    /**
     * @return if you can set on command line or config file
     */
    bool allowedToChangeAtStartup() const {
        return _allowedToChangeAtStartup;
    }

    /**
     * @param if you can use (get|set)Parameter
     */
    bool allowedToChangeAtRuntime() const {
        return _allowedToChangeAtRuntime;
    }


    virtual void append(OperationContext* opCtx, BSONObjBuilder& b, const std::string& name) = 0;

    virtual Status set(const BSONElement& newValueElement) = 0;

    virtual Status setFromString(const std::string& str) = 0;

    bool isTestOnly() const {
        return _testOnly;
    }

    void setTestOnly() {
        _testOnly = true;
    }

private:
    std::string _name;
    bool _allowedToChangeAtStartup;
    bool _allowedToChangeAtRuntime;
    bool _testOnly = false;
};

class ServerParameterSet {
public:
    typedef std::map<std::string, ServerParameter*> Map;

    void add(ServerParameter* sp);

    const Map& getMap() const {
        return _map;
    }

    static ServerParameterSet* getGlobal();

    void disableTestParameters();

private:
    Map _map;
};

/**
 * Server Parameters can be set startup up and/or runtime.
 *
 * At startup, --setParameter ... or config file is used.
 * At runtime, { setParameter : 1, ...} is used.
 */
enum class ServerParameterType {

    /**
     * Parameter can only be set via runCommand.
     */
    kRuntimeOnly,

    /**
     * Parameter can only be set via --setParameter, and is only read at startup after command-line
     * parameters, and the config file are processed.
     */
    kStartupOnly,

    /**
     * Parameter can be set at both startup and runtime.
     */
    kStartupAndRuntime,
};

/**
 * Lets you make server level settings easily configurable.
 * Hooks into (set|get)Parameter, as well as command line processing
 */
template <typename T>
class BoundServerParameter : public ServerParameter {
private:
    using setter = stdx::function<Status(const T&)>;
    using getter = stdx::function<T()>;
    using SPT = ServerParameterType;

public:
    BoundServerParameter(const std::string& name,
                         const setter set,
                         const getter get,
                         SPT paramType = SPT::kStartupOnly)
        : BoundServerParameter(ServerParameterSet::getGlobal(), name, set, get, paramType) {}

    BoundServerParameter(ServerParameterSet* sps,
                         const std::string& name,
                         const setter set,
                         const getter get,
                         SPT paramType = SPT::kStartupOnly)
        : ServerParameter(sps,
                          name,
                          paramType == SPT::kStartupOnly || paramType == SPT::kStartupAndRuntime,
                          paramType == SPT::kRuntimeOnly || paramType == SPT::kStartupAndRuntime),
          _setter(set),
          _getter(get) {}
    ~BoundServerParameter() override = default;

    void append(OperationContext* opCtx, BSONObjBuilder& b, const std::string& name) override {
        b.append(name, _getter());
    }

    Status set(const BSONElement& newValueElement) override {
        T newValue;

        if (!newValueElement.coerce(&newValue)) {
            return Status(ErrorCodes::BadValue, "Can't coerce value");
        }

        return _setter(newValue);
    }

    Status setFromString(const std::string& str) override;

private:
    const setter _setter;
    const getter _getter;
};

template <>
inline Status BoundServerParameter<bool>::setFromString(const std::string& str) {
    if ((str == "1") || (str == "true")) {
        return _setter(true);
    }
    if ((str == "0") || (str == "false")) {
        return _setter(false);
    }
    return Status(ErrorCodes::BadValue, "Value is not a valid boolean");
}

template <>
inline Status BoundServerParameter<std::string>::setFromString(const std::string& str) {
    return _setter(str);
}

template <>
inline Status BoundServerParameter<std::vector<std::string>>::setFromString(
    const std::string& str) {
    std::vector<std::string> v;
    splitStringDelim(str, &v, ',');
    return _setter(v);
}

template <typename T>
inline Status BoundServerParameter<T>::setFromString(const std::string& str) {
    T value;
    Status status = parseNumberFromString(str, &value);
    if (!status.isOK()) {
        return status;
    }
    return _setter(value);
}

template <typename T>
class LockedServerParameter : public BoundServerParameter<T> {
private:
    using SPT = ServerParameterType;

public:
    LockedServerParameter(const std::string& name,
                          const T& initval,
                          SPT paramType = SPT::kStartupAndRuntime)
        : LockedServerParameter(ServerParameterSet::getGlobal(), name, initval, paramType) {}

    LockedServerParameter(ServerParameterSet* sps,
                          const std::string& name,
                          const T& initval,
                          SPT paramType = SPT::kStartupAndRuntime)
        : BoundServerParameter<T>(sps,
                                  name,
                                  [this](const T& v) { return setLocked(v); },
                                  [this]() { return getLocked(); },
                                  paramType),
          _value(initval) {}
    ~LockedServerParameter() override = default;

    Status setLocked(const T& value) {
        stdx::unique_lock<stdx::mutex> lk(_mutex);
        _value = value;
        return Status::OK();
    }

    T getLocked() const {
        stdx::unique_lock<stdx::mutex> lk(_mutex);
        return _value;
    }

private:
    mutable stdx::mutex _mutex;
    T _value;
};

namespace server_parameter_detail {

template <typename T, typename...>
struct IsOneOf : std::false_type {};

template <typename T, typename U0, typename... Us>
struct IsOneOf<T, U0, Us...>
    : std::conditional_t<std::is_same<T, U0>::value, std::true_type, IsOneOf<T, Us...>> {};

/**
 * Type trait for ServerParameterType to identify which types are safe to use at runtime because
 * they have std::atomic or equivalent types.
 */
template <typename T>
struct IsSafeRuntimeType : IsOneOf<T, bool, int, long long, double> {};

/**
 * Get the type of storage to use for a given tuple of <type, ServerParameterType>.
 *
 * By default, we want std::atomic or equivalent types because they are thread-safe.
 * If the parameter is a startup only type, then there are no concurrency concerns since
 * server parameters are processed on the main thread while it is single-threaded during startup.
 */
template <typename T, ServerParameterType paramType>
struct StorageTraits {
    /**
     * For kStartupOnly parameters, we can use the type T as storage directly.
     * Otherwise if T is double, use AtomicDouble. Otherwise use AtomicWord<T>.
     */
    using value_type = std::conditional_t<
        paramType == ServerParameterType::kStartupOnly,
        T,
        std::conditional_t<std::is_same<T, double>::value, AtomicDouble, AtomicWord<T>>>;

    static T get(value_type* v) {
        return _get(v);
    }

    static void set(value_type* v, const T& newValue) {
        _set(v, newValue);
    }

private:
    static T _get(AtomicDouble* v) {
        return v->load();
    }
    template <typename U>
    static T _get(AtomicWord<U>* v) {
        return v->load();
    }
    template <typename U>
    static T _get(U* v) {
        return *v;
    }

    static void _set(AtomicDouble* v, const T& newValue) {
        v->store(newValue);
    }
    template <typename U>
    static void _set(AtomicWord<U>* v, const T& newValue) {
        v->store(newValue);
    }
    template <typename U>
    static void _set(U* v, const T& newValue) {
        *v = newValue;
    }
};

}  // namespace server_parameter_detail

/**
 * Implementation of BoundServerParameter for reading and writing a server parameter with a given
 * name and type into a specific C++ variable.
 *
 * NOTE: ServerParameters set at runtime can be read or written to at anytime, and are not
 * thread-safe without atomic types or other concurrency techniques.
 */
template <typename T, ServerParameterType paramType>
class ExportedServerParameter : public BoundServerParameter<T> {
public:
    MONGO_STATIC_ASSERT_MSG(paramType == ServerParameterType::kStartupOnly ||
                                server_parameter_detail::IsSafeRuntimeType<T>::value,
                            "This type is not supported as a runtime server parameter.");

    using storage_traits = server_parameter_detail::StorageTraits<T, paramType>;
    using storage_type = typename storage_traits::value_type;
    using validator_function = stdx::function<Status(const T&)>;

    /**
     * Construct an ExportedServerParameter in parameter set "sps", named "name", whose storage
     * is at "value".
     *
     * If allowedToChangeAtStartup is true, the parameter may be set at the command line,
     * e.g. via the --setParameter switch.  If allowedToChangeAtRuntime is true, the parameter
     * may be set at runtime, e.g.  via the setParameter command.
     */
    ExportedServerParameter(ServerParameterSet* sps, const std::string& name, storage_type* value)
        : BoundServerParameter<T>(sps,
                                  name,
                                  [this](const T& v) { return set(v); },
                                  [this] { return storage_traits::get(_value); },
                                  paramType),
          _value(value) {}

    // Don't let the template method hide our inherited method
    using BoundServerParameter<T>::set;

    virtual Status set(const T& newValue) {
        auto const status = validate(newValue);
        if (!status.isOK()) {
            return status;
        }
        storage_traits::set(_value, newValue);
        return Status::OK();
    }

    ExportedServerParameter* withValidator(validator_function validator) {
        invariant(!_validator);
        _validator = std::move(validator);
        return this;
    }

protected:
    /**
     * Note that if a subclass overrides the validate member function, the validator provided via
     * withValidate will not be used.
     **/
    virtual Status validate(const T& potentialNewValue) {
        if (_validator) {
            return _validator(potentialNewValue);
        }
        return Status::OK();
    }

    storage_type* const _value;  // owned elsewhere
    validator_function _validator;
};

}  // namespace mongo

#define MONGO_EXPORT_SERVER_PARAMETER_IMPL_(NAME, TYPE, INITIAL_VALUE, PARAM_TYPE) \
    ExportedServerParameter<TYPE, PARAM_TYPE>::storage_type NAME(INITIAL_VALUE);   \
    MONGO_COMPILER_VARIABLE_UNUSED auto _exportedParameter_##NAME =                \
        (new ExportedServerParameter<TYPE, PARAM_TYPE>(                            \
            ServerParameterSet::getGlobal(), #NAME, &NAME))

/**
 * Create a global variable of type "TYPE" named "NAME" with the given INITIAL_VALUE.  The
 * value may be set at startup or at runtime.
 */
#define MONGO_EXPORT_SERVER_PARAMETER(NAME, TYPE, INITIAL_VALUE) \
    MONGO_EXPORT_SERVER_PARAMETER_IMPL_(                         \
        NAME, TYPE, INITIAL_VALUE, ServerParameterType::kStartupAndRuntime)

/**
 * Like MONGO_EXPORT_SERVER_PARAMETER, but the value may only be set at startup.
 */
#define MONGO_EXPORT_STARTUP_SERVER_PARAMETER(NAME, TYPE, INITIAL_VALUE) \
    MONGO_EXPORT_SERVER_PARAMETER_IMPL_(                                 \
        NAME, TYPE, INITIAL_VALUE, ServerParameterType::kStartupOnly)

/**
 * Like MONGO_EXPORT_SERVER_PARAMETER, but the value may only be set at runtime.
 */
#define MONGO_EXPORT_RUNTIME_SERVER_PARAMETER(NAME, TYPE, INITIAL_VALUE) \
    MONGO_EXPORT_SERVER_PARAMETER_IMPL_(                                 \
        NAME, TYPE, INITIAL_VALUE, ServerParameterType::kRuntimeOnly)




posted @ 2018-12-28 14:43  papering  阅读(277)  评论(0编辑  收藏  举报