Branch data Line data Source code
1 : : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 : : *
3 : : * Copyright © 2017, 2018 Endless Mobile, Inc.
4 : : *
5 : : * This library is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU Lesser General Public
7 : : * License as published by the Free Software Foundation; either
8 : : * version 2.1 of the License, or (at your option) any later version.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Lesser General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public
16 : : * License along with this library; if not, write to the Free Software
17 : : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 : : *
19 : : * Authors:
20 : : * - Philip Withnall <withnall@endlessm.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : :
25 : : #include <glib.h>
26 : : #include <glib-object.h>
27 : : #include <glib-unix.h>
28 : : #include <glib/gi18n-lib.h>
29 : : #include <gio/gio.h>
30 : : #include <libmogwai-schedule/clock-system.h>
31 : : #include <libmogwai-schedule/connection-monitor-nm.h>
32 : : #include <libmogwai-schedule/peer-manager-dbus.h>
33 : : #include <libmogwai-schedule/schedule-service.h>
34 : : #include <libmogwai-schedule/scheduler.h>
35 : : #include <libmogwai-schedule/service.h>
36 : : #include <locale.h>
37 : :
38 : :
39 : : static void mws_service_dispose (GObject *object);
40 : :
41 : : static void mws_service_startup_async (GssService *service,
42 : : GCancellable *cancellable,
43 : : GAsyncReadyCallback callback,
44 : : gpointer user_data);
45 : : static void mws_service_startup_finish (GssService *service,
46 : : GAsyncResult *result,
47 : : GError **error);
48 : : static void mws_service_shutdown (GssService *service);
49 : :
50 : : static void notify_busy_cb (GObject *obj,
51 : : GParamSpec *pspec,
52 : : gpointer user_data);
53 : :
54 : : /**
55 : : * MwsService:
56 : : *
57 : : * The core implementation of the scheduling daemon, which exposes its D-Bus
58 : : * API on the bus.
59 : : *
60 : : * Since: 0.1.0
61 : : */
62 : : struct _MwsService
63 : : {
64 : : GssService parent;
65 : :
66 : : MwsScheduler *scheduler; /* (owned) */
67 : : MwsScheduleService *schedule_service; /* (owned) */
68 : :
69 : : GCancellable *cancellable; /* (owned) */
70 : :
71 : : gboolean busy;
72 : : };
73 : :
74 [ + + + - : 8 : G_DEFINE_TYPE (MwsService, mws_service, GSS_TYPE_SERVICE)
+ + ]
75 : :
76 : : static void
77 : 2 : mws_service_class_init (MwsServiceClass *klass)
78 : : {
79 : 2 : GObjectClass *object_class = (GObjectClass *) klass;
80 : 2 : GssServiceClass *service_class = (GssServiceClass *) klass;
81 : :
82 : 2 : object_class->dispose = mws_service_dispose;
83 : :
84 : 2 : service_class->startup_async = mws_service_startup_async;
85 : 2 : service_class->startup_finish = mws_service_startup_finish;
86 : 2 : service_class->shutdown = mws_service_shutdown;
87 : 2 : }
88 : :
89 : : static void
90 : 2 : mws_service_init (MwsService *self)
91 : : {
92 : : /* A cancellable to allow pending asynchronous operations to be cancelled when
93 : : * shutdown() is called. */
94 : 2 : self->cancellable = g_cancellable_new ();
95 : 2 : }
96 : :
97 : : static void
98 : 2 : mws_service_dispose (GObject *object)
99 : : {
100 : 2 : MwsService *self = MWS_SERVICE (object);
101 : :
102 : 2 : g_cancellable_cancel (self->cancellable);
103 [ + - ]: 2 : g_clear_object (&self->cancellable);
104 : :
105 [ - + ]: 2 : if (self->schedule_service != NULL)
106 : 0 : g_signal_handlers_disconnect_by_func (self->schedule_service, notify_busy_cb, self);
107 : :
108 [ - + ]: 2 : g_clear_object (&self->schedule_service);
109 [ - + ]: 2 : g_clear_object (&self->scheduler);
110 : :
111 : : /* Chain up to the parent class */
112 : 2 : G_OBJECT_CLASS (mws_service_parent_class)->dispose (object);
113 : 2 : }
114 : :
115 : : static void connection_monitor_new_cb (GObject *source_object,
116 : : GAsyncResult *result,
117 : : gpointer user_data);
118 : :
119 : : static void
120 : 0 : mws_service_startup_async (GssService *service,
121 : : GCancellable *cancellable,
122 : : GAsyncReadyCallback callback,
123 : : gpointer user_data)
124 : : {
125 : 0 : g_autoptr(GTask) task = g_task_new (service, cancellable, callback, user_data);
126 [ # # ]: 0 : g_task_set_source_tag (task, mws_service_startup_async);
127 : :
128 : : /* Get a connection monitor first. */
129 : 0 : mws_connection_monitor_nm_new_async (cancellable, connection_monitor_new_cb,
130 : : g_steal_pointer (&task));
131 : 0 : }
132 : :
133 : : static void
134 : 0 : connection_monitor_new_cb (GObject *source_object,
135 : : GAsyncResult *result,
136 : : gpointer user_data)
137 : : {
138 [ # # ]: 0 : g_autoptr(GTask) task = G_TASK (user_data);
139 : 0 : MwsService *self = MWS_SERVICE (g_task_get_source_object (task));
140 [ # # ]: 0 : g_autoptr(GError) local_error = NULL;
141 : :
142 [ # # ]: 0 : g_autoptr(MwsConnectionMonitor) connection_monitor = NULL;
143 : 0 : connection_monitor = MWS_CONNECTION_MONITOR (mws_connection_monitor_nm_new_finish (result, &local_error));
144 [ # # ]: 0 : if (local_error != NULL)
145 : : {
146 : 0 : g_task_return_error (task, g_steal_pointer (&local_error));
147 : 0 : return;
148 : : }
149 : :
150 : 0 : GDBusConnection *connection = gss_service_get_dbus_connection (GSS_SERVICE (self));
151 : :
152 : 0 : g_autoptr(MwsPeerManager) peer_manager = NULL;
153 : 0 : peer_manager = MWS_PEER_MANAGER (mws_peer_manager_dbus_new (connection));
154 : :
155 : 0 : g_autoptr(MwsClock) clock = MWS_CLOCK (mws_clock_system_new ());
156 : :
157 : 0 : self->scheduler = mws_scheduler_new (connection_monitor, peer_manager, clock);
158 : 0 : self->schedule_service = mws_schedule_service_new (connection,
159 : : "/com/endlessm/DownloadManager1",
160 : : self->scheduler);
161 : 0 : g_signal_connect (self->schedule_service, "notify::busy",
162 : : (GCallback) notify_busy_cb, self);
163 : 0 : notify_busy_cb (G_OBJECT (self->schedule_service), NULL, self);
164 : :
165 [ # # ]: 0 : if (!mws_schedule_service_register (self->schedule_service, &local_error))
166 : 0 : g_task_return_error (task, g_steal_pointer (&local_error));
167 : : else
168 : 0 : g_task_return_boolean (task, TRUE);
169 : : }
170 : :
171 : : static void
172 : 0 : mws_service_startup_finish (GssService *service,
173 : : GAsyncResult *result,
174 : : GError **error)
175 : : {
176 : 0 : g_task_propagate_boolean (G_TASK (result), error);
177 : 0 : }
178 : :
179 : : static void
180 : 0 : notify_busy_cb (GObject *obj,
181 : : GParamSpec *pspec,
182 : : gpointer user_data)
183 : : {
184 : 0 : MwsService *self = MWS_SERVICE (user_data);
185 : :
186 : 0 : gboolean was_busy = self->busy;
187 : 0 : gboolean now_busy = mws_schedule_service_get_busy (self->schedule_service);
188 : :
189 [ # # # # ]: 0 : g_debug ("%s: was_busy: %s, now_busy: %s",
190 : : G_STRFUNC, was_busy ? "yes" : "no", now_busy ? "yes" : "no");
191 : :
192 [ # # # # ]: 0 : if (was_busy && !now_busy)
193 : 0 : gss_service_release (GSS_SERVICE (self));
194 [ # # # # ]: 0 : else if (!was_busy && now_busy)
195 : 0 : gss_service_hold (GSS_SERVICE (self));
196 : :
197 : 0 : self->busy = now_busy;
198 : 0 : }
199 : :
200 : : static void
201 : 0 : mws_service_shutdown (GssService *service)
202 : : {
203 : 0 : MwsService *self = MWS_SERVICE (service);
204 : :
205 : 0 : g_cancellable_cancel (self->cancellable);
206 : 0 : mws_schedule_service_unregister (self->schedule_service);
207 : 0 : }
208 : :
209 : : /**
210 : : * mws_service_new:
211 : : *
212 : : * Create a new #MwsService.
213 : : *
214 : : * Returns: (transfer full): a new #MwsService
215 : : * Since: 0.1.0
216 : : */
217 : : MwsService *
218 : 2 : mws_service_new (void)
219 : : {
220 : 2 : return g_object_new (MWS_TYPE_SERVICE,
221 : : "bus-type", G_BUS_TYPE_SYSTEM,
222 : : "service-id", "com.endlessm.MogwaiSchedule1",
223 : : "inactivity-timeout", 30000 /* ms */,
224 : : "translation-domain", GETTEXT_PACKAGE,
225 : 2 : "parameter-string", _("— schedule downloads to conserve bandwidth"),
226 : 2 : "summary", _("Schedule large downloads from multiple "
227 : : "system processes to conserve bandwidth "
228 : : "and avoid unnecessary use of metered "
229 : : "data."),
230 : : NULL);
231 : : }
232 : :
|