summaryrefslogtreecommitdiff
path: root/src/bus-proxyd/bus-xml-policy.c
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2015-01-17 18:07:58 +0100
committerDavid Herrmann <dh.herrmann@gmail.com>2015-01-17 18:27:23 +0100
commitc4bc1a8434f2a34840ea6f63064fa998ecfae738 (patch)
treec10ae7cfd3864cc74fc83c997baaf45e81215b48 /src/bus-proxyd/bus-xml-policy.c
parentb58d857136496ee463223cd90af46512e9eef152 (diff)
bus-proxy: share policy between threads
This implements a shared policy cache with read-write locks. We no longer parse the XML policy in each thread. This will allow us to easily implement ReloadConfig().
Diffstat (limited to 'src/bus-proxyd/bus-xml-policy.c')
-rw-r--r--src/bus-proxyd/bus-xml-policy.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c
index c0f3764ae2..b3daad5017 100644
--- a/src/bus-proxyd/bus-xml-policy.c
+++ b/src/bus-proxyd/bus-xml-policy.c
@@ -1106,6 +1106,122 @@ void policy_dump(Policy *p) {
fflush(stdout);
}
+int shared_policy_new(SharedPolicy **out) {
+ SharedPolicy *sp;
+ int r;
+
+ sp = new0(SharedPolicy, 1);
+ if (!sp)
+ return log_oom();
+
+ r = pthread_mutex_init(&sp->lock, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Cannot initialize shared policy mutex: %m");
+ goto exit_free;
+ }
+
+ r = pthread_rwlock_init(&sp->rwlock, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Cannot initialize shared policy rwlock: %m");
+ goto exit_mutex;
+ }
+
+ *out = sp;
+ sp = NULL;
+ return 0;
+
+ /* pthread lock destruction is not fail-safe... meh! */
+exit_mutex:
+ pthread_mutex_destroy(&sp->lock);
+exit_free:
+ free(sp);
+ return r;
+}
+
+SharedPolicy *shared_policy_free(SharedPolicy *sp) {
+ if (!sp)
+ return NULL;
+
+ policy_free(sp->policy);
+ pthread_rwlock_destroy(&sp->rwlock);
+ pthread_mutex_destroy(&sp->lock);
+ free(sp);
+
+ return NULL;
+}
+
+static int shared_policy_reload_unlocked(SharedPolicy *sp, char **configuration) {
+ Policy old, buffer = {};
+ bool free_old;
+ int r;
+
+ assert(sp);
+
+ r = policy_load(&buffer, configuration);
+ if (r < 0)
+ return log_error_errno(r, "Failed to load policy: %m");
+
+ /* policy_dump(&buffer); */
+
+ pthread_rwlock_wrlock(&sp->rwlock);
+ memcpy(&old, &sp->buffer, sizeof(old));
+ memcpy(&sp->buffer, &buffer, sizeof(buffer));
+ free_old = !!sp->policy;
+ sp->policy = &sp->buffer;
+ pthread_rwlock_unlock(&sp->rwlock);
+
+ if (free_old)
+ policy_free(&old);
+
+ return 0;
+}
+
+int shared_policy_reload(SharedPolicy *sp, char **configuration) {
+ int r;
+
+ assert(sp);
+
+ pthread_mutex_lock(&sp->lock);
+ r = shared_policy_reload_unlocked(sp, configuration);
+ pthread_mutex_unlock(&sp->lock);
+
+ return r;
+}
+
+int shared_policy_preload(SharedPolicy *sp, char **configuration) {
+ int r;
+
+ assert(sp);
+
+ pthread_mutex_lock(&sp->lock);
+ if (!sp->policy)
+ r = shared_policy_reload_unlocked(sp, configuration);
+ else
+ r = 0;
+ pthread_mutex_unlock(&sp->lock);
+
+ return r;
+}
+
+Policy *shared_policy_acquire(SharedPolicy *sp) {
+ assert(sp);
+
+ pthread_rwlock_rdlock(&sp->rwlock);
+ if (sp->policy)
+ return sp->policy;
+ pthread_rwlock_unlock(&sp->rwlock);
+
+ return NULL;
+}
+
+void shared_policy_release(SharedPolicy *sp, Policy *p) {
+ assert(sp);
+ assert(!p || sp->policy == p);
+
+ if (p)
+ pthread_rwlock_unlock(&sp->rwlock);
+}
+
static const char* const policy_item_type_table[_POLICY_ITEM_TYPE_MAX] = {
[_POLICY_ITEM_TYPE_UNSET] = "unset",
[POLICY_ITEM_ALLOW] = "allow",