After a larger transaction, e.g. after bootup, we're left with an empty hashmap
with hundreds of buckets. Long-term, it'd be better to size hashmaps down when
they are less than 1/4 full, but even if we implement that, jobs hashmap is
likely to be empty almost always, so it seems useful to deallocate it once the
jobs count reaches 0.
return log_unit_debug_errno(j->unit, SYNTHETIC_ERRNO(EEXIST),
"Unit already has a job installed. Not installing deserialized job.");
+ r = hashmap_ensure_allocated(&j->manager->jobs, NULL);
+ if (r < 0)
+ return r;
+
r = hashmap_put(j->manager->jobs, UINT32_TO_PTR(j->id), j);
if (r == -EEXIST)
return log_unit_debug_errno(j->unit, r, "Job ID %" PRIu32 " already used, cannot deserialize job.", j->id);
if (r < 0)
return r;
- r = hashmap_ensure_allocated(&m->jobs, NULL);
- if (r < 0)
- return r;
-
r = hashmap_ensure_allocated(&m->cgroup_unit, &path_hash_ops);
if (r < 0)
return r;
return;
}
+ /* The jobs hashmap tends to grow a lot during boot, and then it's not reused until shutdown. Let's
+ kill the hashmap if it is relatively large. */
+ if (hashmap_buckets(m->jobs) > hashmap_size(m->units) / 10)
+ m->jobs = hashmap_free(m->jobs);
+
manager_flip_auto_status(m, false, "boot finished");
/* Notify Type=idle units that we are done now */
assert(!j->transaction_prev);
assert(!j->transaction_next);
+ r = hashmap_ensure_allocated(&m->jobs, NULL);
+ if (r < 0)
+ return r;
+
r = hashmap_put(m->jobs, UINT32_TO_PTR(j->id), j);
if (r < 0)
goto rollback;