Merge lp:~marcustomlinson/unity-scopes-api/switch-to-net-cpp into lp:unity-scopes-api
- switch-to-net-cpp
- Merge into trunk
Status: | Superseded | ||||||||
---|---|---|---|---|---|---|---|---|---|
Proposed branch: | lp:~marcustomlinson/unity-scopes-api/switch-to-net-cpp | ||||||||
Merge into: | lp:unity-scopes-api | ||||||||
Prerequisite: | lp:~marcustomlinson/unity-scopes-api/lp-1410125 | ||||||||
Diff against target: |
1440 lines (+380/-716) 19 files modified
CMakeLists.txt (+27/-47) debian/control (+24/-19) include/unity/scopes/OnlineAccountClient.h (+1/-1) include/unity/scopes/internal/smartscopes/HttpClientInterface.h (+1/-1) include/unity/scopes/internal/smartscopes/HttpClientNetCpp.h (+78/-0) include/unity/scopes/internal/smartscopes/HttpClientQt.h (+0/-91) include/unity/scopes/internal/smartscopes/HttpClientQtThread.h (+0/-100) src/scopes/internal/JsonCppNode.cpp (+4/-4) src/scopes/internal/RegistryObject.cpp (+1/-1) src/scopes/internal/smartscopes/CMakeLists.txt (+2/-31) src/scopes/internal/smartscopes/HttpClientNetCpp.cpp (+189/-0) src/scopes/internal/smartscopes/HttpClientQt.cpp (+0/-151) src/scopes/internal/smartscopes/HttpClientQtThread.cpp (+0/-186) src/scopes/internal/smartscopes/SSRegistryObject.cpp (+2/-2) src/scopes/internal/smartscopes/SmartScopesClient.cpp (+41/-30) test/gtest/scopes/internal/smartscopes/HttpClient/HttpClient_test.cpp (+3/-3) test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeSss.py (+4/-1) test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp (+3/-2) valgrind-suppress (+0/-46) |
||||||||
To merge this branch: | bzr merge lp:~marcustomlinson/unity-scopes-api/switch-to-net-cpp | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michi Henning (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Review via email: mp+246538@code.launchpad.net |
This proposal has been superseded by a proposal from 2015-01-20.
Commit message
Switch from QNetwork to net-cpp
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
Michi Henning (michihenning) wrote : | # |
Looks good, thanks!
A few minor quibbles:
Please don't use uint anywhere. It's not a C++ type, and whether it works or not depends on whether some random header happens to drag in sys/types.h. Use unsigned int instead. (uint also causes warnings from doxygen when building the developer doc because it ends up not being able to match the signature in some cases.)
And, as an aside, try to not use unsigneds at all. They are evil. (See John Lakos for a really good explanation.)
76 + explicit HttpClientNetCp
86 + void cancel_get(uint session_id) override;
88 + uint no_reply_timeout;
416 + std::pair<uint, std::shared_
424 + uint add(const std::shared_
428 + uint result{
435 + void cancel_
448 + uint request_id{0};
450 + std::unordered_
454 +HttpClientNetC
529 +void HttpClientNetCp
923 HttpClientTest(uint no_reply_timeout = 20000)
It would be good to ditch the static library for smartscopes, I don't think we need it anymore.
While you are working on this anyway, would you mind making the lineData lambda thread-safe? At the moment, it appends to the string from a different thread without a lock.
Also, the lineData param should be called line_data instead.
Minor style issue here:
506 + } else
507 + {
And here (missing curlies):
465 + if (worker.joinable())
466 + worker.join();
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:188
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michi Henning (michihenning) wrote : | # |
Thanks for that!
One request (please forgive me for being anal):
10 +find_library(
11 +if(NOT ZMQPPLIB)
12 + message(FATAL_ERROR "Zmqpp lib not found.")
13 +endif()
I think this is nice. Without this, cmake says:
CMake Error at CMakeLists.txt:122 (message):
Capnp compiler not found.
But it would be a *lot* nicer if it actually told me the package name instead of "Zmqpp lib not found".
I can't count the number of times where some sort of install script told me that command "foo" or library "libxyz" couldn't be found, and then I have to spend five minutes trying to figure out which package bloody "foo" or "libxyz" can be found in.
So, I'd change the error messages to actually spell out the package name "package capnproto not found". That way, I can just copy and paste: "apt-get install capnproto" and Bob's my uncle :-)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:189
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Marcus Tomlinson (marcustomlinson) wrote : | # |
> Thanks for that!
>
> One request (please forgive me for being anal):
>
> 10 +find_library(
> 11 +if(NOT ZMQPPLIB)
> 12 + message(FATAL_ERROR "Zmqpp lib not found.")
> 13 +endif()
>
> I think this is nice. Without this, cmake says:
>
> CMake Error at CMakeLists.txt:122 (message):
> Capnp compiler not found.
>
> But it would be a *lot* nicer if it actually told me the package name instead
> of "Zmqpp lib not found".
>
> I can't count the number of times where some sort of install script told me
> that command "foo" or library "libxyz" couldn't be found, and then I have to
> spend five minutes trying to figure out which package bloody "foo" or "libxyz"
> can be found in.
>
> So, I'd change the error messages to actually spell out the package name
> "package capnproto not found". That way, I can just copy and paste: "apt-get
> install capnproto" and Bob's my uncle :-)
k, done
Michi Henning (michihenning) wrote : | # |
Thanks for that, and thanks for your diligence!
Michi Henning (michihenning) wrote : | # |
Not sure what was broken with Jenkins last time around. Top-approving to see what happens.
Marcus Tomlinson (marcustomlinson) wrote : | # |
Fixed some small stupid mistakes (191 and 192), top approving again
- 193. By Marcus Tomlinson
-
Merged trunk and resolved conflicts
- 194. By Marcus Tomlinson
-
Merged fix-cross-wrap and resolved conflict
- 195. By Marcus Tomlinson
-
Fixed formatting in control
Unmerged revisions
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2015-01-19 08:08:55 +0000 |
3 | +++ CMakeLists.txt 2015-01-20 09:09:48 +0000 |
4 | @@ -67,9 +67,30 @@ |
5 | pkg_check_modules(LTTNG_UST lttng-ust REQUIRED) |
6 | pkg_check_modules(LIBURCU_BP liburcu-bp REQUIRED) |
7 | pkg_check_modules(JSONCPP jsoncpp REQUIRED) |
8 | -pkg_check_modules(LIBACCOUNTS REQUIRED libaccounts-glib) |
9 | -pkg_check_modules(LIBSIGNON REQUIRED libsignon-glib) |
10 | +pkg_check_modules(LIBACCOUNTS libaccounts-glib REQUIRED) |
11 | +pkg_check_modules(LIBSIGNON libsignon-glib REQUIRED) |
12 | pkg_check_modules(ZMQLIB libzmq REQUIRED) |
13 | +pkg_check_modules(NET_CPP net-cpp REQUIRED) |
14 | + |
15 | +find_library(ZMQPPLIB zmqpp) |
16 | +if(NOT ZMQPPLIB) |
17 | + message(FATAL_ERROR "libzmqpp-dev not found.") |
18 | +endif() |
19 | + |
20 | +find_library(CAPNPLIB capnp) |
21 | +if(NOT CAPNPLIB) |
22 | + message(FATAL_ERROR "libcapnp-dev not found.") |
23 | +endif() |
24 | + |
25 | +find_library(KJLIB kj) |
26 | +if(NOT KJLIB) |
27 | + message(FATAL_ERROR "capnproto not found.") |
28 | +endif() |
29 | + |
30 | +find_library(DLLIB dl) |
31 | +if(NOT DLLIB) |
32 | + message(FATAL_ERROR "dl lib not found.") |
33 | +endif() |
34 | |
35 | find_program(LTTNG_EXECUTABLE lttng) |
36 | if (NOT LTTNG_EXECUTABLE) |
37 | @@ -118,8 +139,10 @@ |
38 | |
39 | set(OTHER_INCLUDE_DIRS ${OTHER_INCLUDE_DIRS} ${UNITY_API_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} |
40 | ${JSONCPP_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS} ${APPARMOR_INCLUDE_DIRS} |
41 | - ${LIBACCOUNTS_INCLUDE_DIRS} ${LIBSIGNON_INCLUDE_DIRS}) |
42 | -set(OTHER_LIBS ${OTHER_LIBS} ${UNITY_API_LDFLAGS} ${APPARMOR_LDFLAGS} ${LIBACCOUNTS_LIBRARIES} ${LIBSIGNON_LIBRARIES}) |
43 | + ${LIBACCOUNTS_INCLUDE_DIRS} ${LIBSIGNON_INCLUDE_DIRS} ${NET_CPP_INCLUDE_DIRS}) |
44 | +set(OTHER_LIBS ${OTHER_LIBS} ${UNITY_API_LDFLAGS} ${APPARMOR_LDFLAGS} ${LIBACCOUNTS_LIBRARIES} |
45 | + ${LIBSIGNON_LIBRARIES} ${Boost_LIBRARIES} ${JSONCPP_LDFLAGS} ${PROCESS_CPP_LDFLAGS} |
46 | + ${ZMQPPLIB} ${ZMQLIB_LDFLAGS} ${CAPNPLIB} ${KJLIB} ${DLLIB} ${NET_CPP_LDFLAGS} pthread) |
47 | |
48 | # Standard install paths |
49 | include(GNUInstallDirs) |
50 | @@ -207,49 +230,6 @@ |
51 | # Version for testing, with all symbols visible |
52 | set(UNITY_SCOPES_TEST_LIB ${UNITY_SCOPES_LIB}-test) |
53 | |
54 | -find_library(ZMQPPLIB zmqpp) |
55 | -if(NOT ZMQPPLIB) |
56 | - message(FATAL_ERROR "Zmqpp lib not found.") |
57 | -endif() |
58 | - |
59 | -find_library(CAPNPLIB capnp) |
60 | -if(NOT CAPNPLIB) |
61 | - message(FATAL_ERROR "Cap'n Proto lib not found.") |
62 | -endif() |
63 | - |
64 | -find_library(KJLIB kj) |
65 | -if(NOT KJLIB) |
66 | - message(FATAL_ERROR "Kj lib not found.") |
67 | -endif() |
68 | - |
69 | -find_library(DLLIB dl) |
70 | -if(NOT DLLIB) |
71 | - message(FATAL_ERROR "Dl lib not found.") |
72 | -endif() |
73 | - |
74 | - |
75 | -# Stop complaints during the generation phase about executables depending |
76 | -# on Qt5::Core and Qt5::Network. They are bogus because only |
77 | -# only smartscopes uses these. |
78 | -if(POLICY CMP0028) |
79 | - cmake_policy(SET CMP0028 OLD) |
80 | -endif() |
81 | - |
82 | -# Other libraries we depend on |
83 | -set(OTHER_LIBS |
84 | - ${OTHER_LIBS} |
85 | - ${Boost_LIBRARIES} |
86 | - ${JSONCPP_LDFLAGS} |
87 | - ${PROCESS_CPP_LDFLAGS} |
88 | - ${ZMQPPLIB} |
89 | - ${ZMQLIB_LDFLAGS} |
90 | - ${CAPNPLIB} |
91 | - ${KJLIB} |
92 | - ${DLLIB} |
93 | - pthread |
94 | - smartscopes |
95 | -) |
96 | - |
97 | # All the libraries we need to link a normal executable that uses Unity scopes |
98 | set(LIBS ${UNITY_SCOPES_LIB}) |
99 | |
100 | |
101 | === modified file 'debian/control' |
102 | --- debian/control 2014-11-18 07:04:04 +0000 |
103 | +++ debian/control 2015-01-20 09:09:48 +0000 |
104 | @@ -1,34 +1,39 @@ |
105 | Source: unity-scopes-api |
106 | Priority: optional |
107 | Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> |
108 | -Build-Depends: g++-4.9, |
109 | - debhelper (>= 9), |
110 | +Build-Depends: capnproto, |
111 | click-dev (>= 0.2.2), |
112 | cmake, |
113 | + dbus-test-runner, |
114 | + debhelper (>= 9), |
115 | doxygen, |
116 | +# We rely on C++11 features, and to prevent from ABI breaks |
117 | +# in libstdc++ causing us issues, we explicitly select a G++ |
118 | +# version. To allow cross-compiling to work, we also must |
119 | +# append :native to g++-4.9 so we don't try to run armhf g++ |
120 | +# on an x86 CPU for example, when cross-compiling. |
121 | + g++-4.9:native, |
122 | google-mock, |
123 | graphviz, |
124 | - pkg-config, |
125 | - python3:any, |
126 | - capnproto, |
127 | + libaccounts-glib-dev, |
128 | libapparmor-dev, |
129 | - libprocess-cpp-dev (>= 1.0.1), |
130 | - libunity-api-dev (>= 7.80.7~), |
131 | libboost-filesystem-dev, |
132 | + libboost-log-dev, |
133 | libboost-regex-dev, |
134 | libboost-serialization-dev, |
135 | - libboost-log-dev, |
136 | libcapnp-dev (>= 0.4.0), |
137 | + libdbustest1-dev, |
138 | + libjsoncpp-dev, |
139 | + liblttng-ust-dev, |
140 | + libnet-cpp-dev, |
141 | + libprocess-cpp-dev (>= 1.0.1), |
142 | + libsignon-glib-dev, |
143 | + libunity-api-dev (>= 7.80.7~), |
144 | libzmq3-dev, |
145 | libzmqpp-dev, |
146 | - liblttng-ust-dev, |
147 | lttng-tools, |
148 | - qtbase5-dev, |
149 | - libjsoncpp-dev, |
150 | - libaccounts-glib-dev, |
151 | - libsignon-glib-dev, |
152 | - dbus-test-runner, |
153 | - libdbustest1-dev, |
154 | + pkg-config, |
155 | + python3:any, |
156 | valgrind, |
157 | Standards-Version: 3.9.5 |
158 | XS-Testsuite: autopkgtest |
159 | @@ -45,7 +50,7 @@ |
160 | Multi-Arch: same |
161 | Pre-Depends: ${misc:Pre-Depends}, |
162 | Depends: ${misc:Depends}, |
163 | - ${shlibs:Depends} |
164 | + ${shlibs:Depends}, |
165 | Replaces: libunity-scopes0, |
166 | libunity-scopes1, |
167 | libunity-scopes2, |
168 | @@ -60,9 +65,9 @@ |
169 | Architecture: any |
170 | Multi-Arch: same |
171 | Pre-Depends: ${misc:Pre-Depends}, |
172 | -Depends: libunity-scopes3 (= ${binary:Version}), |
173 | - libproperties-cpp-dev, |
174 | +Depends: libproperties-cpp-dev, |
175 | libunity-api-dev, |
176 | + libunity-scopes3 (= ${binary:Version}), |
177 | ${misc:Depends}, |
178 | Description: Header files for Unity scopes API |
179 | Library to integrate scopes with the Unity shell (dev files) |
180 | @@ -73,8 +78,8 @@ |
181 | Multi-Arch: foreign |
182 | Pre-Depends: ${misc:Pre-Depends}, |
183 | Depends: libunity-scopes3 (= ${binary:Version}), |
184 | + ${misc:Depends}, |
185 | ${shlibs:Depends}, |
186 | - ${misc:Depends}, |
187 | Description: Client utility for Unity scopes API |
188 | Commandline client utility for querying Unity scopes, useful for testing. |
189 | |
190 | |
191 | === modified file 'include/unity/scopes/OnlineAccountClient.h' |
192 | --- include/unity/scopes/OnlineAccountClient.h 2014-11-03 05:31:30 +0000 |
193 | +++ include/unity/scopes/OnlineAccountClient.h 2015-01-20 09:09:48 +0000 |
194 | @@ -59,7 +59,7 @@ |
195 | */ |
196 | struct ServiceStatus |
197 | { |
198 | - uint account_id; ///< A unique ID of the online account parenting this service. |
199 | + unsigned int account_id; ///< A unique ID of the online account parenting this service. |
200 | bool service_enabled; ///< True if this service is enabled. |
201 | bool service_authenticated; ///< True if this service is authenticated. |
202 | std::string client_id; ///< "ConsumerKey" / "ClientId" OAuth (1 / 2) parameter. |
203 | |
204 | === modified file 'include/unity/scopes/internal/smartscopes/HttpClientInterface.h' |
205 | --- include/unity/scopes/internal/smartscopes/HttpClientInterface.h 2014-11-03 05:31:30 +0000 |
206 | +++ include/unity/scopes/internal/smartscopes/HttpClientInterface.h 2015-01-20 09:09:48 +0000 |
207 | @@ -53,7 +53,7 @@ |
208 | virtual ~HttpClientInterface() = default; |
209 | |
210 | virtual std::shared_ptr<HttpResponseHandle> get(std::string const& request_url, |
211 | - std::function<void(std::string const&)> const& lineData = [](std::string const&) {}, |
212 | + std::function<void(std::string const&)> const& line_data = [](std::string const&) {}, |
213 | HttpHeaders const& headers = HttpHeaders()) = 0; |
214 | |
215 | virtual std::string to_percent_encoding(std::string const& string) = 0; |
216 | |
217 | === added file 'include/unity/scopes/internal/smartscopes/HttpClientNetCpp.h' |
218 | --- include/unity/scopes/internal/smartscopes/HttpClientNetCpp.h 1970-01-01 00:00:00 +0000 |
219 | +++ include/unity/scopes/internal/smartscopes/HttpClientNetCpp.h 2015-01-20 09:09:48 +0000 |
220 | @@ -0,0 +1,78 @@ |
221 | +/* |
222 | + * Copyright (C) 2013 Canonical Ltd |
223 | + * |
224 | + * This program is free software: you can redistribute it and/or modify |
225 | + * it under the terms of the GNU Lesser General Public License version 3 as |
226 | + * published by the Free Software Foundation. |
227 | + * |
228 | + * This program is distributed in the hope that it will be useful, |
229 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
230 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
231 | + * GNU Lesser General Public License for more details. |
232 | + * |
233 | + * You should have received a copy of the GNU Lesser General Public License |
234 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
235 | + * |
236 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
237 | + */ |
238 | + |
239 | +#ifndef UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTNETCPP_H |
240 | +#define UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTNETCPP_H |
241 | + |
242 | +#include <unity/scopes/internal/smartscopes/HttpClientInterface.h> |
243 | + |
244 | +#include <memory> |
245 | +#include <thread> |
246 | + |
247 | +namespace core |
248 | +{ |
249 | +namespace net |
250 | +{ |
251 | +namespace http |
252 | +{ |
253 | +class Client; |
254 | +} |
255 | +} |
256 | +} |
257 | + |
258 | +namespace unity |
259 | +{ |
260 | + |
261 | +namespace scopes |
262 | +{ |
263 | + |
264 | +namespace internal |
265 | +{ |
266 | + |
267 | +namespace smartscopes |
268 | +{ |
269 | + |
270 | +class HttpClientNetCpp : public HttpClientInterface |
271 | +{ |
272 | +public: |
273 | + explicit HttpClientNetCpp(unsigned int no_reply_timeout); |
274 | + ~HttpClientNetCpp(); |
275 | + |
276 | + HttpResponseHandle::SPtr get(std::string const& request_url, |
277 | + std::function<void(std::string const&)> const& line_data = [](std::string const&) {}, |
278 | + HttpHeaders const& headers = HttpHeaders()) override; |
279 | + |
280 | + std::string to_percent_encoding(std::string const& string) override; |
281 | + |
282 | +private: |
283 | + void cancel_get(unsigned int session_id) override; |
284 | + |
285 | + unsigned int no_reply_timeout; |
286 | + std::shared_ptr<core::net::http::Client> client; |
287 | + std::thread worker; |
288 | +}; |
289 | + |
290 | +} // namespace smartscopes |
291 | + |
292 | +} // namespace internal |
293 | + |
294 | +} // namespace scopes |
295 | + |
296 | +} // namespace unity |
297 | + |
298 | +#endif // UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTNETCPP_H |
299 | |
300 | === removed file 'include/unity/scopes/internal/smartscopes/HttpClientQt.h' |
301 | --- include/unity/scopes/internal/smartscopes/HttpClientQt.h 2014-11-03 05:31:30 +0000 |
302 | +++ include/unity/scopes/internal/smartscopes/HttpClientQt.h 1970-01-01 00:00:00 +0000 |
303 | @@ -1,91 +0,0 @@ |
304 | -/* |
305 | - * Copyright (C) 2013 Canonical Ltd |
306 | - * |
307 | - * This program is free software: you can redistribute it and/or modify |
308 | - * it under the terms of the GNU Lesser General Public License version 3 as |
309 | - * published by the Free Software Foundation. |
310 | - * |
311 | - * This program is distributed in the hope that it will be useful, |
312 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
313 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
314 | - * GNU Lesser General Public License for more details. |
315 | - * |
316 | - * You should have received a copy of the GNU Lesser General Public License |
317 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
318 | - * |
319 | - * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
320 | - */ |
321 | - |
322 | -#pragma once |
323 | - |
324 | -#include <unity/scopes/internal/smartscopes/HttpClientInterface.h> |
325 | -#include <map> |
326 | - |
327 | -class QCoreApplication; |
328 | - |
329 | -namespace unity |
330 | -{ |
331 | - |
332 | -namespace scopes |
333 | -{ |
334 | - |
335 | -namespace internal |
336 | -{ |
337 | - |
338 | -namespace smartscopes |
339 | -{ |
340 | - |
341 | -class HttpClientQtThread; |
342 | - |
343 | -class HttpClientQt : public HttpClientInterface |
344 | -{ |
345 | -public: |
346 | - explicit HttpClientQt(unsigned int no_reply_timeout); |
347 | - ~HttpClientQt(); |
348 | - |
349 | - HttpResponseHandle::SPtr get(std::string const& request_url, std::function<void(std::string const&)> const& lineData = [](std::string const&) {}, |
350 | - HttpHeaders const& headers = HttpHeaders()) override; |
351 | - |
352 | - std::string to_percent_encoding(std::string const& string) override; |
353 | - |
354 | -private: |
355 | - void cancel_get(unsigned int session_id) override; |
356 | - |
357 | -private: |
358 | - class HttpSession |
359 | - { |
360 | - public: |
361 | - HttpSession(std::string const& request_url, unsigned int timeout, std::function<void(std::string const&)> const& lineData, HttpHeaders const& headers = |
362 | - HttpHeaders()); |
363 | - ~HttpSession(); |
364 | - |
365 | - std::future<void> get_future(); |
366 | - |
367 | - void cancel_session(); |
368 | - void wait_for_session(); |
369 | - |
370 | - private: |
371 | - std::promise<void> promise_; |
372 | - std::thread get_thread_; |
373 | - std::unique_ptr<HttpClientQtThread> qt_thread_; |
374 | - std::mutex qt_thread_mutex_; |
375 | - std::promise<void> qt_thread_ready_; |
376 | - }; |
377 | - |
378 | -private: |
379 | - unsigned int session_index_; |
380 | - std::map<unsigned int, std::shared_ptr<HttpSession>> sessions_; |
381 | - std::mutex sessions_mutex_; |
382 | - |
383 | - unsigned int const no_reply_timeout_; |
384 | - |
385 | - std::unique_ptr<QCoreApplication> app_; |
386 | -}; |
387 | - |
388 | -} // namespace smartscopes |
389 | - |
390 | -} // namespace internal |
391 | - |
392 | -} // namespace scopes |
393 | - |
394 | -} // namespace unity |
395 | |
396 | === removed file 'include/unity/scopes/internal/smartscopes/HttpClientQtThread.h' |
397 | --- include/unity/scopes/internal/smartscopes/HttpClientQtThread.h 2014-11-03 05:31:30 +0000 |
398 | +++ include/unity/scopes/internal/smartscopes/HttpClientQtThread.h 1970-01-01 00:00:00 +0000 |
399 | @@ -1,100 +0,0 @@ |
400 | -/* |
401 | - * Copyright (C) 2013 Canonical Ltd |
402 | - * |
403 | - * This program is free software: you can redistribute it and/or modify |
404 | - * it under the terms of the GNU Lesser General Public License version 3 as |
405 | - * published by the Free Software Foundation. |
406 | - * |
407 | - * This program is distributed in the hope that it will be useful, |
408 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
409 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
410 | - * GNU Lesser General Public License for more details. |
411 | - * |
412 | - * You should have received a copy of the GNU Lesser General Public License |
413 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
414 | - * |
415 | - * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
416 | - */ |
417 | - |
418 | -#pragma once |
419 | - |
420 | -// This hack allows unity-scopes-api to be built with |
421 | -// clang-3.4+ and versions of Qt before v5.1.1. |
422 | -#if QT_VERSION < 0x050101 |
423 | - #define register |
424 | - |
425 | - #include <QThread> |
426 | - |
427 | - #define qHash(x,y) qHash(const QUrl &url, unsigned int seed) |
428 | - #include <QUrl> |
429 | - #undef qHash |
430 | - |
431 | - #undef register |
432 | -#else |
433 | - #include <QThread> |
434 | - #include <QUrl> |
435 | -#endif |
436 | - |
437 | -#include <unity/scopes/internal/smartscopes/HttpClientInterface.h> |
438 | -#include <unity/util/NonCopyable.h> |
439 | - |
440 | -#include <mutex> |
441 | - |
442 | -class QNetworkReply; |
443 | -class QNetworkAccessManager; |
444 | - |
445 | -namespace unity |
446 | -{ |
447 | - |
448 | -namespace scopes |
449 | -{ |
450 | - |
451 | -namespace internal |
452 | -{ |
453 | - |
454 | -namespace smartscopes |
455 | -{ |
456 | - |
457 | -class Q_DECL_EXPORT HttpClientQtThread : public QThread |
458 | -{ |
459 | - Q_OBJECT |
460 | - |
461 | -public: |
462 | - NONCOPYABLE(HttpClientQtThread); |
463 | - |
464 | - HttpClientQtThread(const QUrl& url, unsigned int timeout, std::function<void(std::string const&)> const& lineData, const HttpHeaders& headers = |
465 | - HttpHeaders()); |
466 | - ~HttpClientQtThread(); |
467 | - |
468 | - bool get_reply(std::string& reply); |
469 | - |
470 | -private: |
471 | - void run(); |
472 | - |
473 | -public Q_SLOTS: |
474 | - void cancel(); |
475 | - void timeout(); |
476 | - void got_reply(QNetworkReply* reply); |
477 | - void dataReady(); |
478 | - |
479 | -Q_SIGNALS: |
480 | - void abort(); |
481 | - |
482 | -private: |
483 | - QUrl url_; |
484 | - const std::function<void(std::string const&)> lineDataCallback_; |
485 | - HttpHeaders headers_; |
486 | - unsigned int timeout_; |
487 | - std::mutex reply_mutex_; |
488 | - |
489 | - bool success_; |
490 | - std::string reply_; |
491 | -}; |
492 | - |
493 | -} // namespace smartscopes |
494 | - |
495 | -} // namespace internal |
496 | - |
497 | -} // namespace scopes |
498 | - |
499 | -} // namespace unity |
500 | |
501 | === modified file 'src/scopes/internal/JsonCppNode.cpp' |
502 | --- src/scopes/internal/JsonCppNode.cpp 2015-01-13 09:12:06 +0000 |
503 | +++ src/scopes/internal/JsonCppNode.cpp 2015-01-20 09:09:48 +0000 |
504 | @@ -117,7 +117,7 @@ |
505 | return Variant(value.asString()); |
506 | case Json::ValueType::intValue: |
507 | case Json::ValueType::uintValue: |
508 | - return Variant(value.asInt()); // this can throw std::runtime_error from jsoncpp if uint to int conversion is not possible |
509 | + return Variant(value.asInt()); // this can throw std::runtime_error from jsoncpp if unsigned int to int conversion is not possible |
510 | case Json::ValueType::realValue: |
511 | return Variant(value.asDouble()); |
512 | case Json::ValueType::booleanValue: |
513 | @@ -220,11 +220,11 @@ |
514 | return root_.asInt(); |
515 | } |
516 | |
517 | -uint JsonCppNode::as_uint() const |
518 | +unsigned int JsonCppNode::as_uint() const |
519 | { |
520 | if (!root_.isConvertibleTo(Json::uintValue)) |
521 | { |
522 | - throw unity::LogicException("Node does not contain a uint value"); |
523 | + throw unity::LogicException("Node does not contain a unsigned int value"); |
524 | } |
525 | |
526 | return root_.asUInt(); |
527 | @@ -281,7 +281,7 @@ |
528 | return std::make_shared<JsonCppNode>(value_node); |
529 | } |
530 | |
531 | -JsonNodeInterface::SPtr JsonCppNode::get_node(uint node_index) const |
532 | +JsonNodeInterface::SPtr JsonCppNode::get_node(unsigned int node_index) const |
533 | { |
534 | if (root_.type() != Json::arrayValue) |
535 | { |
536 | |
537 | === modified file 'src/scopes/internal/RegistryObject.cpp' |
538 | --- src/scopes/internal/RegistryObject.cpp 2015-01-05 01:48:35 +0000 |
539 | +++ src/scopes/internal/RegistryObject.cpp 2015-01-20 09:09:48 +0000 |
540 | @@ -766,7 +766,7 @@ |
541 | util::ResourcePtr<wordexp_t*, decltype(&wordfree)> free_guard(&exp, wordfree); |
542 | |
543 | command_args.push_back(exp.we_wordv[0]); |
544 | - for (uint i = 1; i < exp.we_wordc; ++i) |
545 | + for (unsigned int i = 1; i < exp.we_wordc; ++i) |
546 | { |
547 | std::string arg = exp.we_wordv[i]; |
548 | // Replace "%R" placeholders with the runtime config |
549 | |
550 | === modified file 'src/scopes/internal/smartscopes/CMakeLists.txt' |
551 | --- src/scopes/internal/smartscopes/CMakeLists.txt 2014-08-18 08:50:39 +0000 |
552 | +++ src/scopes/internal/smartscopes/CMakeLists.txt 2015-01-20 09:09:48 +0000 |
553 | @@ -1,5 +1,7 @@ |
554 | set(SRC |
555 | + ${CMAKE_CURRENT_SOURCE_DIR}/HttpClientNetCpp.cpp |
556 | ${CMAKE_CURRENT_SOURCE_DIR}/SmartScope.cpp |
557 | + ${CMAKE_CURRENT_SOURCE_DIR}/SmartScopesClient.cpp |
558 | ${CMAKE_CURRENT_SOURCE_DIR}/SSConfig.cpp |
559 | ${CMAKE_CURRENT_SOURCE_DIR}/SSQueryCtrlObject.cpp |
560 | ${CMAKE_CURRENT_SOURCE_DIR}/SSQueryObject.cpp |
561 | @@ -7,34 +9,3 @@ |
562 | ${CMAKE_CURRENT_SOURCE_DIR}/SSScopeObject.cpp |
563 | ) |
564 | set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE) |
565 | - |
566 | -# -- libsmartscopes -- |
567 | - |
568 | -set(CMAKE_AUTOMOC ON) |
569 | -set(CMAKE_INCLUDE_CURRENT_DIR ON) |
570 | - |
571 | -find_package(Qt5Core REQUIRED) |
572 | -include_directories(${Qt5Core_INCLUDE_DIRS}) |
573 | - |
574 | -add_library( |
575 | - smartscopes STATIC |
576 | - |
577 | - HttpClientQt.cpp |
578 | - |
579 | - ${CMAKE_SOURCE_DIR}/include/unity/scopes/internal/smartscopes/HttpClientQtThread.h |
580 | - HttpClientQtThread.cpp |
581 | - |
582 | - SmartScopesClient.cpp |
583 | -) |
584 | - |
585 | -qt5_use_modules( |
586 | - smartscopes |
587 | - |
588 | - Core |
589 | - Network |
590 | -) |
591 | - |
592 | -target_link_libraries( |
593 | - smartscopes |
594 | - ${UNITY_API_LDFLAGS} |
595 | -) |
596 | |
597 | === added file 'src/scopes/internal/smartscopes/HttpClientNetCpp.cpp' |
598 | --- src/scopes/internal/smartscopes/HttpClientNetCpp.cpp 1970-01-01 00:00:00 +0000 |
599 | +++ src/scopes/internal/smartscopes/HttpClientNetCpp.cpp 2015-01-20 09:09:48 +0000 |
600 | @@ -0,0 +1,189 @@ |
601 | +/* |
602 | + * Copyright (C) 2013 Canonical Ltd |
603 | + * |
604 | + * This program is free software: you can redistribute it and/or modify |
605 | + * it under the terms of the GNU Lesser General Public License version 3 as |
606 | + * published by the Free Software Foundation. |
607 | + * |
608 | + * This program is distributed in the hope that it will be useful, |
609 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
610 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
611 | + * GNU Lesser General Public License for more details. |
612 | + * |
613 | + * You should have received a copy of the GNU Lesser General Public License |
614 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
615 | + * |
616 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
617 | + */ |
618 | + |
619 | +#include <unity/scopes/internal/smartscopes/HttpClientNetCpp.h> |
620 | + |
621 | +#include <unity/UnityExceptions.h> |
622 | + |
623 | +#include <core/net/http/client.h> |
624 | +#include <core/net/http/request.h> |
625 | +#include <core/net/http/response.h> |
626 | +#include <core/net/http/status.h> |
627 | + |
628 | +#include <iostream> |
629 | +#include <unordered_map> |
630 | + |
631 | +namespace net = core::net; |
632 | +namespace http = core::net::http; |
633 | + |
634 | +using namespace unity::scopes::internal::smartscopes; |
635 | + |
636 | +namespace |
637 | +{ |
638 | +struct Cancelable |
639 | +{ |
640 | + Cancelable() = default; |
641 | + Cancelable(const Cancelable&) = delete; |
642 | + Cancelable& operator=(const Cancelable&) = delete; |
643 | + |
644 | + void cancel() |
645 | + { |
646 | + cancelled.store(true); |
647 | + } |
648 | + |
649 | + bool is_cancelled() const |
650 | + { |
651 | + return cancelled.load(); |
652 | + } |
653 | + |
654 | + std::atomic<bool> cancelled{false}; |
655 | +}; |
656 | + |
657 | +struct CancellationRegistry |
658 | +{ |
659 | + static CancellationRegistry& instance() |
660 | + { |
661 | + static CancellationRegistry cr; |
662 | + return cr; |
663 | + } |
664 | + |
665 | + std::pair<unsigned int, std::shared_ptr<Cancelable>> add() |
666 | + { |
667 | + auto cancelable = std::make_shared<Cancelable>(); |
668 | + auto id = add(cancelable); |
669 | + |
670 | + return std::make_pair(id, cancelable); |
671 | + } |
672 | + |
673 | + unsigned int add(const std::shared_ptr<Cancelable>& cancelable) |
674 | + { |
675 | + std::lock_guard<std::mutex> lg(guard); |
676 | + |
677 | + unsigned int result{++request_id}; |
678 | + |
679 | + store.insert(std::make_pair(result, cancelable)); |
680 | + |
681 | + return result; |
682 | + } |
683 | + |
684 | + void cancel_and_remove_for_id(unsigned int id) |
685 | + { |
686 | + std::lock_guard<std::mutex> lg(guard); |
687 | + |
688 | + auto it = store.find(id); |
689 | + |
690 | + if (it != store.end()) |
691 | + { |
692 | + it->second->cancel(); |
693 | + store.erase(it); |
694 | + } |
695 | + } |
696 | + |
697 | + unsigned int request_id{0}; |
698 | + std::mutex guard; |
699 | + std::unordered_map<unsigned int, std::shared_ptr<Cancelable>> store; |
700 | +}; |
701 | +} |
702 | + |
703 | +HttpClientNetCpp::HttpClientNetCpp(unsigned int no_reply_timeout) |
704 | + : no_reply_timeout{no_reply_timeout}, |
705 | + client{http::make_client()}, |
706 | + worker([this]() { client->run(); }) |
707 | +{ |
708 | +} |
709 | + |
710 | +HttpClientNetCpp::~HttpClientNetCpp() |
711 | +{ |
712 | + client->stop(); |
713 | + |
714 | + if (worker.joinable()) |
715 | + { |
716 | + worker.join(); |
717 | + } |
718 | +} |
719 | + |
720 | +HttpResponseHandle::SPtr HttpClientNetCpp::get(std::string const& request_url, |
721 | + std::function<void(std::string const&)> const& line_data, |
722 | + HttpHeaders const& headers) |
723 | +{ |
724 | + auto http_config = http::Request::Configuration::from_uri_as_string(request_url); |
725 | + http::Header http_header; |
726 | + for (auto const& hdr: headers) |
727 | + { |
728 | + http_header.add(hdr.first, hdr.second); |
729 | + } |
730 | + http_config.header = http_header; |
731 | + |
732 | + auto request = client->get(http_config); |
733 | + request->set_timeout(std::chrono::milliseconds{no_reply_timeout}); |
734 | + |
735 | + auto promise = std::make_shared<std::promise<void>>(); |
736 | + std::shared_future<void> future(promise->get_future()); |
737 | + |
738 | + auto id_and_cancelable = CancellationRegistry::instance().add(); |
739 | + |
740 | + request->async_execute( |
741 | + http::Request::Handler() |
742 | + .on_progress([id_and_cancelable](const http::Request::Progress&) |
743 | + { |
744 | + return id_and_cancelable.second->is_cancelled() ? |
745 | + http::Request::Progress::Next::abort_operation : |
746 | + http::Request::Progress::Next::continue_operation; |
747 | + }) |
748 | + .on_response([line_data, promise](const http::Response& response) |
749 | + { |
750 | + if (response.status != http::Status::ok) |
751 | + { |
752 | + std::ostringstream msg; |
753 | + msg << "HTTP request failed with: " << response.status << std::endl << response.body; |
754 | + unity::ResourceException e(msg.str()); |
755 | + |
756 | + promise->set_exception(std::make_exception_ptr(e)); |
757 | + } |
758 | + else |
759 | + { |
760 | + std::istringstream in(response.body); |
761 | + std::string line; |
762 | + while (std::getline(in, line)) |
763 | + { |
764 | + line_data(line); |
765 | + } |
766 | + promise->set_value(); |
767 | + } |
768 | + }) |
769 | + .on_error([promise](const net::Error& e) |
770 | + { |
771 | + unity::ResourceException re(e.what()); |
772 | + promise->set_exception(std::make_exception_ptr(re)); |
773 | + })); |
774 | + |
775 | + return std::make_shared<HttpResponseHandle>( |
776 | + shared_from_this(), |
777 | + id_and_cancelable.first, |
778 | + future); |
779 | +} |
780 | + |
781 | +void HttpClientNetCpp::cancel_get(unsigned int id) |
782 | +{ |
783 | + CancellationRegistry::instance().cancel_and_remove_for_id(id); |
784 | +} |
785 | + |
786 | +std::string HttpClientNetCpp::to_percent_encoding(std::string const& string) |
787 | +{ |
788 | + return client->url_escape(string); |
789 | +} |
790 | |
791 | === removed file 'src/scopes/internal/smartscopes/HttpClientQt.cpp' |
792 | --- src/scopes/internal/smartscopes/HttpClientQt.cpp 2014-12-02 02:00:57 +0000 |
793 | +++ src/scopes/internal/smartscopes/HttpClientQt.cpp 1970-01-01 00:00:00 +0000 |
794 | @@ -1,151 +0,0 @@ |
795 | -/* |
796 | - * Copyright (C) 2013 Canonical Ltd |
797 | - * |
798 | - * This program is free software: you can redistribute it and/or modify |
799 | - * it under the terms of the GNU Lesser General Public License version 3 as |
800 | - * published by the Free Software Foundation. |
801 | - * |
802 | - * This program is distributed in the hope that it will be useful, |
803 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
804 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
805 | - * GNU Lesser General Public License for more details. |
806 | - * |
807 | - * You should have received a copy of the GNU Lesser General Public License |
808 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
809 | - * |
810 | - * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
811 | - */ |
812 | - |
813 | -#pragma GCC diagnostic push |
814 | -#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
815 | -#pragma GCC diagnostic ignored "-Wswitch-default" |
816 | - |
817 | -#include <unity/scopes/internal/smartscopes/HttpClientQt.h> |
818 | -#include <unity/scopes/internal/smartscopes/HttpClientQtThread.h> |
819 | -#include <unity/UnityExceptions.h> |
820 | - |
821 | -#include <QCoreApplication> |
822 | -#include <QEventLoop> |
823 | -#include <QUrl> |
824 | -#include <QNetworkRequest> |
825 | -#include <QNetworkReply> |
826 | - |
827 | -#pragma GCC diagnostic pop |
828 | - |
829 | -using namespace unity::scopes::internal::smartscopes; |
830 | - |
831 | -//-- HttpClientQt |
832 | - |
833 | -HttpClientQt::HttpClientQt(uint no_reply_timeout) |
834 | - : session_index_(0) |
835 | - , no_reply_timeout_(no_reply_timeout) |
836 | - , app_(nullptr) |
837 | -{ |
838 | - if (!QCoreApplication::instance()) |
839 | - { |
840 | - int argc = 0; |
841 | - app_ = std::unique_ptr<QCoreApplication>(new QCoreApplication(argc, nullptr)); |
842 | - } |
843 | -} |
844 | - |
845 | -HttpClientQt::~HttpClientQt() |
846 | -{ |
847 | -} |
848 | - |
849 | -HttpResponseHandle::SPtr HttpClientQt::get(std::string const& request_url, std::function<void(std::string const&)> const& lineData, |
850 | - HttpHeaders const& headers) |
851 | -{ |
852 | - std::lock_guard<std::mutex> lock(sessions_mutex_); |
853 | - |
854 | - // start new session |
855 | - auto session = std::make_shared<HttpSession>(request_url, no_reply_timeout_, lineData, headers); |
856 | - sessions_[session_index_] = session; |
857 | - |
858 | - return std::make_shared<HttpResponseHandle>(shared_from_this(), session_index_++, session->get_future()); |
859 | -} |
860 | - |
861 | -void HttpClientQt::cancel_get(uint session_id) |
862 | -{ |
863 | - std::lock_guard<std::mutex> lock(sessions_mutex_); |
864 | - |
865 | - // if session_id in map, cancel it |
866 | - auto it = sessions_.find(session_id); |
867 | - if (it != sessions_.end()) |
868 | - { |
869 | - it->second->cancel_session(); |
870 | - sessions_.erase(it); |
871 | - } |
872 | -} |
873 | - |
874 | -std::string HttpClientQt::to_percent_encoding(std::string const& string) |
875 | -{ |
876 | - return QUrl::toPercentEncoding(string.c_str()).constData(); |
877 | -} |
878 | - |
879 | -//-- HttpClientQt::HttpSession |
880 | - |
881 | -HttpClientQt::HttpSession::HttpSession(std::string const& request_url, uint timeout, std::function<void(std::string const&)> const& lineData, |
882 | - HttpHeaders const& headers) |
883 | - : qt_thread_(nullptr) |
884 | -{ |
885 | - get_thread_ = |
886 | - std::thread([this, request_url, headers, timeout, lineData]() |
887 | - { |
888 | - QUrl url(request_url.c_str()); |
889 | - |
890 | - { |
891 | - std::lock_guard<std::mutex> lock(qt_thread_mutex_); |
892 | - qt_thread_ = std::unique_ptr<HttpClientQtThread>(new HttpClientQtThread(url, timeout, lineData, headers)); |
893 | - } |
894 | - |
895 | - QEventLoop loop; |
896 | - QObject::connect(qt_thread_.get(), &HttpClientQtThread::finished, &loop, &QEventLoop::quit); |
897 | - |
898 | - qt_thread_->start(); |
899 | - qt_thread_ready_.set_value(); |
900 | - loop.exec(); |
901 | - |
902 | - std::string reply; |
903 | - bool success = qt_thread_->get_reply(reply); |
904 | - |
905 | - if (!success) |
906 | - { |
907 | - unity::ResourceException e(reply); |
908 | - promise_.set_exception(e.self()); |
909 | - } |
910 | - else |
911 | - { |
912 | - promise_.set_value(); |
913 | - } |
914 | - }); |
915 | - |
916 | - qt_thread_ready_.get_future().wait(); |
917 | -} |
918 | - |
919 | -HttpClientQt::HttpSession::~HttpSession() |
920 | -{ |
921 | - cancel_session(); |
922 | -} |
923 | - |
924 | -std::future<void> HttpClientQt::HttpSession::get_future() |
925 | -{ |
926 | - return promise_.get_future(); |
927 | -} |
928 | - |
929 | -void HttpClientQt::HttpSession::cancel_session() |
930 | -{ |
931 | - { |
932 | - std::lock_guard<std::mutex> lock(qt_thread_mutex_); |
933 | - qt_thread_->cancel(); |
934 | - } |
935 | - |
936 | - wait_for_session(); |
937 | -} |
938 | - |
939 | -void HttpClientQt::HttpSession::wait_for_session() |
940 | -{ |
941 | - if (get_thread_.joinable()) |
942 | - { |
943 | - get_thread_.join(); |
944 | - } |
945 | -} |
946 | |
947 | === removed file 'src/scopes/internal/smartscopes/HttpClientQtThread.cpp' |
948 | --- src/scopes/internal/smartscopes/HttpClientQtThread.cpp 2014-12-02 02:00:57 +0000 |
949 | +++ src/scopes/internal/smartscopes/HttpClientQtThread.cpp 1970-01-01 00:00:00 +0000 |
950 | @@ -1,186 +0,0 @@ |
951 | -/* |
952 | - * Copyright (C) 2013 Canonical Ltd |
953 | - * |
954 | - * This program is free software: you can redistribute it and/or modify |
955 | - * it under the terms of the GNU Lesser General Public License version 3 as |
956 | - * published by the Free Software Foundation. |
957 | - * |
958 | - * This program is distributed in the hope that it will be useful, |
959 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
960 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
961 | - * GNU Lesser General Public License for more details. |
962 | - * |
963 | - * You should have received a copy of the GNU Lesser General Public License |
964 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
965 | - * |
966 | - * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
967 | - * Pawel Stolowski <pawel.stolowski@canonical.com> |
968 | - */ |
969 | - |
970 | -#pragma GCC diagnostic push |
971 | -#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
972 | -#pragma GCC diagnostic ignored "-Wswitch-default" |
973 | - |
974 | -#include "unity/scopes/internal/smartscopes/HttpClientQtThread.h" |
975 | - |
976 | -#include <QNetworkRequest> |
977 | -#include <QNetworkAccessManager> |
978 | -#include <QNetworkReply> |
979 | -#include <QTimer> |
980 | - |
981 | -#pragma GCC diagnostic pop |
982 | - |
983 | -#include <cassert> |
984 | - |
985 | -namespace unity |
986 | -{ |
987 | - |
988 | -namespace scopes |
989 | -{ |
990 | - |
991 | -namespace internal |
992 | -{ |
993 | - |
994 | -namespace smartscopes |
995 | -{ |
996 | - |
997 | -HttpClientQtThread::HttpClientQtThread(const QUrl& url, uint timeout, std::function<void(std::string const&)> const& lineData, HttpHeaders const& headers) |
998 | - : QThread() |
999 | - , url_(url) |
1000 | - , lineDataCallback_(lineData) |
1001 | - , headers_(headers) |
1002 | - , timeout_(timeout) |
1003 | - , success_(false) |
1004 | -{ |
1005 | -} |
1006 | - |
1007 | -HttpClientQtThread::~HttpClientQtThread() |
1008 | -{ |
1009 | - cancel(); |
1010 | - |
1011 | - wait(); |
1012 | -} |
1013 | - |
1014 | -bool HttpClientQtThread::get_reply(std::string& reply) |
1015 | -{ |
1016 | - std::lock_guard<std::mutex> lock(reply_mutex_); |
1017 | - |
1018 | - reply = reply_; |
1019 | - return success_; |
1020 | -} |
1021 | - |
1022 | -void HttpClientQtThread::run() |
1023 | -{ |
1024 | - QNetworkAccessManager* manager = new QNetworkAccessManager(); |
1025 | - |
1026 | - QNetworkRequest request(url_); |
1027 | - for (auto const& hdr: headers_) |
1028 | - { |
1029 | - request.setRawHeader(QString::fromStdString(hdr.first).toUtf8(), QString::fromStdString(hdr.second).toUtf8()); |
1030 | - } |
1031 | - |
1032 | - QNetworkReply* reply = manager->get(request); |
1033 | - reply->setReadBufferSize(0); // unlimited buffer |
1034 | - |
1035 | - connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(got_reply(QNetworkReply *))); |
1036 | - connect(reply, SIGNAL(readyRead()), this, SLOT(dataReady())); |
1037 | - connect(this, &HttpClientQtThread::abort, reply, &QNetworkReply::abort); |
1038 | - |
1039 | - QTimer timeout; |
1040 | - timeout.singleShot(timeout_, this, SLOT(timeout())); |
1041 | - QThread::exec(); // enter event loop |
1042 | - |
1043 | - reply->deleteLater(); |
1044 | - manager->deleteLater(); |
1045 | -} |
1046 | - |
1047 | -void HttpClientQtThread::cancel() |
1048 | -{ |
1049 | - std::lock_guard<std::mutex> lock(reply_mutex_); |
1050 | - |
1051 | - success_ = false; |
1052 | - reply_ = "Request cancelled: " + url_.url().toStdString(); |
1053 | - |
1054 | - emit HttpClientQtThread::abort(); |
1055 | - quit(); |
1056 | -} |
1057 | - |
1058 | -void HttpClientQtThread::timeout() |
1059 | -{ |
1060 | - std::lock_guard<std::mutex> lock(reply_mutex_); |
1061 | - |
1062 | - success_ = false; |
1063 | - reply_ = "Request timed out: " + url_.url().toStdString(); |
1064 | - |
1065 | - emit HttpClientQtThread::abort(); |
1066 | - quit(); |
1067 | -} |
1068 | - |
1069 | -void HttpClientQtThread::dataReady() |
1070 | -{ |
1071 | - QNetworkReply* net_reply = qobject_cast<QNetworkReply*>(sender()); |
1072 | - if (net_reply) |
1073 | - { |
1074 | - if (net_reply->canReadLine()) |
1075 | - { |
1076 | - QByteArray data = net_reply->readLine(); |
1077 | - const std::string replyLine(data.constData(), data.size()); |
1078 | - lineDataCallback_(replyLine); |
1079 | - } |
1080 | - } |
1081 | -} |
1082 | - |
1083 | -void HttpClientQtThread::got_reply(QNetworkReply* reply) |
1084 | -{ |
1085 | - std::lock_guard<std::mutex> lock(reply_mutex_); |
1086 | - |
1087 | - if (!reply_.empty()) |
1088 | - { |
1089 | - return; |
1090 | - } |
1091 | - |
1092 | - if (!reply) |
1093 | - { |
1094 | - // no reply |
1095 | - success_ = false; |
1096 | - reply_ = "No reply from " + url_.url().toStdString(); |
1097 | - } |
1098 | - else if (!reply->isFinished()) |
1099 | - { |
1100 | - // incomplete reply |
1101 | - success_ = false; |
1102 | - reply_ = "Incomplete reply from " + url_.url().toStdString(); |
1103 | - } |
1104 | - else if (reply->error() != QNetworkReply::NoError) |
1105 | - { |
1106 | - // communication error |
1107 | - success_ = false; |
1108 | - reply_ = reply->errorString().toStdString(); |
1109 | - } |
1110 | - else |
1111 | - { |
1112 | - success_ = true; |
1113 | - // read any remaining lines |
1114 | - while (reply->canReadLine()) |
1115 | - { |
1116 | - const QByteArray byte_array = reply->readLine(); |
1117 | - lineDataCallback_(std::string(byte_array.constData(), byte_array.size())); |
1118 | - } |
1119 | - // there may be data left which is not "\n" terminated |
1120 | - if (reply->bytesAvailable()) |
1121 | - { |
1122 | - const QByteArray byte_array = reply->readAll(); |
1123 | - lineDataCallback_(std::string(byte_array.constData(), byte_array.size())); |
1124 | - } |
1125 | - } |
1126 | - |
1127 | - quit(); |
1128 | -} |
1129 | - |
1130 | -} // namespace smartscopes |
1131 | - |
1132 | -} // namespace internal |
1133 | - |
1134 | -} // namespace scopes |
1135 | - |
1136 | -} // namespace unity |
1137 | |
1138 | === modified file 'src/scopes/internal/smartscopes/SSRegistryObject.cpp' |
1139 | --- src/scopes/internal/smartscopes/SSRegistryObject.cpp 2015-01-09 03:16:51 +0000 |
1140 | +++ src/scopes/internal/smartscopes/SSRegistryObject.cpp 2015-01-20 09:09:48 +0000 |
1141 | @@ -25,7 +25,7 @@ |
1142 | #include <unity/scopes/internal/RuntimeImpl.h> |
1143 | #include <unity/scopes/internal/ScopeImpl.h> |
1144 | #include <unity/scopes/internal/ScopeMetadataImpl.h> |
1145 | -#include <unity/scopes/internal/smartscopes/HttpClientQt.h> |
1146 | +#include <unity/scopes/internal/smartscopes/HttpClientNetCpp.h> |
1147 | #include <unity/scopes/internal/Utils.h> |
1148 | #include <unity/scopes/ScopeExceptions.h> |
1149 | #include <unity/UnityExceptions.h> |
1150 | @@ -48,7 +48,7 @@ |
1151 | std::string const& sss_url, |
1152 | bool caching_enabled) |
1153 | : ssclient_(std::make_shared<SmartScopesClient>( |
1154 | - std::make_shared<HttpClientQt>(ss_config.http_reply_timeout() * 1000), // need millisecs |
1155 | + std::make_shared<HttpClientNetCpp>(ss_config.http_reply_timeout() * 1000), // need millisecs |
1156 | std::make_shared<JsonCppNode>(), |
1157 | middleware->runtime(), |
1158 | sss_url)) |
1159 | |
1160 | === modified file 'src/scopes/internal/smartscopes/SmartScopesClient.cpp' |
1161 | --- src/scopes/internal/smartscopes/SmartScopesClient.cpp 2015-01-09 03:16:51 +0000 |
1162 | +++ src/scopes/internal/smartscopes/SmartScopesClient.cpp 2015-01-20 09:09:48 +0000 |
1163 | @@ -63,7 +63,7 @@ |
1164 | |
1165 | //-- SearchHandle |
1166 | |
1167 | -SearchHandle::SearchHandle(uint search_id, SmartScopesClient::SPtr ssc) |
1168 | +SearchHandle::SearchHandle(unsigned int search_id, SmartScopesClient::SPtr ssc) |
1169 | : search_id_(search_id) |
1170 | , ssc_(ssc) |
1171 | { |
1172 | @@ -86,7 +86,7 @@ |
1173 | |
1174 | //-- PreviewHandle |
1175 | |
1176 | -PreviewHandle::PreviewHandle(uint preview_id, SmartScopesClient::SPtr ssc) |
1177 | +PreviewHandle::PreviewHandle(unsigned int preview_id, SmartScopesClient::SPtr ssc) |
1178 | : preview_id_(preview_id) |
1179 | , ssc_(ssc) |
1180 | { |
1181 | @@ -200,9 +200,13 @@ |
1182 | BOOST_LOG_SEV(logger_, Logger::Error) << "SmartScopesClient.get_remote_scopes(): failed to read " << partner_file_ << ": " << e.what(); |
1183 | } |
1184 | |
1185 | - HttpResponseHandle::SPtr response = http_client_->get(remote_scopes_uri.str(), [&response_str](std::string const& replyLine) { |
1186 | - response_str += replyLine; // accumulate all reply lines |
1187 | + std::mutex reponse_mutex; |
1188 | + HttpResponseHandle::SPtr response = http_client_->get(remote_scopes_uri.str(), [&response_str, &reponse_mutex](std::string const& replyLine) |
1189 | + { |
1190 | + std::lock_guard<std::mutex> lock(reponse_mutex); |
1191 | + response_str += replyLine; // accumulate all reply lines |
1192 | }, headers); |
1193 | + |
1194 | response->get(); |
1195 | |
1196 | BOOST_LOG_SEV(logger_, Logger::Info) |
1197 | @@ -409,7 +413,7 @@ |
1198 | std::string const& locale, |
1199 | LocationInfo const& location, |
1200 | std::string const& user_agent_hdr, |
1201 | - uint limit) |
1202 | + unsigned int limit) |
1203 | { |
1204 | std::ostringstream search_uri; |
1205 | search_uri.imbue(std::locale::classic()); // so that doubles use one standard formatting wrt decimal point |
1206 | @@ -458,7 +462,7 @@ |
1207 | } |
1208 | |
1209 | std::lock_guard<std::mutex> lock(query_results_mutex_); |
1210 | - uint search_id = ++query_counter_; |
1211 | + unsigned int search_id = ++query_counter_; |
1212 | |
1213 | BOOST_LOG_SEV(logger_, Logger::Info) << "SmartScopesClient.search(): GET " << search_uri.str(); |
1214 | |
1215 | @@ -469,15 +473,18 @@ |
1216 | headers.push_back(std::make_pair("User-Agent", user_agent_hdr)); |
1217 | } |
1218 | |
1219 | - query_results_[search_id] = http_client_->get(search_uri.str(), [this, handler](std::string const& lineData) { |
1220 | - try |
1221 | - { |
1222 | - parse_line(lineData, handler); |
1223 | - } |
1224 | - catch (std::exception const &e) |
1225 | - { |
1226 | - BOOST_LOG(logger_) << "SmartScopesClient.search(): Failed to parse: " << e.what(); |
1227 | - } |
1228 | + auto reponse_mutex = std::make_shared<std::mutex>(); |
1229 | + query_results_[search_id] = http_client_->get(search_uri.str(), [this, handler, reponse_mutex](std::string const& line_data) |
1230 | + { |
1231 | + std::lock_guard<std::mutex> lock(*reponse_mutex); |
1232 | + try |
1233 | + { |
1234 | + parse_line(line_data, handler); |
1235 | + } |
1236 | + catch (std::exception const &e) |
1237 | + { |
1238 | + BOOST_LOG_SEV(logger_, Logger::Error) << "SmartScopesClient.search(): Failed to parse: " << e.what(); |
1239 | + } |
1240 | }, headers); |
1241 | |
1242 | return SearchHandle::UPtr(new SearchHandle(search_id, shared_from_this())); |
1243 | @@ -488,7 +495,7 @@ |
1244 | std::string const& result, |
1245 | std::string const& session_id, |
1246 | std::string const& platform, |
1247 | - const uint widgets_api_version, |
1248 | + const unsigned int widgets_api_version, |
1249 | VariantMap const& settings, |
1250 | std::string const& locale, |
1251 | std::string const& country, |
1252 | @@ -530,18 +537,22 @@ |
1253 | } |
1254 | |
1255 | std::lock_guard<std::mutex> lock(query_results_mutex_); |
1256 | - uint preview_id = ++query_counter_; |
1257 | + unsigned int preview_id = ++query_counter_; |
1258 | |
1259 | BOOST_LOG_SEV(logger_, Logger::Info) << "SmartScopesClient.preview(): GET " << preview_uri.str(); |
1260 | - query_results_[preview_id] = http_client_->get(preview_uri.str(), [this, handler](std::string const& lineData) { |
1261 | - try |
1262 | - { |
1263 | - parse_line(lineData, handler); |
1264 | - } |
1265 | - catch (std::exception const &e) |
1266 | - { |
1267 | - BOOST_LOG(logger_) << "SmartScopesClient.preview(): Failed to parse: " << e.what(); |
1268 | - } |
1269 | + |
1270 | + auto reponse_mutex = std::make_shared<std::mutex>(); |
1271 | + query_results_[preview_id] = http_client_->get(preview_uri.str(), [this, handler, reponse_mutex](std::string const& line_data) |
1272 | + { |
1273 | + std::lock_guard<std::mutex> lock(*reponse_mutex); |
1274 | + try |
1275 | + { |
1276 | + parse_line(line_data, handler); |
1277 | + } |
1278 | + catch (std::exception const &e) |
1279 | + { |
1280 | + BOOST_LOG_SEV(logger_, Logger::Error) << "SmartScopesClient.preview(): Failed to parse: " << e.what(); |
1281 | + } |
1282 | }, headers); |
1283 | |
1284 | return PreviewHandle::UPtr(new PreviewHandle(preview_id, shared_from_this())); |
1285 | @@ -675,7 +686,7 @@ |
1286 | } |
1287 | } |
1288 | |
1289 | -void SmartScopesClient::wait_for_search(uint search_id) |
1290 | +void SmartScopesClient::wait_for_search(unsigned int search_id) |
1291 | { |
1292 | try |
1293 | { |
1294 | @@ -781,7 +792,7 @@ |
1295 | return FilterStateImpl::deserialize(node->to_variant().get_dict()); |
1296 | } |
1297 | |
1298 | -void SmartScopesClient::wait_for_preview(uint preview_id) |
1299 | +void SmartScopesClient::wait_for_preview(unsigned int preview_id) |
1300 | { |
1301 | try |
1302 | { |
1303 | @@ -817,7 +828,7 @@ |
1304 | { |
1305 | std::vector<std::string> jsons; |
1306 | |
1307 | - uint start_pos = 0; |
1308 | + unsigned int start_pos = 0; |
1309 | |
1310 | while (start_pos < json_stream.size()) |
1311 | { |
1312 | @@ -835,7 +846,7 @@ |
1313 | return jsons; |
1314 | } |
1315 | |
1316 | -void SmartScopesClient::cancel_query(uint query_id) |
1317 | +void SmartScopesClient::cancel_query(unsigned int query_id) |
1318 | { |
1319 | std::lock_guard<std::mutex> lock(query_results_mutex_); |
1320 | |
1321 | |
1322 | === modified file 'test/gtest/scopes/internal/smartscopes/HttpClient/HttpClient_test.cpp' |
1323 | --- test/gtest/scopes/internal/smartscopes/HttpClient/HttpClient_test.cpp 2014-09-03 11:55:23 +0000 |
1324 | +++ test/gtest/scopes/internal/smartscopes/HttpClient/HttpClient_test.cpp 2015-01-20 09:09:48 +0000 |
1325 | @@ -16,7 +16,7 @@ |
1326 | * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
1327 | */ |
1328 | |
1329 | -#include <unity/scopes/internal/smartscopes/HttpClientQt.h> |
1330 | +#include <unity/scopes/internal/smartscopes/HttpClientNetCpp.h> |
1331 | #include <unity/UnityExceptions.h> |
1332 | |
1333 | #include "../RaiiServer.h" |
1334 | @@ -37,8 +37,8 @@ |
1335 | class HttpClientTest : public Test |
1336 | { |
1337 | public: |
1338 | - HttpClientTest(uint no_reply_timeout = 20000) |
1339 | - : http_client_(new HttpClientQt(no_reply_timeout)), |
1340 | + HttpClientTest(unsigned int no_reply_timeout = 20000) |
1341 | + : http_client_(new HttpClientNetCpp(no_reply_timeout)), |
1342 | server_(FAKE_SERVER_PATH) |
1343 | { |
1344 | test_url_ = c_test_url + ":" + std::to_string(server_.port_); |
1345 | |
1346 | === modified file 'test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeSss.py' |
1347 | --- test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeSss.py 2014-12-09 10:44:42 +0000 |
1348 | +++ test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeSss.py 2015-01-20 09:09:48 +0000 |
1349 | @@ -32,7 +32,10 @@ |
1350 | |
1351 | if outfile != '': |
1352 | f = open(outfile, 'a') |
1353 | - f.writelines(["%s : %s\n" % (environ['PATH_INFO'], environ['HTTP_USER_AGENT'])]) |
1354 | + if environ.has_key('HTTP_USER_AGENT'): |
1355 | + f.writelines(["%s : %s\n" % (environ['PATH_INFO'], environ['HTTP_USER_AGENT'])]) |
1356 | + else: |
1357 | + f.writelines(["%s : \n" % (environ['PATH_INFO'])]) |
1358 | |
1359 | if environ['PATH_INFO'] == '/remote-scopes' and (environ['QUERY_STRING'] == '' or environ['QUERY_STRING'] == 'locale=test_TEST'): |
1360 | return [remote_scopes_response] |
1361 | |
1362 | === modified file 'test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp' |
1363 | --- test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp 2015-01-09 03:16:51 +0000 |
1364 | +++ test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp 2015-01-20 09:09:48 +0000 |
1365 | @@ -17,7 +17,8 @@ |
1366 | */ |
1367 | |
1368 | #include <unity/scopes/internal/JsonCppNode.h> |
1369 | -#include <unity/scopes/internal/smartscopes/HttpClientQt.h> |
1370 | +#include <unity/scopes/internal/Logger.h> |
1371 | +#include <unity/scopes/internal/smartscopes/HttpClientNetCpp.h> |
1372 | #include <unity/scopes/internal/smartscopes/SmartScopesClient.h> |
1373 | #include <unity/scopes/OptionSelectorFilter.h> |
1374 | |
1375 | @@ -45,7 +46,7 @@ |
1376 | { |
1377 | public: |
1378 | SmartScopesClientTest() |
1379 | - : http_client_(new HttpClientQt(20000)), |
1380 | + : http_client_(new HttpClientNetCpp(20000)), |
1381 | json_node_(new JsonCppNode()), |
1382 | server_(FAKE_SSS_PATH, FAKE_SSS_LOG) |
1383 | { |
1384 | |
1385 | === modified file 'valgrind-suppress' |
1386 | --- valgrind-suppress 2014-12-10 05:32:14 +0000 |
1387 | +++ valgrind-suppress 2015-01-20 09:09:48 +0000 |
1388 | @@ -63,52 +63,6 @@ |
1389 | obj:/lib/x86_64-linux-gnu/ld-2.18.so |
1390 | } |
1391 | |
1392 | -# False positives for memory leaks in Qt |
1393 | - |
1394 | -{ |
1395 | - QNetworkConfigurationManager |
1396 | - Memcheck:Leak |
1397 | - fun:*alloc |
1398 | - ... |
1399 | - fun:_ZN35QNetworkConfigurationManagerPrivate20updateConfigurationsEv |
1400 | - fun:_ZN35QNetworkConfigurationManagerPrivate10initializeEv |
1401 | -} |
1402 | - |
1403 | -{ |
1404 | - QCoreApplication |
1405 | - Memcheck:Leak |
1406 | - fun:realloc |
1407 | - ... |
1408 | - fun:_ZN7QObject5eventEP6QEvent |
1409 | - fun:_ZN16QCoreApplication6notifyEP7QObjectP6QEvent |
1410 | -} |
1411 | - |
1412 | -{ |
1413 | - QNetworkAccessManager |
1414 | - Memcheck:Leak |
1415 | - ... |
1416 | - fun:_ZN21QNetworkAccessManager13createRequestENS_9OperationERK15QNetworkRequestP9QIODevice |
1417 | - fun:_ZN21QNetworkAccessManager3getERK15QNetworkRequest |
1418 | -} |
1419 | - |
1420 | -{ |
1421 | - QNetworkConfigurationManager |
1422 | - Memcheck:Leak |
1423 | - match-leak-kinds: possible |
1424 | - ... |
1425 | - fun:_ZN7QThread5startENS_8PriorityE |
1426 | - fun:_ZN35QNetworkConfigurationManagerPrivate10initializeEv |
1427 | - fun:_Z35qNetworkConfigurationManagerPrivatev |
1428 | -} |
1429 | - |
1430 | -{ |
1431 | - QFactoryLoader |
1432 | - Memcheck:Leak |
1433 | - fun:*alloc |
1434 | - ... |
1435 | - fun:_ZNK14QFactoryLoader8instanceEi |
1436 | -} |
1437 | - |
1438 | # Bogus "invalid read" reports for ::putenv and ::genenv |
1439 | |
1440 | { |
PASSED: Continuous integration, rev:183 jenkins. qa.ubuntu. com/job/ unity-scopes- api-ci/ 514/ jenkins. qa.ubuntu. com/job/ unity-scopes- api-vivid- amd64-ci/ 39 jenkins. qa.ubuntu. com/job/ unity-scopes- api-vivid- armhf-ci/ 39 jenkins. qa.ubuntu. com/job/ unity-scopes- api-vivid- armhf-ci/ 39/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ unity-scopes- api-vivid- i386-ci/ 39
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- scopes- api-ci/ 514/rebuild
http://