Merge lp:~marcustomlinson/unity-scopes-api/switch-to-net-cpp into lp:unity-scopes-api

Proposed by Marcus Tomlinson
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
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

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
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 HttpClientNetCpp(uint no_reply_timeout);
86 + void cancel_get(uint session_id) override;
88 + uint no_reply_timeout;
416 + std::pair<uint, std::shared_ptr<Cancelable>> add()
424 + uint add(const std::shared_ptr<Cancelable>& cancelable)
428 + uint result{++request_id};
435 + void cancel_and_remove_for_id(uint id)
448 + uint request_id{0};
450 + std::unordered_map<uint, std::shared_ptr<Cancelable>> store;
454 +HttpClientNetCpp::HttpClientNetCpp(uint no_reply_timeout)
529 +void HttpClientNetCpp::cancel_get(uint id)
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();

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michi Henning (michihenning) wrote :

Thanks for that!

One request (please forgive me for being anal):

10 +find_library(ZMQPPLIB zmqpp)
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 :-)

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

> Thanks for that!
>
> One request (please forgive me for being anal):
>
> 10 +find_library(ZMQPPLIB zmqpp)
> 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

Revision history for this message
Michi Henning (michihenning) wrote :

Thanks for that, and thanks for your diligence!

review: Approve
Revision history for this message
Michi Henning (michihenning) wrote :

Not sure what was broken with Jenkins last time around. Top-approving to see what happens.

Revision history for this message
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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 {

Subscribers

People subscribed via source and target branches

to all changes: