summaryrefslogtreecommitdiff
path: root/Userland/Services/ConfigServer
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-08-26 19:31:43 +0200
committerAndreas Kling <kling@serenityos.org>2021-08-26 23:41:38 +0200
commit83d3720842d1b31769c05615c7c8eb23471bba79 (patch)
tree52ca1d3f110e8b4ace7b2144be950d05abe60309 /Userland/Services/ConfigServer
parent696dbc889f8aefd394e32aafe50e2d166c57cf02 (diff)
downloadserenity-83d3720842d1b31769c05615c7c8eb23471bba79.zip
ConfigServer: Monitor opened config files for changes
After opening a domain configuration and putting into our configuration cache, we now monitor the underlying file for changes and send out notifications to monitoring clients as needed. This patch has three FIXME's: - We create a new Core::FileWatcher for each domain. - We don't yet detect removed keys. - We don't know the type of key, so we assume everything is a string. There are a number of ways we can solve those problems but let's not hold up this patch while we wait for solutions. :^)
Diffstat (limited to 'Userland/Services/ConfigServer')
-rw-r--r--Userland/Services/ConfigServer/ClientConnection.cpp27
-rw-r--r--Userland/Services/ConfigServer/ClientConnection.h2
2 files changed, 28 insertions, 1 deletions
diff --git a/Userland/Services/ConfigServer/ClientConnection.cpp b/Userland/Services/ConfigServer/ClientConnection.cpp
index 246a95e10f..6a2e0194b6 100644
--- a/Userland/Services/ConfigServer/ClientConnection.cpp
+++ b/Userland/Services/ConfigServer/ClientConnection.cpp
@@ -7,6 +7,7 @@
#include "ClientConnection.h"
#include <ConfigServer/ConfigClientEndpoint.h>
#include <LibCore/ConfigFile.h>
+#include <LibCore/FileWatcher.h>
namespace ConfigServer {
@@ -15,6 +16,7 @@ static HashMap<int, RefPtr<ClientConnection>> s_connections;
struct CachedDomain {
String domain;
NonnullRefPtr<Core::ConfigFile> config;
+ RefPtr<Core::FileWatcher> watcher;
};
static HashMap<String, NonnullOwnPtr<CachedDomain>> s_cache;
@@ -26,7 +28,30 @@ static Core::ConfigFile& ensure_domain_config(String const& domain)
return *it->value->config;
auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes);
- auto cache_entry = make<CachedDomain>(domain, config);
+ // FIXME: Use a single FileWatcher with multiple watches inside.
+ auto watcher_or_error = Core::FileWatcher::create(InodeWatcherFlags::Nonblock);
+ VERIFY(!watcher_or_error.is_error());
+ auto result = watcher_or_error.value()->add_watch(config->filename(), Core::FileWatcherEvent::Type::ContentModified);
+ VERIFY(!result.is_error());
+ watcher_or_error.value()->on_change = [config, domain](auto&) {
+ auto new_config = Core::ConfigFile::open(config->filename());
+ // FIXME: Detect removed keys.
+ // FIXME: Detect type of keys.
+ for (auto& group : new_config->groups()) {
+ for (auto& key : new_config->keys(group)) {
+ auto old_value = config->read_entry(group, key);
+ auto new_value = new_config->read_entry(group, key);
+ if (old_value != new_value) {
+ for (auto& it : s_connections) {
+ if (it.value->is_monitoring_domain(domain)) {
+ it.value->async_notify_changed_string_value(domain, group, key, new_value);
+ }
+ }
+ }
+ }
+ }
+ };
+ auto cache_entry = make<CachedDomain>(domain, config, watcher_or_error.release_value());
s_cache.set(domain, move(cache_entry));
return *config;
}
diff --git a/Userland/Services/ConfigServer/ClientConnection.h b/Userland/Services/ConfigServer/ClientConnection.h
index 55bd3ebb9c..026f17ff81 100644
--- a/Userland/Services/ConfigServer/ClientConnection.h
+++ b/Userland/Services/ConfigServer/ClientConnection.h
@@ -20,6 +20,8 @@ public:
virtual void die() override;
+ bool is_monitoring_domain(String const& domain) const { return m_monitored_domains.contains(domain); }
+
private:
explicit ClientConnection(NonnullRefPtr<Core::LocalSocket>, int client_id);