diff options
-rw-r--r-- | src/core/job.c | 33 | ||||
-rw-r--r-- | src/core/transaction.c | 4 |
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; } |