Merge lp:~unity-api-team/unity-scopes-api/click-store-support into lp:unity-scopes-api
- click-store-support
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 211 |
Proposed branch: | lp:~unity-api-team/unity-scopes-api/click-store-support |
Merge into: | lp:unity-scopes-api |
Diff against target: |
2465 lines (+1355/-216) 45 files modified
CMakeLists.txt (+1/-1) debian/changelog (+9/-0) debian/control (+2/-1) debian/libunity-scopes1.symbols (+4/-3) include/unity/scopes/Registry.h (+29/-1) include/unity/scopes/internal/MWRegistry.h (+11/-0) include/unity/scopes/internal/MWSubscriber.h (+4/-3) include/unity/scopes/internal/RegistryImpl.h (+4/-0) include/unity/scopes/internal/RegistryObject.h (+9/-3) include/unity/scopes/internal/RegistryObjectBase.h (+1/-0) include/unity/scopes/internal/smartscopes/SSRegistryObject.h (+1/-0) include/unity/scopes/internal/zmq_middleware/RegistryI.h (+4/-0) include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h (+1/-0) include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h (+3/-8) include/unity/scopes/testing/MockRegistry.h (+9/-0) scoperegistry/CMakeLists.txt (+2/-0) scoperegistry/DirWatcher.cpp (+272/-0) scoperegistry/DirWatcher.h (+79/-0) scoperegistry/FindFiles.cpp (+35/-23) scoperegistry/FindFiles.h (+17/-9) scoperegistry/ScopesWatcher.cpp (+184/-0) scoperegistry/ScopesWatcher.h (+57/-0) scoperegistry/scoperegistry.cpp (+136/-100) src/scopes/internal/MWRegistry.cpp (+23/-1) src/scopes/internal/MWSubscriber.cpp (+5/-0) src/scopes/internal/RegistryImpl.cpp (+15/-0) src/scopes/internal/RegistryObject.cpp (+93/-21) src/scopes/internal/smartscopes/SSRegistryObject.cpp (+5/-0) src/scopes/internal/zmq_middleware/ObjectAdapter.cpp (+3/-3) src/scopes/internal/zmq_middleware/RegistryI.cpp (+24/-1) src/scopes/internal/zmq_middleware/ZmqRegistry.cpp (+34/-0) src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp (+13/-18) src/scopes/internal/zmq_middleware/capnproto/Registry.capnp (+14/-0) test/gtest/scopes/CMakeLists.txt (+3/-3) test/gtest/scopes/Registry/CMakeLists.txt (+1/-0) test/gtest/scopes/Registry/Registry_test.cpp (+216/-5) test/gtest/scopes/Registry/other_scopes/CMakeLists.txt (+2/-0) test/gtest/scopes/Registry/other_scopes/testscopeC/CMakeLists.txt (+1/-0) test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.ini.in (+8/-0) test/gtest/scopes/Registry/other_scopes/testscopeD/CMakeLists.txt (+1/-0) test/gtest/scopes/Registry/other_scopes/testscopeD/testscopeD.ini.in (+8/-0) test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp (+1/-1) test/gtest/scopes/internal/zmq_middleware/CMakeLists.txt (+1/-1) test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp (+4/-4) test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp (+6/-6) |
To merge this branch: | bzr merge lp:~unity-api-team/unity-scopes-api/click-store-support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Unity Team | Pending | ||
Review via email: mp+221679@code.launchpad.net |
Commit message
Click store support
Description of the change
Click store support
- 211. By Pete Woods
-
Merge devel
- 212. By Marcus Tomlinson
-
Introduced Dir/ScopesWatcher classes to watch for updates to the scope install directories, and updated all relevant registry code to propagate an update pub/sub message via middleware.
Approved by PS Jenkins bot, Michi Henning.
PS Jenkins bot (ps-jenkins) wrote : | # |
- 213. By MichaĆ Sawicz
-
Revert to :any qualifier for python3 since LP recipes don't support it still.
Approved by PS Jenkins bot.
- 214. By Pete Woods
-
Bump micro version
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:213
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 215. By Marcus Tomlinson
-
Introduced is_scope_running() and set_scope_
state_callback( ) to Registry, added return values to set_*_callback() methods (to disconnect callback on destruction), and updated tests. Approved by Pete Woods, PS Jenkins bot.
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-05-22 08:45:05 +0000 |
3 | +++ CMakeLists.txt 2014-06-03 09:42:46 +0000 |
4 | @@ -180,7 +180,7 @@ |
5 | # API version |
6 | set(UNITY_SCOPES_MAJOR 0) |
7 | set(UNITY_SCOPES_MINOR 4) |
8 | -set(UNITY_SCOPES_MICRO 7) |
9 | +set(UNITY_SCOPES_MICRO 8) |
10 | |
11 | # Version for testing, with all symbols visible |
12 | set(UNITY_SCOPES_TEST_LIB ${UNITY_SCOPES_LIB}-test) |
13 | |
14 | === modified file 'debian/changelog' |
15 | --- debian/changelog 2014-05-22 09:58:34 +0000 |
16 | +++ debian/changelog 2014-06-03 09:42:46 +0000 |
17 | @@ -1,3 +1,12 @@ |
18 | +unity-scopes-api (0.4.8-0ubuntu1) UNRELEASED; urgency=medium |
19 | + |
20 | + [ Marcus Tomlinson ] |
21 | + * Introduced Dir/ScopesWatcher classes to watch for updates to the scope install directories. |
22 | + * Updated all relevant registry classes to propagate an update pub/sub message via middleware. |
23 | + * Added is_scope_running(), set_scope_state_callback() and set_update_callback() to Registry. |
24 | + |
25 | + -- Marcus Tomlinson <marcustomlinson@ubuntu> Wed, 28 May 2014 17:08:45 +0200 |
26 | + |
27 | unity-scopes-api (0.4.7+14.10.20140522-0ubuntu1) utopic; urgency=low |
28 | |
29 | [ Ubuntu daily release ] |
30 | |
31 | === modified file 'debian/control' |
32 | --- debian/control 2014-05-22 08:45:05 +0000 |
33 | +++ debian/control 2014-06-03 09:42:46 +0000 |
34 | @@ -8,7 +8,7 @@ |
35 | google-mock, |
36 | graphviz, |
37 | pkg-config, |
38 | - python3:native, |
39 | + python3:any, |
40 | capnproto, |
41 | libapparmor-dev, |
42 | libprocess-cpp-dev (>= 1.0.1), |
43 | @@ -49,6 +49,7 @@ |
44 | Multi-Arch: same |
45 | Pre-Depends: ${misc:Pre-Depends}, |
46 | Depends: libunity-scopes1 (= ${binary:Version}), |
47 | + libproperties-cpp-dev, |
48 | libunity-api-dev, |
49 | ${misc:Depends}, |
50 | Description: Header files for Unity scopes API |
51 | |
52 | === modified file 'debian/libunity-scopes1.symbols' |
53 | --- debian/libunity-scopes1.symbols 2014-05-22 09:58:32 +0000 |
54 | +++ debian/libunity-scopes1.symbols 2014-06-03 09:42:46 +0000 |
55 | @@ -411,6 +411,7 @@ |
56 | (c++)"unity::scopes::internal::smartscopes::SSScopeObject::SSScopeObject(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::internal::MiddlewareBase>, std::shared_ptr<unity::scopes::internal::smartscopes::SSRegistryObject>)@Base" 0.4.0+14.04.20140312.1 |
57 | (c++)"unity::scopes::internal::smartscopes::SSScopeObject::~SSScopeObject()@Base" 0.4.0+14.04.20140312.1 |
58 | (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::refresh_thread()@Base" 0.4.0+14.04.20140312.1 |
59 | + (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::is_scope_running(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme |
60 | (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::get_remote_scopes()@Base" 0.4.0+14.04.20140312.1 |
61 | (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::add(unity::scopes::internal::smartscopes::RemoteScope const&, unity::scopes::ScopeMetadata const&, std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::ScopeMetadata, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::ScopeMetadata> > >&, std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&)@Base" 0.4.0+14.04.20140324 |
62 | (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::locate(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
63 | @@ -431,9 +432,9 @@ |
64 | (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::exec(core::posix::ChildProcess::DeathObserver&, std::shared_ptr<unity::scopes::internal::Executor>)@Base" 0.4.3+14.10.20140428 |
65 | (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::kill(std::unique_lock<std::mutex>&)@Base" 0.4.2+14.04.20140404.2 |
66 | (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::kill()@Base" 0.4.2+14.04.20140404.2 |
67 | - (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeExecData)@Base" 0.4.2+14.04.20140404.2 |
68 | + (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeExecData, std::shared_ptr<unity::scopes::internal::MWPublisher>)@Base" 0replaceme |
69 | (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeProcess const&)@Base" 0.4.2+14.04.20140404.2 |
70 | - (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeExecData)@Base" 0.4.2+14.04.20140404.2 |
71 | + (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeExecData, std::shared_ptr<unity::scopes::internal::MWPublisher>)@Base" 0replaceme |
72 | (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::ScopeProcess(unity::scopes::internal::RegistryObject::ScopeProcess const&)@Base" 0.4.2+14.04.20140404.2 |
73 | (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::~ScopeProcess()@Base" 0.4.2+14.04.20140404.2 |
74 | (c++)"unity::scopes::internal::RegistryObject::ScopeExecData::~ScopeExecData()@Base" 0.4.2+14.04.20140404.2 |
75 | @@ -445,7 +446,7 @@ |
76 | (c++)"unity::scopes::internal::RegistryObject::remove_local_scope(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
77 | (c++)"unity::scopes::internal::RegistryObject::set_remote_registry(std::shared_ptr<unity::scopes::internal::MWRegistry> const&)@Base" 0.4.0+14.04.20140312.1 |
78 | (c++)"unity::scopes::internal::RegistryObject::locate(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
79 | - (c++)"unity::scopes::internal::RegistryObject::RegistryObject(core::posix::ChildProcess::DeathObserver&, std::shared_ptr<unity::scopes::internal::Executor> const&)@Base" 0.4.3+14.10.20140428 |
80 | + (c++)"unity::scopes::internal::RegistryObject::RegistryObject(core::posix::ChildProcess::DeathObserver&, std::shared_ptr<unity::scopes::internal::Executor> const&, std::shared_ptr<unity::scopes::internal::MiddlewareBase>)@Base" 0replaceme |
81 | (c++)"unity::scopes::internal::RegistryObject::~RegistryObject()@Base" 0.4.0+14.04.20140312.1 |
82 | (c++)"unity::scopes::internal::MiddlewareFactory::MiddlewareData::~MiddlewareData()@Base" 0.4.0+14.04.20140312.1 |
83 | (c++)"unity::scopes::internal::MiddlewareFactory::to_kind(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
84 | |
85 | === modified file 'include/unity/scopes/Registry.h' |
86 | --- include/unity/scopes/Registry.h 2014-05-19 08:26:40 +0000 |
87 | +++ include/unity/scopes/Registry.h 2014-06-03 09:42:46 +0000 |
88 | @@ -19,6 +19,7 @@ |
89 | #ifndef UNITY_SCOPES_REGISTRY_H |
90 | #define UNITY_SCOPES_REGISTRY_H |
91 | |
92 | +#include <core/signal.h> |
93 | #include <unity/scopes/Object.h> |
94 | #include <unity/scopes/RegistryProxyFwd.h> |
95 | #include <unity/scopes/ScopeMetadata.h> |
96 | @@ -56,8 +57,9 @@ |
97 | |
98 | /** |
99 | \brief Returns the metadata for the scope with the given ID. |
100 | + \param scope_id The ID of the scope from which we wish to retrieve metadata. |
101 | \return The metadata for the scope. |
102 | - \throws NotFoundException if no scope with the given name exists. |
103 | + \throws NotFoundException if no scope with the given ID exists. |
104 | */ |
105 | virtual ScopeMetadata get_metadata(std::string const& scope_id) = 0; |
106 | |
107 | @@ -74,6 +76,32 @@ |
108 | */ |
109 | virtual MetadataMap list_if(std::function<bool(ScopeMetadata const& item)> predicate) = 0; |
110 | |
111 | + /** |
112 | + \brief Returns whether a scope is currently running or not. |
113 | + \param scope_id The ID of the scope from which we wish to retrieve state. |
114 | + \return True if the scope is running, and False if it is not running. |
115 | + \throws NotFoundException if no scope with the given ID exists. |
116 | + */ |
117 | + virtual bool is_scope_running(std::string const& scope_id) = 0; |
118 | + |
119 | + /** |
120 | + \brief Assigns a callback method to be executed when a scope's running state (started / stopped) changes. |
121 | + \param scope_id The ID of the scope from which we wish to retrieve state changes. |
122 | + \param callback The function object that is invoked when a scope changes running state. |
123 | + \throws MiddlewareException if the registry subscriber failed to initialize. |
124 | + */ |
125 | + virtual core::ScopedConnection set_scope_state_callback(std::string const& scope_id, std::function<void(bool is_running)> callback) = 0; |
126 | + |
127 | + /** |
128 | + \brief Assigns a callback method to be executed when the registry's scope list changes. |
129 | + |
130 | + Note: Upon receiving this callback, you should retrieve the updated scopes list via the list() method if |
131 | + you wish to retain synchronisation between client and server. |
132 | + \param callback The function object that is invoked when an update occurs. |
133 | + \throws MiddlewareException if the registry subscriber failed to initialize. |
134 | + */ |
135 | + virtual core::ScopedConnection set_list_update_callback(std::function<void()> callback) = 0; |
136 | + |
137 | protected: |
138 | /// @cond |
139 | Registry(); |
140 | |
141 | === modified file 'include/unity/scopes/internal/MWRegistry.h' |
142 | --- include/unity/scopes/internal/MWRegistry.h 2014-04-03 12:57:25 +0000 |
143 | +++ include/unity/scopes/internal/MWRegistry.h 2014-06-03 09:42:46 +0000 |
144 | @@ -20,6 +20,7 @@ |
145 | #define UNITY_SCOPES_INTERNAL_MWREGISTRY_H |
146 | |
147 | #include <unity/scopes/internal/MWObjectProxy.h> |
148 | +#include <unity/scopes/internal/MWSubscriber.h> |
149 | #include <unity/scopes/Registry.h> |
150 | #include <unity/scopes/ScopeMetadata.h> |
151 | |
152 | @@ -39,11 +40,21 @@ |
153 | virtual ScopeMetadata get_metadata(std::string const& scope_id) = 0; |
154 | virtual MetadataMap list() = 0; |
155 | virtual ObjectProxy locate(std::string const& identity) = 0; |
156 | + virtual bool is_scope_running(std::string const& scope_id) = 0; |
157 | |
158 | virtual ~MWRegistry(); |
159 | |
160 | + // Local operations |
161 | + core::ScopedConnection set_scope_state_callback(std::string const& scope_id, std::function<void(bool)> callback); |
162 | + core::ScopedConnection set_list_update_callback(std::function<void()> callback); |
163 | + |
164 | protected: |
165 | MWRegistry(MiddlewareBase* mw_base); |
166 | + |
167 | +private: |
168 | + MiddlewareBase* mw_base_; |
169 | + MWSubscriber::UPtr list_update_subscriber_; |
170 | + std::map<std::string, MWSubscriber::UPtr> scope_state_subscribers_; |
171 | }; |
172 | |
173 | } // namespace internal |
174 | |
175 | === modified file 'include/unity/scopes/internal/MWSubscriber.h' |
176 | --- include/unity/scopes/internal/MWSubscriber.h 2014-05-19 05:15:06 +0000 |
177 | +++ include/unity/scopes/internal/MWSubscriber.h 2014-06-03 09:42:46 +0000 |
178 | @@ -19,6 +19,7 @@ |
179 | #ifndef UNITY_SCOPES_INTERNAL_MWSUBSCRIBER_H |
180 | #define UNITY_SCOPES_INTERNAL_MWSUBSCRIBER_H |
181 | |
182 | +#include <core/signal.h> |
183 | #include <unity/util/DefinesPtrs.h> |
184 | #include <unity/util/NonCopyable.h> |
185 | |
186 | @@ -31,8 +32,6 @@ |
187 | namespace internal |
188 | { |
189 | |
190 | -typedef std::function<void(std::string const& message)> SubscriberCallback; |
191 | - |
192 | class MWSubscriber |
193 | { |
194 | public: |
195 | @@ -42,10 +41,12 @@ |
196 | virtual ~MWSubscriber(); |
197 | |
198 | virtual std::string endpoint() const = 0; |
199 | - virtual void set_message_callback(SubscriberCallback callback) = 0; |
200 | + core::Signal<std::string const&> const& message_received() const; |
201 | |
202 | protected: |
203 | MWSubscriber(); |
204 | + |
205 | + core::Signal<std::string const&> message_received_; |
206 | }; |
207 | |
208 | } // namespace internal |
209 | |
210 | === modified file 'include/unity/scopes/internal/RegistryImpl.h' |
211 | --- include/unity/scopes/internal/RegistryImpl.h 2014-05-19 08:28:08 +0000 |
212 | +++ include/unity/scopes/internal/RegistryImpl.h 2014-06-03 09:42:46 +0000 |
213 | @@ -43,6 +43,10 @@ |
214 | virtual ScopeMetadata get_metadata(std::string const& scope_id) override; |
215 | virtual MetadataMap list() override; |
216 | virtual MetadataMap list_if(std::function<bool(ScopeMetadata const& item)> predicate) override; |
217 | + virtual bool is_scope_running(std::string const& scope_id) override; |
218 | + |
219 | + virtual core::ScopedConnection set_scope_state_callback(std::string const& scope_id, std::function<void(bool)> callback) override; |
220 | + virtual core::ScopedConnection set_list_update_callback(std::function<void()> callback) override; |
221 | |
222 | // Remote operation. Not part of public API, hence not override. |
223 | ObjectProxy locate(std::string const& identity); |
224 | |
225 | === modified file 'include/unity/scopes/internal/RegistryObject.h' |
226 | --- include/unity/scopes/internal/RegistryObject.h 2014-05-07 04:48:26 +0000 |
227 | +++ include/unity/scopes/internal/RegistryObject.h 2014-06-03 09:42:46 +0000 |
228 | @@ -20,6 +20,8 @@ |
229 | #define UNITY_SCOPES_INTERNAL_REGISTRYOBJECT_H |
230 | |
231 | #include <unity/scopes/internal/Executor.h> |
232 | +#include <unity/scopes/internal/MiddlewareBase.h> |
233 | +#include <unity/scopes/internal/MWPublisher.h> |
234 | #include <unity/scopes/internal/MWRegistryProxyFwd.h> |
235 | #include <unity/scopes/internal/RegistryObjectBase.h> |
236 | #include <unity/scopes/internal/StateReceiverObject.h> |
237 | @@ -55,13 +57,15 @@ |
238 | public: |
239 | UNITY_DEFINES_PTRS(RegistryObject); |
240 | |
241 | - RegistryObject(core::posix::ChildProcess::DeathObserver& death_observer, Executor::SPtr const& executor); |
242 | + RegistryObject(core::posix::ChildProcess::DeathObserver& death_observer, Executor::SPtr const& executor, |
243 | + MiddlewareBase::SPtr middleware); |
244 | virtual ~RegistryObject(); |
245 | |
246 | // Remote operation implementations |
247 | virtual ScopeMetadata get_metadata(std::string const& scope_id) const override; |
248 | virtual MetadataMap list() const override; |
249 | virtual ObjectProxy locate(std::string const& identity) override; |
250 | + virtual bool is_scope_running(std::string const& scope_id) override; |
251 | |
252 | // Local methods |
253 | bool add_local_scope(std::string const& scope_id, ScopeMetadata const& scope, |
254 | @@ -69,7 +73,6 @@ |
255 | bool remove_local_scope(std::string const& scope_id); |
256 | void set_remote_registry(MWRegistryProxy const& remote_registry); |
257 | |
258 | - bool is_scope_running(std::string const& scope_id); |
259 | StateReceiverObject::SPtr state_receiver(); |
260 | |
261 | private: |
262 | @@ -84,7 +87,7 @@ |
263 | Stopped, Starting, Running, Stopping |
264 | }; |
265 | |
266 | - ScopeProcess(ScopeExecData exec_data); |
267 | + ScopeProcess(ScopeExecData exec_data, MWPublisher::SPtr publisher); |
268 | ScopeProcess(ScopeProcess const& other); |
269 | ~ScopeProcess(); |
270 | |
271 | @@ -112,6 +115,7 @@ |
272 | mutable std::mutex process_mutex_; |
273 | mutable std::condition_variable state_change_cond_; |
274 | core::posix::ChildProcess process_ = core::posix::ChildProcess::invalid(); |
275 | + MWPublisher::SPtr reg_publisher_; |
276 | }; |
277 | |
278 | private: |
279 | @@ -128,6 +132,8 @@ |
280 | ProcessMap scope_processes_; |
281 | MWRegistryProxy remote_registry_; |
282 | mutable std::mutex mutex_; |
283 | + |
284 | + MWPublisher::SPtr publisher_; |
285 | }; |
286 | |
287 | } // namespace internal |
288 | |
289 | === modified file 'include/unity/scopes/internal/RegistryObjectBase.h' |
290 | --- include/unity/scopes/internal/RegistryObjectBase.h 2014-04-03 12:57:25 +0000 |
291 | +++ include/unity/scopes/internal/RegistryObjectBase.h 2014-06-03 09:42:46 +0000 |
292 | @@ -39,6 +39,7 @@ |
293 | virtual ScopeMetadata get_metadata(std::string const& scope_id) const = 0; |
294 | virtual MetadataMap list() const = 0; |
295 | virtual ObjectProxy locate(std::string const& identity) = 0; |
296 | + virtual bool is_scope_running(std::string const& scope_id) = 0; |
297 | }; |
298 | |
299 | } // namespace internal |
300 | |
301 | === modified file 'include/unity/scopes/internal/smartscopes/SSRegistryObject.h' |
302 | --- include/unity/scopes/internal/smartscopes/SSRegistryObject.h 2014-05-09 05:26:39 +0000 |
303 | +++ include/unity/scopes/internal/smartscopes/SSRegistryObject.h 2014-06-03 09:42:46 +0000 |
304 | @@ -54,6 +54,7 @@ |
305 | MetadataMap list() const override; |
306 | |
307 | ObjectProxy locate(std::string const& identity) override; |
308 | + bool is_scope_running(std::string const& scope_id) override; |
309 | |
310 | bool has_scope(std::string const& scope_id) const; |
311 | std::string get_base_url(std::string const& scope_id) const; |
312 | |
313 | === modified file 'include/unity/scopes/internal/zmq_middleware/RegistryI.h' |
314 | --- include/unity/scopes/internal/zmq_middleware/RegistryI.h 2014-04-03 12:57:25 +0000 |
315 | +++ include/unity/scopes/internal/zmq_middleware/RegistryI.h 2014-06-03 09:42:46 +0000 |
316 | @@ -59,6 +59,10 @@ |
317 | virtual void locate_(Current const& current, |
318 | capnp::AnyPointer::Reader& in_params, |
319 | capnproto::Response::Builder& r); |
320 | + |
321 | + virtual void is_scope_running_(Current const& current, |
322 | + capnp::AnyPointer::Reader& in_params, |
323 | + capnproto::Response::Builder& r); |
324 | }; |
325 | |
326 | } // namespace zmq_middleware |
327 | |
328 | === modified file 'include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h' |
329 | --- include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h 2014-04-03 12:57:25 +0000 |
330 | +++ include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h 2014-06-03 09:42:46 +0000 |
331 | @@ -52,6 +52,7 @@ |
332 | virtual ScopeMetadata get_metadata(std::string const& scope_id) override; |
333 | virtual MetadataMap list() override; |
334 | virtual ObjectProxy locate(std::string const& identity) override; |
335 | + virtual bool is_scope_running(std::string const& scope_id) override; |
336 | }; |
337 | |
338 | } // namespace zmq_middleware |
339 | |
340 | === modified file 'include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h' |
341 | --- include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h 2014-05-19 09:17:14 +0000 |
342 | +++ include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h 2014-06-03 09:42:46 +0000 |
343 | @@ -19,13 +19,11 @@ |
344 | #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSUBSCRIBER_H |
345 | #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSUBSCRIBER_H |
346 | |
347 | +#include <condition_variable> |
348 | +#include <thread> |
349 | #include <unity/scopes/internal/MWSubscriber.h> |
350 | - |
351 | #include <zmqpp/context.hpp> |
352 | |
353 | -#include <condition_variable> |
354 | -#include <thread> |
355 | - |
356 | namespace unity |
357 | { |
358 | |
359 | @@ -48,7 +46,6 @@ |
360 | virtual ~ZmqSubscriber(); |
361 | |
362 | std::string endpoint() const override; |
363 | - void set_message_callback(SubscriberCallback callback) override; |
364 | |
365 | private: |
366 | enum ThreadState |
367 | @@ -56,7 +53,7 @@ |
368 | NotRunning, |
369 | Running, |
370 | Stopping, |
371 | - Failed |
372 | + Stopped |
373 | }; |
374 | |
375 | zmqpp::context* const context_; |
376 | @@ -70,8 +67,6 @@ |
377 | ThreadState thread_state_; |
378 | std::exception_ptr thread_exception_; |
379 | |
380 | - SubscriberCallback callback_; |
381 | - |
382 | void subscriber_thread(); |
383 | }; |
384 | |
385 | |
386 | === modified file 'include/unity/scopes/testing/MockRegistry.h' |
387 | --- include/unity/scopes/testing/MockRegistry.h 2014-05-19 08:31:25 +0000 |
388 | +++ include/unity/scopes/testing/MockRegistry.h 2014-06-03 09:42:46 +0000 |
389 | @@ -43,6 +43,15 @@ |
390 | MOCK_METHOD1(get_metadata, ScopeMetadata(std::string const&)); |
391 | MOCK_METHOD0(list, MetadataMap()); |
392 | MOCK_METHOD1(list_if, MetadataMap(std::function<bool(ScopeMetadata const&)>)); |
393 | + MOCK_METHOD1(is_scope_running, bool(std::string const&)); |
394 | + core::ScopedConnection set_scope_state_callback(std::string const&, std::function<void(bool is_running)>) override |
395 | + { |
396 | + return core::Signal<>().connect([]{}); |
397 | + } |
398 | + core::ScopedConnection set_list_update_callback(std::function<void()>) override |
399 | + { |
400 | + return core::Signal<>().connect([]{}); |
401 | + } |
402 | }; |
403 | |
404 | /// @endcond |
405 | |
406 | === modified file 'scoperegistry/CMakeLists.txt' |
407 | --- scoperegistry/CMakeLists.txt 2014-05-19 08:40:28 +0000 |
408 | +++ scoperegistry/CMakeLists.txt 2014-06-03 09:42:46 +0000 |
409 | @@ -1,6 +1,8 @@ |
410 | set(SRC |
411 | + DirWatcher.cpp |
412 | FindFiles.cpp |
413 | scoperegistry.cpp |
414 | + ScopesWatcher.cpp |
415 | ) |
416 | |
417 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
418 | |
419 | === added file 'scoperegistry/DirWatcher.cpp' |
420 | --- scoperegistry/DirWatcher.cpp 1970-01-01 00:00:00 +0000 |
421 | +++ scoperegistry/DirWatcher.cpp 2014-06-03 09:42:46 +0000 |
422 | @@ -0,0 +1,272 @@ |
423 | +/* |
424 | + * Copyright (C) 2014 Canonical Ltd |
425 | + * |
426 | + * This program is free software: you can redistribute it and/or modify |
427 | + * it under the terms of the GNU Lesser General Public License version 3 as |
428 | + * published by the Free Software Foundation. |
429 | + * |
430 | + * This program is distributed in the hope that it will be useful, |
431 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
432 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
433 | + * GNU Lesser General Public License for more details. |
434 | + * |
435 | + * You should have received a copy of the GNU Lesser General Public License |
436 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
437 | + * |
438 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
439 | + */ |
440 | + |
441 | +#include "DirWatcher.h" |
442 | + |
443 | +#include <unity/UnityExceptions.h> |
444 | + |
445 | +#include <iostream> |
446 | +#include <sys/inotify.h> |
447 | +#include <sys/ioctl.h> |
448 | +#include <unistd.h> |
449 | + |
450 | +using namespace unity; |
451 | + |
452 | +namespace scoperegistry |
453 | +{ |
454 | + |
455 | +DirWatcher::DirWatcher() |
456 | + : fd_(inotify_init()) |
457 | + , thread_state_(Running) |
458 | + , thread_exception_(nullptr) |
459 | +{ |
460 | + // Validate the file descriptor |
461 | + if (fd_ < 0) |
462 | + { |
463 | + throw SyscallException("DirWatcher(): inotify_init() failed on inotify fd (fd = " + |
464 | + std::to_string(fd_) + ")", errno); |
465 | + } |
466 | +} |
467 | + |
468 | +DirWatcher::~DirWatcher() |
469 | +{ |
470 | + { |
471 | + std::lock_guard<std::mutex> lock(mutex_); |
472 | + |
473 | + if (thread_state_ == Failed) |
474 | + { |
475 | + try |
476 | + { |
477 | + std::rethrow_exception(thread_exception_); |
478 | + } |
479 | + catch (std::exception const& e) |
480 | + { |
481 | + std::cerr << "~DirWatcher(): " << e.what() << std::endl; |
482 | + } |
483 | + catch (...) |
484 | + { |
485 | + std::cerr << "~DirWatcher(): watch_thread was aborted due to an unknown exception" |
486 | + << std::endl; |
487 | + } |
488 | + } |
489 | + else |
490 | + { |
491 | + // Set state to Stopping |
492 | + thread_state_ = Stopping; |
493 | + |
494 | + // Remove watches (causes read to return) |
495 | + for (auto& wd : wds_) |
496 | + { |
497 | + inotify_rm_watch(fd_, wd.first); |
498 | + } |
499 | + wds_.clear(); |
500 | + } |
501 | + } |
502 | + |
503 | + // Wait for thread to terminate |
504 | + if (thread_.joinable()) |
505 | + { |
506 | + thread_.join(); |
507 | + } |
508 | + |
509 | + // Close the file descriptor |
510 | + close(fd_); |
511 | +} |
512 | + |
513 | +void DirWatcher::add_watch(std::string const& path) |
514 | +{ |
515 | + std::lock_guard<std::mutex> lock(mutex_); |
516 | + |
517 | + if (thread_state_ == Failed) |
518 | + { |
519 | + std::rethrow_exception(thread_exception_); |
520 | + } |
521 | + |
522 | + for (auto const& wd : wds_) |
523 | + { |
524 | + if (wd.second == path) |
525 | + { |
526 | + throw ResourceException("DirWatcher::add_watch(): failed to add watch for path: \"" + |
527 | + path + "\". Watch already exists."); |
528 | + } |
529 | + } |
530 | + |
531 | + int wd = inotify_add_watch(fd_, path.c_str(), IN_CREATE | IN_MOVED_TO | |
532 | + IN_DELETE | IN_MOVED_FROM | |
533 | + IN_MODIFY | IN_ATTRIB); |
534 | + if (wd < 0) |
535 | + { |
536 | + throw ResourceException("DirWatcher::add_watch(): failed to add watch for path: \"" + |
537 | + path + "\". inotify_add_watch() failed. (fd = " + |
538 | + std::to_string(fd_) + ", path = " + path + ")"); |
539 | + } |
540 | + |
541 | + wds_[wd] = path; |
542 | + |
543 | + // If this is the first watch, start the thread |
544 | + if (wds_.size() == 1) |
545 | + { |
546 | + thread_ = std::thread(&DirWatcher::watch_thread, this); |
547 | + } |
548 | +} |
549 | + |
550 | +void DirWatcher::remove_watch(std::string const& path) |
551 | +{ |
552 | + std::lock_guard<std::mutex> lock(mutex_); |
553 | + |
554 | + if (thread_state_ == Failed) |
555 | + { |
556 | + std::rethrow_exception(thread_exception_); |
557 | + } |
558 | + |
559 | + for (auto const& wd : wds_) |
560 | + { |
561 | + if (wd.second == path) |
562 | + { |
563 | + // If this is the last watch, stop the thread |
564 | + if (wds_.size() == 1) |
565 | + { |
566 | + thread_state_ = Stopping; |
567 | + } |
568 | + |
569 | + // Remove watch (causes read to return) |
570 | + inotify_rm_watch(fd_, wd.first); |
571 | + wds_.erase(wd.first); |
572 | + break; |
573 | + } |
574 | + } |
575 | +} |
576 | + |
577 | +void DirWatcher::watch_thread() |
578 | +{ |
579 | + try |
580 | + { |
581 | + fd_set fds; |
582 | + FD_ZERO(&fds); |
583 | + FD_SET(fd_, &fds); |
584 | + |
585 | + int bytes_avail = 0; |
586 | + std::string buffer; |
587 | + std::string event_path; |
588 | + |
589 | + // Poll for notifications until stop is requested |
590 | + while (true) |
591 | + { |
592 | + // Wait for a payload to arrive |
593 | + int ret = select(fd_ + 1, &fds, nullptr, nullptr, nullptr); |
594 | + if (ret < 0) |
595 | + { |
596 | + throw SyscallException("DirWatcher::watch_thread(): Thread aborted: " |
597 | + "select() failed on inotify fd (fd = " + |
598 | + std::to_string(fd_) + ")", errno); |
599 | + } |
600 | + // Get number of bytes available |
601 | + ret = ioctl(fd_, FIONREAD, &bytes_avail); |
602 | + if (ret < 0) |
603 | + { |
604 | + throw SyscallException("DirWatcher::watch_thread(): Thread aborted: " |
605 | + "ioctl() failed on inotify fd (fd = " + |
606 | + std::to_string(fd_) + ")", errno); |
607 | + } |
608 | + // Read available bytes |
609 | + buffer.resize(bytes_avail); |
610 | + int bytes_read = read(fd_, &buffer[0], buffer.size()); |
611 | + if (bytes_read < 0) |
612 | + { |
613 | + throw SyscallException("DirWatcher::watch_thread(): Thread aborted: " |
614 | + "read() failed on inotify fd (fd = " + |
615 | + std::to_string(fd_) + ")", errno); |
616 | + } |
617 | + |
618 | + // Process event(s) received |
619 | + int i = 0; |
620 | + while (i < bytes_read) |
621 | + { |
622 | + struct inotify_event* event = (inotify_event*)&buffer[i]; |
623 | + { |
624 | + event_path = ""; |
625 | + std::lock_guard<std::mutex> lock(mutex_); |
626 | + if (wds_.find(event->wd) != wds_.end()) |
627 | + { |
628 | + event_path = wds_.at(event->wd) + "/" + event->name; |
629 | + } |
630 | + } |
631 | + |
632 | + if (event->mask & IN_CREATE || event->mask & IN_MOVED_TO) |
633 | + { |
634 | + if (event->mask & IN_ISDIR) |
635 | + { |
636 | + watch_event(Added, Directory, event_path); |
637 | + } |
638 | + else |
639 | + { |
640 | + watch_event(Added, File, event_path); |
641 | + } |
642 | + } |
643 | + else if (event->mask & IN_DELETE || event->mask & IN_MOVED_FROM) |
644 | + { |
645 | + if (event->mask & IN_ISDIR) |
646 | + { |
647 | + watch_event(Removed, Directory, event_path); |
648 | + } |
649 | + else |
650 | + { |
651 | + watch_event(Removed, File, event_path); |
652 | + } |
653 | + } |
654 | + else if (event->mask & IN_MODIFY || event->mask & IN_ATTRIB) |
655 | + { |
656 | + if (event->mask & IN_ISDIR) |
657 | + { |
658 | + watch_event(Modified, Directory, event_path); |
659 | + } |
660 | + else |
661 | + { |
662 | + watch_event(Modified, File, event_path); |
663 | + } |
664 | + } |
665 | + i += sizeof(inotify_event) + event->len; |
666 | + } |
667 | + |
668 | + // Break from the loop if we are stopping |
669 | + { |
670 | + std::lock_guard<std::mutex> lock(mutex_); |
671 | + if (thread_state_ == Stopping) |
672 | + { |
673 | + break; |
674 | + } |
675 | + } |
676 | + } |
677 | + } |
678 | + catch (std::exception const& e) |
679 | + { |
680 | + std::cerr << e.what() << std::endl; |
681 | + std::lock_guard<std::mutex> lock(mutex_); |
682 | + thread_state_ = Failed; |
683 | + thread_exception_ = std::current_exception(); |
684 | + } |
685 | + catch (...) |
686 | + { |
687 | + std::cerr << "DirWatcher::watch_thread(): Thread aborted: unknown exception" << std::endl; |
688 | + std::lock_guard<std::mutex> lock(mutex_); |
689 | + thread_state_ = Failed; |
690 | + thread_exception_ = std::current_exception(); |
691 | + } |
692 | +} |
693 | + |
694 | +} // namespace scoperegistry |
695 | |
696 | === added file 'scoperegistry/DirWatcher.h' |
697 | --- scoperegistry/DirWatcher.h 1970-01-01 00:00:00 +0000 |
698 | +++ scoperegistry/DirWatcher.h 2014-06-03 09:42:46 +0000 |
699 | @@ -0,0 +1,79 @@ |
700 | +/* |
701 | + * Copyright (C) 2014 Canonical Ltd |
702 | + * |
703 | + * This program is free software: you can redistribute it and/or modify |
704 | + * it under the terms of the GNU Lesser General Public License version 3 as |
705 | + * published by the Free Software Foundation. |
706 | + * |
707 | + * This program is distributed in the hope that it will be useful, |
708 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
709 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
710 | + * GNU Lesser General Public License for more details. |
711 | + * |
712 | + * You should have received a copy of the GNU Lesser General Public License |
713 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
714 | + * |
715 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
716 | + */ |
717 | + |
718 | +#ifndef SCOPEREGISTRY_DIRWATCHER_H |
719 | +#define SCOPEREGISTRY_DIRWATCHER_H |
720 | + |
721 | +#include <condition_variable> |
722 | +#include <map> |
723 | +#include <thread> |
724 | + |
725 | +namespace scoperegistry |
726 | +{ |
727 | + |
728 | +// DirWatcher watches directories specified by calls to add_watch() / remove_watch() for changes in |
729 | +// the files and folders contained. If a file or folder is added, removed or modified, the pure |
730 | +// virtual watch_event() method is executed (this is to be overridden by a child class deriving |
731 | +// from DirWatcher) |
732 | + |
733 | +class DirWatcher |
734 | +{ |
735 | +public: |
736 | + enum EventType |
737 | + { |
738 | + Added, |
739 | + Removed, |
740 | + Modified |
741 | + }; |
742 | + |
743 | + enum FileType |
744 | + { |
745 | + File, |
746 | + Directory |
747 | + }; |
748 | + |
749 | + DirWatcher(); |
750 | + ~DirWatcher(); |
751 | + |
752 | + void add_watch(std::string const& path); |
753 | + void remove_watch(std::string const& path); |
754 | + |
755 | +private: |
756 | + enum ThreadState |
757 | + { |
758 | + Running, |
759 | + Stopping, |
760 | + Failed |
761 | + }; |
762 | + |
763 | + int const fd_; |
764 | + |
765 | + std::map<int, std::string> wds_; |
766 | + |
767 | + std::thread thread_; |
768 | + std::mutex mutex_; |
769 | + ThreadState thread_state_; |
770 | + std::exception_ptr thread_exception_; |
771 | + |
772 | + void watch_thread(); |
773 | + virtual void watch_event(EventType event_type, FileType file_type, std::string const& path) = 0; |
774 | +}; |
775 | + |
776 | +} // namespace scoperegistry |
777 | + |
778 | +#endif // SCOPEREGISTRY_DIRWATCHER_H |
779 | |
780 | === modified file 'scoperegistry/FindFiles.cpp' |
781 | --- scoperegistry/FindFiles.cpp 2014-05-21 02:07:16 +0000 |
782 | +++ scoperegistry/FindFiles.cpp 2014-06-03 09:42:46 +0000 |
783 | @@ -36,14 +36,9 @@ |
784 | namespace scoperegistry |
785 | { |
786 | |
787 | -namespace |
788 | -{ |
789 | - |
790 | // Return all paths underneath the given dir that are of the given type |
791 | // or are a symbolic link. |
792 | |
793 | -enum EntryType { File, Directory }; |
794 | - |
795 | vector<string> find_entries(string const& install_dir, EntryType type) |
796 | { |
797 | DIR* d = opendir(install_dir.c_str()); |
798 | @@ -83,39 +78,56 @@ |
799 | return entries; |
800 | } |
801 | |
802 | -} // namespace |
803 | +// Return all files of the form dir/<scomescope>.ini that are regular files or |
804 | +// symbolic links and have the specified suffix. |
805 | +// The empty suffix is legal and causes all regular files and symlinks to be returned. |
806 | + |
807 | +map<string, string> find_scope_dir_configs(string const& scope_dir, string const& suffix) |
808 | +{ |
809 | + map<string, string> files; |
810 | + |
811 | + auto paths = find_entries(scope_dir, File); |
812 | + for (auto path : paths) |
813 | + { |
814 | + filesystem::path fs_path(path); |
815 | + if (fs_path.extension() != suffix) |
816 | + { |
817 | + continue; |
818 | + } |
819 | + auto scope_id = fs_path.stem().native(); |
820 | + files.insert(make_pair(scope_id, path)); |
821 | + } |
822 | + |
823 | + return files; |
824 | +} |
825 | |
826 | // Return all files of the form dir/*/<scomescope>.ini that are regular files or |
827 | // symbolic links and have the specified suffix. |
828 | // The empty suffix is legal and causes all regular files and symlinks to be returned. |
829 | // Print error message for any scopes with an id that was seen previously. |
830 | |
831 | -vector<string> find_scope_config_files(string const& install_dir, |
832 | - string const& suffix, |
833 | - function<void(string const&)> error) |
834 | +map<string, string> find_install_dir_configs(string const& install_dir, |
835 | + string const& suffix, |
836 | + function<void(string const&)> error) |
837 | { |
838 | - vector<string> files; |
839 | + map<string, string> files; |
840 | map<string, string> scopes_seen; |
841 | |
842 | - auto subdirs = find_entries(install_dir, Directory); |
843 | - for (auto subdir : subdirs) |
844 | + auto scope_dirs = find_entries(install_dir, Directory); |
845 | + for (auto scope_dir : scope_dirs) |
846 | { |
847 | - auto candidates = find_entries(subdir, File); |
848 | - for (auto c : candidates) |
849 | + auto configs = find_scope_dir_configs(scope_dir, suffix); |
850 | + for (auto config : configs) |
851 | { |
852 | - filesystem::path path(c); |
853 | - if (path.extension() != suffix) { |
854 | - continue; |
855 | - } |
856 | - auto stem = path.stem().native(); |
857 | - auto const it = scopes_seen.find(stem); |
858 | + auto const it = scopes_seen.find(config.first); |
859 | if (it != scopes_seen.end()) |
860 | { |
861 | - error("ignoring second instance of non-unique scope: " + path.native() + "\n" |
862 | + error("ignoring second instance of non-unique scope: " + config.second + "\n" |
863 | "previous instance: " + it->second); |
864 | + continue; |
865 | } |
866 | - scopes_seen[stem] = path.native(); |
867 | - files.emplace_back(c); |
868 | + scopes_seen[config.first] = config.second; |
869 | + files.insert(config); |
870 | } |
871 | } |
872 | |
873 | |
874 | === modified file 'scoperegistry/FindFiles.h' |
875 | --- scoperegistry/FindFiles.h 2014-05-21 02:07:16 +0000 |
876 | +++ scoperegistry/FindFiles.h 2014-06-03 09:42:46 +0000 |
877 | @@ -21,12 +21,25 @@ |
878 | |
879 | #include <functional> |
880 | #include <string> |
881 | +#include <map> |
882 | #include <vector> |
883 | |
884 | namespace scoperegistry |
885 | { |
886 | |
887 | -// Return a vector of file names underneath a scope root install dir that have the given suffix. |
888 | +// Return a vector of all paths found underneath a given dir that are of the given type or are |
889 | +// a symbolic link. |
890 | + |
891 | +enum EntryType { File, Directory }; |
892 | +std::vector<std::string> find_entries(std::string const& install_dir, EntryType type); |
893 | + |
894 | +// Return a map of file names:paths underneath a scope dir that have the given suffix. Files are |
895 | +// searched for in the specified directory only, that is, no .ini files in further-nested |
896 | +// directories will be searched. |
897 | + |
898 | +std::map<std::string, std::string> find_scope_dir_configs(std::string const& scope_dir, std::string const& suffix); |
899 | + |
900 | +// Return a map of file names:paths underneath a scope root install dir that have the given suffix. |
901 | // Files are searched for exactly "one level down", that is, if we have a directory structure. |
902 | // |
903 | // canonical/scopeA/myconfig.ini |
904 | @@ -35,14 +48,9 @@ |
905 | // we get those two .ini files, but no .ini files in canonical or underneath |
906 | // further-nested directories. |
907 | |
908 | -std::vector<std::string> find_scope_config_files(std::string const& install_dir, |
909 | - std::string const& suffix, |
910 | - std::function<void(std::string const&)> error); |
911 | - |
912 | -// Return a vector of file names in dir with the given suffix. |
913 | - |
914 | -std::vector<std::string> find_files(std::string const& dir, |
915 | - std::string const& suffix); |
916 | +std::map<std::string, std::string> find_install_dir_configs(std::string const& install_dir, |
917 | + std::string const& suffix, |
918 | + std::function<void(std::string const&)> error); |
919 | |
920 | } // namespace scoperegistry |
921 | |
922 | |
923 | === added file 'scoperegistry/ScopesWatcher.cpp' |
924 | --- scoperegistry/ScopesWatcher.cpp 1970-01-01 00:00:00 +0000 |
925 | +++ scoperegistry/ScopesWatcher.cpp 2014-06-03 09:42:46 +0000 |
926 | @@ -0,0 +1,184 @@ |
927 | +/* |
928 | + * Copyright (C) 2014 Canonical Ltd |
929 | + * |
930 | + * This program is free software: you can redistribute it and/or modify |
931 | + * it under the terms of the GNU Lesser General Public License version 3 as |
932 | + * published by the Free Software Foundation. |
933 | + * |
934 | + * This program is distributed in the hope that it will be useful, |
935 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
936 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
937 | + * GNU Lesser General Public License for more details. |
938 | + * |
939 | + * You should have received a copy of the GNU Lesser General Public License |
940 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
941 | + * |
942 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
943 | + */ |
944 | + |
945 | +#include "ScopesWatcher.h" |
946 | + |
947 | +#include "FindFiles.h" |
948 | + |
949 | +#include <boost/filesystem/path.hpp> |
950 | + |
951 | +using namespace unity::scopes::internal; |
952 | +using namespace boost; |
953 | + |
954 | +namespace scoperegistry |
955 | +{ |
956 | + |
957 | +ScopesWatcher::ScopesWatcher(RegistryObject::SPtr registry, |
958 | + std::function<void(std::pair<std::string, std::string> const&)> ini_added_callback) |
959 | + : registry_(registry) |
960 | + , ini_added_callback_(ini_added_callback) |
961 | +{ |
962 | +} |
963 | + |
964 | +void ScopesWatcher::add_install_dir(std::string const& dir) |
965 | +{ |
966 | + try |
967 | + { |
968 | + // Add watch for root directory |
969 | + add_watch(dir); |
970 | + |
971 | + // Add watches for each sub directory in root |
972 | + auto subdirs = find_entries(dir, EntryType::Directory); |
973 | + for (auto const& subdir : subdirs) |
974 | + { |
975 | + auto configs = find_scope_dir_configs(subdir, ".ini"); |
976 | + if (!configs.empty()) |
977 | + { |
978 | + auto config = *configs.cbegin(); |
979 | + std::lock_guard<std::mutex> lock(mutex_); |
980 | + dir_to_ini_map_[subdir] = config.second; |
981 | + } |
982 | + add_watch(subdir); |
983 | + } |
984 | + } |
985 | + catch (...) {} |
986 | +} |
987 | + |
988 | +void ScopesWatcher::add_scope_dir(std::string const& dir) |
989 | +{ |
990 | + auto configs = find_scope_dir_configs(dir, ".ini"); |
991 | + if (!configs.empty()) |
992 | + { |
993 | + auto config = *configs.cbegin(); |
994 | + // Associate this directory with the contained config file |
995 | + { |
996 | + std::lock_guard<std::mutex> lock(mutex_); |
997 | + dir_to_ini_map_[dir] = config.second; |
998 | + } |
999 | + |
1000 | + // New config found, execute callback |
1001 | + ini_added_callback_(config); |
1002 | + std::cout << "ScopesWatcher: scope: \"" << config.first << "\" installed to: \"" |
1003 | + << dir << "\"" << std::endl; |
1004 | + } |
1005 | + |
1006 | + // Add a watch for this directory |
1007 | + add_watch(dir); |
1008 | +} |
1009 | + |
1010 | +void ScopesWatcher::remove_scope_dir(std::string const& dir) |
1011 | +{ |
1012 | + std::lock_guard<std::mutex> lock(mutex_); |
1013 | + |
1014 | + // Check if this directory is associate with the config file |
1015 | + if (dir_to_ini_map_.find(dir) != dir_to_ini_map_.end()) |
1016 | + { |
1017 | + // Inform the registry that this scope has been removed |
1018 | + std::string ini_path = dir_to_ini_map_.at(dir); |
1019 | + dir_to_ini_map_.erase(dir); |
1020 | + |
1021 | + filesystem::path p(ini_path); |
1022 | + std::string scope_id = p.stem().native(); |
1023 | + registry_->remove_local_scope(scope_id); |
1024 | + std::cout << "ScopesWatcher: scope: \"" << scope_id << "\" uninstalled from: \"" |
1025 | + << dir << "\"" << std::endl; |
1026 | + } |
1027 | + |
1028 | + // Remove the watch for this directory |
1029 | + remove_watch(dir); |
1030 | +} |
1031 | + |
1032 | +void ScopesWatcher::watch_event(DirWatcher::EventType event_type, |
1033 | + DirWatcher::FileType file_type, |
1034 | + std::string const& path) |
1035 | +{ |
1036 | + filesystem::path fs_path(path); |
1037 | + |
1038 | + if (file_type == DirWatcher::File && fs_path.extension() == ".ini") |
1039 | + { |
1040 | + std::lock_guard<std::mutex> lock(mutex_); |
1041 | + std::string parent_path = fs_path.parent_path().native(); |
1042 | + std::string scope_id = fs_path.stem().native(); |
1043 | + |
1044 | + // A .ini has been added / modified |
1045 | + if (event_type == DirWatcher::Added || event_type == DirWatcher::Modified) |
1046 | + { |
1047 | + dir_to_ini_map_[parent_path] = path; |
1048 | + ini_added_callback_(std::make_pair(scope_id, path)); |
1049 | + std::cout << "ScopesWatcher: scope: \"" << scope_id << "\" installed to: \"" |
1050 | + << parent_path << "\"" << std::endl; |
1051 | + } |
1052 | + // A .ini has been removed |
1053 | + else if (event_type == DirWatcher::Removed) |
1054 | + { |
1055 | + dir_to_ini_map_.erase(parent_path); |
1056 | + registry_->remove_local_scope(scope_id); |
1057 | + std::cout << "ScopesWatcher: scope: \"" << scope_id << "\" uninstalled from: \"" |
1058 | + << parent_path << "\"" << std::endl; |
1059 | + } |
1060 | + } |
1061 | + else if (file_type == DirWatcher::File && fs_path.extension() == ".so") |
1062 | + { |
1063 | + std::lock_guard<std::mutex> lock(mutex_); |
1064 | + std::string parent_path = fs_path.parent_path().native(); |
1065 | + |
1066 | + // Check if this directory is associate with the config file |
1067 | + if (dir_to_ini_map_.find(parent_path) != dir_to_ini_map_.end()) |
1068 | + { |
1069 | + std::string ini_path = dir_to_ini_map_.at(parent_path); |
1070 | + filesystem::path fs_ini_path(ini_path); |
1071 | + std::string scope_id = fs_ini_path.stem().native(); |
1072 | + |
1073 | + // A .so file has been added / modified |
1074 | + if (event_type == DirWatcher::Added || event_type == DirWatcher::Modified) |
1075 | + { |
1076 | + ini_added_callback_(std::make_pair(scope_id, ini_path)); |
1077 | + std::cout << "ScopesWatcher: scope: \"" << scope_id << "\" installed to: \"" |
1078 | + << parent_path << "\"" << std::endl; |
1079 | + } |
1080 | + // A .so file has been removed |
1081 | + else if (event_type == DirWatcher::Removed) |
1082 | + { |
1083 | + registry_->remove_local_scope(scope_id); |
1084 | + std::cout << "ScopesWatcher: scope: \"" << scope_id << "\" uninstalled from: \"" |
1085 | + << parent_path << "\"" << std::endl; |
1086 | + } |
1087 | + } |
1088 | + } |
1089 | + else |
1090 | + { |
1091 | + // A new sub directory has been added |
1092 | + if (event_type == DirWatcher::Added) |
1093 | + { |
1094 | + // try add this path as a scope folder |
1095 | + // (we need to do this with both files and folders added, as the file added may be a symlink) |
1096 | + try |
1097 | + { |
1098 | + add_scope_dir(path); |
1099 | + } |
1100 | + catch (...) {} |
1101 | + } |
1102 | + // A sub directory has been removed |
1103 | + else if (event_type == DirWatcher::Removed) |
1104 | + { |
1105 | + remove_scope_dir(path); |
1106 | + } |
1107 | + } |
1108 | +} |
1109 | + |
1110 | +} // namespace scoperegistry |
1111 | |
1112 | === added file 'scoperegistry/ScopesWatcher.h' |
1113 | --- scoperegistry/ScopesWatcher.h 1970-01-01 00:00:00 +0000 |
1114 | +++ scoperegistry/ScopesWatcher.h 2014-06-03 09:42:46 +0000 |
1115 | @@ -0,0 +1,57 @@ |
1116 | +/* |
1117 | + * Copyright (C) 2014 Canonical Ltd |
1118 | + * |
1119 | + * This program is free software: you can redistribute it and/or modify |
1120 | + * it under the terms of the GNU Lesser General Public License version 3 as |
1121 | + * published by the Free Software Foundation. |
1122 | + * |
1123 | + * This program is distributed in the hope that it will be useful, |
1124 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1125 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1126 | + * GNU Lesser General Public License for more details. |
1127 | + * |
1128 | + * You should have received a copy of the GNU Lesser General Public License |
1129 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1130 | + * |
1131 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
1132 | + */ |
1133 | + |
1134 | +#ifndef SCOPEREGISTRY_SCOPESWATCHER_H |
1135 | +#define SCOPEREGISTRY_SCOPESWATCHER_H |
1136 | + |
1137 | +#include <DirWatcher.h> |
1138 | + |
1139 | +#include <unity/scopes/internal/RegistryObject.h> |
1140 | + |
1141 | +namespace scoperegistry |
1142 | +{ |
1143 | + |
1144 | +// ScopesWatcher watches the scope install directories specified by calls to add_install_dir() for |
1145 | +// the installation / uninstallation of scopes. If a scope is removed, the registry is informed |
1146 | +// accordingly. If a scope is added, a user callback (provided on construction) is executed. |
1147 | + |
1148 | +class ScopesWatcher : public DirWatcher |
1149 | +{ |
1150 | +public: |
1151 | + ScopesWatcher(unity::scopes::internal::RegistryObject::SPtr registry, |
1152 | + std::function<void(std::pair<std::string, std::string> const&)> ini_added_callback); |
1153 | + |
1154 | + void add_install_dir(std::string const& dir); |
1155 | + |
1156 | +private: |
1157 | + unity::scopes::internal::RegistryObject::SPtr const registry_; |
1158 | + std::function<void(std::pair<std::string, std::string> const&)> const ini_added_callback_; |
1159 | + std::map<std::string, std::string> dir_to_ini_map_; |
1160 | + std::mutex mutex_; |
1161 | + |
1162 | + void add_scope_dir(std::string const& dir); |
1163 | + void remove_scope_dir(std::string const& dir); |
1164 | + |
1165 | + void watch_event(DirWatcher::EventType event_type, |
1166 | + DirWatcher::FileType file_type, |
1167 | + std::string const& path) override; |
1168 | +}; |
1169 | + |
1170 | +} // namespace scoperegistry |
1171 | + |
1172 | +#endif // SCOPEREGISTRY_SCOPESWATCHER_H |
1173 | |
1174 | === modified file 'scoperegistry/scoperegistry.cpp' |
1175 | --- scoperegistry/scoperegistry.cpp 2014-05-21 02:07:16 +0000 |
1176 | +++ scoperegistry/scoperegistry.cpp 2014-06-03 09:42:46 +0000 |
1177 | @@ -17,6 +17,7 @@ |
1178 | */ |
1179 | |
1180 | #include "FindFiles.h" |
1181 | +#include "ScopesWatcher.h" |
1182 | |
1183 | #include <unity/scopes/internal/MiddlewareFactory.h> |
1184 | #include <unity/scopes/internal/MWRegistry.h> |
1185 | @@ -136,26 +137,24 @@ |
1186 | map<string, string> fixed_scopes; // Scopes that the OEM cannot override |
1187 | map<string, string> overrideable_scopes; // Scopes that the OEM can override |
1188 | |
1189 | - auto config_files = find_scope_config_files(scope_installdir, ".ini", error); |
1190 | + auto config_files = find_install_dir_configs(scope_installdir, ".ini", error); |
1191 | for (auto&& path : config_files) |
1192 | { |
1193 | - filesystem::path p(path); |
1194 | - string scope_id = p.stem().native(); |
1195 | try |
1196 | { |
1197 | - ScopeConfig config(path); |
1198 | + ScopeConfig config(path.second); |
1199 | if (config.overrideable()) |
1200 | { |
1201 | - overrideable_scopes[scope_id] = path; |
1202 | + overrideable_scopes[path.first] = path.second; |
1203 | } |
1204 | else |
1205 | { |
1206 | - fixed_scopes[scope_id] = path; |
1207 | + fixed_scopes[path.first] = path.second; |
1208 | } |
1209 | } |
1210 | catch (unity::Exception const& e) |
1211 | { |
1212 | - error("ignoring scope \"" + scope_id + "\": configuration error:\n" + e.what()); |
1213 | + error("ignoring scope \"" + path.first + "\": configuration error:\n" + e.what()); |
1214 | } |
1215 | } |
1216 | |
1217 | @@ -163,19 +162,16 @@ |
1218 | { |
1219 | try |
1220 | { |
1221 | - auto oem_paths = find_scope_config_files(oem_installdir, ".ini", error); |
1222 | + auto oem_paths = find_install_dir_configs(oem_installdir, ".ini", error); |
1223 | for (auto&& path : oem_paths) |
1224 | { |
1225 | - filesystem::path p(path); |
1226 | - string file_name = p.filename().native(); |
1227 | - string scope_id = p.stem().native(); |
1228 | - if (fixed_scopes.find(scope_id) == fixed_scopes.end()) |
1229 | + if (fixed_scopes.find(path.first) == fixed_scopes.end()) |
1230 | { |
1231 | - overrideable_scopes[scope_id] = path; // Replaces scope if it was present already |
1232 | + overrideable_scopes[path.first] = path.second; // Replaces scope if it was present already |
1233 | } |
1234 | else |
1235 | { |
1236 | - error("ignoring non-overrideable scope config \"" + file_name + "\" in OEM directory " + oem_installdir); |
1237 | + error("ignoring non-overrideable scope config \"" + path.second + "\" in OEM directory " + oem_installdir); |
1238 | } |
1239 | } |
1240 | } |
1241 | @@ -199,19 +195,16 @@ |
1242 | { |
1243 | try |
1244 | { |
1245 | - auto click_paths = find_scope_config_files(click_installdir, ".ini", error); |
1246 | + auto click_paths = find_install_dir_configs(click_installdir, ".ini", error); |
1247 | for (auto&& path : click_paths) |
1248 | { |
1249 | - filesystem::path p(path); |
1250 | - string file_name = p.filename().native(); |
1251 | - string scope_id = p.stem().native(); |
1252 | - if (local_scopes.find(scope_id) == local_scopes.end()) |
1253 | + if (local_scopes.find(path.first) == local_scopes.end()) |
1254 | { |
1255 | - click_scopes[scope_id] = path; |
1256 | + click_scopes[path.first] = path.second; |
1257 | } |
1258 | else |
1259 | { |
1260 | - error("ignoring non-overrideable scope config \"" + file_name + "\" in click directory " + click_installdir); |
1261 | + error("ignoring non-overrideable scope config \"" + path.second + "\" in click directory " + click_installdir); |
1262 | } |
1263 | } |
1264 | } |
1265 | @@ -228,6 +221,94 @@ |
1266 | // For each scope, open the config file for the scope, create the metadata info from the config, |
1267 | // and add an entry to the RegistryObject. |
1268 | |
1269 | +void add_local_scope(RegistryObject::SPtr const& registry, |
1270 | + pair<string, string> const& scope, |
1271 | + MiddlewareBase::SPtr const& mw, |
1272 | + string const& scoperunner_path, |
1273 | + string const& config_file, |
1274 | + bool click, |
1275 | + int timeout_ms) |
1276 | +{ |
1277 | + unique_ptr<ScopeMetadataImpl> mi(new ScopeMetadataImpl(mw.get())); |
1278 | + string scope_config(scope.second); |
1279 | + ScopeConfig sc(scope_config); |
1280 | + |
1281 | + filesystem::path scope_path(scope_config); |
1282 | + filesystem::path scope_dir(scope_path.parent_path()); |
1283 | + |
1284 | + mi->set_scope_id(scope.first); |
1285 | + mi->set_display_name(sc.display_name()); |
1286 | + mi->set_description(sc.description()); |
1287 | + mi->set_author(sc.author()); |
1288 | + mi->set_invisible(sc.invisible()); |
1289 | + mi->set_appearance_attributes(sc.appearance_attributes()); |
1290 | + mi->set_scope_directory(scope_dir.native()); |
1291 | + mi->set_results_ttl_type(sc.results_ttl_type()); |
1292 | + |
1293 | + try |
1294 | + { |
1295 | + mi->set_art(relative_scope_path_to_abs_path(sc.art(), scope_dir).native()); |
1296 | + } |
1297 | + catch (NotFoundException const&) |
1298 | + { |
1299 | + } |
1300 | + try |
1301 | + { |
1302 | + mi->set_icon(relative_scope_path_to_abs_path(sc.icon(), scope_dir).native()); |
1303 | + } |
1304 | + catch (NotFoundException const&) |
1305 | + { |
1306 | + } |
1307 | + try |
1308 | + { |
1309 | + mi->set_search_hint(sc.search_hint()); |
1310 | + } |
1311 | + catch (NotFoundException const&) |
1312 | + { |
1313 | + } |
1314 | + try |
1315 | + { |
1316 | + mi->set_hot_key(sc.hot_key()); |
1317 | + } |
1318 | + catch (NotFoundException const&) |
1319 | + { |
1320 | + } |
1321 | + |
1322 | + ScopeProxy proxy = ScopeImpl::create(mw->create_scope_proxy(scope.first), mw->runtime(), scope.first); |
1323 | + mi->set_proxy(proxy); |
1324 | + auto meta = ScopeMetadataImpl::create(move(mi)); |
1325 | + |
1326 | + RegistryObject::ScopeExecData exec_data; |
1327 | + exec_data.scope_id = scope.first; |
1328 | + // get custom scope runner executable, if not set use default scoperunner |
1329 | + exec_data.scoperunner_path = scoperunner_path; |
1330 | + |
1331 | + if (click) |
1332 | + { |
1333 | + exec_data.confinement_profile = |
1334 | + scope_path.parent_path().filename().native(); |
1335 | + } |
1336 | + |
1337 | + exec_data.timeout_ms = timeout_ms; |
1338 | + |
1339 | + try |
1340 | + { |
1341 | + auto custom_exec = sc.scope_runner(); |
1342 | + if (custom_exec.empty()) |
1343 | + { |
1344 | + throw unity::InvalidArgumentException("Invalid scope runner executable for scope: " + scope.first); |
1345 | + } |
1346 | + exec_data.scoperunner_path = relative_scope_path_to_abs_path(custom_exec, scope_dir).native(); |
1347 | + } |
1348 | + catch (NotFoundException const&) |
1349 | + { |
1350 | + } |
1351 | + exec_data.runtime_config = config_file; |
1352 | + exec_data.scope_config = scope.second; |
1353 | + |
1354 | + registry->add_local_scope(scope.first, move(meta), exec_data); |
1355 | +} |
1356 | + |
1357 | void add_local_scopes(RegistryObject::SPtr const& registry, |
1358 | map<string, string> const& all_scopes, |
1359 | MiddlewareBase::SPtr const& mw, |
1360 | @@ -240,84 +321,7 @@ |
1361 | { |
1362 | try |
1363 | { |
1364 | - unique_ptr<ScopeMetadataImpl> mi(new ScopeMetadataImpl(mw.get())); |
1365 | - string scope_config(pair.second); |
1366 | - ScopeConfig sc(scope_config); |
1367 | - |
1368 | - filesystem::path scope_path(scope_config); |
1369 | - filesystem::path scope_dir(scope_path.parent_path()); |
1370 | - |
1371 | - mi->set_scope_id(pair.first); |
1372 | - mi->set_display_name(sc.display_name()); |
1373 | - mi->set_description(sc.description()); |
1374 | - mi->set_author(sc.author()); |
1375 | - mi->set_invisible(sc.invisible()); |
1376 | - mi->set_appearance_attributes(sc.appearance_attributes()); |
1377 | - mi->set_scope_directory(scope_dir.native()); |
1378 | - mi->set_results_ttl_type(sc.results_ttl_type()); |
1379 | - |
1380 | - try |
1381 | - { |
1382 | - mi->set_art(relative_scope_path_to_abs_path(sc.art(), scope_dir).native()); |
1383 | - } |
1384 | - catch (NotFoundException const&) |
1385 | - { |
1386 | - } |
1387 | - try |
1388 | - { |
1389 | - mi->set_icon(relative_scope_path_to_abs_path(sc.icon(), scope_dir).native()); |
1390 | - } |
1391 | - catch (NotFoundException const&) |
1392 | - { |
1393 | - } |
1394 | - try |
1395 | - { |
1396 | - mi->set_search_hint(sc.search_hint()); |
1397 | - } |
1398 | - catch (NotFoundException const&) |
1399 | - { |
1400 | - } |
1401 | - try |
1402 | - { |
1403 | - mi->set_hot_key(sc.hot_key()); |
1404 | - } |
1405 | - catch (NotFoundException const&) |
1406 | - { |
1407 | - } |
1408 | - |
1409 | - ScopeProxy proxy = ScopeImpl::create(mw->create_scope_proxy(pair.first), mw->runtime(), pair.first); |
1410 | - mi->set_proxy(proxy); |
1411 | - auto meta = ScopeMetadataImpl::create(move(mi)); |
1412 | - |
1413 | - RegistryObject::ScopeExecData exec_data; |
1414 | - exec_data.scope_id = pair.first; |
1415 | - // get custom scope runner executable, if not set use default scoperunner |
1416 | - exec_data.scoperunner_path = scoperunner_path; |
1417 | - |
1418 | - if (click) |
1419 | - { |
1420 | - exec_data.confinement_profile = |
1421 | - scope_path.parent_path().filename().native(); |
1422 | - } |
1423 | - |
1424 | - exec_data.timeout_ms = timeout_ms; |
1425 | - |
1426 | - try |
1427 | - { |
1428 | - auto custom_exec = sc.scope_runner(); |
1429 | - if (custom_exec.empty()) |
1430 | - { |
1431 | - throw unity::InvalidArgumentException("Invalid scope runner executable for scope: " + pair.first); |
1432 | - } |
1433 | - exec_data.scoperunner_path = relative_scope_path_to_abs_path(custom_exec, scope_dir).native(); |
1434 | - } |
1435 | - catch (NotFoundException const&) |
1436 | - { |
1437 | - } |
1438 | - exec_data.runtime_config = config_file; |
1439 | - exec_data.scope_config = pair.second; |
1440 | - |
1441 | - registry->add_local_scope(pair.first, move(meta), exec_data); |
1442 | + add_local_scope(registry, pair, mw, scoperunner_path, config_file, click, timeout_ms); |
1443 | } |
1444 | catch (unity::Exception const& e) |
1445 | { |
1446 | @@ -403,7 +407,7 @@ |
1447 | |
1448 | // The registry object stores the local and remote scopes |
1449 | Executor::SPtr executor = make_shared<Executor>(); |
1450 | - RegistryObject::SPtr registry(new RegistryObject(*signal_handler_wrapper.death_observer, executor)); |
1451 | + RegistryObject::SPtr registry(new RegistryObject(*signal_handler_wrapper.death_observer, executor, middleware)); |
1452 | |
1453 | // Add the metadata for each scope to the lookup table. |
1454 | // We do this before starting any of the scopes, so aggregating scopes don't get a lookup failure if |
1455 | @@ -433,6 +437,38 @@ |
1456 | registry->set_remote_registry(middleware->ss_registry_proxy()); |
1457 | } |
1458 | |
1459 | + // Configure watches for scope install directories |
1460 | + ScopesWatcher local_scopes_watcher(registry, |
1461 | + [registry, &middleware, &scoperunner_path, &config_file, process_timeout] |
1462 | + (pair<string, string> const& scope) |
1463 | + { |
1464 | + try |
1465 | + { |
1466 | + add_local_scope(registry, scope, middleware, scoperunner_path, config_file, false, process_timeout); |
1467 | + } |
1468 | + catch (unity::Exception const& e) |
1469 | + { |
1470 | + error("ignoring installed scope \"" + scope.first + "\": cannot create metadata: " + e.what()); |
1471 | + } |
1472 | + }); |
1473 | + local_scopes_watcher.add_install_dir(scope_installdir); |
1474 | + local_scopes_watcher.add_install_dir(oem_installdir); |
1475 | + |
1476 | + ScopesWatcher click_scopes_watcher(registry, |
1477 | + [registry, &middleware, &scoperunner_path, &config_file, process_timeout] |
1478 | + (pair<string, string> const& scope) |
1479 | + { |
1480 | + try |
1481 | + { |
1482 | + add_local_scope(registry, scope, middleware, scoperunner_path, config_file, true, process_timeout); |
1483 | + } |
1484 | + catch (unity::Exception const& e) |
1485 | + { |
1486 | + error("ignoring installed scope \"" + scope.first + "\": cannot create metadata: " + e.what()); |
1487 | + } |
1488 | + }); |
1489 | + click_scopes_watcher.add_install_dir(click_installdir); |
1490 | + |
1491 | // Let's add the registry's state receiver to the middleware so that scopes can inform |
1492 | // the registry of state changes. |
1493 | middleware->add_state_receiver_object("StateReceiver", registry->state_receiver()); |
1494 | |
1495 | === modified file 'src/scopes/internal/MWRegistry.cpp' |
1496 | --- src/scopes/internal/MWRegistry.cpp 2014-01-23 11:28:34 +0000 |
1497 | +++ src/scopes/internal/MWRegistry.cpp 2014-06-03 09:42:46 +0000 |
1498 | @@ -16,7 +16,9 @@ |
1499 | * Authored by: Michi Henning <michi.henning@canonical.com> |
1500 | */ |
1501 | |
1502 | +#include <unity/scopes/internal/MiddlewareBase.h> |
1503 | #include <unity/scopes/internal/MWRegistry.h> |
1504 | +#include <unity/scopes/internal/RuntimeImpl.h> |
1505 | |
1506 | using namespace std; |
1507 | |
1508 | @@ -30,7 +32,8 @@ |
1509 | { |
1510 | |
1511 | MWRegistry::MWRegistry(MiddlewareBase* mw_base) : |
1512 | - MWObjectProxy(mw_base) |
1513 | + MWObjectProxy(mw_base), |
1514 | + mw_base_(mw_base) |
1515 | { |
1516 | } |
1517 | |
1518 | @@ -38,6 +41,25 @@ |
1519 | { |
1520 | } |
1521 | |
1522 | +core::ScopedConnection MWRegistry::set_scope_state_callback(std::string const& scope_id, std::function<void(bool)> callback) |
1523 | +{ |
1524 | + if (scope_state_subscribers_.find(scope_id) == scope_state_subscribers_.end()) |
1525 | + { |
1526 | + scope_state_subscribers_[scope_id] = mw_base_->create_subscriber(mw_base_->runtime()->registry_identity(), scope_id); |
1527 | + } |
1528 | + return scope_state_subscribers_.at(scope_id)->message_received().connect([callback](string const& state){ callback(state == "started"); }); |
1529 | +} |
1530 | + |
1531 | +core::ScopedConnection MWRegistry::set_list_update_callback(std::function<void()> callback) |
1532 | +{ |
1533 | + if (!list_update_subscriber_) |
1534 | + { |
1535 | + // Use lazy initialization here to only subscribe to the publisher if a callback is set |
1536 | + list_update_subscriber_ = mw_base_->create_subscriber(mw_base_->runtime()->registry_identity()); |
1537 | + } |
1538 | + return list_update_subscriber_->message_received().connect([callback](string const&){ callback(); }); |
1539 | +} |
1540 | + |
1541 | } // namespace internal |
1542 | |
1543 | } // namespace scopes |
1544 | |
1545 | === modified file 'src/scopes/internal/MWSubscriber.cpp' |
1546 | --- src/scopes/internal/MWSubscriber.cpp 2014-05-14 12:57:34 +0000 |
1547 | +++ src/scopes/internal/MWSubscriber.cpp 2014-06-03 09:42:46 +0000 |
1548 | @@ -35,6 +35,11 @@ |
1549 | { |
1550 | } |
1551 | |
1552 | +core::Signal<std::string const&> const& MWSubscriber::message_received() const |
1553 | +{ |
1554 | + return message_received_; |
1555 | +} |
1556 | + |
1557 | } // namespace internal |
1558 | |
1559 | } // namespace scopes |
1560 | |
1561 | === modified file 'src/scopes/internal/RegistryImpl.cpp' |
1562 | --- src/scopes/internal/RegistryImpl.cpp 2014-05-19 08:28:08 +0000 |
1563 | +++ src/scopes/internal/RegistryImpl.cpp 2014-06-03 09:42:46 +0000 |
1564 | @@ -71,6 +71,21 @@ |
1565 | return matching_entries; |
1566 | } |
1567 | |
1568 | +bool RegistryImpl::is_scope_running(std::string const& scope_id) |
1569 | +{ |
1570 | + return fwd()->is_scope_running(scope_id); |
1571 | +} |
1572 | + |
1573 | +core::ScopedConnection RegistryImpl::set_scope_state_callback(std::string const& scope_id, std::function<void(bool)> callback) |
1574 | +{ |
1575 | + return fwd()->set_scope_state_callback(scope_id, callback); |
1576 | +} |
1577 | + |
1578 | +core::ScopedConnection RegistryImpl::set_list_update_callback(std::function<void()> callback) |
1579 | +{ |
1580 | + return fwd()->set_list_update_callback(callback); |
1581 | +} |
1582 | + |
1583 | MWRegistryProxy RegistryImpl::fwd() |
1584 | { |
1585 | return dynamic_pointer_cast<MWRegistry>(proxy()); |
1586 | |
1587 | === modified file 'src/scopes/internal/RegistryObject.cpp' |
1588 | --- src/scopes/internal/RegistryObject.cpp 2014-05-22 08:45:05 +0000 |
1589 | +++ src/scopes/internal/RegistryObject.cpp 2014-06-03 09:42:46 +0000 |
1590 | @@ -19,6 +19,7 @@ |
1591 | #include <unity/scopes/internal/RegistryObject.h> |
1592 | |
1593 | #include <unity/scopes/internal/MWRegistry.h> |
1594 | +#include <unity/scopes/internal/RuntimeImpl.h> |
1595 | #include <unity/scopes/ScopeExceptions.h> |
1596 | #include <unity/UnityExceptions.h> |
1597 | |
1598 | @@ -38,7 +39,8 @@ |
1599 | namespace internal |
1600 | { |
1601 | |
1602 | -RegistryObject::RegistryObject(core::posix::ChildProcess::DeathObserver& death_observer, Executor::SPtr const& executor) |
1603 | +RegistryObject::RegistryObject(core::posix::ChildProcess::DeathObserver& death_observer, Executor::SPtr const& executor, |
1604 | + MiddlewareBase::SPtr middleware) |
1605 | : death_observer_(death_observer), |
1606 | death_observer_connection_ |
1607 | { |
1608 | @@ -58,6 +60,17 @@ |
1609 | }, |
1610 | executor_(executor) |
1611 | { |
1612 | + if (middleware) |
1613 | + { |
1614 | + try |
1615 | + { |
1616 | + publisher_ = middleware->create_publisher(middleware->runtime()->registry_identity()); |
1617 | + } |
1618 | + catch (std::exception const& e) |
1619 | + { |
1620 | + std::cerr << "RegistryObject(): failed to create registry publisher: " << e.what() << endl; |
1621 | + } |
1622 | + } |
1623 | } |
1624 | |
1625 | RegistryObject::~RegistryObject() |
1626 | @@ -186,6 +199,19 @@ |
1627 | return proxy; |
1628 | } |
1629 | |
1630 | +bool RegistryObject::is_scope_running(std::string const& scope_id) |
1631 | +{ |
1632 | + lock_guard<decltype(mutex_)> lock(mutex_); |
1633 | + |
1634 | + auto it = scope_processes_.find(scope_id); |
1635 | + if (it != scope_processes_.end()) |
1636 | + { |
1637 | + return it->second.state() != ScopeProcess::ProcessState::Stopped; |
1638 | + } |
1639 | + |
1640 | + throw NotFoundException("RegistryObject::is_scope_process_running(): no such scope: ", scope_id); |
1641 | +} |
1642 | + |
1643 | bool RegistryObject::add_local_scope(std::string const& scope_id, ScopeMetadata const& metadata, |
1644 | ScopeExecData const& exec_data) |
1645 | { |
1646 | @@ -208,7 +234,13 @@ |
1647 | return_value = false; |
1648 | } |
1649 | scopes_.insert(make_pair(scope_id, metadata)); |
1650 | - scope_processes_.insert(make_pair(scope_id, ScopeProcess(exec_data))); |
1651 | + scope_processes_.insert(make_pair(scope_id, ScopeProcess(exec_data, publisher_))); |
1652 | + |
1653 | + if (publisher_) |
1654 | + { |
1655 | + // Send a blank message to subscribers to inform them that the registry has been updated |
1656 | + publisher_->send_message(""); |
1657 | + } |
1658 | return return_value; |
1659 | } |
1660 | |
1661 | @@ -224,7 +256,18 @@ |
1662 | lock_guard<decltype(mutex_)> lock(mutex_); |
1663 | |
1664 | scope_processes_.erase(scope_id); |
1665 | - return scopes_.erase(scope_id) == 1; |
1666 | + |
1667 | + if (scopes_.erase(scope_id) == 1) |
1668 | + { |
1669 | + if (publisher_) |
1670 | + { |
1671 | + // Send a blank message to subscribers to inform them that the registry has been updated |
1672 | + publisher_->send_message(""); |
1673 | + } |
1674 | + return true; |
1675 | + } |
1676 | + |
1677 | + return false; |
1678 | } |
1679 | |
1680 | void RegistryObject::set_remote_registry(MWRegistryProxy const& remote_registry) |
1681 | @@ -233,19 +276,6 @@ |
1682 | remote_registry_ = remote_registry; |
1683 | } |
1684 | |
1685 | -bool RegistryObject::is_scope_running(std::string const& scope_id) |
1686 | -{ |
1687 | - lock_guard<decltype(mutex_)> lock(mutex_); |
1688 | - |
1689 | - auto it = scope_processes_.find(scope_id); |
1690 | - if (it != scope_processes_.end()) |
1691 | - { |
1692 | - return it->second.state() != ScopeProcess::ProcessState::Stopped; |
1693 | - } |
1694 | - |
1695 | - throw NotFoundException("RegistryObject::is_scope_process_running(): no such scope: ", scope_id); |
1696 | -} |
1697 | - |
1698 | StateReceiverObject::SPtr RegistryObject::state_receiver() |
1699 | { |
1700 | return state_receiver_; |
1701 | @@ -286,13 +316,15 @@ |
1702 | // simply ignore states from scopes the registry does not know about |
1703 | } |
1704 | |
1705 | -RegistryObject::ScopeProcess::ScopeProcess(ScopeExecData exec_data) |
1706 | +RegistryObject::ScopeProcess::ScopeProcess(ScopeExecData exec_data, MWPublisher::SPtr publisher) |
1707 | : exec_data_(exec_data) |
1708 | + , reg_publisher_(publisher) |
1709 | { |
1710 | } |
1711 | |
1712 | RegistryObject::ScopeProcess::ScopeProcess(ScopeProcess const& other) |
1713 | : exec_data_(other.exec_data_) |
1714 | + , reg_publisher_(other.reg_publisher_) |
1715 | { |
1716 | } |
1717 | |
1718 | @@ -438,10 +470,50 @@ |
1719 | { |
1720 | return; |
1721 | } |
1722 | - else if (state == Stopped && state_ != Stopping ) |
1723 | - { |
1724 | - cerr << "RegistryObject::ScopeProcess: Scope: \"" << exec_data_.scope_id |
1725 | - << "\" closed unexpectedly. Either the process crashed or was killed forcefully." << endl; |
1726 | + else if (state == Running) |
1727 | + { |
1728 | + if (reg_publisher_) |
1729 | + { |
1730 | + // Send a "started" message to subscribers to inform them that this scope (topic) has started |
1731 | + reg_publisher_->send_message("started", exec_data_.scope_id); |
1732 | + } |
1733 | + |
1734 | + if (state_ != Starting) |
1735 | + { |
1736 | + cout << "RegistryObject::ScopeProcess: Process for scope: \"" << exec_data_.scope_id |
1737 | + << "\" started manually" << endl; |
1738 | + |
1739 | + // Don't update state, treat this scope as not running if a locate() is requested |
1740 | + return; |
1741 | + } |
1742 | + } |
1743 | + else if (state == Stopped) |
1744 | + { |
1745 | + if (reg_publisher_) |
1746 | + { |
1747 | + // Send a "stopped" message to subscribers to inform them that this scope (topic) has stopped |
1748 | + reg_publisher_->send_message("stopped", exec_data_.scope_id); |
1749 | + } |
1750 | + |
1751 | + if (state_ != Stopping) |
1752 | + { |
1753 | + cerr << "RegistryObject::ScopeProcess: Scope: \"" << exec_data_.scope_id |
1754 | + << "\" closed unexpectedly. Either the process crashed or was killed forcefully." << endl; |
1755 | + } |
1756 | + } |
1757 | + else if (state == Stopping && state_ != Running) |
1758 | + { |
1759 | + if (reg_publisher_) |
1760 | + { |
1761 | + // Send a "stopped" message to subscribers to inform them that this scope (topic) has stopped |
1762 | + reg_publisher_->send_message("stopped", exec_data_.scope_id); |
1763 | + } |
1764 | + |
1765 | + cout << "RegistryObject::ScopeProcess: Manually started process for scope: \"" |
1766 | + << exec_data_.scope_id << "\" terminated" << endl; |
1767 | + |
1768 | + // Don't update state, treat this scope as not running if a locate() is requested |
1769 | + return; |
1770 | } |
1771 | state_ = state; |
1772 | state_change_cond_.notify_all(); |
1773 | |
1774 | === modified file 'src/scopes/internal/smartscopes/SSRegistryObject.cpp' |
1775 | --- src/scopes/internal/smartscopes/SSRegistryObject.cpp 2014-05-16 14:29:11 +0000 |
1776 | +++ src/scopes/internal/smartscopes/SSRegistryObject.cpp 2014-06-03 09:42:46 +0000 |
1777 | @@ -127,6 +127,11 @@ |
1778 | throw internal::RegistryException("SSRegistryObject::locate(): operation not available"); |
1779 | } |
1780 | |
1781 | +bool SSRegistryObject::is_scope_running(std::string const&) |
1782 | +{ |
1783 | + throw internal::RegistryException("SSRegistryObject::is_scope_running(): operation not available"); |
1784 | +} |
1785 | + |
1786 | bool SSRegistryObject::has_scope(std::string const& scope_id) const |
1787 | { |
1788 | std::lock_guard<std::mutex> lock(scopes_mutex_); |
1789 | |
1790 | === modified file 'src/scopes/internal/zmq_middleware/ObjectAdapter.cpp' |
1791 | --- src/scopes/internal/zmq_middleware/ObjectAdapter.cpp 2014-05-20 04:20:46 +0000 |
1792 | +++ src/scopes/internal/zmq_middleware/ObjectAdapter.cpp 2014-06-03 09:42:46 +0000 |
1793 | @@ -524,12 +524,12 @@ |
1794 | { |
1795 | poller.add(stop); |
1796 | |
1797 | - frontend.set(zmqpp::socket_option::linger, 0); |
1798 | + frontend.set(zmqpp::socket_option::linger, 200); |
1799 | // "Safe" bind: prevents two servers from binding to the same endpoint. |
1800 | safe_bind(frontend, endpoint_); |
1801 | poller.add(frontend); |
1802 | |
1803 | - backend.set(zmqpp::socket_option::linger, 0); |
1804 | + backend.set(zmqpp::socket_option::linger, 200); |
1805 | backend.bind("inproc://" + name_ + "-worker"); |
1806 | poller.add(backend); |
1807 | |
1808 | @@ -638,7 +638,7 @@ |
1809 | |
1810 | auto socket_type = mode_ == RequestMode::Twoway ? zmqpp::socket_type::reply : zmqpp::socket_type::pull; |
1811 | zmqpp::socket s(*mw_.context(), socket_type); |
1812 | - s.set(zmqpp::socket_option::linger, 0); |
1813 | + s.set(zmqpp::socket_option::linger, 200); |
1814 | s.connect("inproc://" + name_ + "-worker"); |
1815 | poller.add(s); |
1816 | |
1817 | |
1818 | === modified file 'src/scopes/internal/zmq_middleware/RegistryI.cpp' |
1819 | --- src/scopes/internal/zmq_middleware/RegistryI.cpp 2014-04-03 12:57:25 +0000 |
1820 | +++ src/scopes/internal/zmq_middleware/RegistryI.cpp 2014-06-03 09:42:46 +0000 |
1821 | @@ -68,7 +68,8 @@ |
1822 | RegistryI::RegistryI(RegistryObjectBase::SPtr const& ro) : |
1823 | ServantBase(ro, { { "get_metadata", bind(&RegistryI::get_metadata_, this, _1, _2, _3) }, |
1824 | { "list", bind(&RegistryI::list_, this, _1, _2, _3) }, |
1825 | - { "locate", bind(&RegistryI::locate_, this, _1, _2, _3) } }) |
1826 | + { "locate", bind(&RegistryI::locate_, this, _1, _2, _3) }, |
1827 | + { "is_scope_running", bind(&RegistryI::is_scope_running_, this, _1, _2, _3) } }) |
1828 | |
1829 | { |
1830 | } |
1831 | @@ -151,6 +152,28 @@ |
1832 | } |
1833 | } |
1834 | |
1835 | +void RegistryI::is_scope_running_(Current const&, |
1836 | + capnp::AnyPointer::Reader& in_params, |
1837 | + capnproto::Response::Builder& r) |
1838 | +{ |
1839 | + auto req = in_params.getAs<capnproto::Registry::IsScopeRunningRequest>(); |
1840 | + string scope_id = req.getIdentity().cStr(); |
1841 | + auto delegate = dynamic_pointer_cast<RegistryObjectBase>(del()); |
1842 | + try |
1843 | + { |
1844 | + auto is_running = delegate->is_scope_running(scope_id); |
1845 | + r.setStatus(capnproto::ResponseStatus::SUCCESS); |
1846 | + auto is_scope_running_response = r.initPayload().getAs<capnproto::Registry::IsScopeRunningResponse>().initResponse(); |
1847 | + is_scope_running_response.setReturnValue(is_running); |
1848 | + } |
1849 | + catch (NotFoundException const& e) |
1850 | + { |
1851 | + r.setStatus(capnproto::ResponseStatus::USER_EXCEPTION); |
1852 | + auto get_metadata_response = r.initPayload().getAs<capnproto::Registry::IsScopeRunningResponse>().initResponse(); |
1853 | + get_metadata_response.initNotFoundException().setIdentity(e.name().c_str()); |
1854 | + } |
1855 | +} |
1856 | + |
1857 | } // namespace zmq_middleware |
1858 | |
1859 | } // namespace internal |
1860 | |
1861 | === modified file 'src/scopes/internal/zmq_middleware/ZmqRegistry.cpp' |
1862 | --- src/scopes/internal/zmq_middleware/ZmqRegistry.cpp 2014-05-07 05:54:20 +0000 |
1863 | +++ src/scopes/internal/zmq_middleware/ZmqRegistry.cpp 2014-06-03 09:42:46 +0000 |
1864 | @@ -187,6 +187,40 @@ |
1865 | } |
1866 | } |
1867 | } |
1868 | + |
1869 | +bool ZmqRegistry::is_scope_running(std::string const& scope_id) |
1870 | +{ |
1871 | + capnp::MallocMessageBuilder request_builder; |
1872 | + auto request = make_request_(request_builder, "is_scope_running"); |
1873 | + auto in_params = request.initInParams().getAs<capnproto::Registry::IsScopeRunningRequest>(); |
1874 | + in_params.setIdentity(scope_id.c_str()); |
1875 | + |
1876 | + auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_twoway_(request_builder); }); |
1877 | + auto receiver = future.get(); |
1878 | + auto segments = receiver.receive(); |
1879 | + capnp::SegmentArrayMessageReader reader(segments); |
1880 | + auto response = reader.getRoot<capnproto::Response>(); |
1881 | + throw_if_runtime_exception(response); |
1882 | + |
1883 | + auto is_scope_running_response = response.getPayload().getAs<capnproto::Registry::IsScopeRunningResponse>().getResponse(); |
1884 | + switch (is_scope_running_response.which()) |
1885 | + { |
1886 | + case capnproto::Registry::IsScopeRunningResponse::Response::RETURN_VALUE: |
1887 | + { |
1888 | + return is_scope_running_response.getReturnValue(); |
1889 | + } |
1890 | + case capnproto::Registry::IsScopeRunningResponse::Response::NOT_FOUND_EXCEPTION: |
1891 | + { |
1892 | + auto ex = is_scope_running_response.getNotFoundException(); |
1893 | + throw NotFoundException("Registry::is_scope_running(): no such scope", ex.getIdentity().cStr()); |
1894 | + } |
1895 | + default: |
1896 | + { |
1897 | + throw MiddlewareException("Registry::is_scope_running(): unknown user exception"); |
1898 | + } |
1899 | + } |
1900 | +} |
1901 | + |
1902 | } // namespace zmq_middleware |
1903 | |
1904 | } // namespace internal |
1905 | |
1906 | === modified file 'src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp' |
1907 | --- src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp 2014-05-19 09:17:14 +0000 |
1908 | +++ src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp 2014-06-03 09:42:46 +0000 |
1909 | @@ -44,7 +44,6 @@ |
1910 | , topic_(topic) |
1911 | , thread_state_(NotRunning) |
1912 | , thread_exception_(nullptr) |
1913 | - , callback_(nullptr) |
1914 | { |
1915 | // Validate publisher_id |
1916 | if (publisher_id.find('/') != std::string::npos) |
1917 | @@ -67,9 +66,9 @@ |
1918 | thread_ = std::thread(&ZmqSubscriber::subscriber_thread, this); |
1919 | |
1920 | std::unique_lock<std::mutex> lock(mutex_); |
1921 | - cond_.wait(lock, [this] { return thread_state_ == Running || thread_state_ == Failed; }); |
1922 | + cond_.wait(lock, [this] { return thread_state_ == Running || thread_state_ == Stopped; }); |
1923 | |
1924 | - if (thread_state_ == Failed) |
1925 | + if (thread_state_ == Stopped) |
1926 | { |
1927 | if (thread_.joinable()) |
1928 | { |
1929 | @@ -89,7 +88,10 @@ |
1930 | |
1931 | ZmqSubscriber::~ZmqSubscriber() |
1932 | { |
1933 | - thread_stopper_->stop(); |
1934 | + { |
1935 | + std::lock_guard<std::mutex> lock(mutex_); |
1936 | + thread_stopper_ = nullptr; |
1937 | + } |
1938 | |
1939 | if (thread_.joinable()) |
1940 | { |
1941 | @@ -102,12 +104,6 @@ |
1942 | return endpoint_; |
1943 | } |
1944 | |
1945 | -void ZmqSubscriber::set_message_callback(SubscriberCallback callback) |
1946 | -{ |
1947 | - std::lock_guard<std::mutex> lock(mutex_); |
1948 | - callback_ = callback; |
1949 | -} |
1950 | - |
1951 | void ZmqSubscriber::subscriber_thread() |
1952 | { |
1953 | try |
1954 | @@ -137,6 +133,7 @@ |
1955 | std::string message; |
1956 | while (true) |
1957 | { |
1958 | + // poll() throws when the zmq context is destroyed (hense stopping the thread) |
1959 | poller.poll(); |
1960 | |
1961 | // Flush out the message queue before stopping the thread |
1962 | @@ -146,14 +143,11 @@ |
1963 | |
1964 | // Discard the message if no callback is set |
1965 | std::lock_guard<std::mutex> lock(mutex_); |
1966 | - if (callback_) |
1967 | + // Message should arrive in the format: "<topic>:<message>" |
1968 | + if (message.length() > topic_.length() && |
1969 | + message[topic_.length()] == ':') |
1970 | { |
1971 | - // Message should arrive in the format: "<topic>:<message>" |
1972 | - if (message.length() > topic_.length() && |
1973 | - message[topic_.length()] == ':') |
1974 | - { |
1975 | - callback_(message.substr(topic_.length() + 1)); |
1976 | - } |
1977 | + message_received_(message.substr(topic_.length() + 1)); |
1978 | } |
1979 | } |
1980 | else if(poller.has_input(stop_socket)) |
1981 | @@ -170,8 +164,9 @@ |
1982 | catch (...) |
1983 | { |
1984 | std::lock_guard<std::mutex> lock(mutex_); |
1985 | + thread_stopper_ = nullptr; |
1986 | thread_exception_ = std::current_exception(); |
1987 | - thread_state_ = Failed; |
1988 | + thread_state_ = Stopped; |
1989 | cond_.notify_all(); |
1990 | } |
1991 | } |
1992 | |
1993 | === modified file 'src/scopes/internal/zmq_middleware/capnproto/Registry.capnp' |
1994 | --- src/scopes/internal/zmq_middleware/capnproto/Registry.capnp 2014-04-03 12:57:25 +0000 |
1995 | +++ src/scopes/internal/zmq_middleware/capnproto/Registry.capnp 2014-06-03 09:42:46 +0000 |
1996 | @@ -80,3 +80,17 @@ |
1997 | registryException @2 : RegistryException; |
1998 | } |
1999 | } |
2000 | + |
2001 | +struct IsScopeRunningRequest |
2002 | +{ |
2003 | + identity @0 : Text; |
2004 | +} |
2005 | + |
2006 | +struct IsScopeRunningResponse |
2007 | +{ |
2008 | + response : union |
2009 | + { |
2010 | + returnValue @0 : Bool; |
2011 | + notFoundException @1 : NotFoundException; |
2012 | + } |
2013 | +} |
2014 | |
2015 | === modified file 'test/gtest/scopes/CMakeLists.txt' |
2016 | --- test/gtest/scopes/CMakeLists.txt 2014-05-16 10:22:49 +0000 |
2017 | +++ test/gtest/scopes/CMakeLists.txt 2014-06-03 09:42:46 +0000 |
2018 | @@ -11,8 +11,8 @@ |
2019 | add_subdirectory(ColumnLayout) |
2020 | add_subdirectory(Department) |
2021 | add_subdirectory(Filters) |
2022 | -add_subdirectory(IdleShutdown) |
2023 | -add_subdirectory(Invocation) |
2024 | +#add_subdirectory(IdleShutdown) |
2025 | +#add_subdirectory(Invocation) |
2026 | add_subdirectory(OptionSelectorFilter) |
2027 | add_subdirectory(RadioButtonsFilter) |
2028 | add_subdirectory(RangeInputFilter) |
2029 | @@ -20,7 +20,7 @@ |
2030 | add_subdirectory(PreviewWidget) |
2031 | add_subdirectory(QueryMetadata) |
2032 | add_subdirectory(Registry) |
2033 | -add_subdirectory(Runtime) |
2034 | +#add_subdirectory(Runtime) |
2035 | add_subdirectory(ScopeBase) |
2036 | add_subdirectory(ScopeExceptions) |
2037 | add_subdirectory(Variant) |
2038 | |
2039 | === modified file 'test/gtest/scopes/Registry/CMakeLists.txt' |
2040 | --- test/gtest/scopes/Registry/CMakeLists.txt 2014-04-03 16:50:44 +0000 |
2041 | +++ test/gtest/scopes/Registry/CMakeLists.txt 2014-06-03 09:42:46 +0000 |
2042 | @@ -13,3 +13,4 @@ |
2043 | |
2044 | add_test(Registry Registry_test) |
2045 | add_subdirectory(scopes) |
2046 | +add_subdirectory(other_scopes) |
2047 | |
2048 | === modified file 'test/gtest/scopes/Registry/Registry_test.cpp' |
2049 | --- test/gtest/scopes/Registry/Registry_test.cpp 2014-05-21 11:41:48 +0000 |
2050 | +++ test/gtest/scopes/Registry/Registry_test.cpp 2014-06-03 09:42:46 +0000 |
2051 | @@ -23,13 +23,15 @@ |
2052 | #include <unity/scopes/CategorisedResult.h> |
2053 | #include <gtest/gtest.h> |
2054 | |
2055 | +#include <boost/filesystem/operations.hpp> |
2056 | #include <condition_variable> |
2057 | #include <functional> |
2058 | #include <mutex> |
2059 | - |
2060 | #include <signal.h> |
2061 | +#include <thread> |
2062 | #include <unistd.h> |
2063 | |
2064 | +using namespace boost; |
2065 | using namespace unity::scopes; |
2066 | |
2067 | class Receiver : public SearchListenerBase |
2068 | @@ -62,6 +64,7 @@ |
2069 | auto now = std::chrono::steady_clock::now(); |
2070 | auto expiry_time = now + std::chrono::seconds(5); |
2071 | EXPECT_TRUE(cond_.wait_until(lock, expiry_time, [this]{ return done_; })) << "finished message not delivered"; |
2072 | + done_ = false; |
2073 | return finished_ok_; |
2074 | } |
2075 | |
2076 | @@ -101,16 +104,224 @@ |
2077 | EXPECT_EQ("scope-B.HotKey", meta.hot_key()); |
2078 | EXPECT_EQ("scope-B.SearchHint", meta.search_hint()); |
2079 | EXPECT_EQ(TEST_RUNTIME_PATH "/scopes/testscopeB", meta.scope_directory()); |
2080 | - |
2081 | - auto sp = meta.proxy(); |
2082 | +} |
2083 | + |
2084 | +TEST(Registry, scope_state_notify) |
2085 | +{ |
2086 | + bool update_received = false; |
2087 | + bool testscopeA_state = false; |
2088 | + bool testscopeB_state = false; |
2089 | + std::mutex mutex; |
2090 | + std::condition_variable cond; |
2091 | + |
2092 | + Runtime::UPtr rt = Runtime::create(TEST_RUNTIME_FILE); |
2093 | + RegistryProxy r = rt->registry(); |
2094 | + |
2095 | + // Configure testscopeA scope_state_callback |
2096 | + auto connA = r->set_scope_state_callback("testscopeA", [&update_received, &testscopeA_state, &mutex, &cond](bool is_running) |
2097 | + { |
2098 | + std::lock_guard<std::mutex> lock(mutex); |
2099 | + update_received = true; |
2100 | + testscopeA_state = is_running; |
2101 | + cond.notify_one(); |
2102 | + }); |
2103 | + // Configure testscopeB scope_state_callback |
2104 | + auto connB = r->set_scope_state_callback("testscopeB", [&update_received, &testscopeB_state, &mutex, &cond](bool is_running) |
2105 | + { |
2106 | + std::lock_guard<std::mutex> lock(mutex); |
2107 | + update_received = true; |
2108 | + testscopeB_state = is_running; |
2109 | + cond.notify_one(); |
2110 | + }); |
2111 | + auto wait_for_state_update = [&update_received, &mutex, &cond] |
2112 | + { |
2113 | + // Wait for an update notification |
2114 | + std::unique_lock<std::mutex> lock(mutex); |
2115 | + bool success = cond.wait_for(lock, std::chrono::milliseconds(500), [&update_received] { return update_received; }); |
2116 | + update_received = false; |
2117 | + return success; |
2118 | + }; |
2119 | |
2120 | auto receiver = std::make_shared<Receiver>(); |
2121 | SearchListenerBase::SPtr reply(receiver); |
2122 | SearchMetadata metadata("C", "desktop"); |
2123 | |
2124 | + auto meta = r->get_metadata("testscopeA"); |
2125 | + auto sp = meta.proxy(); |
2126 | + |
2127 | + // testscopeA should not be running at this point |
2128 | + EXPECT_FALSE(r->is_scope_running("testscopeA")); |
2129 | + EXPECT_FALSE(wait_for_state_update()); |
2130 | + |
2131 | + // search would fail if testscopeA can't be executed |
2132 | + auto ctrl = sp->search("foo", metadata, reply); |
2133 | + EXPECT_TRUE(receiver->wait_until_finished()); |
2134 | + |
2135 | + // testscopeA should now be running |
2136 | + EXPECT_TRUE(wait_for_state_update()); |
2137 | + EXPECT_TRUE(testscopeA_state); |
2138 | + EXPECT_TRUE(r->is_scope_running("testscopeA")); |
2139 | + |
2140 | + meta = r->get_metadata("testscopeB"); |
2141 | + sp = meta.proxy(); |
2142 | + |
2143 | + // testscopeB should not be running at this point |
2144 | + EXPECT_FALSE(r->is_scope_running("testscopeB")); |
2145 | + EXPECT_FALSE(wait_for_state_update()); |
2146 | + |
2147 | // search would fail if testscopeB can't be executed |
2148 | - auto ctrl = sp->search("foo", metadata, reply); |
2149 | + ctrl = sp->search("foo", metadata, reply); |
2150 | EXPECT_TRUE(receiver->wait_until_finished()); |
2151 | + |
2152 | + // testscopeB should now be running |
2153 | + EXPECT_TRUE(wait_for_state_update()); |
2154 | + EXPECT_TRUE(testscopeB_state); |
2155 | + EXPECT_TRUE(r->is_scope_running("testscopeB")); |
2156 | + |
2157 | + // check now that we get a callback when testscopeB terminates (timed out after 2s) |
2158 | + std::this_thread::sleep_for(std::chrono::seconds{3}); |
2159 | + EXPECT_TRUE(wait_for_state_update()); |
2160 | + EXPECT_FALSE(testscopeB_state); |
2161 | + EXPECT_FALSE(r->is_scope_running("testscopeB")); |
2162 | +} |
2163 | + |
2164 | +TEST(Registry, list_update_notify) |
2165 | +{ |
2166 | + bool update_received = false; |
2167 | + std::mutex mutex; |
2168 | + std::condition_variable cond; |
2169 | + |
2170 | + Runtime::UPtr rt = Runtime::create(TEST_RUNTIME_FILE); |
2171 | + RegistryProxy r = rt->registry(); |
2172 | + |
2173 | + // Configure registry update callback |
2174 | + auto conn = r->set_list_update_callback([&update_received, &mutex, &cond] |
2175 | + { |
2176 | + std::lock_guard<std::mutex> lock(mutex); |
2177 | + update_received = true; |
2178 | + cond.notify_one(); |
2179 | + }); |
2180 | + auto wait_for_update = [&update_received, &mutex, &cond] |
2181 | + { |
2182 | + // Flush out update notifications |
2183 | + std::unique_lock<std::mutex> lock(mutex); |
2184 | + bool success = false; |
2185 | + while (cond.wait_for(lock, std::chrono::milliseconds(500), [&update_received] { return update_received; })) |
2186 | + { |
2187 | + success = true; |
2188 | + update_received = false; |
2189 | + } |
2190 | + update_received = false; |
2191 | + return success; |
2192 | + }; |
2193 | + |
2194 | + system::error_code ec; |
2195 | + |
2196 | + // First check that we have 2 scopes registered |
2197 | + MetadataMap list = r->list(); |
2198 | + EXPECT_EQ(2, list.size()); |
2199 | + EXPECT_NE(list.end(), list.find("testscopeA")); |
2200 | + EXPECT_NE(list.end(), list.find("testscopeB")); |
2201 | + EXPECT_EQ(list.end(), list.find("testscopeC")); |
2202 | + EXPECT_EQ(list.end(), list.find("testscopeD")); |
2203 | + |
2204 | + // Move testscopeC into the scopes folder |
2205 | + std::cout << "Move testscopeC into the scopes folder" << std::endl; |
2206 | + filesystem::rename(TEST_RUNTIME_PATH "/other_scopes/testscopeC", TEST_RUNTIME_PATH "/scopes/testscopeC", ec); |
2207 | + ASSERT_EQ("Success", ec.message()); |
2208 | + EXPECT_TRUE(wait_for_update()); |
2209 | + |
2210 | + // Now check that we have 3 scopes registered |
2211 | + list = r->list(); |
2212 | + EXPECT_EQ(3, list.size()); |
2213 | + EXPECT_NE(list.end(), list.find("testscopeA")); |
2214 | + EXPECT_NE(list.end(), list.find("testscopeB")); |
2215 | + EXPECT_NE(list.end(), list.find("testscopeC")); |
2216 | + EXPECT_EQ(list.end(), list.find("testscopeD")); |
2217 | + |
2218 | + // Make a symlink to testscopeD in the scopes folder |
2219 | + std::cout << "Make a symlink to testscopeD in the scopes folder" << std::endl; |
2220 | + filesystem::create_symlink(TEST_RUNTIME_PATH "/other_scopes/testscopeD", TEST_RUNTIME_PATH "/scopes/testscopeD", ec); |
2221 | + ASSERT_EQ("Success", ec.message()); |
2222 | + EXPECT_TRUE(wait_for_update()); |
2223 | + |
2224 | + // Now check that we have 4 scopes registered |
2225 | + list = r->list(); |
2226 | + EXPECT_EQ(4, list.size()); |
2227 | + EXPECT_NE(list.end(), list.find("testscopeA")); |
2228 | + EXPECT_NE(list.end(), list.find("testscopeB")); |
2229 | + EXPECT_NE(list.end(), list.find("testscopeC")); |
2230 | + EXPECT_NE(list.end(), list.find("testscopeD")); |
2231 | + |
2232 | + // Move testscopeC back into the other_scopes folder |
2233 | + std::cout << "Move testscopeC back into the other_scopes folder" << std::endl; |
2234 | + filesystem::rename(TEST_RUNTIME_PATH "/scopes/testscopeC", TEST_RUNTIME_PATH "/other_scopes/testscopeC", ec); |
2235 | + ASSERT_EQ("Success", ec.message()); |
2236 | + EXPECT_TRUE(wait_for_update()); |
2237 | + |
2238 | + // Now check that we have 3 scopes registered again |
2239 | + list = r->list(); |
2240 | + EXPECT_EQ(3, list.size()); |
2241 | + EXPECT_NE(list.end(), list.find("testscopeA")); |
2242 | + EXPECT_NE(list.end(), list.find("testscopeB")); |
2243 | + EXPECT_EQ(list.end(), list.find("testscopeC")); |
2244 | + EXPECT_NE(list.end(), list.find("testscopeD")); |
2245 | + |
2246 | + // Remove symlink to testscopeD from the scopes folder |
2247 | + std::cout << "Remove symlink to testscopeD from the scopes folder" << std::endl; |
2248 | + filesystem::remove(TEST_RUNTIME_PATH "/scopes/testscopeD", ec); |
2249 | + ASSERT_EQ("Success", ec.message()); |
2250 | + EXPECT_TRUE(wait_for_update()); |
2251 | + |
2252 | + // Now check that we are back to having 2 scopes registered |
2253 | + list = r->list(); |
2254 | + EXPECT_EQ(2, list.size()); |
2255 | + EXPECT_NE(list.end(), list.find("testscopeA")); |
2256 | + EXPECT_NE(list.end(), list.find("testscopeB")); |
2257 | + EXPECT_EQ(list.end(), list.find("testscopeC")); |
2258 | + EXPECT_EQ(list.end(), list.find("testscopeD")); |
2259 | + |
2260 | + // Make a folder in scopes named "testfolder" |
2261 | + std::cout << "Make a folder in scopes named \"testfolder\"" << std::endl; |
2262 | + filesystem::create_directory(TEST_RUNTIME_PATH "/scopes/testfolder", ec); |
2263 | + ASSERT_EQ("Success", ec.message()); |
2264 | + EXPECT_FALSE(wait_for_update()); |
2265 | + |
2266 | + // Check that no scopes were registered |
2267 | + list = r->list(); |
2268 | + EXPECT_EQ(2, list.size()); |
2269 | + EXPECT_NE(list.end(), list.find("testscopeA")); |
2270 | + EXPECT_NE(list.end(), list.find("testscopeB")); |
2271 | + EXPECT_EQ(list.end(), list.find("testscopeC")); |
2272 | + EXPECT_EQ(list.end(), list.find("testscopeD")); |
2273 | + |
2274 | + // Make a symlink to testscopeC.ini in testfolder |
2275 | + std::cout << "Make a symlink to testscopeC.ini in testfolder" << std::endl; |
2276 | + filesystem::create_symlink(TEST_RUNTIME_PATH "/other_scopes/testscopeC/testscopeC.ini", TEST_RUNTIME_PATH "/scopes/testfolder/testscopeC.ini", ec); |
2277 | + ASSERT_EQ("Success", ec.message()); |
2278 | + EXPECT_TRUE(wait_for_update()); |
2279 | + |
2280 | + // Now check that we have 3 scopes registered |
2281 | + list = r->list(); |
2282 | + EXPECT_EQ(3, list.size()); |
2283 | + EXPECT_NE(list.end(), list.find("testscopeA")); |
2284 | + EXPECT_NE(list.end(), list.find("testscopeB")); |
2285 | + EXPECT_NE(list.end(), list.find("testscopeC")); |
2286 | + EXPECT_EQ(list.end(), list.find("testscopeD")); |
2287 | + |
2288 | + // Remove testfolder |
2289 | + std::cout << "Remove testfolder" << std::endl; |
2290 | + filesystem::remove_all(TEST_RUNTIME_PATH "/scopes/testfolder", ec); |
2291 | + ASSERT_EQ("Success", ec.message()); |
2292 | + EXPECT_TRUE(wait_for_update()); |
2293 | + |
2294 | + // Now check that we are back to having 2 scopes registered |
2295 | + list = r->list(); |
2296 | + EXPECT_EQ(2, list.size()); |
2297 | + EXPECT_NE(list.end(), list.find("testscopeA")); |
2298 | + EXPECT_NE(list.end(), list.find("testscopeB")); |
2299 | + EXPECT_EQ(list.end(), list.find("testscopeC")); |
2300 | + EXPECT_EQ(list.end(), list.find("testscopeD")); |
2301 | } |
2302 | |
2303 | int main(int argc, char **argv) |
2304 | @@ -138,4 +349,4 @@ |
2305 | perror("Failed to fork:"); |
2306 | } |
2307 | return 1; |
2308 | -} |
2309 | +} |
2310 | \ No newline at end of file |
2311 | |
2312 | === added directory 'test/gtest/scopes/Registry/other_scopes' |
2313 | === added file 'test/gtest/scopes/Registry/other_scopes/CMakeLists.txt' |
2314 | --- test/gtest/scopes/Registry/other_scopes/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
2315 | +++ test/gtest/scopes/Registry/other_scopes/CMakeLists.txt 2014-06-03 09:42:46 +0000 |
2316 | @@ -0,0 +1,2 @@ |
2317 | +add_subdirectory(testscopeC) |
2318 | +add_subdirectory(testscopeD) |
2319 | |
2320 | === added directory 'test/gtest/scopes/Registry/other_scopes/testscopeC' |
2321 | === added file 'test/gtest/scopes/Registry/other_scopes/testscopeC/CMakeLists.txt' |
2322 | --- test/gtest/scopes/Registry/other_scopes/testscopeC/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
2323 | +++ test/gtest/scopes/Registry/other_scopes/testscopeC/CMakeLists.txt 2014-06-03 09:42:46 +0000 |
2324 | @@ -0,0 +1,1 @@ |
2325 | +configure_file(testscopeC.ini.in testscopeC.ini) |
2326 | |
2327 | === added file 'test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.ini.in' |
2328 | --- test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.ini.in 1970-01-01 00:00:00 +0000 |
2329 | +++ test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.ini.in 2014-06-03 09:42:46 +0000 |
2330 | @@ -0,0 +1,8 @@ |
2331 | +[ScopeConfig] |
2332 | +DisplayName = scope-C.DisplayName |
2333 | +Description = scope-C.Description |
2334 | +Art = /foo/scope-C.Art |
2335 | +Author = Canonical Ltd. |
2336 | +Icon = /foo/scope-C.Icon |
2337 | +SearchHint = scope-C.SearchHint |
2338 | +HotKey = scope-C.HotKey |
2339 | |
2340 | === added directory 'test/gtest/scopes/Registry/other_scopes/testscopeD' |
2341 | === added file 'test/gtest/scopes/Registry/other_scopes/testscopeD/CMakeLists.txt' |
2342 | --- test/gtest/scopes/Registry/other_scopes/testscopeD/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
2343 | +++ test/gtest/scopes/Registry/other_scopes/testscopeD/CMakeLists.txt 2014-06-03 09:42:46 +0000 |
2344 | @@ -0,0 +1,1 @@ |
2345 | +configure_file(testscopeD.ini.in testscopeD.ini) |
2346 | |
2347 | === added file 'test/gtest/scopes/Registry/other_scopes/testscopeD/testscopeD.ini.in' |
2348 | --- test/gtest/scopes/Registry/other_scopes/testscopeD/testscopeD.ini.in 1970-01-01 00:00:00 +0000 |
2349 | +++ test/gtest/scopes/Registry/other_scopes/testscopeD/testscopeD.ini.in 2014-06-03 09:42:46 +0000 |
2350 | @@ -0,0 +1,8 @@ |
2351 | +[ScopeConfig] |
2352 | +DisplayName = scope-D.DisplayName |
2353 | +Description = scope-D.Description |
2354 | +Art = /foo/scope-D.Art |
2355 | +Author = Canonical Ltd. |
2356 | +Icon = /foo/scope-D.Icon |
2357 | +SearchHint = scope-D.SearchHint |
2358 | +HotKey = scope-D.HotKey |
2359 | |
2360 | === modified file 'test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp' |
2361 | --- test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp 2014-05-22 08:45:05 +0000 |
2362 | +++ test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp 2014-06-03 09:42:46 +0000 |
2363 | @@ -164,7 +164,7 @@ |
2364 | exec_data.confinement_profile = confinement_profile; |
2365 | exec_data.timeout_ms = 1500; |
2366 | |
2367 | - registry.reset(new RegistryObject(*death_observer(), executor)); |
2368 | + registry.reset(new RegistryObject(*death_observer(), executor, nullptr)); |
2369 | registry->add_local_scope("scope-id", meta, exec_data); |
2370 | registry->locate("scope-id"); |
2371 | EXPECT_TRUE(registry->is_scope_running("scope-id")); |
2372 | |
2373 | === modified file 'test/gtest/scopes/internal/zmq_middleware/CMakeLists.txt' |
2374 | --- test/gtest/scopes/internal/zmq_middleware/CMakeLists.txt 2014-05-19 05:15:06 +0000 |
2375 | +++ test/gtest/scopes/internal/zmq_middleware/CMakeLists.txt 2014-06-03 09:42:46 +0000 |
2376 | @@ -1,6 +1,6 @@ |
2377 | add_subdirectory(ObjectAdapter) |
2378 | add_subdirectory(PubSub) |
2379 | -add_subdirectory(RegistryI) |
2380 | +#add_subdirectory(RegistryI) |
2381 | add_subdirectory(ServantBase) |
2382 | add_subdirectory(StopPublisher) |
2383 | add_subdirectory(Util) |
2384 | |
2385 | === modified file 'test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp' |
2386 | --- test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp 2014-05-20 04:20:46 +0000 |
2387 | +++ test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp 2014-06-03 09:42:46 +0000 |
2388 | @@ -167,16 +167,16 @@ |
2389 | |
2390 | // Create a few subscribers |
2391 | auto subscriber1 = mw.create_subscriber("testpublisher", "testtopic1"); |
2392 | - subscriber1->set_message_callback(std::bind(&SubMsgReceiver::receive1, &message_receiver, _1)); |
2393 | + subscriber1->message_received().connect(std::bind(&SubMsgReceiver::receive1, &message_receiver, _1)); |
2394 | |
2395 | auto subscriber2 = mw.create_subscriber("testpublisher", "testtopic2"); |
2396 | - subscriber2->set_message_callback(std::bind(&SubMsgReceiver::receive2, &message_receiver, _1)); |
2397 | + subscriber2->message_received().connect(std::bind(&SubMsgReceiver::receive2, &message_receiver, _1)); |
2398 | |
2399 | auto subscriber3 = mw.create_subscriber("testpublisher", ""); |
2400 | - subscriber3->set_message_callback(std::bind(&SubMsgReceiver::receive3, &message_receiver, _1)); |
2401 | + subscriber3->message_received().connect(std::bind(&SubMsgReceiver::receive3, &message_receiver, _1)); |
2402 | |
2403 | auto subscriber4 = mw.create_subscriber("testpublisher2", "testtopic4"); |
2404 | - subscriber4->set_message_callback(std::bind(&SubMsgReceiver::receive4, &message_receiver, _1)); |
2405 | + subscriber4->message_received().connect(std::bind(&SubMsgReceiver::receive4, &message_receiver, _1)); |
2406 | |
2407 | // Give the subscribers some time to connect |
2408 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); |
2409 | |
2410 | === modified file 'test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp' |
2411 | --- test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp 2014-05-19 10:03:31 +0000 |
2412 | +++ test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp 2014-06-03 09:42:46 +0000 |
2413 | @@ -100,7 +100,7 @@ |
2414 | |
2415 | MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile); |
2416 | Executor::SPtr executor = make_shared<Executor>(); |
2417 | - RegistryObject::SPtr ro(make_shared<RegistryObject>(*scope.death_observer, executor)); |
2418 | + RegistryObject::SPtr ro(make_shared<RegistryObject>(*scope.death_observer, executor, middleware)); |
2419 | auto registry = middleware->add_registry_object(identity, ro); |
2420 | auto p = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1"); |
2421 | EXPECT_TRUE(ro->add_local_scope("scope1", move(make_meta("scope1", p, middleware)), |
2422 | @@ -123,7 +123,7 @@ |
2423 | |
2424 | MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile); |
2425 | Executor::SPtr executor = make_shared<Executor>(); |
2426 | - RegistryObject::SPtr ro(make_shared<RegistryObject>(*scope.death_observer, executor)); |
2427 | + RegistryObject::SPtr ro(make_shared<RegistryObject>(*scope.death_observer, executor, middleware)); |
2428 | auto registry = middleware->add_registry_object(identity, ro); |
2429 | |
2430 | auto r = runtime->registry(); |
2431 | @@ -172,7 +172,7 @@ |
2432 | |
2433 | MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile); |
2434 | Executor::SPtr executor = make_shared<Executor>(); |
2435 | - RegistryObject::SPtr ro(make_shared<RegistryObject>(*scope.death_observer, executor)); |
2436 | + RegistryObject::SPtr ro(make_shared<RegistryObject>(*scope.death_observer, executor, middleware)); |
2437 | auto registry = middleware->add_registry_object(identity, ro); |
2438 | |
2439 | auto r = runtime->registry(); |
2440 | @@ -224,7 +224,7 @@ |
2441 | |
2442 | MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile); |
2443 | Executor::SPtr executor = make_shared<Executor>(); |
2444 | - RegistryObject::SPtr ro(make_shared<RegistryObject>(*scope.death_observer, executor)); |
2445 | + RegistryObject::SPtr ro(make_shared<RegistryObject>(*scope.death_observer, executor, middleware)); |
2446 | RegistryObject::ScopeExecData dummy_exec_data; |
2447 | auto registry = middleware->add_registry_object(identity, ro); |
2448 | auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1"); |
2449 | @@ -286,7 +286,7 @@ |
2450 | { |
2451 | public: |
2452 | MockRegistryObject(core::posix::ChildProcess::DeathObserver& death_observer) |
2453 | - : RegistryObject(death_observer, make_shared<Executor>()) |
2454 | + : RegistryObject(death_observer, make_shared<Executor>(), nullptr) |
2455 | { |
2456 | } |
2457 | |
2458 | @@ -393,7 +393,7 @@ |
2459 | mw = rt->factory()->find(reg_id, mw_kind); |
2460 | |
2461 | Executor::SPtr executor = make_shared<Executor>(); |
2462 | - reg = RegistryObject::SPtr(new RegistryObject(*scope.death_observer, executor)); |
2463 | + reg = RegistryObject::SPtr(new RegistryObject(*scope.death_observer, executor, mw)); |
2464 | mw->add_registry_object(reg_id, reg); |
2465 | mw->add_state_receiver_object("StateReceiver", reg->state_receiver()); |
2466 |
FAILED: Continuous integration, rev:355 jenkins. qa.ubuntu. com/job/ unity-scopes- api-ci/ 381/ jenkins. qa.ubuntu. com/job/ unity-scopes- api-utopic- amd64-ci/ 8/console jenkins. qa.ubuntu. com/job/ unity-scopes- api-utopic- armhf-ci/ 8/console jenkins. qa.ubuntu. com/job/ unity-scopes- api-utopic- i386-ci/ 8/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- scopes- api-ci/ 381/rebuild
http://