chiark / gitweb /
unit: add new abstracted maintenance state for units
[elogind.git] / src / unit.c
index c12c2a7deb3fa02b7f297e8d91137ce655401287..79b9e2bb8a0f8dc9563a6f6e42439e8bdb03a5fb 100644 (file)
@@ -365,8 +365,12 @@ void unit_free(Unit *u) {
 UnitActiveState unit_active_state(Unit *u) {
         assert(u);
 
 UnitActiveState unit_active_state(Unit *u) {
         assert(u);
 
-        if (u->meta.load_state != UNIT_LOADED)
-                return UNIT_INACTIVE;
+        if (u->meta.load_state == UNIT_MERGED)
+                return unit_active_state(unit_follow_merge(u));
+
+        /* After a reload it might happen that a unit is not correctly
+         * loaded but still has a process around. That's why we won't
+         * shortcut failed loading to UNIT_INACTIVE_MAINTENANCE. */
 
         return UNIT_VTABLE(u)->active_state(u);
 }
 
         return UNIT_VTABLE(u)->active_state(u);
 }
@@ -463,7 +467,7 @@ int unit_merge(Unit *u, Unit *other) {
         if (other->meta.job)
                 return -EEXIST;
 
         if (other->meta.job)
                 return -EEXIST;
 
-        if (unit_active_state(other) != UNIT_INACTIVE)
+        if (!UNIT_IS_INACTIVE_OR_MAINTENANCE(unit_active_state(other)))
                 return -EEXIST;
 
         /* Merge names */
                 return -EEXIST;
 
         /* Merge names */
@@ -542,7 +546,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
         if ((r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_LOGGER_SOCKET, NULL, true)) < 0)
                 return r;
 
         if ((r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_LOGGER_SOCKET, NULL, true)) < 0)
                 return r;
 
-        if (u->meta.manager->running_as != MANAGER_SESSION)
+        if (u->meta.manager->running_as == MANAGER_SYSTEM)
                 if ((r = unit_add_dependency_by_name(u, UNIT_REQUIRES, SPECIAL_LOGGER_SOCKET, NULL, true)) < 0)
                         return r;
 
                 if ((r = unit_add_dependency_by_name(u, UNIT_REQUIRES, SPECIAL_LOGGER_SOCKET, NULL, true)) < 0)
                         return r;
 
@@ -746,6 +750,9 @@ int unit_start(Unit *u) {
 
         assert(u);
 
 
         assert(u);
 
+        if (u->meta.load_state != UNIT_LOADED)
+                return -EINVAL;
+
         /* If this is already (being) started, then this will
          * succeed. Note that this will even succeed if this unit is
          * not startable by the user. This is relied on to detect when
         /* If this is already (being) started, then this will
          * succeed. Note that this will even succeed if this unit is
          * not startable by the user. This is relied on to detect when
@@ -785,7 +792,7 @@ int unit_stop(Unit *u) {
         assert(u);
 
         state = unit_active_state(u);
         assert(u);
 
         state = unit_active_state(u);
-        if (state == UNIT_INACTIVE)
+        if (UNIT_IS_INACTIVE_OR_MAINTENANCE(state))
                 return -EALREADY;
 
         if (!UNIT_VTABLE(u)->stop)
                 return -EALREADY;
 
         if (!UNIT_VTABLE(u)->stop)
@@ -805,6 +812,9 @@ int unit_reload(Unit *u) {
 
         assert(u);
 
 
         assert(u);
 
+        if (u->meta.load_state != UNIT_LOADED)
+                return -EINVAL;
+
         if (!unit_can_reload(u))
                 return -EBADR;
 
         if (!unit_can_reload(u))
                 return -EBADR;
 
@@ -926,7 +936,7 @@ static void retroactively_stop_dependencies(Unit *u) {
 
 void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
         bool unexpected = false;
 
 void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
         bool unexpected = false;
-        timestamp ts;
+        dual_timestamp ts;
 
         assert(u);
         assert(os < _UNIT_ACTIVE_STATE_MAX);
 
         assert(u);
         assert(os < _UNIT_ACTIVE_STATE_MAX);
@@ -939,11 +949,11 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
          * this function will be called too and the utmp code below
          * relies on that! */
 
          * this function will be called too and the utmp code below
          * relies on that! */
 
-        timestamp_get(&ts);
+        dual_timestamp_get(&ts);
 
 
-        if (os == UNIT_INACTIVE && ns != UNIT_INACTIVE)
+        if (UNIT_IS_INACTIVE_OR_MAINTENANCE(os) && !UNIT_IS_INACTIVE_OR_MAINTENANCE(ns))
                 u->meta.inactive_exit_timestamp = ts;
                 u->meta.inactive_exit_timestamp = ts;
-        else if (os != UNIT_INACTIVE && ns == UNIT_INACTIVE)
+        else if (!UNIT_IS_INACTIVE_OR_MAINTENANCE(os) && UNIT_IS_INACTIVE_OR_MAINTENANCE(ns))
                 u->meta.inactive_enter_timestamp = ts;
 
         if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns))
                 u->meta.inactive_enter_timestamp = ts;
 
         if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns))
@@ -1002,6 +1012,8 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
 
                         if (ns == UNIT_INACTIVE)
                                 job_finish_and_invalidate(u->meta.job, true);
 
                         if (ns == UNIT_INACTIVE)
                                 job_finish_and_invalidate(u->meta.job, true);
+                        else if (ns == UNIT_INACTIVE_MAINTENANCE)
+                                job_finish_and_invalidate(u->meta.job, false);
                         else if (u->meta.job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
                                 unexpected = true;
                                 job_finish_and_invalidate(u->meta.job, false);
                         else if (u->meta.job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
                                 unexpected = true;
                                 job_finish_and_invalidate(u->meta.job, false);
@@ -1952,7 +1964,9 @@ DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
 
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
         [UNIT_ACTIVE] = "active",
 
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
         [UNIT_ACTIVE] = "active",
+        [UNIT_ACTIVE_RELOADING] = "active-reloading",
         [UNIT_INACTIVE] = "inactive",
         [UNIT_INACTIVE] = "inactive",
+        [UNIT_INACTIVE_MAINTENANCE] = "inactive-maintenance",
         [UNIT_ACTIVATING] = "activating",
         [UNIT_DEACTIVATING] = "deactivating"
 };
         [UNIT_ACTIVATING] = "activating",
         [UNIT_DEACTIVATING] = "deactivating"
 };