chiark / gitweb /
unit: reduce heap usage for unit objects
[elogind.git] / src / unit.c
index 56137d7bd14c60ae423c80884d0cb48a5dd536aa..fa3c2649b35b87cba48d1cf117021f0f7602fc34 100644 (file)
@@ -57,15 +57,18 @@ const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
         [UNIT_PATH] = &path_vtable
 };
 
-Unit *unit_new(Manager *m) {
+Unit *unit_new(Manager *m, size_t size) {
         Unit *u;
 
         assert(m);
+        assert(size >= sizeof(Meta));
 
-        if (!(u = new0(Unit, 1)))
+        u = malloc0(size);
+        if (!u)
                 return NULL;
 
-        if (!(u->meta.names = set_new(string_hash_func, string_compare_func))) {
+        u->meta.names = set_new(string_hash_func, string_compare_func);
+        if (!u->meta.names) {
                 free(u);
                 return NULL;
         }
@@ -377,12 +380,15 @@ void unit_free(Unit *u) {
 
         free(u->meta.description);
         free(u->meta.fragment_path);
+        free(u->meta.instance);
 
         set_free_free(u->meta.names);
 
         condition_free_list(u->meta.conditions);
 
-        free(u->meta.instance);
+        while (u->meta.refs)
+                unit_ref_unset(u->meta.refs);
+
         free(u);
 }
 
@@ -498,6 +504,10 @@ int unit_merge(Unit *u, Unit *other) {
         /* Merge names */
         merge_names(u, other);
 
+        /* Redirect all references */
+        while (other->meta.refs)
+                unit_ref_set(other->meta.refs, u);
+
         /* Merge dependencies */
         for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
                 merge_dependencies(u, other, d);
@@ -561,11 +571,15 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
 
         if (c->std_output != EXEC_OUTPUT_KMSG &&
             c->std_output != EXEC_OUTPUT_SYSLOG &&
+            c->std_output != EXEC_OUTPUT_JOURNAL &&
             c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
             c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
+            c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
             c->std_error != EXEC_OUTPUT_KMSG &&
             c->std_error != EXEC_OUTPUT_SYSLOG &&
+            c->std_error != EXEC_OUTPUT_JOURNAL &&
             c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
+            c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
             c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
                 return 0;
 
@@ -573,7 +587,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
          * logging daemon is run first. */
 
         if (u->meta.manager->running_as == MANAGER_SYSTEM)
-                if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_STDOUT_SYSLOG_BRIDGE_SOCKET, NULL, true)) < 0)
+                if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true)) < 0)
                         return r;
 
         return 0;
@@ -1105,6 +1119,14 @@ static void retroactively_stop_dependencies(Unit *u) {
         SET_FOREACH(other, u->meta.dependencies[UNIT_BOUND_BY], i)
                 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
                         manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
+}
+
+static void check_unneeded_dependencies(Unit *u) {
+        Iterator i;
+        Unit *other;
+
+        assert(u);
+        assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
 
         /* Garbage collect services that might not be needed anymore, if enabled */
         SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRES], i)
@@ -1263,6 +1285,10 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
                                 retroactively_stop_dependencies(u);
                 }
 
+                /* stop unneeded units regardless if going down was expected or not */
+                if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns))
+                        check_unneeded_dependencies(u);
+
                 if (ns != os && ns == UNIT_FAILED) {
                         log_notice("Unit %s entered failed state.", u->meta.id);
                         unit_trigger_on_failure(u);
@@ -1315,7 +1341,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
                 }
         }
 
-        manager_recheck_syslog(u->meta.manager);
+        manager_recheck_journal(u->meta.manager);
 
         /* Maybe we finished startup and are now ready for being
          * stopped because unneeded? */
@@ -1514,7 +1540,11 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
                 [UNIT_AFTER] = UNIT_BEFORE,
                 [UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID,
                 [UNIT_REFERENCES] = UNIT_REFERENCED_BY,
-                [UNIT_REFERENCED_BY] = UNIT_REFERENCES
+                [UNIT_REFERENCED_BY] = UNIT_REFERENCES,
+                [UNIT_TRIGGERS] = UNIT_TRIGGERED_BY,
+                [UNIT_TRIGGERED_BY] = UNIT_TRIGGERS,
+                [UNIT_PROPAGATE_RELOAD_TO] = UNIT_PROPAGATE_RELOAD_FROM,
+                [UNIT_PROPAGATE_RELOAD_FROM] = UNIT_PROPAGATE_RELOAD_TO
         };
         int r, q = 0, v = 0, w = 0;
 
@@ -2429,9 +2459,6 @@ int unit_coldplug(Unit *u) {
 
 void unit_status_printf(Unit *u, const char *status, const char *format, ...) {
         va_list ap;
-        char *s, *e;
-        int err;
-        const unsigned emax = status ? 80 - (sizeof("[  OK  ]")-1) : 80;
 
         assert(u);
         assert(format);
@@ -2446,21 +2473,8 @@ void unit_status_printf(Unit *u, const char *status, const char *format, ...) {
                 return;
 
         va_start(ap, format);
-        err = vasprintf(&s, format, ap);
+        status_vprintf(status, true, format, ap);
         va_end(ap);
-        if (err < 0)
-                return;
-
-        e = ellipsize(s, emax, 100);
-        free(s);
-        if (!e)
-                return;
-
-        if (status)
-                status_printf("%s%*s[%s]\n", e, emax - strlen(e), "", status);
-        else
-                status_printf("%s\n", e);
-        free(e);
 }
 
 bool unit_need_daemon_reload(Unit *u) {
@@ -2592,6 +2606,28 @@ UnitFileState unit_get_unit_file_state(Unit *u) {
         return u->meta.unit_file_state;
 }
 
+Unit* unit_ref_set(UnitRef *ref, Unit *u) {
+        assert(ref);
+        assert(u);
+
+        if (ref->unit)
+                unit_ref_unset(ref);
+
+        ref->unit = u;
+        LIST_PREPEND(UnitRef, refs, u->meta.refs, ref);
+        return u;
+}
+
+void unit_ref_unset(UnitRef *ref) {
+        assert(ref);
+
+        if (!ref->unit)
+                return;
+
+        LIST_REMOVE(UnitRef, refs, ref->unit->meta.refs, ref);
+        ref->unit = NULL;
+}
+
 static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
         [UNIT_STUB] = "stub",
         [UNIT_LOADED] = "loaded",
@@ -2630,7 +2666,11 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
         [UNIT_AFTER] = "After",
         [UNIT_REFERENCES] = "References",
         [UNIT_REFERENCED_BY] = "ReferencedBy",
-        [UNIT_ON_FAILURE] = "OnFailure"
+        [UNIT_ON_FAILURE] = "OnFailure",
+        [UNIT_TRIGGERS] = "Triggers",
+        [UNIT_TRIGGERED_BY] = "TriggeredBy",
+        [UNIT_PROPAGATE_RELOAD_TO] = "PropagateReloadTo",
+        [UNIT_PROPAGATE_RELOAD_FROM] = "PropagateReloadFrom"
 };
 
 DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);