Hi list!

First patch removes StopWhenUnneeded= when service starts, if service  will be 
stopped after start, because WantedBy=,RequiredBy,.. is empty.

Second one allows templated enable, like:

 > grep WantedBy ~/.config/systemd/user/mpop@.timer           
WantedBy=services@%i.target

> srv disable mpop@iit.timer
rm '/home/alxchk/.config/systemd/user/services@iit.target.wants/mpop@iit.timer'
alxchk > srv enable mpop@iit.timer       
ln -s '/home/alxchk/.config/systemd/user/mpop@.timer' 
'/home/alxchk/.config/systemd/user/services@iit.target.wants/mpop@iit.timer'

diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index c7bf043..06c5d25 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -1096,7 +1096,7 @@ const BusProperty bus_unit_properties[] = {
         { "CanReload",            bus_unit_append_can_reload,         "b", 0 },
         { "CanIsolate",           bus_unit_append_can_isolate,        "b", 0 },
         { "Job",                  bus_unit_append_job,             "(uo)", 0 },
-        { "StopWhenUnneeded",     bus_property_append_bool,           "b", offsetof(Unit, stop_when_unneeded)                 },
+        { "StopWhenUnneeded",     bus_property_append_bool,           "b", offsetof(Unit, stop_when_unneeded_runtime)         },
         { "RefuseManualStart",    bus_property_append_bool,           "b", offsetof(Unit, refuse_manual_start)                },
         { "RefuseManualStop",     bus_property_append_bool,           "b", offsetof(Unit, refuse_manual_stop)                 },
         { "AllowIsolate",         bus_property_append_bool,           "b", offsetof(Unit, allow_isolate)                      },
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 7fba0cf..4f3e52a 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -114,7 +114,7 @@ Unit.ReloadPropagatedFrom,       config_parse_unit_deps,             UNIT_RELOAD
 Unit.PropagateReloadFrom,        config_parse_unit_deps,             UNIT_RELOAD_PROPAGATED_FROM,   0
 Unit.PartOf,                     config_parse_unit_deps,             UNIT_PART_OF,                  0
 Unit.RequiresMountsFor,          config_parse_unit_requires_mounts_for, 0,                          offsetof(Unit, requires_mounts_for)
-Unit.StopWhenUnneeded,           config_parse_bool,                  0,                             offsetof(Unit, stop_when_unneeded)
+Unit.StopWhenUnneeded,           config_parse_bool,                  0,                             offsetof(Unit, stop_when_unneeded_unit)
 Unit.RefuseManualStart,          config_parse_bool,                  0,                             offsetof(Unit, refuse_manual_start)
 Unit.RefuseManualStop,           config_parse_bool,                  0,                             offsetof(Unit, refuse_manual_stop)
 Unit.AllowIsolate,               config_parse_bool,                  0,                             offsetof(Unit, allow_isolate)
diff --git a/src/core/unit.c b/src/core/unit.c
index 1194c52..b4dfa68 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -731,7 +731,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                         "%s\tOnFailureIsolate: %s\n"
                         "%s\tIgnoreOnIsolate: %s\n"
                         "%s\tIgnoreOnSnapshot: %s\n",
-                        prefix, yes_no(u->stop_when_unneeded),
+                        prefix, yes_no(u->stop_when_unneeded_unit),
                         prefix, yes_no(u->refuse_manual_start),
                         prefix, yes_no(u->refuse_manual_stop),
                         prefix, yes_no(u->default_dependencies),
@@ -1063,6 +1063,14 @@ int unit_start(Unit *u) {
                 return -EALREADY;
         }
 
+        u->stop_when_unneeded_runtime = u->stop_when_unneeded_unit;
+
+        if (unit_unneeded(u)) {
+                log_debug("Started unneded unit %s with StopWhenUnneeded=yes."
+                         "Disabling unneeded property.", u->id);
+                u->stop_when_unneeded_runtime = false;
+        }
+
         /* Forward to the main object, if we aren't it. */
         if ((following = unit_following(u))) {
                 log_debug("Redirecting start request from %s to %s.", u->id, following->id);
@@ -1178,36 +1186,44 @@ bool unit_can_reload(Unit *u) {
         return UNIT_VTABLE(u)->can_reload(u);
 }
 
-static void unit_check_unneeded(Unit *u) {
+bool unit_unneeded(Unit *u) {
         Iterator i;
         Unit *other;
 
         assert(u);
 
+        if (!u->stop_when_unneeded_runtime)
+                return false;
+
+        SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
+                if (unit_pending_active(other))
+                        return false;
+
+        SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
+                if (unit_pending_active(other))
+                        return false;
+
+        SET_FOREACH(other, u->dependencies[UNIT_WANTED_BY], i)
+                if (unit_pending_active(other))
+                        return false;
+
+        SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
+                if (unit_pending_active(other))
+                        return false;
+
+        return true;
+}
+
+static void unit_check_unneeded(Unit *u) {
+
         /* If this service shall be shut down when unneeded then do
          * so. */
 
-        if (!u->stop_when_unneeded)
-                return;
-
         if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))
                 return;
 
-        SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
-                if (unit_pending_active(other))
-                        return;
-
-        SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
-                if (unit_pending_active(other))
-                        return;
-
-        SET_FOREACH(other, u->dependencies[UNIT_WANTED_BY], i)
-                if (unit_pending_active(other))
-                        return;
-
-        SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
-                if (unit_pending_active(other))
-                        return;
+        if (! unit_unneeded(u))
+                return;
 
         log_info("Service %s is not needed anymore. Stopping.", u->id);
 
diff --git a/src/core/unit.h b/src/core/unit.h
index d1ecae7..4ba5628 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -198,7 +198,8 @@ struct Unit {
         UnitFileState unit_file_state;
 
         /* Garbage collect us we nobody wants or requires us anymore */
-        bool stop_when_unneeded;
+        bool stop_when_unneeded_unit;
+        bool stop_when_unneeded_runtime;
 
         /* Create default dependencies */
         bool default_dependencies;
@@ -479,6 +480,7 @@ bool unit_can_isolate(Unit *u);
 int unit_start(Unit *u);
 int unit_stop(Unit *u);
 int unit_reload(Unit *u);
+bool unit_unneeded(Unit *u);
 
 int unit_kill(Unit *u, KillWho w, int signo, DBusError *error);
 
diff --git a/src/shared/log.c b/src/shared/log.c
index 8d3458e..3aa1a13 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -1,4 +1,4 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+//*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 
 /***
   This file is part of systemd.
diff --git a/src/shared/install.c b/src/shared/install.c
index a9d75f3..49100a4 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -36,6 +36,7 @@
 #include "install.h"
 #include "conf-parser.h"
 #include "conf-files.h"
+#include "specifier.h"
 
 typedef struct {
         char *name;
@@ -51,6 +52,33 @@ typedef struct {
         Hashmap *have_installed;
 } InstallContext;
 
+static char *name_printf(char * prefix, char * instance, char* format) {
+
+        /*
+         * This will use the passed string as format string and
+         * replace the following specifiers, if any:
+         *
+         * %p: the unit prefix
+         * %i: the instance
+         *
+         * Pass empty_prefix and empty_instance, if not specified,
+         * to get better error.
+         */
+
+        char empty_prefix[]   = "%p";
+        char empty_instance[] = "%i";
+
+        const Specifier table[] = {
+                { 'p', specifier_string, prefix   ? : empty_prefix},
+                { 'i', specifier_string, instance ? : empty_instance},
+                { 0, NULL, NULL }
+        };
+
+        assert(format);
+
+        return specifier_printf(format, table, NULL);
+}
+
 static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
         assert(paths);
         assert(scope >= 0);
@@ -1271,13 +1299,21 @@ static int install_info_symlink_wants(
 
         STRV_FOREACH(s, i->wanted_by) {
                 char *path;
+                char *instance = NULL;
+                char *prefix   = NULL;
+                char *dst      = NULL;
 
-                if (!unit_name_is_valid(*s, true)) {
+                unit_name_to_instance(i->name, &instance);
+                prefix = unit_name_to_prefix(i->name);
+
+                dst = name_printf(prefix, instance, *s);
+
+                if (!unit_name_is_valid(dst, true)) {
                         r = -EINVAL;
                         continue;
                 }
 
-                if (asprintf(&path, "%s/%s.wants/%s", config_path, *s, i->name) < 0)
+                if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
                         return -ENOMEM;
 
                 q = create_symlink(i->path, path, force, changes, n_changes);
_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to