Add Restart() handler
[profile/ivi/node-startup-controller.git] / boot-manager / boot-manager-service.c
1 /* vi:set et ai sw=2 sts=2 ts=2: */
2 /* -
3  * Copyright (c) 2012 GENIVI.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9
10 #ifdef HAVE_CONFIG_H
11 #include <config.h>
12 #endif
13
14 #include <glib-object.h>
15 #include <gio/gio.h>
16
17 #include <boot-manager/boot-manager-dbus.h>
18 #include <boot-manager/boot-manager-service.h>
19
20
21
22 typedef struct _BootManagerServiceJob BootManagerServiceJob;
23
24
25
26 /* property identifiers */
27 enum
28 {
29   PROP_0,
30   PROP_CONNECTION,
31   PROP_SYSTEMD_MANAGER,
32 };
33
34
35
36 static void                   boot_manager_service_finalize              (GObject                   *object);
37 static void                   boot_manager_service_constructed           (GObject                   *object);
38 static void                   boot_manager_service_get_property          (GObject                   *object,
39                                                                           guint                      prop_id,
40                                                                           GValue                    *value,
41                                                                           GParamSpec                *pspec);
42 static void                   boot_manager_service_set_property          (GObject                   *object,
43                                                                           guint                      prop_id,
44                                                                           const GValue              *value,
45                                                                           GParamSpec                *pspec);
46 static gboolean               boot_manager_service_handle_start          (BootManager               *interface,
47                                                                           GDBusMethodInvocation     *invocation,
48                                                                           const gchar               *unit,
49                                                                           BootManagerService        *service);
50 static void                   boot_manager_service_handle_start_finish   (BootManagerService        *service,
51                                                                           const gchar               *unit,
52                                                                           const gchar               *result,
53                                                                           GError                    *error,
54                                                                           gpointer                   user_data);
55 static void                   boot_manager_service_start_unit_reply      (GObject                   *object,
56                                                                           GAsyncResult              *result,
57                                                                           gpointer                   user_data);
58 static gboolean               boot_manager_service_handle_stop           (BootManager               *interface,
59                                                                           GDBusMethodInvocation     *invocation,
60                                                                           const gchar               *unit,
61                                                                           BootManagerService        *service);
62 static void                   boot_manager_service_handle_stop_finish    (BootManagerService        *service,
63                                                                           const gchar               *unit,
64                                                                           const gchar               *result,
65                                                                           GError                    *error,
66                                                                           gpointer                   user_data);
67 static void                   boot_manager_service_stop_unit_reply       (GObject                   *object,
68                                                                           GAsyncResult              *result,
69                                                                           gpointer                   user_data);
70 static gboolean               boot_manager_service_handle_kill           (BootManager               *interface,
71                                                                           GDBusMethodInvocation     *invocation,
72                                                                           const gchar               *unit,
73                                                                           BootManagerService        *service);
74 static void                   boot_manager_service_handle_kill_finish    (BootManagerService        *service,
75                                                                           const gchar               *unit,
76                                                                           const gchar               *result,
77                                                                           GError                    *error,
78                                                                           gpointer                   user_data);
79 static void                   boot_manager_service_kill_unit_reply       (GObject                   *object,
80                                                                           GAsyncResult              *result,
81                                                                           gpointer                   user_data);
82 static gboolean               boot_manager_service_handle_restart        (BootManager               *interface,
83                                                                           GDBusMethodInvocation     *invocation,
84                                                                           const gchar               *unit,
85                                                                           BootManagerService        *service);
86 static void                   boot_manager_service_handle_restart_finish (BootManagerService        *service,
87                                                                           const gchar               *unit,
88                                                                           const gchar               *result,
89                                                                           GError                    *error,
90                                                                           gpointer                   user_data);
91 static void                   boot_manager_service_restart_unit_reply    (GObject                   *object,
92                                                                           GAsyncResult              *result,
93                                                                           gpointer                   user_data);
94 static void                   boot_manager_service_job_removed           (SystemdManager            *manager,
95                                                                           guint                      id,
96                                                                           const gchar               *job_name,
97                                                                           const gchar               *result,
98                                                                           BootManagerService        *service);
99 static BootManagerServiceJob *boot_manager_service_job_new               (BootManagerService        *service,
100                                                                           const gchar               *unit,
101                                                                           GCancellable              *cancellable,
102                                                                           BootManagerServiceCallback callback,
103                                                                           gpointer                   user_data);
104 static void                   boot_manager_service_job_unref             (BootManagerServiceJob     *job);
105 static void                   boot_manager_service_remember_job          (BootManagerService        *service,
106                                                                           const gchar               *job_name,
107                                                                           BootManagerServiceJob     *job);
108 static void                   boot_manager_service_forget_job            (BootManagerService        *service,
109                                                                           const gchar               *job_name);
110
111
112
113 struct _BootManagerServiceClass
114 {
115   GObjectClass __parent__;
116 };
117
118 struct _BootManagerService
119 {
120   GObject          __parent__;
121
122   GDBusConnection *connection;
123   BootManager     *interface;
124   SystemdManager  *systemd_manager;
125
126   GHashTable      *jobs;
127 };
128
129 struct _BootManagerServiceJob
130 {
131   BootManagerService        *service;
132   gchar                     *unit;
133   GCancellable              *cancellable;
134   BootManagerServiceCallback callback;
135   gpointer                   user_data;
136   gchar                     *name;
137 };
138
139
140
141 G_DEFINE_TYPE (BootManagerService, boot_manager_service, G_TYPE_OBJECT);
142
143
144
145 static void
146 boot_manager_service_class_init (BootManagerServiceClass *klass)
147 {
148   GObjectClass *gobject_class;
149
150   gobject_class = G_OBJECT_CLASS (klass);
151   gobject_class->finalize = boot_manager_service_finalize;
152   gobject_class->constructed = boot_manager_service_constructed;
153   gobject_class->get_property = boot_manager_service_get_property;
154   gobject_class->set_property = boot_manager_service_set_property;
155
156   g_object_class_install_property (gobject_class,
157                                    PROP_CONNECTION,
158                                    g_param_spec_object ("connection",
159                                                         "connection",
160                                                         "connection",
161                                                         G_TYPE_DBUS_CONNECTION,
162                                                         G_PARAM_READWRITE |
163                                                         G_PARAM_CONSTRUCT_ONLY |
164                                                         G_PARAM_STATIC_STRINGS));
165
166   g_object_class_install_property (gobject_class,
167                                    PROP_SYSTEMD_MANAGER,
168                                    g_param_spec_object ("systemd-manager",
169                                                         "systemd-manager",
170                                                         "systemd-manager",
171                                                         TYPE_SYSTEMD_MANAGER,
172                                                         G_PARAM_READWRITE |
173                                                         G_PARAM_CONSTRUCT_ONLY |
174                                                         G_PARAM_STATIC_STRINGS));
175 }
176
177
178
179 static void
180 boot_manager_service_init (BootManagerService *service)
181 {
182   /* create a mapping of systemd job names to job objects; we will use this
183    * to remember jobs that we started */
184   service->jobs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
185                                          (GDestroyNotify) boot_manager_service_job_unref);
186
187   service->interface = boot_manager_skeleton_new ();
188
189   /* implement the Start() method handler */
190   g_signal_connect (service->interface, "handle-start",
191                     G_CALLBACK (boot_manager_service_handle_start), service);
192
193   /* implement the Stop() method handler */
194   g_signal_connect (service->interface, "handle-stop",
195                     G_CALLBACK (boot_manager_service_handle_stop), service);
196
197   /* implement the Kill() method handler */
198   g_signal_connect (service->interface, "handle-kill",
199                     G_CALLBACK (boot_manager_service_handle_kill), service);
200   /* implement the Restart() method handler */
201   g_signal_connect (service->interface, "handle-restart",
202                     G_CALLBACK (boot_manager_service_handle_restart), service);
203 }
204
205
206
207 static void
208 boot_manager_service_finalize (GObject *object)
209 {
210   BootManagerService *service = BOOT_MANAGER_SERVICE (object);
211
212   /* release all the jobs we have remembered */
213   g_hash_table_unref (service->jobs);
214
215   /* release the D-Bus connection object */
216   g_object_unref (service->connection);
217
218   /* release the systemd manager */
219   g_signal_handlers_disconnect_matched (service->systemd_manager,
220                                         G_SIGNAL_MATCH_DATA,
221                                         0, 0, NULL, NULL, service);
222   g_object_unref (service->systemd_manager);
223
224   /* release the interface skeleton */
225   g_signal_handlers_disconnect_matched (service->interface,
226                                         G_SIGNAL_MATCH_DATA,
227                                         0, 0, NULL, NULL, service);
228   g_object_unref (service->interface);
229
230   (*G_OBJECT_CLASS (boot_manager_service_parent_class)->finalize) (object);
231 }
232
233
234
235 static void
236 boot_manager_service_constructed (GObject *object)
237 {
238   BootManagerService *service = BOOT_MANAGER_SERVICE (object);
239
240   /* connect to systemd's "JobRemoved" signal so that we are notified
241    * whenever a job is finished */
242   g_signal_connect (service->systemd_manager, "job-removed",
243                     G_CALLBACK (boot_manager_service_job_removed), service);
244 }
245
246
247
248 static void
249 boot_manager_service_get_property (GObject    *object,
250                                    guint       prop_id,
251                                    GValue     *value,
252                                    GParamSpec *pspec)
253 {
254   BootManagerService *service = BOOT_MANAGER_SERVICE (object);
255
256   switch (prop_id)
257     {
258     case PROP_CONNECTION:
259       g_value_set_object (value, service->connection);
260       break;
261     case PROP_SYSTEMD_MANAGER:
262       g_value_set_object (value, service->systemd_manager);
263       break;
264     default:
265       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
266       break;
267     }
268 }
269
270
271
272 static void
273 boot_manager_service_set_property (GObject      *object,
274                                    guint         prop_id,
275                                    const GValue *value,
276                                    GParamSpec   *pspec)
277 {
278   BootManagerService *service = BOOT_MANAGER_SERVICE (object);
279
280   switch (prop_id)
281     {
282     case PROP_CONNECTION:
283       service->connection = g_value_dup_object (value);
284       break;
285     case PROP_SYSTEMD_MANAGER:
286       service->systemd_manager = g_value_dup_object (value);
287       break;
288     default:
289       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
290       break;
291     }
292 }
293
294
295
296 static gboolean
297 boot_manager_service_handle_start (BootManager           *interface,
298                                    GDBusMethodInvocation *invocation,
299                                    const gchar           *unit,
300                                    BootManagerService    *service)
301 {
302   g_return_val_if_fail (IS_BOOT_MANAGER (interface), FALSE);
303   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE);
304   g_return_val_if_fail (unit != NULL, FALSE);
305   g_return_val_if_fail (BOOT_MANAGER_IS_SERVICE (service), FALSE);
306
307   /* ask systemd to start the unit for us, send a D-Bus reply in the finish callback */
308   boot_manager_service_start (service, unit, NULL,
309                               boot_manager_service_handle_start_finish, invocation);
310
311   return TRUE;
312 }
313
314
315
316 static void
317 boot_manager_service_handle_start_finish (BootManagerService *service,
318                                           const gchar        *unit,
319                                           const gchar        *result,
320                                           GError             *error,
321                                           gpointer            user_data)
322 {
323   GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
324
325   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
326   g_return_if_fail (unit != NULL);
327   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
328
329   /* log any potential errors */
330   if (error != NULL)
331     g_warning ("there was an error: %s", error->message);
332
333   /* report the result back to the boot manager client */
334   boot_manager_complete_start (service->interface, invocation, result);
335 }
336
337
338
339 static void
340 boot_manager_service_start_unit_reply (GObject      *object,
341                                        GAsyncResult *result,
342                                        gpointer      user_data)
343 {
344   BootManagerServiceJob *job = user_data;
345   GError                *error = NULL;
346   gchar                 *job_name = NULL;
347
348   g_return_if_fail (IS_SYSTEMD_MANAGER (object));
349   g_return_if_fail (G_IS_ASYNC_RESULT (result));
350   g_return_if_fail (user_data != NULL);
351
352   /* finish the start unit call */
353   if (!systemd_manager_call_start_unit_finish (job->service->systemd_manager,
354                                                &job_name, result, &error))
355     {
356       /* there was an error; let the caller know */
357       job->callback (job->service, job->unit, "failed", error, job->user_data);
358       g_error_free (error);
359       g_free (job_name);
360
361       /* finish the job immediately */
362       boot_manager_service_job_unref (job);
363     }
364   else
365     {
366       /* remember the job so that we can finish it in the "job-removed" signal
367        * handler. the service takes ownership of the job so we don't need to
368        * unref it here */
369       boot_manager_service_remember_job (job->service, job_name, job);
370     }
371 }
372
373
374
375 static gboolean
376 boot_manager_service_handle_stop (BootManager           *interface,
377                                   GDBusMethodInvocation *invocation,
378                                   const gchar           *unit,
379                                   BootManagerService    *service)
380 {
381   g_return_val_if_fail (IS_BOOT_MANAGER (interface), FALSE);
382   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE);
383   g_return_val_if_fail (unit != NULL, FALSE);
384   g_return_val_if_fail (BOOT_MANAGER_IS_SERVICE (service), FALSE);
385
386   /* ask systemd to stop the unit for us, send a D-Bus reply in the finish callback */
387   boot_manager_service_stop (service, unit, NULL,
388                              boot_manager_service_handle_stop_finish, invocation);
389
390   return TRUE;
391 }
392
393
394
395 static void
396 boot_manager_service_handle_stop_finish (BootManagerService *service,
397                                          const gchar        *unit,
398                                          const gchar        *result,
399                                          GError             *error,
400                                          gpointer            user_data)
401 {
402   GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
403
404   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
405   g_return_if_fail (unit != NULL);
406   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
407
408   /* log any potential errors */
409   if (error != NULL)
410     g_warning ("there was an error: %s", error->message);
411
412   /* report the result back to the boot manager client */
413   boot_manager_complete_stop (service->interface, invocation, result);
414 }
415
416
417
418 static void
419 boot_manager_service_stop_unit_reply (GObject      *object,
420                                       GAsyncResult *result,
421                                       gpointer      user_data)
422 {
423   BootManagerServiceJob *job = user_data;
424   GError                *error = NULL;
425   gchar                 *job_name = NULL;
426
427   g_return_if_fail (IS_SYSTEMD_MANAGER (object));
428   g_return_if_fail (G_IS_ASYNC_RESULT (result));
429   g_return_if_fail (user_data != NULL);
430
431   /* finish the stop unit call */
432   if (!systemd_manager_call_stop_unit_finish (job->service->systemd_manager,
433                                               &job_name, result, &error))
434     {
435       /* there was an error; let the caller know */
436       job->callback (job->service, job->unit, "failed", error, job->user_data);
437       g_error_free (error);
438       g_free (job_name);
439
440       /* finish the job immediately */
441       boot_manager_service_job_unref (job);
442     }
443   else
444     {
445       /* remember the job so that we can finish it in the "job-removed" signal
446        * handler. the service takes ownership of the job so we don't need to
447        * unref it here */
448       boot_manager_service_remember_job (job->service, job_name, job);
449     }
450 }
451
452
453
454 static gboolean
455 boot_manager_service_handle_kill (BootManager           *interface,
456                                   GDBusMethodInvocation *invocation,
457                                   const gchar           *unit,
458                                   BootManagerService    *service)
459 {
460   g_return_val_if_fail (IS_BOOT_MANAGER (interface), FALSE);
461   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE);
462   g_return_val_if_fail (unit != NULL, FALSE);
463   g_return_val_if_fail (BOOT_MANAGER_IS_SERVICE (service), FALSE);  
464
465   /* ask systemd to kill the unit, send a D-Bus reply in the finish callback */
466   boot_manager_service_kill (service, unit, NULL, boot_manager_service_handle_kill_finish,
467                              invocation);
468
469   return TRUE;
470 }
471
472
473
474 static void
475 boot_manager_service_handle_kill_finish (BootManagerService *service,
476                                          const gchar        *unit,
477                                          const gchar        *result,
478                                          GError             *error,
479                                          gpointer            user_data)
480 {
481   GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
482
483   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
484   g_return_if_fail (unit!= NULL);
485   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
486
487   /* log any potential errors */
488   if (error != NULL)
489     g_warning ("there was an error: %s", error->message);
490
491   /* report the result back to the boot manager client */
492   boot_manager_complete_kill (service->interface, invocation, result);
493 }
494
495
496
497 static void
498 boot_manager_service_kill_unit_reply (GObject      *object,
499                                       GAsyncResult *result,
500                                       gpointer      user_data)
501 {
502   BootManagerServiceJob *job = user_data;
503   GError                *error = NULL;
504
505   g_return_if_fail (IS_SYSTEMD_MANAGER (object));
506   g_return_if_fail (G_IS_ASYNC_RESULT (result));
507   g_return_if_fail (user_data != NULL);
508
509   /* finish the kill unit call */
510   systemd_manager_call_kill_unit_finish (job->service->systemd_manager,
511                                          result, &error);
512
513   /* got a reply from systemd; let the caller know we're done */
514   job->callback (job->service, job->unit, (error == NULL) ? "done" : "failed", error,
515                  job->user_data);
516   if (error != NULL)
517     g_error_free (error);
518
519   /* finish the job */
520   boot_manager_service_job_unref (job);
521 }
522
523
524
525 static gboolean
526 boot_manager_service_handle_restart (BootManager           *interface,
527                                      GDBusMethodInvocation *invocation,
528                                      const gchar           *unit,
529                                      BootManagerService    *service)
530 {
531   g_return_val_if_fail (IS_BOOT_MANAGER (interface), FALSE);
532   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE);
533   g_return_val_if_fail (unit != NULL, FALSE);
534   g_return_val_if_fail (BOOT_MANAGER_IS_SERVICE (service), FALSE);
535
536   /* ask systemd to restart the unit for us, send a D-Bus reply in the finish callback */
537   boot_manager_service_restart (service, unit, NULL,
538                                 boot_manager_service_handle_restart_finish, invocation);
539
540   return TRUE;
541 }
542
543
544
545 static void
546 boot_manager_service_handle_restart_finish (BootManagerService *service,
547                                             const gchar        *unit,
548                                             const gchar        *result,
549                                             GError             *error,
550                                             gpointer            user_data)
551 {
552   GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
553
554   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
555   g_return_if_fail (unit != NULL);
556   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
557
558   /* log any potential errors */
559   if (error != NULL)
560     g_warning ("there was an error: %s", error->message);
561
562   /* report the result back to the boot manager client */
563   boot_manager_complete_restart (service->interface, invocation, result);
564 }
565
566
567
568 static void
569 boot_manager_service_restart_unit_reply (GObject      *object,
570                                          GAsyncResult *result,
571                                          gpointer      user_data)
572 {
573   BootManagerServiceJob *job = user_data;
574   GError                *error = NULL;
575   gchar                 *job_name = NULL;
576
577   g_return_if_fail (IS_SYSTEMD_MANAGER (object));
578   g_return_if_fail (G_IS_ASYNC_RESULT (result));
579   g_return_if_fail (user_data != NULL);
580
581   /* finish the restart unit call */
582   if (!systemd_manager_call_restart_unit_finish (job->service->systemd_manager,
583                                                  &job_name, result, &error))
584     {
585       /* there was an error; let the caller know */
586       job->callback (job->service, job->unit, "failed", error, job->user_data);
587       g_error_free (error);
588       g_free (job_name);
589
590       /* finish the job immediately */
591       boot_manager_service_job_unref (job);
592     }
593   else
594     {
595       /* remember the job so that we can finish it in the "job-removed" signal
596        * handler. the service takes ownership of the job so we don't need to
597        * unref it here */
598       boot_manager_service_remember_job (job->service, job_name, job);
599     }
600 }
601
602
603
604 static void
605 boot_manager_service_job_removed (SystemdManager     *manager,
606                                   guint               id,
607                                   const gchar        *job_name,
608                                   const gchar        *result,
609                                   BootManagerService *service)
610 {
611   BootManagerServiceJob *job;
612
613   g_return_if_fail (IS_SYSTEMD_MANAGER (manager));
614   g_return_if_fail (job_name != NULL && *job_name != '\0');
615   g_return_if_fail (result != NULL && *result != '\0');
616   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
617
618   /* lookup the rememebred job for this job name */
619   job = g_hash_table_lookup (service->jobs, job_name);
620
621   /* if there is no such job, just ignore this job-removed signal */
622   if (job == NULL)
623     return;
624
625   /* finish the job by notifying the caller */
626   job->callback (service, job->unit, result, NULL, job->user_data);
627
628   /* forget about this job; this will unref the job */
629   boot_manager_service_forget_job (service, job_name);
630 }
631
632
633
634 static BootManagerServiceJob *
635 boot_manager_service_job_new (BootManagerService        *service,
636                               const gchar               *unit,
637                               GCancellable              *cancellable,
638                               BootManagerServiceCallback callback,
639                               gpointer                   user_data)
640 {
641   BootManagerServiceJob *job;
642
643   g_return_val_if_fail (BOOT_MANAGER_IS_SERVICE (service), NULL);
644   g_return_val_if_fail (unit != NULL, NULL);
645   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
646
647   /* allocate a new job struct */
648   job = g_slice_new0 (BootManagerServiceJob);
649   job->service = g_object_ref (service);
650   job->unit = g_strdup (unit);
651   if (cancellable != NULL)
652     job->cancellable = g_object_ref (cancellable);
653   job->callback = callback;
654   job->user_data = user_data;
655
656   return job;
657 }
658
659
660
661 static void
662 boot_manager_service_job_unref (BootManagerServiceJob *job)
663 {
664   if (job == NULL)
665     return;
666
667   /* release all memory and references held by the job */
668   if (job->cancellable != NULL)
669     g_object_unref (job->cancellable);
670   g_free (job->unit);
671   g_object_unref (job->service);
672   g_slice_free (BootManagerServiceJob, job);
673 }
674
675
676
677 static void
678 boot_manager_service_remember_job (BootManagerService    *service,
679                                    const gchar           *job_name,
680                                    BootManagerServiceJob *job)
681 {
682   BootManagerServiceJob *existing_job;
683
684   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
685   g_return_if_fail (job_name != NULL && *job_name != '\0');
686   g_return_if_fail (job != NULL);
687
688   /* if the job is already being remembered, then there is a programming
689    * mistake and we should make people aware of it */
690   existing_job = g_hash_table_lookup (service->jobs, job_name);
691   if (existing_job != NULL)
692     {
693       g_critical ("trying to remember the same job twice");
694       return;
695     }
696
697   /* associate the job name with the job */
698   g_hash_table_insert (service->jobs, g_strdup (job_name), job);
699 }
700
701
702
703 static void
704 boot_manager_service_forget_job (BootManagerService *service,
705                                  const gchar        *job_name)
706 {
707   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
708   g_return_if_fail (job_name != NULL && *job_name != '\0');
709
710   g_hash_table_remove (service->jobs, job_name);
711 }
712
713
714
715 BootManagerService *
716 boot_manager_service_new (GDBusConnection *connection,
717                           SystemdManager  *systemd_manager)
718 {
719   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
720   g_return_val_if_fail (IS_SYSTEMD_MANAGER (systemd_manager), NULL);
721
722   return g_object_new (BOOT_MANAGER_TYPE_SERVICE,
723                        "connection", connection,
724                        "systemd-manager", systemd_manager,
725                        NULL);
726 }
727
728
729
730 gboolean
731 boot_manager_service_start_up (BootManagerService *service,
732                                GError            **error)
733 {
734   g_return_val_if_fail (BOOT_MANAGER_IS_SERVICE (service), FALSE);
735   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
736
737   /* announce the org.genivi.BootManager1 service on the bus */
738   return g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (service->interface),
739                                            service->connection,
740                                            "/org/genivi/BootManager1",
741                                            error);
742 }
743
744
745
746 void
747 boot_manager_service_start (BootManagerService        *service,
748                             const gchar               *unit,
749                             GCancellable              *cancellable,
750                             BootManagerServiceCallback callback,
751                             gpointer                   user_data)
752 {
753   BootManagerServiceJob *job;
754
755   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
756   g_return_if_fail (unit != NULL);
757   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
758   g_return_if_fail (callback != NULL);
759
760   /* create a new job object */
761   job = boot_manager_service_job_new (service, unit, cancellable, callback, user_data);
762
763   /* ask systemd to start the unit asynchronously */
764   systemd_manager_call_start_unit (service->systemd_manager, unit, "fail", cancellable,
765                                    boot_manager_service_start_unit_reply, job);
766 }
767
768
769
770 void
771 boot_manager_service_stop (BootManagerService        *service,
772                            const gchar               *unit,
773                            GCancellable              *cancellable,
774                            BootManagerServiceCallback callback,
775                            gpointer                   user_data)
776 {
777   BootManagerServiceJob *job;
778
779   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
780   g_return_if_fail (unit != NULL);
781   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
782   g_return_if_fail (callback != NULL);
783
784   /* create a new job object */
785   job = boot_manager_service_job_new (service, unit, cancellable, callback, user_data);
786
787   /* ask systemd to stop the unit asynchronously */
788   systemd_manager_call_stop_unit (service->systemd_manager, unit, "fail", cancellable,
789                                   boot_manager_service_stop_unit_reply, job);
790 }
791
792
793
794 void
795 boot_manager_service_kill (BootManagerService        *service,
796                            const gchar               *unit,
797                            GCancellable              *cancellable,
798                            BootManagerServiceCallback callback,
799                            gpointer                   user_data)
800 {
801   BootManagerServiceJob *job;
802
803   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
804   g_return_if_fail (unit != NULL);
805   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
806   g_return_if_fail (callback != NULL);
807
808   /* create a new job object */
809   job = boot_manager_service_job_new (service, unit, cancellable, callback, user_data);
810
811   /* ask systemd to stop the unit asynchronously */
812   systemd_manager_call_kill_unit (service->systemd_manager, unit, "all", "control-group",
813                                   SIGKILL, cancellable,
814                                   boot_manager_service_kill_unit_reply, job);
815 }
816
817
818
819 void
820 boot_manager_service_restart (BootManagerService        *service,
821                               const gchar               *unit,
822                               GCancellable              *cancellable,
823                               BootManagerServiceCallback callback,
824                               gpointer                   user_data)
825 {
826   BootManagerServiceJob *job;
827
828   g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
829   g_return_if_fail (unit != NULL);
830   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
831   g_return_if_fail (callback != NULL);
832
833   /* create a new job object */
834   job = boot_manager_service_job_new (service, unit, cancellable, callback, user_data);
835
836   /* ask systemd to restart the unit asynchronously */
837   systemd_manager_call_restart_unit (service->systemd_manager, unit, "fail", cancellable,
838                                      boot_manager_service_restart_unit_reply, job);
839 }