@@ -60,6 +60,7 @@ Job* job_new_raw(Unit *unit) {
60
60
61
61
j -> manager = unit -> manager ;
62
62
j -> unit = unit ;
63
+ j -> type = _JOB_TYPE_INVALID ;
63
64
j -> timer_watch .type = WATCH_INVALID ;
64
65
65
66
return j ;
@@ -115,15 +116,21 @@ void job_free(Job *j) {
115
116
}
116
117
117
118
void job_uninstall (Job * j ) {
119
+ Job * * pj ;
120
+
118
121
assert (j -> installed );
119
- assert (j -> unit -> job == j );
122
+
123
+ pj = (j -> type == JOB_NOP ) ? & j -> unit -> nop_job : & j -> unit -> job ;
124
+ assert (* pj == j );
125
+
120
126
/* Detach from next 'bigger' objects */
121
127
122
128
/* daemon-reload should be transparent to job observers */
123
129
if (j -> manager -> n_reloading <= 0 )
124
130
bus_job_send_removed_signal (j );
125
131
126
- j -> unit -> job = NULL ;
132
+ * pj = NULL ;
133
+
127
134
unit_add_to_gc_queue (j -> unit );
128
135
129
136
hashmap_remove (j -> manager -> jobs , UINT32_TO_PTR (j -> id ));
@@ -144,31 +151,38 @@ static bool job_type_allows_late_merge(JobType t) {
144
151
* patched into JOB_START after stopping the unit. So if we see a
145
152
* JOB_RESTART running, it means the unit hasn't stopped yet and at
146
153
* this time the merge is still allowed. */
147
- return !( t == JOB_RELOAD || t == JOB_RELOAD_OR_START ) ;
154
+ return t != JOB_RELOAD ;
148
155
}
149
156
150
157
static void job_merge_into_installed (Job * j , Job * other ) {
151
158
assert (j -> installed );
152
159
assert (j -> unit == other -> unit );
153
160
154
- j -> type = job_type_lookup_merge (j -> type , other -> type );
155
- assert (j -> type >= 0 );
161
+ if (j -> type != JOB_NOP )
162
+ job_type_merge_and_collapse (& j -> type , other -> type , j -> unit );
163
+ else
164
+ assert (other -> type == JOB_NOP );
156
165
157
166
j -> override = j -> override || other -> override ;
158
167
}
159
168
160
169
Job * job_install (Job * j ) {
161
- Job * uj = j -> unit -> job ;
170
+ Job * * pj ;
171
+ Job * uj ;
162
172
163
173
assert (!j -> installed );
174
+ assert (j -> type < _JOB_TYPE_MAX_IN_TRANSACTION );
175
+
176
+ pj = (j -> type == JOB_NOP ) ? & j -> unit -> nop_job : & j -> unit -> job ;
177
+ uj = * pj ;
164
178
165
179
if (uj ) {
166
- if (job_type_is_conflicting (uj -> type , j -> type ))
180
+ if (j -> type != JOB_NOP && job_type_is_conflicting (uj -> type , j -> type ))
167
181
job_finish_and_invalidate (uj , JOB_CANCELED , true);
168
182
else {
169
183
/* not conflicting, i.e. mergeable */
170
184
171
- if (uj -> state == JOB_WAITING ||
185
+ if (j -> type == JOB_NOP || uj -> state == JOB_WAITING ||
172
186
(job_type_allows_late_merge (j -> type ) && job_type_is_superset (uj -> type , j -> type ))) {
173
187
job_merge_into_installed (uj , j );
174
188
log_debug ("Merged into installed job %s/%s as %u" ,
@@ -189,23 +203,33 @@ Job* job_install(Job *j) {
189
203
}
190
204
191
205
/* Install the job */
192
- j -> unit -> job = j ;
206
+ * pj = j ;
193
207
j -> installed = true;
194
208
j -> manager -> n_installed_jobs ++ ;
195
209
log_debug ("Installed new job %s/%s as %u" , j -> unit -> id , job_type_to_string (j -> type ), (unsigned ) j -> id );
196
210
return j ;
197
211
}
198
212
199
- void job_install_deserialized (Job * j ) {
213
+ int job_install_deserialized (Job * j ) {
214
+ Job * * pj ;
215
+
200
216
assert (!j -> installed );
201
217
202
- if (j -> unit -> job ) {
218
+ if (j -> type < 0 || j -> type >= _JOB_TYPE_MAX_IN_TRANSACTION ) {
219
+ log_debug ("Invalid job type %s in deserialization." , strna (job_type_to_string (j -> type )));
220
+ return - EINVAL ;
221
+ }
222
+
223
+ pj = (j -> type == JOB_NOP ) ? & j -> unit -> nop_job : & j -> unit -> job ;
224
+
225
+ if (* pj ) {
203
226
log_debug ("Unit %s already has a job installed. Not installing deserialized job." , j -> unit -> id );
204
- return ;
227
+ return - EEXIST ;
205
228
}
206
- j -> unit -> job = j ;
229
+ * pj = j ;
207
230
j -> installed = true;
208
231
log_debug ("Reinstalled deserialized job %s/%s as %u" , j -> unit -> id , job_type_to_string (j -> type ), (unsigned ) j -> id );
232
+ return 0 ;
209
233
}
210
234
211
235
JobDependency * job_dependency_new (Job * subject , Job * object , bool matters , bool conflicts ) {
@@ -268,6 +292,10 @@ void job_dump(Job *j, FILE*f, const char *prefix) {
268
292
* its lower triangle to avoid duplication. We don't store the main diagonal,
269
293
* because A merged with A is simply A.
270
294
*
295
+ * If the resulting type is collapsed immediately afterwards (to get rid of
296
+ * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
297
+ * the following properties hold:
298
+ *
271
299
* Merging is associative! A merged with B merged with C is the same as
272
300
* A merged with C merged with B.
273
301
*
@@ -278,21 +306,19 @@ void job_dump(Job *j, FILE*f, const char *prefix) {
278
306
* be merged with C either.
279
307
*/
280
308
static const JobType job_merging_table [] = {
281
- /* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD JOB_RELOAD_OR_START JOB_RESTART JOB_TRY_RESTART */
282
- /************************************************************************************************************************************ /
309
+ /* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
310
+ /*********************************************************************************/
283
311
/*JOB_START */
284
312
/*JOB_VERIFY_ACTIVE */ JOB_START ,
285
313
/*JOB_STOP */ -1 , -1 ,
286
314
/*JOB_RELOAD */ JOB_RELOAD_OR_START , JOB_RELOAD , -1 ,
287
- /*JOB_RELOAD_OR_START*/ JOB_RELOAD_OR_START , JOB_RELOAD_OR_START , -1 , JOB_RELOAD_OR_START ,
288
- /*JOB_RESTART */ JOB_RESTART , JOB_RESTART , -1 , JOB_RESTART , JOB_RESTART ,
289
- /*JOB_TRY_RESTART */ JOB_RESTART , JOB_TRY_RESTART , -1 , JOB_TRY_RESTART , JOB_RESTART , JOB_RESTART ,
315
+ /*JOB_RESTART */ JOB_RESTART , JOB_RESTART , -1 , JOB_RESTART ,
290
316
};
291
317
292
318
JobType job_type_lookup_merge (JobType a , JobType b ) {
293
- assert_cc (ELEMENTSOF (job_merging_table ) == _JOB_TYPE_MAX * (_JOB_TYPE_MAX - 1 ) / 2 );
294
- assert (a >= 0 && a < _JOB_TYPE_MAX );
295
- assert (b >= 0 && b < _JOB_TYPE_MAX );
319
+ assert_cc (ELEMENTSOF (job_merging_table ) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1 ) / 2 );
320
+ assert (a >= 0 && a < _JOB_TYPE_MAX_MERGING );
321
+ assert (b >= 0 && b < _JOB_TYPE_MAX_MERGING );
296
322
297
323
if (a == b )
298
324
return a ;
@@ -328,24 +354,50 @@ bool job_type_is_redundant(JobType a, UnitActiveState b) {
328
354
return
329
355
b == UNIT_RELOADING ;
330
356
331
- case JOB_RELOAD_OR_START :
332
- return
333
- b == UNIT_ACTIVATING ||
334
- b == UNIT_RELOADING ;
335
-
336
357
case JOB_RESTART :
337
358
return
338
359
b == UNIT_ACTIVATING ;
339
360
361
+ default :
362
+ assert_not_reached ("Invalid job type" );
363
+ }
364
+ }
365
+
366
+ void job_type_collapse (JobType * t , Unit * u ) {
367
+ UnitActiveState s ;
368
+
369
+ switch (* t ) {
370
+
340
371
case JOB_TRY_RESTART :
341
- return
342
- b == UNIT_ACTIVATING ;
372
+ s = unit_active_state (u );
373
+ if (UNIT_IS_INACTIVE_OR_DEACTIVATING (s ))
374
+ * t = JOB_NOP ;
375
+ else
376
+ * t = JOB_RESTART ;
377
+ break ;
378
+
379
+ case JOB_RELOAD_OR_START :
380
+ s = unit_active_state (u );
381
+ if (UNIT_IS_INACTIVE_OR_DEACTIVATING (s ))
382
+ * t = JOB_START ;
383
+ else
384
+ * t = JOB_RELOAD ;
385
+ break ;
343
386
344
387
default :
345
- assert_not_reached ( "Invalid job type" ) ;
388
+ ;
346
389
}
347
390
}
348
391
392
+ int job_type_merge_and_collapse (JobType * a , JobType b , Unit * u ) {
393
+ JobType t = job_type_lookup_merge (* a , b );
394
+ if (t < 0 )
395
+ return - EEXIST ;
396
+ * a = t ;
397
+ job_type_collapse (a , u );
398
+ return 0 ;
399
+ }
400
+
349
401
bool job_is_runnable (Job * j ) {
350
402
Iterator i ;
351
403
Unit * other ;
@@ -362,10 +414,12 @@ bool job_is_runnable(Job *j) {
362
414
if (j -> ignore_order )
363
415
return true;
364
416
417
+ if (j -> type == JOB_NOP )
418
+ return true;
419
+
365
420
if (j -> type == JOB_START ||
366
421
j -> type == JOB_VERIFY_ACTIVE ||
367
- j -> type == JOB_RELOAD ||
368
- j -> type == JOB_RELOAD_OR_START ) {
422
+ j -> type == JOB_RELOAD ) {
369
423
370
424
/* Immediate result is that the job is or might be
371
425
* started. In this case lets wait for the
@@ -383,8 +437,7 @@ bool job_is_runnable(Job *j) {
383
437
SET_FOREACH (other , j -> unit -> dependencies [UNIT_BEFORE ], i )
384
438
if (other -> job &&
385
439
(other -> job -> type == JOB_STOP ||
386
- other -> job -> type == JOB_RESTART ||
387
- other -> job -> type == JOB_TRY_RESTART ))
440
+ other -> job -> type == JOB_RESTART ))
388
441
return false;
389
442
390
443
/* This means that for a service a and a service b where b
@@ -416,6 +469,7 @@ int job_run_and_invalidate(Job *j) {
416
469
417
470
assert (j );
418
471
assert (j -> installed );
472
+ assert (j -> type < _JOB_TYPE_MAX_IN_TRANSACTION );
419
473
420
474
if (j -> in_run_queue ) {
421
475
LIST_REMOVE (Job , run_queue , j -> manager -> run_queue , j );
@@ -441,15 +495,6 @@ int job_run_and_invalidate(Job *j) {
441
495
442
496
switch (j -> type ) {
443
497
444
- case JOB_RELOAD_OR_START :
445
- if (unit_active_state (j -> unit ) == UNIT_ACTIVE ) {
446
- job_change_type (j , JOB_RELOAD );
447
- r = unit_reload (j -> unit );
448
- break ;
449
- }
450
- job_change_type (j , JOB_START );
451
- /* fall through */
452
-
453
498
case JOB_START :
454
499
r = unit_start (j -> unit );
455
500
@@ -469,14 +514,6 @@ int job_run_and_invalidate(Job *j) {
469
514
break ;
470
515
}
471
516
472
- case JOB_TRY_RESTART :
473
- if (UNIT_IS_INACTIVE_OR_DEACTIVATING (unit_active_state (j -> unit ))) {
474
- r = - ENOEXEC ;
475
- break ;
476
- }
477
- job_change_type (j , JOB_RESTART );
478
- /* fall through */
479
-
480
517
case JOB_STOP :
481
518
case JOB_RESTART :
482
519
r = unit_stop (j -> unit );
@@ -490,11 +527,16 @@ int job_run_and_invalidate(Job *j) {
490
527
r = unit_reload (j -> unit );
491
528
break ;
492
529
530
+ case JOB_NOP :
531
+ r = - EALREADY ;
532
+ break ;
533
+
493
534
default :
494
535
assert_not_reached ("Unknown job type" );
495
536
}
496
537
497
- if ((j = manager_get_job (m , id ))) {
538
+ j = manager_get_job (m , id );
539
+ if (j ) {
498
540
if (r == - EALREADY )
499
541
r = job_finish_and_invalidate (j , JOB_DONE , true);
500
542
else if (r == - ENOEXEC )
@@ -564,6 +606,7 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
564
606
565
607
assert (j );
566
608
assert (j -> installed );
609
+ assert (j -> type < _JOB_TYPE_MAX_IN_TRANSACTION );
567
610
568
611
job_add_to_dbus_queue (j );
569
612
@@ -597,38 +640,33 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
597
640
if (result != JOB_DONE && recursive ) {
598
641
599
642
if (t == JOB_START ||
600
- t == JOB_VERIFY_ACTIVE ||
601
- t == JOB_RELOAD_OR_START ) {
643
+ t == JOB_VERIFY_ACTIVE ) {
602
644
603
645
SET_FOREACH (other , u -> dependencies [UNIT_REQUIRED_BY ], i )
604
646
if (other -> job &&
605
647
(other -> job -> type == JOB_START ||
606
- other -> job -> type == JOB_VERIFY_ACTIVE ||
607
- other -> job -> type == JOB_RELOAD_OR_START ))
648
+ other -> job -> type == JOB_VERIFY_ACTIVE ))
608
649
job_finish_and_invalidate (other -> job , JOB_DEPENDENCY , true);
609
650
610
651
SET_FOREACH (other , u -> dependencies [UNIT_BOUND_BY ], i )
611
652
if (other -> job &&
612
653
(other -> job -> type == JOB_START ||
613
- other -> job -> type == JOB_VERIFY_ACTIVE ||
614
- other -> job -> type == JOB_RELOAD_OR_START ))
654
+ other -> job -> type == JOB_VERIFY_ACTIVE ))
615
655
job_finish_and_invalidate (other -> job , JOB_DEPENDENCY , true);
616
656
617
657
SET_FOREACH (other , u -> dependencies [UNIT_REQUIRED_BY_OVERRIDABLE ], i )
618
658
if (other -> job &&
619
659
!other -> job -> override &&
620
660
(other -> job -> type == JOB_START ||
621
- other -> job -> type == JOB_VERIFY_ACTIVE ||
622
- other -> job -> type == JOB_RELOAD_OR_START ))
661
+ other -> job -> type == JOB_VERIFY_ACTIVE ))
623
662
job_finish_and_invalidate (other -> job , JOB_DEPENDENCY , true);
624
663
625
664
} else if (t == JOB_STOP ) {
626
665
627
666
SET_FOREACH (other , u -> dependencies [UNIT_CONFLICTED_BY ], i )
628
667
if (other -> job &&
629
668
(other -> job -> type == JOB_START ||
630
- other -> job -> type == JOB_VERIFY_ACTIVE ||
631
- other -> job -> type == JOB_RELOAD_OR_START ))
669
+ other -> job -> type == JOB_VERIFY_ACTIVE ))
632
670
job_finish_and_invalidate (other -> job , JOB_DEPENDENCY , true);
633
671
}
634
672
}
@@ -808,6 +846,8 @@ int job_deserialize(Job *j, FILE *f, FDSet *fds) {
808
846
JobType t = job_type_from_string (v );
809
847
if (t < 0 )
810
848
log_debug ("Failed to parse job type %s" , v );
849
+ else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION )
850
+ log_debug ("Cannot deserialize job of type %s" , v );
811
851
else
812
852
j -> type = t ;
813
853
} else if (streq (l , "job-state" )) {
@@ -887,6 +927,7 @@ static const char* const job_type_table[_JOB_TYPE_MAX] = {
887
927
[JOB_RELOAD_OR_START ] = "reload-or-start" ,
888
928
[JOB_RESTART ] = "restart" ,
889
929
[JOB_TRY_RESTART ] = "try-restart" ,
930
+ [JOB_NOP ] = "nop" ,
890
931
};
891
932
892
933
DEFINE_STRING_TABLE_LOOKUP (job_type , JobType );
0 commit comments