Merge lp:~unity-api-team/storage-framework/merge-devel into lp:storage-framework
- merge-devel
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Michi Henning |
Approved revision: | 64 |
Merged at revision: | 11 |
Proposed branch: | lp:~unity-api-team/storage-framework/merge-devel |
Merge into: | lp:storage-framework |
Diff against target: |
14429 lines (+8069/-2223) 126 files modified
CMakeLists.txt (+5/-2) data/provider.xml (+12/-9) debian/bileto_pre_release_hook (+1/-1) debian/changelog (+6/-0) demo/provider_test/CMakeLists.txt (+0/-1) demo/provider_test/provider-test.cpp (+55/-60) include/unity/storage/internal/ItemMetadata.h (+4/-1) include/unity/storage/internal/TraceMessageHandler.h (+47/-0) include/unity/storage/internal/dbus_error.h (+32/-0) include/unity/storage/internal/dbusmarshal.h (+44/-0) include/unity/storage/provider/CMakeLists.txt (+2/-0) include/unity/storage/provider/Exceptions.h (+187/-0) include/unity/storage/provider/ProviderBase.h (+7/-3) include/unity/storage/provider/TempfileUploadJob.h (+6/-0) include/unity/storage/provider/internal/AccountData.h (+5/-0) include/unity/storage/provider/internal/DBusPeerCache.h (+5/-0) include/unity/storage/provider/internal/DownloadJobImpl.h (+0/-4) include/unity/storage/provider/internal/Handler.h (+2/-0) include/unity/storage/provider/internal/MainLoopExecutor.h (+1/-15) include/unity/storage/provider/internal/PendingJobs.h (+21/-11) include/unity/storage/provider/internal/ProviderInterface.h (+5/-0) include/unity/storage/provider/internal/ServerImpl.h (+2/-0) include/unity/storage/provider/internal/TempfileUploadJobImpl.h (+6/-1) include/unity/storage/provider/internal/TestServerImpl.h (+65/-0) include/unity/storage/provider/internal/UploadJobImpl.h (+4/-4) include/unity/storage/provider/internal/dbusmarshal.h (+7/-0) include/unity/storage/provider/metadata_keys.h (+19/-6) include/unity/storage/provider/testing/CMakeLists.txt (+5/-0) include/unity/storage/provider/testing/TestServer.h (+68/-0) include/unity/storage/qt/client/Account.h (+1/-1) include/unity/storage/qt/client/Exceptions.h (+13/-5) include/unity/storage/qt/client/Item.h (+1/-1) include/unity/storage/qt/client/Root.h (+1/-1) include/unity/storage/qt/client/Runtime.h (+13/-0) include/unity/storage/qt/client/Uploader.h (+8/-0) include/unity/storage/qt/client/internal/AccountBase.h (+1/-1) include/unity/storage/qt/client/internal/ItemBase.h (+6/-2) include/unity/storage/qt/client/internal/RootBase.h (+1/-1) include/unity/storage/qt/client/internal/RuntimeBase.h (+9/-4) include/unity/storage/qt/client/internal/UploaderBase.h (+4/-1) include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h (+2/-1) include/unity/storage/qt/client/internal/local_client/FolderImpl.h (+1/-0) include/unity/storage/qt/client/internal/local_client/ItemImpl.h (+4/-7) include/unity/storage/qt/client/internal/local_client/RuntimeImpl.h (+2/-0) include/unity/storage/qt/client/internal/local_client/UploaderImpl.h (+2/-2) include/unity/storage/qt/client/internal/local_client/storage_exception.h (+94/-0) include/unity/storage/qt/client/internal/make_future.h (+21/-37) include/unity/storage/qt/client/internal/remote_client/AccountImpl.h (+2/-1) include/unity/storage/qt/client/internal/remote_client/Handler.h (+38/-2) include/unity/storage/qt/client/internal/remote_client/ItemImpl.h (+0/-3) include/unity/storage/qt/client/internal/remote_client/RuntimeImpl.h (+8/-0) include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h (+4/-2) include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h (+16/-17) include/unity/storage/qt/client/internal/remote_client/validate.h (+51/-0) src/internal/CMakeLists.txt (+5/-0) src/internal/TraceMessageHandler.cpp (+96/-0) src/internal/dbusmarshal.cpp (+113/-0) src/provider/CMakeLists.txt (+48/-17) src/provider/Exceptions.cpp (+157/-0) src/provider/TempfileUploadJob.cpp (+5/-0) src/provider/internal/DownloadJobImpl.cpp (+31/-15) src/provider/internal/Handler.cpp (+84/-13) src/provider/internal/MainLoopExecutor.cpp (+0/-4) src/provider/internal/PendingJobs.cpp (+109/-106) src/provider/internal/ProviderInterface.cpp (+9/-29) src/provider/internal/ServerImpl.cpp (+7/-2) src/provider/internal/TempfileUploadJobImpl.cpp (+21/-1) src/provider/internal/TestServerImpl.cpp (+84/-0) src/provider/internal/UploadJobImpl.cpp (+35/-18) src/provider/internal/dbusmarshal.cpp (+38/-9) src/provider/testing/TestServer.cpp (+60/-0) src/qt/client/Account.cpp (+1/-1) src/qt/client/CMakeLists.txt (+2/-1) src/qt/client/Exceptions.cpp (+14/-9) src/qt/client/Item.cpp (+1/-1) src/qt/client/Root.cpp (+2/-1) src/qt/client/Runtime.cpp (+6/-0) src/qt/client/Uploader.cpp (+5/-0) src/qt/client/internal/AccountBase.cpp (+10/-3) src/qt/client/internal/ItemBase.cpp (+39/-4) src/qt/client/internal/RootBase.cpp (+11/-2) src/qt/client/internal/RuntimeBase.cpp (+0/-5) src/qt/client/internal/UploaderBase.cpp (+11/-2) src/qt/client/internal/local_client/AccountImpl.cpp (+16/-3) src/qt/client/internal/local_client/CMakeLists.txt (+1/-0) src/qt/client/internal/local_client/DownloaderImpl.cpp (+27/-13) src/qt/client/internal/local_client/FileImpl.cpp (+25/-23) src/qt/client/internal/local_client/FolderImpl.cpp (+79/-50) src/qt/client/internal/local_client/ItemImpl.cpp (+148/-131) src/qt/client/internal/local_client/RootImpl.cpp (+88/-18) src/qt/client/internal/local_client/RuntimeImpl.cpp (+16/-1) src/qt/client/internal/local_client/UploaderImpl.cpp (+53/-36) src/qt/client/internal/local_client/storage_exception.cpp (+99/-0) src/qt/client/internal/remote_client/AccountImpl.cpp (+28/-10) src/qt/client/internal/remote_client/CMakeLists.txt (+1/-0) src/qt/client/internal/remote_client/DownloaderImpl.cpp (+7/-5) src/qt/client/internal/remote_client/FileImpl.cpp (+42/-26) src/qt/client/internal/remote_client/FolderImpl.cpp (+82/-42) src/qt/client/internal/remote_client/ItemImpl.cpp (+91/-68) src/qt/client/internal/remote_client/RootImpl.cpp (+67/-12) src/qt/client/internal/remote_client/RuntimeImpl.cpp (+81/-14) src/qt/client/internal/remote_client/UploaderImpl.cpp (+32/-17) src/qt/client/internal/remote_client/dbusmarshal.cpp (+102/-90) src/qt/client/internal/remote_client/validate.cpp (+169/-0) tests/CMakeLists.txt (+5/-2) tests/headers/CMakeLists.txt (+5/-0) tests/headers/compile_headers.py (+10/-13) tests/local-client/local-client_test.cpp (+1794/-338) tests/provider-AccountData/AccountData_test.cpp (+141/-0) tests/provider-AccountData/CMakeLists.txt (+8/-0) tests/provider-DBusPeerCache/CMakeLists.txt (+8/-0) tests/provider-DBusPeerCache/DBusPeerCache_test.cpp (+141/-0) tests/provider-ProviderInterface/CMakeLists.txt (+16/-0) tests/provider-ProviderInterface/ProviderInterface_test.cpp (+789/-0) tests/provider-ProviderInterface/TestProvider.cpp (+462/-0) tests/provider-ProviderInterface/TestProvider.h (+65/-0) tests/remote-client/CMakeLists.txt (+4/-3) tests/remote-client/MockProvider.cpp (+236/-0) tests/remote-client/MockProvider.h (+96/-0) tests/remote-client/remote-client_test.cpp (+947/-856) tests/utils/CMakeLists.txt (+16/-2) tests/utils/DBusEnvironment.cpp (+5/-0) tests/utils/DBusEnvironment.h (+1/-0) tests/utils/ProviderFixture.cpp (+84/-0) tests/utils/ProviderFixture.h (+50/-0) tests/utils/fake-online-accounts-daemon.py (+2/-0) |
To merge this branch: | bzr merge lp:~unity-api-team/storage-framework/merge-devel |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michi Henning (community) | Approve | ||
Review via email: mp+302665@code.launchpad.net |
Commit message
Merged devel at revision 64. Lots of fixes in preparation for integration with backup service and mcloud provider.
Description of the change
Merged devel at revision 64. Lots of fixes in preparation for integration with backup service and mcloud provider.
Michi Henning (michihenning) wrote : | # |
Oops, sorry, that wasn't meant to be approved.
- 57. By Michi Henning
-
Increased remote client coverage.
Approved by James Henstridge, unity-api-1-bot.
- 58. By Michi Henning
-
Added provider headers to unit tests.
Approved by unity-api-1-bot, James Henstridge.
- 59. By Michi Henning
-
Removed half-close on the provider side because this messes with QLocalSocket on the client side.
Approved by James Henstridge, unity-api-1-bot.
- 60. By Michi Henning
-
Increased test timeouts because CI builders are hopelessly overloaded.
Approved by unity-api-1-bot, James Henstridge.
- 61. By James Henstridge
-
Add a drain() method to UploadJob to allow the provider to read the last bit of data from the socket when the client asks to finish the upload.
Approved by unity-api-1-bot, Michi Henning.
- 62. By Michi Henning
-
Don't throw when unknown metadata key is received and log a warning instead.
Approved by unity-api-1-bot, Michi Henning, James Henstridge.
- 63. By Michi Henning
-
Removed stale debug trace. Suppressed more compile warnings from system headers that caused a lot of noise in the arm builds.
Approved by James Henstridge, unity-api-1-bot.
- 64. By Michi Henning
-
Merged devel at revision 64.
- 65. By Michi Henning
-
Merged devel at revision 68.
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2016-07-22 08:38:24 +0000 |
3 | +++ CMakeLists.txt 2016-09-09 02:13:43 +0000 |
4 | @@ -17,7 +17,7 @@ |
5 | # These two should be incremented when the ABI changes. |
6 | set(SF_CLIENT_SOVERSION "0") |
7 | execute_process( |
8 | - COMMAND /bin/sh ${CMAKE_CURRENT_SOURCE_DIR}/get-provider-soversion.sh |
9 | + COMMAND /bin/sh ${CMAKE_CURRENT_SOURCE_DIR}/tools/get-provider-soversion.sh |
10 | OUTPUT_VARIABLE SF_PROVIDER_SOVERSION |
11 | OUTPUT_STRIP_TRAILING_WHITESPACE |
12 | RESULT_VARIABLE result) |
13 | @@ -108,7 +108,7 @@ |
14 | |
15 | include(GNUInstallDirs) |
16 | |
17 | -find_package(Boost COMPONENTS filesystem system thread REQUIRED) |
18 | +find_package(Boost 1.56 COMPONENTS filesystem system thread REQUIRED) |
19 | find_package(Qt5Concurrent REQUIRED) |
20 | find_package(Qt5Core REQUIRED) |
21 | find_package(Qt5DBus REQUIRED) |
22 | @@ -130,8 +130,11 @@ |
23 | enable_coverage_report( |
24 | TARGETS |
25 | qt-client-lib-common |
26 | + storage-framework-common-internal |
27 | storage-framework-qt-client |
28 | storage-framework-qt-local-client |
29 | + sf-provider-objects |
30 | + storage-framework-provider |
31 | FILTER |
32 | ${CMAKE_SOURCE_DIR}/tests/* |
33 | ${CMAKE_BINARY_DIR}/* |
34 | |
35 | === modified file 'data/provider.xml' |
36 | --- data/provider.xml 2016-07-11 07:17:04 +0000 |
37 | +++ data/provider.xml 2016-09-09 02:13:43 +0000 |
38 | @@ -5,14 +5,17 @@ |
39 | com.canonical.StorageFramework.Provider: |
40 | @short_description: Interface providing access to a storage account |
41 | |
42 | - For methods dealing with metadata, the representation |
43 | - "(ssssia{sv})" is used, where the struct members are: |
44 | + For methods returning metadata, the representation |
45 | + "(sasssia{sv})" is used, where the struct members are: |
46 | - item_id |
47 | - - parent_id |
48 | + - parent_ids |
49 | - name |
50 | - etag |
51 | - type (enum: file, folder, root) |
52 | - metadata |
53 | + |
54 | + Note that parent_ids is a sequence of IDs instead of a single ID to allow the client to |
55 | + navigate items in Google Drive, which permits more than one parent for a file or folder. |
56 | --> |
57 | <interface name="com.canonical.StorageFramework.Provider"> |
58 | <!-- |
59 | @@ -25,7 +28,7 @@ |
60 | of files, this list will contain a single item. |
61 | --> |
62 | <method name="Roots"> |
63 | - <arg type="a(ssssia{sv})" name="roots" direction="out"/> |
64 | + <arg type="a(sasssia{sv})" name="roots" direction="out"/> |
65 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList<unity::storage::internal::ItemMetadata>"/> |
66 | </method> |
67 | |
68 | @@ -45,7 +48,7 @@ |
69 | <method name="List"> |
70 | <arg type="s" name="item_id" direction="in"/> |
71 | <arg type="s" name="page_token" direction="in"/> |
72 | - <arg type="a(ssssia{sv})" name="children" direction="out"/> |
73 | + <arg type="a(sasssia{sv})" name="children" direction="out"/> |
74 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList<unity::storage::internal::ItemMetadata>"/> |
75 | <arg type="s" name="next_token" direction="out"/> |
76 | </method> |
77 | @@ -60,7 +63,7 @@ |
78 | <method name="Lookup"> |
79 | <arg type="s" name="parent_id" direction="in"/> |
80 | <arg type="s" name="name" direction="in"/> |
81 | - <arg type="a(ssssia{sv})" name="items" direction="out"/> |
82 | + <arg type="a(sasssia{sv})" name="items" direction="out"/> |
83 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList<unity::storage::internal::ItemMetadata>"/> |
84 | </method> |
85 | |
86 | @@ -72,7 +75,7 @@ |
87 | --> |
88 | <method name="Metadata"> |
89 | <arg type="s" name="item_id" direction="in"/> |
90 | - <arg type="(ssssia{sv})" name="metadata" direction="out"/> |
91 | + <arg type="(sasssia{sv})" name="metadata" direction="out"/> |
92 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="unity::storage::internal::ItemMetadata"/> |
93 | </method> |
94 | |
95 | @@ -86,7 +89,7 @@ |
96 | <method name="CreateFolder"> |
97 | <arg type="s" name="parent_id" direction="in"/> |
98 | <arg type="s" name="name" direction="in"/> |
99 | - <arg type="(ssssia{sv})" name="metadata" direction="out"/> |
100 | + <arg type="(sasssia{sv})" name="metadata" direction="out"/> |
101 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="unity::storage::internal::ItemMetadata"/> |
102 | </method> |
103 | |
104 | @@ -160,7 +163,7 @@ |
105 | --> |
106 | <method name="FinishUpload"> |
107 | <arg type="s" name="upload_id" direction="in"/> |
108 | - <arg type="(ssssia{sv})" name="metadata" direction="out"/> |
109 | + <arg type="(sasssia{sv})" name="metadata" direction="out"/> |
110 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="unity::storage::internal::ItemMetadata"/> |
111 | </method> |
112 | |
113 | |
114 | === modified file 'debian/bileto_pre_release_hook' |
115 | --- debian/bileto_pre_release_hook 2016-07-22 04:23:08 +0000 |
116 | +++ debian/bileto_pre_release_hook 2016-09-09 02:13:43 +0000 |
117 | @@ -2,7 +2,7 @@ |
118 | |
119 | set -eu |
120 | |
121 | -soversion=$(sh ./get-provider-soversion.sh) |
122 | +soversion=$(sh ./tools/get-provider-soversion.sh) |
123 | |
124 | infile=./debian/control.in |
125 | outfile=./debian/control |
126 | |
127 | === modified file 'debian/changelog' |
128 | --- debian/changelog 2016-08-04 07:20:09 +0000 |
129 | +++ debian/changelog 2016-09-09 02:13:43 +0000 |
130 | @@ -1,3 +1,9 @@ |
131 | +storage-framework (0.1+16.10.20160804.1-0ubuntu2) UNRELEASED; urgency=medium |
132 | + |
133 | + * Merged devel at revision 64. |
134 | + |
135 | + -- Michi Henning <michi.henning@canonical.com> Fri, 26 Aug 2016 14:03:02 +1000 |
136 | + |
137 | storage-framework (0.1+16.10.20160804.1-0ubuntu1) yakkety; urgency=medium |
138 | |
139 | [ Michi Henning ] |
140 | |
141 | === modified file 'demo/provider_test/CMakeLists.txt' |
142 | --- demo/provider_test/CMakeLists.txt 2016-05-23 02:27:16 +0000 |
143 | +++ demo/provider_test/CMakeLists.txt 2016-09-09 02:13:43 +0000 |
144 | @@ -1,4 +1,3 @@ |
145 | - |
146 | add_definitions(-DBOOST_THREAD_VERSION=4) |
147 | |
148 | add_executable(provider-test provider-test.cpp) |
149 | |
150 | === modified file 'demo/provider_test/provider-test.cpp' |
151 | --- demo/provider_test/provider-test.cpp 2016-07-26 03:30:05 +0000 |
152 | +++ demo/provider_test/provider-test.cpp 2016-09-09 02:13:43 +0000 |
153 | @@ -17,6 +17,8 @@ |
154 | */ |
155 | |
156 | #include <unity/storage/provider/DownloadJob.h> |
157 | +#include <unity/storage/provider/Exceptions.h> |
158 | +#include <unity/storage/provider/metadata_keys.h> |
159 | #include <unity/storage/provider/ProviderBase.h> |
160 | #include <unity/storage/provider/Server.h> |
161 | #include <unity/storage/provider/TempfileUploadJob.h> |
162 | @@ -32,47 +34,8 @@ |
163 | using namespace unity::storage::provider; |
164 | using namespace std; |
165 | |
166 | -#if BOOST_VERSION >= 105600 |
167 | using boost::make_ready_future; |
168 | using boost::make_exceptional_future; |
169 | -#else |
170 | -namespace |
171 | -{ |
172 | - |
173 | -boost::future<void> make_ready_future() |
174 | -{ |
175 | - boost::promise<void> p; |
176 | - p.set_value(); |
177 | - return p.get_future(); |
178 | -} |
179 | - |
180 | -template <typename T> |
181 | -boost::future<T> make_ready_future(T& value) |
182 | -{ |
183 | - boost::promise<T> p; |
184 | - p.set_value(value); |
185 | - return p.get_future(); |
186 | -} |
187 | - |
188 | -template <typename T> |
189 | -boost::future<T> make_ready_future(T&& value) |
190 | -{ |
191 | - boost::promise<T> p; |
192 | - p.set_value(std::move(value)); |
193 | - return p.get_future(); |
194 | -} |
195 | - |
196 | -template <typename T, typename E> |
197 | -boost::future<T> make_exceptional_future(E const& ex) |
198 | -{ |
199 | - boost::promise<T> p; |
200 | - p.set_exception(boost::copy_exception(ex)); |
201 | - return p.get_future(); |
202 | -} |
203 | - |
204 | -} |
205 | -#endif |
206 | - |
207 | |
208 | class MyProvider : public ProviderBase |
209 | { |
210 | @@ -140,7 +103,7 @@ |
211 | printf("roots() called by %s (%d)\n", ctx.security_label.c_str(), ctx.pid); |
212 | fflush(stdout); |
213 | ItemList roots = { |
214 | - {"root_id", "", "Root", "etag", ItemType::root, {}}, |
215 | + {"root_id", {}, "Root", "etag", ItemType::root, {}}, |
216 | }; |
217 | return make_ready_future<ItemList>(roots); |
218 | } |
219 | @@ -153,14 +116,20 @@ |
220 | fflush(stdout); |
221 | if (item_id != "root_id") |
222 | { |
223 | - return make_exceptional_future<tuple<ItemList,string>>(runtime_error("unknown folder")); |
224 | + string msg = string("Item::list(): no such item: \"") + item_id + "\""; |
225 | + return make_exceptional_future<tuple<ItemList,string>>(NotExistsException(msg, item_id)); |
226 | } |
227 | if (page_token != "") |
228 | { |
229 | - return make_exceptional_future<tuple<ItemList,string>>(runtime_error("unknown page token")); |
230 | + string msg = string("Item::list(): invalid page token: \"") + page_token + "\""; |
231 | + return make_exceptional_future<tuple<ItemList,string>>(LogicException(msg)); |
232 | } |
233 | - ItemList children = { |
234 | - {"child_id", "root_id", "Child", "etag", ItemType::file, {}} |
235 | + ItemList children = |
236 | + { |
237 | + { |
238 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
239 | + { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
240 | + } |
241 | }; |
242 | boost::promise<tuple<ItemList,string>> p; |
243 | p.set_value(make_tuple(children, string())); |
244 | @@ -172,12 +141,20 @@ |
245 | { |
246 | printf("lookup('%s', '%s') called by %s (%d)\n", parent_id.c_str(), name.c_str(), ctx.security_label.c_str(), ctx.pid); |
247 | fflush(stdout); |
248 | - if (parent_id != "root_id" || name != "Child") |
249 | - { |
250 | - return make_exceptional_future<ItemList>(runtime_error("file not found")); |
251 | - } |
252 | - ItemList children = { |
253 | - {"child_id", "root_id", "Child", "etag", ItemType::file, {}} |
254 | + if (parent_id != "root_id") |
255 | + { |
256 | + string msg = string("Folder::lookup(): no such item: \"") + parent_id + "\""; |
257 | + return make_exceptional_future<ItemList>(NotExistsException(msg, parent_id)); |
258 | + } |
259 | + if (name != "Child") |
260 | + { |
261 | + string msg = string("Folder::lookup(): no such item: \"") + name + "\""; |
262 | + return make_exceptional_future<ItemList>(NotExistsException(msg, name)); |
263 | + } |
264 | + ItemList children = |
265 | + { |
266 | + { "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
267 | + { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } } |
268 | }; |
269 | return make_ready_future<ItemList>(children); |
270 | } |
271 | @@ -189,15 +166,24 @@ |
272 | fflush(stdout); |
273 | if (item_id == "root_id") |
274 | { |
275 | - Item metadata{"root_id", "", "Root", "etag", ItemType::root, {}}; |
276 | + Item metadata{"root_id", {}, "Root", "etag", ItemType::root, {}}; |
277 | return make_ready_future<Item>(metadata); |
278 | } |
279 | else if (item_id == "child_id") |
280 | { |
281 | - Item metadata{"child_id", "root_id", "Child", "etag", ItemType::file, {}}; |
282 | - return make_ready_future<Item>(metadata); |
283 | - } |
284 | - return make_exceptional_future<Item>(runtime_error("no such file")); |
285 | + Item metadata |
286 | + { |
287 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
288 | + { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
289 | + }; |
290 | + return make_ready_future<Item>(metadata); |
291 | + } |
292 | + else if (item_id == "child_folder_id") |
293 | + { |
294 | + Item metadata{"child_folder_id", { "root_id" }, "Child_Folder", "etag", ItemType::folder, {}}; |
295 | + return make_ready_future<Item>(metadata); |
296 | + } |
297 | + return make_exceptional_future<Item>(NotExistsException("metadata(): no such item: " + item_id, item_id)); |
298 | } |
299 | |
300 | boost::future<Item> MyProvider::create_folder( |
301 | @@ -206,7 +192,7 @@ |
302 | { |
303 | printf("create_folder('%s', '%s') called by %s (%d)\n", parent_id.c_str(), name.c_str(), ctx.security_label.c_str(), ctx.pid); |
304 | fflush(stdout); |
305 | - Item metadata{"new_folder_id", parent_id, name, "etag", ItemType::folder, {}}; |
306 | + Item metadata{"new_folder_id", { parent_id }, name, "etag", ItemType::folder, {}}; |
307 | return make_ready_future<Item>(metadata); |
308 | } |
309 | |
310 | @@ -242,7 +228,12 @@ |
311 | |
312 | unique_ptr<DownloadJob> job(new MyDownloadJob(make_job_id())); |
313 | const char contents[] = "Hello world"; |
314 | - write(job->write_socket(), contents, sizeof(contents)); |
315 | + if (write(job->write_socket(), contents, sizeof(contents)) != sizeof(contents)) |
316 | + { |
317 | + ResourceException e("download(): write failed", errno); |
318 | + job->report_error(make_exception_ptr(e)); |
319 | + return make_exceptional_future<unique_ptr<DownloadJob>>(e); |
320 | + } |
321 | job->report_complete(); |
322 | return make_ready_future(std::move(job)); |
323 | } |
324 | @@ -261,7 +252,7 @@ |
325 | { |
326 | printf("move('%s', '%s', '%s') called by %s (%d)\n", item_id.c_str(), new_parent_id.c_str(), new_name.c_str(), ctx.security_label.c_str(), ctx.pid); |
327 | fflush(stdout); |
328 | - Item metadata{item_id, new_parent_id, new_name, "etag", ItemType::file, {}}; |
329 | + Item metadata{item_id, { new_parent_id }, new_name, "etag", ItemType::file, {}}; |
330 | return make_ready_future(metadata); |
331 | } |
332 | |
333 | @@ -271,7 +262,7 @@ |
334 | { |
335 | printf("copy('%s', '%s', '%s') called by %s (%d)\n", item_id.c_str(), new_parent_id.c_str(), new_name.c_str(), ctx.security_label.c_str(), ctx.pid); |
336 | fflush(stdout); |
337 | - Item metadata{"new_item_id", new_parent_id, new_name, "etag", ItemType::file, {}}; |
338 | + Item metadata{"new_item_id", { new_parent_id }, new_name, "etag", ItemType::file, {}}; |
339 | return make_ready_future(metadata); |
340 | } |
341 | |
342 | @@ -294,7 +285,11 @@ |
343 | unlink(new_filename.c_str()); |
344 | link(old_filename.c_str(), new_filename.c_str()); |
345 | |
346 | - Item metadata{"some_id", "", "some_upload", "etag", ItemType::file, {}}; |
347 | + Item metadata |
348 | + { |
349 | + "some_id", { "root_id" }, "some_upload", "etag", ItemType::file, |
350 | + { { SIZE_IN_BYTES, 10 }, { LAST_MODIFIED_TIME, "2011-04-05T14:30:10.005Z" } } |
351 | + }; |
352 | return make_ready_future(metadata); |
353 | } |
354 | |
355 | |
356 | === modified file 'include/unity/storage/internal/ItemMetadata.h' |
357 | --- include/unity/storage/internal/ItemMetadata.h 2016-07-12 02:22:05 +0000 |
358 | +++ include/unity/storage/internal/ItemMetadata.h 2016-09-09 02:13:43 +0000 |
359 | @@ -21,9 +21,12 @@ |
360 | #include <unity/storage/common.h> |
361 | |
362 | #pragma GCC diagnostic push |
363 | +#pragma GCC diagnostic ignored "-Wcast-align" |
364 | #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
365 | +#pragma GCC diagnostic ignored "-Wswitch-default" |
366 | #include <QMap> |
367 | #include <QVariant> |
368 | +#include <QVector> |
369 | #pragma GCC diagnostic pop |
370 | |
371 | namespace unity |
372 | @@ -36,7 +39,7 @@ |
373 | struct ItemMetadata |
374 | { |
375 | QString item_id; |
376 | - QString parent_id; |
377 | + QVector<QString> parent_ids; |
378 | QString name; |
379 | QString etag; |
380 | ItemType type; |
381 | |
382 | === added file 'include/unity/storage/internal/TraceMessageHandler.h' |
383 | --- include/unity/storage/internal/TraceMessageHandler.h 1970-01-01 00:00:00 +0000 |
384 | +++ include/unity/storage/internal/TraceMessageHandler.h 2016-09-09 02:13:43 +0000 |
385 | @@ -0,0 +1,47 @@ |
386 | +/* |
387 | + * Copyright (C) 2015 Canonical Ltd |
388 | + * |
389 | + * This program is free software: you can redistribute it and/or modify |
390 | + * it under the terms of the GNU Lesser General Public License version 3 as |
391 | + * published by the Free Software Foundation. |
392 | + * |
393 | + * This program is distributed in the hope that it will be useful, |
394 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
395 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
396 | + * GNU Lesser General Public License for more details. |
397 | + * |
398 | + * You should have received a copy of the GNU Lesser General Public License |
399 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
400 | + * |
401 | + * Authors: Michi Henning <michi.henning@canonical.com> |
402 | + */ |
403 | + |
404 | +#pragma once |
405 | + |
406 | +#pragma GCC diagnostic push |
407 | +#pragma GCC diagnostic ignored "-Wcast-align" |
408 | +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
409 | +#pragma GCC diagnostic ignored "-Wswitch-default" |
410 | +#include <QDebug> |
411 | +#pragma GCC diagnostic pop |
412 | + |
413 | +namespace unity |
414 | +{ |
415 | +namespace storage |
416 | +{ |
417 | +namespace internal |
418 | +{ |
419 | + |
420 | +class TraceMessageHandler final |
421 | +{ |
422 | +public: |
423 | + TraceMessageHandler(std::string const& prog_name); |
424 | + ~TraceMessageHandler(); |
425 | + |
426 | +private: |
427 | + QtMessageHandler old_message_handler_; |
428 | +}; |
429 | + |
430 | +} // namespace internal |
431 | +} // namespace storage |
432 | +} // namespace unity |
433 | |
434 | === added file 'include/unity/storage/internal/dbus_error.h' |
435 | --- include/unity/storage/internal/dbus_error.h 1970-01-01 00:00:00 +0000 |
436 | +++ include/unity/storage/internal/dbus_error.h 2016-09-09 02:13:43 +0000 |
437 | @@ -0,0 +1,32 @@ |
438 | +/* |
439 | + * Copyright (C) 2016 Canonical Ltd |
440 | + * |
441 | + * This program is free software: you can redistribute it and/or modify |
442 | + * it under the terms of the GNU Lesser General Public License version 3 as |
443 | + * published by the Free Software Foundation. |
444 | + * |
445 | + * This program is distributed in the hope that it will be useful, |
446 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
447 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
448 | + * GNU Lesser General Public License for more details. |
449 | + * |
450 | + * You should have received a copy of the GNU Lesser General Public License |
451 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
452 | + * |
453 | + * Authors: Michi Henning <michi.henning@canonical.com> |
454 | + */ |
455 | + |
456 | +#pragma once |
457 | + |
458 | +namespace unity |
459 | +{ |
460 | +namespace storage |
461 | +{ |
462 | +namespace internal |
463 | +{ |
464 | + |
465 | +constexpr char DBUS_ERROR_PREFIX[] = "com.canonical.StorageFramework."; |
466 | + |
467 | +} // namespace internal |
468 | +} // namespace storage |
469 | +} // namespace unity |
470 | |
471 | === added file 'include/unity/storage/internal/dbusmarshal.h' |
472 | --- include/unity/storage/internal/dbusmarshal.h 1970-01-01 00:00:00 +0000 |
473 | +++ include/unity/storage/internal/dbusmarshal.h 2016-09-09 02:13:43 +0000 |
474 | @@ -0,0 +1,44 @@ |
475 | +/* |
476 | + * Copyright (C) 2016 Canonical Ltd |
477 | + * |
478 | + * This program is free software: you can redistribute it and/or modify |
479 | + * it under the terms of the GNU Lesser General Public License version 3 as |
480 | + * published by the Free Software Foundation. |
481 | + * |
482 | + * This program is distributed in the hope that it will be useful, |
483 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
484 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
485 | + * GNU Lesser General Public License for more details. |
486 | + * |
487 | + * You should have received a copy of the GNU Lesser General Public License |
488 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
489 | + * |
490 | + * Authors: Michi Henning <michi.henning@canonical.com> |
491 | + */ |
492 | + |
493 | +#pragma once |
494 | + |
495 | +#include <unity/storage/internal/ItemMetadata.h> |
496 | + |
497 | +#include <QDBusArgument> |
498 | +#include <QMetaType> |
499 | + |
500 | +namespace unity |
501 | +{ |
502 | +namespace storage |
503 | +{ |
504 | +namespace internal |
505 | +{ |
506 | + |
507 | +QDBusArgument& operator<<(QDBusArgument& argument, ItemMetadata const& metadata); |
508 | +QDBusArgument const& operator>>(QDBusArgument const& argument, ItemMetadata& metadata); |
509 | + |
510 | +QDBusArgument& operator<<(QDBusArgument& argument, QList<ItemMetadata> const& md_list); |
511 | +QDBusArgument const& operator>>(QDBusArgument const& argument, QList<ItemMetadata>& md_list); |
512 | + |
513 | +} // namespace internal |
514 | +} // storage |
515 | +} // unity |
516 | + |
517 | +Q_DECLARE_METATYPE(unity::storage::internal::ItemMetadata) |
518 | +Q_DECLARE_METATYPE(QList<unity::storage::internal::ItemMetadata>) |
519 | |
520 | === modified file 'include/unity/storage/provider/CMakeLists.txt' |
521 | --- include/unity/storage/provider/CMakeLists.txt 2016-07-11 03:28:40 +0000 |
522 | +++ include/unity/storage/provider/CMakeLists.txt 2016-09-09 02:13:43 +0000 |
523 | @@ -3,3 +3,5 @@ |
524 | |
525 | install(FILES ${provider_headers} |
526 | DESTINATION ${provider_base_includedir}/${includeprefix}) |
527 | + |
528 | +add_subdirectory(testing) |
529 | |
530 | === added file 'include/unity/storage/provider/Exceptions.h' |
531 | --- include/unity/storage/provider/Exceptions.h 1970-01-01 00:00:00 +0000 |
532 | +++ include/unity/storage/provider/Exceptions.h 2016-09-09 02:13:43 +0000 |
533 | @@ -0,0 +1,187 @@ |
534 | +/* |
535 | + * Copyright (C) 2016 Canonical Ltd |
536 | + * |
537 | + * This program is free software: you can redistribute it and/or modify |
538 | + * it under the terms of the GNU Lesser General Public License version 3 as |
539 | + * published by the Free Software Foundation. |
540 | + * |
541 | + * This program is distributed in the hope that it will be useful, |
542 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
543 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
544 | + * GNU Lesser General Public License for more details. |
545 | + * |
546 | + * You should have received a copy of the GNU Lesser General Public License |
547 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
548 | + * |
549 | + * Authors: Michi Henning <michi.henning@canonical.com> |
550 | + */ |
551 | + |
552 | +#pragma once |
553 | + |
554 | +#include <unity/storage/visibility.h> |
555 | + |
556 | +#include <string> |
557 | + |
558 | +namespace unity |
559 | +{ |
560 | +namespace storage |
561 | +{ |
562 | +namespace provider |
563 | +{ |
564 | + |
565 | +// Note: Adding new exception types also requires updating the marshaling and |
566 | +// unmarshaling code for exceptions in the client and server APIs. |
567 | + |
568 | +/** |
569 | +\brief Base exception class for all server-side exceptions. |
570 | +*/ |
571 | +class UNITY_STORAGE_EXPORT StorageException : public std::exception |
572 | +{ |
573 | +public: |
574 | + StorageException(std::string const& exception_type, std::string const& error_message); |
575 | + ~StorageException(); |
576 | + |
577 | + virtual char const* what() const noexcept override; |
578 | + |
579 | + std::string type() const; |
580 | + std::string error_message() const; |
581 | + |
582 | +private: |
583 | + std::string what_string_; |
584 | + std::string type_; |
585 | + std::string error_message_; |
586 | +}; |
587 | + |
588 | +/** |
589 | +\brief Indicates errors in the communication between the storage provider and the cloud service. |
590 | +*/ |
591 | +class UNITY_STORAGE_EXPORT RemoteCommsException : public StorageException |
592 | +{ |
593 | +public: |
594 | + RemoteCommsException(std::string const& error_message); |
595 | + ~RemoteCommsException(); |
596 | +}; |
597 | + |
598 | +/** |
599 | +\brief Indicates that an item does not exist or could not be found. |
600 | +*/ |
601 | +class UNITY_STORAGE_EXPORT NotExistsException : public StorageException |
602 | +{ |
603 | +public: |
604 | + NotExistsException(std::string const& error_message, std::string const& key); |
605 | + ~NotExistsException(); |
606 | + |
607 | + std::string key() const; |
608 | + |
609 | +private: |
610 | + std::string key_; |
611 | +}; |
612 | + |
613 | +/** |
614 | +\brief Indicates that an item cannot be created because it exists already. |
615 | +*/ |
616 | +class UNITY_STORAGE_EXPORT ExistsException : public StorageException |
617 | +{ |
618 | +public: |
619 | + ExistsException(std::string const& error_message, std::string const& identity, std::string const& name); |
620 | + ~ExistsException(); |
621 | + |
622 | + std::string native_identity() const; |
623 | + std::string name() const; |
624 | + |
625 | +private: |
626 | + std::string identity_; |
627 | + std::string name_; |
628 | +}; |
629 | + |
630 | +/** |
631 | +\brief Indicates that an upload detected a version mismatch. |
632 | +*/ |
633 | +class UNITY_STORAGE_EXPORT ConflictException : public StorageException |
634 | +{ |
635 | +public: |
636 | + ConflictException(std::string const& error_message); |
637 | + ~ConflictException(); |
638 | +}; |
639 | + |
640 | +/** |
641 | +\brief Indicates that an operation failed because of a permission problem. |
642 | +*/ |
643 | +class UNITY_STORAGE_EXPORT PermissionException : public StorageException |
644 | +{ |
645 | +public: |
646 | + PermissionException(std::string const& error_message); |
647 | + ~PermissionException(); |
648 | +}; |
649 | + |
650 | +/** |
651 | +\brief Indicates that an update failed because the provider ran out of space. |
652 | +*/ |
653 | +class UNITY_STORAGE_EXPORT QuotaException : public StorageException |
654 | +{ |
655 | +public: |
656 | + QuotaException(std::string const& error_message); |
657 | + ~QuotaException(); |
658 | +}; |
659 | + |
660 | +/** |
661 | +\brief Indicates that an upload or download was cancelled before it could complete. |
662 | +*/ |
663 | +class UNITY_STORAGE_EXPORT CancelledException : public StorageException |
664 | +{ |
665 | +public: |
666 | + CancelledException(std::string const& error_message); |
667 | + ~CancelledException(); |
668 | +}; |
669 | + |
670 | +/** |
671 | +\brief Indicates incorrect use of the API, such as calling methods in the wrong order. |
672 | +*/ |
673 | +class UNITY_STORAGE_EXPORT LogicException : public StorageException |
674 | +{ |
675 | +public: |
676 | + LogicException(std::string const& error_message); |
677 | + ~LogicException(); |
678 | +}; |
679 | + |
680 | +/** |
681 | +\brief Indicates an invalid parameter, such as a negative value when a positive one was |
682 | +expected, or a string that does not parse correctly or is empty when it should be non-empty. |
683 | +*/ |
684 | +class UNITY_STORAGE_EXPORT InvalidArgumentException : public StorageException |
685 | +{ |
686 | +public: |
687 | + InvalidArgumentException(std::string const& error_message); |
688 | + ~InvalidArgumentException(); |
689 | +}; |
690 | + |
691 | +/** |
692 | +\brief Indicates a system error, such as failure to create a file or folder, |
693 | +or any other (usually non-recoverable) kind of error that should not arise during normal operation. |
694 | +*/ |
695 | +class UNITY_STORAGE_EXPORT ResourceException : public StorageException |
696 | +{ |
697 | +public: |
698 | + ResourceException(std::string const& error_message, int error_code); |
699 | + ~ResourceException(); |
700 | + |
701 | + int error_code() const noexcept; |
702 | + |
703 | +private: |
704 | + int error_code_; |
705 | +}; |
706 | + |
707 | +/** |
708 | +\brief Indicates that the server side caught an exception that does not derive from |
709 | +StorageException, such as a std::exception, or caught some other unknown type (such as `int`). |
710 | +*/ |
711 | +class UNITY_STORAGE_EXPORT UnknownException : public StorageException |
712 | +{ |
713 | +public: |
714 | + UnknownException(std::string const& error_message); |
715 | + ~UnknownException(); |
716 | +}; |
717 | + |
718 | +} // namespace provider |
719 | +} // namespace storage |
720 | +} // namespace unity |
721 | |
722 | === modified file 'include/unity/storage/provider/ProviderBase.h' |
723 | --- include/unity/storage/provider/ProviderBase.h 2016-07-14 00:17:14 +0000 |
724 | +++ include/unity/storage/provider/ProviderBase.h 2016-09-09 02:13:43 +0000 |
725 | @@ -23,6 +23,7 @@ |
726 | #include <unity/storage/provider/Credentials.h> |
727 | |
728 | #include <boost/thread/future.hpp> |
729 | +#include <boost/variant.hpp> |
730 | |
731 | #include <sys/types.h> |
732 | #include <string> |
733 | @@ -48,15 +49,18 @@ |
734 | Credentials credentials; |
735 | }; |
736 | |
737 | +// Note: When growing the set of supported variant types, add new types |
738 | +// to the *end* of the list, and update the marshaling code in dbusmarshal.cpp. |
739 | +typedef boost::variant<std::string, int64_t> MetadataValue; |
740 | + |
741 | struct UNITY_STORAGE_EXPORT Item |
742 | { |
743 | std::string item_id; |
744 | - std::string parent_id; |
745 | + std::vector<std::string> parent_ids; |
746 | std::string name; |
747 | std::string etag; |
748 | unity::storage::ItemType type; |
749 | - // Should be map<string,variant> |
750 | - std::map<std::string,std::string> metadata; |
751 | + std::map<std::string, MetadataValue> metadata; |
752 | }; |
753 | |
754 | typedef std::vector<Item> ItemList; |
755 | |
756 | === modified file 'include/unity/storage/provider/TempfileUploadJob.h' |
757 | --- include/unity/storage/provider/TempfileUploadJob.h 2016-07-12 02:22:05 +0000 |
758 | +++ include/unity/storage/provider/TempfileUploadJob.h 2016-09-09 02:13:43 +0000 |
759 | @@ -44,6 +44,12 @@ |
760 | |
761 | std::string file_name() const; |
762 | |
763 | + // This function should be called from your finish() |
764 | + // implementation to read the remaining data from the socket. If |
765 | + // the client has not closed the socket as expected, LogicError |
766 | + // will be thrown. |
767 | + void drain(); |
768 | + |
769 | protected: |
770 | TempfileUploadJob(internal::TempfileUploadJobImpl *p) UNITY_STORAGE_HIDDEN; |
771 | }; |
772 | |
773 | === modified file 'include/unity/storage/provider/internal/AccountData.h' |
774 | --- include/unity/storage/provider/internal/AccountData.h 2016-07-12 02:22:05 +0000 |
775 | +++ include/unity/storage/provider/internal/AccountData.h 2016-09-09 02:13:43 +0000 |
776 | @@ -20,10 +20,15 @@ |
777 | |
778 | #include <unity/storage/provider/Credentials.h> |
779 | |
780 | +#pragma GCC diagnostic push |
781 | +#pragma GCC diagnostic ignored "-Wcast-align" |
782 | +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
783 | +#pragma GCC diagnostic ignored "-Wswitch-default" |
784 | #include <OnlineAccounts/Account> |
785 | #include <OnlineAccounts/PendingCallWatcher> |
786 | #include <QObject> |
787 | #include <QDBusConnection> |
788 | +#pragma GCC diagnostic pop |
789 | |
790 | #include <string> |
791 | |
792 | |
793 | === modified file 'include/unity/storage/provider/internal/DBusPeerCache.h' |
794 | --- include/unity/storage/provider/internal/DBusPeerCache.h 2016-07-12 02:22:05 +0000 |
795 | +++ include/unity/storage/provider/internal/DBusPeerCache.h 2016-09-09 02:13:43 +0000 |
796 | @@ -20,8 +20,13 @@ |
797 | #pragma once |
798 | |
799 | #include <boost/thread/future.hpp> |
800 | +#pragma GCC diagnostic push |
801 | +#pragma GCC diagnostic ignored "-Wcast-align" |
802 | +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
803 | +#pragma GCC diagnostic ignored "-Wswitch-default" |
804 | #include <QDBusConnection> |
805 | #include <QDBusPendingReply> |
806 | +#pragma GCC diagnostic pop |
807 | #include <QString> |
808 | |
809 | #include <functional> |
810 | |
811 | === modified file 'include/unity/storage/provider/internal/DownloadJobImpl.h' |
812 | --- include/unity/storage/provider/internal/DownloadJobImpl.h 2016-07-12 02:22:05 +0000 |
813 | +++ include/unity/storage/provider/internal/DownloadJobImpl.h 2016-09-09 02:13:43 +0000 |
814 | @@ -48,9 +48,6 @@ |
815 | int write_socket() const; |
816 | int take_read_socket(); |
817 | |
818 | - std::string const& sender_bus_name() const; |
819 | - void set_sender_bus_name(std::string const& bus_name); |
820 | - |
821 | void report_complete(); |
822 | void report_error(std::exception_ptr p); |
823 | boost::future<void> finish(DownloadJob& job); |
824 | @@ -63,7 +60,6 @@ |
825 | std::string const download_id_; |
826 | int read_socket_ = -1; |
827 | int write_socket_ = -1; |
828 | - std::string sender_bus_name_; |
829 | |
830 | std::mutex completion_lock_; |
831 | bool completed_ = false; |
832 | |
833 | === modified file 'include/unity/storage/provider/internal/Handler.h' |
834 | --- include/unity/storage/provider/internal/Handler.h 2016-07-19 07:08:50 +0000 |
835 | +++ include/unity/storage/provider/internal/Handler.h 2016-09-09 02:13:43 +0000 |
836 | @@ -63,6 +63,8 @@ |
837 | void finished(); |
838 | |
839 | private: |
840 | + void marshal_exception(std::exception_ptr ep); |
841 | + |
842 | std::shared_ptr<AccountData> const account_; |
843 | Callback const callback_; |
844 | QDBusConnection const bus_; |
845 | |
846 | === modified file 'include/unity/storage/provider/internal/MainLoopExecutor.h' |
847 | --- include/unity/storage/provider/internal/MainLoopExecutor.h 2016-07-19 03:26:36 +0000 |
848 | +++ include/unity/storage/provider/internal/MainLoopExecutor.h 2016-09-09 02:13:43 +0000 |
849 | @@ -19,13 +19,7 @@ |
850 | #pragma once |
851 | |
852 | #include <boost/version.hpp> |
853 | - |
854 | -#if BOOST_VERSION >= 105600 |
855 | -# define SF_SUPPORTS_EXECUTORS |
856 | -#endif |
857 | -#ifdef SF_SUPPORTS_EXECUTORS |
858 | -# include <boost/thread/executor.hpp> |
859 | -#endif |
860 | +#include <boost/thread/executor.hpp> |
861 | #include <QObject> |
862 | |
863 | #include <functional> |
864 | @@ -39,8 +33,6 @@ |
865 | namespace internal |
866 | { |
867 | |
868 | -#ifdef SF_SUPPORTS_EXECUTORS |
869 | - |
870 | /* Declare future continuations like so to execute within the event |
871 | * loop if possible: |
872 | * |
873 | @@ -72,12 +64,6 @@ |
874 | Q_DISABLE_COPY(MainLoopExecutor) |
875 | }; |
876 | |
877 | -#else |
878 | - |
879 | -#define EXEC_IN_MAIN /*nothing*/ |
880 | - |
881 | -#endif |
882 | - |
883 | } |
884 | } |
885 | } |
886 | |
887 | === modified file 'include/unity/storage/provider/internal/PendingJobs.h' |
888 | --- include/unity/storage/provider/internal/PendingJobs.h 2016-07-12 02:22:05 +0000 |
889 | +++ include/unity/storage/provider/internal/PendingJobs.h 2016-09-09 02:13:43 +0000 |
890 | @@ -18,14 +18,21 @@ |
891 | |
892 | #pragma once |
893 | |
894 | +#pragma GCC diagnostic push |
895 | +#pragma GCC diagnostic ignored "-Wcast-align" |
896 | +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
897 | +#pragma GCC diagnostic ignored "-Wswitch-default" |
898 | #include <QDBusConnection> |
899 | #include <QDBusServiceWatcher> |
900 | #include <QObject> |
901 | +#include <QString> |
902 | +#pragma GCC diagnostic pop |
903 | |
904 | #include <map> |
905 | #include <memory> |
906 | #include <mutex> |
907 | #include <string> |
908 | +#include <utility> |
909 | |
910 | namespace unity |
911 | { |
912 | @@ -49,27 +56,30 @@ |
913 | explicit PendingJobs(QDBusConnection const& bus, QObject *parent=nullptr); |
914 | virtual ~PendingJobs(); |
915 | |
916 | - void add_download(std::unique_ptr<DownloadJob> &&job); |
917 | - std::shared_ptr<DownloadJob> get_download(std::string const& download_id); |
918 | - std::shared_ptr<DownloadJob> remove_download(std::string const& download_id); |
919 | + void add_download(QString const& client_bus_name, std::unique_ptr<DownloadJob> &&job); |
920 | + std::shared_ptr<DownloadJob> remove_download(QString const& client_bus_name, std::string const& download_id); |
921 | |
922 | - void add_upload(std::unique_ptr<UploadJob> &&job); |
923 | - std::shared_ptr<UploadJob> get_upload(std::string const& upload_id); |
924 | - std::shared_ptr<UploadJob> remove_upload(std::string const& upload_id); |
925 | + void add_upload(QString const& client_bus_name, std::unique_ptr<UploadJob> &&job); |
926 | + std::shared_ptr<UploadJob> remove_upload(QString const& client_bus_name, std::string const& upload_id); |
927 | |
928 | private Q_SLOTS: |
929 | void service_disconnected(QString const& service_name); |
930 | |
931 | private: |
932 | - void watch_peer(std::string const& bus_name); |
933 | - void unwatch_peer(std::string const& bus_name); |
934 | + void watch_peer(QString const& bus_name); |
935 | + void unwatch_peer(QString const& bus_name); |
936 | + |
937 | + template <typename Job> |
938 | + void cancel_job(std::shared_ptr<Job> const& job, |
939 | + std::string const& identifier); |
940 | |
941 | std::mutex lock_; |
942 | - std::map<std::string,std::shared_ptr<UploadJob>> uploads_; |
943 | - std::map<std::string,std::shared_ptr<DownloadJob>> downloads_; |
944 | + // Key is client_bus_name and upload or download ID. |
945 | + std::map<std::pair<QString,std::string>,std::shared_ptr<UploadJob>> uploads_; |
946 | + std::map<std::pair<QString,std::string>,std::shared_ptr<DownloadJob>> downloads_; |
947 | |
948 | QDBusServiceWatcher watcher_; |
949 | - std::map<std::string,int> services_; |
950 | + std::map<QString,int> services_; |
951 | |
952 | Q_DISABLE_COPY(PendingJobs) |
953 | }; |
954 | |
955 | === modified file 'include/unity/storage/provider/internal/ProviderInterface.h' |
956 | --- include/unity/storage/provider/internal/ProviderInterface.h 2016-07-14 00:17:14 +0000 |
957 | +++ include/unity/storage/provider/internal/ProviderInterface.h 2016-09-09 02:13:43 +0000 |
958 | @@ -21,11 +21,16 @@ |
959 | #include <unity/storage/internal/ItemMetadata.h> |
960 | #include <unity/storage/provider/internal/Handler.h> |
961 | |
962 | +#pragma GCC diagnostic push |
963 | +#pragma GCC diagnostic ignored "-Wcast-align" |
964 | +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
965 | +#pragma GCC diagnostic ignored "-Wswitch-default" |
966 | #include <QObject> |
967 | #include <QList> |
968 | #include <QDBusConnection> |
969 | #include <QDBusContext> |
970 | #include <QDBusUnixFileDescriptor> |
971 | +#pragma GCC diagnostic pop |
972 | |
973 | #include <map> |
974 | #include <memory> |
975 | |
976 | === modified file 'include/unity/storage/provider/internal/ServerImpl.h' |
977 | --- include/unity/storage/provider/internal/ServerImpl.h 2016-07-12 02:22:05 +0000 |
978 | +++ include/unity/storage/provider/internal/ServerImpl.h 2016-09-09 02:13:43 +0000 |
979 | @@ -19,6 +19,7 @@ |
980 | #pragma once |
981 | |
982 | #include <unity/storage/provider/Server.h> |
983 | +#include <unity/storage/internal/TraceMessageHandler.h> |
984 | #include <unity/storage/provider/internal/DBusPeerCache.h> |
985 | #include <unity/storage/provider/internal/ProviderInterface.h> |
986 | |
987 | @@ -58,6 +59,7 @@ |
988 | ServerBase* const server_; |
989 | std::string const bus_name_; |
990 | std::string const service_id_; |
991 | + unity::storage::internal::TraceMessageHandler trace_message_handler_; |
992 | |
993 | std::unique_ptr<QCoreApplication> app_; |
994 | std::unique_ptr<OnlineAccounts::Manager> manager_; |
995 | |
996 | === modified file 'include/unity/storage/provider/internal/TempfileUploadJobImpl.h' |
997 | --- include/unity/storage/provider/internal/TempfileUploadJobImpl.h 2016-07-12 02:22:05 +0000 |
998 | +++ include/unity/storage/provider/internal/TempfileUploadJobImpl.h 2016-09-09 02:13:43 +0000 |
999 | @@ -20,8 +20,12 @@ |
1000 | |
1001 | #include <unity/storage/provider/internal/UploadJobImpl.h> |
1002 | |
1003 | +#pragma GCC diagnostic push |
1004 | +#pragma GCC diagnostic ignored "-Wcast-align" |
1005 | +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
1006 | #include <QLocalSocket> |
1007 | #include <QTemporaryFile> |
1008 | +#pragma GCC diagnostic pop |
1009 | |
1010 | #include <memory> |
1011 | #include <string> |
1012 | @@ -43,6 +47,7 @@ |
1013 | virtual ~TempfileUploadJobImpl(); |
1014 | |
1015 | void complete_init() override; |
1016 | + void drain(); |
1017 | |
1018 | std::string file_name() const; |
1019 | |
1020 | @@ -51,8 +56,8 @@ |
1021 | void on_read_channel_finished(); |
1022 | |
1023 | private: |
1024 | + std::unique_ptr<QTemporaryFile> tmpfile_; |
1025 | std::unique_ptr<QLocalSocket> reader_; |
1026 | - std::unique_ptr<QTemporaryFile> tmpfile_; |
1027 | |
1028 | Q_DISABLE_COPY(TempfileUploadJobImpl) |
1029 | }; |
1030 | |
1031 | === added file 'include/unity/storage/provider/internal/TestServerImpl.h' |
1032 | --- include/unity/storage/provider/internal/TestServerImpl.h 1970-01-01 00:00:00 +0000 |
1033 | +++ include/unity/storage/provider/internal/TestServerImpl.h 2016-09-09 02:13:43 +0000 |
1034 | @@ -0,0 +1,65 @@ |
1035 | +/* |
1036 | + * Copyright (C) 2016 Canonical Ltd |
1037 | + * |
1038 | + * This program is free software: you can redistribute it and/or modify |
1039 | + * it under the terms of the GNU Lesser General Public License version 3 as |
1040 | + * published by the Free Software Foundation. |
1041 | + * |
1042 | + * This program is distributed in the hope that it will be useful, |
1043 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1044 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1045 | + * GNU Lesser General Public License for more details. |
1046 | + * |
1047 | + * You should have received a copy of the GNU Lesser General Public License |
1048 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1049 | + * |
1050 | + * Authors: James Henstridge <james.henstridge@canonical.com> |
1051 | + */ |
1052 | + |
1053 | +#pragma once |
1054 | + |
1055 | +#include <unity/storage/provider/testing/TestServer.h> |
1056 | + |
1057 | +#pragma GCC diagnostic push |
1058 | +#pragma GCC diagnostic ignored "-Wcast-align" |
1059 | +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
1060 | +#include <QDBusConnection> |
1061 | +#pragma GCC diagnostic pop |
1062 | + |
1063 | +#include <memory> |
1064 | +#include <string> |
1065 | + |
1066 | +namespace unity |
1067 | +{ |
1068 | +namespace storage |
1069 | +{ |
1070 | +namespace provider |
1071 | +{ |
1072 | +namespace internal |
1073 | +{ |
1074 | + |
1075 | +class ProviderInterface; |
1076 | + |
1077 | +class TestServerImpl |
1078 | +{ |
1079 | +public: |
1080 | + TestServerImpl(std::unique_ptr<ProviderBase>&& provider, |
1081 | + OnlineAccounts::Account* account, |
1082 | + QDBusConnection const& connection, |
1083 | + std::string const& object_path); |
1084 | + ~TestServerImpl(); |
1085 | + |
1086 | + QDBusConnection const& connection() const; |
1087 | + std::string const& object_path() const; |
1088 | + |
1089 | +private: |
1090 | + QDBusConnection connection_; |
1091 | + std::string const object_path_; |
1092 | + |
1093 | + std::unique_ptr<ProviderInterface> interface_; |
1094 | +}; |
1095 | + |
1096 | +} |
1097 | +} |
1098 | +} |
1099 | +} |
1100 | |
1101 | === modified file 'include/unity/storage/provider/internal/UploadJobImpl.h' |
1102 | --- include/unity/storage/provider/internal/UploadJobImpl.h 2016-07-12 02:22:05 +0000 |
1103 | +++ include/unity/storage/provider/internal/UploadJobImpl.h 2016-09-09 02:13:43 +0000 |
1104 | @@ -21,7 +21,11 @@ |
1105 | #include <unity/storage/provider/ProviderBase.h> |
1106 | |
1107 | #include <boost/thread/future.hpp> |
1108 | +#pragma GCC diagnostic push |
1109 | +#pragma GCC diagnostic ignored "-Wcast-align" |
1110 | +#pragma GCC diagnostic ignored "-Wswitch-default" |
1111 | #include <QObject> |
1112 | +#pragma GCC diagnostic pop |
1113 | |
1114 | #include <exception> |
1115 | #include <mutex> |
1116 | @@ -49,9 +53,6 @@ |
1117 | int read_socket() const; |
1118 | int take_write_socket(); |
1119 | |
1120 | - std::string const& sender_bus_name() const; |
1121 | - void set_sender_bus_name(std::string const& bus_name); |
1122 | - |
1123 | void report_error(std::exception_ptr p); |
1124 | boost::future<Item> finish(UploadJob& job); |
1125 | boost::future<void> cancel(UploadJob& job); |
1126 | @@ -63,7 +64,6 @@ |
1127 | std::string const upload_id_; |
1128 | int read_socket_ = -1; |
1129 | int write_socket_ = -1; |
1130 | - std::string sender_bus_name_; |
1131 | |
1132 | std::mutex completion_lock_; |
1133 | bool completed_ = false; |
1134 | |
1135 | === modified file 'include/unity/storage/provider/internal/dbusmarshal.h' |
1136 | --- include/unity/storage/provider/internal/dbusmarshal.h 2016-07-12 02:22:05 +0000 |
1137 | +++ include/unity/storage/provider/internal/dbusmarshal.h 2016-09-09 02:13:43 +0000 |
1138 | @@ -18,8 +18,15 @@ |
1139 | |
1140 | #pragma once |
1141 | |
1142 | +#include <unity/storage/provider/ProviderBase.h> |
1143 | + |
1144 | +#pragma GCC diagnostic push |
1145 | +#pragma GCC diagnostic ignored "-Wcast-align" |
1146 | +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
1147 | #include <QDBusArgument> |
1148 | #include <QVariant> |
1149 | +#pragma GCC diagnostic pop |
1150 | + |
1151 | #include <vector> |
1152 | |
1153 | namespace unity |
1154 | |
1155 | === renamed file 'include/unity/storage/internal/MetadataKeys.h' => 'include/unity/storage/provider/metadata_keys.h' |
1156 | --- include/unity/storage/internal/MetadataKeys.h 2016-07-14 00:25:40 +0000 |
1157 | +++ include/unity/storage/provider/metadata_keys.h 2016-09-09 02:13:43 +0000 |
1158 | @@ -18,15 +18,28 @@ |
1159 | |
1160 | #pragma once |
1161 | |
1162 | +#include <unordered_map> |
1163 | + |
1164 | namespace unity |
1165 | { |
1166 | namespace storage |
1167 | { |
1168 | -namespace internal |
1169 | -{ |
1170 | - |
1171 | -static char constexpr CREATION_TIME[] = "creation_time"; |
1172 | - |
1173 | -} // namespace internal |
1174 | +namespace provider |
1175 | +{ |
1176 | + |
1177 | +static char constexpr SIZE_IN_BYTES[] = "size_in_bytes"; // int64_t, >= 0 |
1178 | +static char constexpr CREATION_TIME[] = "creation_time"; // String, ISO 8601 format |
1179 | +static char constexpr LAST_MODIFIED_TIME[] = "last_modified_time"; // String, ISO 8601 format |
1180 | + |
1181 | +enum class MetadataType { int64, iso_8601_date_time }; |
1182 | + |
1183 | +static std::unordered_map<std::string, MetadataType> known_metadata = |
1184 | +{ |
1185 | + { SIZE_IN_BYTES, MetadataType::int64 }, |
1186 | + { CREATION_TIME, MetadataType::iso_8601_date_time }, |
1187 | + { LAST_MODIFIED_TIME, MetadataType::iso_8601_date_time } |
1188 | +}; |
1189 | + |
1190 | +} // namespace provider |
1191 | } // namespace storage |
1192 | } // namespace unity |
1193 | |
1194 | === added directory 'include/unity/storage/provider/testing' |
1195 | === added file 'include/unity/storage/provider/testing/CMakeLists.txt' |
1196 | --- include/unity/storage/provider/testing/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1197 | +++ include/unity/storage/provider/testing/CMakeLists.txt 2016-09-09 02:13:43 +0000 |
1198 | @@ -0,0 +1,5 @@ |
1199 | +set(includeprefix unity/storage/provider/testing) |
1200 | +file(GLOB provider_headers *.h) |
1201 | + |
1202 | +install(FILES ${provider_headers} |
1203 | + DESTINATION ${provider_base_includedir}/${includeprefix}) |
1204 | |
1205 | === added file 'include/unity/storage/provider/testing/TestServer.h' |
1206 | --- include/unity/storage/provider/testing/TestServer.h 1970-01-01 00:00:00 +0000 |
1207 | +++ include/unity/storage/provider/testing/TestServer.h 2016-09-09 02:13:43 +0000 |
1208 | @@ -0,0 +1,68 @@ |
1209 | +/* |
1210 | + * Copyright (C) 2016 Canonical Ltd |
1211 | + * |
1212 | + * This program is free software: you can redistribute it and/or modify |
1213 | + * it under the terms of the GNU Lesser General Public License version 3 as |
1214 | + * published by the Free Software Foundation. |
1215 | + * |
1216 | + * This program is distributed in the hope that it will be useful, |
1217 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1218 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1219 | + * GNU Lesser General Public License for more details. |
1220 | + * |
1221 | + * You should have received a copy of the GNU Lesser General Public License |
1222 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1223 | + * |
1224 | + * Authors: James Henstridge <james.henstridge@canonical.com> |
1225 | + */ |
1226 | + |
1227 | +#pragma once |
1228 | + |
1229 | +#include <unity/storage/visibility.h> |
1230 | + |
1231 | +#include <memory> |
1232 | +#include <string> |
1233 | + |
1234 | +namespace OnlineAccounts |
1235 | +{ |
1236 | +class Account; |
1237 | +} |
1238 | +class QDBusConnection; |
1239 | + |
1240 | +namespace unity |
1241 | +{ |
1242 | +namespace storage |
1243 | +{ |
1244 | +namespace provider |
1245 | +{ |
1246 | + |
1247 | +class ProviderBase; |
1248 | + |
1249 | +namespace internal |
1250 | +{ |
1251 | +class TestServerImpl; |
1252 | +} |
1253 | + |
1254 | +namespace testing |
1255 | +{ |
1256 | + |
1257 | +class UNITY_STORAGE_EXPORT TestServer |
1258 | +{ |
1259 | +public: |
1260 | + TestServer(std::unique_ptr<ProviderBase>&& provider, |
1261 | + OnlineAccounts::Account* account, |
1262 | + QDBusConnection const& connection, |
1263 | + std::string const& object_path); |
1264 | + ~TestServer(); |
1265 | + |
1266 | + QDBusConnection const& connection() const; |
1267 | + std::string const& object_path() const; |
1268 | + |
1269 | +private: |
1270 | + std::unique_ptr<internal::TestServerImpl> p_; |
1271 | +}; |
1272 | + |
1273 | +} |
1274 | +} |
1275 | +} |
1276 | +} |
1277 | |
1278 | === modified file 'include/unity/storage/qt/client/Account.h' |
1279 | --- include/unity/storage/qt/client/Account.h 2016-07-22 02:35:12 +0000 |
1280 | +++ include/unity/storage/qt/client/Account.h 2016-09-09 02:13:43 +0000 |
1281 | @@ -77,7 +77,7 @@ |
1282 | |
1283 | typedef std::shared_ptr<Account> SPtr; |
1284 | |
1285 | - Runtime* runtime() const; |
1286 | + std::shared_ptr<Runtime> runtime() const; |
1287 | |
1288 | QString owner() const; |
1289 | QString owner_id() const; |
1290 | |
1291 | === modified file 'include/unity/storage/qt/client/Exceptions.h' |
1292 | --- include/unity/storage/qt/client/Exceptions.h 2016-07-22 02:35:12 +0000 |
1293 | +++ include/unity/storage/qt/client/Exceptions.h 2016-09-09 02:13:43 +0000 |
1294 | @@ -20,7 +20,10 @@ |
1295 | |
1296 | #include <unity/storage/visibility.h> |
1297 | |
1298 | +#pragma GCC diagnostic push |
1299 | +#pragma GCC diagnostic ignored "-Wcast-align" |
1300 | #include <QException> |
1301 | +#pragma GCC diagnostic pop |
1302 | #include <QString> |
1303 | |
1304 | namespace unity |
1305 | @@ -46,6 +49,8 @@ |
1306 | |
1307 | virtual char const* what() const noexcept override; |
1308 | |
1309 | + QString error_message() const; |
1310 | + |
1311 | private: |
1312 | std::string what_string_; |
1313 | QString error_message_; |
1314 | @@ -83,18 +88,16 @@ |
1315 | class UNITY_STORAGE_EXPORT DeletedException : public StorageException |
1316 | { |
1317 | public: |
1318 | - DeletedException(QString const& error_message, QString const& identity_, QString const& name_); |
1319 | + DeletedException(QString const& error_message, QString const& identity_); |
1320 | ~DeletedException(); |
1321 | |
1322 | virtual DeletedException* clone() const override; |
1323 | virtual void raise() const override; |
1324 | |
1325 | QString native_identity() const; |
1326 | - QString name() const; |
1327 | |
1328 | private: |
1329 | QString identity_; |
1330 | - QString name_; |
1331 | }; |
1332 | |
1333 | /** |
1334 | @@ -228,17 +231,22 @@ |
1335 | }; |
1336 | |
1337 | /** |
1338 | -\brief Indicates a system error, such as failure to to create a file or folder, |
1339 | +\brief Indicates a system error, such as failure to create a file or folder, |
1340 | or any other (usually non-recoverable) kind of error that should not arise during normal operation. |
1341 | */ |
1342 | class UNITY_STORAGE_EXPORT ResourceException : public StorageException |
1343 | { |
1344 | public: |
1345 | - ResourceException(QString const& error_message); |
1346 | + ResourceException(QString const& error_message, int error_code); |
1347 | ~ResourceException(); |
1348 | |
1349 | virtual ResourceException* clone() const override; |
1350 | virtual void raise() const override; |
1351 | + |
1352 | + int error_code() const noexcept; |
1353 | + |
1354 | +private: |
1355 | + int error_code_; |
1356 | }; |
1357 | |
1358 | } // namespace client |
1359 | |
1360 | === modified file 'include/unity/storage/qt/client/Item.h' |
1361 | --- include/unity/storage/qt/client/Item.h 2016-07-22 02:45:24 +0000 |
1362 | +++ include/unity/storage/qt/client/Item.h 2016-09-09 02:13:43 +0000 |
1363 | @@ -103,7 +103,7 @@ |
1364 | |
1365 | If this item is a root, the returned pointer points at this item. |
1366 | */ |
1367 | - Root* root() const; |
1368 | + std::shared_ptr<Root> root() const; |
1369 | |
1370 | /** |
1371 | \brief Returns the type of the item. |
1372 | |
1373 | === modified file 'include/unity/storage/qt/client/Root.h' |
1374 | --- include/unity/storage/qt/client/Root.h 2016-07-12 02:22:05 +0000 |
1375 | +++ include/unity/storage/qt/client/Root.h 2016-09-09 02:13:43 +0000 |
1376 | @@ -70,7 +70,7 @@ |
1377 | /** |
1378 | \brief Returns the account for this root. |
1379 | */ |
1380 | - Account* account() const; |
1381 | + std::shared_ptr<Account> account() const; |
1382 | |
1383 | QFuture<int64_t> free_space_bytes() const; |
1384 | QFuture<int64_t> used_space_bytes() const; |
1385 | |
1386 | === modified file 'include/unity/storage/qt/client/Runtime.h' |
1387 | --- include/unity/storage/qt/client/Runtime.h 2016-07-22 02:35:12 +0000 |
1388 | +++ include/unity/storage/qt/client/Runtime.h 2016-09-09 02:13:43 +0000 |
1389 | @@ -44,6 +44,7 @@ |
1390 | namespace internal |
1391 | { |
1392 | |
1393 | +class AccountBase; |
1394 | class RuntimeBase; |
1395 | |
1396 | namespace remote_client |
1397 | @@ -95,11 +96,23 @@ |
1398 | |
1399 | QFuture<QVector<std::shared_ptr<Account>>> accounts(); |
1400 | |
1401 | + /// @cond |
1402 | + /** |
1403 | + \brief Creates an Account object pointing at (bus_name, object_path) |
1404 | + |
1405 | + This method is intended for use in tests, where you want to talk |
1406 | + to a provider that has already been set up on the bus. |
1407 | + */ |
1408 | + std::shared_ptr<Account> make_test_account(QString const& bus_name, |
1409 | + QString const& object_path); |
1410 | + /// @endcond |
1411 | + |
1412 | private: |
1413 | Runtime(internal::RuntimeBase* p) UNITY_STORAGE_HIDDEN; |
1414 | |
1415 | std::shared_ptr<internal::RuntimeBase> p_; |
1416 | |
1417 | + friend class internal::AccountBase; |
1418 | friend class internal::remote_client::AccountImpl; |
1419 | }; |
1420 | |
1421 | |
1422 | === modified file 'include/unity/storage/qt/client/Uploader.h' |
1423 | --- include/unity/storage/qt/client/Uploader.h 2016-07-22 02:35:12 +0000 |
1424 | +++ include/unity/storage/qt/client/Uploader.h 2016-09-09 02:13:43 +0000 |
1425 | @@ -92,6 +92,14 @@ |
1426 | std::shared_ptr<QLocalSocket> socket() const; |
1427 | |
1428 | /** |
1429 | + \brief Returns the size that was passed to Folder::create_file() or File::create_uploader(). |
1430 | + |
1431 | + \return The number of bytes that the uploader expects to be written to the `QLocalSocket` returned |
1432 | + from socket(). |
1433 | + */ |
1434 | + int64_t size() const; |
1435 | + |
1436 | + /** |
1437 | \brief Finalizes the upload. |
1438 | |
1439 | Once you have written the file contents to the socket returned by socket(), you must call finish_upload(), |
1440 | |
1441 | === modified file 'include/unity/storage/qt/client/internal/AccountBase.h' |
1442 | --- include/unity/storage/qt/client/internal/AccountBase.h 2016-07-22 02:35:12 +0000 |
1443 | +++ include/unity/storage/qt/client/internal/AccountBase.h 2016-09-09 02:13:43 +0000 |
1444 | @@ -52,7 +52,7 @@ |
1445 | AccountBase(AccountBase const&) = delete; |
1446 | AccountBase& operator=(AccountBase const&) = delete; |
1447 | |
1448 | - Runtime* runtime() const; |
1449 | + std::shared_ptr<Runtime> runtime() const; |
1450 | virtual QString owner() const = 0; |
1451 | virtual QString owner_id() const = 0; |
1452 | virtual QString description() const = 0; |
1453 | |
1454 | === modified file 'include/unity/storage/qt/client/internal/ItemBase.h' |
1455 | --- include/unity/storage/qt/client/internal/ItemBase.h 2016-07-27 02:19:17 +0000 |
1456 | +++ include/unity/storage/qt/client/internal/ItemBase.h 2016-09-09 02:13:43 +0000 |
1457 | @@ -20,10 +20,10 @@ |
1458 | |
1459 | #include <unity/storage/common.h> |
1460 | |
1461 | -#include <QDateTime> |
1462 | #pragma GCC diagnostic push |
1463 | #pragma GCC diagnostic ignored "-Wcast-align" |
1464 | #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
1465 | +#include <QDateTime> |
1466 | #include <QFuture> |
1467 | #pragma GCC diagnostic pop |
1468 | #include <QVariantMap> |
1469 | @@ -60,7 +60,7 @@ |
1470 | |
1471 | QString native_identity() const; |
1472 | ItemType type() const; |
1473 | - Root* root() const; |
1474 | + std::shared_ptr<Root> root() const; |
1475 | |
1476 | virtual QString name() const = 0; |
1477 | virtual QString etag() const = 0; |
1478 | @@ -82,10 +82,14 @@ |
1479 | void set_public_instance(std::weak_ptr<Item> p); |
1480 | |
1481 | protected: |
1482 | + std::shared_ptr<Root> get_root() const noexcept; |
1483 | + void throw_if_destroyed(QString const& method) const; |
1484 | + |
1485 | const QString identity_; |
1486 | const ItemType type_; |
1487 | std::weak_ptr<Root> root_; |
1488 | std::weak_ptr<Item> public_instance_; |
1489 | + bool deleted_ = false; |
1490 | |
1491 | friend class ItemImpl; |
1492 | }; |
1493 | |
1494 | === modified file 'include/unity/storage/qt/client/internal/RootBase.h' |
1495 | --- include/unity/storage/qt/client/internal/RootBase.h 2016-07-12 02:22:05 +0000 |
1496 | +++ include/unity/storage/qt/client/internal/RootBase.h 2016-09-09 02:13:43 +0000 |
1497 | @@ -46,7 +46,7 @@ |
1498 | public: |
1499 | RootBase(QString const& identity, std::weak_ptr<Account> const& account); |
1500 | |
1501 | - Account* account() const; |
1502 | + std::shared_ptr<Account> account() const; |
1503 | virtual QFuture<int64_t> free_space_bytes() const = 0; |
1504 | virtual QFuture<int64_t> used_space_bytes() const = 0; |
1505 | virtual QFuture<Item::SPtr> get(QString native_identity) const = 0; |
1506 | |
1507 | === modified file 'include/unity/storage/qt/client/internal/RuntimeBase.h' |
1508 | --- include/unity/storage/qt/client/internal/RuntimeBase.h 2016-07-22 02:35:12 +0000 |
1509 | +++ include/unity/storage/qt/client/internal/RuntimeBase.h 2016-09-09 02:13:43 +0000 |
1510 | @@ -25,7 +25,6 @@ |
1511 | #pragma GCC diagnostic pop |
1512 | #include <QVector> |
1513 | |
1514 | -#include <atomic> |
1515 | #include <memory> |
1516 | |
1517 | namespace unity |
1518 | @@ -43,23 +42,29 @@ |
1519 | namespace internal |
1520 | { |
1521 | |
1522 | +class AccountBase; |
1523 | + |
1524 | class RuntimeBase : public QObject |
1525 | { |
1526 | public: |
1527 | - RuntimeBase(); |
1528 | + RuntimeBase() = default; |
1529 | virtual ~RuntimeBase() = default; |
1530 | RuntimeBase(RuntimeBase const&) = delete; |
1531 | RuntimeBase& operator=(RuntimeBase const&) = delete; |
1532 | |
1533 | virtual void shutdown() = 0; |
1534 | virtual QFuture<QVector<std::shared_ptr<Account>>> accounts() = 0; |
1535 | + virtual std::shared_ptr<Account> make_test_account(QString const& bus_name, |
1536 | + QString const& object_path) = 0; |
1537 | |
1538 | void set_public_instance(std::weak_ptr<Runtime> p); |
1539 | |
1540 | protected: |
1541 | - std::atomic_bool destroyed_; |
1542 | - QVector<std::shared_ptr<Account>> accounts_; // Immutable once set |
1543 | + bool destroyed_ = false; |
1544 | + QVector<std::shared_ptr<Account>> accounts_; |
1545 | std::weak_ptr<Runtime> public_instance_; // Immutable once set |
1546 | + |
1547 | + friend class unity::storage::qt::client::internal::AccountBase; |
1548 | }; |
1549 | |
1550 | } // namespace internal |
1551 | |
1552 | === modified file 'include/unity/storage/qt/client/internal/UploaderBase.h' |
1553 | --- include/unity/storage/qt/client/internal/UploaderBase.h 2016-07-22 02:35:12 +0000 |
1554 | +++ include/unity/storage/qt/client/internal/UploaderBase.h 2016-09-09 02:13:43 +0000 |
1555 | @@ -47,7 +47,7 @@ |
1556 | class UploaderBase : public QObject |
1557 | { |
1558 | public: |
1559 | - UploaderBase(ConflictPolicy policy); |
1560 | + UploaderBase(ConflictPolicy policy, int64_t size); |
1561 | UploaderBase(UploaderBase&) = delete; |
1562 | UploaderBase& operator=(UploaderBase const&) = delete; |
1563 | |
1564 | @@ -55,8 +55,11 @@ |
1565 | virtual QFuture<std::shared_ptr<File>> finish_upload() = 0; |
1566 | virtual QFuture<void> cancel() noexcept = 0; |
1567 | |
1568 | + int64_t size() const; |
1569 | + |
1570 | protected: |
1571 | ConflictPolicy policy_; |
1572 | + int64_t size_; |
1573 | }; |
1574 | |
1575 | } // namespace internal |
1576 | |
1577 | === modified file 'include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h' |
1578 | --- include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h 2016-07-14 04:50:36 +0000 |
1579 | +++ include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h 2016-09-09 02:13:43 +0000 |
1580 | @@ -60,7 +60,7 @@ |
1581 | |
1582 | private: |
1583 | void read_and_write_chunk(); |
1584 | - void handle_error(QString const& msg); |
1585 | + void handle_error(QString const& msg, int error_code); |
1586 | |
1587 | enum State { in_progress, finalized, cancelled, error }; |
1588 | |
1589 | @@ -73,6 +73,7 @@ |
1590 | QFutureInterface<void>& worker_initialized_; |
1591 | qint64 bytes_to_write_; |
1592 | QString error_msg_; |
1593 | + int error_code_ = 0; |
1594 | }; |
1595 | |
1596 | class DownloadThread : public QThread |
1597 | |
1598 | === modified file 'include/unity/storage/qt/client/internal/local_client/FolderImpl.h' |
1599 | --- include/unity/storage/qt/client/internal/local_client/FolderImpl.h 2016-07-14 00:17:14 +0000 |
1600 | +++ include/unity/storage/qt/client/internal/local_client/FolderImpl.h 2016-09-09 02:13:43 +0000 |
1601 | @@ -40,6 +40,7 @@ |
1602 | FolderImpl(QString const& identity); |
1603 | FolderImpl(QString const& identity, ItemType type); |
1604 | |
1605 | + virtual QString name() const override; |
1606 | QFuture<QVector<std::shared_ptr<Item>>> list() const override; |
1607 | QFuture<QVector<std::shared_ptr<Item>>> lookup(QString const& name) const override; |
1608 | QFuture<std::shared_ptr<Folder>> create_folder(QString const& name) override; |
1609 | |
1610 | === modified file 'include/unity/storage/qt/client/internal/local_client/ItemImpl.h' |
1611 | --- include/unity/storage/qt/client/internal/local_client/ItemImpl.h 2016-07-27 02:19:17 +0000 |
1612 | +++ include/unity/storage/qt/client/internal/local_client/ItemImpl.h 2016-09-09 02:13:43 +0000 |
1613 | @@ -47,7 +47,6 @@ |
1614 | ItemImpl(QString const& identity, ItemType type); |
1615 | virtual ~ItemImpl(); |
1616 | |
1617 | - virtual QString name() const override; |
1618 | virtual QString etag() const override; |
1619 | virtual QVariantMap metadata() const override; |
1620 | virtual QDateTime last_modified_time() const override; |
1621 | @@ -65,20 +64,18 @@ |
1622 | void set_timestamps() noexcept; |
1623 | bool has_conflict() const noexcept; |
1624 | |
1625 | - std::unique_lock<std::mutex> get_lock(); |
1626 | - |
1627 | protected: |
1628 | static boost::filesystem::path sanitize(QString const& name, QString const& method); |
1629 | static bool is_reserved_path(boost::filesystem::path const& path) noexcept; |
1630 | |
1631 | - DeletedException deleted_ex(QString const& method) const noexcept; |
1632 | - |
1633 | - bool deleted_; |
1634 | QString name_; |
1635 | QString etag_; |
1636 | QDateTime modified_time_; |
1637 | QVariantMap metadata_; |
1638 | - std::mutex mutable mutex_; |
1639 | + std::recursive_mutex mutable mutex_; |
1640 | + |
1641 | +private: |
1642 | + static void copy_recursively(boost::filesystem::path const& source, boost::filesystem::path const& target); |
1643 | }; |
1644 | |
1645 | } // namespace local_client |
1646 | |
1647 | === modified file 'include/unity/storage/qt/client/internal/local_client/RuntimeImpl.h' |
1648 | --- include/unity/storage/qt/client/internal/local_client/RuntimeImpl.h 2016-07-12 02:22:05 +0000 |
1649 | +++ include/unity/storage/qt/client/internal/local_client/RuntimeImpl.h 2016-09-09 02:13:43 +0000 |
1650 | @@ -41,6 +41,8 @@ |
1651 | |
1652 | virtual void shutdown() override; |
1653 | virtual QFuture<QVector<std::shared_ptr<Account>>> accounts() override; |
1654 | + virtual std::shared_ptr<Account> make_test_account(QString const& bus_name, |
1655 | + QString const& object_path) override; |
1656 | }; |
1657 | |
1658 | } // namespace local_client |
1659 | |
1660 | === modified file 'include/unity/storage/qt/client/internal/local_client/UploaderImpl.h' |
1661 | --- include/unity/storage/qt/client/internal/local_client/UploaderImpl.h 2016-07-26 01:51:26 +0000 |
1662 | +++ include/unity/storage/qt/client/internal/local_client/UploaderImpl.h 2016-09-09 02:13:43 +0000 |
1663 | @@ -68,12 +68,11 @@ |
1664 | private Q_SLOTS: |
1665 | void on_bytes_ready(); |
1666 | void on_read_channel_finished(); |
1667 | - void on_error(); |
1668 | |
1669 | private: |
1670 | void read_and_write_chunk(); |
1671 | void finalize(); |
1672 | - void handle_error(QString const& msg); |
1673 | + void handle_error(QString const& msg, int error_code); |
1674 | |
1675 | enum State { in_progress, finalized, cancelled, error }; |
1676 | |
1677 | @@ -91,6 +90,7 @@ |
1678 | QFutureInterface<std::shared_ptr<File>>& qf_; |
1679 | QFutureInterface<void>& worker_initialized_; |
1680 | QString error_msg_; |
1681 | + int error_code_ = 0; |
1682 | bool use_linkat_ = true; |
1683 | }; |
1684 | |
1685 | |
1686 | === added file 'include/unity/storage/qt/client/internal/local_client/storage_exception.h' |
1687 | --- include/unity/storage/qt/client/internal/local_client/storage_exception.h 1970-01-01 00:00:00 +0000 |
1688 | +++ include/unity/storage/qt/client/internal/local_client/storage_exception.h 2016-09-09 02:13:43 +0000 |
1689 | @@ -0,0 +1,94 @@ |
1690 | +/* |
1691 | + * Copyright (C) 2016 Canonical Ltd |
1692 | + * |
1693 | + * This program is free software: you can redistribute it and/or modify |
1694 | + * it under the terms of the GNU Lesser General Public License version 3 as |
1695 | + * published by the Free Software Foundation. |
1696 | + * |
1697 | + * This program is distributed in the hope that it will be useful, |
1698 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1699 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1700 | + * GNU Lesser General Public License for more details. |
1701 | + * |
1702 | + * You should have received a copy of the GNU Lesser General Public License |
1703 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1704 | + * |
1705 | + * Authors: Michi Henning <michi.henning@canonical.com> |
1706 | + */ |
1707 | + |
1708 | +#pragma once |
1709 | + |
1710 | +#include <unity/storage/qt/client/Exceptions.h> |
1711 | +#include <unity/storage/qt/client/internal/local_client/boost_filesystem.h> |
1712 | + |
1713 | +#pragma GCC diagnostic push |
1714 | +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
1715 | +#pragma GCC diagnostic ignored "-Wcast-align" |
1716 | +#include <QFuture> |
1717 | +#pragma GCC diagnostic pop |
1718 | +#include <QFutureInterface> |
1719 | + |
1720 | +class QString; |
1721 | + |
1722 | +namespace unity |
1723 | +{ |
1724 | +namespace storage |
1725 | +{ |
1726 | +namespace qt |
1727 | +{ |
1728 | +namespace client |
1729 | +{ |
1730 | +namespace internal |
1731 | +{ |
1732 | +namespace local_client |
1733 | +{ |
1734 | + |
1735 | +void throw_storage_exception(QString const& method, |
1736 | + std::exception_ptr ep) __attribute__ ((noreturn)); |
1737 | + |
1738 | +void throw_storage_exception(QString const& method, |
1739 | + std::exception_ptr ep, |
1740 | + QString const& key) __attribute__ ((noreturn)); |
1741 | + |
1742 | +template<typename T> |
1743 | +QFuture<T> make_exceptional_future(QString const& method, std::exception_ptr ep) |
1744 | +{ |
1745 | + try |
1746 | + { |
1747 | + throw_storage_exception(method, ep); |
1748 | + } |
1749 | + catch (StorageException const& e) |
1750 | + { |
1751 | + QFutureInterface<T> qf; |
1752 | + qf.reportException(e); |
1753 | + qf.reportFinished(); |
1754 | + return qf.future(); |
1755 | + } |
1756 | + abort(); // Impossible. // LCOV_EXCL_LINE |
1757 | +} |
1758 | + |
1759 | +template<typename T> |
1760 | +QFuture<T> make_exceptional_future(QString const& method, |
1761 | + std::exception_ptr ep, |
1762 | + QString const& key) |
1763 | +{ |
1764 | + try |
1765 | + { |
1766 | + throw_storage_exception(method, ep, key); |
1767 | + } |
1768 | + catch (StorageException const& e) |
1769 | + { |
1770 | + QFutureInterface<T> qf; |
1771 | + qf.reportException(e); |
1772 | + qf.reportFinished(); |
1773 | + return qf.future(); |
1774 | + } |
1775 | + abort(); // Impossible. // LCOV_EXCL_LINE |
1776 | +} |
1777 | + |
1778 | +} // namespace local_client |
1779 | +} // namespace internal |
1780 | +} // namespace client |
1781 | +} // namespace qt |
1782 | +} // namespace storage |
1783 | +} // namespace unity |
1784 | |
1785 | === renamed file 'include/unity/storage/qt/client/internal/local_client/tmpfile-prefix.h' => 'include/unity/storage/qt/client/internal/local_client/tmpfile_prefix.h' |
1786 | === modified file 'include/unity/storage/qt/client/internal/make_future.h' |
1787 | --- include/unity/storage/qt/client/internal/make_future.h 2016-07-22 02:35:12 +0000 |
1788 | +++ include/unity/storage/qt/client/internal/make_future.h 2016-09-09 02:13:43 +0000 |
1789 | @@ -36,40 +36,30 @@ |
1790 | namespace internal |
1791 | { |
1792 | |
1793 | +template<typename T> |
1794 | +QFuture<T> |
1795 | +__attribute__ ((warn_unused_result)) |
1796 | +make_ready_future(T const& val) |
1797 | +{ |
1798 | + QFutureInterface<T> qf; |
1799 | + qf.reportResult(val); |
1800 | + qf.reportFinished(); |
1801 | + return qf.future(); |
1802 | +} |
1803 | + |
1804 | template<typename T = void> |
1805 | -QFuture<T> make_ready_future() |
1806 | +QFuture<T> |
1807 | +__attribute__ ((warn_unused_result)) |
1808 | +make_ready_future() |
1809 | { |
1810 | QFutureInterface<void> qf; |
1811 | - qf.reportFinished(); |
1812 | - return qf.future(); |
1813 | -} |
1814 | - |
1815 | -template<typename T = void> |
1816 | -QFuture<T> make_ready_future(QFutureInterface<T> qf) |
1817 | -{ |
1818 | - qf.reportFinished(); |
1819 | - return qf.future(); |
1820 | -} |
1821 | - |
1822 | -template<typename T> |
1823 | -QFuture<T> make_ready_future(T const& val) |
1824 | -{ |
1825 | - QFutureInterface<T> qf; |
1826 | - qf.reportResult(val); |
1827 | - qf.reportFinished(); |
1828 | - return qf.future(); |
1829 | -} |
1830 | - |
1831 | -template<typename T> |
1832 | -QFuture<T> make_ready_future(QFutureInterface<T> qf, T const& val) |
1833 | -{ |
1834 | - qf.reportResult(val); |
1835 | - qf.reportFinished(); |
1836 | - return qf.future(); |
1837 | + return make_ready_future(qf); |
1838 | } |
1839 | |
1840 | template<typename E> |
1841 | -QFuture<void> make_exceptional_future(E const& ex) |
1842 | +QFuture<void> |
1843 | +__attribute__ |
1844 | +((warn_unused_result)) make_exceptional_future(E const& ex) |
1845 | { |
1846 | QFutureInterface<void> qf; |
1847 | qf.reportException(ex); |
1848 | @@ -78,7 +68,9 @@ |
1849 | } |
1850 | |
1851 | template<typename T, typename E> |
1852 | -QFuture<T> make_exceptional_future(E const& ex) |
1853 | +QFuture<T> |
1854 | +__attribute__ ((warn_unused_result)) |
1855 | +make_exceptional_future(E const& ex) |
1856 | { |
1857 | QFutureInterface<T> qf; |
1858 | qf.reportException(ex); |
1859 | @@ -86,14 +78,6 @@ |
1860 | return qf.future(); |
1861 | } |
1862 | |
1863 | -template<typename T, typename E> |
1864 | -QFuture<T> make_exceptional_future(QFutureInterface<T> qf, E const& ex) |
1865 | -{ |
1866 | - qf.reportException(ex); |
1867 | - qf.reportFinished(); |
1868 | - return qf.future(); |
1869 | -} |
1870 | - |
1871 | } // namespace internal |
1872 | } // namespace client |
1873 | } // namespace qt |
1874 | |
1875 | === modified file 'include/unity/storage/qt/client/internal/remote_client/AccountImpl.h' |
1876 | --- include/unity/storage/qt/client/internal/remote_client/AccountImpl.h 2016-07-15 03:56:14 +0000 |
1877 | +++ include/unity/storage/qt/client/internal/remote_client/AccountImpl.h 2016-09-09 02:13:43 +0000 |
1878 | @@ -39,7 +39,8 @@ |
1879 | { |
1880 | public: |
1881 | AccountImpl(std::weak_ptr<Runtime> const& runtime, |
1882 | - int account_id, |
1883 | + QString const& bus_name, |
1884 | + QString const& object_path, |
1885 | QString const& owner, |
1886 | QString const& owner_id, |
1887 | QString const& description); |
1888 | |
1889 | === modified file 'include/unity/storage/qt/client/internal/remote_client/Handler.h' |
1890 | --- include/unity/storage/qt/client/internal/remote_client/Handler.h 2016-07-15 03:58:35 +0000 |
1891 | +++ include/unity/storage/qt/client/internal/remote_client/Handler.h 2016-09-09 02:13:43 +0000 |
1892 | @@ -20,10 +20,13 @@ |
1893 | |
1894 | #include <unity/storage/qt/client/Exceptions.h> |
1895 | #include <unity/storage/qt/client/internal/make_future.h> |
1896 | +#include <unity/storage/qt/client/internal/remote_client/dbusmarshal.h> |
1897 | #include <unity/storage/qt/client/internal/remote_client/HandlerBase.h> |
1898 | |
1899 | #include <QDBusPendingReply> |
1900 | |
1901 | +#include <cassert> |
1902 | + |
1903 | namespace unity |
1904 | { |
1905 | namespace storage |
1906 | @@ -72,8 +75,41 @@ |
1907 | { |
1908 | if (call.isError()) |
1909 | { |
1910 | - qDebug() << call.error().message(); // TODO, remove this |
1911 | - make_exceptional_future<T>(ResourceException("DBus error return")); |
1912 | + try |
1913 | + { |
1914 | + auto ep = unmarshal_exception(call); |
1915 | + std::rethrow_exception(ep); |
1916 | + } |
1917 | + // We catch some exceptions that are "surprising" so we can log those. |
1918 | + catch (LocalCommsException const& e) |
1919 | + { |
1920 | + qCritical() << "provider exception:" << e.what(); |
1921 | + qf_.reportException(e); |
1922 | + qf_.reportFinished(); |
1923 | + } |
1924 | + catch (RemoteCommsException const& e) |
1925 | + { |
1926 | + qCritical() << "provider exception:" << e.what(); |
1927 | + qf_.reportException(e); |
1928 | + qf_.reportFinished(); |
1929 | + } |
1930 | + catch (ResourceException const& e) |
1931 | + { |
1932 | + qCritical() << "provider exception:" << e.what(); |
1933 | + qf_.reportException(e); |
1934 | + qf_.reportFinished(); |
1935 | + } |
1936 | + catch (StorageException const& e) |
1937 | + { |
1938 | + qf_.reportException(e); |
1939 | + qf_.reportFinished(); |
1940 | + } |
1941 | + // LCOV_EXCL_START |
1942 | + catch (...) |
1943 | + { |
1944 | + abort(); // Impossible. |
1945 | + } |
1946 | + // LCOV_EXCL_STOP |
1947 | return; |
1948 | } |
1949 | // TODO: See HACK above. Should just be closure(call, qf_); |
1950 | |
1951 | === modified file 'include/unity/storage/qt/client/internal/remote_client/ItemImpl.h' |
1952 | --- include/unity/storage/qt/client/internal/remote_client/ItemImpl.h 2016-07-22 00:17:24 +0000 |
1953 | +++ include/unity/storage/qt/client/internal/remote_client/ItemImpl.h 2016-09-09 02:13:43 +0000 |
1954 | @@ -66,9 +66,6 @@ |
1955 | static std::shared_ptr<Item> make_item(storage::internal::ItemMetadata const& md, std::weak_ptr<Root> root); |
1956 | |
1957 | protected: |
1958 | - DeletedException deleted_ex(QString const& method) const noexcept; |
1959 | - |
1960 | - bool deleted_ = false; |
1961 | storage::internal::ItemMetadata md_; |
1962 | |
1963 | friend class DeleteHandler; |
1964 | |
1965 | === modified file 'include/unity/storage/qt/client/internal/remote_client/RuntimeImpl.h' |
1966 | --- include/unity/storage/qt/client/internal/remote_client/RuntimeImpl.h 2016-07-22 00:17:24 +0000 |
1967 | +++ include/unity/storage/qt/client/internal/remote_client/RuntimeImpl.h 2016-09-09 02:13:43 +0000 |
1968 | @@ -50,6 +50,8 @@ |
1969 | |
1970 | virtual void shutdown() override; |
1971 | virtual QFuture<QVector<std::shared_ptr<Account>>> accounts() override; |
1972 | + virtual std::shared_ptr<Account> make_test_account(QString const& bus_name, |
1973 | + QString const& object_path) override; |
1974 | |
1975 | QDBusConnection& connection(); |
1976 | |
1977 | @@ -58,6 +60,12 @@ |
1978 | virtual void timeout(); |
1979 | |
1980 | private: |
1981 | + std::shared_ptr<Account> make_account(QString const& bus_name, |
1982 | + QString const& object_path, |
1983 | + QString const& owner, |
1984 | + QString const& owner_id, |
1985 | + QString const& description); |
1986 | + |
1987 | QDBusConnection conn_; |
1988 | std::unique_ptr<OnlineAccounts::Manager> manager_; // TODO: Hack until we can use the registry |
1989 | QTimer timer_; |
1990 | |
1991 | === modified file 'include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h' |
1992 | --- include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h 2016-07-22 00:17:24 +0000 |
1993 | +++ include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h 2016-09-09 02:13:43 +0000 |
1994 | @@ -65,13 +65,15 @@ |
1995 | std::shared_ptr<ProviderInterface> const& provider); |
1996 | |
1997 | private: |
1998 | + enum State { uploading, finalized }; |
1999 | + |
2000 | QString upload_id_; |
2001 | QDBusUnixFileDescriptor fd_; |
2002 | - int64_t size_; |
2003 | QString old_etag_; |
2004 | - std::weak_ptr<Root> root_; |
2005 | + std::shared_ptr<Root> root_; |
2006 | std::shared_ptr<ProviderInterface> provider_; |
2007 | std::shared_ptr<QLocalSocket> write_socket_; |
2008 | + State state_; |
2009 | }; |
2010 | |
2011 | } // namespace remote_client |
2012 | |
2013 | === modified file 'include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h' |
2014 | --- include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h 2016-07-12 02:22:05 +0000 |
2015 | +++ include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h 2016-09-09 02:13:43 +0000 |
2016 | @@ -18,29 +18,28 @@ |
2017 | |
2018 | #pragma once |
2019 | |
2020 | -#include <unity/storage/internal/ItemMetadata.h> |
2021 | +#include <exception> |
2022 | |
2023 | -#include <QDBusArgument> |
2024 | -#include <QMetaType> |
2025 | -#include <QVariant> |
2026 | +class QDBusPendingCallWatcher; |
2027 | |
2028 | namespace unity |
2029 | { |
2030 | namespace storage |
2031 | { |
2032 | +namespace qt |
2033 | +{ |
2034 | +namespace client |
2035 | +{ |
2036 | namespace internal |
2037 | { |
2038 | - |
2039 | -struct ItemMetadata; |
2040 | -QDBusArgument& operator<<(QDBusArgument& argument, storage::internal::ItemMetadata const& metadata); |
2041 | -QDBusArgument const& operator>>(QDBusArgument const& argument, storage::internal::ItemMetadata& metadata); |
2042 | - |
2043 | -QDBusArgument& operator<<(QDBusArgument& argument, QList<storage::internal::ItemMetadata> const& md_list); |
2044 | -QDBusArgument const& operator>>(QDBusArgument const& argument, QList<storage::internal::ItemMetadata>& md_list); |
2045 | - |
2046 | +namespace remote_client |
2047 | +{ |
2048 | + |
2049 | +std::exception_ptr unmarshal_exception(QDBusPendingCallWatcher const& call); |
2050 | + |
2051 | +} // namespace remote_client |
2052 | } // namespace internal |
2053 | -} // namespace storage |
2054 | -} // namespace unity |
2055 | - |
2056 | -Q_DECLARE_METATYPE(unity::storage::internal::ItemMetadata) |
2057 | -Q_DECLARE_METATYPE(QList<unity::storage::internal::ItemMetadata>) |
2058 | +} // client |
2059 | +} // qt |
2060 | +} // storage |
2061 | +} // unity |
2062 | |
2063 | === added file 'include/unity/storage/qt/client/internal/remote_client/validate.h' |
2064 | --- include/unity/storage/qt/client/internal/remote_client/validate.h 1970-01-01 00:00:00 +0000 |
2065 | +++ include/unity/storage/qt/client/internal/remote_client/validate.h 2016-09-09 02:13:43 +0000 |
2066 | @@ -0,0 +1,51 @@ |
2067 | +/* |
2068 | + * Copyright (C) 2016 Canonical Ltd |
2069 | + * |
2070 | + * This program is free software: you can redistribute it and/or modify |
2071 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2072 | + * published by the Free Software Foundation. |
2073 | + * |
2074 | + * This program is distributed in the hope that it will be useful, |
2075 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2076 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2077 | + * GNU Lesser General Public License for more details. |
2078 | + * |
2079 | + * You should have received a copy of the GNU Lesser General Public License |
2080 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2081 | + * |
2082 | + * Authors: Michi Henning <michi.henning@canonical.com> |
2083 | + */ |
2084 | + |
2085 | +#pragma once |
2086 | + |
2087 | +#include <QString> |
2088 | + |
2089 | +namespace unity |
2090 | +{ |
2091 | +namespace storage |
2092 | +{ |
2093 | + |
2094 | +namespace internal |
2095 | +{ |
2096 | + |
2097 | +class ItemMetadata; |
2098 | + |
2099 | +} // namespace internal |
2100 | + |
2101 | +namespace qt |
2102 | +{ |
2103 | +namespace client |
2104 | +{ |
2105 | +namespace internal |
2106 | +{ |
2107 | +namespace remote_client |
2108 | +{ |
2109 | + |
2110 | +void validate(QString const& method, unity::storage::internal::ItemMetadata const& md); |
2111 | + |
2112 | +} // namespace remote_client |
2113 | +} // namespace internal |
2114 | +} // namespace client |
2115 | +} // namespace qt |
2116 | +} // namespace storage |
2117 | +} // namespace unity |
2118 | |
2119 | === modified file 'src/internal/CMakeLists.txt' |
2120 | --- src/internal/CMakeLists.txt 2016-07-06 00:59:42 +0000 |
2121 | +++ src/internal/CMakeLists.txt 2016-09-09 02:13:43 +0000 |
2122 | @@ -1,5 +1,10 @@ |
2123 | set(src |
2124 | + dbusmarshal.cpp |
2125 | safe_strerror.cpp |
2126 | + TraceMessageHandler.cpp |
2127 | ) |
2128 | |
2129 | add_library(storage-framework-common-internal STATIC ${src}) |
2130 | +target_link_libraries(storage-framework-common-internal |
2131 | + Qt5::DBus |
2132 | +) |
2133 | |
2134 | === added file 'src/internal/TraceMessageHandler.cpp' |
2135 | --- src/internal/TraceMessageHandler.cpp 1970-01-01 00:00:00 +0000 |
2136 | +++ src/internal/TraceMessageHandler.cpp 2016-09-09 02:13:43 +0000 |
2137 | @@ -0,0 +1,96 @@ |
2138 | +/* |
2139 | + * Copyright (C) 2015 Canonical Ltd |
2140 | + * |
2141 | + * This program is free software: you can redistribute it and/or modify |
2142 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2143 | + * published by the Free Software Foundation. |
2144 | + * |
2145 | + * This program is distributed in the hope that it will be useful, |
2146 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2147 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2148 | + * GNU Lesser General Public License for more details. |
2149 | + * |
2150 | + * You should have received a copy of the GNU Lesser General Public License |
2151 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2152 | + * |
2153 | + * Authors: Michi Henning <michi.henning@canonical.com> |
2154 | + */ |
2155 | + |
2156 | +#include <unity/storage/internal/TraceMessageHandler.h> |
2157 | + |
2158 | +#include <chrono> |
2159 | +#include <mutex> |
2160 | + |
2161 | +using namespace std; |
2162 | + |
2163 | +namespace unity |
2164 | +{ |
2165 | +namespace storage |
2166 | +{ |
2167 | +namespace internal |
2168 | +{ |
2169 | +namespace |
2170 | +{ |
2171 | + |
2172 | +string prefix; |
2173 | + |
2174 | +void trace_message_handler(QtMsgType type, const QMessageLogContext& /*context*/, const QString& msg) |
2175 | +{ |
2176 | + using namespace std; |
2177 | + using namespace std::chrono; |
2178 | + |
2179 | + static recursive_mutex mutex; |
2180 | + lock_guard<decltype(mutex)> lock(mutex); |
2181 | + |
2182 | + auto now = system_clock::now(); |
2183 | + auto sys_time = system_clock::to_time_t(now); |
2184 | + struct tm local_time; |
2185 | + localtime_r(&sys_time, &local_time); |
2186 | + int msecs = duration_cast<milliseconds>(now.time_since_epoch()).count() % 1000; |
2187 | + |
2188 | + if (!prefix.empty()) |
2189 | + { |
2190 | + fprintf(stderr, "%s: ", prefix.c_str()); |
2191 | + } |
2192 | + char buf[100]; |
2193 | + strftime(buf, sizeof(buf), "%T", &local_time); |
2194 | + fprintf(stderr, "[%s.%03d]", buf, msecs); |
2195 | + switch (type) |
2196 | + { |
2197 | + case QtWarningMsg: |
2198 | + fputs(" Warning:", stderr); |
2199 | + break; |
2200 | + case QtCriticalMsg: |
2201 | + fputs(" Critical:", stderr); |
2202 | + break; |
2203 | + // LCOV_EXCL_START |
2204 | + case QtFatalMsg: |
2205 | + fputs(" Fatal:", stderr); |
2206 | + break; |
2207 | + // LCOV_EXCL_STOP |
2208 | + default: |
2209 | + break; // No label for debug messages. |
2210 | + } |
2211 | + fprintf(stderr, " %s\n", msg.toLocal8Bit().constData()); |
2212 | + if (type == QtFatalMsg) |
2213 | + { |
2214 | + abort(); // LCOV_EXCL_LINE |
2215 | + } |
2216 | +} |
2217 | + |
2218 | +} // namespace |
2219 | + |
2220 | +TraceMessageHandler::TraceMessageHandler(string const& prog_name) |
2221 | +{ |
2222 | + prefix = prog_name; |
2223 | + old_message_handler_ = qInstallMessageHandler(trace_message_handler); |
2224 | +} |
2225 | + |
2226 | +TraceMessageHandler::~TraceMessageHandler() |
2227 | +{ |
2228 | + qInstallMessageHandler(old_message_handler_); |
2229 | +} |
2230 | + |
2231 | +} // namespace internal |
2232 | +} // namespace storage |
2233 | +} // namespace unity |
2234 | |
2235 | === added file 'src/internal/dbusmarshal.cpp' |
2236 | --- src/internal/dbusmarshal.cpp 1970-01-01 00:00:00 +0000 |
2237 | +++ src/internal/dbusmarshal.cpp 2016-09-09 02:13:43 +0000 |
2238 | @@ -0,0 +1,113 @@ |
2239 | +/* |
2240 | + * Copyright (C) 2016 Canonical Ltd |
2241 | + * |
2242 | + * This program is free software: you can redistribute it and/or modify |
2243 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2244 | + * published by the Free Software Foundation. |
2245 | + * |
2246 | + * This program is distributed in the hope that it will be useful, |
2247 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2248 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2249 | + * GNU Lesser General Public License for more details. |
2250 | + * |
2251 | + * You should have received a copy of the GNU Lesser General Public License |
2252 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2253 | + * |
2254 | + * Authors: Michi Henning <michi.henning@canonical.com> |
2255 | + */ |
2256 | + |
2257 | +#include <unity/storage/internal/dbusmarshal.h> |
2258 | + |
2259 | +#include <QDebug> |
2260 | + |
2261 | +using namespace unity::storage::internal; |
2262 | +using namespace std; |
2263 | + |
2264 | +namespace unity |
2265 | +{ |
2266 | +namespace storage |
2267 | +{ |
2268 | +namespace internal |
2269 | +{ |
2270 | + |
2271 | +QDBusArgument& operator<<(QDBusArgument& argument, storage::internal::ItemMetadata const& metadata) |
2272 | +{ |
2273 | + argument.beginStructure(); |
2274 | + argument << metadata.item_id; |
2275 | + argument << metadata.parent_ids; |
2276 | + argument << metadata.name; |
2277 | + argument << metadata.etag; |
2278 | + argument << static_cast<int32_t>(metadata.type); |
2279 | + argument.beginMap(QVariant::String, qMetaTypeId<QDBusVariant>()); |
2280 | + decltype(ItemMetadata::metadata)::const_iterator i = metadata.metadata.constBegin(); |
2281 | + while (i != metadata.metadata.constEnd()) |
2282 | + { |
2283 | + argument.beginMapEntry(); |
2284 | + argument << i.key() << QDBusVariant(i.value()); |
2285 | + argument.endMapEntry(); |
2286 | + ++i; |
2287 | + } |
2288 | + argument.endMap(); |
2289 | + argument.endStructure(); |
2290 | + return argument; |
2291 | +} |
2292 | + |
2293 | +QDBusArgument const& operator>>(QDBusArgument const& argument, storage::internal::ItemMetadata& metadata) |
2294 | +{ |
2295 | + argument.beginStructure(); |
2296 | + argument >> metadata.item_id; |
2297 | + argument >> metadata.parent_ids; |
2298 | + argument >> metadata.name; |
2299 | + argument >> metadata.etag; |
2300 | + int32_t enum_val; |
2301 | + argument >> enum_val; |
2302 | + if (enum_val < 0 || enum_val >= int(ItemType::LAST_ENTRY__)) |
2303 | + { |
2304 | + qCritical() << "unmarshaling error: impossible ItemType value: " + QString::number(enum_val); |
2305 | + return argument; // Forces error |
2306 | + } |
2307 | + metadata.type = static_cast<ItemType>(enum_val); |
2308 | + metadata.metadata.clear(); |
2309 | + argument.beginMap(); |
2310 | + while (!argument.atEnd()) |
2311 | + { |
2312 | + QString key; |
2313 | + QVariant value; |
2314 | + argument.beginMapEntry(); |
2315 | + argument >> key >> value; |
2316 | + argument.endMapEntry(); |
2317 | + metadata.metadata.insert(key, value); |
2318 | + } |
2319 | + argument.endMap(); |
2320 | + argument.endStructure(); |
2321 | + return argument; |
2322 | +} |
2323 | + |
2324 | +QDBusArgument& operator<<(QDBusArgument& argument, QList<storage::internal::ItemMetadata> const& md_list) |
2325 | +{ |
2326 | + argument.beginArray(qMetaTypeId<storage::internal::ItemMetadata>()); |
2327 | + for (auto const& md : md_list) |
2328 | + { |
2329 | + argument << md; |
2330 | + } |
2331 | + argument.endArray(); |
2332 | + return argument; |
2333 | +} |
2334 | + |
2335 | +QDBusArgument const& operator>>(QDBusArgument const& argument, QList<storage::internal::ItemMetadata>& md_list) |
2336 | +{ |
2337 | + md_list.clear(); |
2338 | + argument.beginArray(); |
2339 | + while (!argument.atEnd()) |
2340 | + { |
2341 | + ItemMetadata imd; |
2342 | + argument >> imd; |
2343 | + md_list.append(imd); |
2344 | + } |
2345 | + argument.endArray(); |
2346 | + return argument; |
2347 | +} |
2348 | + |
2349 | +} // namespace internal |
2350 | +} // namespace storage |
2351 | +} // namespace unity |
2352 | |
2353 | === modified file 'src/provider/CMakeLists.txt' |
2354 | --- src/provider/CMakeLists.txt 2016-07-22 03:29:45 +0000 |
2355 | +++ src/provider/CMakeLists.txt 2016-09-09 02:13:43 +0000 |
2356 | @@ -1,9 +1,3 @@ |
2357 | - |
2358 | -add_definitions( |
2359 | - -DBOOST_THREAD_VERSION=4 |
2360 | - -DBOOST_THREAD_PROVIDES_EXECUTORS |
2361 | - ${APPARMOR_DEPS_CFLAGS} |
2362 | - ${ONLINEACCOUNTS_DEPS_CFLAGS}) |
2363 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) |
2364 | |
2365 | qt5_add_dbus_adaptor(generated_files ${CMAKE_SOURCE_DIR}/data/provider.xml unity/storage/provider/internal/ProviderInterface.h unity::storage::provider::internal::ProviderInterface) |
2366 | @@ -12,16 +6,20 @@ |
2367 | qt5_add_dbus_interface(generated_files bus.xml businterface) |
2368 | |
2369 | set_source_files_properties(${generated_files} PROPERTIES |
2370 | - COMPILE_FLAGS "-Wno-ctor-dtor-privacy -Wmissing-field-initializers" |
2371 | - GENERATED TRUE |
2372 | + COMPILE_FLAGS "-Wno-ctor-dtor-privacy -Wmissing-field-initializers" |
2373 | + GENERATED TRUE |
2374 | ) |
2375 | |
2376 | -add_library(storage-framework-provider SHARED |
2377 | +add_custom_target(sf-provider-generated-files DEPENDS ${generated_files}) |
2378 | + |
2379 | +add_library(sf-provider-objects OBJECT |
2380 | DownloadJob.cpp |
2381 | + Exceptions.cpp |
2382 | ProviderBase.cpp |
2383 | Server.cpp |
2384 | TempfileUploadJob.cpp |
2385 | UploadJob.cpp |
2386 | + testing/TestServer.cpp |
2387 | internal/AccountData.cpp |
2388 | internal/DBusPeerCache.cpp |
2389 | internal/DownloadJobImpl.cpp |
2390 | @@ -31,6 +29,7 @@ |
2391 | internal/ProviderInterface.cpp |
2392 | internal/ServerImpl.cpp |
2393 | internal/TempfileUploadJobImpl.cpp |
2394 | + internal/TestServerImpl.cpp |
2395 | internal/UploadJobImpl.cpp |
2396 | internal/dbusmarshal.cpp |
2397 | ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/AccountData.h |
2398 | @@ -42,6 +41,23 @@ |
2399 | ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/ServerImpl.h |
2400 | ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/TempfileUploadJobImpl.h |
2401 | ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/UploadJobImpl.h |
2402 | +) |
2403 | +add_dependencies(sf-provider-objects sf-provider-generated-files) |
2404 | +set_target_properties(sf-provider-objects PROPERTIES |
2405 | + AUTOMOC TRUE |
2406 | +) |
2407 | +target_compile_options(sf-provider-objects PUBLIC |
2408 | + -DBOOST_THREAD_VERSION=4 |
2409 | + -DBOOST_THREAD_PROVIDES_EXECUTORS |
2410 | + ${APPARMOR_DEPS_CFLAGS} |
2411 | + ${ONLINEACCOUNTS_DEPS_CFLAGS}) |
2412 | +target_include_directories(sf-provider-objects PRIVATE |
2413 | + ${Qt5DBus_INCLUDE_DIRS} |
2414 | + ${Qt5Network_INCLUDE_DIRS} |
2415 | +) |
2416 | + |
2417 | +add_library(storage-framework-provider SHARED |
2418 | + $<TARGET_OBJECTS:sf-provider-objects> |
2419 | ${generated_files}) |
2420 | |
2421 | set_target_properties(storage-framework-provider PROPERTIES |
2422 | @@ -51,7 +67,10 @@ |
2423 | SOVERSION ${SF_PROVIDER_SOVERSION} |
2424 | VERSION ${SF_PROVIDER_LIBVERSION} |
2425 | ) |
2426 | +target_compile_options(storage-framework-provider PUBLIC |
2427 | + $<TARGET_PROPERTY:sf-provider-objects,COMPILE_OPTIONS>) |
2428 | target_link_libraries(storage-framework-provider |
2429 | + storage-framework-common-internal |
2430 | Qt5::Core |
2431 | Qt5::DBus |
2432 | Qt5::Network |
2433 | @@ -60,19 +79,31 @@ |
2434 | ${ONLINEACCOUNTS_DEPS_LDFLAGS} |
2435 | ) |
2436 | |
2437 | -# moc does not know how to interpret the preprocessor logic in |
2438 | -# MainLoopExecutor.h, so we reproduce it here. |
2439 | -if(Boost_VERSION GREATER "105599") |
2440 | - set_target_properties(storage-framework-provider PROPERTIES |
2441 | - AUTOMOC_MOC_OPTIONS "-DSF_SUPPORTS_EXECUTORS" |
2442 | - ) |
2443 | -endif() |
2444 | - |
2445 | install( |
2446 | TARGETS storage-framework-provider |
2447 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} |
2448 | ) |
2449 | |
2450 | +# Build a static version of the library so that tests have access to |
2451 | +# hidden visibility symbols. |
2452 | +add_library(storage-framework-provider-static STATIC |
2453 | + $<TARGET_OBJECTS:sf-provider-objects> |
2454 | + ${generated_files}) |
2455 | +set_target_properties(storage-framework-provider-static PROPERTIES |
2456 | + AUTOMOC TRUE |
2457 | + ) |
2458 | +target_compile_options(storage-framework-provider-static PUBLIC |
2459 | + $<TARGET_PROPERTY:sf-provider-objects,COMPILE_OPTIONS>) |
2460 | +target_link_libraries(storage-framework-provider-static |
2461 | + storage-framework-common-internal |
2462 | + Qt5::Core |
2463 | + Qt5::DBus |
2464 | + Qt5::Network |
2465 | + ${Boost_LIBRARIES} |
2466 | + ${APPARMOR_DEPS_LDFLAGS} |
2467 | + ${ONLINEACCOUNTS_DEPS_LDFLAGS} |
2468 | +) |
2469 | + |
2470 | configure_file( |
2471 | storage-framework-provider.pc.in |
2472 | storage-framework-provider-${SF_PROVIDER_API_VERSION}.pc |
2473 | |
2474 | === added file 'src/provider/Exceptions.cpp' |
2475 | --- src/provider/Exceptions.cpp 1970-01-01 00:00:00 +0000 |
2476 | +++ src/provider/Exceptions.cpp 2016-09-09 02:13:43 +0000 |
2477 | @@ -0,0 +1,157 @@ |
2478 | +/* |
2479 | + * Copyright (C) 2016 Canonical Ltd |
2480 | + * |
2481 | + * This program is free software: you can redistribute it and/or modify |
2482 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2483 | + * published by the Free Software Foundation. |
2484 | + * |
2485 | + * This program is distributed in the hope that it will be useful, |
2486 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2487 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2488 | + * GNU Lesser General Public License for more details. |
2489 | + * |
2490 | + * You should have received a copy of the GNU Lesser General Public License |
2491 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2492 | + * |
2493 | + * Authors: Michi Henning <michi.henning@canonical.com> |
2494 | + */ |
2495 | + |
2496 | +#include <unity/storage/provider/Exceptions.h> |
2497 | + |
2498 | +using namespace std; |
2499 | + |
2500 | +namespace unity |
2501 | +{ |
2502 | +namespace storage |
2503 | +{ |
2504 | +namespace provider |
2505 | +{ |
2506 | + |
2507 | +StorageException::StorageException(std::string const& exception_type, string const& error_message) |
2508 | + : what_string_(string(exception_type) + ": " + error_message) |
2509 | + , type_(exception_type) |
2510 | + , error_message_(error_message) |
2511 | +{ |
2512 | +} |
2513 | + |
2514 | +StorageException::~StorageException() = default; |
2515 | + |
2516 | +char const* StorageException::what() const noexcept |
2517 | +{ |
2518 | + return what_string_.c_str(); |
2519 | +} |
2520 | + |
2521 | +string StorageException::type() const |
2522 | +{ |
2523 | + return type_; |
2524 | +} |
2525 | + |
2526 | +string StorageException::error_message() const |
2527 | +{ |
2528 | + return error_message_; |
2529 | +} |
2530 | + |
2531 | +RemoteCommsException::RemoteCommsException(string const& error_message) |
2532 | + : StorageException("RemoteCommsException", error_message) |
2533 | +{ |
2534 | +} |
2535 | + |
2536 | +RemoteCommsException::~RemoteCommsException() = default; |
2537 | + |
2538 | +NotExistsException::NotExistsException(string const& error_message, string const& key) |
2539 | + : StorageException("NotExistsException", error_message) |
2540 | + , key_(key) |
2541 | +{ |
2542 | +} |
2543 | + |
2544 | +NotExistsException::~NotExistsException() = default; |
2545 | + |
2546 | +string NotExistsException::key() const |
2547 | +{ |
2548 | + return key_; |
2549 | +} |
2550 | + |
2551 | +ExistsException::ExistsException(string const& error_message, string const& identity, string const& name) |
2552 | + : StorageException("ExistsException", error_message) |
2553 | + , identity_(identity) |
2554 | + , name_(name) |
2555 | +{ |
2556 | +} |
2557 | + |
2558 | +ExistsException::~ExistsException() = default; |
2559 | + |
2560 | +string ExistsException::native_identity() const |
2561 | +{ |
2562 | + return identity_; |
2563 | +} |
2564 | + |
2565 | +string ExistsException::name() const |
2566 | +{ |
2567 | + return name_; |
2568 | +} |
2569 | + |
2570 | +ConflictException::ConflictException(string const& error_message) |
2571 | + : StorageException("ConflictException", error_message) |
2572 | +{ |
2573 | +} |
2574 | + |
2575 | +ConflictException::~ConflictException() = default; |
2576 | + |
2577 | +PermissionException::PermissionException(string const& error_message) |
2578 | + : StorageException("PermissionException", error_message) |
2579 | +{ |
2580 | +} |
2581 | + |
2582 | +PermissionException::~PermissionException() = default; |
2583 | + |
2584 | +QuotaException::QuotaException(string const& error_message) |
2585 | + : StorageException("QuotaException", error_message) |
2586 | +{ |
2587 | +} |
2588 | + |
2589 | +QuotaException::~QuotaException() = default; |
2590 | + |
2591 | +CancelledException::CancelledException(string const& error_message) |
2592 | + : StorageException("CancelledException", error_message) |
2593 | +{ |
2594 | +} |
2595 | + |
2596 | +CancelledException::~CancelledException() = default; |
2597 | + |
2598 | +LogicException::LogicException(string const& error_message) |
2599 | + : StorageException("LogicException", error_message) |
2600 | +{ |
2601 | +} |
2602 | + |
2603 | +LogicException::~LogicException() = default; |
2604 | + |
2605 | +InvalidArgumentException::InvalidArgumentException(string const& error_message) |
2606 | + : StorageException("InvalidArgumentException", error_message) |
2607 | +{ |
2608 | +} |
2609 | + |
2610 | +InvalidArgumentException::~InvalidArgumentException() = default; |
2611 | + |
2612 | +ResourceException::ResourceException(string const& error_message, int error_code) |
2613 | + : StorageException("ResourceException", error_message) |
2614 | + , error_code_(error_code) |
2615 | +{ |
2616 | +} |
2617 | + |
2618 | +ResourceException::~ResourceException() = default; |
2619 | + |
2620 | +int ResourceException::error_code() const noexcept |
2621 | +{ |
2622 | + return error_code_; |
2623 | +} |
2624 | + |
2625 | +UnknownException::UnknownException(string const& error_message) |
2626 | + : StorageException("UnknownException", error_message) |
2627 | +{ |
2628 | +} |
2629 | + |
2630 | +UnknownException::~UnknownException() = default; |
2631 | + |
2632 | +} // namespace provider |
2633 | +} // namespace storage |
2634 | +} // namespace unity |
2635 | |
2636 | === modified file 'src/provider/TempfileUploadJob.cpp' |
2637 | --- src/provider/TempfileUploadJob.cpp 2016-07-12 02:22:05 +0000 |
2638 | +++ src/provider/TempfileUploadJob.cpp 2016-09-09 02:13:43 +0000 |
2639 | @@ -40,6 +40,11 @@ |
2640 | |
2641 | TempfileUploadJob::~TempfileUploadJob() = default; |
2642 | |
2643 | +void TempfileUploadJob::drain() |
2644 | +{ |
2645 | + static_cast<internal::TempfileUploadJobImpl*>(p_)->drain(); |
2646 | +} |
2647 | + |
2648 | string TempfileUploadJob::file_name() const |
2649 | { |
2650 | return static_cast<internal::TempfileUploadJobImpl*>(p_)->file_name(); |
2651 | |
2652 | === modified file 'src/provider/internal/DownloadJobImpl.cpp' |
2653 | --- src/provider/internal/DownloadJobImpl.cpp 2016-07-12 02:22:05 +0000 |
2654 | +++ src/provider/internal/DownloadJobImpl.cpp 2016-09-09 02:13:43 +0000 |
2655 | @@ -17,7 +17,9 @@ |
2656 | */ |
2657 | |
2658 | #include <unity/storage/provider/internal/DownloadJobImpl.h> |
2659 | +#include <unity/storage/internal/safe_strerror.h> |
2660 | #include <unity/storage/provider/DownloadJob.h> |
2661 | +#include <unity/storage/provider/Exceptions.h> |
2662 | |
2663 | #include <sys/socket.h> |
2664 | #include <sys/types.h> |
2665 | @@ -26,6 +28,7 @@ |
2666 | #include <stdexcept> |
2667 | |
2668 | using namespace std; |
2669 | +using namespace unity::storage::internal; |
2670 | |
2671 | namespace unity |
2672 | { |
2673 | @@ -42,18 +45,30 @@ |
2674 | int socks[2]; |
2675 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) < 0) |
2676 | { |
2677 | - throw runtime_error("could not create socketpair"); |
2678 | + int error_code = errno; |
2679 | + string msg = "could not create socketpair: " + safe_strerror(error_code); |
2680 | + throw ResourceException(msg, error_code); |
2681 | } |
2682 | read_socket_ = socks[0]; |
2683 | write_socket_ = socks[1]; |
2684 | + |
2685 | +#if 0 |
2686 | + // TODO: We should be able to half-close the write channel of the read socket and the read channel of |
2687 | + // the write socket. But, if we do, QLocalSocket indicates that everything was closed, which causes |
2688 | + // failures on the client side. We suspect a QLocalSocket bug -- need to investigate. |
2689 | if (shutdown(read_socket_, SHUT_WR) < 0) |
2690 | { |
2691 | - throw runtime_error("Could not shut down write channel on read socket"); |
2692 | + int error_code = errno; |
2693 | + string msg = "Could not shut down write channel on read socket" + safe_strerror(error_code); |
2694 | + throw ResourceException(msg, error_code); |
2695 | } |
2696 | if (shutdown(write_socket_, SHUT_RD) < 0) |
2697 | { |
2698 | - throw runtime_error("Could not shut down read channel on write socket"); |
2699 | + int error_code = errno; |
2700 | + string msg = "Could not shut down read channel on write socket: " + safe_strerror(error_code); |
2701 | + throw ResourceException(msg, error_code); |
2702 | } |
2703 | +#endif |
2704 | } |
2705 | |
2706 | DownloadJobImpl::~DownloadJobImpl() |
2707 | @@ -90,17 +105,6 @@ |
2708 | return sock; |
2709 | } |
2710 | |
2711 | -string const& DownloadJobImpl::sender_bus_name() const |
2712 | -{ |
2713 | - return sender_bus_name_; |
2714 | -} |
2715 | - |
2716 | -void DownloadJobImpl::set_sender_bus_name(string const& bus_name) |
2717 | -{ |
2718 | - assert(bus_name[0] == ':'); |
2719 | - sender_bus_name_ = bus_name; |
2720 | -} |
2721 | - |
2722 | void DownloadJobImpl::report_complete() |
2723 | { |
2724 | if (write_socket_ >= 0) |
2725 | @@ -124,7 +128,19 @@ |
2726 | |
2727 | lock_guard<mutex> guard(completion_lock_); |
2728 | completed_ = true; |
2729 | - completion_promise_.set_exception(p); |
2730 | + // Convert std::exception_ptr to boost::exception_ptr |
2731 | + try |
2732 | + { |
2733 | + std::rethrow_exception(p); |
2734 | + } |
2735 | + catch (StorageException const& e) |
2736 | + { |
2737 | + completion_promise_.set_exception(e); |
2738 | + } |
2739 | + catch (...) |
2740 | + { |
2741 | + completion_promise_.set_exception(boost::current_exception()); |
2742 | + } |
2743 | } |
2744 | |
2745 | boost::future<void> DownloadJobImpl::finish(DownloadJob& job) |
2746 | |
2747 | === modified file 'src/provider/internal/Handler.cpp' |
2748 | --- src/provider/internal/Handler.cpp 2016-07-20 02:20:53 +0000 |
2749 | +++ src/provider/internal/Handler.cpp 2016-09-09 02:13:43 +0000 |
2750 | @@ -17,20 +17,26 @@ |
2751 | */ |
2752 | |
2753 | #include <unity/storage/provider/internal/Handler.h> |
2754 | + |
2755 | +#include <unity/storage/internal/dbus_error.h> |
2756 | #include <unity/storage/provider/internal/AccountData.h> |
2757 | +#include <unity/storage/provider/internal/dbusmarshal.h> |
2758 | #include <unity/storage/provider/internal/DBusPeerCache.h> |
2759 | #include <unity/storage/provider/internal/MainLoopExecutor.h> |
2760 | #include <unity/storage/provider/ProviderBase.h> |
2761 | +#include <unity/storage/provider/Exceptions.h> |
2762 | + |
2763 | +#pragma GCC diagnostic push |
2764 | +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
2765 | +#pragma GCC diagnostic ignored "-Wswitch-default" |
2766 | +#include <QDebug> |
2767 | +#pragma GCC diagnostic pop |
2768 | |
2769 | #include <stdexcept> |
2770 | |
2771 | +using namespace unity::storage::internal; |
2772 | using namespace std; |
2773 | |
2774 | -namespace |
2775 | -{ |
2776 | -char const ERROR[] = "com.canonical.StorageFramework.Provider.Error"; |
2777 | -} |
2778 | - |
2779 | namespace unity |
2780 | { |
2781 | namespace storage |
2782 | @@ -53,7 +59,8 @@ |
2783 | auto peer_future = account_->dbus_peer().get(message_.service()); |
2784 | creds_future_ = peer_future.then( |
2785 | EXEC_IN_MAIN |
2786 | - [this](decltype(peer_future) f) { |
2787 | + [this](decltype(peer_future) f) |
2788 | + { |
2789 | auto info = f.get(); |
2790 | if (info.valid) |
2791 | { |
2792 | @@ -64,8 +71,10 @@ |
2793 | } |
2794 | else |
2795 | { |
2796 | - reply_ = message_.createErrorReply( |
2797 | - ERROR, "Handler::begin(): could not retrieve credentials"); |
2798 | + string msg = "Handler::begin(): could not retrieve credentials"; |
2799 | + qDebug() << QString::fromStdString(msg); |
2800 | + auto ep = make_exception_ptr(PermissionException(msg)); |
2801 | + marshal_exception(ep); |
2802 | QMetaObject::invokeMethod(this, "send_reply", |
2803 | Qt::QueuedConnection); |
2804 | } |
2805 | @@ -75,23 +84,29 @@ |
2806 | void Handler::credentials_received() |
2807 | { |
2808 | boost::future<QDBusMessage> msg_future; |
2809 | - try { |
2810 | + try |
2811 | + { |
2812 | msg_future = callback_(account_, context_, message_); |
2813 | - } catch (std::exception const& e) { |
2814 | - reply_ = message_.createErrorReply(ERROR, e.what()); |
2815 | + } |
2816 | + catch (std::exception const& e) |
2817 | + { |
2818 | + qDebug() << "provider method threw an exception:" << e.what(); |
2819 | + marshal_exception(current_exception()); |
2820 | QMetaObject::invokeMethod(this, "send_reply", Qt::QueuedConnection); |
2821 | return; |
2822 | } |
2823 | reply_future_ = msg_future.then( |
2824 | EXEC_IN_MAIN |
2825 | - [this](decltype(msg_future) f) { |
2826 | + [this](decltype(msg_future) f) |
2827 | + { |
2828 | try |
2829 | { |
2830 | reply_ = f.get(); |
2831 | } |
2832 | catch (std::exception const& e) |
2833 | { |
2834 | - reply_ = message_.createErrorReply(ERROR, e.what()); |
2835 | + qDebug() << e.what(); |
2836 | + marshal_exception(current_exception()); |
2837 | } |
2838 | QMetaObject::invokeMethod(this, "send_reply", Qt::QueuedConnection); |
2839 | }); |
2840 | @@ -103,6 +118,62 @@ |
2841 | Q_EMIT finished(); |
2842 | } |
2843 | |
2844 | +void Handler::marshal_exception(exception_ptr ep) |
2845 | +{ |
2846 | + try |
2847 | + { |
2848 | + rethrow_exception(ep); |
2849 | + } |
2850 | + catch (StorageException const& e) |
2851 | + { |
2852 | + reply_ = message_.createErrorReply(QString(DBUS_ERROR_PREFIX) + QString::fromStdString(e.type()), |
2853 | + QString::fromStdString(e.error_message())); |
2854 | + try |
2855 | + { |
2856 | + throw; |
2857 | + } |
2858 | + catch (NotExistsException const& e) |
2859 | + { |
2860 | + reply_ << QVariant(QString::fromStdString(e.key())); |
2861 | + } |
2862 | + catch (ExistsException const& e) |
2863 | + { |
2864 | + reply_ << QVariant(QString::fromStdString(e.native_identity())); |
2865 | + reply_ << QVariant(QString::fromStdString(e.name())); |
2866 | + } |
2867 | + catch (ResourceException const& e) |
2868 | + { |
2869 | + qDebug() << e.what(); |
2870 | + reply_ << QVariant(e.error_code()); |
2871 | + } |
2872 | + catch (RemoteCommsException const& e) |
2873 | + { |
2874 | + qDebug() << e.what(); |
2875 | + } |
2876 | + catch (UnknownException const& e) |
2877 | + { |
2878 | + qDebug() << e.what(); |
2879 | + } |
2880 | + catch (StorageException const&) |
2881 | + { |
2882 | + // Some other sub-type of StorageException without additional data members, |
2883 | + // and we don't want to log this (not surprising) exception. |
2884 | + } |
2885 | + } |
2886 | + catch (std::exception const& e) |
2887 | + { |
2888 | + QString msg = QString("unknown exception thrown by provider: ") + e.what(); |
2889 | + qDebug() << msg; |
2890 | + reply_ = message_.createErrorReply(QString(DBUS_ERROR_PREFIX) + "UnknownException", msg); |
2891 | + } |
2892 | + catch (...) |
2893 | + { |
2894 | + QString msg = "unknown exception thrown by provider"; |
2895 | + qDebug() << msg; |
2896 | + reply_ = message_.createErrorReply(QString(DBUS_ERROR_PREFIX) + "UnknownException", msg); |
2897 | + } |
2898 | +} |
2899 | + |
2900 | } |
2901 | } |
2902 | } |
2903 | |
2904 | === modified file 'src/provider/internal/MainLoopExecutor.cpp' |
2905 | --- src/provider/internal/MainLoopExecutor.cpp 2016-07-19 03:29:15 +0000 |
2906 | +++ src/provider/internal/MainLoopExecutor.cpp 2016-09-09 02:13:43 +0000 |
2907 | @@ -23,8 +23,6 @@ |
2908 | |
2909 | #include <stdexcept> |
2910 | |
2911 | -#ifdef SF_SUPPORTS_EXECUTORS |
2912 | - |
2913 | namespace { |
2914 | |
2915 | class WorkEvent : public QEvent { |
2916 | @@ -107,5 +105,3 @@ |
2917 | } |
2918 | } |
2919 | } |
2920 | - |
2921 | -#endif /* SF_SUPPORTS_EXECUTORS */ |
2922 | |
2923 | === modified file 'src/provider/internal/PendingJobs.cpp' |
2924 | --- src/provider/internal/PendingJobs.cpp 2016-07-19 03:26:36 +0000 |
2925 | +++ src/provider/internal/PendingJobs.cpp 2016-09-09 02:13:43 +0000 |
2926 | @@ -18,6 +18,7 @@ |
2927 | |
2928 | #include <unity/storage/provider/internal/PendingJobs.h> |
2929 | #include <unity/storage/provider/DownloadJob.h> |
2930 | +#include <unity/storage/provider/Exceptions.h> |
2931 | #include <unity/storage/provider/UploadJob.h> |
2932 | #include <unity/storage/provider/internal/DownloadJobImpl.h> |
2933 | #include <unity/storage/provider/internal/MainLoopExecutor.h> |
2934 | @@ -47,67 +48,79 @@ |
2935 | this, &PendingJobs::service_disconnected); |
2936 | } |
2937 | |
2938 | -PendingJobs::~PendingJobs() = default; |
2939 | +PendingJobs::~PendingJobs() |
2940 | +{ |
2941 | + for (const auto& pair : downloads_) |
2942 | + { |
2943 | + cancel_job(pair.second, "download " + pair.second->download_id()); |
2944 | + } |
2945 | + for (const auto& pair : uploads_) |
2946 | + { |
2947 | + cancel_job(pair.second, "upload " + pair.second->upload_id()); |
2948 | + } |
2949 | +} |
2950 | |
2951 | -void PendingJobs::add_download(unique_ptr<DownloadJob> &&job) |
2952 | +void PendingJobs::add_download(QString const& client_bus_name, |
2953 | + unique_ptr<DownloadJob> &&job) |
2954 | { |
2955 | lock_guard<mutex> guard(lock_); |
2956 | |
2957 | - assert(!job->p_->sender_bus_name().empty()); |
2958 | - assert(downloads_.find(job->download_id()) == downloads_.end()); |
2959 | + assert(!client_bus_name.isEmpty() && client_bus_name[0] == ':'); |
2960 | + const auto job_id = make_pair(client_bus_name, job->download_id()); |
2961 | + assert(downloads_.find(job_id) == downloads_.end()); |
2962 | |
2963 | shared_ptr<DownloadJob> j(std::move(job)); |
2964 | - downloads_.emplace(j->download_id(), j); |
2965 | - watch_peer(j->p_->sender_bus_name()); |
2966 | -} |
2967 | - |
2968 | -std::shared_ptr<DownloadJob> PendingJobs::get_download(std::string const& download_id) |
2969 | -{ |
2970 | - lock_guard<mutex> guard(lock_); |
2971 | - |
2972 | - return downloads_.at(download_id); |
2973 | -} |
2974 | - |
2975 | -std::shared_ptr<DownloadJob> PendingJobs::remove_download(std::string const& download_id) |
2976 | -{ |
2977 | - lock_guard<mutex> guard(lock_); |
2978 | - |
2979 | - auto job = downloads_.at(download_id); |
2980 | - downloads_.erase(download_id); |
2981 | - unwatch_peer(job->p_->sender_bus_name()); |
2982 | + downloads_.emplace(job_id, j); |
2983 | + watch_peer(client_bus_name); |
2984 | +} |
2985 | + |
2986 | +shared_ptr<DownloadJob> PendingJobs::remove_download(QString const& client_bus_name, |
2987 | + string const& download_id) |
2988 | +{ |
2989 | + lock_guard<mutex> guard(lock_); |
2990 | + |
2991 | + auto it = downloads_.find({client_bus_name, download_id}); |
2992 | + if (it == downloads_.cend()) |
2993 | + { |
2994 | + throw LogicException("No such download: " + download_id); |
2995 | + } |
2996 | + auto job = it->second; |
2997 | + downloads_.erase(it); |
2998 | + unwatch_peer(client_bus_name); |
2999 | return job; |
3000 | } |
3001 | |
3002 | -void PendingJobs::add_upload(unique_ptr<UploadJob> &&job) |
3003 | +void PendingJobs::add_upload(QString const& client_bus_name, |
3004 | + unique_ptr<UploadJob> &&job) |
3005 | { |
3006 | lock_guard<mutex> guard(lock_); |
3007 | |
3008 | - assert(!job->p_->sender_bus_name().empty()); |
3009 | - assert(uploads_.find(job->upload_id()) == uploads_.end()); |
3010 | + assert(!client_bus_name.isEmpty() && client_bus_name[0] == ':'); |
3011 | + const auto job_id = make_pair(client_bus_name, job->upload_id()); |
3012 | + assert(uploads_.find(job_id) == uploads_.end()); |
3013 | |
3014 | shared_ptr<UploadJob> j(std::move(job)); |
3015 | - uploads_.emplace(j->upload_id(), j); |
3016 | - watch_peer(j->p_->sender_bus_name()); |
3017 | -} |
3018 | - |
3019 | -std::shared_ptr<UploadJob> PendingJobs::get_upload(std::string const& upload_id) |
3020 | -{ |
3021 | - lock_guard<mutex> guard(lock_); |
3022 | - |
3023 | - return uploads_.at(upload_id); |
3024 | -} |
3025 | - |
3026 | -std::shared_ptr<UploadJob> PendingJobs::remove_upload(std::string const& upload_id) |
3027 | -{ |
3028 | - lock_guard<mutex> guard(lock_); |
3029 | - |
3030 | - auto job = uploads_.at(upload_id); |
3031 | - uploads_.erase(upload_id); |
3032 | - unwatch_peer(job->p_->sender_bus_name()); |
3033 | + uploads_.emplace(job_id, j); |
3034 | + watch_peer(client_bus_name); |
3035 | +} |
3036 | + |
3037 | +shared_ptr<UploadJob> PendingJobs::remove_upload(QString const& client_bus_name, |
3038 | + string const& upload_id) |
3039 | +{ |
3040 | + lock_guard<mutex> guard(lock_); |
3041 | + |
3042 | + auto it = uploads_.find({client_bus_name, upload_id}); |
3043 | + if (it == uploads_.cend()) |
3044 | + { |
3045 | + throw LogicException("No such upload: " + upload_id); |
3046 | + } |
3047 | + auto job = it->second; |
3048 | + uploads_.erase(it); |
3049 | + unwatch_peer(client_bus_name); |
3050 | return job; |
3051 | } |
3052 | |
3053 | -void PendingJobs::watch_peer(string const& bus_name) |
3054 | +void PendingJobs::watch_peer(QString const& bus_name) |
3055 | { |
3056 | auto it = services_.find(bus_name); |
3057 | if (it != services_.end()) |
3058 | @@ -116,12 +129,12 @@ |
3059 | } |
3060 | else |
3061 | { |
3062 | - watcher_.addWatchedService(QString::fromStdString(bus_name)); |
3063 | + watcher_.addWatchedService(bus_name); |
3064 | services_[bus_name] = 1; |
3065 | } |
3066 | } |
3067 | |
3068 | -void PendingJobs::unwatch_peer(string const& bus_name) |
3069 | +void PendingJobs::unwatch_peer(QString const& bus_name) |
3070 | { |
3071 | auto it = services_.find(bus_name); |
3072 | if (it == services_.end()) |
3073 | @@ -132,72 +145,62 @@ |
3074 | if (it->second == 0) |
3075 | { |
3076 | services_.erase(it); |
3077 | - watcher_.removeWatchedService(QString::fromStdString(bus_name)); |
3078 | + watcher_.removeWatchedService(bus_name); |
3079 | } |
3080 | } |
3081 | |
3082 | void PendingJobs::service_disconnected(QString const& service_name) |
3083 | { |
3084 | lock_guard<mutex> guard(lock_); |
3085 | - string const bus_name = service_name.toStdString(); |
3086 | - |
3087 | - for (auto it = downloads_.cbegin(); it != downloads_.cend(); ) |
3088 | - { |
3089 | - if (it->second->p_->sender_bus_name() == bus_name) |
3090 | - { |
3091 | - auto job = it->second; |
3092 | - it = downloads_.erase(it); |
3093 | - auto f = job->p_->cancel(*job); |
3094 | - // This continuation also ensures that the job remains |
3095 | - // alive until the cancel method has completed. |
3096 | - f.then( |
3097 | - EXEC_IN_MAIN |
3098 | - [job](decltype(f) f) { |
3099 | - try |
3100 | - { |
3101 | - f.get(); |
3102 | - } |
3103 | - catch (std::exception const& e) |
3104 | - { |
3105 | - fprintf(stderr, "Error cancelling download job '%s': %s\n", |
3106 | - job->download_id().c_str(), e.what()); |
3107 | - } |
3108 | - }); |
3109 | - } |
3110 | - else |
3111 | - { |
3112 | - ++it; |
3113 | - } |
3114 | - } |
3115 | - |
3116 | - for (auto it = uploads_.cbegin(); it != uploads_.cend(); ) |
3117 | - { |
3118 | - if (it->second->p_->sender_bus_name() == bus_name) |
3119 | - { |
3120 | - auto job = it->second; |
3121 | - it = uploads_.erase(it); |
3122 | - auto f = job->p_->cancel(*job); |
3123 | - // This continuation also ensures that the job remains |
3124 | - // alive until the cancel method has completed. |
3125 | - f.then( |
3126 | - EXEC_IN_MAIN |
3127 | - [job](decltype(f) f) { |
3128 | - try |
3129 | - { |
3130 | - f.get(); |
3131 | - } |
3132 | - catch (std::exception const& e) |
3133 | - { |
3134 | - fprintf(stderr, "Error cancelling upload job '%s': %s\n", |
3135 | - job->upload_id().c_str(), e.what()); |
3136 | - } |
3137 | - }); |
3138 | - } |
3139 | - else |
3140 | - { |
3141 | - ++it; |
3142 | - } |
3143 | - } |
3144 | + |
3145 | + services_.erase(service_name); |
3146 | + watcher_.removeWatchedService(service_name); |
3147 | + |
3148 | + const auto lower = make_pair(service_name, string()); |
3149 | + |
3150 | + for (auto it = downloads_.lower_bound(lower); |
3151 | + it != downloads_.cend() && it->first.first == service_name; ) |
3152 | + { |
3153 | + auto job = it->second; |
3154 | + it = downloads_.erase(it); |
3155 | + cancel_job(job, "download " + job->download_id()); |
3156 | + } |
3157 | + |
3158 | + for (auto it = uploads_.lower_bound(lower); |
3159 | + it != uploads_.cend() && it->first.first == service_name; ) |
3160 | + { |
3161 | + auto job = it->second; |
3162 | + it = uploads_.erase(it); |
3163 | + cancel_job(job, "upload " + job->upload_id()); |
3164 | + } |
3165 | +} |
3166 | + |
3167 | +template<typename Job> |
3168 | +void PendingJobs::cancel_job(shared_ptr<Job> const& job, string const& identifier) |
3169 | +{ |
3170 | + auto f = job->p_->cancel(*job); |
3171 | + // This continuation also ensures that the job remains |
3172 | + // alive until the cancel method has completed. |
3173 | + auto cancel_future = std::make_shared<boost::future<void>>(); |
3174 | + *cancel_future = f.then( |
3175 | + EXEC_IN_MAIN |
3176 | + [job, identifier, cancel_future](decltype(f) f) { |
3177 | + try |
3178 | + { |
3179 | + f.get(); |
3180 | + } |
3181 | + catch (std::exception const& e) |
3182 | + { |
3183 | + fprintf(stderr, "Error cancelling job '%s': %s\n", |
3184 | + identifier.c_str(), e.what()); |
3185 | + } |
3186 | + |
3187 | + // Break the reference cycle between the continuation |
3188 | + // future and closure, while making sure the future |
3189 | + // survives long enough to be marked ready. |
3190 | + auto fut = std::make_shared<boost::future<void>>(std::move(*cancel_future)); |
3191 | + MainLoopExecutor::instance().submit([fut]{}); |
3192 | + }); |
3193 | } |
3194 | |
3195 | } |
3196 | |
3197 | === modified file 'src/provider/internal/ProviderInterface.cpp' |
3198 | --- src/provider/internal/ProviderInterface.cpp 2016-07-21 12:48:40 +0000 |
3199 | +++ src/provider/internal/ProviderInterface.cpp 2016-09-09 02:13:43 +0000 |
3200 | @@ -18,6 +18,7 @@ |
3201 | |
3202 | #include <unity/storage/provider/internal/ProviderInterface.h> |
3203 | #include <unity/storage/provider/DownloadJob.h> |
3204 | +#include <unity/storage/provider/Exceptions.h> |
3205 | #include <unity/storage/provider/ProviderBase.h> |
3206 | #include <unity/storage/provider/UploadJob.h> |
3207 | #include <unity/storage/provider/internal/AccountData.h> |
3208 | @@ -171,15 +172,13 @@ |
3209 | EXEC_IN_MAIN |
3210 | [account, message](decltype(f) f) -> QDBusMessage { |
3211 | auto job = f.get(); |
3212 | - job->p_->set_sender_bus_name(message.service().toStdString()); |
3213 | - |
3214 | auto upload_id = QString::fromStdString(job->upload_id()); |
3215 | QDBusUnixFileDescriptor file_desc; |
3216 | int fd = job->p_->take_write_socket(); |
3217 | file_desc.setFileDescriptor(fd); |
3218 | close(fd); |
3219 | |
3220 | - account->jobs().add_upload(std::move(job)); |
3221 | + account->jobs().add_upload(message.service(), std::move(job)); |
3222 | return message.createReply({ |
3223 | QVariant(upload_id), |
3224 | QVariant::fromValue(file_desc), |
3225 | @@ -198,15 +197,13 @@ |
3226 | EXEC_IN_MAIN |
3227 | [account, message](decltype(f) f) -> QDBusMessage { |
3228 | auto job = f.get(); |
3229 | - job->p_->set_sender_bus_name(message.service().toStdString()); |
3230 | - |
3231 | auto upload_id = QString::fromStdString(job->upload_id()); |
3232 | QDBusUnixFileDescriptor file_desc; |
3233 | int fd = job->p_->take_write_socket(); |
3234 | file_desc.setFileDescriptor(fd); |
3235 | close(fd); |
3236 | |
3237 | - account->jobs().add_upload(std::move(job)); |
3238 | + account->jobs().add_upload(message.service(), std::move(job)); |
3239 | return message.createReply({ |
3240 | QVariant(upload_id), |
3241 | QVariant::fromValue(file_desc), |
3242 | @@ -219,15 +216,10 @@ |
3243 | ProviderInterface::IMD ProviderInterface::FinishUpload(QString const& upload_id) |
3244 | { |
3245 | queue_request([upload_id](shared_ptr<AccountData> const& account, Context const& /*ctx*/, QDBusMessage const& message) { |
3246 | - // Throws if job is not available |
3247 | - auto job = account->jobs().get_upload(upload_id.toStdString()); |
3248 | - if (job->p_->sender_bus_name() != message.service().toStdString()) |
3249 | - { |
3250 | - throw runtime_error("Upload job belongs to a different client"); |
3251 | - } |
3252 | // FIXME: removing the job at this point means we can't |
3253 | // cancel during finish(). |
3254 | - account->jobs().remove_upload(upload_id.toStdString()); |
3255 | + // Throws if job is not available |
3256 | + auto job = account->jobs().remove_upload(message.service(), upload_id.toStdString()); |
3257 | auto f = job->p_->finish(*job); |
3258 | return f.then( |
3259 | EXEC_IN_MAIN |
3260 | @@ -243,12 +235,7 @@ |
3261 | { |
3262 | queue_request([upload_id](shared_ptr<AccountData> const& account, Context const& /*ctx*/, QDBusMessage const& message) { |
3263 | // Throws if job is not available |
3264 | - auto job = account->jobs().get_upload(upload_id.toStdString()); |
3265 | - if (job->p_->sender_bus_name() != message.service().toStdString()) |
3266 | - { |
3267 | - throw runtime_error("Upload job belongs to a different client"); |
3268 | - } |
3269 | - account->jobs().remove_upload(upload_id.toStdString()); |
3270 | + auto job = account->jobs().remove_upload(message.service(), upload_id.toStdString()); |
3271 | auto f = job->p_->cancel(*job); |
3272 | return f.then( |
3273 | EXEC_IN_MAIN |
3274 | @@ -268,15 +255,13 @@ |
3275 | EXEC_IN_MAIN |
3276 | [account, message](decltype(f) f) -> QDBusMessage { |
3277 | auto job = f.get(); |
3278 | - job->p_->set_sender_bus_name(message.service().toStdString()); |
3279 | - |
3280 | auto download_id = QString::fromStdString(job->download_id()); |
3281 | QDBusUnixFileDescriptor file_desc; |
3282 | int fd = job->p_->take_read_socket(); |
3283 | file_desc.setFileDescriptor(fd); |
3284 | close(fd); |
3285 | |
3286 | - account->jobs().add_download(std::move(job)); |
3287 | + account->jobs().add_download(message.service(), std::move(job)); |
3288 | return message.createReply({ |
3289 | QVariant(download_id), |
3290 | QVariant::fromValue(file_desc), |
3291 | @@ -289,15 +274,10 @@ |
3292 | void ProviderInterface::FinishDownload(QString const& download_id) |
3293 | { |
3294 | queue_request([download_id](shared_ptr<AccountData> const& account, Context const& /*ctx*/, QDBusMessage const& message) { |
3295 | - // Throws if job is not available |
3296 | - auto job = account->jobs().get_download(download_id.toStdString()); |
3297 | - if (job->p_->sender_bus_name() != message.service().toStdString()) |
3298 | - { |
3299 | - throw runtime_error("Download job belongs to a different client"); |
3300 | - } |
3301 | // FIXME: removing the job at this point means we can't |
3302 | // cancel during finish(). |
3303 | - account->jobs().remove_download(download_id.toStdString()); |
3304 | + // Throws if job is not available |
3305 | + auto job = account->jobs().remove_download(message.service(), download_id.toStdString()); |
3306 | auto f = job->p_->finish(*job); |
3307 | return f.then( |
3308 | EXEC_IN_MAIN |
3309 | |
3310 | === modified file 'src/provider/internal/ServerImpl.cpp' |
3311 | --- src/provider/internal/ServerImpl.cpp 2016-07-21 04:00:29 +0000 |
3312 | +++ src/provider/internal/ServerImpl.cpp 2016-09-09 02:13:43 +0000 |
3313 | @@ -17,6 +17,7 @@ |
3314 | */ |
3315 | |
3316 | #include <unity/storage/provider/internal/ServerImpl.h> |
3317 | +#include <unity/storage/provider/Exceptions.h> |
3318 | #include <unity/storage/provider/ProviderBase.h> |
3319 | #include <unity/storage/provider/internal/AccountData.h> |
3320 | #include <unity/storage/provider/internal/MainLoopExecutor.h> |
3321 | @@ -37,7 +38,10 @@ |
3322 | { |
3323 | |
3324 | ServerImpl::ServerImpl(ServerBase* server, string const& bus_name, string const& account_service_id) |
3325 | - : server_(server), bus_name_(bus_name), service_id_(account_service_id) |
3326 | + : server_(server) |
3327 | + , bus_name_(bus_name) |
3328 | + , service_id_(account_service_id) |
3329 | + , trace_message_handler_("storage_provider") |
3330 | { |
3331 | qDBusRegisterMetaType<Item>(); |
3332 | qDBusRegisterMetaType<std::vector<Item>>(); |
3333 | @@ -85,7 +89,8 @@ |
3334 | |
3335 | if (!bus.registerService(QString::fromStdString(bus_name_))) |
3336 | { |
3337 | - throw runtime_error("Could not acquire bus name: " + bus_name_); |
3338 | + string msg = string("Could not acquire bus name: ") + bus_name_ + ": " + bus.lastError().message().toStdString(); |
3339 | + throw ResourceException(msg, int(bus.lastError().type())); |
3340 | } |
3341 | // TODO: claim bus name |
3342 | qDebug() << "Bus unique name:" << bus.baseService(); |
3343 | |
3344 | === modified file 'src/provider/internal/TempfileUploadJobImpl.cpp' |
3345 | --- src/provider/internal/TempfileUploadJobImpl.cpp 2016-07-12 02:22:05 +0000 |
3346 | +++ src/provider/internal/TempfileUploadJobImpl.cpp 2016-09-09 02:13:43 +0000 |
3347 | @@ -17,9 +17,10 @@ |
3348 | */ |
3349 | |
3350 | #include <unity/storage/provider/internal/TempfileUploadJobImpl.h> |
3351 | +#include <unity/storage/provider/Exceptions.h> |
3352 | |
3353 | #include <cassert> |
3354 | -#include <stdexcept> |
3355 | +#include <exception> |
3356 | |
3357 | using namespace std; |
3358 | |
3359 | @@ -64,6 +65,25 @@ |
3360 | return tmpfile_->fileName().toStdString(); |
3361 | } |
3362 | |
3363 | +void TempfileUploadJobImpl::drain() |
3364 | +{ |
3365 | + while (true) |
3366 | + { |
3367 | + if (!tmpfile_->isOpen()) |
3368 | + { |
3369 | + break; |
3370 | + } |
3371 | + if (!reader_->waitForReadyRead(0)) |
3372 | + { |
3373 | + // Nothing was available to read: is the read channel still open? |
3374 | + if (tmpfile_->isOpen()) |
3375 | + { |
3376 | + throw LogicException("Socket not closed"); |
3377 | + } |
3378 | + } |
3379 | + } |
3380 | +} |
3381 | + |
3382 | void TempfileUploadJobImpl::on_ready_read() |
3383 | { |
3384 | char buffer[4096]; |
3385 | |
3386 | === added file 'src/provider/internal/TestServerImpl.cpp' |
3387 | --- src/provider/internal/TestServerImpl.cpp 1970-01-01 00:00:00 +0000 |
3388 | +++ src/provider/internal/TestServerImpl.cpp 2016-09-09 02:13:43 +0000 |
3389 | @@ -0,0 +1,84 @@ |
3390 | +/* |
3391 | + * Copyright (C) 2016 Canonical Ltd |
3392 | + * |
3393 | + * This program is free software: you can redistribute it and/or modify |
3394 | + * it under the terms of the GNU Lesser General Public License version 3 as |
3395 | + * published by the Free Software Foundation. |
3396 | + * |
3397 | + * This program is distributed in the hope that it will be useful, |
3398 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3399 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3400 | + * GNU Lesser General Public License for more details. |
3401 | + * |
3402 | + * You should have received a copy of the GNU Lesser General Public License |
3403 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3404 | + * |
3405 | + * Authors: James Henstridge <james.henstridge@canonical.com> |
3406 | + */ |
3407 | + |
3408 | +#include <unity/storage/provider/internal/TestServerImpl.h> |
3409 | +#include <unity/storage/provider/Exceptions.h> |
3410 | +#include <unity/storage/provider/ProviderBase.h> |
3411 | +#include <unity/storage/provider/internal/AccountData.h> |
3412 | +#include <unity/storage/provider/internal/DBusPeerCache.h> |
3413 | +#include <unity/storage/provider/internal/ProviderInterface.h> |
3414 | +#include <unity/storage/provider/internal/dbusmarshal.h> |
3415 | +#include "provideradaptor.h" |
3416 | + |
3417 | +#include <OnlineAccounts/Account> |
3418 | + |
3419 | +#include <stdexcept> |
3420 | + |
3421 | +using namespace std; |
3422 | + |
3423 | +namespace unity |
3424 | +{ |
3425 | +namespace storage |
3426 | +{ |
3427 | +namespace provider |
3428 | +{ |
3429 | +namespace internal |
3430 | +{ |
3431 | + |
3432 | +TestServerImpl::TestServerImpl(unique_ptr<ProviderBase>&& provider, |
3433 | + OnlineAccounts::Account* account, |
3434 | + QDBusConnection const& connection, |
3435 | + string const& object_path) |
3436 | + : connection_(connection), object_path_(object_path) |
3437 | +{ |
3438 | + qDBusRegisterMetaType<Item>(); |
3439 | + qDBusRegisterMetaType<std::vector<Item>>(); |
3440 | + |
3441 | + auto peer_cache = make_shared<DBusPeerCache>(connection_); |
3442 | + auto account_data = make_shared<AccountData>( |
3443 | + move(provider), peer_cache, connection_, account); |
3444 | + interface_.reset(new ProviderInterface(account_data)); |
3445 | + new ProviderAdaptor(interface_.get()); |
3446 | + |
3447 | + if (!connection_.registerObject(QString::fromStdString(object_path_), |
3448 | + interface_.get())) |
3449 | + { |
3450 | + string msg = "Could not register provider on connection: " + connection_.lastError().message().toStdString(); |
3451 | + throw ResourceException(msg, int(connection_.lastError().type())); |
3452 | + } |
3453 | +} |
3454 | + |
3455 | +TestServerImpl::~TestServerImpl() |
3456 | +{ |
3457 | + connection_.unregisterObject(QString::fromStdString(object_path_)); |
3458 | +} |
3459 | + |
3460 | +QDBusConnection const& TestServerImpl::connection() const |
3461 | +{ |
3462 | + return connection_; |
3463 | +} |
3464 | + |
3465 | +string const& TestServerImpl::object_path() const |
3466 | +{ |
3467 | + return object_path_; |
3468 | +} |
3469 | + |
3470 | +} |
3471 | +} |
3472 | +} |
3473 | +} |
3474 | |
3475 | === modified file 'src/provider/internal/UploadJobImpl.cpp' |
3476 | --- src/provider/internal/UploadJobImpl.cpp 2016-07-12 02:22:05 +0000 |
3477 | +++ src/provider/internal/UploadJobImpl.cpp 2016-09-09 02:13:43 +0000 |
3478 | @@ -17,7 +17,10 @@ |
3479 | */ |
3480 | |
3481 | #include <unity/storage/provider/internal/UploadJobImpl.h> |
3482 | +#include <unity/storage/internal/safe_strerror.h> |
3483 | +#include <unity/storage/provider/Exceptions.h> |
3484 | #include <unity/storage/provider/UploadJob.h> |
3485 | +#include <unity/storage/provider/internal/MainLoopExecutor.h> |
3486 | |
3487 | #include <sys/socket.h> |
3488 | #include <sys/types.h> |
3489 | @@ -26,6 +29,7 @@ |
3490 | #include <stdexcept> |
3491 | |
3492 | using namespace std; |
3493 | +using namespace unity::storage::internal; |
3494 | |
3495 | namespace unity |
3496 | { |
3497 | @@ -42,18 +46,30 @@ |
3498 | int socks[2]; |
3499 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) < 0) |
3500 | { |
3501 | - throw runtime_error("could not create socketpair"); |
3502 | + int error_code = errno; |
3503 | + string msg = "could not create socketpair: " + safe_strerror(error_code); |
3504 | + throw ResourceException(msg, error_code); |
3505 | } |
3506 | read_socket_ = socks[0]; |
3507 | write_socket_ = socks[1]; |
3508 | + |
3509 | +#if 0 |
3510 | + // TODO: We should be able to half-close the write channel of the read socket, and the read channel of |
3511 | + // the write socket. But, if we do, QLocalSocket indicates that everything was closed, which causes |
3512 | + // failures on the client side. We suspect a QLocalSocket bug -- need to investigate. |
3513 | if (shutdown(read_socket_, SHUT_WR) < 0) |
3514 | { |
3515 | - throw runtime_error("Could not shut down write channel on read socket"); |
3516 | + int error_code = errno; |
3517 | + string msg = "could not shut down write channel on read socket: " + safe_strerror(error_code); |
3518 | + throw ResourceException(msg, error_code); |
3519 | } |
3520 | if (shutdown(write_socket_, SHUT_RD) < 0) |
3521 | { |
3522 | - throw runtime_error("Could not shut down read channel on write socket"); |
3523 | + int error_code = errno; |
3524 | + string msg = "Could not shut down read channel on write socket" + safe_strerror(error_code); |
3525 | + throw ResourceException(msg, error_code); |
3526 | } |
3527 | +#endif |
3528 | } |
3529 | |
3530 | UploadJobImpl::~UploadJobImpl() |
3531 | @@ -72,7 +88,7 @@ |
3532 | { |
3533 | } |
3534 | |
3535 | -std::string const& UploadJobImpl::upload_id() const |
3536 | +string const& UploadJobImpl::upload_id() const |
3537 | { |
3538 | return upload_id_; |
3539 | } |
3540 | @@ -90,28 +106,29 @@ |
3541 | return sock; |
3542 | } |
3543 | |
3544 | -string const& UploadJobImpl::sender_bus_name() const |
3545 | -{ |
3546 | - return sender_bus_name_; |
3547 | -} |
3548 | - |
3549 | -void UploadJobImpl::set_sender_bus_name(string const& bus_name) |
3550 | -{ |
3551 | - assert(bus_name[0] == ':'); |
3552 | - sender_bus_name_ = bus_name; |
3553 | -} |
3554 | - |
3555 | -void UploadJobImpl::report_error(std::exception_ptr p) |
3556 | +void UploadJobImpl::report_error(exception_ptr p) |
3557 | { |
3558 | if (read_socket_ >= 0) |
3559 | { |
3560 | - close(write_socket_); |
3561 | + close(read_socket_); |
3562 | read_socket_ = -1; |
3563 | } |
3564 | |
3565 | lock_guard<mutex> guard(completion_lock_); |
3566 | completed_ = true; |
3567 | - completion_promise_.set_exception(p); |
3568 | + // Convert std::exception_ptr to boost::exception_ptr |
3569 | + try |
3570 | + { |
3571 | + rethrow_exception(p); |
3572 | + } |
3573 | + catch (StorageException const& e) |
3574 | + { |
3575 | + completion_promise_.set_exception(e); |
3576 | + } |
3577 | + catch (...) |
3578 | + { |
3579 | + completion_promise_.set_exception(boost::current_exception()); |
3580 | + } |
3581 | } |
3582 | |
3583 | boost::future<Item> UploadJobImpl::finish(UploadJob& job) |
3584 | |
3585 | === modified file 'src/provider/internal/dbusmarshal.cpp' |
3586 | --- src/provider/internal/dbusmarshal.cpp 2016-07-21 12:48:40 +0000 |
3587 | +++ src/provider/internal/dbusmarshal.cpp 2016-09-09 02:13:43 +0000 |
3588 | @@ -31,29 +31,57 @@ |
3589 | namespace provider |
3590 | { |
3591 | |
3592 | +namespace |
3593 | +{ |
3594 | + |
3595 | +QDBusVariant to_qdbus_variant(MetadataValue const& v) |
3596 | +{ |
3597 | + switch (v.which()) |
3598 | + { |
3599 | + case 0: |
3600 | + return QDBusVariant(QString::fromStdString(boost::get<string>(v))); |
3601 | + case 1: |
3602 | + return QDBusVariant(qlonglong(boost::get<int64_t>(v))); |
3603 | + default: |
3604 | + abort(); // Impossible. // LCOV_EXCL_LINE |
3605 | + } |
3606 | +} |
3607 | + |
3608 | +} // namespace |
3609 | + |
3610 | QDBusArgument& operator<<(QDBusArgument& argument, Item const& item) |
3611 | { |
3612 | argument.beginStructure(); |
3613 | argument << QString::fromStdString(item.item_id); |
3614 | - argument << QString::fromStdString(item.parent_id); |
3615 | + { |
3616 | + argument.beginArray(qMetaTypeId<QString>()); |
3617 | + for (auto const& id : item.parent_ids) |
3618 | + { |
3619 | + argument << QString::fromStdString(id); |
3620 | + } |
3621 | + argument.endArray(); |
3622 | + } |
3623 | argument << QString::fromStdString(item.name); |
3624 | argument << QString::fromStdString(item.etag); |
3625 | argument << static_cast<int32_t>(item.type); |
3626 | - argument.beginMap(QVariant::String, qMetaTypeId<QDBusVariant>()); |
3627 | - for (auto const& pair : item.metadata) |
3628 | { |
3629 | - argument.beginMapEntry(); |
3630 | - argument << QString::fromStdString(pair.first) << QDBusVariant(QString::fromStdString(pair.second)); |
3631 | - argument.endMapEntry(); |
3632 | + argument.beginMap(QVariant::String, qMetaTypeId<QDBusVariant>()); |
3633 | + for (auto const& pair : item.metadata) |
3634 | + { |
3635 | + argument.beginMapEntry(); |
3636 | + argument << QString::fromStdString(pair.first) << to_qdbus_variant(pair.second); |
3637 | + argument.endMapEntry(); |
3638 | + } |
3639 | + argument.endMap(); |
3640 | } |
3641 | - argument.endMap(); |
3642 | argument.endStructure(); |
3643 | return argument; |
3644 | } |
3645 | |
3646 | QDBusArgument const& operator>>(QDBusArgument const&, Item&) |
3647 | { |
3648 | - throw std::runtime_error("Item decode not implemented"); |
3649 | + // We don't expect to ever have to unmarshal anything, only marshal it. |
3650 | + qFatal("unexpected call to operator>>(QDBusArgument const&, Item&)"); // LCOV_EXCL_LINE |
3651 | } |
3652 | |
3653 | QDBusArgument& operator<<(QDBusArgument& argument, ItemList const& items) |
3654 | @@ -69,7 +97,8 @@ |
3655 | |
3656 | QDBusArgument const& operator>>(QDBusArgument const&, ItemList&) |
3657 | { |
3658 | - throw std::runtime_error("std::vector<Item> decode not implemented"); |
3659 | + // We don't expect to ever have to unmarshal anything, only marshal it. |
3660 | + qFatal("unexpected call to operator>>(QDBusArgument const&, ItemList&)"); // LCOV_EXCL_LINE |
3661 | } |
3662 | |
3663 | } |
3664 | |
3665 | === added directory 'src/provider/testing' |
3666 | === added file 'src/provider/testing/TestServer.cpp' |
3667 | --- src/provider/testing/TestServer.cpp 1970-01-01 00:00:00 +0000 |
3668 | +++ src/provider/testing/TestServer.cpp 2016-09-09 02:13:43 +0000 |
3669 | @@ -0,0 +1,60 @@ |
3670 | +/* |
3671 | + * Copyright (C) 2016 Canonical Ltd |
3672 | + * |
3673 | + * This program is free software: you can redistribute it and/or modify |
3674 | + * it under the terms of the GNU Lesser General Public License version 3 as |
3675 | + * published by the Free Software Foundation. |
3676 | + * |
3677 | + * This program is distributed in the hope that it will be useful, |
3678 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3679 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3680 | + * GNU Lesser General Public License for more details. |
3681 | + * |
3682 | + * You should have received a copy of the GNU Lesser General Public License |
3683 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3684 | + * |
3685 | + * Authors: James Henstridge <james.henstridge@canonical.com> |
3686 | + */ |
3687 | + |
3688 | +#include <unity/storage/provider/testing/TestServer.h> |
3689 | +#include <unity/storage/provider/internal/TestServerImpl.h> |
3690 | +#include <unity/storage/provider/ProviderBase.h> |
3691 | + |
3692 | +#include <OnlineAccounts/Account> |
3693 | + |
3694 | +using namespace std; |
3695 | + |
3696 | +namespace unity |
3697 | +{ |
3698 | +namespace storage |
3699 | +{ |
3700 | +namespace provider |
3701 | +{ |
3702 | +namespace testing |
3703 | +{ |
3704 | + |
3705 | +TestServer::TestServer(unique_ptr<ProviderBase>&& provider, |
3706 | + OnlineAccounts::Account* account, |
3707 | + QDBusConnection const& connection, |
3708 | + string const& object_path) |
3709 | + : p_(new internal::TestServerImpl(move(provider), account, |
3710 | + connection, object_path)) |
3711 | +{ |
3712 | +} |
3713 | + |
3714 | +TestServer::~TestServer() = default; |
3715 | + |
3716 | +QDBusConnection const& TestServer::connection() const |
3717 | +{ |
3718 | + return p_->connection(); |
3719 | +} |
3720 | + |
3721 | +string const& TestServer::object_path() const |
3722 | +{ |
3723 | + return p_->object_path(); |
3724 | +} |
3725 | + |
3726 | +} |
3727 | +} |
3728 | +} |
3729 | +} |
3730 | |
3731 | === modified file 'src/qt/client/Account.cpp' |
3732 | --- src/qt/client/Account.cpp 2016-07-12 02:22:05 +0000 |
3733 | +++ src/qt/client/Account.cpp 2016-09-09 02:13:43 +0000 |
3734 | @@ -41,7 +41,7 @@ |
3735 | |
3736 | Account::~Account() = default; |
3737 | |
3738 | -Runtime* Account::runtime() const |
3739 | +shared_ptr<Runtime> Account::runtime() const |
3740 | { |
3741 | return p_->runtime(); |
3742 | } |
3743 | |
3744 | === modified file 'src/qt/client/CMakeLists.txt' |
3745 | --- src/qt/client/CMakeLists.txt 2016-07-27 02:19:17 +0000 |
3746 | +++ src/qt/client/CMakeLists.txt 2016-09-09 02:13:43 +0000 |
3747 | @@ -80,7 +80,7 @@ |
3748 | # Build the remote client library |
3749 | set_source_files_properties(${CMAKE_SOURCE_DIR}/data/provider.xml PROPERTIES |
3750 | CLASSNAME ProviderInterface |
3751 | - INCLUDE unity/storage/qt/client/internal/remote_client/dbusmarshal.h |
3752 | + INCLUDE unity/storage/internal/dbusmarshal.h |
3753 | ) |
3754 | |
3755 | qt5_add_dbus_interface(generated_files |
3756 | @@ -109,6 +109,7 @@ |
3757 | VERSION ${SF_CLIENT_LIBVERSION} |
3758 | ) |
3759 | target_link_libraries(storage-framework-qt-client |
3760 | + storage-framework-common-internal |
3761 | Qt5::Concurrent |
3762 | Qt5::Core |
3763 | Qt5::DBus |
3764 | |
3765 | === modified file 'src/qt/client/Exceptions.cpp' |
3766 | --- src/qt/client/Exceptions.cpp 2016-07-22 01:45:39 +0000 |
3767 | +++ src/qt/client/Exceptions.cpp 2016-09-09 02:13:43 +0000 |
3768 | @@ -42,6 +42,11 @@ |
3769 | return what_string_.c_str(); |
3770 | } |
3771 | |
3772 | +QString StorageException::error_message() const |
3773 | +{ |
3774 | + return error_message_; |
3775 | +} |
3776 | + |
3777 | LocalCommsException::LocalCommsException(QString const& error_message) |
3778 | : StorageException("LocalCommsException", error_message) |
3779 | { |
3780 | @@ -76,10 +81,9 @@ |
3781 | throw *this; |
3782 | } |
3783 | |
3784 | -DeletedException::DeletedException(QString const& error_message, QString const& identity, QString const& name) |
3785 | +DeletedException::DeletedException(QString const& error_message, QString const& identity) |
3786 | : StorageException("DeletedException", error_message) |
3787 | , identity_(identity) |
3788 | - , name_(name) |
3789 | { |
3790 | } |
3791 | |
3792 | @@ -100,13 +104,8 @@ |
3793 | return identity_; |
3794 | } |
3795 | |
3796 | -QString DeletedException::name() const |
3797 | -{ |
3798 | - return name_; |
3799 | -} |
3800 | - |
3801 | RuntimeDestroyedException::RuntimeDestroyedException(QString const& method) |
3802 | - : StorageException("RuntimeDestroyedException", method + ": Runtime was destroyed previously") |
3803 | + : StorageException("RuntimeDestroyedException", method + ": runtime was destroyed previously") |
3804 | { |
3805 | } |
3806 | |
3807 | @@ -276,8 +275,9 @@ |
3808 | throw *this; |
3809 | } |
3810 | |
3811 | -ResourceException::ResourceException(QString const& error_message) |
3812 | +ResourceException::ResourceException(QString const& error_message, int error_code) |
3813 | : StorageException("ResourceException", error_message) |
3814 | + , error_code_(error_code) |
3815 | { |
3816 | } |
3817 | |
3818 | @@ -293,6 +293,11 @@ |
3819 | throw *this; |
3820 | } |
3821 | |
3822 | +int ResourceException::error_code() const noexcept |
3823 | +{ |
3824 | + return error_code_; |
3825 | +} |
3826 | + |
3827 | } // namespace client |
3828 | } // namespace qt |
3829 | } // namespace storage |
3830 | |
3831 | === modified file 'src/qt/client/Item.cpp' |
3832 | --- src/qt/client/Item.cpp 2016-07-14 00:25:40 +0000 |
3833 | +++ src/qt/client/Item.cpp 2016-09-09 02:13:43 +0000 |
3834 | @@ -51,7 +51,7 @@ |
3835 | return p_->name(); |
3836 | } |
3837 | |
3838 | -Root* Item::root() const |
3839 | +shared_ptr<Root> Item::root() const |
3840 | { |
3841 | return p_->root(); |
3842 | } |
3843 | |
3844 | === modified file 'src/qt/client/Root.cpp' |
3845 | --- src/qt/client/Root.cpp 2016-07-12 02:22:05 +0000 |
3846 | +++ src/qt/client/Root.cpp 2016-09-09 02:13:43 +0000 |
3847 | @@ -30,6 +30,7 @@ |
3848 | { |
3849 | |
3850 | using namespace internal; |
3851 | +using namespace std; |
3852 | |
3853 | Root::Root(RootBase* p) |
3854 | : Folder(p) |
3855 | @@ -38,7 +39,7 @@ |
3856 | |
3857 | Root::~Root() = default; |
3858 | |
3859 | -Account* Root::account() const |
3860 | +shared_ptr<Account> Root::account() const |
3861 | { |
3862 | return dynamic_cast<RootBase*>(p_.get())->account(); |
3863 | } |
3864 | |
3865 | === modified file 'src/qt/client/Runtime.cpp' |
3866 | --- src/qt/client/Runtime.cpp 2016-07-21 04:00:29 +0000 |
3867 | +++ src/qt/client/Runtime.cpp 2016-09-09 02:13:43 +0000 |
3868 | @@ -64,6 +64,12 @@ |
3869 | return p_->accounts(); |
3870 | } |
3871 | |
3872 | +shared_ptr<Account> Runtime::make_test_account(QString const& bus_name, |
3873 | + QString const& object_path) |
3874 | +{ |
3875 | + return p_->make_test_account(bus_name, object_path); |
3876 | +} |
3877 | + |
3878 | } // namespace client |
3879 | } // namespace qt |
3880 | } // namespace storage |
3881 | |
3882 | === modified file 'src/qt/client/Uploader.cpp' |
3883 | --- src/qt/client/Uploader.cpp 2016-07-12 02:22:05 +0000 |
3884 | +++ src/qt/client/Uploader.cpp 2016-09-09 02:13:43 +0000 |
3885 | @@ -46,6 +46,11 @@ |
3886 | return p_->socket(); |
3887 | } |
3888 | |
3889 | +int64_t Uploader::size() const |
3890 | +{ |
3891 | + return p_->size(); |
3892 | +} |
3893 | + |
3894 | QFuture<shared_ptr<File>> Uploader::finish_upload() |
3895 | { |
3896 | return p_->finish_upload(); |
3897 | |
3898 | === modified file 'src/qt/client/internal/AccountBase.cpp' |
3899 | --- src/qt/client/internal/AccountBase.cpp 2016-07-14 04:50:36 +0000 |
3900 | +++ src/qt/client/internal/AccountBase.cpp 2016-09-09 02:13:43 +0000 |
3901 | @@ -19,6 +19,8 @@ |
3902 | #include <unity/storage/qt/client/internal/AccountBase.h> |
3903 | |
3904 | #include <unity/storage/qt/client/Exceptions.h> |
3905 | +#include <unity/storage/qt/client/internal/RuntimeBase.h> |
3906 | +#include <unity/storage/qt/client/Runtime.h> |
3907 | |
3908 | #include <cassert> |
3909 | |
3910 | @@ -42,13 +44,18 @@ |
3911 | assert(runtime.lock()); |
3912 | } |
3913 | |
3914 | -Runtime* AccountBase::runtime() const |
3915 | +shared_ptr<Runtime> AccountBase::runtime() const |
3916 | { |
3917 | if (auto runtime = runtime_.lock()) |
3918 | { |
3919 | - return runtime.get(); |
3920 | + auto runtime_base = runtime->p_; |
3921 | + if (runtime_base->destroyed_) |
3922 | + { |
3923 | + throw RuntimeDestroyedException("Account::runtime()"); |
3924 | + } |
3925 | + return runtime; |
3926 | } |
3927 | - throw RuntimeDestroyedException("AccountBase::runtime()"); |
3928 | + throw RuntimeDestroyedException("Account::runtime()"); |
3929 | } |
3930 | |
3931 | void AccountBase::set_public_instance(weak_ptr<Account> const& p) |
3932 | |
3933 | === modified file 'src/qt/client/internal/ItemBase.cpp' |
3934 | --- src/qt/client/internal/ItemBase.cpp 2016-07-14 04:50:36 +0000 |
3935 | +++ src/qt/client/internal/ItemBase.cpp 2016-09-09 02:13:43 +0000 |
3936 | @@ -18,7 +18,9 @@ |
3937 | |
3938 | #include <unity/storage/qt/client/internal/ItemBase.h> |
3939 | |
3940 | +#include <unity/storage/qt/client/Account.h> |
3941 | #include <unity/storage/qt/client/Exceptions.h> |
3942 | +#include <unity/storage/qt/client/Root.h> |
3943 | |
3944 | #include <cassert> |
3945 | |
3946 | @@ -46,21 +48,24 @@ |
3947 | |
3948 | QString ItemBase::native_identity() const |
3949 | { |
3950 | + throw_if_destroyed("Item::native_identity()"); |
3951 | return identity_; |
3952 | } |
3953 | |
3954 | ItemType ItemBase::type() const |
3955 | { |
3956 | + throw_if_destroyed("Item::type()"); |
3957 | return type_; |
3958 | } |
3959 | |
3960 | -Root* ItemBase::root() const |
3961 | +shared_ptr<Root> ItemBase::root() const |
3962 | { |
3963 | - if (auto r = root_.lock()) |
3964 | + auto root = get_root(); |
3965 | + if (!root) |
3966 | { |
3967 | - return r.get(); |
3968 | + throw RuntimeDestroyedException("Item::root()"); |
3969 | } |
3970 | - throw RuntimeDestroyedException("Item::root()"); |
3971 | + return root; |
3972 | } |
3973 | |
3974 | void ItemBase::set_root(std::weak_ptr<Root> root) |
3975 | @@ -75,6 +80,36 @@ |
3976 | public_instance_ = p; |
3977 | } |
3978 | |
3979 | +shared_ptr<Root> ItemBase::get_root() const noexcept |
3980 | +{ |
3981 | + try |
3982 | + { |
3983 | + auto root = root_.lock(); |
3984 | + if (root) |
3985 | + { |
3986 | + root->account(); // Throws if either account or runtime has been destroyed. |
3987 | + return root; |
3988 | + } |
3989 | + } |
3990 | + catch (RuntimeDestroyedException const&) |
3991 | + { |
3992 | + } |
3993 | + return nullptr; |
3994 | +} |
3995 | + |
3996 | +void ItemBase::throw_if_destroyed(QString const& method) const |
3997 | +{ |
3998 | + if (deleted_) |
3999 | + { |
4000 | + QString msg = method + ": \"" + identity_ + "\" was deleted previously"; |
4001 | + throw DeletedException(msg, identity_); |
4002 | + } |
4003 | + if (!get_root()) |
4004 | + { |
4005 | + throw RuntimeDestroyedException(method); |
4006 | + } |
4007 | +} |
4008 | + |
4009 | } // namespace internal |
4010 | } // namespace client |
4011 | } // namespace qt |
4012 | |
4013 | === modified file 'src/qt/client/internal/RootBase.cpp' |
4014 | --- src/qt/client/internal/RootBase.cpp 2016-07-27 02:19:17 +0000 |
4015 | +++ src/qt/client/internal/RootBase.cpp 2016-09-09 02:13:43 +0000 |
4016 | @@ -18,6 +18,7 @@ |
4017 | |
4018 | #include <unity/storage/qt/client/internal/RootBase.h> |
4019 | |
4020 | +#include <unity/storage/qt/client/Account.h> |
4021 | #include <unity/storage/qt/client/Exceptions.h> |
4022 | |
4023 | #include <cassert> |
4024 | @@ -43,11 +44,19 @@ |
4025 | assert(account.lock()); |
4026 | } |
4027 | |
4028 | -Account* RootBase::account() const |
4029 | +shared_ptr<Account> RootBase::account() const |
4030 | { |
4031 | if (auto acc = account_.lock()) |
4032 | { |
4033 | - return acc.get(); |
4034 | + try |
4035 | + { |
4036 | + acc->runtime(); |
4037 | + } |
4038 | + catch (RuntimeDestroyedException const&) |
4039 | + { |
4040 | + throw RuntimeDestroyedException("Root::account()"); |
4041 | + } |
4042 | + return acc; |
4043 | } |
4044 | throw RuntimeDestroyedException("Root::account()"); |
4045 | } |
4046 | |
4047 | === modified file 'src/qt/client/internal/RuntimeBase.cpp' |
4048 | --- src/qt/client/internal/RuntimeBase.cpp 2016-07-12 02:22:05 +0000 |
4049 | +++ src/qt/client/internal/RuntimeBase.cpp 2016-09-09 02:13:43 +0000 |
4050 | @@ -34,11 +34,6 @@ |
4051 | namespace internal |
4052 | { |
4053 | |
4054 | -RuntimeBase::RuntimeBase() |
4055 | - : destroyed_(false) |
4056 | -{ |
4057 | -} |
4058 | - |
4059 | void RuntimeBase::set_public_instance(weak_ptr<Runtime> p) |
4060 | { |
4061 | assert(p.lock()); |
4062 | |
4063 | === modified file 'src/qt/client/internal/UploaderBase.cpp' |
4064 | --- src/qt/client/internal/UploaderBase.cpp 2016-07-22 01:45:39 +0000 |
4065 | +++ src/qt/client/internal/UploaderBase.cpp 2016-09-09 02:13:43 +0000 |
4066 | @@ -25,6 +25,8 @@ |
4067 | #include <QFuture> |
4068 | #pragma GCC diagnostic pop |
4069 | |
4070 | +#include <cassert> |
4071 | + |
4072 | using namespace std; |
4073 | |
4074 | namespace unity |
4075 | @@ -38,9 +40,16 @@ |
4076 | namespace internal |
4077 | { |
4078 | |
4079 | -UploaderBase::UploaderBase(ConflictPolicy policy) |
4080 | +UploaderBase::UploaderBase(ConflictPolicy policy, int64_t size) |
4081 | : policy_(policy) |
4082 | -{ |
4083 | + , size_(size) |
4084 | +{ |
4085 | + assert(size >= 0); |
4086 | +} |
4087 | + |
4088 | +int64_t UploaderBase::size() const |
4089 | +{ |
4090 | + return size_; |
4091 | } |
4092 | |
4093 | } // namespace internal |
4094 | |
4095 | === modified file 'src/qt/client/internal/local_client/AccountImpl.cpp' |
4096 | --- src/qt/client/internal/local_client/AccountImpl.cpp 2016-07-14 04:50:36 +0000 |
4097 | +++ src/qt/client/internal/local_client/AccountImpl.cpp 2016-09-09 02:13:43 +0000 |
4098 | @@ -67,7 +67,7 @@ |
4099 | if (ec) |
4100 | { |
4101 | QString msg = "Account::roots(): Cannot stat " + QString(dir) + ": " + QString::fromStdString(ec.message()); |
4102 | - throw ResourceException(msg); |
4103 | + throw ResourceException(msg, errno); |
4104 | } |
4105 | if (!is_dir) |
4106 | { |
4107 | @@ -85,7 +85,7 @@ |
4108 | { |
4109 | QString msg = "Account::roots(): Cannot create " + QString(dir) + ": " |
4110 | + QString::fromStdString(ec.message()); |
4111 | - throw ResourceException(msg); |
4112 | + throw ResourceException(msg, ec.value()); |
4113 | } |
4114 | } |
4115 | return data_dir; |
4116 | @@ -109,22 +109,32 @@ |
4117 | |
4118 | QString AccountImpl::owner() const |
4119 | { |
4120 | + runtime(); // Throws RuntimeDestroyedException if runtime was destroyed. |
4121 | return owner_; |
4122 | } |
4123 | |
4124 | QString AccountImpl::owner_id() const |
4125 | { |
4126 | + runtime(); // Throws RuntimeDestroyedException if runtime was destroyed. |
4127 | return owner_id_; |
4128 | } |
4129 | |
4130 | QString AccountImpl::description() const |
4131 | { |
4132 | + runtime(); // Throws RuntimeDestroyedException if runtime was destroyed. |
4133 | return description_; |
4134 | } |
4135 | |
4136 | QFuture<QVector<Root::SPtr>> AccountImpl::roots() |
4137 | { |
4138 | - using namespace boost::filesystem; |
4139 | + try |
4140 | + { |
4141 | + runtime(); // Throws RuntimeDestroyedException if runtime was destroyed. |
4142 | + } |
4143 | + catch (RuntimeDestroyedException const& e) |
4144 | + { |
4145 | + return make_exceptional_future<QVector<Root::SPtr>>(e); |
4146 | + } |
4147 | |
4148 | if (!roots_.isEmpty()) |
4149 | { |
4150 | @@ -132,6 +142,9 @@ |
4151 | } |
4152 | |
4153 | // Create the root on first access. |
4154 | + |
4155 | + using namespace boost::filesystem; |
4156 | + |
4157 | auto rpath = canonical(get_data_dir()).native(); |
4158 | auto root = RootImpl::make_root(QString::fromStdString(rpath), public_instance_); |
4159 | roots_.append(root); |
4160 | |
4161 | === modified file 'src/qt/client/internal/local_client/CMakeLists.txt' |
4162 | --- src/qt/client/internal/local_client/CMakeLists.txt 2016-07-22 00:17:24 +0000 |
4163 | +++ src/qt/client/internal/local_client/CMakeLists.txt 2016-09-09 02:13:43 +0000 |
4164 | @@ -7,6 +7,7 @@ |
4165 | ${CMAKE_CURRENT_SOURCE_DIR}/RootImpl.cpp |
4166 | ${CMAKE_CURRENT_SOURCE_DIR}/Runtime_create.cpp |
4167 | ${CMAKE_CURRENT_SOURCE_DIR}/RuntimeImpl.cpp |
4168 | + ${CMAKE_CURRENT_SOURCE_DIR}/storage_exception.cpp |
4169 | ${CMAKE_CURRENT_SOURCE_DIR}/UploaderImpl.cpp |
4170 | ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h |
4171 | ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/client/internal/local_client/UploaderImpl.h |
4172 | |
4173 | === modified file 'src/qt/client/internal/local_client/DownloaderImpl.cpp' |
4174 | --- src/qt/client/internal/local_client/DownloaderImpl.cpp 2016-07-22 00:17:24 +0000 |
4175 | +++ src/qt/client/internal/local_client/DownloaderImpl.cpp 2016-09-09 02:13:43 +0000 |
4176 | @@ -23,7 +23,10 @@ |
4177 | #include <unity/storage/qt/client/File.h> |
4178 | #include <unity/storage/qt/client/internal/make_future.h> |
4179 | |
4180 | +#pragma GCC diagnostic push |
4181 | +#pragma GCC diagnostic ignored "-Wcast-align" |
4182 | #include <QLocalSocket> |
4183 | +#pragma GCC diagnostic pop |
4184 | |
4185 | #include <cassert> |
4186 | |
4187 | @@ -79,8 +82,10 @@ |
4188 | input_file_.reset(new QFile(filename_)); |
4189 | if (!input_file_->open(QIODevice::ReadOnly)) |
4190 | { |
4191 | - handle_error("cannot open " + filename_ + ": " + input_file_->errorString()); |
4192 | + // LCOV_EXCL_START |
4193 | + handle_error("cannot open " + filename_ + ": " + input_file_->errorString(), input_file_->error()); |
4194 | return; |
4195 | + // LCOV_EXCL_STOP |
4196 | } |
4197 | bytes_to_write_ = input_file_->size(); |
4198 | |
4199 | @@ -116,7 +121,7 @@ |
4200 | + QString::number(written) + " byte"; |
4201 | msg += written == 1 ? " was" : "s were"; |
4202 | msg += " consumed."; |
4203 | - make_exceptional_future(qf_, LogicException(msg)); |
4204 | + qf_.reportException(LogicException(msg)); |
4205 | } |
4206 | else |
4207 | { |
4208 | @@ -131,12 +136,12 @@ |
4209 | case cancelled: |
4210 | { |
4211 | QString msg = "Downloader::finish_download(): download of " + filename_ + " was cancelled"; |
4212 | - make_exceptional_future(qf_, CancelledException(msg)); |
4213 | + qf_.reportException(CancelledException(msg)); |
4214 | break; |
4215 | } |
4216 | case error: |
4217 | { |
4218 | - make_exceptional_future(qf_, ResourceException(error_msg_)); |
4219 | + qf_.reportException(ResourceException(error_msg_, error_code_)); |
4220 | break; |
4221 | } |
4222 | default: |
4223 | @@ -144,7 +149,7 @@ |
4224 | abort(); // LCOV_EXCL_LINE // Impossible |
4225 | } |
4226 | } |
4227 | - make_ready_future(qf_); |
4228 | + qf_.reportFinished(); |
4229 | QThread::currentThread()->quit(); |
4230 | } |
4231 | |
4232 | @@ -189,7 +194,8 @@ |
4233 | |
4234 | void DownloadWorker::on_error() |
4235 | { |
4236 | - handle_error(write_socket_->errorString()); |
4237 | + disconnect(write_socket_.get(), nullptr, this, nullptr); |
4238 | + handle_error(write_socket_->errorString(), write_socket_->error()); |
4239 | } |
4240 | |
4241 | // Read the next chunk of data from the input file and write it to the socket. |
4242 | @@ -203,25 +209,31 @@ |
4243 | auto bytes_read = input_file_->read(buf.data(), buf.size()); |
4244 | if (bytes_read == -1) |
4245 | { |
4246 | - handle_error(filename_ + ": read error: " + input_file_->errorString()); |
4247 | + // LCOV_EXCL_START |
4248 | + handle_error(filename_ + ": read error: " + input_file_->errorString(), input_file_->error()); |
4249 | return; |
4250 | + // LCOV_EXCL_STOP |
4251 | } |
4252 | buf.resize(bytes_read); |
4253 | |
4254 | auto bytes_written = write_socket_->write(buf); |
4255 | if (bytes_written == -1) |
4256 | { |
4257 | - handle_error(filename_ + ": socket error: " + write_socket_->errorString()); |
4258 | + // LCOV_EXCL_START |
4259 | + handle_error(filename_ + ": socket error: " + write_socket_->errorString(), write_socket_->error()); |
4260 | + // LCOV_EXCL_STOP |
4261 | } |
4262 | else if (bytes_written != bytes_read) |
4263 | { |
4264 | + // LCOV_EXCL_START |
4265 | QString msg = filename_ + ": write error, requested " + bytes_read + " B, but wrote only " |
4266 | + bytes_written + " B."; |
4267 | - handle_error(msg); |
4268 | + handle_error(msg, 0); |
4269 | + // LCOV_EXCL_STOP |
4270 | } |
4271 | } |
4272 | |
4273 | -void DownloadWorker::handle_error(QString const& msg) |
4274 | +void DownloadWorker::handle_error(QString const& msg, int error_code) |
4275 | { |
4276 | if (state_ == in_progress) |
4277 | { |
4278 | @@ -229,6 +241,7 @@ |
4279 | } |
4280 | state_ = error; |
4281 | error_msg_ = "Downloader: " + msg; |
4282 | + error_code_ = error_code; |
4283 | do_finish(); |
4284 | } |
4285 | |
4286 | @@ -245,17 +258,18 @@ |
4287 | |
4288 | DownloaderImpl::DownloaderImpl(weak_ptr<File> file) |
4289 | : DownloaderBase(file) |
4290 | - , read_socket_(new QLocalSocket) |
4291 | + , read_socket_(new QLocalSocket, [](QLocalSocket* s){ s->deleteLater(); }) |
4292 | { |
4293 | // Set up socket pair. |
4294 | int fds[2]; |
4295 | - int rc = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds); |
4296 | + int rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); |
4297 | if (rc == -1) |
4298 | { |
4299 | // LCOV_EXCL_START |
4300 | QString msg = "Downloader: cannot create socket pair: " |
4301 | + QString::fromStdString(storage::internal::safe_strerror(errno)); |
4302 | - make_exceptional_future(qf_, ResourceException(msg)); |
4303 | + qf_.reportException(ResourceException(msg, errno)); |
4304 | + qf_.reportFinished(); |
4305 | return; |
4306 | // LCOV_EXCL_STOP |
4307 | } |
4308 | |
4309 | === modified file 'src/qt/client/internal/local_client/FileImpl.cpp' |
4310 | --- src/qt/client/internal/local_client/FileImpl.cpp 2016-07-22 01:45:39 +0000 |
4311 | +++ src/qt/client/internal/local_client/FileImpl.cpp 2016-09-09 02:13:43 +0000 |
4312 | @@ -22,6 +22,7 @@ |
4313 | #include <unity/storage/qt/client/Exceptions.h> |
4314 | #include <unity/storage/qt/client/File.h> |
4315 | #include <unity/storage/qt/client/internal/local_client/DownloaderImpl.h> |
4316 | +#include <unity/storage/qt/client/internal/local_client/storage_exception.h> |
4317 | #include <unity/storage/qt/client/internal/local_client/UploaderImpl.h> |
4318 | #include <unity/storage/qt/client/internal/make_future.h> |
4319 | #include <unity/storage/qt/client/Uploader.h> |
4320 | @@ -50,47 +51,44 @@ |
4321 | |
4322 | QString FileImpl::name() const |
4323 | { |
4324 | - lock_guard<mutex> guard(mutex_); |
4325 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4326 | |
4327 | - if (deleted_) |
4328 | - { |
4329 | - throw deleted_ex("File::name()"); |
4330 | - } |
4331 | + throw_if_destroyed("File::name()"); |
4332 | return name_; |
4333 | } |
4334 | |
4335 | int64_t FileImpl::size() const |
4336 | { |
4337 | - lock_guard<mutex> guard(mutex_); |
4338 | - |
4339 | - if (deleted_) |
4340 | - { |
4341 | - throw deleted_ex("File::size()"); |
4342 | - } |
4343 | - |
4344 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4345 | + |
4346 | + throw_if_destroyed("File::size()"); |
4347 | try |
4348 | { |
4349 | boost::filesystem::path p = identity_.toStdString(); |
4350 | return file_size(p); |
4351 | } |
4352 | - catch (std::exception const& e) |
4353 | + catch (std::exception const&) |
4354 | { |
4355 | - throw ResourceException(e.what()); |
4356 | + throw_storage_exception(QString("File::size()"), current_exception()); |
4357 | } |
4358 | } |
4359 | |
4360 | QFuture<Uploader::SPtr> FileImpl::create_uploader(ConflictPolicy policy, int64_t size) |
4361 | { |
4362 | - lock_guard<mutex> guard(mutex_); |
4363 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4364 | |
4365 | - if (deleted_) |
4366 | - { |
4367 | - return make_exceptional_future<Uploader::SPtr>(deleted_ex("File::create_uploader()")); |
4368 | + try |
4369 | + { |
4370 | + throw_if_destroyed("File::create_uploader()"); |
4371 | + } |
4372 | + catch (StorageException const& e) |
4373 | + { |
4374 | + return internal::make_exceptional_future<Uploader::SPtr>(e); |
4375 | } |
4376 | if (size < 0) |
4377 | { |
4378 | QString msg = "File::create_uploader(): size must be >= 0"; |
4379 | - return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); |
4380 | + return internal::make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); |
4381 | } |
4382 | |
4383 | auto file = dynamic_pointer_cast<File>(public_instance_.lock()); |
4384 | @@ -102,11 +100,15 @@ |
4385 | |
4386 | QFuture<Downloader::SPtr> FileImpl::create_downloader() |
4387 | { |
4388 | - lock_guard<mutex> guard(mutex_); |
4389 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4390 | |
4391 | - if (deleted_) |
4392 | - { |
4393 | - return make_exceptional_future<Downloader::SPtr>(deleted_ex("File::create_downloader()")); |
4394 | + try |
4395 | + { |
4396 | + throw_if_destroyed("File::create_downloader()"); |
4397 | + } |
4398 | + catch (StorageException const& e) |
4399 | + { |
4400 | + return internal::make_exceptional_future<Downloader::SPtr>(e); |
4401 | } |
4402 | |
4403 | auto pi = public_instance_.lock(); |
4404 | |
4405 | === modified file 'src/qt/client/internal/local_client/FolderImpl.cpp' |
4406 | --- src/qt/client/internal/local_client/FolderImpl.cpp 2016-07-22 01:45:39 +0000 |
4407 | +++ src/qt/client/internal/local_client/FolderImpl.cpp 2016-09-09 02:13:43 +0000 |
4408 | @@ -24,7 +24,8 @@ |
4409 | #include <unity/storage/qt/client/Uploader.h> |
4410 | #include <unity/storage/qt/client/internal/make_future.h> |
4411 | #include <unity/storage/qt/client/internal/local_client/FileImpl.h> |
4412 | -#include <unity/storage/qt/client/internal/local_client/tmpfile-prefix.h> |
4413 | +#include <unity/storage/qt/client/internal/local_client/storage_exception.h> |
4414 | +#include <unity/storage/qt/client/internal/local_client/tmpfile_prefix.h> |
4415 | #include <unity/storage/qt/client/internal/local_client/UploaderImpl.h> |
4416 | |
4417 | #include <boost/algorithm/string/predicate.hpp> |
4418 | @@ -62,22 +63,36 @@ |
4419 | { |
4420 | } |
4421 | |
4422 | +QString FolderImpl::name() const |
4423 | +{ |
4424 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4425 | + |
4426 | + throw_if_destroyed("Item::name()"); |
4427 | + return name_; |
4428 | +} |
4429 | + |
4430 | QFuture<QVector<Item::SPtr>> FolderImpl::list() const |
4431 | { |
4432 | + try |
4433 | + { |
4434 | + throw_if_destroyed("Folder::list()"); |
4435 | + } |
4436 | + catch (StorageException const& e) |
4437 | + { |
4438 | + return internal::make_exceptional_future<QVector<Item::SPtr>>(e); |
4439 | + } |
4440 | + |
4441 | auto This = dynamic_pointer_cast<FolderImpl const>(shared_from_this()); // Keep this folder alive while the lambda is alive. |
4442 | auto list = [This]() |
4443 | { |
4444 | - lock_guard<mutex> guard(This->mutex_); |
4445 | - |
4446 | - if (This->deleted_) |
4447 | - { |
4448 | - throw This->deleted_ex("Folder::list()"); |
4449 | - } |
4450 | - |
4451 | + lock_guard<decltype(mutex_)> guard(This->mutex_); |
4452 | + |
4453 | + This->throw_if_destroyed("Folder::list()"); |
4454 | try |
4455 | { |
4456 | using namespace boost::filesystem; |
4457 | |
4458 | + auto root = This->root_.lock(); |
4459 | QVector<Item::SPtr> results; |
4460 | for (directory_iterator it(This->native_identity().toStdString()); it != directory_iterator(); ++it) |
4461 | { |
4462 | @@ -90,11 +105,11 @@ |
4463 | QString path = QString::fromStdString(dirent.path().native()); |
4464 | if (is_directory(s)) |
4465 | { |
4466 | - results.append(make_folder(path, This->root_)); |
4467 | + results.append(make_folder(path, root)); |
4468 | } |
4469 | else if (is_regular_file(s)) |
4470 | { |
4471 | - results.append(FileImpl::make_file(path, This->root_)); |
4472 | + results.append(FileImpl::make_file(path, root)); |
4473 | } |
4474 | else |
4475 | { |
4476 | @@ -103,9 +118,9 @@ |
4477 | } |
4478 | return results; |
4479 | } |
4480 | - catch (std::exception const& e) |
4481 | + catch (std::exception const&) |
4482 | { |
4483 | - throw ResourceException(QString("Folder::list(): ") + e.what()); |
4484 | + throw_storage_exception("Folder::list()", current_exception()); |
4485 | } |
4486 | }; |
4487 | return QtConcurrent::run(list); |
4488 | @@ -113,49 +128,51 @@ |
4489 | |
4490 | QFuture<QVector<Item::SPtr>> FolderImpl::lookup(QString const& name) const |
4491 | { |
4492 | + try |
4493 | + { |
4494 | + throw_if_destroyed("Folder::lookup()"); |
4495 | + } |
4496 | + catch (StorageException const& e) |
4497 | + { |
4498 | + return internal::make_exceptional_future<QVector<Item::SPtr>>(e); |
4499 | + } |
4500 | + |
4501 | auto This = dynamic_pointer_cast<FolderImpl const>(shared_from_this()); // Keep this folder alive while the lambda is alive. |
4502 | auto lookup = [This, name]() -> QVector<Item::SPtr> |
4503 | { |
4504 | - lock_guard<mutex> guard(This->mutex_); |
4505 | - |
4506 | - if (This->deleted_) |
4507 | - { |
4508 | - throw This->deleted_ex("Folder::lookup()"); |
4509 | - } |
4510 | - |
4511 | + lock_guard<decltype(mutex_)> guard(This->mutex_); |
4512 | + |
4513 | + This->throw_if_destroyed("Folder::lookup()"); // LCOV_EXCL_LINE |
4514 | try |
4515 | { |
4516 | using namespace boost::filesystem; |
4517 | |
4518 | + auto root = This->root_.lock(); |
4519 | path p = This->native_identity().toStdString(); |
4520 | auto sanitized_name = sanitize(name, "Folder::lookup()"); |
4521 | if (is_reserved_path(sanitized_name)) |
4522 | { |
4523 | - throw NotExistsException("Folder::lookup(): no such item: " + name, name); |
4524 | + throw NotExistsException("Folder::lookup(): no such item: \"" + name + "\"", name); |
4525 | } |
4526 | p /= sanitized_name; |
4527 | file_status s = status(p); |
4528 | if (is_directory(s)) |
4529 | { |
4530 | QVector<Item::SPtr> v; |
4531 | - v.append(make_folder(QString::fromStdString(p.native()), This->root_)); |
4532 | + v.append(make_folder(QString::fromStdString(p.native()), root)); |
4533 | return v; |
4534 | } |
4535 | if (is_regular_file(s)) |
4536 | { |
4537 | QVector<Item::SPtr> v; |
4538 | - v.append(FileImpl::make_file(QString::fromStdString(p.native()), This->root_)); |
4539 | + v.append(FileImpl::make_file(QString::fromStdString(p.native()), root)); |
4540 | return v; |
4541 | } |
4542 | - throw NotExistsException("Folder::lookup(): no such item: " + name, name); |
4543 | - } |
4544 | - catch (StorageException const&) |
4545 | - { |
4546 | - throw; |
4547 | - } |
4548 | - catch (std::exception const& e) |
4549 | - { |
4550 | - throw ResourceException(QString("Folder::lookup(): ") + e.what()); |
4551 | + throw NotExistsException("Folder::lookup(): no such item: \"" + name + "\"", name); |
4552 | + } |
4553 | + catch (std::exception const&) |
4554 | + { |
4555 | + throw_storage_exception("Folder::lookup()", current_exception()); |
4556 | } |
4557 | }; |
4558 | return QtConcurrent::run(lookup); |
4559 | @@ -163,12 +180,15 @@ |
4560 | |
4561 | QFuture<Folder::SPtr> FolderImpl::create_folder(QString const& name) |
4562 | { |
4563 | - lock_guard<mutex> guard(mutex_); |
4564 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4565 | |
4566 | - QFutureInterface<Folder::SPtr> qf; |
4567 | - if (deleted_) |
4568 | - { |
4569 | - return make_exceptional_future<Folder::SPtr>(deleted_ex("Folder::create_folder()")); |
4570 | + try |
4571 | + { |
4572 | + throw_if_destroyed("Folder::create_folder()"); |
4573 | + } |
4574 | + catch (StorageException const& e) |
4575 | + { |
4576 | + return internal::make_exceptional_future<Folder::SPtr>(e); |
4577 | } |
4578 | |
4579 | try |
4580 | @@ -179,31 +199,40 @@ |
4581 | auto sanitized_name = sanitize(name, "Folder::create_folder()"); |
4582 | if (is_reserved_path(sanitized_name)) |
4583 | { |
4584 | - QString msg = "Folder::create_folder(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved"; |
4585 | - return make_exceptional_future<Folder::SPtr>(InvalidArgumentException(msg)); |
4586 | + QString msg = "Folder::create_folder(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved"; |
4587 | + throw InvalidArgumentException(msg); |
4588 | } |
4589 | p /= sanitized_name; |
4590 | + if (exists(p)) |
4591 | + { |
4592 | + QString msg = "Folder::create_folder(): item with name \"" + name + "\" exists already"; |
4593 | + throw ExistsException(msg, native_identity() + "/" + name, name); |
4594 | + } |
4595 | create_directory(p); |
4596 | return make_ready_future(make_folder(QString::fromStdString(p.native()), root_)); |
4597 | } |
4598 | - catch (std::exception const& e) |
4599 | + catch (std::exception const&) |
4600 | { |
4601 | - return make_exceptional_future<Folder::SPtr>(ResourceException(QString("Folder::create_folder: ") + e.what())); |
4602 | + return make_exceptional_future<Folder::SPtr>("Folder::create_folder()", current_exception()); |
4603 | } |
4604 | } |
4605 | |
4606 | QFuture<shared_ptr<Uploader>> FolderImpl::create_file(QString const& name, int64_t size) |
4607 | { |
4608 | - unique_lock<mutex> guard(mutex_); |
4609 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4610 | |
4611 | - if (deleted_) |
4612 | - { |
4613 | - return make_exceptional_future<Uploader::SPtr>(deleted_ex("Folder::create_file()")); |
4614 | + try |
4615 | + { |
4616 | + throw_if_destroyed("Folder::create_file()"); |
4617 | + } |
4618 | + catch (StorageException const& e) |
4619 | + { |
4620 | + return internal::make_exceptional_future<shared_ptr<Uploader>>(e); |
4621 | } |
4622 | if (size < 0) |
4623 | { |
4624 | QString msg = "Folder::create_file(): size must be >= 0"; |
4625 | - return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); |
4626 | + return internal::make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); |
4627 | } |
4628 | |
4629 | try |
4630 | @@ -214,14 +243,14 @@ |
4631 | auto sanitized_name = sanitize(name, "Folder::create_file()"); |
4632 | if (is_reserved_path(sanitized_name)) |
4633 | { |
4634 | - QString msg = "Folder::create_file(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved"; |
4635 | - return make_exceptional_future<Uploader::SPtr>(InvalidArgumentException(msg)); |
4636 | + QString msg = "Folder::create_file(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved"; |
4637 | + throw InvalidArgumentException(msg); |
4638 | } |
4639 | p /= sanitized_name; |
4640 | if (exists(p)) |
4641 | { |
4642 | QString msg = "Folder::create_file(): item with name \"" + name + "\" exists already"; |
4643 | - return make_exceptional_future<Uploader::SPtr>(ExistsException(msg, native_identity(), name)); |
4644 | + throw ExistsException(msg, native_identity() + "/" + name, name); |
4645 | } |
4646 | auto impl = new UploaderImpl(shared_ptr<File>(), |
4647 | size, |
4648 | @@ -231,9 +260,9 @@ |
4649 | Uploader::SPtr uploader(new Uploader(impl)); |
4650 | return make_ready_future(uploader); |
4651 | } |
4652 | - catch (std::exception const& e) |
4653 | + catch (std::exception const&) |
4654 | { |
4655 | - return make_exceptional_future<Uploader::SPtr>(ResourceException(QString("Folder::create_file: ") + e.what())); |
4656 | + return make_exceptional_future<Uploader::SPtr>("Folder::create_file()", current_exception()); |
4657 | } |
4658 | } |
4659 | |
4660 | |
4661 | === modified file 'src/qt/client/internal/local_client/ItemImpl.cpp' |
4662 | --- src/qt/client/internal/local_client/ItemImpl.cpp 2016-07-22 00:17:24 +0000 |
4663 | +++ src/qt/client/internal/local_client/ItemImpl.cpp 2016-09-09 02:13:43 +0000 |
4664 | @@ -21,14 +21,16 @@ |
4665 | #include <unity/storage/internal/safe_strerror.h> |
4666 | #include <unity/storage/qt/client/Account.h> |
4667 | #include <unity/storage/qt/client/Exceptions.h> |
4668 | -#include <unity/storage/qt/client/internal/make_future.h> |
4669 | #include <unity/storage/qt/client/internal/local_client/AccountImpl.h> |
4670 | #include <unity/storage/qt/client/internal/local_client/FileImpl.h> |
4671 | #include <unity/storage/qt/client/internal/local_client/RootImpl.h> |
4672 | -#include <unity/storage/qt/client/internal/local_client/tmpfile-prefix.h> |
4673 | +#include <unity/storage/qt/client/internal/local_client/storage_exception.h> |
4674 | +#include <unity/storage/qt/client/internal/local_client/tmpfile_prefix.h> |
4675 | +#include <unity/storage/qt/client/internal/make_future.h> |
4676 | |
4677 | #include <boost/algorithm/string/predicate.hpp> |
4678 | #pragma GCC diagnostic push |
4679 | +#pragma GCC diagnostic ignored "-Wcast-align" |
4680 | #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
4681 | #include <QtConcurrent> |
4682 | #pragma GCC diagnostic pop |
4683 | @@ -54,7 +56,6 @@ |
4684 | |
4685 | ItemImpl::ItemImpl(QString const& identity, ItemType type) |
4686 | : ItemBase(identity, type) |
4687 | - , deleted_(false) |
4688 | { |
4689 | assert(!identity.isEmpty()); |
4690 | auto path = boost::filesystem::canonical(identity.toStdString()); |
4691 | @@ -64,102 +65,70 @@ |
4692 | |
4693 | ItemImpl::~ItemImpl() = default; |
4694 | |
4695 | -QString ItemImpl::name() const |
4696 | -{ |
4697 | - lock_guard<mutex> guard(mutex_); |
4698 | - |
4699 | - if (deleted_) |
4700 | - { |
4701 | - throw deleted_ex("Item::name()"); |
4702 | - } |
4703 | - return name_; |
4704 | -} |
4705 | - |
4706 | QString ItemImpl::etag() const |
4707 | { |
4708 | - lock_guard<mutex> guard(mutex_); |
4709 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4710 | |
4711 | - if (deleted_) |
4712 | - { |
4713 | - throw deleted_ex("Item::etag()"); |
4714 | - } |
4715 | + throw_if_destroyed("Item::etag()"); |
4716 | return etag_; |
4717 | } |
4718 | |
4719 | QVariantMap ItemImpl::metadata() const |
4720 | { |
4721 | - lock_guard<mutex> guard(mutex_); |
4722 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4723 | |
4724 | - if (deleted_) |
4725 | - { |
4726 | - throw deleted_ex("Item::metadata()"); |
4727 | - } |
4728 | + throw_if_destroyed("Item::metadata()"); |
4729 | return metadata_; |
4730 | } |
4731 | |
4732 | QDateTime ItemImpl::last_modified_time() const |
4733 | { |
4734 | - lock_guard<mutex> guard(mutex_); |
4735 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4736 | |
4737 | - if (deleted_) |
4738 | - { |
4739 | - throw deleted_ex("Item::last_modified_time()"); |
4740 | - } |
4741 | + throw_if_destroyed("Item::last_modified_time()"); |
4742 | return modified_time_; |
4743 | } |
4744 | |
4745 | -namespace |
4746 | -{ |
4747 | - |
4748 | -using namespace boost::filesystem; |
4749 | - |
4750 | -void copy_recursively(path const& source, path const& target) |
4751 | -{ |
4752 | - auto s = status(source); |
4753 | - if (is_regular_file(s)) |
4754 | - { |
4755 | - copy_file(source, target); |
4756 | - return; |
4757 | - } |
4758 | - else if (is_directory(s)) |
4759 | - { |
4760 | - copy_directory(source, target); // Poorly named in boost; this creates the target dir without recursion |
4761 | - for (directory_iterator it(source); it != directory_iterator(); ++it) |
4762 | - { |
4763 | - path source_entry = it->path(); |
4764 | - path target_entry = target; |
4765 | - target_entry /= source_entry.filename(); |
4766 | - copy_recursively(source_entry, target_entry); |
4767 | - } |
4768 | - } |
4769 | - else |
4770 | - { |
4771 | - // Ignore everything that's not a directory or file. |
4772 | - } |
4773 | -} |
4774 | - |
4775 | -} // namespace |
4776 | - |
4777 | QFuture<shared_ptr<Item>> ItemImpl::copy(shared_ptr<Folder> const& new_parent, QString const& new_name) |
4778 | { |
4779 | + if (!new_parent) |
4780 | + { |
4781 | + QString msg = "Item::copy(): new_parent cannot be nullptr"; |
4782 | + return internal::make_exceptional_future<shared_ptr<Item>>(InvalidArgumentException(msg)); |
4783 | + } |
4784 | + auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); |
4785 | + |
4786 | + lock(mutex_, new_parent_impl->mutex_); |
4787 | + lock_guard<decltype(mutex_)> this_guard(mutex_, std::adopt_lock); |
4788 | + lock_guard<decltype(mutex_)> other_guard(new_parent_impl->mutex_, adopt_lock); |
4789 | + |
4790 | + try |
4791 | + { |
4792 | + throw_if_destroyed("Item::copy()"); |
4793 | + new_parent_impl->throw_if_destroyed("Item::copy()"); |
4794 | + } |
4795 | + catch (StorageException const& e) |
4796 | + { |
4797 | + return internal::make_exceptional_future<shared_ptr<Item>>(e); |
4798 | + } |
4799 | + |
4800 | auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive. |
4801 | auto copy = [This, new_parent, new_name]() -> Item::SPtr |
4802 | { |
4803 | auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); |
4804 | |
4805 | lock(This->mutex_, new_parent_impl->mutex_); |
4806 | - lock_guard<mutex> this_guard(This->mutex_, std::adopt_lock); |
4807 | - lock_guard<mutex> other_guard(new_parent_impl->mutex_, adopt_lock); |
4808 | - |
4809 | - if (This->deleted_ || new_parent_impl->deleted_) |
4810 | - { |
4811 | - throw This->deleted_ex("Item::copy"); |
4812 | - } |
4813 | - |
4814 | - if (This->root()->account() != new_parent->root()->account()) |
4815 | + lock_guard<decltype(mutex_)> this_guard(This->mutex_, std::adopt_lock); |
4816 | + lock_guard<decltype(mutex_)> other_guard(new_parent_impl->mutex_, adopt_lock); |
4817 | + |
4818 | + This->throw_if_destroyed("Item::copy()"); |
4819 | + new_parent_impl->throw_if_destroyed("Item::copy()"); |
4820 | + |
4821 | + // TODO: This needs to deeply compare account identity because the client may have refreshed the accounts list. |
4822 | + if (This->root()->account() != new_parent->root()->account()) // Throws if account or runtime were destroyed. |
4823 | { |
4824 | // Can't do cross-account copy. |
4825 | - QString msg = QString("Item::copy(): Source (") + This->name_ + ") and target (" |
4826 | + QString msg = QString("Item::copy(): source (") + This->name_ + ") and target (" |
4827 | + new_name + ") must belong to the same account"; |
4828 | throw LogicException(msg); |
4829 | } |
4830 | @@ -175,22 +144,22 @@ |
4831 | target_path /= sanitized_name; |
4832 | if (is_reserved_path(target_path)) |
4833 | { |
4834 | - QString msg = "Item::copy(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved"; |
4835 | + QString msg = "Item::copy(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved"; |
4836 | throw InvalidArgumentException(msg); |
4837 | } |
4838 | |
4839 | + if (exists(target_path)) |
4840 | + { |
4841 | + QString msg = "Item::copy(): item with name \"" + new_name + "\" exists already"; |
4842 | + throw ExistsException(msg, This->identity_, This->name_); |
4843 | + } |
4844 | + |
4845 | if (This->type_ == ItemType::file) |
4846 | { |
4847 | copy_file(source_path, target_path); |
4848 | return FileImpl::make_file(QString::fromStdString(target_path.native()), new_parent_impl->root_); |
4849 | } |
4850 | |
4851 | - if (exists(target_path)) |
4852 | - { |
4853 | - QString msg = "Item::copy(): item with name \"" + new_name + "\" exists already"; |
4854 | - throw ExistsException(msg, This->identity_, This->name_); |
4855 | - } |
4856 | - |
4857 | // For recursive copy, we create a temporary directory in lieu of target_path and recursively copy |
4858 | // everything into the temporary directory. This ensures that we don't invalidate directory iterators |
4859 | // by creating things while we are iterating, potentially getting trapped in an infinite loop. |
4860 | @@ -199,7 +168,7 @@ |
4861 | create_directories(tmp_path); |
4862 | for (directory_iterator it(source_path); it != directory_iterator(); ++it) |
4863 | { |
4864 | - if (tmp_path.compare(canonical(it->path())) == 0) |
4865 | + if (is_reserved_path(it->path())) |
4866 | { |
4867 | continue; // Don't recurse into the temporary directory |
4868 | } |
4869 | @@ -209,15 +178,15 @@ |
4870 | path source_entry = it->path(); |
4871 | path target_entry = tmp_path; |
4872 | target_entry /= source_entry.filename(); |
4873 | - copy_recursively(source_entry, target_entry); |
4874 | + ItemImpl::copy_recursively(source_entry, target_entry); |
4875 | } |
4876 | } |
4877 | rename(tmp_path, target_path); |
4878 | return FolderImpl::make_folder(QString::fromStdString(target_path.native()), new_parent_impl->root_); |
4879 | } |
4880 | - catch (std::exception const& e) |
4881 | + catch (std::exception const&) |
4882 | { |
4883 | - throw ResourceException(QString("Item::copy(): ") + e.what()); |
4884 | + throw_storage_exception("Item::copy()", current_exception()); |
4885 | } |
4886 | }; |
4887 | return QtConcurrent::run(copy); |
4888 | @@ -225,31 +194,51 @@ |
4889 | |
4890 | QFuture<shared_ptr<Item>> ItemImpl::move(shared_ptr<Folder> const& new_parent, QString const& new_name) |
4891 | { |
4892 | + if (!new_parent) |
4893 | + { |
4894 | + QString msg = "Item::move(): new_parent cannot be nullptr"; |
4895 | + return internal::make_exceptional_future<shared_ptr<Item>>(InvalidArgumentException(msg)); |
4896 | + } |
4897 | + auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); |
4898 | + |
4899 | + lock(mutex_, new_parent_impl->mutex_); |
4900 | + lock_guard<decltype(mutex_)> this_guard(mutex_, std::adopt_lock); |
4901 | + lock_guard<decltype(mutex_)> other_guard(new_parent_impl->mutex_, adopt_lock); |
4902 | + |
4903 | + try |
4904 | + { |
4905 | + throw_if_destroyed("Item::move()"); |
4906 | + new_parent_impl->throw_if_destroyed("Item::move()"); |
4907 | + } |
4908 | + catch (StorageException const& e) |
4909 | + { |
4910 | + return internal::make_exceptional_future<shared_ptr<Item>>(e); |
4911 | + } |
4912 | + |
4913 | auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive. |
4914 | auto move = [This, new_parent, new_name]() -> Item::SPtr |
4915 | { |
4916 | auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); |
4917 | |
4918 | lock(This->mutex_, new_parent_impl->mutex_); |
4919 | - lock_guard<mutex> this_guard(This->mutex_, std::adopt_lock); |
4920 | - lock_guard<mutex> other_guard(new_parent_impl->mutex_, adopt_lock); |
4921 | - |
4922 | - if (This->deleted_ || new_parent_impl->deleted_) |
4923 | - { |
4924 | - throw This->deleted_ex("Item::move"); |
4925 | - } |
4926 | - |
4927 | - if (This->root()->account() != new_parent->root()->account()) |
4928 | + lock_guard<decltype(mutex_)> this_guard(This->mutex_, std::adopt_lock); |
4929 | + lock_guard<decltype(mutex_)> other_guard(new_parent_impl->mutex_, adopt_lock); |
4930 | + |
4931 | + This->throw_if_destroyed("Item::move()"); |
4932 | + new_parent_impl->throw_if_destroyed("Item::move()"); |
4933 | + |
4934 | + // TODO: This needs to deeply compare account identity because the client may have refreshed the accounts list. |
4935 | + if (This->root()->account() != new_parent->root()->account()) // Throws if account or runtime were destroyed. |
4936 | { |
4937 | // Can't do cross-account move. |
4938 | - QString msg = QString("Item::move(): Source (") + This->name_ + ") and target (" |
4939 | + QString msg = QString("Item::move(): source (") + This->name_ + ") and target (" |
4940 | + new_name + ") must belong to the same account"; |
4941 | throw LogicException(msg); |
4942 | } |
4943 | if (This->type_ == ItemType::root) |
4944 | { |
4945 | // Can't move a root. |
4946 | - throw LogicException("Item::move(): Cannot move root folder"); |
4947 | + throw LogicException("Item::move(): cannot move root folder"); |
4948 | } |
4949 | |
4950 | try |
4951 | @@ -265,7 +254,7 @@ |
4952 | } |
4953 | if (is_reserved_path(target_path)) |
4954 | { |
4955 | - QString msg = "Item::move(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved"; |
4956 | + QString msg = "Item::move(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved"; |
4957 | throw InvalidArgumentException(msg); |
4958 | } |
4959 | rename(This->native_identity().toStdString(), target_path); |
4960 | @@ -276,9 +265,9 @@ |
4961 | } |
4962 | return FileImpl::make_file(QString::fromStdString(target_path.native()), new_parent_impl->root_); |
4963 | } |
4964 | - catch (std::exception const& e) |
4965 | + catch (std::exception const&) |
4966 | { |
4967 | - throw ResourceException(QString("Item::move(): ") + e.what()); |
4968 | + throw_storage_exception(QString("Item::move(): "), current_exception()); |
4969 | } |
4970 | }; |
4971 | return QtConcurrent::run(move); |
4972 | @@ -286,18 +275,15 @@ |
4973 | |
4974 | QFuture<QVector<Folder::SPtr>> ItemImpl::parents() const |
4975 | { |
4976 | - lock_guard<mutex> guard(mutex_); |
4977 | + lock_guard<decltype(mutex_)> guard(mutex_); |
4978 | |
4979 | - QFutureInterface<QVector<Folder::SPtr>> qf; |
4980 | - if (deleted_) |
4981 | + try |
4982 | { |
4983 | - return make_exceptional_future<QVector<Folder::SPtr>>(deleted_ex("Item::parents()")); |
4984 | + throw_if_destroyed("Item::parents()"); |
4985 | } |
4986 | - |
4987 | - Root::SPtr root = root_.lock(); |
4988 | - if (!root) |
4989 | + catch (StorageException const& e) |
4990 | { |
4991 | - return make_exceptional_future<QVector<Folder::SPtr>>(RuntimeDestroyedException("Item::parents()")); |
4992 | + return internal::make_exceptional_future<QVector<Folder::SPtr>>(e); |
4993 | } |
4994 | |
4995 | using namespace boost::filesystem; |
4996 | @@ -306,10 +292,11 @@ |
4997 | path p = native_identity().toStdString(); |
4998 | QString parent_path = QString::fromStdString(p.parent_path().native()); |
4999 | |
5000 | + auto root = root_.lock(); |
Looks good, thanks!