mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-22 09:30:45 +00:00
db: introduce read-write lock to synchronize config updates with REST API
Config is reloaded from SIGHUP on shard 0 and broadcast to all shards under a write lock. REST API callers reading find_config_id acquire a read lock via value_as_json_string_for_name() and are guaranteed a consistent snapshot even when a reload is in progress.
This commit is contained in:
@@ -82,15 +82,16 @@ void set_config(std::shared_ptr < api_registry_builder20 > rb, http_context& ctx
|
||||
});
|
||||
});
|
||||
|
||||
cs::find_config_id.set(r, [&cfg] (const_req r) {
|
||||
auto id = r.get_path_param("id");
|
||||
for (auto&& cfg_ref : cfg.values()) {
|
||||
auto&& cfg = cfg_ref.get();
|
||||
if (id == cfg.name()) {
|
||||
return cfg.value_as_json();
|
||||
}
|
||||
cs::find_config_id.set(r, [&cfg] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
auto id = req->get_path_param("id");
|
||||
auto value = co_await cfg.value_as_json_string_for_name(id);
|
||||
if (!value) {
|
||||
throw bad_param_exception(sstring("No such config entry: ") + id);
|
||||
}
|
||||
throw bad_param_exception(sstring("No such config entry: ") + id);
|
||||
//value is already a json string
|
||||
json::json_return_type ret{json::json_void()};
|
||||
ret._res = std::move(*value);
|
||||
co_return ret;
|
||||
});
|
||||
|
||||
sp::get_rpc_timeout.set(r, [&cfg](const_req req) {
|
||||
|
||||
19
db/config.cc
19
db/config.cc
@@ -7,6 +7,7 @@
|
||||
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.1
|
||||
*/
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <sstream>
|
||||
|
||||
@@ -19,6 +20,7 @@
|
||||
|
||||
#include <seastar/core/coroutine.hh>
|
||||
#include <seastar/core/format.hh>
|
||||
#include <seastar/core/smp.hh>
|
||||
#include <seastar/core/sstring.hh>
|
||||
#include <seastar/json/json_elements.hh>
|
||||
#include <seastar/util/log.hh>
|
||||
@@ -1725,6 +1727,23 @@ void db::config::maybe_in_workdir(named_value<string_list>& tos, const char* sub
|
||||
}
|
||||
}
|
||||
|
||||
future<std::optional<sstring>> db::config::value_as_json_string_for_name(sstring name) const {
|
||||
// Config reloads triggered by SIGHUP are applied on shard 0 and then
|
||||
// broadcast to all other shards. We read the value on shard 0 under
|
||||
// a read lock to guarantee a consistent snapshot — the SIGHUP handler
|
||||
// holds the write lock across the entire reload-and-broadcast sequence.
|
||||
co_return co_await smp::submit_to(0, [this, name = std::move(name)] () -> future<std::optional<sstring>> {
|
||||
auto lock = co_await _config_update_lock.hold_read_lock();
|
||||
for (auto&& cfg_ref : values()) {
|
||||
auto&& c = cfg_ref.get();
|
||||
if (name == c.name()) {
|
||||
co_return c.value_as_json()._res;
|
||||
}
|
||||
}
|
||||
co_return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
const sstring db::config::default_tls_priority("SECURE128:-VERS-TLS1.0");
|
||||
|
||||
template <>
|
||||
|
||||
18
db/config.hh
18
db/config.hh
@@ -12,6 +12,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include <seastar/core/sstring.hh>
|
||||
#include <seastar/core/rwlock.hh>
|
||||
#include <seastar/util/program-options.hh>
|
||||
#include <seastar/util/log.hh>
|
||||
|
||||
@@ -179,6 +180,16 @@ public:
|
||||
static fs::path get_conf_dir();
|
||||
static fs::path get_conf_sub(fs::path);
|
||||
|
||||
future<rwlock::holder> lock_for_config_update() {
|
||||
return _config_update_lock.hold_write_lock();
|
||||
};
|
||||
|
||||
// Look up a config entry by name and return its JSON representation as a string.
|
||||
// Runs on shard 0 under a read lock so the result is consistent with
|
||||
// any in-progress SIGHUP reload + broadcast_to_all_shards() sequence.
|
||||
// Returns std::nullopt if no config entry with the given name exists.
|
||||
future<std::optional<sstring>> value_as_json_string_for_name(sstring name) const;
|
||||
|
||||
using string_map = std::unordered_map<sstring, sstring>;
|
||||
//program_options::string_map;
|
||||
using string_list = std::vector<sstring>;
|
||||
@@ -657,6 +668,13 @@ private:
|
||||
void maybe_in_workdir(named_value<string_list>&, const char*);
|
||||
|
||||
std::shared_ptr<db::extensions> _extensions;
|
||||
|
||||
// Read-write lock used to synchronize config updates (SIGHUP reload +
|
||||
// broadcast to all shards) with config value readers.
|
||||
// The SIGHUP handler holds the write lock across read_config() +
|
||||
// broadcast_to_all_shards(). Readers acquire the read lock on shard 0
|
||||
// via value_as_json_string_for_name() so they always see a consistent snapshot.
|
||||
mutable rwlock _config_update_lock;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user