summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/job.c33
-rw-r--r--src/core/transaction.c4
2 files changed, 32 insertions, 5 deletions
diff --git a/src/core/job.c b/src/core/job.c
index 826ef6809c..24f407ad83 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -48,6 +48,28 @@ Job* job_new_raw(Unit *unit) {
return j;
}
+static uint32_t manager_get_new_job_id(Manager *m) {
+ bool overflow = false;
+
+ assert(m);
+
+ for (;;) {
+ uint32_t id = m->current_job_id;
+
+ if (_unlikely_(id == UINT32_MAX)) {
+ assert_se(!overflow);
+ m->current_job_id = 1;
+ overflow = true;
+ } else
+ m->current_job_id++;
+
+ if (hashmap_contains(m->jobs, UINT32_TO_PTR(id)))
+ continue;
+
+ return id;
+ }
+}
+
Job* job_new(Unit *unit, JobType type) {
Job *j;
@@ -57,7 +79,7 @@ Job* job_new(Unit *unit, JobType type) {
if (!j)
return NULL;
- j->id = j->manager->current_job_id++;
+ j->id = manager_get_new_job_id(j->manager);
j->type = type;
/* We don't link it here, that's what job_dependency() is for */
@@ -237,6 +259,7 @@ Job* job_install(Job *j) {
}
/* Install the job */
+ assert(!*pj);
*pj = j;
j->installed = true;
@@ -261,14 +284,18 @@ int job_install_deserialized(Job *j) {
if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION)
return log_unit_debug_errno(j->unit, SYNTHETIC_ERRNO(EINVAL),
- "Invalid job type %s in deserialization.",
- strna(job_type_to_string(j->type)));
+ "Invalid job type %s in deserialization.",
+ strna(job_type_to_string(j->type)));
pj = j->type == JOB_NOP ? &j->unit->nop_job : &j->unit->job;
if (*pj)
return log_unit_debug_errno(j->unit, SYNTHETIC_ERRNO(EEXIST),
"Unit already has a job installed. Not installing deserialized job.");
+ /* When the job does not have ID, or we failed to deserialize the job ID, then use a new ID. */
+ if (j->id <= 0)
+ j->id = manager_get_new_job_id(j->manager);
+
r = hashmap_ensure_put(&j->manager->jobs, NULL, 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);
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 059558ebc0..cd0c28123f 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -662,7 +662,7 @@ static int transaction_apply(
/* j has been merged into a previously installed job */
if (tr->anchor_job == j)
tr->anchor_job = installed_job;
- hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
+ hashmap_remove_value(m->jobs, UINT32_TO_PTR(j->id), j);
job_free(j);
j = installed_job;
}
@@ -683,7 +683,7 @@ static int transaction_apply(
rollback:
HASHMAP_FOREACH(j, tr->jobs)
- hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
+ hashmap_remove_value(m->jobs, UINT32_TO_PTR(j->id), j);
return r;
}