chiark / gitweb /
treewide: no need to negate errno for log_*_errno()
[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_unit_debug(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_unit_debug(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_unit_debug(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                         return 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                 }
274         }
275
276         /* Second step, merge the jobs. */
277         HASHMAP_FOREACH(j, tr->jobs, i) {
278                 JobType t = j->type;
279                 Job *k;
280
281                 /* Merge all transaction jobs for j->unit */
282                 LIST_FOREACH(transaction, k, j->transaction_next)
283                         assert_se(job_type_merge_and_collapse(&t, k->type, j->unit) == 0);
284
285                 while ((k = j->transaction_next)) {
286                         if (tr->anchor_job == k) {
287                                 transaction_merge_and_delete_job(tr, k, j, t);
288                                 j = k;
289                         } else
290                                 transaction_merge_and_delete_job(tr, j, k, t);
291                 }
292
293                 assert(!j->transaction_next);
294                 assert(!j->transaction_prev);
295         }
296
297         return 0;
298 }
299
300 static void transaction_drop_redundant(Transaction *tr) {
301         Job *j;
302         Iterator i;
303
304         /* Goes through the transaction and removes all jobs of the units
305          * whose jobs are all noops. If not all of a unit's jobs are
306          * redundant, they are kept. */
307
308         assert(tr);
309
310 rescan:
311         HASHMAP_FOREACH(j, tr->jobs, i) {
312                 Job *k;
313
314                 LIST_FOREACH(transaction, k, j) {
315
316                         if (tr->anchor_job == k ||
317                             !job_type_is_redundant(k->type, unit_active_state(k->unit)) ||
318                             (k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type)))
319                                 goto next_unit;
320                 }
321
322                 /* log_debug("Found redundant job %s/%s, dropping.", j->unit->id, job_type_to_string(j->type)); */
323                 transaction_delete_job(tr, j, false);
324                 goto rescan;
325         next_unit:;
326         }
327 }
328
329 _pure_ static bool unit_matters_to_anchor(Unit *u, Job *j) {
330         assert(u);
331         assert(!j->transaction_prev);
332
333         /* Checks whether at least one of the jobs for this unit
334          * matters to the anchor. */
335
336         LIST_FOREACH(transaction, j, j)
337                 if (j->matters_to_anchor)
338                         return true;
339
340         return false;
341 }
342
343 static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, sd_bus_error *e) {
344         Iterator i;
345         Unit *u;
346         int r;
347
348         assert(tr);
349         assert(j);
350         assert(!j->transaction_prev);
351
352         /* Does a recursive sweep through the ordering graph, looking
353          * for a cycle. If we find a cycle we try to break it. */
354
355         /* Have we seen this before? */
356         if (j->generation == generation) {
357                 Job *k, *delete;
358
359                 /* If the marker is NULL we have been here already and
360                  * decided the job was loop-free from here. Hence
361                  * shortcut things and return right-away. */
362                 if (!j->marker)
363                         return 0;
364
365                 /* So, the marker is not NULL and we already have been
366                  * here. We have a cycle. Let's try to break it. We go
367                  * backwards in our path and try to find a suitable
368                  * job to remove. We use the marker to find our way
369                  * back, since smart how we are we stored our way back
370                  * in there. */
371                 log_unit_warning(j->unit->id,
372                                  "Found ordering cycle on %s/%s",
373                                  j->unit->id, job_type_to_string(j->type));
374
375                 delete = NULL;
376                 for (k = from; k; k = ((k->generation == generation && k->marker != k) ? k->marker : NULL)) {
377
378                         /* logging for j not k here here to provide consistent narrative */
379                         log_unit_warning(j->unit->id,
380                                          "Found dependency on %s/%s",
381                                          k->unit->id, job_type_to_string(k->type));
382
383                         if (!delete && hashmap_get(tr->jobs, k->unit) &&
384                             !unit_matters_to_anchor(k->unit, k)) {
385                                 /* Ok, we can drop this one, so let's
386                                  * do so. */
387                                 delete = k;
388                         }
389
390                         /* Check if this in fact was the beginning of
391                          * the cycle */
392                         if (k == j)
393                                 break;
394                 }
395
396
397                 if (delete) {
398                         /* logging for j not k here here to provide consistent narrative */
399                         log_unit_warning(j->unit->id,
400                                          "Breaking ordering cycle by deleting job %s/%s",
401                                          delete->unit->id, job_type_to_string(delete->type));
402                         log_unit_error(delete->unit->id,
403                                        "Job %s/%s deleted to break ordering cycle starting with %s/%s",
404                                        delete->unit->id, job_type_to_string(delete->type),
405                                        j->unit->id, job_type_to_string(j->type));
406                         unit_status_printf(delete->unit, ANSI_HIGHLIGHT_RED_ON " SKIP " ANSI_HIGHLIGHT_OFF,
407                                            "Ordering cycle found, skipping %s");
408                         transaction_delete_unit(tr, delete->unit);
409                         return -EAGAIN;
410                 }
411
412                 log_error("Unable to break cycle");
413
414                 return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,
415                                          "Transaction order is cyclic. See system logs for details.");
416         }
417
418         /* Make the marker point to where we come from, so that we can
419          * find our way backwards if we want to break a cycle. We use
420          * a special marker for the beginning: we point to
421          * ourselves. */
422         j->marker = from ? from : j;
423         j->generation = generation;
424
425         /* We assume that the dependencies are bidirectional, and
426          * hence can ignore UNIT_AFTER */
427         SET_FOREACH(u, j->unit->dependencies[UNIT_BEFORE], i) {
428                 Job *o;
429
430                 /* Is there a job for this unit? */
431                 o = hashmap_get(tr->jobs, u);
432                 if (!o) {
433                         /* Ok, there is no job for this in the
434                          * transaction, but maybe there is already one
435                          * running? */
436                         o = u->job;
437                         if (!o)
438                                 continue;
439                 }
440
441                 r = transaction_verify_order_one(tr, o, j, generation, e);
442                 if (r < 0)
443                         return r;
444         }
445
446         /* Ok, let's backtrack, and remember that this entry is not on
447          * our path anymore. */
448         j->marker = NULL;
449
450         return 0;
451 }
452
453 static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bus_error *e) {
454         Job *j;
455         int r;
456         Iterator i;
457         unsigned g;
458
459         assert(tr);
460         assert(generation);
461
462         /* Check if the ordering graph is cyclic. If it is, try to fix
463          * that up by dropping one of the jobs. */
464
465         g = (*generation)++;
466
467         HASHMAP_FOREACH(j, tr->jobs, i)
468                 if ((r = transaction_verify_order_one(tr, j, NULL, g, e)) < 0)
469                         return r;
470
471         return 0;
472 }
473
474 static void transaction_collect_garbage(Transaction *tr) {
475         Iterator i;
476         Job *j;
477
478         assert(tr);
479
480         /* Drop jobs that are not required by any other job */
481
482 rescan:
483         HASHMAP_FOREACH(j, tr->jobs, i) {
484                 if (tr->anchor_job == j || j->object_list) {
485                         /* log_debug("Keeping job %s/%s because of %s/%s", */
486                         /*           j->unit->id, job_type_to_string(j->type), */
487                         /*           j->object_list->subject ? j->object_list->subject->unit->id : "root", */
488                         /*           j->object_list->subject ? job_type_to_string(j->object_list->subject->type) : "root"); */
489                         continue;
490                 }
491
492                 /* log_debug("Garbage collecting job %s/%s", j->unit->id, job_type_to_string(j->type)); */
493                 transaction_delete_job(tr, j, true);
494                 goto rescan;
495         }
496 }
497
498 static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_error *e) {
499         Iterator i;
500         Job *j;
501
502         assert(tr);
503
504         /* Checks whether applying this transaction means that
505          * existing jobs would be replaced */
506
507         HASHMAP_FOREACH(j, tr->jobs, i) {
508
509                 /* Assume merged */
510                 assert(!j->transaction_prev);
511                 assert(!j->transaction_next);
512
513                 if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) &&
514                     job_type_is_conflicting(j->unit->job->type, j->type))
515                         return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE,
516                                                  "Transaction is destructive.");
517         }
518
519         return 0;
520 }
521
522 static void transaction_minimize_impact(Transaction *tr) {
523         Job *j;
524         Iterator i;
525
526         assert(tr);
527
528         /* Drops all unnecessary jobs that reverse already active jobs
529          * or that stop a running service. */
530
531 rescan:
532         HASHMAP_FOREACH(j, tr->jobs, i) {
533                 LIST_FOREACH(transaction, j, j) {
534                         bool stops_running_service, changes_existing_job;
535
536                         /* If it matters, we shouldn't drop it */
537                         if (j->matters_to_anchor)
538                                 continue;
539
540                         /* Would this stop a running service?
541                          * Would this change an existing job?
542                          * If so, let's drop this entry */
543
544                         stops_running_service =
545                                 j->type == JOB_STOP && UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(j->unit));
546
547                         changes_existing_job =
548                                 j->unit->job &&
549                                 job_type_is_conflicting(j->type, j->unit->job->type);
550
551                         if (!stops_running_service && !changes_existing_job)
552                                 continue;
553
554                         if (stops_running_service)
555                                 log_unit_debug(j->unit->id,
556                                                "%s/%s would stop a running service.",
557                                                j->unit->id, job_type_to_string(j->type));
558
559                         if (changes_existing_job)
560                                 log_unit_debug(j->unit->id,
561                                                "%s/%s would change existing job.",
562                                                j->unit->id, job_type_to_string(j->type));
563
564                         /* Ok, let's get rid of this */
565                         log_unit_debug(j->unit->id,
566                                        "Deleting %s/%s to minimize impact.",
567                                        j->unit->id, job_type_to_string(j->type));
568
569                         transaction_delete_job(tr, j, true);
570                         goto rescan;
571                 }
572         }
573 }
574
575 static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) {
576         Iterator i;
577         Job *j;
578         int r;
579
580         /* Moves the transaction jobs to the set of active jobs */
581
582         if (mode == JOB_ISOLATE || mode == JOB_FLUSH) {
583
584                 /* When isolating first kill all installed jobs which
585                  * aren't part of the new transaction */
586                 HASHMAP_FOREACH(j, m->jobs, i) {
587                         assert(j->installed);
588
589                         if (hashmap_get(tr->jobs, j->unit))
590                                 continue;
591
592                         /* Not invalidating recursively. Avoids triggering
593                          * OnFailure= actions of dependent jobs. Also avoids
594                          * invalidating our iterator. */
595                         job_finish_and_invalidate(j, JOB_CANCELED, false);
596                 }
597         }
598
599         HASHMAP_FOREACH(j, tr->jobs, i) {
600                 /* Assume merged */
601                 assert(!j->transaction_prev);
602                 assert(!j->transaction_next);
603
604                 r = hashmap_put(m->jobs, UINT32_TO_PTR(j->id), j);
605                 if (r < 0)
606                         goto rollback;
607         }
608
609         while ((j = hashmap_steal_first(tr->jobs))) {
610                 Job *installed_job;
611
612                 /* Clean the job dependencies */
613                 transaction_unlink_job(tr, j, false);
614
615                 installed_job = job_install(j);
616                 if (installed_job != j) {
617                         /* j has been merged into a previously installed job */
618                         if (tr->anchor_job == j)
619                                 tr->anchor_job = installed_job;
620                         hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
621                         job_free(j);
622                         j = installed_job;
623                 }
624
625                 job_add_to_run_queue(j);
626                 job_add_to_dbus_queue(j);
627                 job_start_timer(j);
628                 job_shutdown_magic(j);
629         }
630
631         return 0;
632
633 rollback:
634
635         HASHMAP_FOREACH(j, tr->jobs, i)
636                 hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
637
638         return r;
639 }
640
641 int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e) {
642         Iterator i;
643         Job *j;
644         int r;
645         unsigned generation = 1;
646
647         assert(tr);
648
649         /* This applies the changes recorded in tr->jobs to
650          * the actual list of jobs, if possible. */
651
652         /* Reset the generation counter of all installed jobs. The detection of cycles
653          * looks at installed jobs. If they had a non-zero generation from some previous
654          * walk of the graph, the algorithm would break. */
655         HASHMAP_FOREACH(j, m->jobs, i)
656                 j->generation = 0;
657
658         /* First step: figure out which jobs matter */
659         transaction_find_jobs_that_matter_to_anchor(tr->anchor_job, generation++);
660
661         /* Second step: Try not to stop any running services if
662          * we don't have to. Don't try to reverse running
663          * jobs if we don't have to. */
664         if (mode == JOB_FAIL)
665                 transaction_minimize_impact(tr);
666
667         /* Third step: Drop redundant jobs */
668         transaction_drop_redundant(tr);
669
670         for (;;) {
671                 /* Fourth step: Let's remove unneeded jobs that might
672                  * be lurking. */
673                 if (mode != JOB_ISOLATE)
674                         transaction_collect_garbage(tr);
675
676                 /* Fifth step: verify order makes sense and correct
677                  * cycles if necessary and possible */
678                 r = transaction_verify_order(tr, &generation, e);
679                 if (r >= 0)
680                         break;
681
682                 if (r != -EAGAIN) {
683                         log_warning("Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error_message(e, r));
684                         return r;
685                 }
686
687                 /* Let's see if the resulting transaction ordering
688                  * graph is still cyclic... */
689         }
690
691         for (;;) {
692                 /* Sixth step: let's drop unmergeable entries if
693                  * necessary and possible, merge entries we can
694                  * merge */
695                 r = transaction_merge_jobs(tr, e);
696                 if (r >= 0)
697                         break;
698
699                 if (r != -EAGAIN) {
700                         log_warning("Requested transaction contains unmergeable jobs: %s", bus_error_message(e, r));
701                         return r;
702                 }
703
704                 /* Seventh step: an entry got dropped, let's garbage
705                  * collect its dependencies. */
706                 if (mode != JOB_ISOLATE)
707                         transaction_collect_garbage(tr);
708
709                 /* Let's see if the resulting transaction still has
710                  * unmergeable entries ... */
711         }
712
713         /* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
714         transaction_drop_redundant(tr);
715
716         /* Ninth step: check whether we can actually apply this */
717         r = transaction_is_destructive(tr, mode, e);
718         if (r < 0) {
719                 log_notice("Requested transaction contradicts existing jobs: %s", bus_error_message(e, r));
720                 return r;
721         }
722
723         /* Tenth step: apply changes */
724         r = transaction_apply(tr, m, mode);
725         if (r < 0) {
726                 log_warning_errno(r, "Failed to apply transaction: %m");
727                 return r;
728         }
729
730         assert(hashmap_isempty(tr->jobs));
731
732         if (!hashmap_isempty(m->jobs)) {
733                 /* Are there any jobs now? Then make sure we have the
734                  * idle pipe around. We don't really care too much
735                  * whether this works or not, as the idle pipe is a
736                  * feature for cosmetics, not actually useful for
737                  * anything beyond that. */
738
739                 if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0 &&
740                     m->idle_pipe[2] < 0 && m->idle_pipe[3] < 0) {
741                         pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC);
742                         pipe2(m->idle_pipe + 2, O_NONBLOCK|O_CLOEXEC);
743                 }
744         }
745
746         return 0;
747 }
748
749 static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, bool override, bool *is_new) {
750         Job *j, *f;
751
752         assert(tr);
753         assert(unit);
754
755         /* Looks for an existing prospective job and returns that. If
756          * it doesn't exist it is created and added to the prospective
757          * jobs list. */
758
759         f = hashmap_get(tr->jobs, unit);
760
761         LIST_FOREACH(transaction, j, f) {
762                 assert(j->unit == unit);
763
764                 if (j->type == type) {
765                         if (is_new)
766                                 *is_new = false;
767                         return j;
768                 }
769         }
770
771         j = job_new(unit, type);
772         if (!j)
773                 return NULL;
774
775         j->generation = 0;
776         j->marker = NULL;
777         j->matters_to_anchor = false;
778         j->override = override;
779         j->irreversible = tr->irreversible;
780
781         LIST_PREPEND(transaction, f, j);
782
783         if (hashmap_replace(tr->jobs, unit, f) < 0) {
784                 LIST_REMOVE(transaction, f, j);
785                 job_free(j);
786                 return NULL;
787         }
788
789         if (is_new)
790                 *is_new = true;
791
792         /* log_debug("Added job %s/%s to transaction.", unit->id, job_type_to_string(type)); */
793
794         return j;
795 }
796
797 static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies) {
798         assert(tr);
799         assert(j);
800
801         if (j->transaction_prev)
802                 j->transaction_prev->transaction_next = j->transaction_next;
803         else if (j->transaction_next)
804                 hashmap_replace(tr->jobs, j->unit, j->transaction_next);
805         else
806                 hashmap_remove_value(tr->jobs, j->unit, j);
807
808         if (j->transaction_next)
809                 j->transaction_next->transaction_prev = j->transaction_prev;
810
811         j->transaction_prev = j->transaction_next = NULL;
812
813         while (j->subject_list)
814                 job_dependency_free(j->subject_list);
815
816         while (j->object_list) {
817                 Job *other = j->object_list->matters ? j->object_list->subject : NULL;
818
819                 job_dependency_free(j->object_list);
820
821                 if (other && delete_dependencies) {
822                         log_unit_debug(other->unit->id,
823                                        "Deleting job %s/%s as dependency of job %s/%s",
824                                        other->unit->id, job_type_to_string(other->type),
825                                        j->unit->id, job_type_to_string(j->type));
826                         transaction_delete_job(tr, other, delete_dependencies);
827                 }
828         }
829 }
830
831 int transaction_add_job_and_dependencies(
832                 Transaction *tr,
833                 JobType type,
834                 Unit *unit,
835                 Job *by,
836                 bool matters,
837                 bool override,
838                 bool conflicts,
839                 bool ignore_requirements,
840                 bool ignore_order,
841                 sd_bus_error *e) {
842         Job *ret;
843         Iterator i;
844         Unit *dep;
845         int r;
846         bool is_new;
847
848         assert(tr);
849         assert(type < _JOB_TYPE_MAX);
850         assert(type < _JOB_TYPE_MAX_IN_TRANSACTION);
851         assert(unit);
852
853         /* log_debug("Pulling in %s/%s from %s/%s", */
854         /*           unit->id, job_type_to_string(type), */
855         /*           by ? by->unit->id : "NA", */
856         /*           by ? job_type_to_string(by->type) : "NA"); */
857
858         if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_MASKED))
859                 return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
860                                          "Unit %s is not loaded properly.", unit->id);
861
862         if (type != JOB_STOP && unit->load_state == UNIT_ERROR) {
863                 if (unit->load_error == -ENOENT || unit->manager->test_run)
864                         return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
865                                                  "Unit %s failed to load: %s.",
866                                                  unit->id,
867                                                  strerror(-unit->load_error));
868                 else
869                         return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
870                                                  "Unit %s failed to load: %s. "
871                                                  "See system logs and 'systemctl status %s' for details.",
872                                                  unit->id,
873                                                  strerror(-unit->load_error),
874                                                  unit->id);
875         }
876
877         if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND)
878                 return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
879                                          "Unit %s failed to load: %s.",
880                                          unit->id, strerror(-unit->load_error));
881
882         if (type != JOB_STOP && unit->load_state == UNIT_MASKED)
883                 return sd_bus_error_setf(e, BUS_ERROR_UNIT_MASKED,
884                                          "Unit %s is masked.", unit->id);
885
886         if (!unit_job_is_applicable(unit, type))
887                 return sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,
888                                          "Job type %s is not applicable for unit %s.",
889                                          job_type_to_string(type), unit->id);
890
891
892         /* First add the job. */
893         ret = transaction_add_one_job(tr, type, unit, override, &is_new);
894         if (!ret)
895                 return -ENOMEM;
896
897         ret->ignore_order = ret->ignore_order || ignore_order;
898
899         /* Then, add a link to the job. */
900         if (by) {
901                 if (!job_dependency_new(by, ret, matters, conflicts))
902                         return -ENOMEM;
903         } else {
904                 /* If the job has no parent job, it is the anchor job. */
905                 assert(!tr->anchor_job);
906                 tr->anchor_job = ret;
907         }
908
909         if (is_new && !ignore_requirements && type != JOB_NOP) {
910                 Set *following;
911
912                 /* If we are following some other unit, make sure we
913                  * add all dependencies of everybody following. */
914                 if (unit_following_set(ret->unit, &following) > 0) {
915                         SET_FOREACH(dep, following, i) {
916                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, override, false, false, ignore_order, e);
917                                 if (r < 0) {
918                                         log_unit_warning(dep->id,
919                                                          "Cannot add dependency job for unit %s, ignoring: %s",
920                                                          dep->id, bus_error_message(e, r));
921
922                                         if (e)
923                                                 sd_bus_error_free(e);
924                                 }
925                         }
926
927                         set_free(following);
928                 }
929
930                 /* Finally, recursively add in all dependencies. */
931                 if (type == JOB_START || type == JOB_RESTART) {
932                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES], i) {
933                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
934                                 if (r < 0) {
935                                         if (r != -EBADR)
936                                                 goto fail;
937
938                                         if (e)
939                                                 sd_bus_error_free(e);
940                                 }
941                         }
942
943                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_BINDS_TO], i) {
944                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
945                                 if (r < 0) {
946                                         if (r != -EBADR)
947                                                 goto fail;
948
949                                         if (e)
950                                                 sd_bus_error_free(e);
951                                 }
952                         }
953
954                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES_OVERRIDABLE], i) {
955                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, !override, override, false, false, ignore_order, e);
956                                 if (r < 0) {
957                                         log_unit_full(dep->id,
958                                                       r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING,
959                                                       "Cannot add dependency job for unit %s, ignoring: %s",
960                                                       dep->id, bus_error_message(e, r));
961
962                                         if (e)
963                                                 sd_bus_error_free(e);
964                                 }
965                         }
966
967                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_WANTS], i) {
968                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, false, ignore_order, e);
969                                 if (r < 0) {
970                                         log_unit_full(dep->id,
971                                                       r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING,
972                                                       "Cannot add dependency job for unit %s, ignoring: %s",
973                                                       dep->id, bus_error_message(e, r));
974
975                                         if (e)
976                                                 sd_bus_error_free(e);
977                                 }
978                         }
979
980                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE], i) {
981                                 r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, override, false, false, ignore_order, e);
982                                 if (r < 0) {
983                                         if (r != -EBADR)
984                                                 goto fail;
985
986                                         if (e)
987                                                 sd_bus_error_free(e);
988                                 }
989                         }
990
991                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE_OVERRIDABLE], i) {
992                                 r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, !override, override, false, false, ignore_order, e);
993                                 if (r < 0) {
994                                         log_unit_full(dep->id,
995                                                       r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING,
996                                                       "Cannot add dependency job for unit %s, ignoring: %s",
997                                                       dep->id, bus_error_message(e, r));
998
999                                         if (e)
1000                                                 sd_bus_error_free(e);
1001                                 }
1002                         }
1003
1004                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTS], i) {
1005                                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, override, true, false, ignore_order, e);
1006                                 if (r < 0) {
1007                                         if (r != -EBADR)
1008                                                 goto fail;
1009
1010                                         if (e)
1011                                                 sd_bus_error_free(e);
1012                                 }
1013                         }
1014
1015                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTED_BY], i) {
1016                                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, override, false, false, ignore_order, e);
1017                                 if (r < 0) {
1018                                         log_unit_warning(dep->id,
1019                                                          "Cannot add dependency job for unit %s, ignoring: %s",
1020                                                          dep->id, bus_error_message(e, r));
1021
1022                                         if (e)
1023                                                 sd_bus_error_free(e);
1024                                 }
1025                         }
1026
1027                 }
1028
1029                 if (type == JOB_STOP || type == JOB_RESTART) {
1030
1031                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRED_BY], i) {
1032                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1033                                 if (r < 0) {
1034                                         if (r != -EBADR)
1035                                                 goto fail;
1036
1037                                         if (e)
1038                                                 sd_bus_error_free(e);
1039                                 }
1040                         }
1041
1042                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_BOUND_BY], i) {
1043                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1044                                 if (r < 0) {
1045                                         if (r != -EBADR)
1046                                                 goto fail;
1047
1048                                         if (e)
1049                                                 sd_bus_error_free(e);
1050                                 }
1051                         }
1052
1053                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONSISTS_OF], i) {
1054                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1055                                 if (r < 0) {
1056                                         if (r != -EBADR)
1057                                                 goto fail;
1058
1059                                         if (e)
1060                                                 sd_bus_error_free(e);
1061                                 }
1062                         }
1063
1064                 }
1065
1066                 if (type == JOB_RELOAD) {
1067
1068                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) {
1069                                 r = transaction_add_job_and_dependencies(tr, JOB_RELOAD, dep, ret, false, override, false, false, ignore_order, e);
1070                                 if (r < 0) {
1071                                         log_unit_warning(dep->id,
1072                                                          "Cannot add dependency reload job for unit %s, ignoring: %s",
1073                                                          dep->id, bus_error_message(e, r));
1074
1075                                         if (e)
1076                                                 sd_bus_error_free(e);
1077                                 }
1078                         }
1079                 }
1080
1081                 /* JOB_VERIFY_STARTED require no dependency handling */
1082         }
1083
1084         return 0;
1085
1086 fail:
1087         return r;
1088 }
1089
1090 int transaction_add_isolate_jobs(Transaction *tr, Manager *m) {
1091         Iterator i;
1092         Unit *u;
1093         char *k;
1094         int r;
1095
1096         assert(tr);
1097         assert(m);
1098
1099         HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1100
1101                 /* ignore aliases */
1102                 if (u->id != k)
1103                         continue;
1104
1105                 if (u->ignore_on_isolate)
1106                         continue;
1107
1108                 /* No need to stop inactive jobs */
1109                 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)) && !u->job)
1110                         continue;
1111
1112                 /* Is there already something listed for this? */
1113                 if (hashmap_get(tr->jobs, u))
1114                         continue;
1115
1116                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, u, tr->anchor_job, true, false, false, false, false, NULL);
1117                 if (r < 0)
1118                         log_unit_warning(u->id,
1119                                          "Cannot add isolate job for unit %s, ignoring: %s",
1120                                          u->id, strerror(-r));
1121         }
1122
1123         return 0;
1124 }
1125
1126 Transaction *transaction_new(bool irreversible) {
1127         Transaction *tr;
1128
1129         tr = new0(Transaction, 1);
1130         if (!tr)
1131                 return NULL;
1132
1133         tr->jobs = hashmap_new(NULL);
1134         if (!tr->jobs) {
1135                 free(tr);
1136                 return NULL;
1137         }
1138
1139         tr->irreversible = irreversible;
1140
1141         return tr;
1142 }
1143
1144 void transaction_free(Transaction *tr) {
1145         assert(hashmap_isempty(tr->jobs));
1146         hashmap_free(tr->jobs);
1147         free(tr);
1148 }