mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:37:46 +00:00
ConfigServer+LibConfig: Add way for clients to listen for config changes
This patch adds a Config::Listener abstract class that anyone can inherit from and receive notifications when configuration values change. We don't yet monitor file system changes, so these only work for changes made by ConfigServer itself. In order to receive these notifications, clients must monitor the domain by calling monitor_domain(). Only pledged domains can be monitored. Note that the client initiating the change does not get notified.
This commit is contained in:
parent
9509f2ff87
commit
edf7843409
9 changed files with 188 additions and 15 deletions
|
@ -12,6 +12,25 @@ namespace ConfigServer {
|
|||
|
||||
static HashMap<int, RefPtr<ClientConnection>> s_connections;
|
||||
|
||||
struct CachedDomain {
|
||||
String domain;
|
||||
NonnullRefPtr<Core::ConfigFile> config;
|
||||
};
|
||||
|
||||
static HashMap<String, NonnullOwnPtr<CachedDomain>> s_cache;
|
||||
|
||||
static Core::ConfigFile& ensure_domain_config(String const& domain)
|
||||
{
|
||||
auto it = s_cache.find(domain);
|
||||
if (it != s_cache.end())
|
||||
return *it->value->config;
|
||||
|
||||
auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes);
|
||||
auto cache_entry = make<CachedDomain>(domain, config);
|
||||
s_cache.set(domain, move(cache_entry));
|
||||
return *config;
|
||||
}
|
||||
|
||||
ClientConnection::ClientConnection(NonnullRefPtr<Core::LocalSocket> client_socket, int client_id)
|
||||
: IPC::ClientConnection<ConfigClientEndpoint, ConfigServerEndpoint>(*this, move(client_socket), client_id)
|
||||
{
|
||||
|
@ -38,6 +57,16 @@ void ClientConnection::pledge_domains(Vector<String> const& domains)
|
|||
m_pledged_domains.set(domain);
|
||||
}
|
||||
|
||||
void ClientConnection::monitor_domain(String const& domain)
|
||||
{
|
||||
if (m_has_pledged && !m_pledged_domains.contains(domain)) {
|
||||
did_misbehave("Attempt to monitor non-pledged domain");
|
||||
return;
|
||||
}
|
||||
|
||||
m_monitored_domains.set(domain);
|
||||
}
|
||||
|
||||
bool ClientConnection::validate_access(String const& domain, String const& group, String const& key)
|
||||
{
|
||||
if (!m_has_pledged)
|
||||
|
@ -53,10 +82,10 @@ Messages::ConfigServer::ReadStringValueResponse ClientConnection::read_string_va
|
|||
if (!validate_access(domain, group, key))
|
||||
return nullptr;
|
||||
|
||||
auto config = Core::ConfigFile::open_for_app(domain);
|
||||
if (!config->has_key(group, key))
|
||||
auto& config = ensure_domain_config(domain);
|
||||
if (!config.has_key(group, key))
|
||||
return Optional<String> {};
|
||||
return Optional<String> { config->read_entry(group, key) };
|
||||
return Optional<String> { config.read_entry(group, key) };
|
||||
}
|
||||
|
||||
Messages::ConfigServer::ReadI32ValueResponse ClientConnection::read_i32_value(String const& domain, String const& group, String const& key)
|
||||
|
@ -64,10 +93,10 @@ Messages::ConfigServer::ReadI32ValueResponse ClientConnection::read_i32_value(St
|
|||
if (!validate_access(domain, group, key))
|
||||
return nullptr;
|
||||
|
||||
auto config = Core::ConfigFile::open_for_app(domain);
|
||||
if (!config->has_key(group, key))
|
||||
auto& config = ensure_domain_config(domain);
|
||||
if (!config.has_key(group, key))
|
||||
return Optional<i32> {};
|
||||
return Optional<i32> { config->read_num_entry(group, key) };
|
||||
return Optional<i32> { config.read_num_entry(group, key) };
|
||||
}
|
||||
|
||||
Messages::ConfigServer::ReadBoolValueResponse ClientConnection::read_bool_value(String const& domain, String const& group, String const& key)
|
||||
|
@ -75,10 +104,10 @@ Messages::ConfigServer::ReadBoolValueResponse ClientConnection::read_bool_value(
|
|||
if (!validate_access(domain, group, key))
|
||||
return nullptr;
|
||||
|
||||
auto config = Core::ConfigFile::open_for_app(domain);
|
||||
if (!config->has_key(group, key))
|
||||
auto& config = ensure_domain_config(domain);
|
||||
if (!config.has_key(group, key))
|
||||
return Optional<bool> {};
|
||||
return Optional<bool> { config->read_bool_entry(group, key) };
|
||||
return Optional<bool> { config.read_bool_entry(group, key) };
|
||||
}
|
||||
|
||||
void ClientConnection::write_string_value(String const& domain, String const& group, String const& key, String const& value)
|
||||
|
@ -86,8 +115,17 @@ void ClientConnection::write_string_value(String const& domain, String const& gr
|
|||
if (!validate_access(domain, group, key))
|
||||
return;
|
||||
|
||||
auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes);
|
||||
config->write_entry(group, key, value);
|
||||
auto& config = ensure_domain_config(domain);
|
||||
|
||||
if (config.has_key(group, key) && config.read_entry(group, key) == value)
|
||||
return;
|
||||
|
||||
config.write_entry(group, key, value);
|
||||
|
||||
for (auto& it : s_connections) {
|
||||
if (it.value != this && it.value->m_monitored_domains.contains(domain))
|
||||
it.value->async_notify_changed_string_value(domain, group, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientConnection::write_i32_value(String const& domain, String const& group, String const& key, i32 value)
|
||||
|
@ -95,8 +133,17 @@ void ClientConnection::write_i32_value(String const& domain, String const& group
|
|||
if (!validate_access(domain, group, key))
|
||||
return;
|
||||
|
||||
auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes);
|
||||
config->write_num_entry(group, key, value);
|
||||
auto& config = ensure_domain_config(domain);
|
||||
|
||||
if (config.has_key(group, key) && config.read_num_entry(group, key) == value)
|
||||
return;
|
||||
|
||||
config.write_num_entry(group, key, value);
|
||||
|
||||
for (auto& it : s_connections) {
|
||||
if (it.value != this && it.value->m_monitored_domains.contains(domain))
|
||||
it.value->async_notify_changed_i32_value(domain, group, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientConnection::write_bool_value(String const& domain, String const& group, String const& key, bool value)
|
||||
|
@ -104,8 +151,17 @@ void ClientConnection::write_bool_value(String const& domain, String const& grou
|
|||
if (!validate_access(domain, group, key))
|
||||
return;
|
||||
|
||||
auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes);
|
||||
config->write_bool_entry(group, key, value);
|
||||
auto& config = ensure_domain_config(domain);
|
||||
|
||||
if (config.has_key(group, key) && config.read_bool_entry(group, key) == value)
|
||||
return;
|
||||
|
||||
config.write_bool_entry(group, key, value);
|
||||
|
||||
for (auto& it : s_connections) {
|
||||
if (it.value != this && it.value->m_monitored_domains.contains(domain))
|
||||
it.value->async_notify_changed_bool_value(domain, group, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue