chiark / gitweb /
Fix a few more typos
[elogind.git] / src / core / transaction.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <unistd.h>
23 #include <fcntl.h>
24
25 #include "bus-errors.h"
26 #include "bus-util.h"
27 #include "bus-error.h"
28 #include "transaction.h"
29
30 static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
31
32 static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependencies) {
33         assert(tr);
34         assert(j);
35
36         /* Deletes one job from the transaction */
37
38         transaction_unlink_job(tr, j, delete_dependencies);
39
40         job_free(j);
41 }
42
43 static void transaction_delete_unit(Transaction *tr, Unit *u) {
44         Job *j;
45
46         /* Deletes all jobs associated with a certain unit from the
47          * transaction */
48
49         while ((j = hashmap_get(tr->jobs, u)))
50                 transaction_delete_job(tr, j, true);
51 }
52
53 void transaction_abort(Transaction *tr) {
54         Job *j;
55
56         assert(tr);
57
58         while ((j = hashmap_first(tr->jobs)))
59                 transaction_delete_job(tr, j, false);
60
61         assert(hashmap_isempty(tr->jobs));
62 }
63
64 static void transaction_find_jobs_that_matter_to_anchor(Job *j, unsigned generation) {
65         JobDependency *l;
66
67         /* A recursive sweep through the graph that marks all units
68          * that matter to the anchor job, i.e. are directly or
69          * indirectly a dependency of the anchor job via paths that
70          * are fully marked as mattering. */
71
72         j->matters_to_anchor = true;
73         j->generation = generation;
74
75         LIST_FOREACH(subject, l, j->subject_list) {
76
77                 /* This link does not matter */
78                 if (!l->matters)
79                         continue;
80
81                 /* This unit has already been marked */
82                 if (l->object->generation == generation)
83                         continue;
84
85                 transaction_find_jobs_that_matter_to_anchor(l->object, generation);
86         }
87 }
88
89 static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other, JobType t) {
90         JobDependency *l, *last;
91
92         assert(j);
93         assert(other);
94         assert(j->unit == other->unit);
95         assert(!j->installed);
96
97         /* Merges 'other' into 'j' and then deletes 'other'. */
98
99         j->type = t;
100         j->state = JOB_WAITING;
101         j->override = j->override || other->override;
102         j->irreversible = j->irreversible || other->irreversible;
103
104         j->matters_to_anchor = j->matters_to_anchor || other->matters_to_anchor;
105
106         /* Patch us in as new owner of the JobDependency objects */
107         last = NULL;
108         LIST_FOREACH(subject, l, other->subject_list) {
109                 assert(l->subject == other);
110                 l->subject = j;
111                 last = l;
112         }
113
114         /* Merge both lists */
115         if (last) {
116                 last->subject_next = j->subject_list;
117                 if (j->subject_list)
118                         j->subject_list->subject_prev = last;
119                 j->subject_list = other->subject_list;
120         }
121
122         /* Patch us in as new owner of the JobDependency objects */
123         last = NULL;
124         LIST_FOREACH(object, l, other->object_list) {
125                 assert(l->object == other);
126                 l->object = j;
127                 last = l;
128         }
129
130         /* Merge both lists */
131         if (last) {
132                 last->object_next = j->object_list;
133                 if (j->object_list)
134                         j->object_list->object_prev = last;
135                 j->object_list = other->object_list;
136         }
137
138         /* Kill the other job */
139         other->subject_list = NULL;
140         other->object_list = NULL;
141         transaction_delete_job(tr, other, true);
142 }
143
144 _pure_ static bool job_is_conflicted_by(Job *j) {
145         JobDependency *l;
146
147         assert(j);
148
149         /* Returns true if this job is pulled in by a least one
150          * ConflictedBy dependency. */
151
152         LIST_FOREACH(object, l, j->object_list)
153                 if (l->conflicts)
154                         return true;
155
156         return false;
157 }
158
159 static int delete_one_unmergeable_job(Transaction *tr, Job *j) {
160         Job *k;
161
162         assert(j);
163
164         /* Tries to delete one item in the linked list
165          * j->transaction_next->transaction_next->... that conflicts
166          * with another one, in an attempt to make an inconsistent
167          * transaction work. */
168
169         /* We rely here on the fact that if a merged with b does not
170          * merge with c, either a or b merge with c neither */
171         LIST_FOREACH(transaction, j, j)
172                 LIST_FOREACH(transaction, k, j->transaction_next) {
173                         Job *d;
174
175                         /* Is this one mergeable? Then skip it */
176                         if (job_type_is_mergeable(j->type, k->type))
177                                 continue;
178
179                         /* Ok, we found two that conflict, let's see if we can
180                          * drop one of them */
181                         if (!j->matters_to_anchor && !k->matters_to_anchor) {
182
183                                 /* Both jobs don't matter, so let's
184                                  * find the one that is smarter to
185                                  * remove. Let's think positive and
186                                  * rather remove stops then starts --
187                                  * except if something is being
188                                  * stopped because it is conflicted by
189                                  * another unit in which case we
190                                  * rather remove the start. */
191
192                                 log_debug_unit(j->unit->id,
193                                                "Looking at job %s/%s conflicted_by=%s",
194                                                j->unit->id, job_type_to_string(j->type),
195                                                yes_no(j->type == JOB_STOP && job_is_conflicted_by(j)));
196                                 log_debug_unit(k->unit->id,
197                                                "Looking at job %s/%s conflicted_by=%s",
198                                                k->unit->id, job_type_to_string(k->type),
199                                                yes_no(k->type == JOB_STOP && job_is_conflicted_by(k)));
200
201                                 if (j->type == JOB_STOP) {
202
203                                         if (job_is_conflicted_by(j))
204                                                 d = k;
205                                         else
206                                                 d = j;
207
208                                 } else if (k->type == JOB_STOP) {
209
210                                         if (job_is_conflicted_by(k))
211                                                 d = j;
212                                         else
213                                                 d = k;
214                                 } else
215                                         d = j;
216
217                         } else if (!j->matters_to_anchor)
218                                 d = j;
219                         else if (!k->matters_to_anchor)
220                                 d = k;
221                         else
222                                 return -ENOEXEC;
223
224                         /* Ok, we can drop one, so let's do so. */
225                         log_debug_unit(d->unit->id,
226                                        "Fixing conflicting jobs %s/%s,%s/%s by deleting job %s/%s",
227                                        j->unit->id, job_type_to_string(j->type),
228                                        k->unit->id, job_type_to_string(k->type),
229                                        d->unit->id, job_type_to_string(d->type));
230                         transaction_delete_job(tr, d, true);
231                         return 0;
232                 }
233
234         return -EINVAL;
235 }
236
237 static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
238         Job *j;
239         Iterator i;
240         int r;
241
242         assert(tr);
243
244         /* First step, check whether any of the jobs for one specific
245          * task conflict. If so, try to drop one of them. */
246         HASHMAP_FOREACH(j, tr->jobs, i) {
247                 JobType t;
248                 Job *k;
249
250                 t = j->type;
251                 LIST_FOREACH(transaction, k, j->transaction_next) {
252                         if (job_type_merge_and_collapse(&t, k->type, j->unit) >= 0)
253                                 continue;
254
255                         /* OK, we could not merge all jobs for this
256                          * action. Let's see if we can get rid of one
257                          * of them */
258
259                         r = delete_one_unmergeable_job(tr, j);
260                         if (r >= 0)
261                                 /* Ok, we managed to drop one, now
262                                  * let's ask our callers to call us
263                                  * again after garbage collecting */
264                                 return -EAGAIN;
265
266                         /* We couldn't merge anything. Failure */
267                         sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING,
268                                           "Transaction contains conflicting jobs '%s' and '%s' for %s. "
269                                           "Probably contradicting requirement dependencies configured.",
270                                           job_type_to_string(t),
271                                           job_type_to_string(k->type),
272                                           k->unit->id);
273                         return r;
274                 }
275         }
276
277         /* Second step, merge the jobs. */
278         HASHMAP_FOREACH(j, tr->jobs, i) {
279                 JobType t = j->type;
280                 Job *k;
281
282                 /* Merge all transaction jobs for j->unit */
283                 LIST_FOREACH(transaction, k, j->transaction_next)
284                         assert_se(job_type_merge_and_collapse(&t, k->type, j->unit) == 0);
285
286                 while ((k = j->transaction_next)) {
287                         if (tr->anchor_job == k) {
288                                 transaction_merge_and_delete_job(tr, k, j, t);
289                                 j = k;
290                         } else
291                                 transaction_merge_and_delete_job(tr, j, k, t);
292                 }
293
294                 assert(!j->transaction_next);
295                 assert(!j->transaction_prev);
296         }
297
298         return 0;
299 }
300
301 static void transaction_drop_redundant(Transaction *tr) {
302         Job *j;
303         Iterator i;
304
305         /* Goes through the transaction and removes all jobs of the units
306          * whose jobs are all noops. If not all of a unit's jobs are
307          * redundant, they are kept. */
308
309         assert(tr);
310
311 rescan:
312         HASHMAP_FOREACH(j, tr->jobs, i) {
313                 Job *k;
314
315                 LIST_FOREACH(transaction, k, j) {
316
317                         if (tr->anchor_job == k ||
318                             !job_type_is_redundant(k->type, unit_active_state(k->unit)) ||
319                             (k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type)))
320                                 goto next_unit;
321                 }
322
323                 /* log_debug("Found redundant job %s/%s, dropping.", j->unit->id, job_type_to_string(j->type)); */
324                 transaction_delete_job(tr, j, false);
325                 goto rescan;
326         next_unit:;
327         }
328 }
329
330 _pure_ static bool unit_matters_to_anchor(Unit *u, Job *j) {
331         assert(u);
332         assert(!j->transaction_prev);
333
334         /* Checks whether at least one of the jobs for this unit
335          * matters to the anchor. */
336
337         LIST_FOREACH(transaction, j, j)
338                 if (j->matters_to_anchor)
339                         return true;
340
341         return false;
342 }
343
344 static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, sd_bus_error *e) {
345         Iterator i;
346         Unit *u;
347         int r;
348
349         assert(tr);
350         assert(j);
351         assert(!j->transaction_prev);
352
353         /* Does a recursive sweep through the ordering graph, looking
354          * for a cycle. If we find a cycle we try to break it. */
355
356         /* Have we seen this before? */
357         if (j->generation == generation) {
358                 Job *k, *delete;
359
360                 /* If the marker is NULL we have been here already and
361                  * decided the job was loop-free from here. Hence
362                  * shortcut things and return right-away. */
363                 if (!j->marker)
364                         return 0;
365
366                 /* So, the marker is not NULL and we already have been
367                  * here. We have a cycle. Let's try to break it. We go
368                  * backwards in our path and try to find a suitable
369                  * job to remove. We use the marker to find our way
370                  * back, since smart how we are we stored our way back
371                  * in there. */
372                 log_warning_unit(j->unit->id,
373                                  "Found ordering cycle on %s/%s",
374                                  j->unit->id, job_type_to_string(j->type));
375
376                 delete = NULL;
377                 for (k = from; k; k = ((k->generation == generation && k->marker != k) ? k->marker : NULL)) {
378
379                         /* logging for j not k here here to provide consistent narrative */
380                         log_info_unit(j->unit->id,
381                                       "Found dependency on %s/%s",
382                                       k->unit->id, job_type_to_string(k->type));
383
384                         if (!delete && hashmap_get(tr->jobs, k->unit) &&
385                             !unit_matters_to_anchor(k->unit, k)) {
386                                 /* Ok, we can drop this one, so let's
387                                  * do so. */
388                                 delete = k;
389                         }
390
391                         /* Check if this in fact was the beginning of
392                          * the cycle */
393                         if (k == j)
394                                 break;
395                 }
396
397
398                 if (delete) {
399                         /* logging for j not k here here to provide consistent narrative */
400                         log_warning_unit(j->unit->id,
401                                          "Breaking ordering cycle by deleting job %s/%s",
402                                          delete->unit->id, job_type_to_string(delete->type));
403                         log_error_unit(delete->unit->id,
404                                        "Job %s/%s deleted to break ordering cycle starting with %s/%s",
405                                        delete->unit->id, job_type_to_string(delete->type),
406                                        j->unit->id, job_type_to_string(j->type));
407                         unit_status_printf(delete->unit, ANSI_HIGHLIGHT_RED_ON " SKIP " ANSI_HIGHLIGHT_OFF,
408                                            "Ordering cycle found, skipping %s");
409                         transaction_delete_unit(tr, delete->unit);
410                         return -EAGAIN;
411                 }
412
413                 log_error("Unable to break cycle");
414
415                 sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,
416                                   "Transaction order is cyclic. See system logs for details.");
417                 return -ENOEXEC;
418         }
419
420         /* Make the marker point to where we come from, so that we can
421          * find our way backwards if we want to break a cycle. We use
422          * a special marker for the beginning: we point to
423          * ourselves. */
424         j->marker = from ? from : j;
425         j->generation = generation;
426
427         /* We assume that the dependencies are bidirectional, and
428          * hence can ignore UNIT_AFTER */
429         SET_FOREACH(u, j->unit->dependencies[UNIT_BEFORE], i) {
430                 Job *o;
431
432                 /* Is there a job for this unit? */
433                 o = hashmap_get(tr->jobs, u);
434                 if (!o) {
435                         /* Ok, there is no job for this in the
436                          * transaction, but maybe there is already one
437                          * running? */
438                         o = u->job;
439                         if (!o)
440                                 continue;
441                 }
442
443                 r = transaction_verify_order_one(tr, o, j, generation, e);
444                 if (r < 0)
445                         return r;
446         }
447
448         /* Ok, let's backtrack, and remember that this entry is not on
449          * our path anymore. */
450         j->marker = NULL;
451
452         return 0;
453 }
454
455 static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bus_error *e) {
456         Job *j;
457         int r;
458         Iterator i;
459         unsigned g;
460
461         assert(tr);
462         assert(generation);
463
464         /* Check if the ordering graph is cyclic. If it is, try to fix
465          * that up by dropping one of the jobs. */
466
467         g = (*generation)++;
468
469         HASHMAP_FOREACH(j, tr->jobs, i)
470                 if ((r = transaction_verify_order_one(tr, j, NULL, g, e)) < 0)
471                         return r;
472
473         return 0;
474 }
475
476 static void transaction_collect_garbage(Transaction *tr) {
477         Iterator i;
478         Job *j;
479
480         assert(tr);
481
482         /* Drop jobs that are not required by any other job */
483
484 rescan:
485         HASHMAP_FOREACH(j, tr->jobs, i) {
486                 if (tr->anchor_job == j || j->object_list) {
487                         /* log_debug("Keeping job %s/%s because of %s/%s", */
488                         /*           j->unit->id, job_type_to_string(j->type), */
489                         /*           j->object_list->subject ? j->object_list->subject->unit->id : "root", */
490                         /*           j->object_list->subject ? job_type_to_string(j->object_list->subject->type) : "root"); */
491                         continue;
492                 }
493
494                 /* log_debug("Garbage collecting job %s/%s", j->unit->id, job_type_to_string(j->type)); */
495                 transaction_delete_job(tr, j, true);
496                 goto rescan;
497         }
498 }
499
500 static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_error *e) {
501         Iterator i;
502         Job *j;
503
504         assert(tr);
505
506         /* Checks whether applying this transaction means that
507          * existing jobs would be replaced */
508
509         HASHMAP_FOREACH(j, tr->jobs, i) {
510
511                 /* Assume merged */
512                 assert(!j->transaction_prev);
513                 assert(!j->transaction_next);
514
515                 if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) &&
516                     !job_type_is_superset(j->type, j->unit->job->type)) {
517
518                         sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE,
519                                           "Transaction is destructive.");
520                         return -EEXIST;
521                 }
522         }
523
524         return 0;
525 }
526
527 static void transaction_minimize_impact(Transaction *tr) {
528         Job *j;
529         Iterator i;
530
531         assert(tr);
532
533         /* Drops all unnecessary jobs that reverse already active jobs
534          * or that stop a running service. */
535
536 rescan:
537         HASHMAP_FOREACH(j, tr->jobs, i) {
538                 LIST_FOREACH(transaction, j, j) {
539                         bool stops_running_service, changes_existing_job;
540
541                         /* If it matters, we shouldn't drop it */
542                         if (j->matters_to_anchor)
543                                 continue;
544
545                         /* Would this stop a running service?
546                          * Would this change an existing job?
547                          * If so, let's drop this entry */
548
549                         stops_running_service =
550                                 j->type == JOB_STOP && UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(j->unit));
551
552                         changes_existing_job =
553                                 j->unit->job &&
554                                 job_type_is_conflicting(j->type, j->unit->job->type);
555
556                         if (!stops_running_service && !changes_existing_job)
557                                 continue;
558
559                         if (stops_running_service)
560                                 log_debug_unit(j->unit->id,
561                                                "%s/%s would stop a running service.",
562                                                j->unit->id, job_type_to_string(j->type));
563
564                         if (changes_existing_job)
565                                 log_debug_unit(j->unit->id,
566                                                "%s/%s would change existing job.",
567                                                j->unit->id, job_type_to_string(j->type));
568
569                         /* Ok, let's get rid of this */
570                         log_debug_unit(j->unit->id,
571                                        "Deleting %s/%s to minimize impact.",
572                                        j->unit->id, job_type_to_string(j->type));
573
574                         transaction_delete_job(tr, j, true);
575                         goto rescan;
576                 }
577         }
578 }
579
580 static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) {
581         Iterator i;
582         Job *j;
583         int r;
584
585         /* Moves the transaction jobs to the set of active jobs */
586
587         if (mode == JOB_ISOLATE || mode == JOB_FLUSH) {
588
589                 /* When isolating first kill all installed jobs which
590                  * aren't part of the new transaction */
591                 HASHMAP_FOREACH(j, m->jobs, i) {
592                         assert(j->installed);
593
594                         if (hashmap_get(tr->jobs, j->unit))
595                                 continue;
596
597                         /* Not invalidating recursively. Avoids triggering
598                          * OnFailure= actions of dependent jobs. Also avoids
599                          * invalidating our iterator. */
600                         job_finish_and_invalidate(j, JOB_CANCELED, false);
601                 }
602         }
603
604         HASHMAP_FOREACH(j, tr->jobs, i) {
605                 /* Assume merged */
606                 assert(!j->transaction_prev);
607                 assert(!j->transaction_next);
608
609                 r = hashmap_put(m->jobs, UINT32_TO_PTR(j->id), j);
610                 if (r < 0)
611                         goto rollback;
612         }
613
614         while ((j = hashmap_steal_first(tr->jobs))) {
615                 Job *installed_job;
616
617                 /* Clean the job dependencies */
618                 transaction_unlink_job(tr, j, false);
619
620                 installed_job = job_install(j);
621                 if (installed_job != j) {
622                         /* j has been merged into a previously installed job */
623                         if (tr->anchor_job == j)
624                                 tr->anchor_job = installed_job;
625                         hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
626                         job_free(j);
627                         j = installed_job;
628                 }
629
630                 job_add_to_run_queue(j);
631                 job_add_to_dbus_queue(j);
632                 job_start_timer(j);
633                 job_shutdown_magic(j);
634         }
635
636         return 0;
637
638 rollback:
639
640         HASHMAP_FOREACH(j, tr->jobs, i)
641                 hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
642
643         return r;
644 }
645
646 int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e) {
647         Iterator i;
648         Job *j;
649         int r;
650         unsigned generation = 1;
651
652         assert(tr);
653
654         /* This applies the changes recorded in tr->jobs to
655          * the actual list of jobs, if possible. */
656
657         /* Reset the generation counter of all installed jobs. The detection of cycles
658          * looks at installed jobs. If they had a non-zero generation from some previous
659          * walk of the graph, the algorithm would break. */
660         HASHMAP_FOREACH(j, m->jobs, i)
661                 j->generation = 0;
662
663         /* First step: figure out which jobs matter */
664         transaction_find_jobs_that_matter_to_anchor(tr->anchor_job, generation++);
665
666         /* Second step: Try not to stop any running services if
667          * we don't have to. Don't try to reverse running
668          * jobs if we don't have to. */
669         if (mode == JOB_FAIL)
670                 transaction_minimize_impact(tr);
671
672         /* Third step: Drop redundant jobs */
673         transaction_drop_redundant(tr);
674
675         for (;;) {
676                 /* Fourth step: Let's remove unneeded jobs that might
677                  * be lurking. */
678                 if (mode != JOB_ISOLATE)
679                         transaction_collect_garbage(tr);
680
681                 /* Fifth step: verify order makes sense and correct
682                  * cycles if necessary and possible */
683                 r = transaction_verify_order(tr, &generation, e);
684                 if (r >= 0)
685                         break;
686
687                 if (r != -EAGAIN) {
688                         log_warning("Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error_message(e, r));
689                         return r;
690                 }
691
692                 /* Let's see if the resulting transaction ordering
693                  * graph is still cyclic... */
694         }
695
696         for (;;) {
697                 /* Sixth step: let's drop unmergeable entries if
698                  * necessary and possible, merge entries we can
699                  * merge */
700                 r = transaction_merge_jobs(tr, e);
701                 if (r >= 0)
702                         break;
703
704                 if (r != -EAGAIN) {
705                         log_warning("Requested transaction contains unmergeable jobs: %s", bus_error_message(e, r));
706                         return r;
707                 }
708
709                 /* Seventh step: an entry got dropped, let's garbage
710                  * collect its dependencies. */
711                 if (mode != JOB_ISOLATE)
712                         transaction_collect_garbage(tr);
713
714                 /* Let's see if the resulting transaction still has
715                  * unmergeable entries ... */
716         }
717
718         /* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
719         transaction_drop_redundant(tr);
720
721         /* Ninth step: check whether we can actually apply this */
722         r = transaction_is_destructive(tr, mode, e);
723         if (r < 0) {
724                 log_notice("Requested transaction contradicts existing jobs: %s", bus_error_message(e, r));
725                 return r;
726         }
727
728         /* Tenth step: apply changes */
729         r = transaction_apply(tr, m, mode);
730         if (r < 0) {
731                 log_warning("Failed to apply transaction: %s", strerror(-r));
732                 return r;
733         }
734
735         assert(hashmap_isempty(tr->jobs));
736
737         if (!hashmap_isempty(m->jobs)) {
738                 /* Are there any jobs now? Then make sure we have the
739                  * idle pipe around. We don't really care too much
740                  * whether this works or not, as the idle pipe is a
741                  * feature for cosmetics, not actually useful for
742                  * anything beyond that. */
743
744                 if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0 &&
745                     m->idle_pipe[2] < 0 && m->idle_pipe[3] < 0) {
746                         pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC);
747                         pipe2(m->idle_pipe + 2, O_NONBLOCK|O_CLOEXEC);
748                 }
749         }
750
751         return 0;
752 }
753
754 static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, bool override, bool *is_new) {
755         Job *j, *f;
756
757         assert(tr);
758         assert(unit);
759
760         /* Looks for an existing prospective job and returns that. If
761          * it doesn't exist it is created and added to the prospective
762          * jobs list. */
763
764         f = hashmap_get(tr->jobs, unit);
765
766         LIST_FOREACH(transaction, j, f) {
767                 assert(j->unit == unit);
768
769                 if (j->type == type) {
770                         if (is_new)
771                                 *is_new = false;
772                         return j;
773                 }
774         }
775
776         j = job_new(unit, type);
777         if (!j)
778                 return NULL;
779
780         j->generation = 0;
781         j->marker = NULL;
782         j->matters_to_anchor = false;
783         j->override = override;
784         j->irreversible = tr->irreversible;
785
786         LIST_PREPEND(transaction, f, j);
787
788         if (hashmap_replace(tr->jobs, unit, f) < 0) {
789                 LIST_REMOVE(transaction, f, j);
790                 job_free(j);
791                 return NULL;
792         }
793
794         if (is_new)
795                 *is_new = true;
796
797         /* log_debug("Added job %s/%s to transaction.", unit->id, job_type_to_string(type)); */
798
799         return j;
800 }
801
802 static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies) {
803         assert(tr);
804         assert(j);
805
806         if (j->transaction_prev)
807                 j->transaction_prev->transaction_next = j->transaction_next;
808         else if (j->transaction_next)
809                 hashmap_replace(tr->jobs, j->unit, j->transaction_next);
810         else
811                 hashmap_remove_value(tr->jobs, j->unit, j);
812
813         if (j->transaction_next)
814                 j->transaction_next->transaction_prev = j->transaction_prev;
815
816         j->transaction_prev = j->transaction_next = NULL;
817
818         while (j->subject_list)
819                 job_dependency_free(j->subject_list);
820
821         while (j->object_list) {
822                 Job *other = j->object_list->matters ? j->object_list->subject : NULL;
823
824                 job_dependency_free(j->object_list);
825
826                 if (other && delete_dependencies) {
827                         log_debug_unit(other->unit->id,
828                                        "Deleting job %s/%s as dependency of job %s/%s",
829                                        other->unit->id, job_type_to_string(other->type),
830                                        j->unit->id, job_type_to_string(j->type));
831                         transaction_delete_job(tr, other, delete_dependencies);
832                 }
833         }
834 }
835
836 int transaction_add_job_and_dependencies(
837                 Transaction *tr,
838                 JobType type,
839                 Unit *unit,
840                 Job *by,
841                 bool matters,
842                 bool override,
843                 bool conflicts,
844                 bool ignore_requirements,
845                 bool ignore_order,
846                 sd_bus_error *e) {
847         Job *ret;
848         Iterator i;
849         Unit *dep;
850         int r;
851         bool is_new;
852
853         assert(tr);
854         assert(type < _JOB_TYPE_MAX);
855         assert(type < _JOB_TYPE_MAX_IN_TRANSACTION);
856         assert(unit);
857
858         /* log_debug("Pulling in %s/%s from %s/%s", */
859         /*           unit->id, job_type_to_string(type), */
860         /*           by ? by->unit->id : "NA", */
861         /*           by ? job_type_to_string(by->type) : "NA"); */
862
863         if (unit->load_state != UNIT_LOADED &&
864             unit->load_state != UNIT_ERROR &&
865             unit->load_state != UNIT_NOT_FOUND &&
866             unit->load_state != UNIT_MASKED) {
867                 sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
868                                   "Unit %s is not loaded properly.", unit->id);
869                 return -EINVAL;
870         }
871
872         if (type != JOB_STOP && unit->load_state == UNIT_ERROR) {
873                 if (unit->load_error == -ENOENT || unit->manager->test_run)
874                         sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
875                                           "Unit %s failed to load: %s.",
876                                           unit->id,
877                                           strerror(-unit->load_error));
878                 else
879                         sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
880                                           "Unit %s failed to load: %s. "
881                                           "See system logs and 'systemctl status %s' for details.",
882                                           unit->id,
883                                           strerror(-unit->load_error),
884                                           unit->id);
885                 return -EINVAL;
886         }
887
888         if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND) {
889                 sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
890                                   "Unit %s failed to load: %s.",
891                                   unit->id, strerror(-unit->load_error));
892                 return -EINVAL;
893         }
894
895         if (type != JOB_STOP && unit->load_state == UNIT_MASKED) {
896                 sd_bus_error_setf(e, BUS_ERROR_UNIT_MASKED,
897                                   "Unit %s is masked.", unit->id);
898                 return -EADDRNOTAVAIL;
899         }
900
901         if (!unit_job_is_applicable(unit, type)) {
902                 sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,
903                                   "Job type %s is not applicable for unit %s.",
904                                   job_type_to_string(type), unit->id);
905                 return -EBADR;
906         }
907
908         /* First add the job. */
909         ret = transaction_add_one_job(tr, type, unit, override, &is_new);
910         if (!ret)
911                 return -ENOMEM;
912
913         ret->ignore_order = ret->ignore_order || ignore_order;
914
915         /* Then, add a link to the job. */
916         if (by) {
917                 if (!job_dependency_new(by, ret, matters, conflicts))
918                         return -ENOMEM;
919         } else {
920                 /* If the job has no parent job, it is the anchor job. */
921                 assert(!tr->anchor_job);
922                 tr->anchor_job = ret;
923         }
924
925         if (is_new && !ignore_requirements && type != JOB_NOP) {
926                 Set *following;
927
928                 /* If we are following some other unit, make sure we
929                  * add all dependencies of everybody following. */
930                 if (unit_following_set(ret->unit, &following) > 0) {
931                         SET_FOREACH(dep, following, i) {
932                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, override, false, false, ignore_order, e);
933                                 if (r < 0) {
934                                         log_warning_unit(dep->id,
935                                                          "Cannot add dependency job for unit %s, ignoring: %s",
936                                                          dep->id, bus_error_message(e, r));
937
938                                         if (e)
939                                                 sd_bus_error_free(e);
940                                 }
941                         }
942
943                         set_free(following);
944                 }
945
946                 /* Finally, recursively add in all dependencies. */
947                 if (type == JOB_START || type == JOB_RESTART) {
948                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES], i) {
949                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
950                                 if (r < 0) {
951                                         if (r != -EBADR)
952                                                 goto fail;
953
954                                         if (e)
955                                                 sd_bus_error_free(e);
956                                 }
957                         }
958
959                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_BINDS_TO], i) {
960                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
961                                 if (r < 0) {
962                                         if (r != -EBADR)
963                                                 goto fail;
964
965                                         if (e)
966                                                 sd_bus_error_free(e);
967                                 }
968                         }
969
970                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES_OVERRIDABLE], i) {
971                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, !override, override, false, false, ignore_order, e);
972                                 if (r < 0) {
973                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
974                                                       "Cannot add dependency job for unit %s, ignoring: %s",
975                                                       dep->id, bus_error_message(e, r));
976
977                                         if (e)
978                                                 sd_bus_error_free(e);
979                                 }
980                         }
981
982                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_WANTS], i) {
983                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, false, ignore_order, e);
984                                 if (r < 0) {
985                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
986                                                       "Cannot add dependency job for unit %s, ignoring: %s",
987                                                       dep->id, bus_error_message(e, r));
988
989                                         if (e)
990                                                 sd_bus_error_free(e);
991                                 }
992                         }
993
994                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE], i) {
995                                 r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, override, false, false, ignore_order, e);
996                                 if (r < 0) {
997                                         if (r != -EBADR)
998                                                 goto fail;
999
1000                                         if (e)
1001                                                 sd_bus_error_free(e);
1002                                 }
1003                         }
1004
1005                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE_OVERRIDABLE], i) {
1006                                 r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, !override, override, false, false, ignore_order, e);
1007                                 if (r < 0) {
1008                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
1009                                                       "Cannot add dependency job for unit %s, ignoring: %s",
1010                                                       dep->id, bus_error_message(e, r));
1011
1012                                         if (e)
1013                                                 sd_bus_error_free(e);
1014                                 }
1015                         }
1016
1017                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTS], i) {
1018                                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, override, true, false, ignore_order, e);
1019                                 if (r < 0) {
1020                                         if (r != -EBADR)
1021                                                 goto fail;
1022
1023                                         if (e)
1024                                                 sd_bus_error_free(e);
1025                                 }
1026                         }
1027
1028                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTED_BY], i) {
1029                                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, override, false, false, ignore_order, e);
1030                                 if (r < 0) {
1031                                         log_warning_unit(dep->id,
1032                                                          "Cannot add dependency job for unit %s, ignoring: %s",
1033                                                          dep->id, bus_error_message(e, r));
1034
1035                                         if (e)
1036                                                 sd_bus_error_free(e);
1037                                 }
1038                         }
1039
1040                 }
1041
1042                 if (type == JOB_STOP || type == JOB_RESTART) {
1043
1044                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRED_BY], i) {
1045                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1046                                 if (r < 0) {
1047                                         if (r != -EBADR)
1048                                                 goto fail;
1049
1050                                         if (e)
1051                                                 sd_bus_error_free(e);
1052                                 }
1053                         }
1054
1055                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_BOUND_BY], i) {
1056                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1057                                 if (r < 0) {
1058                                         if (r != -EBADR)
1059                                                 goto fail;
1060
1061                                         if (e)
1062                                                 sd_bus_error_free(e);
1063                                 }
1064                         }
1065
1066                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONSISTS_OF], i) {
1067                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1068                                 if (r < 0) {
1069                                         if (r != -EBADR)
1070                                                 goto fail;
1071
1072                                         if (e)
1073                                                 sd_bus_error_free(e);
1074                                 }
1075                         }
1076
1077                 }
1078
1079                 if (type == JOB_RELOAD) {
1080
1081                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) {
1082                                 r = transaction_add_job_and_dependencies(tr, JOB_RELOAD, dep, ret, false, override, false, false, ignore_order, e);
1083                                 if (r < 0) {
1084                                         log_warning_unit(dep->id,
1085                                                          "Cannot add dependency reload job for unit %s, ignoring: %s",
1086                                                          dep->id, bus_error_message(e, r));
1087
1088                                         if (e)
1089                                                 sd_bus_error_free(e);
1090                                 }
1091                         }
1092                 }
1093
1094                 /* JOB_VERIFY_STARTED require no dependency handling */
1095         }
1096
1097         return 0;
1098
1099 fail:
1100         return r;
1101 }
1102
1103 int transaction_add_isolate_jobs(Transaction *tr, Manager *m) {
1104         Iterator i;
1105         Unit *u;
1106         char *k;
1107         int r;
1108
1109         assert(tr);
1110         assert(m);
1111
1112         HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1113
1114                 /* ignore aliases */
1115                 if (u->id != k)
1116                         continue;
1117
1118                 if (u->ignore_on_isolate)
1119                         continue;
1120
1121                 /* No need to stop inactive jobs */
1122                 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)) && !u->job)
1123                         continue;
1124
1125                 /* Is there already something listed for this? */
1126                 if (hashmap_get(tr->jobs, u))
1127                         continue;
1128
1129                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, u, tr->anchor_job, true, false, false, false, false, NULL);
1130                 if (r < 0)
1131                         log_warning_unit(u->id,
1132                                          "Cannot add isolate job for unit %s, ignoring: %s",
1133                                          u->id, strerror(-r));
1134         }
1135
1136         return 0;
1137 }
1138
1139 Transaction *transaction_new(bool irreversible) {
1140         Transaction *tr;
1141
1142         tr = new0(Transaction, 1);
1143         if (!tr)
1144                 return NULL;
1145
1146         tr->jobs = hashmap_new(trivial_hash_func, trivial_compare_func);
1147         if (!tr->jobs) {
1148                 free(tr);
1149                 return NULL;
1150         }
1151
1152         tr->irreversible = irreversible;
1153
1154         return tr;
1155 }
1156
1157 void transaction_free(Transaction *tr) {
1158         assert(hashmap_isempty(tr->jobs));
1159         hashmap_free(tr->jobs);
1160         free(tr);
1161 }