[systemd-devel] [PATCH] daemon-reload timestamped: coalesce redundant daemon-reloads

2014-12-02 Thread Ken Sedgwick
Systems with many units (~10K) take many seconds to perform a
daemon-reload.  The process of load-balancing these systems requires
multiple daemon-reloads, many issued concurrently.  Currently many of
these redundant daemon-reloads timeout and fail.

This patch adds a new systemd method ReloadTimestamped which contains
the monotonic timestamp of the daemon-reload issuance.  When a
ReloadTimestamped message is handled it's timestamp is compared to
the timestamp of the most recent successful daemon reload.  If the
message is redundant it is returns with success immediately.

The original Reload method is preserved to support compatibility with
older systemctl versions.

If a new systemctl receives a SD_BUS_ERROR_UNKNOWN_METHOD error in
response to ReloadTimestamped it retries with the original Reload
method.
---
 src/core/dbus-manager.c   | 47 +++
 src/core/manager.c|  8 
 src/core/manager.h|  3 +++
 src/systemctl/systemctl.c | 19 ++-
 4 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 0994d7b..6a42456 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1100,6 +1100,52 @@ static int method_reload(sd_bus *bus, sd_bus_message 
*message, void *userdata, s
 return 1;
 }
 
+static int method_reload_timestamped(sd_bus *bus, sd_bus_message *message, 
void *userdata, sd_bus_error *error) {
+Manager *m = userdata;
+int r;
+usec_t requested_time;
+
+assert(bus);
+assert(message);
+assert(m);
+
+r = bus_verify_reload_daemon_async(m, message, error);
+if (r  0)
+return r;
+if (r == 0)
+return 1; /* No authorization for now, but the async polkit 
stuff will call us again when it has it */
+
+r = mac_selinux_access_check(message, reload, error);
+if (r  0)
+return r;
+
+r = sd_bus_message_read(message, t, requested_time);
+if (r  0)
+return r;
+
+/* Is this reload needed?  If a completed reload was started
+ * after this reload was requested we can coalesce it and
+ * return immediate success. */
+
+if (requested_time  m-last_reload_time)
+return sd_bus_reply_method_return(message, NULL);
+
+/* Instead of sending the reply back right away, we just
+ * remember that we need to and then send it after the reload
+ * is finished. That way the caller knows when the reload
+ * finished. */
+
+assert(!m-queued_message);
+r = sd_bus_message_new_method_return(message, m-queued_message);
+if (r  0)
+return r;
+
+m-queued_message_bus = sd_bus_ref(bus);
+m-exit_code = MANAGER_RELOAD;
+
+return 1;
+}
+
 static int method_reexecute(sd_bus *bus, sd_bus_message *message, void 
*userdata, sd_bus_error *error) {
 Manager *m = userdata;
 int r;
@@ -1917,6 +1963,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
 SD_BUS_METHOD(CreateSnapshot, sb, o, method_create_snapshot, 0),
 SD_BUS_METHOD(RemoveSnapshot, s, NULL, method_remove_snapshot, 0),
 SD_BUS_METHOD(Reload, NULL, NULL, method_reload, 
SD_BUS_VTABLE_UNPRIVILEGED),
+SD_BUS_METHOD(ReloadTimestamped, t, NULL, 
method_reload_timestamped, SD_BUS_VTABLE_UNPRIVILEGED),
 SD_BUS_METHOD(Reexecute, NULL, NULL, method_reexecute, 
SD_BUS_VTABLE_UNPRIVILEGED),
 SD_BUS_METHOD(Exit, NULL, NULL, method_exit, 0),
 SD_BUS_METHOD(Reboot, NULL, NULL, method_reboot, 
SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
diff --git a/src/core/manager.c b/src/core/manager.c
index cff24fa..4619ce3 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -616,6 +616,8 @@ int manager_new(SystemdRunningAs running_as, bool test_run, 
Manager **_m) {
 
 m-taint_usr = dir_is_empty(/usr)  0;
 
+m-last_reload_time = 0ULL;
+
 *_m = m;
 return 0;
 
@@ -2444,9 +2446,12 @@ int manager_reload(Manager *m) {
 int r, q;
 _cleanup_fclose_ FILE *f = NULL;
 _cleanup_fdset_free_ FDSet *fds = NULL;
+usec_t this_reload_time;
 
 assert(m);
 
+this_reload_time = now(CLOCK_MONOTONIC);
+
 r = manager_open_serialization(m, f);
 if (r  0)
 return r;
@@ -2518,6 +2523,9 @@ int manager_reload(Manager *m) {
 
 m-send_reloading_done = true;
 
+if (r = 0)
+m-last_reload_time = this_reload_time;
+
 return r;
 }
 
diff --git a/src/core/manager.h b/src/core/manager.h
index ab75f90..7790127 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -295,6 +295,9 @@ struct Manager {
 
 /* Used for processing polkit authorization responses */
 Hashmap *polkit_registry;
+
+/* Used to coalesce redundant reloads */
+usec_t 

[systemd-devel] [PATCH, v3 1/3] tests: added tests for unit_file_get_{state, list}

2014-10-21 Thread Ken Sedgwick
This test constructs different unit file states and checks the output
of unit_file_get_state and unit_file_get_list for each.

This test characterizes the current output of the master branch in
preparation for a patch which improves the performance of unit state
detection in the face of thousands of units.
---
 .gitignore |   1 +
 Makefile.am|  44 ++-
 src/test/test-enabled.c| 141 +
 .../etc/systemd/system/masked.service  |   1 +
 .../etc/systemd/system/maskedstatic.service|   1 +
 .../etc/systemd/system/some.target |  11 ++
 .../system/some.target.wants/aliased.service   |   1 +
 .../system/some.target.wants/also_masked.service   |   1 +
 .../system/some.target.wants/another.service   |   1 +
 .../system/some.target.wants/different.service |   1 +
 .../system/some.target.wants/masked.service|   1 +
 .../some.target.wants/templating@four.service  |   1 +
 .../some.target.wants/templating@one.service   |   1 +
 .../some.target.wants/templating@three.service |   1 +
 .../some.target.wants/templating@two.service   |   1 +
 .../run/systemd/system/maskedruntime.service   |   1 +
 .../run/systemd/system/maskedruntimestatic.service |   1 +
 .../run/systemd/system/other.target|  14 ++
 .../system/other.target.wants/runtime.service  |   1 +
 .../usr/lib/systemd/system/another.service |   9 ++
 .../usr/lib/systemd/system/disabled.service|   9 ++
 .../usr/lib/systemd/system/invalid.service |   1 +
 .../usr/lib/systemd/system/masked.service  |   9 ++
 .../usr/lib/systemd/system/maskedruntime.service   |   9 ++
 .../lib/systemd/system/maskedruntimestatic.service |   6 +
 .../usr/lib/systemd/system/maskedstatic.service|   6 +
 .../usr/lib/systemd/system/runtime.service |   9 ++
 .../usr/lib/systemd/system/static.service  |   6 +
 .../usr/lib/systemd/system/templating@.service |   9 ++
 .../lib/systemd/system/templating@three.service|   9 ++
 .../usr/lib/systemd/system/templating@two.service  |   9 ++
 .../usr/lib/systemd/system/unique.service  |   9 ++
 32 files changed, 322 insertions(+), 3 deletions(-)
 create mode 100644 src/test/test-enabled.c
 create mode 12 test/test-enabled-root/etc/systemd/system/masked.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/maskedstatic.service
 create mode 100644 test/test-enabled-root/etc/systemd/system/some.target
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@four.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@one.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@three.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@two.service
 create mode 12 
test/test-enabled-root/run/systemd/system/maskedruntime.service
 create mode 12 
test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
 create mode 100644 test/test-enabled-root/run/systemd/system/other.target
 create mode 12 
test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/another.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/disabled.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/invalid.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/masked.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/runtime.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/static.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/templating@.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/templating@three.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/templating@two.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/unique.service

diff --git 

[systemd-devel] [PATCH, v3 3/3] find_symlinks: adds a cache of enabled unit symbolic link state

2014-10-21 Thread Ken Sedgwick
The current find_symlinks_fd code traverses the config directories
duplicatively. This is a performance problem if 1000s of units are
being controlled. This patch adds a hashmap cache of symbolic link
state which is filled in one traversal and then consulted as needed to
prevent re-traversal.

The enabled_context cache lives in the manager struct.  Initially the
cache is empty and is filled on first use.  A pointer to the cache is
passed to all routines which can call find_symlinks_fd.  If a NULL is
passed to find_symlinks_fd a temporary cache is created and used for
the single call.

The cache has two levels, the first is keyed by config_path and the
second by the names and paths of the units.

The cache contains both forward and reverse mappings; from symbolic
link name to target and from target to symbolic link name.

The cache contains entries for both the basename of the unit and the
full path of the link name and target.

The test-enabled patch (previously submitted) checks that the results
of unit_file_get_state and unit_file_get_list do not change as a
result of this cache. This patch presumes the test-enabled patch has
already been applied.

The test-manyunits patch (previously submitted) checks that the
performance of unit_file_get_list is acceptable in the face of
thousands of units.  This patch presumes the test-manyunits patch has
already been applied.
---
 src/core/dbus-manager.c   |   6 +-
 src/core/manager.c|   6 +
 src/core/manager.h|   2 +
 src/core/unit.c   |   2 +-
 src/shared/install.c  | 283 ++
 src/shared/install.h  |  18 ++-
 src/systemctl/systemctl.c |   6 +-
 src/test/test-enabled.c   |  24 ++--
 src/test/test-install.c   |  87 +++---
 src/test/test-manyunits.c |  11 +-
 src/test/test-unit-file.c |   2 +-
 11 files changed, 339 insertions(+), 108 deletions(-)

diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 57db1c9..0ce41b0 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1403,7 +1403,7 @@ static int method_list_unit_files(sd_bus *bus, 
sd_bus_message *message, void *us
 if (!h)
 return -ENOMEM;
 
-r = unit_file_get_list(m-running_as == SYSTEMD_SYSTEM ? 
UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
+r = unit_file_get_list(m-running_as == SYSTEMD_SYSTEM ? 
UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h, m-enabled);
 if (r  0)
 goto fail;
 
@@ -1454,7 +1454,7 @@ static int method_get_unit_file_state(sd_bus *bus, 
sd_bus_message *message, void
 
 scope = m-running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : 
UNIT_FILE_USER;
 
-state = unit_file_get_state(scope, NULL, name);
+state = unit_file_get_state(scope, NULL, name, m-enabled);
 if (state  0)
 return state;
 
@@ -1843,7 +1843,7 @@ static int method_add_dependency_unit_files(sd_bus *bus, 
sd_bus_message *message
 
 scope = m-running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : 
UNIT_FILE_USER;
 
-r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, 
force, changes, n_changes);
+r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, 
force, NULL, changes, n_changes);
 if (r  0)
 return r;
 
diff --git a/src/core/manager.c b/src/core/manager.c
index 1a5d252..1eb9683 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -464,6 +464,10 @@ int manager_new(SystemdRunningAs running_as, bool 
test_run, Manager **_m) {
 if (r  0)
 goto fail;
 
+m-enabled = enabled_context_new();
+if (!m-enabled)
+goto fail;
+
 r = set_ensure_allocated(m-startup_units, NULL);
 if (r  0)
 goto fail;
@@ -821,6 +825,8 @@ void manager_free(Manager *m) {
 hashmap_free(m-watch_pids2);
 hashmap_free(m-watch_bus);
 
+enabled_context_free(m-enabled);
+
 set_free(m-startup_units);
 set_free(m-failed_units);
 
diff --git a/src/core/manager.h b/src/core/manager.h
index 8e3c146..3f54fe0 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -72,6 +72,7 @@ typedef enum ManagerExitCode {
 #include unit-name.h
 #include exit-status.h
 #include show-status.h
+#include install.h
 #include failure-action.h
 
 struct Manager {
@@ -82,6 +83,7 @@ struct Manager {
 /* Active jobs and units */
 Hashmap *units;  /* name string = Unit object n:1 */
 Hashmap *jobs;   /* job id = Job object 1:1 */
+EnabledContext *enabled; /* name string = is enabled */
 
 /* To make it easy to iterate through the units of a specific
  * type we maintain a per type linked list */
diff --git a/src/core/unit.c b/src/core/unit.c
index 0389e6e..3e29944 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2941,7 +2941,7 @@ UnitFileState unit_get_unit_file_state(Unit *u) {
 if (u-unit_file_state  0  

[systemd-devel] [PATCH, v3 2/3] tests: unit_file_get_list performance with many units

2014-10-21 Thread Ken Sedgwick
This test temporarily creates several thousand unit files and checks
the performance of unit_file_get_list.

This test is currently added to manual_tests only since it does not
pass.

This test does pass if the subsequent enabled unit cache patch is
applied.
---
 .gitignore|   1 +
 Makefile.am   |  13 -
 src/test/test-manyunits.c | 133 ++
 3 files changed, 146 insertions(+), 1 deletion(-)
 create mode 100644 src/test/test-manyunits.c

diff --git a/.gitignore b/.gitignore
index 97b2b2b..7d5c97c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -207,6 +207,7 @@
 /test-login-tables
 /test-loopback
 /test-machine-tables
+/test-manyunits
 /test-mmap-cache
 /test-namespace
 /test-network
diff --git a/Makefile.am b/Makefile.am
index 46d532c..12cae02 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1306,7 +1306,8 @@ manual_tests += \
test-install \
test-watchdog \
test-log \
-   test-ipcrm
+   test-ipcrm \
+   test-manyunits
 
 if HAVE_KMOD
 manual_tests += \
@@ -1819,6 +1820,16 @@ test_enabled_LDADD = \
libsystemd-shared.la \
libsystemd-internal.la
 
+test_manyunits_SOURCES = \
+   src/test/test-manyunits.c
+
+test_manyunits_LDADD = \
+   libsystemd-core.la \
+   libsystemd-units.la \
+   libsystemd-label.la \
+   libsystemd-shared.la \
+   libsystemd-internal.la
+
 test_watchdog_SOURCES = \
src/test/test-watchdog.c
 
diff --git a/src/test/test-manyunits.c b/src/test/test-manyunits.c
new file mode 100644
index 000..e76f04c
--- /dev/null
+++ b/src/test/test-manyunits.c
@@ -0,0 +1,133 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Pantheon, Inc.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see http://www.gnu.org/licenses/.
+***/
+
+#include errno.h
+#include fcntl.h
+#include stdio.h
+#include string.h
+#include sys/param.h
+#include unistd.h
+#include time.h
+
+#include manager.h
+#include macro.h
+#include util.h
+
+static const int NUNITS = 3000;
+
+static const char *root_dir;
+
+/* Cleanup the created unit files if we fail an assertion. */
+#define assert_se_cleanup(expr) \
+do {\
+if (_unlikely_(!(expr))) {  \
+cleanup_manyunits();\
+log_assert_failed(#expr, __FILE__, __LINE__,\
+  __PRETTY_FUNCTION__); \
+}   \
+} while (false) \
+
+static const char *many_path(int unitnum) {
+static char path[PATH_MAX];
+snprintf(path, PATH_MAX, %s/%s/many-%06d.service,
+ root_dir, usr/lib/systemd/system, unitnum);
+return path;
+}
+
+static const char *link_path(int unitnum) {
+static char path[PATH_MAX];
+snprintf(path, PATH_MAX, %s/%s/many-%06d.service,
+ root_dir, etc/systemd/system/some.target.wants, unitnum);
+return path;
+}
+
+static const char *another_path(void) {
+static char path[PATH_MAX];
+snprintf(path, PATH_MAX, %s/%s/another.service,
+ root_dir, usr/lib/systemd/system);
+return path;
+}
+
+
+static void cleanup_manyunits(void) {
+int unitnum;
+
+fprintf(stderr, removing %d unit files\n, NUNITS);
+
+for (unitnum = 0; unitnum  NUNITS; ++unitnum) {
+unlink(link_path(unitnum));
+unlink(many_path(unitnum));
+}
+}
+
+static void setup_manyunits(void) {
+int unitnum;
+const char *another;
+
+another = another_path();
+
+fprintf(stderr, creating %d unit files\n, NUNITS);
+
+for (unitnum = 0; unitnum  NUNITS; ++unitnum) {
+assert_se_cleanup(link(another, many_path(unitnum)) == 0);
+assert_se_cleanup(symlink(many_path(unitnum),
+  link_path(unitnum)) == 0);
+}
+}
+
+static void test_manyunits(void) {
+time_t t0, t1;
+int r = 0;
+int count = 0;
+Hashmap *h;
+UnitFileList *p;
+Iterator 

[systemd-devel] [PATCH] test-manyunits: test unit_file_get_list perforamnce with many units

2014-10-17 Thread Ken Sedgwick
This test temporarily creates several thousand unit files and checks
the performance of unit_file_get_list.

This test is currently added to manual_tests only since it does not
pass.

This test does pass if the enabled unit cache patch is applied.
---
 .gitignore|   1 +
 Makefile.am   |  13 -
 src/test/test-manyunits.c | 133 ++
 3 files changed, 146 insertions(+), 1 deletion(-)
 create mode 100644 src/test/test-manyunits.c

diff --git a/.gitignore b/.gitignore
index 97b2b2b..7d5c97c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -207,6 +207,7 @@
 /test-login-tables
 /test-loopback
 /test-machine-tables
+/test-manyunits
 /test-mmap-cache
 /test-namespace
 /test-network
diff --git a/Makefile.am b/Makefile.am
index 46d532c..12cae02 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1306,7 +1306,8 @@ manual_tests += \
test-install \
test-watchdog \
test-log \
-   test-ipcrm
+   test-ipcrm \
+   test-manyunits
 
 if HAVE_KMOD
 manual_tests += \
@@ -1819,6 +1820,16 @@ test_enabled_LDADD = \
libsystemd-shared.la \
libsystemd-internal.la
 
+test_manyunits_SOURCES = \
+   src/test/test-manyunits.c
+
+test_manyunits_LDADD = \
+   libsystemd-core.la \
+   libsystemd-units.la \
+   libsystemd-label.la \
+   libsystemd-shared.la \
+   libsystemd-internal.la
+
 test_watchdog_SOURCES = \
src/test/test-watchdog.c
 
diff --git a/src/test/test-manyunits.c b/src/test/test-manyunits.c
new file mode 100644
index 000..e76f04c
--- /dev/null
+++ b/src/test/test-manyunits.c
@@ -0,0 +1,133 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Pantheon, Inc.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see http://www.gnu.org/licenses/.
+***/
+
+#include errno.h
+#include fcntl.h
+#include stdio.h
+#include string.h
+#include sys/param.h
+#include unistd.h
+#include time.h
+
+#include manager.h
+#include macro.h
+#include util.h
+
+static const int NUNITS = 3000;
+
+static const char *root_dir;
+
+/* Cleanup the created unit files if we fail an assertion. */
+#define assert_se_cleanup(expr) \
+do {\
+if (_unlikely_(!(expr))) {  \
+cleanup_manyunits();\
+log_assert_failed(#expr, __FILE__, __LINE__,\
+  __PRETTY_FUNCTION__); \
+}   \
+} while (false) \
+
+static const char *many_path(int unitnum) {
+static char path[PATH_MAX];
+snprintf(path, PATH_MAX, %s/%s/many-%06d.service,
+ root_dir, usr/lib/systemd/system, unitnum);
+return path;
+}
+
+static const char *link_path(int unitnum) {
+static char path[PATH_MAX];
+snprintf(path, PATH_MAX, %s/%s/many-%06d.service,
+ root_dir, etc/systemd/system/some.target.wants, unitnum);
+return path;
+}
+
+static const char *another_path(void) {
+static char path[PATH_MAX];
+snprintf(path, PATH_MAX, %s/%s/another.service,
+ root_dir, usr/lib/systemd/system);
+return path;
+}
+
+
+static void cleanup_manyunits(void) {
+int unitnum;
+
+fprintf(stderr, removing %d unit files\n, NUNITS);
+
+for (unitnum = 0; unitnum  NUNITS; ++unitnum) {
+unlink(link_path(unitnum));
+unlink(many_path(unitnum));
+}
+}
+
+static void setup_manyunits(void) {
+int unitnum;
+const char *another;
+
+another = another_path();
+
+fprintf(stderr, creating %d unit files\n, NUNITS);
+
+for (unitnum = 0; unitnum  NUNITS; ++unitnum) {
+assert_se_cleanup(link(another, many_path(unitnum)) == 0);
+assert_se_cleanup(symlink(many_path(unitnum),
+  link_path(unitnum)) == 0);
+}
+}
+
+static void test_manyunits(void) {
+time_t t0, t1;
+int r = 0;
+int count = 0;
+Hashmap *h;
+UnitFileList *p;
+Iterator i;
+
+ 

[systemd-devel] [PATCH, REVIEW, v2] find_symlinks: adds a cache of enabled unit symbolic link state

2014-10-17 Thread Ken Sedgwick
The current find_symlinks_fd code traverses the config directories
duplicatively. This is a performance problem if 1000s of units are
being controlled. This patch adds a hashmap cache of symbolic link
state which is filled in one traversal and then consulted as needed to
prevent re-traversal.

The enabled_context cache lives in the manager struct.  Initially the
cache is empty and is filled on first use.  A pointer to the cache is
passed to all routines which can call find_symlinks_fd.  If a NULL is
passed to find_symlinks_fd a temporary cache is created and used for
the single call.

The cache has two levels, the first is keyed by config_path and the
second by the names and paths of the units.

The cache contains both forward and reverse mappings; from symbolic
link name to target and from target to symbolic link name.

The cache contains entries for both the basename of the unit and the
full path of the link name and target.

The test-enabled patch (previously submitted) checks that the results
of unit_file_get_state and unit_file_get_list do not change as a
result of this cache. This patch presumes the test-enabled patch has
already been applied.

The test-manyunits patch (previously submitted) checks that the performance
of unit_file_get_list is acceptable in the face of thousands of units.
This patch presumes the test-manyunits patch has already been applied.
---
 src/core/dbus-manager.c   |   6 +-
 src/core/manager.c|   6 +
 src/core/manager.h|   2 +
 src/core/unit.c   |   2 +-
 src/shared/install.c  | 273 +-
 src/shared/install.h  |  18 ++-
 src/systemctl/systemctl.c |   6 +-
 src/test/test-enabled.c   |  24 ++--
 src/test/test-install.c   |  87 ---
 src/test/test-manyunits.c |  11 +-
 src/test/test-unit-file.c |   2 +-
 11 files changed, 325 insertions(+), 112 deletions(-)

diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 57db1c9..0ce41b0 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1403,7 +1403,7 @@ static int method_list_unit_files(sd_bus *bus, 
sd_bus_message *message, void *us
 if (!h)
 return -ENOMEM;
 
-r = unit_file_get_list(m-running_as == SYSTEMD_SYSTEM ? 
UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
+r = unit_file_get_list(m-running_as == SYSTEMD_SYSTEM ? 
UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h, m-enabled);
 if (r  0)
 goto fail;
 
@@ -1454,7 +1454,7 @@ static int method_get_unit_file_state(sd_bus *bus, 
sd_bus_message *message, void
 
 scope = m-running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : 
UNIT_FILE_USER;
 
-state = unit_file_get_state(scope, NULL, name);
+state = unit_file_get_state(scope, NULL, name, m-enabled);
 if (state  0)
 return state;
 
@@ -1843,7 +1843,7 @@ static int method_add_dependency_unit_files(sd_bus *bus, 
sd_bus_message *message
 
 scope = m-running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : 
UNIT_FILE_USER;
 
-r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, 
force, changes, n_changes);
+r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, 
force, NULL, changes, n_changes);
 if (r  0)
 return r;
 
diff --git a/src/core/manager.c b/src/core/manager.c
index 726977f..f8f41fb 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -465,6 +465,10 @@ int manager_new(SystemdRunningAs running_as, bool 
test_run, Manager **_m) {
 if (r  0)
 goto fail;
 
+m-enabled = enabled_context_new();
+if (!m-enabled)
+goto fail;
+
 r = set_ensure_allocated(m-startup_units, NULL);
 if (r  0)
 goto fail;
@@ -822,6 +826,8 @@ void manager_free(Manager *m) {
 hashmap_free(m-watch_pids2);
 hashmap_free(m-watch_bus);
 
+enabled_context_free(m-enabled);
+
 set_free(m-startup_units);
 set_free(m-failed_units);
 
diff --git a/src/core/manager.h b/src/core/manager.h
index 8e3c146..3f54fe0 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -72,6 +72,7 @@ typedef enum ManagerExitCode {
 #include unit-name.h
 #include exit-status.h
 #include show-status.h
+#include install.h
 #include failure-action.h
 
 struct Manager {
@@ -82,6 +83,7 @@ struct Manager {
 /* Active jobs and units */
 Hashmap *units;  /* name string = Unit object n:1 */
 Hashmap *jobs;   /* job id = Job object 1:1 */
+EnabledContext *enabled; /* name string = is enabled */
 
 /* To make it easy to iterate through the units of a specific
  * type we maintain a per type linked list */
diff --git a/src/core/unit.c b/src/core/unit.c
index 0389e6e..3e29944 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2941,7 +2941,7 @@ UnitFileState unit_get_unit_file_state(Unit *u) {
 if (u-unit_file_state  0  

[systemd-devel] [PATCH v3] tests: added tests for unit_file_get_{state, list}

2014-10-14 Thread Ken Sedgwick
This test constructs different unit file states and checks the output
of unit_file_get_state and unit_file_get_list for each.

This test characterizes the current output of the master branch in
preparation for a patch which improves the performance of unit state
detection in the face of thousands of units.
---
 .gitignore |   1 +
 Makefile.am|  44 ++-
 src/test/test-enabled.c| 141 +
 .../etc/systemd/system/masked.service  |   1 +
 .../etc/systemd/system/maskedstatic.service|   1 +
 .../etc/systemd/system/some.target |  11 ++
 .../system/some.target.wants/aliased.service   |   1 +
 .../system/some.target.wants/also_masked.service   |   1 +
 .../system/some.target.wants/another.service   |   1 +
 .../system/some.target.wants/different.service |   1 +
 .../system/some.target.wants/masked.service|   1 +
 .../some.target.wants/templating@four.service  |   1 +
 .../some.target.wants/templating@one.service   |   1 +
 .../some.target.wants/templating@three.service |   1 +
 .../some.target.wants/templating@two.service   |   1 +
 .../run/systemd/system/maskedruntime.service   |   1 +
 .../run/systemd/system/maskedruntimestatic.service |   1 +
 .../run/systemd/system/other.target|  14 ++
 .../system/other.target.wants/runtime.service  |   1 +
 .../usr/lib/systemd/system/another.service |   9 ++
 .../usr/lib/systemd/system/disabled.service|   9 ++
 .../usr/lib/systemd/system/invalid.service |   1 +
 .../usr/lib/systemd/system/masked.service  |   9 ++
 .../usr/lib/systemd/system/maskedruntime.service   |   9 ++
 .../lib/systemd/system/maskedruntimestatic.service |   6 +
 .../usr/lib/systemd/system/maskedstatic.service|   6 +
 .../usr/lib/systemd/system/runtime.service |   9 ++
 .../usr/lib/systemd/system/static.service  |   6 +
 .../usr/lib/systemd/system/templating@.service |   9 ++
 .../lib/systemd/system/templating@three.service|   9 ++
 .../usr/lib/systemd/system/templating@two.service  |   9 ++
 .../usr/lib/systemd/system/unique.service  |   9 ++
 32 files changed, 322 insertions(+), 3 deletions(-)
 create mode 100644 src/test/test-enabled.c
 create mode 12 test/test-enabled-root/etc/systemd/system/masked.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/maskedstatic.service
 create mode 100644 test/test-enabled-root/etc/systemd/system/some.target
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@four.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@one.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@three.service
 create mode 12 
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@two.service
 create mode 12 
test/test-enabled-root/run/systemd/system/maskedruntime.service
 create mode 12 
test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
 create mode 100644 test/test-enabled-root/run/systemd/system/other.target
 create mode 12 
test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/another.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/disabled.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/invalid.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/masked.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/runtime.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/static.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/templating@.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/templating@three.service
 create mode 100644 
test/test-enabled-root/usr/lib/systemd/system/templating@two.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/unique.service

diff --git 

[systemd-devel] [PATCH, REVIEW] Added unit enabled-context cache to improve performance w/ many units.

2014-10-08 Thread Ken Sedgwick
Resubmitting using git format-patch, git imap-send ... no code changes.

---
 .gitignore |   1 +
 Makefile.am|  44 +++-
 src/core/dbus-manager.c|   4 +-
 src/core/manager.c |   6 +
 src/core/manager.h |   2 +
 src/core/unit.c|   2 +-
 src/shared/install.c   | 268 +
 src/shared/install.h   |  16 +-
 src/systemctl/systemctl.c  |   4 +-
 src/test/test-enabled.c| 151 
 src/test/test-install.c|  87 ---
 src/test/test-unit-file.c  |   2 +-
 .../etc/systemd/system/masked.service  |   1 +
 .../etc/systemd/system/maskedstatic.service|   1 +
 .../etc/systemd/system/some.target |  11 +
 .../system/some.target.wants/aliased.service   |   1 +
 .../system/some.target.wants/also_masked.service   |   1 +
 .../system/some.target.wants/another.service   |   1 +
 .../system/some.target.wants/different.service |   1 +
 .../system/some.target.wants/masked.service|   1 +
 .../some.target.wants/templating@four.service  |   1 +
 .../some.target.wants/templating@one.service   |   1 +
 .../some.target.wants/templating@three.service |   1 +
 .../some.target.wants/templating@two.service   |   1 +
 .../run/systemd/system/maskedruntime.service   |   1 +
 .../run/systemd/system/maskedruntimestatic.service |   1 +
 .../run/systemd/system/other.target|  14 ++
 .../system/other.target.wants/runtime.service  |   1 +
 .../usr/lib/systemd/system/another.service |   9 +
 .../usr/lib/systemd/system/disabled.service|   9 +
 .../usr/lib/systemd/system/invalid.service |   1 +
 .../usr/lib/systemd/system/masked.service  |   9 +
 .../usr/lib/systemd/system/maskedruntime.service   |   9 +
 .../lib/systemd/system/maskedruntimestatic.service |   6 +
 .../usr/lib/systemd/system/maskedstatic.service|   6 +
 .../usr/lib/systemd/system/runtime.service |   9 +
 .../usr/lib/systemd/system/static.service  |   6 +
 .../usr/lib/systemd/system/templating@.service |   9 +
 .../lib/systemd/system/templating@three.service|   9 +
 .../usr/lib/systemd/system/templating@two.service  |   9 +
 .../usr/lib/systemd/system/unique.service  |   9 +
 41 files changed, 626 insertions(+), 100 deletions(-)
 create mode 100644 src/test/test-enabled.c
 create mode 12 test/test-enabled-root/etc/systemd/system/masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/maskedstatic.service
 create mode 100644 test/test-enabled-root/etc/systemd/system/some.target
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@four.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@one.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@three.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@two.service
 create mode 12
test/test-enabled-root/run/systemd/system/maskedruntime.service
 create mode 12
test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
 create mode 100644 test/test-enabled-root/run/systemd/system/other.target
 create mode 12
test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/another.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/disabled.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/invalid.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/masked.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/runtime.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/static.service
 create mode 100644

[systemd-devel] [PATCH 0/3 v2] Added test for unit file state returned by unit_file_get_state and unit_file_get_list.

2014-10-07 Thread Ken Sedgwick
Ken Sedgwick (3):
  Added test for unit file state returned by unit_file_get_state and
unit_file_get_list.
  Made test-enabled units more basic, removing superfluous fields.
  Cleaned up test path assignment code.
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 1/3] Added test for unit file state returned by unit_file_get_state and unit_file_get_list.

2014-10-07 Thread Ken Sedgwick
---
 .gitignore |   1 +
 Makefile.am|  44 ++-
 src/test/test-enabled.c| 143 +
 .../etc/systemd/system/masked.service  |   1 +
 .../etc/systemd/system/maskedstatic.service|   1 +
 .../etc/systemd/system/some.target |  15 +++
 .../system/some.target.wants/aliased.service   |   1 +
 .../system/some.target.wants/also_masked.service   |   1 +
 .../system/some.target.wants/another.service   |   1 +
 .../system/some.target.wants/different.service |   1 +
 .../system/some.target.wants/masked.service|   1 +
 .../some.target.wants/templating@four.service  |   1 +
 .../some.target.wants/templating@one.service   |   1 +
 .../some.target.wants/templating@three.service |   1 +
 .../some.target.wants/templating@two.service   |   1 +
 .../run/systemd/system/maskedruntime.service   |   1 +
 .../run/systemd/system/maskedruntimestatic.service |   1 +
 .../run/systemd/system/other.target|  15 +++
 .../system/other.target.wants/runtime.service  |   1 +
 .../usr/lib/systemd/system/another.service |  12 ++
 .../usr/lib/systemd/system/disabled.service|  12 ++
 .../usr/lib/systemd/system/invalid.service |   1 +
 .../usr/lib/systemd/system/masked.service  |  12 ++
 .../usr/lib/systemd/system/maskedruntime.service   |  12 ++
 .../lib/systemd/system/maskedruntimestatic.service |   9 ++
 .../usr/lib/systemd/system/maskedstatic.service|   9 ++
 .../usr/lib/systemd/system/runtime.service |  12 ++
 .../usr/lib/systemd/system/static.service  |   9 ++
 .../usr/lib/systemd/system/templating@.service |  12 ++
 .../lib/systemd/system/templating@three.service|  12 ++
 .../usr/lib/systemd/system/templating@two.service  |  12 ++
 .../usr/lib/systemd/system/unique.service  |  12 ++
 32 files changed, 365 insertions(+), 3 deletions(-)
 create mode 100644 src/test/test-enabled.c
 create mode 12 test/test-enabled-root/etc/systemd/system/masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/maskedstatic.service
 create mode 100644 test/test-enabled-root/etc/systemd/system/some.target
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@four.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@one.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@three.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@two.service
 create mode 12
test/test-enabled-root/run/systemd/system/maskedruntime.service
 create mode 12
test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
 create mode 100644 test/test-enabled-root/run/systemd/system/other.target
 create mode 12
test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/another.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/disabled.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/invalid.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/masked.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/runtime.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/static.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@three.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@two.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/unique.service

diff --git a/.gitignore b/.gitignore
index f119b57..97b2b2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -173,6 +173,7 @@
 /test-icmp6-rs
 /test-ellipsize
 /test-engine
+/test-enabled
 /test-env-replace
 /test-event
 /test-fdset
diff --git a/Makefile.am b/Makefile.am
index 60011b7..3d782fa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1355,7 

[systemd-devel] [PATCH 2/3] Made test-enabled units more basic, removing superfluous fields.

2014-10-07 Thread Ken Sedgwick
---
 test/test-enabled-root/etc/systemd/system/some.target  | 6 +-
 test/test-enabled-root/run/systemd/system/other.target | 3 +--
 test/test-enabled-root/usr/lib/systemd/system/another.service  | 7 ++-
 test/test-enabled-root/usr/lib/systemd/system/disabled.service | 7 ++-
 test/test-enabled-root/usr/lib/systemd/system/masked.service   | 7 ++-
 .../test-enabled-root/usr/lib/systemd/system/maskedruntime.service | 7 ++-
 .../usr/lib/systemd/system/maskedruntimestatic.service | 7 ++-
 test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service | 7 ++-
 test/test-enabled-root/usr/lib/systemd/system/runtime.service  | 7 ++-
 test/test-enabled-root/usr/lib/systemd/system/static.service   | 7 ++-
 test/test-enabled-root/usr/lib/systemd/system/templating@.service  | 7 ++-
 .../usr/lib/systemd/system/templating@three.service| 7 ++-
 .../usr/lib/systemd/system/templating@two.service  | 7 ++-
 test/test-enabled-root/usr/lib/systemd/system/unique.service   | 7 ++-
 14 files changed, 26 insertions(+), 67 deletions(-)

diff --git a/test/test-enabled-root/etc/systemd/system/some.target
b/test/test-enabled-root/etc/systemd/system/some.target
index a2c4532..06eb04e 100644
--- a/test/test-enabled-root/etc/systemd/system/some.target
+++ b/test/test-enabled-root/etc/systemd/system/some.target
@@ -6,10 +6,6 @@
 #  (at your option) any later version.

 [Unit]
-Description=Graphical Interface
-Documentation=man:systemd.special(7)
+Description=Some sort of target.
 Requires=multi-user.target
 After=multi-user.target
-Conflicts=rescue.target
-Wants=display-manager.service
-AllowIsolate=yes
diff --git a/test/test-enabled-root/run/systemd/system/other.target
b/test/test-enabled-root/run/systemd/system/other.target
index a2c4532..0f54eb3 100644
--- a/test/test-enabled-root/run/systemd/system/other.target
+++ b/test/test-enabled-root/run/systemd/system/other.target
@@ -6,8 +6,7 @@
 #  (at your option) any later version.

 [Unit]
-Description=Graphical Interface
-Documentation=man:systemd.special(7)
+Description=Other Target
 Requires=multi-user.target
 After=multi-user.target
 Conflicts=rescue.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/another.service
b/test/test-enabled-root/usr/lib/systemd/system/another.service
index 669548a..e4ea7f3 100644
--- a/test/test-enabled-root/usr/lib/systemd/system/another.service
+++ b/test/test-enabled-root/usr/lib/systemd/system/another.service
@@ -1,12 +1,9 @@
 [Unit]
-Description=Crash recovery kernel arming
-After=network.target network-online.target remote-fs.target
+Description=Another Service

 [Service]
 Type=oneshot
-ExecStart=/usr/bin/kdumpctl start
-ExecStop=/usr/bin/kdumpctl stop
-RemainAfterExit=yes
+ExecStart=/bin/echo Another Service Start

 [Install]
 WantedBy=some.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/disabled.service
b/test/test-enabled-root/usr/lib/systemd/system/disabled.service
index 669548a..f1d1fc6 100644
--- a/test/test-enabled-root/usr/lib/systemd/system/disabled.service
+++ b/test/test-enabled-root/usr/lib/systemd/system/disabled.service
@@ -1,12 +1,9 @@
 [Unit]
-Description=Crash recovery kernel arming
-After=network.target network-online.target remote-fs.target
+Description=Disabled Service

 [Service]
 Type=oneshot
-ExecStart=/usr/bin/kdumpctl start
-ExecStop=/usr/bin/kdumpctl stop
-RemainAfterExit=yes
+ExecStart=/bin/echo Disabled Service Start

 [Install]
 WantedBy=some.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/masked.service
b/test/test-enabled-root/usr/lib/systemd/system/masked.service
index 669548a..7a64302 100644
--- a/test/test-enabled-root/usr/lib/systemd/system/masked.service
+++ b/test/test-enabled-root/usr/lib/systemd/system/masked.service
@@ -1,12 +1,9 @@
 [Unit]
-Description=Crash recovery kernel arming
-After=network.target network-online.target remote-fs.target
+Description=Masked Service

 [Service]
 Type=oneshot
-ExecStart=/usr/bin/kdumpctl start
-ExecStop=/usr/bin/kdumpctl stop
-RemainAfterExit=yes
+ExecStart=/bin/echo Masked Service Start

 [Install]
 WantedBy=some.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
b/test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
index 669548a..db50f6e 100644
--- a/test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
+++ b/test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
@@ -1,12 +1,9 @@
 [Unit]
-Description=Crash recovery kernel arming
-After=network.target network-online.target remote-fs.target
+Description=Masked Runtime Service

 [Service]
 Type=oneshot
-ExecStart=/usr/bin/kdumpctl start
-ExecStop=/usr/bin/kdumpctl stop
-RemainAfterExit=yes
+ExecStart=/bin/echo Masked Runtime Service Start

 [Install]
 WantedBy=some.target
diff --git 

[systemd-devel] [PATCH 3/3] Cleaned up test path assignment code.

2014-10-07 Thread Ken Sedgwick
---
 src/test/test-enabled.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/test/test-enabled.c b/src/test/test-enabled.c
index 607f68c..104348e 100644
--- a/src/test/test-enabled.c
+++ b/src/test/test-enabled.c
@@ -75,9 +75,6 @@
 */


-const char *subdir = /test-enabled-root;
-char root_dir[UNIT_NAME_MAX + 2 + 1] = TEST_DIR;
-
 #define confirm_unit_state(unit, expected)  \
 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
unit) == expected)

@@ -86,8 +83,9 @@ static void test_enabled(int argc, char* argv[]) {
 UnitFileList *p;
 Iterator i;
 int r;
+const char *root_dir;

-strncat(root_dir, subdir, strlen(subdir));
+root_dir = strappenda(TEST_DIR, /test-enabled-root);

 confirm_unit_state(nonexistent.service, -ENOENT);
 confirm_unit_state(invalid.service, -EBADMSG);
-- 
1.9.3
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH, REVIEW] Added unit enabled-context cache to improve performance w/ many units.

2014-10-07 Thread Ken Sedgwick
The attached patch adds an EnabledContext cache so systems with 1000s of
units do not suffer
O(N^2) performance when determining unit state.  The test-enabled unit test
(added to master under other patch)
is used to confirm that the returned states are the same as the current
master.

Please review.

Many thanks in advance,

Ken

-- 
Ken Sedgwick
Bonsai Software, Inc.
http://www.bonsai.com/ken/
(510) 269-7334
k...@bonsai.com
Public Key: http://www.bonsai.com/ken/ken.asc
GPG Fingerprint: 851E 3B07 E586 0843 9434  5CC7 4033 3B9B 3F3F 9640
diff --git a/.gitignore b/.gitignore
index f119b57..97b2b2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -173,6 +173,7 @@
 /test-icmp6-rs
 /test-ellipsize
 /test-engine
+/test-enabled
 /test-env-replace
 /test-event
 /test-fdset
diff --git a/Makefile.am b/Makefile.am
index e52db17..7d4f2f5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1358,7 +1358,8 @@ tests += \
 	test-ratelimit \
 	test-condition-util \
 	test-uid-range \
-	test-bus-policy
+	test-bus-policy \
+	test-enabled
 
 EXTRA_DIST += \
 	test/a.service \
@@ -1394,8 +1395,36 @@ EXTRA_DIST += \
 	test/bus-policy/hello.conf \
 	test/bus-policy/methods.conf \
 	test/bus-policy/ownerships.conf \
-	test/bus-policy/signals.conf
-
+	test/bus-policy/signals.conf \
+	test/test-enabled-root/usr/lib/systemd/system/masked.service \
+	test/test-enabled-root/usr/lib/systemd/system/runtime.service \
+	test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service \
+	test/test-enabled-root/usr/lib/systemd/system/another.service \
+	test/test-enabled-root/usr/lib/systemd/system/templating@three.service \
+	test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service \
+	test/test-enabled-root/usr/lib/systemd/system/invalid.service \
+	test/test-enabled-root/usr/lib/systemd/system/disabled.service \
+	test/test-enabled-root/usr/lib/systemd/system/templating@two.service \
+	test/test-enabled-root/usr/lib/systemd/system/unique.service \
+	test/test-enabled-root/usr/lib/systemd/system/templating@.service \
+	test/test-enabled-root/usr/lib/systemd/system/static.service \
+	test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service \
+	test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service \
+	test/test-enabled-root/run/systemd/system/maskedruntime.service \
+	test/test-enabled-root/run/systemd/system/other.target \
+	test/test-enabled-root/run/systemd/system/maskedruntimestatic.service \
+	test/test-enabled-root/etc/systemd/system/masked.service \
+	test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service \
+	test/test-enabled-root/etc/systemd/system/some.target.wants/another.service \
+	test/test-enabled-root/etc/systemd/system/some.target.wants/templating@three.service \
+	test/test-enabled-root/etc/systemd/system/some.target.wants/templating@one.service \
+	test/test-enabled-root/etc/systemd/system/some.target.wants/templating@two.service \
+	test/test-enabled-root/etc/systemd/system/some.target.wants/templating@four.service \
+	test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service \
+	test/test-enabled-root/etc/systemd/system/some.target.wants/different.service \
+	test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service \
+	test/test-enabled-root/etc/systemd/system/maskedstatic.service \
+	test/test-enabled-root/etc/systemd/system/some.target
 
 EXTRA_DIST += \
 	src/test/test-helper.h
@@ -1782,6 +1811,15 @@ test_install_LDADD = \
 	libsystemd-shared.la \
 	libsystemd-internal.la
 
+test_enabled_SOURCES = \
+	src/test/test-enabled.c
+
+test_enabled_LDADD = \
+	libsystemd-units.la \
+	libsystemd-label.la \
+	libsystemd-shared.la \
+	libsystemd-internal.la
+
 test_watchdog_SOURCES = \
 	src/test/test-watchdog.c
 
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 533ce43..8dcd552 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1403,7 +1403,7 @@ static int method_list_unit_files(sd_bus *bus, sd_bus_message *message, void *us
 if (!h)
 return -ENOMEM;
 
-r = unit_file_get_list(m-running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
+r = unit_file_get_list(m-running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h, m-enabled);
 if (r  0)
 goto fail;
 
@@ -1454,7 +1454,7 @@ static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void
 
 scope = m-running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
 
-state = unit_file_get_state(scope, NULL, name);
+state = unit_file_get_state(scope, NULL, name, m-enabled);
 if (state  0)
 return state;
 
diff --git a/src/core/manager.c b/src/core/manager.c
index e0c1cd1..c9aef42 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -465,6 +465,10 @@ int manager_new(SystemdRunningAs running_as, bool test_run, Manager **_m) {
 if (r  0)
 goto

[systemd-devel] [PATCH v2] Added test for unit file state returned by unit_file_get_state and unit_file_get_list. Made test-enabled units more basic, removing superfluous fields. Cleaned up test path

2014-10-07 Thread Ken Sedgwick
---
 .gitignore |   1 +
 Makefile.am|  44 ++-
 src/test/test-enabled.c| 141 +
 .../etc/systemd/system/masked.service  |   1 +
 .../etc/systemd/system/maskedstatic.service|   1 +
 .../etc/systemd/system/some.target |  11 ++
 .../system/some.target.wants/aliased.service   |   1 +
 .../system/some.target.wants/also_masked.service   |   1 +
 .../system/some.target.wants/another.service   |   1 +
 .../system/some.target.wants/different.service |   1 +
 .../system/some.target.wants/masked.service|   1 +
 .../some.target.wants/templating@four.service  |   1 +
 .../some.target.wants/templating@one.service   |   1 +
 .../some.target.wants/templating@three.service |   1 +
 .../some.target.wants/templating@two.service   |   1 +
 .../run/systemd/system/maskedruntime.service   |   1 +
 .../run/systemd/system/maskedruntimestatic.service |   1 +
 .../run/systemd/system/other.target|  14 ++
 .../system/other.target.wants/runtime.service  |   1 +
 .../usr/lib/systemd/system/another.service |   9 ++
 .../usr/lib/systemd/system/disabled.service|   9 ++
 .../usr/lib/systemd/system/invalid.service |   1 +
 .../usr/lib/systemd/system/masked.service  |   9 ++
 .../usr/lib/systemd/system/maskedruntime.service   |   9 ++
 .../lib/systemd/system/maskedruntimestatic.service |   6 +
 .../usr/lib/systemd/system/maskedstatic.service|   6 +
 .../usr/lib/systemd/system/runtime.service |   9 ++
 .../usr/lib/systemd/system/static.service  |   6 +
 .../usr/lib/systemd/system/templating@.service |   9 ++
 .../lib/systemd/system/templating@three.service|   9 ++
 .../usr/lib/systemd/system/templating@two.service  |   9 ++
 .../usr/lib/systemd/system/unique.service  |   9 ++
 32 files changed, 322 insertions(+), 3 deletions(-)
 create mode 100644 src/test/test-enabled.c
 create mode 12 test/test-enabled-root/etc/systemd/system/masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/maskedstatic.service
 create mode 100644 test/test-enabled-root/etc/systemd/system/some.target
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@four.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@one.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@three.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@two.service
 create mode 12
test/test-enabled-root/run/systemd/system/maskedruntime.service
 create mode 12
test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
 create mode 100644 test/test-enabled-root/run/systemd/system/other.target
 create mode 12
test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/another.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/disabled.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/invalid.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/masked.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/runtime.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/static.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@three.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@two.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/unique.service

diff --git a/.gitignore b/.gitignore
index f119b57..97b2b2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -173,6 +173,7 @@
 /test-icmp6-rs
 /test-ellipsize
 /test-engine
+/test-enabled
 /test-env-replace
 /test-event
 /test-fdset
diff --git a/Makefile.am b/Makefile.am
index e52db17..7d4f2f5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1358,7 +1358,8 

[systemd-devel] [PATCH v2] Added test for unit file state returned by unit_file_get_state and unit_file_get_list

2014-10-07 Thread Ken Sedgwick
Combined initial submission and subsequent fixes into a single patch.

Ken Sedgwick (1):
  Added test for unit file state returned by unit_file_get_state and
unit_file_get_list. Made test-enabled units more basic, removing
superfluous fields. Cleaned up test path assignment code.

 .gitignore |   1 +
 Makefile.am|  44 ++-
 src/test/test-enabled.c| 141 +
 .../etc/systemd/system/masked.service  |   1 +
 .../etc/systemd/system/maskedstatic.service|   1 +
 .../etc/systemd/system/some.target |  11 ++
 .../system/some.target.wants/aliased.service   |   1 +
 .../system/some.target.wants/also_masked.service   |   1 +
 .../system/some.target.wants/another.service   |   1 +
 .../system/some.target.wants/different.service |   1 +
 .../system/some.target.wants/masked.service|   1 +
 .../some.target.wants/templating@four.service  |   1 +
 .../some.target.wants/templating@one.service   |   1 +
 .../some.target.wants/templating@three.service |   1 +
 .../some.target.wants/templating@two.service   |   1 +
 .../run/systemd/system/maskedruntime.service   |   1 +
 .../run/systemd/system/maskedruntimestatic.service |   1 +
 .../run/systemd/system/other.target|  14 ++
 .../system/other.target.wants/runtime.service  |   1 +
 .../usr/lib/systemd/system/another.service |   9 ++
 .../usr/lib/systemd/system/disabled.service|   9 ++
 .../usr/lib/systemd/system/invalid.service |   1 +
 .../usr/lib/systemd/system/masked.service  |   9 ++
 .../usr/lib/systemd/system/maskedruntime.service   |   9 ++
 .../lib/systemd/system/maskedruntimestatic.service |   6 +
 .../usr/lib/systemd/system/maskedstatic.service|   6 +
 .../usr/lib/systemd/system/runtime.service |   9 ++
 .../usr/lib/systemd/system/static.service  |   6 +
 .../usr/lib/systemd/system/templating@.service |   9 ++
 .../lib/systemd/system/templating@three.service|   9 ++
 .../usr/lib/systemd/system/templating@two.service  |   9 ++
 .../usr/lib/systemd/system/unique.service  |   9 ++
 32 files changed, 322 insertions(+), 3 deletions(-)
 create mode 100644 src/test/test-enabled.c
 create mode 12 test/test-enabled-root/etc/systemd/system/masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/maskedstatic.service
 create mode 100644 test/test-enabled-root/etc/systemd/system/some.target
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@four.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@one.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@three.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@two.service
 create mode 12
test/test-enabled-root/run/systemd/system/maskedruntime.service
 create mode 12
test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
 create mode 100644 test/test-enabled-root/run/systemd/system/other.target
 create mode 12
test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/another.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/disabled.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/invalid.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/masked.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/runtime.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/static.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@three.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@two.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/unique.service

-- 
1.9.3

Re: [systemd-devel] [PATCH] Added test for unit file state returned by unit_file_get_state and unit_file_get_list.

2014-10-05 Thread Ken Sedgwick
Will do.

Ken

On Sun, Oct 5, 2014 at 2:27 PM, Zbigniew Jędrzejewski-Szmek 
zbys...@in.waw.pl wrote:

 On Fri, Oct 03, 2014 at 04:03:14PM -0700, Ken Sedgwick wrote:
  +const char *subdir = /test-enabled-root;
  +char root_dir[UNIT_NAME_MAX + 2 + 1] = TEST_DIR;
  +
  +#define confirm_unit_state(unit, expected)
 \
  +assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
  unit) == expected)
  +
  +static void test_enabled(int argc, char* argv[]) {
  +Hashmap *h;
  +UnitFileList *p;
  +Iterator i;
  +int r;
  +
  +strncat(root_dir, subdir, strlen(subdir));

 This is safe, but ungainly. Why not just:

const char *root_dir;

root_dir = strappenda(TEST_DIR, /test-enabled-root);

 Test looks useful, but like David wrote, can you please remove the
 non-essential
 bits from the service files?

 Zbyszek




-- 
Ken Sedgwick
Bonsai Software, Inc.
http://www.bonsai.com/ken/
(510) 269-7334
k...@bonsai.com
Public Key: http://www.bonsai.com/ken/ken.asc
GPG Fingerprint: 851E 3B07 E586 0843 9434  5CC7 4033 3B9B 3F3F 9640
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH] Added test for unit file state returned by unit_file_get_state and unit_file_get_list.

2014-10-03 Thread Ken Sedgwick
---
 .gitignore |   1 +
 Makefile.am|  44 ++-
 src/test/test-enabled.c| 143 +
 .../etc/systemd/system/masked.service  |   1 +
 .../etc/systemd/system/maskedstatic.service|   1 +
 .../etc/systemd/system/some.target |  15 +++
 .../system/some.target.wants/aliased.service   |   1 +
 .../system/some.target.wants/also_masked.service   |   1 +
 .../system/some.target.wants/another.service   |   1 +
 .../system/some.target.wants/different.service |   1 +
 .../system/some.target.wants/masked.service|   1 +
 .../some.target.wants/templating@four.service  |   1 +
 .../some.target.wants/templating@one.service   |   1 +
 .../some.target.wants/templating@three.service |   1 +
 .../some.target.wants/templating@two.service   |   1 +
 .../run/systemd/system/maskedruntime.service   |   1 +
 .../run/systemd/system/maskedruntimestatic.service |   1 +
 .../run/systemd/system/other.target|  15 +++
 .../system/other.target.wants/runtime.service  |   1 +
 .../usr/lib/systemd/system/another.service |  12 ++
 .../usr/lib/systemd/system/disabled.service|  12 ++
 .../usr/lib/systemd/system/invalid.service |   1 +
 .../usr/lib/systemd/system/masked.service  |  12 ++
 .../usr/lib/systemd/system/maskedruntime.service   |  12 ++
 .../lib/systemd/system/maskedruntimestatic.service |   9 ++
 .../usr/lib/systemd/system/maskedstatic.service|   9 ++
 .../usr/lib/systemd/system/runtime.service |  12 ++
 .../usr/lib/systemd/system/static.service  |   9 ++
 .../usr/lib/systemd/system/templating@.service |  12 ++
 .../lib/systemd/system/templating@three.service|  12 ++
 .../usr/lib/systemd/system/templating@two.service  |  12 ++
 .../usr/lib/systemd/system/unique.service  |  12 ++
 32 files changed, 365 insertions(+), 3 deletions(-)
 create mode 100644 src/test/test-enabled.c
 create mode 12 test/test-enabled-root/etc/systemd/system/masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/maskedstatic.service
 create mode 100644 test/test-enabled-root/etc/systemd/system/some.target
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@four.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@one.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@three.service
 create mode 12
test/test-enabled-root/etc/systemd/system/some.target.wants/templating@two.service
 create mode 12
test/test-enabled-root/run/systemd/system/maskedruntime.service
 create mode 12
test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
 create mode 100644 test/test-enabled-root/run/systemd/system/other.target
 create mode 12
test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/another.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/disabled.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/invalid.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/masked.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/runtime.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/static.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@three.service
 create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating@two.service
 create mode 100644 test/test-enabled-root/usr/lib/systemd/system/unique.service

diff --git a/.gitignore b/.gitignore
index f119b57..97b2b2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -173,6 +173,7 @@
 /test-icmp6-rs
 /test-ellipsize
 /test-engine
+/test-enabled
 /test-env-replace
 /test-event
 /test-fdset
diff --git a/Makefile.am b/Makefile.am
index 60011b7..3d782fa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1355,7