2018-03-02 00:35:02 -08:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#define HAVE_IRCD_CONF_H
|
|
|
|
|
2018-05-21 03:01:40 -07:00
|
|
|
/// Configuration system.
|
|
|
|
///
|
2018-08-13 14:51:06 -07:00
|
|
|
/// This system disseminates mutable runtime values throughout IRCd. All users
|
|
|
|
/// that integrate a configurable value will create a [static] conf::item<>
|
|
|
|
/// instantiated with one of the explicit types available; also a name and
|
|
|
|
/// default value.
|
|
|
|
///
|
|
|
|
/// All conf::items are collected by this system. Users that administrate
|
|
|
|
/// configuration will push values to the conf::item's. The various items have
|
|
|
|
/// O(1) access to the value contained in their item instance. Administrators
|
|
|
|
/// have logarithmic access through this interface using the items map by name.
|
|
|
|
///
|
2018-12-28 13:36:23 -08:00
|
|
|
/// All conf::items can be controlled by environmental variables at program
|
|
|
|
/// startup. The name of the conf::item in the environment uses underscore
|
|
|
|
/// '_' rather than '.' and the environment takes precedence over both defaults
|
|
|
|
/// and databased values. This means you can set a conf through an env var
|
|
|
|
/// to override a broken value.
|
|
|
|
///
|
2018-03-02 00:35:02 -08:00
|
|
|
namespace ircd::conf
|
|
|
|
{
|
|
|
|
template<class T = void> struct item; // doesn't exist
|
|
|
|
template<> struct item<void>; // base class of all conf items
|
2018-03-02 07:45:02 -08:00
|
|
|
template<> struct item<std::string>;
|
2018-05-20 18:23:28 -07:00
|
|
|
template<> struct item<bool>;
|
2018-03-02 23:54:35 -08:00
|
|
|
template<> struct item<uint64_t>;
|
|
|
|
template<> struct item<int64_t>;
|
2018-12-18 17:00:11 -08:00
|
|
|
template<> struct item<uint32_t>;
|
|
|
|
template<> struct item<int32_t>;
|
2018-11-14 17:16:43 -08:00
|
|
|
template<> struct item<float>;
|
|
|
|
template<> struct item<double>;
|
2018-03-09 12:20:23 -08:00
|
|
|
template<> struct item<hours>;
|
2018-03-02 00:35:02 -08:00
|
|
|
template<> struct item<seconds>;
|
2018-03-09 12:20:23 -08:00
|
|
|
template<> struct item<milliseconds>;
|
|
|
|
template<> struct item<microseconds>;
|
|
|
|
|
|
|
|
template<class T> struct value; // abstraction for carrying item value
|
|
|
|
template<class T> struct lex_castable; // abstraction for lex_cast compatible
|
2018-03-02 00:35:02 -08:00
|
|
|
|
|
|
|
IRCD_EXCEPTION(ircd::error, error)
|
2018-03-02 03:03:33 -08:00
|
|
|
IRCD_EXCEPTION(error, not_found)
|
|
|
|
IRCD_EXCEPTION(error, bad_value)
|
2018-03-02 00:35:02 -08:00
|
|
|
|
2018-08-22 13:58:10 -07:00
|
|
|
using set_cb = std::function<void ()>;
|
|
|
|
|
2019-07-27 14:06:23 -07:00
|
|
|
const size_t NAME_MAX_LEN {127};
|
|
|
|
const size_t VALUE_MAX_LEN {48_KiB};
|
|
|
|
|
2018-03-02 03:03:33 -08:00
|
|
|
extern std::map<string_view, item<> *> items;
|
2018-09-15 00:37:16 -07:00
|
|
|
extern callbacks<void (item<> &)> on_init;
|
2018-03-02 03:03:33 -08:00
|
|
|
|
2018-05-25 20:45:30 -07:00
|
|
|
bool exists(const string_view &key);
|
2018-12-08 16:15:22 -08:00
|
|
|
bool persists(const string_view &key);
|
2018-03-02 03:03:33 -08:00
|
|
|
string_view get(const string_view &key, const mutable_buffer &out);
|
2019-03-11 11:13:14 -07:00
|
|
|
std::string get(const string_view &key);
|
2018-03-02 03:03:33 -08:00
|
|
|
bool set(const string_view &key, const string_view &value);
|
|
|
|
bool set(std::nothrow_t, const string_view &key, const string_view &value);
|
2019-03-11 12:16:32 -07:00
|
|
|
bool fault(std::nothrow_t, const string_view &key) noexcept;
|
|
|
|
void fault(const string_view &key);
|
2018-09-02 20:59:18 -07:00
|
|
|
bool reset(std::nothrow_t, const string_view &key);
|
|
|
|
bool reset(const string_view &key);
|
|
|
|
size_t reset();
|
2018-03-02 00:35:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Conf item base class. You don't create this directly; use one of the
|
|
|
|
/// derived templates instead.
|
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<void>
|
|
|
|
{
|
|
|
|
json::strung feature_;
|
|
|
|
json::object feature;
|
|
|
|
string_view name;
|
2018-08-22 13:58:10 -07:00
|
|
|
conf::set_cb set_cb;
|
2018-03-02 00:35:02 -08:00
|
|
|
|
2018-08-22 13:57:03 -07:00
|
|
|
protected:
|
|
|
|
virtual string_view on_get(const mutable_buffer &) const;
|
|
|
|
virtual bool on_set(const string_view &);
|
2018-09-03 04:39:44 -07:00
|
|
|
void call_init();
|
2018-08-22 13:57:03 -07:00
|
|
|
|
|
|
|
public:
|
2019-03-11 11:05:54 -07:00
|
|
|
virtual size_t size() const = 0;
|
2018-08-22 13:57:03 -07:00
|
|
|
string_view get(const mutable_buffer &) const;
|
2019-03-11 11:13:14 -07:00
|
|
|
std::string get() const;
|
2018-08-22 13:57:03 -07:00
|
|
|
bool set(const string_view &);
|
2019-03-11 12:16:32 -07:00
|
|
|
void fault() noexcept;
|
2018-03-02 00:35:02 -08:00
|
|
|
|
2018-08-22 14:08:03 -07:00
|
|
|
item(const json::members &, conf::set_cb);
|
2018-03-02 03:03:33 -08:00
|
|
|
item(item &&) = delete;
|
|
|
|
item(const item &) = delete;
|
2018-03-02 00:35:02 -08:00
|
|
|
virtual ~item() noexcept;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Conf item value abstraction. If possible, the conf item will also
|
|
|
|
/// inherit from this template to deduplicate functionality between
|
|
|
|
/// conf items which contain similar classes of values.
|
|
|
|
template<class T>
|
|
|
|
struct ircd::conf::value
|
|
|
|
{
|
|
|
|
using value_type = T;
|
|
|
|
|
|
|
|
T _value;
|
|
|
|
|
2019-02-15 17:11:20 -08:00
|
|
|
operator const T &() const noexcept
|
2018-03-02 00:35:02 -08:00
|
|
|
{
|
|
|
|
return _value;
|
|
|
|
}
|
|
|
|
|
2018-03-02 03:03:33 -08:00
|
|
|
template<class... A>
|
|
|
|
value(A&&... a)
|
2018-03-09 12:20:23 -08:00
|
|
|
:_value(std::forward<A>(a)...)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
struct ircd::conf::lex_castable
|
|
|
|
:conf::item<>
|
|
|
|
,conf::value<T>
|
|
|
|
{
|
2018-08-22 13:57:03 -07:00
|
|
|
string_view on_get(const mutable_buffer &out) const override
|
2018-03-09 12:20:23 -08:00
|
|
|
{
|
|
|
|
return lex_cast(this->_value, out);
|
|
|
|
}
|
|
|
|
|
2018-08-22 13:57:03 -07:00
|
|
|
bool on_set(const string_view &s) override
|
2018-03-09 12:20:23 -08:00
|
|
|
{
|
|
|
|
this->_value = lex_cast<T>(s);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-11 11:05:54 -07:00
|
|
|
size_t size() const override
|
|
|
|
{
|
|
|
|
return LEX_CAST_BUFSIZE;
|
|
|
|
}
|
|
|
|
|
2018-08-22 13:58:10 -07:00
|
|
|
lex_castable(const json::members &members,
|
|
|
|
conf::set_cb set_cb = {})
|
|
|
|
:conf::item<>
|
|
|
|
{
|
|
|
|
members, std::move(set_cb)
|
|
|
|
}
|
|
|
|
,conf::value<T>
|
|
|
|
(
|
2018-11-14 18:38:54 -08:00
|
|
|
feature.get("default", T(0))
|
2018-08-22 13:58:10 -07:00
|
|
|
)
|
2018-09-03 04:39:44 -07:00
|
|
|
{
|
|
|
|
call_init();
|
|
|
|
}
|
2018-03-02 00:35:02 -08:00
|
|
|
};
|
|
|
|
|
2018-03-02 07:45:02 -08:00
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<std::string>
|
|
|
|
:conf::item<>
|
|
|
|
,conf::value<std::string>
|
|
|
|
{
|
2018-10-02 15:51:45 -07:00
|
|
|
explicit operator const std::string &() const
|
|
|
|
{
|
|
|
|
return _value;
|
|
|
|
}
|
|
|
|
|
2019-07-05 18:05:37 -07:00
|
|
|
explicit operator bool() const
|
|
|
|
{
|
|
|
|
return !empty(_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!() const
|
|
|
|
{
|
|
|
|
return !static_cast<bool>(*this);
|
|
|
|
}
|
|
|
|
|
2018-03-02 07:45:02 -08:00
|
|
|
operator string_view() const
|
|
|
|
{
|
|
|
|
return _value;
|
|
|
|
}
|
|
|
|
|
2018-08-22 13:57:03 -07:00
|
|
|
string_view on_get(const mutable_buffer &out) const override;
|
|
|
|
bool on_set(const string_view &s) override;
|
2019-03-11 11:05:54 -07:00
|
|
|
size_t size() const override;
|
2018-03-02 07:45:02 -08:00
|
|
|
|
2018-08-22 13:58:10 -07:00
|
|
|
item(const json::members &members, conf::set_cb set_cb = {});
|
2018-03-02 07:45:02 -08:00
|
|
|
};
|
|
|
|
|
2018-05-20 18:23:28 -07:00
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<bool>
|
|
|
|
:conf::item<>
|
|
|
|
,conf::value<bool>
|
|
|
|
{
|
2019-06-07 22:25:16 -07:00
|
|
|
bool operator!() const
|
|
|
|
{
|
|
|
|
return !static_cast<const bool &>(*this);
|
|
|
|
}
|
|
|
|
|
2018-08-22 13:57:03 -07:00
|
|
|
string_view on_get(const mutable_buffer &out) const override;
|
|
|
|
bool on_set(const string_view &s) override;
|
2019-03-11 11:05:54 -07:00
|
|
|
size_t size() const override;
|
2018-05-20 18:23:28 -07:00
|
|
|
|
2018-08-22 13:58:10 -07:00
|
|
|
item(const json::members &members, conf::set_cb set_cb = {});
|
2018-05-20 18:23:28 -07:00
|
|
|
};
|
|
|
|
|
2018-03-02 23:54:35 -08:00
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<uint64_t>
|
2018-03-09 12:20:23 -08:00
|
|
|
:lex_castable<uint64_t>
|
2018-03-02 23:54:35 -08:00
|
|
|
{
|
2018-03-09 12:20:23 -08:00
|
|
|
using lex_castable::lex_castable;
|
2018-03-02 23:54:35 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<int64_t>
|
2018-03-09 12:20:23 -08:00
|
|
|
:lex_castable<int64_t>
|
2018-03-02 23:54:35 -08:00
|
|
|
{
|
2018-03-09 12:20:23 -08:00
|
|
|
using lex_castable::lex_castable;
|
|
|
|
};
|
2018-03-02 23:54:35 -08:00
|
|
|
|
2018-12-18 17:00:11 -08:00
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<uint32_t>
|
|
|
|
:lex_castable<uint32_t>
|
|
|
|
{
|
|
|
|
using lex_castable::lex_castable;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<int32_t>
|
|
|
|
:lex_castable<int32_t>
|
|
|
|
{
|
|
|
|
using lex_castable::lex_castable;
|
|
|
|
};
|
|
|
|
|
2018-11-14 17:16:43 -08:00
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<double>
|
|
|
|
:lex_castable<double>
|
|
|
|
{
|
|
|
|
using lex_castable::lex_castable;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<float>
|
|
|
|
:lex_castable<float>
|
|
|
|
{
|
|
|
|
using lex_castable::lex_castable;
|
|
|
|
};
|
|
|
|
|
2018-03-09 12:20:23 -08:00
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<ircd::hours>
|
|
|
|
:lex_castable<ircd::hours>
|
|
|
|
{
|
|
|
|
using lex_castable::lex_castable;
|
2018-03-02 23:54:35 -08:00
|
|
|
};
|
|
|
|
|
2018-03-02 00:35:02 -08:00
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<ircd::seconds>
|
2018-03-09 12:20:23 -08:00
|
|
|
:lex_castable<ircd::seconds>
|
2018-03-02 00:35:02 -08:00
|
|
|
{
|
2018-03-09 12:20:23 -08:00
|
|
|
using lex_castable::lex_castable;
|
|
|
|
};
|
2018-03-02 03:03:33 -08:00
|
|
|
|
2018-03-09 12:20:23 -08:00
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<ircd::milliseconds>
|
|
|
|
:lex_castable<ircd::milliseconds>
|
|
|
|
{
|
|
|
|
using lex_castable::lex_castable;
|
|
|
|
};
|
2018-03-02 03:03:33 -08:00
|
|
|
|
2018-03-09 12:20:23 -08:00
|
|
|
template<>
|
|
|
|
struct ircd::conf::item<ircd::microseconds>
|
|
|
|
:lex_castable<ircd::microseconds>
|
|
|
|
{
|
|
|
|
using lex_castable::lex_castable;
|
2018-03-02 00:35:02 -08:00
|
|
|
};
|