From: Mike Yuan Date: Sat, 4 Oct 2025 22:39:50 +0000 (+0200) Subject: core/transaction: assign unique ids to transactions and encode them in log X-Git-Tag: v259-rc1~68^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0d9e79d5caf541ab991fc6bd5f4063e876358ede;p=thirdparty%2Fsystemd.git core/transaction: assign unique ids to transactions and encode them in log Preparation for later commits, but I think this one makes a ton of sense on its own. When debug logging is enabled it's otherwise difficult to dig up the portion of journal for transaction construction. --- diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c index 469f51f448e..df97fde97ed 100644 --- a/src/core/manager-serialize.c +++ b/src/core/manager-serialize.c @@ -92,6 +92,8 @@ int manager_serialize( _cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m); + (void) serialize_item_format(f, "last-transaction-id", "%" PRIu64, m->last_transaction_id); + (void) serialize_item_format(f, "current-job-id", "%" PRIu32, m->current_job_id); (void) serialize_item_format(f, "n-installed-jobs", "%u", m->n_installed_jobs); (void) serialize_item_format(f, "n-failed-jobs", "%u", m->n_failed_jobs); @@ -325,7 +327,15 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { if (r == 0) /* eof or end marker */ break; - if ((val = startswith(l, "current-job-id="))) { + if ((val = startswith(l, "last-transaction-id="))) { + uint64_t id; + + if (safe_atou64(val, &id) < 0) + log_notice("Failed to parse last transaction id value '%s', ignoring.", val); + else + m->last_transaction_id = MAX(m->last_transaction_id, id); + + } else if ((val = startswith(l, "current-job-id="))) { uint32_t id; if (safe_atou32(val, &id) < 0) diff --git a/src/core/manager.c b/src/core/manager.c index b501d3f1c5b..bb2c1bece13 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2153,14 +2153,16 @@ int manager_add_job_full( if (mode == JOB_RESTART_DEPENDENCIES && type != JOB_START) return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "--job-mode=restart-dependencies is only valid for start."); + tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY, ++m->last_transaction_id); + if (!tr) + return -ENOMEM; + + LOG_CONTEXT_PUSHF("TRANSACTION_ID=%" PRIu64, tr->id); + log_unit_debug(unit, "Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode)); type = job_type_collapse(type, unit); - tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY); - if (!tr) - return -ENOMEM; - r = transaction_add_job_and_dependencies( tr, type, @@ -2247,18 +2249,20 @@ int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, } int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e) { - int r; _cleanup_(transaction_abort_and_freep) Transaction *tr = NULL; + int r; assert(m); assert(unit); assert(mode < _JOB_MODE_MAX); assert(mode != JOB_ISOLATE); /* Isolate is only valid for start */ - tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY); + tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY, ++m->last_transaction_id); if (!tr) return -ENOMEM; + LOG_CONTEXT_PUSHF("TRANSACTION_ID=%" PRIu64, tr->id); + /* We need an anchor job */ r = transaction_add_job_and_dependencies(tr, JOB_NOP, unit, NULL, TRANSACTION_IGNORE_REQUIREMENTS|TRANSACTION_IGNORE_ORDER, e); if (r < 0) diff --git a/src/core/manager.h b/src/core/manager.h index b7ee766b05d..d0855260bfc 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -236,6 +236,8 @@ typedef struct Manager { /* A set which contains all currently failed units */ Set *failed_units; + uint64_t last_transaction_id; + sd_event_source *run_queue_event_source; char *notify_socket; diff --git a/src/core/transaction.c b/src/core/transaction.c index 016bbb1f975..34a0faf5568 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -1235,20 +1235,24 @@ int transaction_add_triggering_jobs(Transaction *tr, Unit *u) { return 0; } -Transaction* transaction_new(bool irreversible) { - Transaction *tr; +Transaction* transaction_new(bool irreversible, uint64_t id) { + _cleanup_free_ Transaction *tr = NULL; - tr = new0(Transaction, 1); + assert(id != 0); + + tr = new(Transaction, 1); if (!tr) return NULL; - tr->jobs = hashmap_new(NULL); + *tr = (Transaction) { + .jobs = hashmap_new(NULL), + .irreversible = irreversible, + .id = id, + }; if (!tr->jobs) - return mfree(tr); - - tr->irreversible = irreversible; + return NULL; - return tr; + return TAKE_PTR(tr); } Transaction* transaction_free(Transaction *tr) { diff --git a/src/core/transaction.h b/src/core/transaction.h index 4f5430d6d4a..275dc5984f8 100644 --- a/src/core/transaction.h +++ b/src/core/transaction.h @@ -8,9 +8,11 @@ typedef struct Transaction { Hashmap *jobs; /* Unit object => Job object list 1:1 */ Job *anchor_job; /* The job the user asked for */ bool irreversible; + + uint64_t id; } Transaction; -Transaction* transaction_new(bool irreversible); +Transaction* transaction_new(bool irreversible, uint64_t id); Transaction* transaction_free(Transaction *tr); Transaction* transaction_abort_and_free(Transaction *tr); DEFINE_TRIVIAL_CLEANUP_FUNC(Transaction*, transaction_abort_and_free);