Merge lp:~thomas-voss/location-service/robustify-event-propagation-in-case-of-multiple-providers-running into lp:location-service/trunk
- robustify-event-propagation-in-case-of-multiple-providers-running
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~thomas-voss/location-service/robustify-event-propagation-in-case-of-multiple-providers-running |
Merge into: | lp:location-service/trunk |
Diff against target: |
722 lines (+542/-48) 6 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/non_selecting_provider_selection_policy.cpp (+24/-14) src/location_service/com/ubuntu/location/service/daemon.cpp (+91/-23) tests/acceptance_tests.cpp (+11/-11) |
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 |
---|---|---|---|
Loïc Minier | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+238544@code.launchpad.net |
This proposal has been superseded by a proposal from 2015-11-18.
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 : | # |
- 130. By Thomas Voß
-
And some further fixes.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:130
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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. - 133. By Thomas Voß
-
Explicitly stop bus instances on shut down.
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 2014-09-18 11:15:35 +0000 |
3 | +++ src/location_service/com/ubuntu/location/CMakeLists.txt 2014-10-16 16:35:27 +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 2014-10-16 16:35:27 +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 2014-10-16 16:35:27 +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/non_selecting_provider_selection_policy.cpp' |
439 | --- src/location_service/com/ubuntu/location/non_selecting_provider_selection_policy.cpp 2014-09-18 11:15:35 +0000 |
440 | +++ src/location_service/com/ubuntu/location/non_selecting_provider_selection_policy.cpp 2014-10-16 16:35:27 +0000 |
441 | @@ -51,24 +51,33 @@ |
442 | // We connect to all updates of each provider. |
443 | for (auto provider : BagOfProviders::providers) |
444 | { |
445 | - provider->updates().position.connect([this](const location::Update<location::Position>& update) |
446 | - { |
447 | - mutable_updates().position(update); |
448 | - }); |
449 | - |
450 | - provider->updates().heading.connect([this](const location::Update<location::Heading>& update) |
451 | - { |
452 | - mutable_updates().heading(update); |
453 | - }); |
454 | - |
455 | - provider->updates().velocity.connect([this](const location::Update<location::Velocity>& update) |
456 | - { |
457 | - mutable_updates().velocity(update); |
458 | - }); |
459 | + event_connections.push_back( |
460 | + provider->updates().position.connect([this](const location::Update<location::Position>& update) |
461 | + { |
462 | + mutable_updates().position(update); |
463 | + })); |
464 | + |
465 | + event_connections.push_back( |
466 | + provider->updates().heading.connect([this](const location::Update<location::Heading>& update) |
467 | + { |
468 | + mutable_updates().heading(update); |
469 | + })); |
470 | + |
471 | + event_connections.push_back( |
472 | + provider->updates().velocity.connect([this](const location::Update<location::Velocity>& update) |
473 | + { |
474 | + mutable_updates().velocity(update); |
475 | + })); |
476 | } |
477 | |
478 | } |
479 | |
480 | + ~BagOfProviders() |
481 | + { |
482 | + for(auto& c : event_connections) |
483 | + c.disconnect(); |
484 | + } |
485 | + |
486 | // We always match :) |
487 | bool matches_criteria(const location::Criteria&) override |
488 | { |
489 | @@ -137,6 +146,7 @@ |
490 | } |
491 | |
492 | std::set<location::Provider::Ptr> providers; |
493 | + std::vector<core::Connection> event_connections; |
494 | }; |
495 | } |
496 | |
497 | |
498 | === modified file 'src/location_service/com/ubuntu/location/service/daemon.cpp' |
499 | --- src/location_service/com/ubuntu/location/service/daemon.cpp 2014-09-16 21:34:33 +0000 |
500 | +++ src/location_service/com/ubuntu/location/service/daemon.cpp 2014-10-16 16:35:27 +0000 |
501 | @@ -17,6 +17,9 @@ |
502 | */ |
503 | #include <com/ubuntu/location/provider_factory.h> |
504 | |
505 | +#include <com/ubuntu/location/logging.h> |
506 | +#include <com/ubuntu/location/dispatching_provider.h> |
507 | + |
508 | #include <com/ubuntu/location/service/default_configuration.h> |
509 | #include <com/ubuntu/location/service/demultiplexing_reporter.h> |
510 | #include <com/ubuntu/location/service/ichnaea_reporter.h> |
511 | @@ -32,6 +35,8 @@ |
512 | |
513 | #include <core/posix/signal.h> |
514 | |
515 | +#include <boost/asio.hpp> |
516 | + |
517 | #include <system_error> |
518 | #include <thread> |
519 | |
520 | @@ -67,6 +72,87 @@ |
521 | } |
522 | }; |
523 | |
524 | +// We bundle our "global" runtime dependencies here, specifically |
525 | +// a dispatcher to decouple multiple in-process providers from one |
526 | +// another , forcing execution to a well known set of threads. |
527 | +struct Runtime |
528 | +{ |
529 | + // Our default concurrency setup. |
530 | + static constexpr const std::uint32_t worker_threads = 2; |
531 | + |
532 | + // Our global singleton instance. |
533 | + static Runtime& instance() |
534 | + { |
535 | + static Runtime runtime; |
536 | + return runtime; |
537 | + } |
538 | + |
539 | + Runtime() |
540 | + : running{true}, |
541 | + service{worker_threads}, |
542 | + strand{service}, |
543 | + keep_alive{service} |
544 | + { |
545 | + for (unsigned int i = 0; i < worker_threads; i++) |
546 | + workers.push_back(std::thread |
547 | + { |
548 | + [this]() |
549 | + { |
550 | + while(running) |
551 | + { |
552 | + try |
553 | + { |
554 | + service.run(); |
555 | + } |
556 | + catch (const std::exception& e) |
557 | + { |
558 | + LOG(WARNING) << e.what(); |
559 | + } |
560 | + catch (...) |
561 | + { |
562 | + LOG(WARNING) << "Unknown exception caught while executing boost::asio::io_service"; |
563 | + } |
564 | + } |
565 | + } |
566 | + }); |
567 | + } |
568 | + |
569 | + ~Runtime() |
570 | + { |
571 | + stop(); |
572 | + } |
573 | + |
574 | + void stop() |
575 | + { |
576 | + VLOG(1) << __PRETTY_FUNCTION__; |
577 | + running = false; |
578 | + service.stop(); |
579 | + VLOG(1) << "\t Service stopped."; |
580 | + |
581 | + for (auto& worker : workers) |
582 | + if (worker.joinable()) |
583 | + worker.join(); |
584 | + |
585 | + VLOG(1) << "\t Worker threads joined."; |
586 | + } |
587 | + |
588 | + // Allows for reusing the runtime in components that require a dispatcher |
589 | + // to control execution of tasks. |
590 | + std::function<void(std::function<void()>)> to_dispatcher_functional() |
591 | + { |
592 | + return [this](std::function<void()> task) |
593 | + { |
594 | + strand.post(task); |
595 | + }; |
596 | + } |
597 | + |
598 | + bool running; |
599 | + boost::asio::io_service service; |
600 | + boost::asio::io_service::strand strand; |
601 | + boost::asio::io_service::work keep_alive; |
602 | + std::vector<std::thread> workers; |
603 | +}; |
604 | + |
605 | location::ProgramOptions init_daemon_options() |
606 | { |
607 | location::ProgramOptions options; |
608 | @@ -179,7 +265,9 @@ |
609 | config.provider_options.at(provider) : empty_provider_configuration); |
610 | |
611 | if (p) |
612 | - instantiated_providers.insert(p); |
613 | + instantiated_providers.insert( |
614 | + location::DispatchingProvider::create( |
615 | + Runtime::instance().to_dispatcher_functional(), p)); |
616 | else |
617 | throw std::runtime_error("Problem instantiating provider"); |
618 | |
619 | @@ -190,8 +278,8 @@ |
620 | } |
621 | } |
622 | |
623 | - config.incoming->install_executor(dbus::asio::make_executor(config.incoming)); |
624 | - config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing)); |
625 | + config.incoming->install_executor(dbus::asio::make_executor(config.incoming, Runtime::instance().service)); |
626 | + config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing, Runtime::instance().service)); |
627 | |
628 | location::service::DefaultConfiguration dc; |
629 | |
630 | @@ -234,28 +322,8 @@ |
631 | configuration |
632 | }; |
633 | |
634 | - std::thread t1{[&config](){config.incoming->run();}}; |
635 | - std::thread t2{[&config](){config.incoming->run();}}; |
636 | - std::thread t3{[&config](){config.incoming->run();}}; |
637 | - std::thread t4{[&config](){config.outgoing->run();}}; |
638 | - |
639 | trap->run(); |
640 | |
641 | - config.incoming->stop(); |
642 | - config.outgoing->stop(); |
643 | - |
644 | - if (t1.joinable()) |
645 | - t1.join(); |
646 | - |
647 | - if (t2.joinable()) |
648 | - t2.join(); |
649 | - |
650 | - if (t3.joinable()) |
651 | - t3.join(); |
652 | - |
653 | - if (t4.joinable()) |
654 | - t4.join(); |
655 | - |
656 | return EXIT_SUCCESS; |
657 | } |
658 | |
659 | |
660 | === modified file 'tests/acceptance_tests.cpp' |
661 | --- tests/acceptance_tests.cpp 2014-08-01 12:51:25 +0000 |
662 | +++ tests/acceptance_tests.cpp 2014-10-16 16:35:27 +0000 |
663 | @@ -677,7 +677,7 @@ |
664 | |
665 | options.add(Keys::update_period, |
666 | "Update period length for dummy::Provider setup.", |
667 | - std::uint32_t{100}); |
668 | + std::uint32_t{10}); |
669 | |
670 | options.add(Keys::client_count, |
671 | "Number of clients that should be fired up.", |
672 | @@ -730,6 +730,8 @@ |
673 | }; |
674 | } |
675 | |
676 | +#include "did_finish_successfully.h" |
677 | + |
678 | TEST_F(LocationServiceStandaloneLoad, MultipleClientsConnectingAndDisconnectingWorks) |
679 | { |
680 | EXPECT_TRUE(trust_store_is_set_up_for_testing); |
681 | @@ -773,7 +775,11 @@ |
682 | config.incoming = session_bus(); |
683 | config.outgoing = session_bus(); |
684 | config.is_testing_enabled = false; |
685 | - config.providers = {cul::providers::dummy::Provider::class_name()}; |
686 | + config.providers = |
687 | + { |
688 | + cul::providers::dummy::Provider::class_name(), |
689 | + cul::providers::dummy::Provider::class_name() |
690 | + }; |
691 | config.provider_options = provider_config; |
692 | |
693 | core::posix::exit::Status status{core::posix::exit::Status::failure}; |
694 | @@ -794,7 +800,7 @@ |
695 | status; |
696 | }, core::posix::StandardStream::empty); |
697 | |
698 | - std::this_thread::sleep_for(std::chrono::seconds{2}); |
699 | + std::this_thread::sleep_for(std::chrono::seconds{15}); |
700 | |
701 | auto client = [this]() |
702 | { |
703 | @@ -922,17 +928,11 @@ |
704 | { |
705 | VLOG(1) << "Stopping client...: " << client.pid(); |
706 | client.send_signal_or_throw(core::posix::Signal::sig_term); |
707 | - auto result = client.wait_for(core::posix::wait::Flags::untraced); |
708 | - |
709 | - EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status); |
710 | - EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status); |
711 | + EXPECT_TRUE(did_finish_successfully(client.wait_for(core::posix::wait::Flags::untraced))); |
712 | } |
713 | |
714 | VLOG(1) << "Cleaned up clients, shutting down the service..."; |
715 | |
716 | server.send_signal_or_throw(core::posix::Signal::sig_term); |
717 | - auto result = server.wait_for(core::posix::wait::Flags::untraced); |
718 | - |
719 | - EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status); |
720 | - EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status); |
721 | + EXPECT_TRUE(did_finish_successfully(server.wait_for(core::posix::wait::Flags::untraced))); |
722 | } |
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://