chiark / gitweb /
core/transaction: reindent and split very long lines
[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 &&
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                 sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
874                                   "Unit %s failed to load: %s. "
875                                   "See system logs and 'systemctl status %s' for details.",
876                                   unit->id,
877                                   strerror(-unit->load_error),
878                                   unit->id);
879                 return -EINVAL;
880         }
881
882         if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND) {
883                 sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
884                                   "Unit %s failed to load: %s.",
885                                   unit->id, strerror(-unit->load_error));
886                 return -EINVAL;
887         }
888
889         if (type != JOB_STOP && unit->load_state == UNIT_MASKED) {
890                 sd_bus_error_setf(e, BUS_ERROR_UNIT_MASKED,
891                                   "Unit %s is masked.", unit->id);
892                 return -EADDRNOTAVAIL;
893         }
894
895         if (!unit_job_is_applicable(unit, type)) {
896                 sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,
897                                   "Job type %s is not applicable for unit %s.",
898                                   job_type_to_string(type), unit->id);
899                 return -EBADR;
900         }
901
902         /* First add the job. */
903         ret = transaction_add_one_job(tr, type, unit, override, &is_new);
904         if (!ret)
905                 return -ENOMEM;
906
907         ret->ignore_order = ret->ignore_order || ignore_order;
908
909         /* Then, add a link to the job. */
910         if (by) {
911                 if (!job_dependency_new(by, ret, matters, conflicts))
912                         return -ENOMEM;
913         } else {
914                 /* If the job has no parent job, it is the anchor job. */
915                 assert(!tr->anchor_job);
916                 tr->anchor_job = ret;
917         }
918
919         if (is_new && !ignore_requirements && type != JOB_NOP) {
920                 Set *following;
921
922                 /* If we are following some other unit, make sure we
923                  * add all dependencies of everybody following. */
924                 if (unit_following_set(ret->unit, &following) > 0) {
925                         SET_FOREACH(dep, following, i) {
926                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, override, false, false, ignore_order, e);
927                                 if (r < 0) {
928                                         log_warning_unit(dep->id,
929                                                          "Cannot add dependency job for unit %s, ignoring: %s",
930                                                          dep->id, bus_error_message(e, r));
931
932                                         if (e)
933                                                 sd_bus_error_free(e);
934                                 }
935                         }
936
937                         set_free(following);
938                 }
939
940                 /* Finally, recursively add in all dependencies. */
941                 if (type == JOB_START || type == JOB_RESTART) {
942                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES], i) {
943                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
944                                 if (r < 0) {
945                                         if (r != -EBADR)
946                                                 goto fail;
947
948                                         if (e)
949                                                 sd_bus_error_free(e);
950                                 }
951                         }
952
953                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_BINDS_TO], i) {
954                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
955                                 if (r < 0) {
956                                         if (r != -EBADR)
957                                                 goto fail;
958
959                                         if (e)
960                                                 sd_bus_error_free(e);
961                                 }
962                         }
963
964                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES_OVERRIDABLE], i) {
965                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, !override, override, false, false, ignore_order, e);
966                                 if (r < 0) {
967                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
968                                                       "Cannot add dependency job for unit %s, ignoring: %s",
969                                                       dep->id, bus_error_message(e, r));
970
971                                         if (e)
972                                                 sd_bus_error_free(e);
973                                 }
974                         }
975
976                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_WANTS], i) {
977                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, false, ignore_order, e);
978                                 if (r < 0) {
979                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
980                                                       "Cannot add dependency job for unit %s, ignoring: %s",
981                                                       dep->id, bus_error_message(e, r));
982
983                                         if (e)
984                                                 sd_bus_error_free(e);
985                                 }
986                         }
987
988                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE], i) {
989                                 r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, override, false, false, ignore_order, e);
990                                 if (r < 0) {
991                                         if (r != -EBADR)
992                                                 goto fail;
993
994                                         if (e)
995                                                 sd_bus_error_free(e);
996                                 }
997                         }
998
999                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE_OVERRIDABLE], i) {
1000                                 r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, !override, override, false, false, ignore_order, e);
1001                                 if (r < 0) {
1002                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
1003                                                       "Cannot add dependency job for unit %s, ignoring: %s",
1004                                                       dep->id, bus_error_message(e, r));
1005
1006                                         if (e)
1007                                                 sd_bus_error_free(e);
1008                                 }
1009                         }
1010
1011                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTS], i) {
1012                                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, override, true, false, ignore_order, e);
1013                                 if (r < 0) {
1014                                         if (r != -EBADR)
1015                                                 goto fail;
1016
1017                                         if (e)
1018                                                 sd_bus_error_free(e);
1019                                 }
1020                         }
1021
1022                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTED_BY], i) {
1023                                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, override, false, false, ignore_order, e);
1024                                 if (r < 0) {
1025                                         log_warning_unit(dep->id,
1026                                                          "Cannot add dependency job for unit %s, ignoring: %s",
1027                                                          dep->id, bus_error_message(e, r));
1028
1029                                         if (e)
1030                                                 sd_bus_error_free(e);
1031                                 }
1032                         }
1033
1034                 }
1035
1036                 if (type == JOB_STOP || type == JOB_RESTART) {
1037
1038                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRED_BY], i) {
1039                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1040                                 if (r < 0) {
1041                                         if (r != -EBADR)
1042                                                 goto fail;
1043
1044                                         if (e)
1045                                                 sd_bus_error_free(e);
1046                                 }
1047                         }
1048
1049                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_BOUND_BY], i) {
1050                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1051                                 if (r < 0) {
1052                                         if (r != -EBADR)
1053                                                 goto fail;
1054
1055                                         if (e)
1056                                                 sd_bus_error_free(e);
1057                                 }
1058                         }
1059
1060                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONSISTS_OF], i) {
1061                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1062                                 if (r < 0) {
1063                                         if (r != -EBADR)
1064                                                 goto fail;
1065
1066                                         if (e)
1067                                                 sd_bus_error_free(e);
1068                                 }
1069                         }
1070
1071                 }
1072
1073                 if (type == JOB_RELOAD) {
1074
1075                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) {
1076                                 r = transaction_add_job_and_dependencies(tr, JOB_RELOAD, dep, ret, false, override, false, false, ignore_order, e);
1077                                 if (r < 0) {
1078                                         log_warning_unit(dep->id,
1079                                                          "Cannot add dependency reload job for unit %s, ignoring: %s",
1080                                                          dep->id, bus_error_message(e, r));
1081
1082                                         if (e)
1083                                                 sd_bus_error_free(e);
1084                                 }
1085                         }
1086                 }
1087
1088                 /* JOB_VERIFY_STARTED require no dependency handling */
1089         }
1090
1091         return 0;
1092
1093 fail:
1094         return r;
1095 }
1096
1097 int transaction_add_isolate_jobs(Transaction *tr, Manager *m) {
1098         Iterator i;
1099         Unit *u;
1100         char *k;
1101         int r;
1102
1103         assert(tr);
1104         assert(m);
1105
1106         HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1107
1108                 /* ignore aliases */
1109                 if (u->id != k)
1110                         continue;
1111
1112                 if (u->ignore_on_isolate)
1113                         continue;
1114
1115                 /* No need to stop inactive jobs */
1116                 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)) && !u->job)
1117                         continue;
1118
1119                 /* Is there already something listed for this? */
1120                 if (hashmap_get(tr->jobs, u))
1121                         continue;
1122
1123                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, u, tr->anchor_job, true, false, false, false, false, NULL);
1124                 if (r < 0)
1125                         log_warning_unit(u->id,
1126                                          "Cannot add isolate job for unit %s, ignoring: %s",
1127                                          u->id, strerror(-r));
1128         }
1129
1130         return 0;
1131 }
1132
1133 Transaction *transaction_new(bool irreversible) {
1134         Transaction *tr;
1135
1136         tr = new0(Transaction, 1);
1137         if (!tr)
1138                 return NULL;
1139
1140         tr->jobs = hashmap_new(trivial_hash_func, trivial_compare_func);
1141         if (!tr->jobs) {
1142                 free(tr);
1143                 return NULL;
1144         }
1145
1146         tr->irreversible = irreversible;
1147
1148         return tr;
1149 }
1150
1151 void transaction_free(Transaction *tr) {
1152         assert(hashmap_isempty(tr->jobs));
1153         hashmap_free(tr->jobs);
1154         free(tr);
1155 }