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