Merge lp:~thomas-voss/location-service/robustify-event-propagation-in-case-of-multiple-providers-running into lp:location-service/15.04
- robustify-event-propagation-in-case-of-multiple-providers-running
- Merge into 15.04
Status: | Needs review |
---|---|
Proposed branch: | lp:~thomas-voss/location-service/robustify-event-propagation-in-case-of-multiple-providers-running |
Merge into: | lp:location-service/15.04 |
Diff against target: |
671 lines (+513/-51) 5 files modified
src/location_service/com/ubuntu/location/CMakeLists.txt (+1/-0) src/location_service/com/ubuntu/location/dispatching_provider.cpp (+325/-0) src/location_service/com/ubuntu/location/dispatching_provider.h (+90/-0) src/location_service/com/ubuntu/location/service/daemon.cpp (+91/-41) tests/acceptance_tests.cpp (+6/-10) |
To merge this branch: | bzr merge lp:~thomas-voss/location-service/robustify-event-propagation-in-case-of-multiple-providers-running |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alberto Mardegan (community) | Approve | ||
Loïc Minier | Pending | ||
PS Jenkins bot | continuous-integration | Pending | |
Review via email: mp+277789@code.launchpad.net |
This proposal supersedes a proposal from 2014-10-16.
Commit message
Introduce a dispatching provider that leverages a functor to hand over updates and invocations to/from providers.
Adjust acceptance tests to account for multiple providers.
Description of the change
Introduce a dispatching provider that leverages a functor to hand over updates and invocations to/from providers.
Adjust acceptance tests to account for multiple providers.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:130
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Loïc Minier (lool) wrote : Posted in a previous version of this proposal | # |
LGTM
- 131. By Thomas Voß
-
[ Alberto Mardegan ]
* Make sure that injected time is given in milliseconds
[ Thomas Voß ]
* Cherry-pick rev. 196 and 199 from lp:location-service. The changes
got accidentally removed by merging the outstanding documentation
branch.
* Handle responses of clients to updates asynchronously. Rely on
dummy::ConnectivityMa nager as harvesting is disabled anyway. (LP:
#1462664, #1387643)
[ Thomas Voß ]
* Add documentation for debugging, hacking and debugging the location
service. Pull manual testing instructions over from the wiki. Add
tools for formatting the source.
[ thomas-voss ]
* Add documentation for debugging, hacking and debugging the location
service. Pull manual testing instructions over from the wiki. Add
tools for formatting the source.
[ CI Train Bot ]
* New rebuild forced.
[ Manuel de la Pena ]
* Make sure that cached modems are considered as well when calculating
connection characteristics.
[ CI Train Bot ]
* New rebuild forced.
[ Manuel de la Pena ]
* Improve the selection of the bag of providers to ensure that the
locations used are within a reasonable time margin.
* Remove the pimpl implementation from the providers and hide their
public headers because they should only be used within the project.
[ Thomas Voß ]
* Increase default timeout for downloading gps xtra data. (LP:
#1447161)
[ CI Train Bot ]
* New rebuild forced.
[ Manuel de la Pena ]
* If an exception is thrown from the io_executor run method it must be
caught, logger and continued with the main loop.
[ CI Train Bot ]
* Launchpad automatic translations update. added: po/af.po po/bg.po
po/sk.po
* New rebuild forced.
[ thomas-voss ]
* Account for dbus interface breakage in NM from 0.9.8.8 -> 0.9.10.0.
[ thomas-voss ]
* Automatically clean up session store for dead clients. (LP:
#1418033)
[ thomas-voss ]
* Make the remote::Provider: :Stub fail loudly on construction if the
other side is not reachable. Relax the exception in
location::Daemon: :main and do not exit if instantiating a provider
fails. (LP: #1414591)
[ CI Train Bot ]
* Resync trunk
[ thomas-voss ]
* Add an interface for querying settings by key. Add an implementation
leveraging boost::property_ tree to provide settings. (LP: #1362765)
* Allow for enabling/disabling providers. Wire up engine state changes
to enabling/disabling of providers. (LP: #1392399)
[ thomas-voss ]
* Print details about visible space vehicles to the gps provider test
case. (LP: #1408984)
[ thomas-voss ]
* Fix #1394204 by: (LP: #1394204)
[ Ubuntu daily release ]
* New rebuild forced
[ thomas-voss ]
* Make sure that devices being added/removed by NetworkManager are
handled correctly. (LP: #1390490)
[ CI bot ]
* Resync trunk
[ Kevin DuBois ]
* The headers shipped in libubuntu-location- service- dev contain
includes that are provided in the libboost-dev package (specifically
headers like boost/units/cmath.hpp) . Make the dev package depend on
libboost-dev so the downstreams get what they need to compile
against the libubuntu-location- service- dev headers
* New rebuild forced
[ thomas-voss ]
* Bump build dependency.
* Disconnect event connections for bag of providers. (LP: #1387572)
[ thomas-voss ]
* Prevent multiple invocations of start positioning on android GPS HAL
to prevent buggy HAL implementations from blocking. Allow for
decorated provider names to enable moving providers OOP. (LP:
#1382501) - 132. By Thomas Voß
-
Revert accidental change to debian/
source/ format.
Alberto Mardegan (mardy) wrote : | # |
The code looks good to me, but I feel that this makes the logic even more complicated.
I would much rather force all providers to be out of process. This would lead to a simpler design, and might also make it possible to free some memory when the GPS is not in use.
I'm approving this because code-wise it's fine, but if it were for me, I would not merge it.
- 133. By Thomas Voß
-
Explicitly stop bus instances on shut down.
Michał Karnicki (karni) wrote : | # |
Was browsing this out of curiosity and to learn. Tiny comment - the license headers should probably contain 2015?
Unmerged revisions
- 133. By Thomas Voß
-
Explicitly stop bus instances on shut down.
Preview Diff
1 | === modified file 'src/location_service/com/ubuntu/location/CMakeLists.txt' |
2 | --- src/location_service/com/ubuntu/location/CMakeLists.txt 2015-04-23 14:48:44 +0000 |
3 | +++ src/location_service/com/ubuntu/location/CMakeLists.txt 2015-11-25 08:29:55 +0000 |
4 | @@ -19,6 +19,7 @@ |
5 | non_selecting_provider_selection_policy.cpp |
6 | |
7 | criteria.cpp |
8 | + dispatching_provider.cpp |
9 | engine.cpp |
10 | init_and_shutdown.cpp |
11 | position.cpp |
12 | |
13 | === added file 'src/location_service/com/ubuntu/location/dispatching_provider.cpp' |
14 | --- src/location_service/com/ubuntu/location/dispatching_provider.cpp 1970-01-01 00:00:00 +0000 |
15 | +++ src/location_service/com/ubuntu/location/dispatching_provider.cpp 2015-11-25 08:29:55 +0000 |
16 | @@ -0,0 +1,325 @@ |
17 | +/* |
18 | + * Copyright © 2014 Canonical Ltd. |
19 | + * |
20 | + * This program is free software: you can redistribute it and/or modify it |
21 | + * under the terms of the GNU Lesser General Public License version 3, |
22 | + * as published by the Free Software Foundation. |
23 | + * |
24 | + * This program is distributed in the hope that it will be useful, |
25 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
26 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
27 | + * GNU Lesser General Public License for more details. |
28 | + * |
29 | + * You should have received a copy of the GNU Lesser General Public License |
30 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
31 | + * |
32 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
33 | + */ |
34 | + |
35 | +#include <com/ubuntu/location/dispatching_provider.h> |
36 | + |
37 | +#include <com/ubuntu/location/logging.h> |
38 | + |
39 | +#include <future> |
40 | + |
41 | +namespace location = com::ubuntu::location; |
42 | + |
43 | +location::DispatchingProvider::Ptr location::DispatchingProvider::create( |
44 | + const location::DispatchingProvider::Dispatcher& dispatcher, |
45 | + const location::Provider::Ptr& fwd) |
46 | +{ |
47 | + std::shared_ptr<location::DispatchingProvider> sp |
48 | + { |
49 | + new location::DispatchingProvider{dispatcher, fwd} |
50 | + }; |
51 | + return sp->init(); |
52 | +} |
53 | + |
54 | +location::DispatchingProvider::DispatchingProvider(const location::DispatchingProvider::Dispatcher& dispatcher, const location::Provider::Ptr& fwd) |
55 | + : dispatcher{dispatcher}, |
56 | + fwd{fwd} |
57 | +{ |
58 | + if (not dispatcher) throw std::logic_error |
59 | + { |
60 | + "com::ubuntu::location::DispatchingProvider: Cannot operate without valid dispatcher" |
61 | + }; |
62 | + |
63 | + if (not fwd) throw std::logic_error |
64 | + { |
65 | + "com::ubuntu::location::DispatchingProvider: Cannot operate without valid Provider" |
66 | + }; |
67 | +} |
68 | + |
69 | +location::DispatchingProvider::~DispatchingProvider() |
70 | +{ |
71 | +} |
72 | + |
73 | +bool location::DispatchingProvider::supports(const location::Provider::Features& f) const |
74 | +{ |
75 | + std::promise<bool> promise; |
76 | + std::future<bool> future = promise.get_future(); |
77 | + |
78 | + dispatcher([&]() |
79 | + { |
80 | + try |
81 | + { |
82 | + promise.set_value(fwd->supports(f)); |
83 | + } catch(const std::exception& e) |
84 | + { |
85 | + LOG(WARNING) << e.what(); |
86 | + promise.set_exception(std::current_exception()); |
87 | + } catch(...) |
88 | + { |
89 | + promise.set_exception(std::current_exception()); |
90 | + } |
91 | + }); |
92 | + |
93 | + return future.get(); |
94 | +} |
95 | + |
96 | +bool location::DispatchingProvider::requires(const location::Provider::Requirements& r) const |
97 | +{ |
98 | + std::promise<bool> promise; |
99 | + std::future<bool> future = promise.get_future(); |
100 | + |
101 | + dispatcher([&]() |
102 | + { |
103 | + try |
104 | + { |
105 | + promise.set_value(fwd->requires(r)); |
106 | + } catch(const std::exception& e) |
107 | + { |
108 | + LOG(WARNING) << e.what(); |
109 | + promise.set_exception(std::current_exception()); |
110 | + } catch(...) |
111 | + { |
112 | + promise.set_exception(std::current_exception()); |
113 | + } |
114 | + }); |
115 | + |
116 | + return future.get(); |
117 | +} |
118 | + |
119 | +bool location::DispatchingProvider::matches_criteria(const location::Criteria& criteria) |
120 | +{ |
121 | + std::promise<bool> promise; |
122 | + std::future<bool> future = promise.get_future(); |
123 | + |
124 | + dispatcher([&]() |
125 | + { |
126 | + try |
127 | + { |
128 | + promise.set_value(fwd->matches_criteria(criteria)); |
129 | + } catch(const std::exception& e) |
130 | + { |
131 | + LOG(WARNING) << e.what(); |
132 | + promise.set_exception(std::current_exception()); |
133 | + } catch(...) |
134 | + { |
135 | + promise.set_exception(std::current_exception()); |
136 | + } |
137 | + }); |
138 | + |
139 | + return future.get(); |
140 | +} |
141 | + |
142 | +// We forward all events to the other providers. |
143 | +void location::DispatchingProvider::on_wifi_and_cell_reporting_state_changed(location::WifiAndCellIdReportingState state) |
144 | +{ |
145 | + std::weak_ptr<location::DispatchingProvider> wp{shared_from_this()}; |
146 | + dispatcher([wp, state]() |
147 | + { |
148 | + auto sp = wp.lock(); |
149 | + |
150 | + if (not sp) |
151 | + return; |
152 | + |
153 | + sp->fwd->on_wifi_and_cell_reporting_state_changed(state); |
154 | + }); |
155 | +} |
156 | + |
157 | +void location::DispatchingProvider::on_reference_location_updated(const location::Update<location::Position>& position) |
158 | +{ |
159 | + std::weak_ptr<location::DispatchingProvider> wp{shared_from_this()}; |
160 | + dispatcher([wp, position]() |
161 | + { |
162 | + auto sp = wp.lock(); |
163 | + |
164 | + if (not sp) |
165 | + return; |
166 | + |
167 | + sp->fwd->on_reference_location_updated(position); |
168 | + }); |
169 | +} |
170 | + |
171 | +void location::DispatchingProvider::on_reference_velocity_updated(const location::Update<location::Velocity>& velocity) |
172 | +{ |
173 | + std::weak_ptr<location::DispatchingProvider> wp{shared_from_this()}; |
174 | + dispatcher([wp, velocity]() |
175 | + { |
176 | + auto sp = wp.lock(); |
177 | + |
178 | + if (not sp) |
179 | + return; |
180 | + |
181 | + sp->fwd->on_reference_velocity_updated(velocity); |
182 | + }); |
183 | +} |
184 | + |
185 | +void location::DispatchingProvider::on_reference_heading_updated(const location::Update<location::Heading>& heading) |
186 | +{ |
187 | + std::weak_ptr<location::DispatchingProvider> wp{shared_from_this()}; |
188 | + dispatcher([wp, heading]() |
189 | + { |
190 | + auto sp = wp.lock(); |
191 | + |
192 | + if (not sp) |
193 | + sp->fwd->on_reference_heading_updated(heading); |
194 | + }); |
195 | +} |
196 | + |
197 | +// As well as the respective state change requests. |
198 | +void location::DispatchingProvider::start_position_updates() |
199 | +{ |
200 | + std::weak_ptr<location::DispatchingProvider> wp{shared_from_this()}; |
201 | + dispatcher([wp]() |
202 | + { |
203 | + auto sp = wp.lock(); |
204 | + |
205 | + if (not sp) |
206 | + return; |
207 | + |
208 | + sp->fwd->state_controller()->start_position_updates(); |
209 | + }); |
210 | +} |
211 | + |
212 | +void location::DispatchingProvider::stop_position_updates() |
213 | +{ |
214 | + std::weak_ptr<location::DispatchingProvider> wp{shared_from_this()}; |
215 | + dispatcher([wp]() |
216 | + { |
217 | + auto sp = wp.lock(); |
218 | + |
219 | + if (not sp) |
220 | + return; |
221 | + |
222 | + sp->fwd->state_controller()->stop_position_updates(); |
223 | + }); |
224 | +} |
225 | + |
226 | +void location::DispatchingProvider::start_heading_updates() |
227 | +{ |
228 | + std::weak_ptr<location::DispatchingProvider> wp{shared_from_this()}; |
229 | + dispatcher([wp]() |
230 | + { |
231 | + auto sp = wp.lock(); |
232 | + |
233 | + if (not sp) |
234 | + return; |
235 | + |
236 | + sp->fwd->state_controller()->start_heading_updates(); |
237 | + }); |
238 | +} |
239 | + |
240 | +void location::DispatchingProvider::stop_heading_updates() |
241 | +{ |
242 | + std::weak_ptr<location::DispatchingProvider> wp{shared_from_this()}; |
243 | + dispatcher([wp]() |
244 | + { |
245 | + auto sp = wp.lock(); |
246 | + |
247 | + if (not sp) |
248 | + return; |
249 | + |
250 | + sp->fwd->state_controller()->stop_heading_updates(); |
251 | + }); |
252 | +} |
253 | + |
254 | +void location::DispatchingProvider::start_velocity_updates() |
255 | +{ |
256 | + std::weak_ptr<location::DispatchingProvider> wp{shared_from_this()}; |
257 | + dispatcher([wp]() |
258 | + { |
259 | + auto sp = wp.lock(); |
260 | + |
261 | + if (not sp) |
262 | + return; |
263 | + |
264 | + sp->fwd->state_controller()->start_velocity_updates(); |
265 | + }); |
266 | +} |
267 | + |
268 | +void location::DispatchingProvider::stop_velocity_updates() |
269 | +{ |
270 | + std::weak_ptr<location::DispatchingProvider> wp{shared_from_this()}; |
271 | + dispatcher([wp]() |
272 | + { |
273 | + auto sp = wp.lock(); |
274 | + |
275 | + if (not sp) |
276 | + return; |
277 | + |
278 | + sp->fwd->state_controller()->stop_velocity_updates(); |
279 | + }); |
280 | +} |
281 | + |
282 | +location::DispatchingProvider::Ptr location::DispatchingProvider::init() |
283 | +{ |
284 | + auto sp = shared_from_this(); |
285 | + std::weak_ptr<location::DispatchingProvider> wp{sp}; |
286 | + connections.push_back(fwd->updates().position.connect([wp](const location::Update<location::Position>& update) |
287 | + { |
288 | + auto sp = wp.lock(); |
289 | + |
290 | + if (not sp) |
291 | + return; |
292 | + |
293 | + sp->dispatcher([wp, update]() |
294 | + { |
295 | + auto sp = wp.lock(); |
296 | + |
297 | + if (not sp) |
298 | + return; |
299 | + |
300 | + sp->mutable_updates().position(update); |
301 | + }); |
302 | + })); |
303 | + |
304 | + connections.push_back(fwd->updates().heading.connect([wp](const location::Update<location::Heading>& update) |
305 | + { |
306 | + auto sp = wp.lock(); |
307 | + |
308 | + if (not sp) |
309 | + return; |
310 | + |
311 | + sp->dispatcher([wp, update]() |
312 | + { |
313 | + auto sp = wp.lock(); |
314 | + |
315 | + if (not sp) |
316 | + return; |
317 | + |
318 | + sp->mutable_updates().heading(update); |
319 | + }); |
320 | + })); |
321 | + |
322 | + connections.push_back(fwd->updates().velocity.connect([wp](const location::Update<location::Velocity>& update) |
323 | + { |
324 | + auto sp = wp.lock(); |
325 | + |
326 | + if (not sp) |
327 | + return; |
328 | + |
329 | + sp->dispatcher([wp, update]() |
330 | + { |
331 | + auto sp = wp.lock(); |
332 | + |
333 | + if (not sp) |
334 | + return; |
335 | + |
336 | + sp->mutable_updates().velocity(update); |
337 | + }); |
338 | + })); |
339 | + |
340 | + return sp; |
341 | +} |
342 | |
343 | === added file 'src/location_service/com/ubuntu/location/dispatching_provider.h' |
344 | --- src/location_service/com/ubuntu/location/dispatching_provider.h 1970-01-01 00:00:00 +0000 |
345 | +++ src/location_service/com/ubuntu/location/dispatching_provider.h 2015-11-25 08:29:55 +0000 |
346 | @@ -0,0 +1,90 @@ |
347 | +/* |
348 | + * Copyright © 2014 Canonical Ltd. |
349 | + * |
350 | + * This program is free software: you can redistribute it and/or modify it |
351 | + * under the terms of the GNU Lesser General Public License version 3, |
352 | + * as published by the Free Software Foundation. |
353 | + * |
354 | + * This program is distributed in the hope that it will be useful, |
355 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
356 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
357 | + * GNU Lesser General Public License for more details. |
358 | + * |
359 | + * You should have received a copy of the GNU Lesser General Public License |
360 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
361 | + * |
362 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
363 | + */ |
364 | + |
365 | +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_DISPATCHING_PROVIDER_H_ |
366 | +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_DISPATCHING_PROVIDER_H_ |
367 | + |
368 | +#include <com/ubuntu/location/provider.h> |
369 | + |
370 | +#include <functional> |
371 | +#include <memory> |
372 | + |
373 | +namespace com |
374 | +{ |
375 | +namespace ubuntu |
376 | +{ |
377 | +namespace location |
378 | +{ |
379 | +// A Provider implementation that wraps another provider implementation |
380 | +// dispatching events/invocations via a Dispatcher functor. The dispatcher |
381 | +// can either immediately process the given task or hand it over to a runtime |
382 | +// with an associated event loop. |
383 | +class DispatchingProvider : public Provider, public std::enable_shared_from_this<DispatchingProvider> |
384 | +{ |
385 | +public: |
386 | + // To safe us some typing. |
387 | + typedef std::shared_ptr<DispatchingProvider> Ptr; |
388 | + |
389 | + // The Dispatcher functor that is invoked for all incoming |
390 | + // invocations and for all events, with both of them being |
391 | + // wrapped as a task. |
392 | + typedef std::function<void()> Task; |
393 | + typedef std::function<void(Task)> Dispatcher; |
394 | + |
395 | + // Create a new instance wired up to the given Provider instance. |
396 | + static DispatchingProvider::Ptr create(const Dispatcher& dispatcher, const Provider::Ptr& fwd); |
397 | + |
398 | + ~DispatchingProvider() noexcept; |
399 | + |
400 | + bool supports(const location::Provider::Features& f) const override; |
401 | + bool requires(const location::Provider::Requirements& r) const override; |
402 | + bool matches_criteria(const location::Criteria&) override; |
403 | + |
404 | + // We forward all events to the other providers. |
405 | + void on_wifi_and_cell_reporting_state_changed(WifiAndCellIdReportingState state) override; |
406 | + void on_reference_location_updated(const location::Update<location::Position>& position) override; |
407 | + void on_reference_velocity_updated(const location::Update<location::Velocity>& velocity) override; |
408 | + void on_reference_heading_updated(const location::Update<location::Heading>& heading) override; |
409 | + |
410 | + // As well as the respective state change requests. |
411 | + void start_position_updates() override; |
412 | + void stop_position_updates() override; |
413 | + void start_heading_updates() override; |
414 | + void stop_heading_updates() override; |
415 | + void start_velocity_updates() override; |
416 | + void stop_velocity_updates() override; |
417 | + |
418 | +private: |
419 | + // We want to pass ourselves around. |
420 | + DispatchingProvider(const Dispatcher& dispatcher, const Provider::Ptr& fwd); |
421 | + |
422 | + // Two stage initialization is evil, but we are somewhat forced to do it. |
423 | + DispatchingProvider::Ptr init(); |
424 | + |
425 | + // The dispatcher we rely on to dispatch events/invocations. |
426 | + Dispatcher dispatcher; |
427 | + // The provider that we relay to/from. |
428 | + Provider::Ptr fwd; |
429 | + // We store all connections that should be cut on destruction. |
430 | + std::vector<core::ScopedConnection> connections; |
431 | +}; |
432 | +} |
433 | +} |
434 | +} |
435 | + |
436 | +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_DISPATCHING_PROVIDER_H_ |
437 | |
438 | === modified file 'src/location_service/com/ubuntu/location/service/daemon.cpp' |
439 | --- src/location_service/com/ubuntu/location/service/daemon.cpp 2015-10-23 13:43:32 +0000 |
440 | +++ src/location_service/com/ubuntu/location/service/daemon.cpp 2015-11-25 08:29:55 +0000 |
441 | @@ -20,6 +20,8 @@ |
442 | #include <com/ubuntu/location/boost_ptree_settings.h> |
443 | #include <com/ubuntu/location/provider_factory.h> |
444 | |
445 | +#include <com/ubuntu/location/logging.h> |
446 | +#include <com/ubuntu/location/dispatching_provider.h> |
447 | #include <com/ubuntu/location/connectivity/dummy_connectivity_manager.h> |
448 | |
449 | #include <com/ubuntu/location/service/default_configuration.h> |
450 | @@ -39,6 +41,8 @@ |
451 | |
452 | #include <core/posix/signal.h> |
453 | |
454 | +#include <boost/asio.hpp> |
455 | + |
456 | #include <system_error> |
457 | #include <thread> |
458 | |
459 | @@ -74,6 +78,88 @@ |
460 | } |
461 | }; |
462 | |
463 | +// We bundle our "global" runtime dependencies here, specifically |
464 | +// a dispatcher to decouple multiple in-process providers from one |
465 | +// another , forcing execution to a well known set of threads. |
466 | +struct Runtime |
467 | +{ |
468 | + // Our default concurrency setup. |
469 | + static constexpr const std::uint32_t worker_threads = 2; |
470 | + |
471 | + // Our global singleton instance. |
472 | + static Runtime& instance() |
473 | + { |
474 | + static Runtime runtime; |
475 | + return runtime; |
476 | + } |
477 | + |
478 | + Runtime() |
479 | + : running{true}, |
480 | + service{worker_threads}, |
481 | + strand{service}, |
482 | + keep_alive{service} |
483 | + { |
484 | + for (unsigned int i = 0; i < worker_threads; i++) |
485 | + workers.push_back(std::thread |
486 | + { |
487 | + [this]() |
488 | + { |
489 | + while(running) |
490 | + { |
491 | + try |
492 | + { |
493 | + service.run(); |
494 | + break; |
495 | + } |
496 | + catch (const std::exception& e) |
497 | + { |
498 | + LOG(WARNING) << e.what(); |
499 | + } |
500 | + catch (...) |
501 | + { |
502 | + LOG(WARNING) << "Unknown exception caught while executing boost::asio::io_service"; |
503 | + } |
504 | + } |
505 | + } |
506 | + }); |
507 | + } |
508 | + |
509 | + ~Runtime() |
510 | + { |
511 | + stop(); |
512 | + } |
513 | + |
514 | + void stop() |
515 | + { |
516 | + VLOG(1) << __PRETTY_FUNCTION__; |
517 | + running = false; |
518 | + service.stop(); |
519 | + VLOG(1) << "\t Service stopped."; |
520 | + |
521 | + for (auto& worker : workers) |
522 | + if (worker.joinable()) |
523 | + worker.join(); |
524 | + |
525 | + VLOG(1) << "\t Worker threads joined."; |
526 | + } |
527 | + |
528 | + // Allows for reusing the runtime in components that require a dispatcher |
529 | + // to control execution of tasks. |
530 | + std::function<void(std::function<void()>)> to_dispatcher_functional() |
531 | + { |
532 | + return [this](std::function<void()> task) |
533 | + { |
534 | + strand.post(task); |
535 | + }; |
536 | + } |
537 | + |
538 | + bool running; |
539 | + boost::asio::io_service service; |
540 | + boost::asio::io_service::strand strand; |
541 | + boost::asio::io_service::work keep_alive; |
542 | + std::vector<std::thread> workers; |
543 | +}; |
544 | + |
545 | location::ProgramOptions init_daemon_options() |
546 | { |
547 | location::ProgramOptions options; |
548 | @@ -193,7 +279,9 @@ |
549 | config.provider_options.at(provider) : empty_provider_configuration); |
550 | |
551 | if (p) |
552 | - instantiated_providers.insert(p); |
553 | + instantiated_providers.insert( |
554 | + location::DispatchingProvider::create( |
555 | + Runtime::instance().to_dispatcher_functional(), p)); |
556 | else |
557 | throw std::runtime_error("Problem instantiating provider"); |
558 | |
559 | @@ -203,8 +291,8 @@ |
560 | } |
561 | } |
562 | |
563 | - config.incoming->install_executor(dbus::asio::make_executor(config.incoming)); |
564 | - config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing)); |
565 | + config.incoming->install_executor(dbus::asio::make_executor(config.incoming, Runtime::instance().service)); |
566 | + config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing, Runtime::instance().service)); |
567 | |
568 | location::service::DefaultConfiguration dc; |
569 | |
570 | @@ -222,50 +310,12 @@ |
571 | }; |
572 | |
573 | auto location_service = std::make_shared<location::service::Implementation>(configuration); |
574 | - // We need to ensure that any exception raised by the executor does not crash the app |
575 | - // and also gets logged. |
576 | - auto execute = [] (std::shared_ptr<core::dbus::Bus> bus) { |
577 | - while(true) |
578 | - { |
579 | - try |
580 | - { |
581 | - VLOG(10) << "Starting a bus executor"; |
582 | - bus->run(); |
583 | - break; // run() exited normally |
584 | - } |
585 | - catch (const std::exception& e) |
586 | - { |
587 | - LOG(WARNING) << e.what(); |
588 | - } |
589 | - catch (...) |
590 | - { |
591 | - LOG(WARNING) << "Unexpected exception was raised by the bus executor"; |
592 | - } |
593 | - } |
594 | - }; |
595 | - |
596 | - std::thread t1{execute, config.incoming}; |
597 | - std::thread t2{execute, config.incoming}; |
598 | - std::thread t3{execute, config.incoming}; |
599 | - std::thread t4{execute, config.outgoing}; |
600 | |
601 | trap->run(); |
602 | |
603 | config.incoming->stop(); |
604 | config.outgoing->stop(); |
605 | |
606 | - if (t1.joinable()) |
607 | - t1.join(); |
608 | - |
609 | - if (t2.joinable()) |
610 | - t2.join(); |
611 | - |
612 | - if (t3.joinable()) |
613 | - t3.join(); |
614 | - |
615 | - if (t4.joinable()) |
616 | - t4.join(); |
617 | - |
618 | return EXIT_SUCCESS; |
619 | } |
620 | |
621 | |
622 | === modified file 'tests/acceptance_tests.cpp' |
623 | --- tests/acceptance_tests.cpp 2015-02-13 13:19:18 +0000 |
624 | +++ tests/acceptance_tests.cpp 2015-11-25 08:29:55 +0000 |
625 | @@ -708,7 +708,7 @@ |
626 | |
627 | options.add(Keys::update_period, |
628 | "Update period length for dummy::Provider setup.", |
629 | - std::uint32_t{100}); |
630 | + std::uint32_t{10}); |
631 | |
632 | options.add(Keys::client_count, |
633 | "Number of clients that should be fired up.", |
634 | @@ -761,6 +761,8 @@ |
635 | }; |
636 | } |
637 | |
638 | +#include "did_finish_successfully.h" |
639 | + |
640 | TEST_F(LocationServiceStandaloneLoad, MultipleClientsConnectingAndDisconnectingWorks) |
641 | { |
642 | EXPECT_TRUE(trust_store_is_set_up_for_testing); |
643 | @@ -829,7 +831,7 @@ |
644 | status; |
645 | }, core::posix::StandardStream::empty); |
646 | |
647 | - std::this_thread::sleep_for(std::chrono::seconds{2}); |
648 | + std::this_thread::sleep_for(std::chrono::seconds{15}); |
649 | |
650 | auto client = [this]() |
651 | { |
652 | @@ -957,17 +959,11 @@ |
653 | { |
654 | VLOG(1) << "Stopping client...: " << client.pid(); |
655 | client.send_signal_or_throw(core::posix::Signal::sig_term); |
656 | - auto result = client.wait_for(core::posix::wait::Flags::untraced); |
657 | - |
658 | - EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status); |
659 | - EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status); |
660 | + EXPECT_TRUE(did_finish_successfully(client.wait_for(core::posix::wait::Flags::untraced))); |
661 | } |
662 | |
663 | VLOG(1) << "Cleaned up clients, shutting down the service..."; |
664 | |
665 | server.send_signal_or_throw(core::posix::Signal::sig_term); |
666 | - auto result = server.wait_for(core::posix::wait::Flags::untraced); |
667 | - |
668 | - EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status); |
669 | - EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status); |
670 | + EXPECT_TRUE(did_finish_successfully(server.wait_for(core::posix::wait::Flags::untraced))); |
671 | } |
FAILED: Continuous integration, rev:129 jenkins. qa.ubuntu. com/job/ location- service- ci/316/ jenkins. qa.ubuntu. com/job/ location- service- utopic- amd64-ci/ 223/console jenkins. qa.ubuntu. com/job/ location- service- utopic- armhf-ci/ 223/console jenkins. qa.ubuntu. com/job/ location- service- utopic- i386-ci/ 223/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/location- service- ci/316/ rebuild
http://