Drop GApplication, fix D-Bus activation, further NSM integration work
[profile/ivi/node-startup-controller.git] / boot-manager / boot-manager-application.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 #include <glib-unix.h>
17
18 #include <systemd/sd-daemon.h>
19
20 #include <dlt/dlt.h>
21
22 #include <common/watchdog-client.h>
23
24 #include <boot-manager/boot-manager-application.h>
25 #include <boot-manager/boot-manager-service.h>
26 #include <boot-manager/job-manager.h>
27 #include <boot-manager/la-handler-service.h>
28 #include <boot-manager/luc-starter.h>
29
30
31
32
33 DLT_IMPORT_CONTEXT (boot_manager_context);
34
35
36
37 /* property identifiers */
38 enum
39 {
40   PROP_0,
41   PROP_CONNECTION,
42   PROP_JOB_MANAGER,
43   PROP_BOOT_MANAGER_SERVICE,
44   PROP_LUC_STARTER,
45   PROP_LA_HANDLER,
46   PROP_MAIN_LOOP,
47 };
48
49
50
51 static void     boot_manager_application_finalize       (GObject                *object);
52 static void     boot_manager_application_constructed    (GObject                *object);
53 static void     boot_manager_application_get_property   (GObject                *object,
54                                                          guint                   prop_id,
55                                                          GValue                 *value,
56                                                          GParamSpec             *pspec);
57 static void     boot_manager_application_set_property   (GObject                *object,
58                                                          guint                   prop_id,
59                                                          const GValue           *value,
60                                                          GParamSpec             *pspec);
61 static gboolean boot_manager_application_sigint_handler (BootManagerApplication *application);
62
63
64
65 struct _BootManagerApplicationClass
66 {
67   GObjectClass __parent__;
68 };
69
70 struct _BootManagerApplication
71 {
72   GObject             __parent__;
73
74   /* the connection to D-Bus */
75   GDBusConnection    *connection;
76
77   /* systemd watchdog client that repeatedly asks systemd to update
78    * the watchdog timestamp */
79   WatchdogClient     *watchdog_client;
80
81   /* internal handler of Start() and Stop() jobs */
82   JobManager         *job_manager;
83
84   /* boot manager service */
85   BootManagerService *boot_manager_service;
86
87   /* LUC starter to restore the LUC */
88   LUCStarter         *luc_starter;
89
90   /* signal handler IDs */
91   guint               sigint_id;
92
93   /* Legacy App Handler to register apps with the Node State Manager */
94   LAHandlerService   *la_handler;
95
96   /* the application's main loop */
97   GMainLoop          *main_loop;
98
99   /* Identifier for the registered bus name */
100   guint               bus_name_id;
101 };
102
103
104
105 G_DEFINE_TYPE (BootManagerApplication, boot_manager_application, G_TYPE_OBJECT);
106
107
108
109 static void
110 boot_manager_application_class_init (BootManagerApplicationClass *klass)
111 {
112   GObjectClass *gobject_class;
113
114   gobject_class = G_OBJECT_CLASS (klass);
115   gobject_class->finalize = boot_manager_application_finalize;
116   gobject_class->constructed = boot_manager_application_constructed;
117   gobject_class->get_property = boot_manager_application_get_property;
118   gobject_class->set_property = boot_manager_application_set_property;
119
120   g_object_class_install_property (gobject_class,
121                                    PROP_CONNECTION,
122                                    g_param_spec_object ("connection",
123                                                         "D-Bus Connection",
124                                                         "The connection to D-Bus",
125                                                         G_TYPE_DBUS_CONNECTION,
126                                                         G_PARAM_READWRITE |
127                                                         G_PARAM_CONSTRUCT_ONLY |
128                                                         G_PARAM_STATIC_STRINGS));
129
130   g_object_class_install_property (gobject_class,
131                                    PROP_JOB_MANAGER,
132                                    g_param_spec_object ("job-manager",
133                                                         "Job Manager",
134                                                         "The internal handler of Start()"
135                                                         " and Stop() jobs",
136                                                         TYPE_JOB_MANAGER,
137                                                         G_PARAM_READWRITE |
138                                                         G_PARAM_CONSTRUCT_ONLY |
139                                                         G_PARAM_STATIC_STRINGS));
140
141   g_object_class_install_property (gobject_class,
142                                    PROP_LA_HANDLER,
143                                    g_param_spec_object ("la-handler",
144                                                         "LA Handler",
145                                                         "Legacy Application Handler",
146                                                         LA_HANDLER_TYPE_SERVICE,
147                                                         G_PARAM_READWRITE |
148                                                         G_PARAM_CONSTRUCT_ONLY |
149                                                         G_PARAM_STATIC_STRINGS));
150
151   g_object_class_install_property (gobject_class,
152                                    PROP_BOOT_MANAGER_SERVICE,
153                                    g_param_spec_object ("boot-manager-service",
154                                                         "boot-manager-service",
155                                                         "boot-manager-service",
156                                                         BOOT_MANAGER_TYPE_SERVICE,
157                                                         G_PARAM_READWRITE |
158                                                         G_PARAM_CONSTRUCT_ONLY |
159                                                         G_PARAM_STATIC_STRINGS));
160
161   g_object_class_install_property (gobject_class,
162                                    PROP_LUC_STARTER,
163                                    g_param_spec_object ("luc-starter",
164                                                         "luc-starter",
165                                                         "luc-starter",
166                                                         TYPE_LUC_STARTER,
167                                                         G_PARAM_READABLE |
168                                                         G_PARAM_STATIC_STRINGS));
169
170   g_object_class_install_property (gobject_class,
171                                    PROP_MAIN_LOOP,
172                                    g_param_spec_boxed ("main-loop",
173                                                        "main-loop",
174                                                        "main-loop",
175                                                        G_TYPE_MAIN_LOOP,
176                                                        G_PARAM_READWRITE |
177                                                        G_PARAM_CONSTRUCT_ONLY |
178                                                        G_PARAM_STATIC_STRINGS));
179 }
180
181
182
183 static void
184 boot_manager_application_init (BootManagerApplication *application)
185 {
186   /* update systemd's watchdog timestamp every 120 seconds */
187   application->watchdog_client = watchdog_client_new (120);
188
189   /* install the signal handler */
190   application->sigint_id =
191     g_unix_signal_add (SIGINT, (GSourceFunc) boot_manager_application_sigint_handler,
192                        application);
193 }
194
195
196
197 static void
198 boot_manager_application_finalize (GObject *object)
199 {
200   BootManagerApplication *application = BOOT_MANAGER_APPLICATION (object);
201
202   /* release the bus name */
203   g_bus_unown_name (application->bus_name_id);
204
205   /* release the D-Bus connection object */
206   if (application->connection != NULL)
207     g_object_unref (application->connection);
208
209   /* release the signal handler */
210   g_source_remove (application->sigint_id);
211
212   /* release the watchdog client */
213   g_object_unref (application->watchdog_client);
214
215   /* release the boot manager */
216   g_object_unref (application->boot_manager_service);
217
218   /* release the LUC starter */
219   g_object_unref (application->luc_starter);
220
221   /* release the legacy app handler */
222   g_object_unref (application->la_handler);
223
224   /* release the job manager */
225   g_object_unref (application->job_manager);
226
227   /* release the main loop */
228   g_main_loop_unref (application->main_loop);
229
230   (*G_OBJECT_CLASS (boot_manager_application_parent_class)->finalize) (object);
231 }
232
233
234
235 static void
236 boot_manager_application_constructed (GObject *object)
237 {
238   BootManagerApplication *application = BOOT_MANAGER_APPLICATION (object);
239   GError                 *error = NULL;
240   gchar                  *log_text;
241
242   /* get a bus name on the given connection */
243   application->bus_name_id =
244     g_bus_own_name_on_connection (application->connection, "org.genivi.BootManager1",
245                                   G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL);
246
247   /* instantiate the LUC starter */
248   application->luc_starter = luc_starter_new (application->job_manager,
249                                               application->boot_manager_service);
250
251   /* attempt to start the boot manager service */
252   if (!boot_manager_service_start_up (application->boot_manager_service, &error))
253     {
254       log_text = g_strdup_printf ("Failed to start the boot manager service: %s",
255                                   error->message);
256       DLT_LOG (boot_manager_context, DLT_LOG_ERROR, DLT_STRING (log_text));
257       g_free (log_text);
258     }
259
260   /* restore the LUC if desired */
261   luc_starter_start_groups (application->luc_starter);
262
263   /* start the legacy app handler */
264   if (!la_handler_service_start (application->la_handler, &error))
265     {
266       log_text = g_strdup_printf ("Failed to start the legacy app handler service: %s",
267                                   error->message);
268       DLT_LOG (boot_manager_context, DLT_LOG_ERROR, DLT_STRING (log_text));
269       g_free (log_text);
270     }
271
272   /* inform systemd that this process has started */
273   sd_notify (0, "READY=1");
274 }
275
276
277
278 static void
279 boot_manager_application_get_property (GObject    *object,
280                                        guint       prop_id,
281                                        GValue     *value,
282                                        GParamSpec *pspec)
283 {
284   BootManagerApplication *application = BOOT_MANAGER_APPLICATION (object);
285
286   switch (prop_id)
287     {
288     case PROP_CONNECTION:
289       g_value_set_object (value, application->connection);
290       break;
291     case PROP_JOB_MANAGER:
292       g_value_set_object (value, application->job_manager);
293       break;
294     case PROP_BOOT_MANAGER_SERVICE:
295       g_value_set_object (value, application->boot_manager_service);
296     case PROP_LA_HANDLER:
297       g_value_set_object (value, application->la_handler);
298       break;
299     case PROP_LUC_STARTER:
300       g_value_set_object (value, application->luc_starter);
301       break;
302     case PROP_MAIN_LOOP:
303       g_value_set_boxed (value, application->main_loop);
304       break;
305     default:
306       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
307       break;
308     }
309 }
310
311
312
313 static void
314 boot_manager_application_set_property (GObject      *object,
315                                        guint         prop_id,
316                                        const GValue *value,
317                                        GParamSpec   *pspec)
318 {
319   BootManagerApplication *application = BOOT_MANAGER_APPLICATION (object);
320
321   switch (prop_id)
322     {
323     case PROP_CONNECTION:
324       application->connection = g_value_dup_object (value);
325       break;
326     case PROP_JOB_MANAGER:
327       application->job_manager = g_value_dup_object (value);
328       break;
329     case PROP_BOOT_MANAGER_SERVICE:
330       application->boot_manager_service = g_value_dup_object (value);
331       break;
332     case PROP_LA_HANDLER:
333       application->la_handler = g_value_dup_object (value);
334       break;
335     case PROP_MAIN_LOOP:
336       application->main_loop = g_main_loop_ref (g_value_get_boxed (value));
337       break;
338     default:
339       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
340       break;
341     }
342 }
343
344
345
346 static gboolean
347 boot_manager_application_sigint_handler (BootManagerApplication *application)
348 {
349   /* cancel the LUC startup */
350   luc_starter_cancel (application->luc_starter);
351
352   /* quit the application */
353   g_main_loop_quit (application->main_loop);
354
355   return FALSE;
356 }
357
358
359
360 BootManagerApplication *
361 boot_manager_application_new (GMainLoop          *main_loop,
362                               GDBusConnection    *connection,
363                               JobManager         *job_manager,
364                               LAHandlerService   *la_handler,
365                               BootManagerService *boot_manager_service)
366 {
367   g_return_val_if_fail (main_loop != NULL, NULL);
368   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
369   g_return_val_if_fail (IS_JOB_MANAGER (job_manager), NULL);
370   g_return_val_if_fail (LA_HANDLER_IS_SERVICE (la_handler), NULL);
371   g_return_val_if_fail (BOOT_MANAGER_IS_SERVICE (boot_manager_service), NULL);
372
373   return g_object_new (BOOT_MANAGER_TYPE_APPLICATION,
374                        "connection", connection,
375                        "boot-manager-service", boot_manager_service,
376                        "job-manager", job_manager,
377                        "la-handler", la_handler,
378                        "main-loop", main_loop,
379                        NULL);
380 }