Merge lp:~unity-api-team/storage-framework/merge-devel into lp:storage-framework

Proposed by Michi Henning
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
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.

To post a comment you must log in.
Revision history for this message
Michi Henning (michihenning) wrote :

Looks good, thanks!

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2016-07-22 08:38:24 +0000
+++ CMakeLists.txt 2016-09-09 02:13:43 +0000
@@ -17,7 +17,7 @@
17# These two should be incremented when the ABI changes.17# These two should be incremented when the ABI changes.
18set(SF_CLIENT_SOVERSION "0")18set(SF_CLIENT_SOVERSION "0")
19execute_process(19execute_process(
20 COMMAND /bin/sh ${CMAKE_CURRENT_SOURCE_DIR}/get-provider-soversion.sh20 COMMAND /bin/sh ${CMAKE_CURRENT_SOURCE_DIR}/tools/get-provider-soversion.sh
21 OUTPUT_VARIABLE SF_PROVIDER_SOVERSION21 OUTPUT_VARIABLE SF_PROVIDER_SOVERSION
22 OUTPUT_STRIP_TRAILING_WHITESPACE22 OUTPUT_STRIP_TRAILING_WHITESPACE
23 RESULT_VARIABLE result)23 RESULT_VARIABLE result)
@@ -108,7 +108,7 @@
108108
109include(GNUInstallDirs)109include(GNUInstallDirs)
110110
111find_package(Boost COMPONENTS filesystem system thread REQUIRED)111find_package(Boost 1.56 COMPONENTS filesystem system thread REQUIRED)
112find_package(Qt5Concurrent REQUIRED)112find_package(Qt5Concurrent REQUIRED)
113find_package(Qt5Core REQUIRED)113find_package(Qt5Core REQUIRED)
114find_package(Qt5DBus REQUIRED)114find_package(Qt5DBus REQUIRED)
@@ -130,8 +130,11 @@
130enable_coverage_report(130enable_coverage_report(
131 TARGETS131 TARGETS
132 qt-client-lib-common132 qt-client-lib-common
133 storage-framework-common-internal
133 storage-framework-qt-client134 storage-framework-qt-client
134 storage-framework-qt-local-client135 storage-framework-qt-local-client
136 sf-provider-objects
137 storage-framework-provider
135 FILTER138 FILTER
136 ${CMAKE_SOURCE_DIR}/tests/*139 ${CMAKE_SOURCE_DIR}/tests/*
137 ${CMAKE_BINARY_DIR}/*140 ${CMAKE_BINARY_DIR}/*
138141
=== modified file 'data/provider.xml'
--- data/provider.xml 2016-07-11 07:17:04 +0000
+++ data/provider.xml 2016-09-09 02:13:43 +0000
@@ -5,14 +5,17 @@
5 com.canonical.StorageFramework.Provider:5 com.canonical.StorageFramework.Provider:
6 @short_description: Interface providing access to a storage account6 @short_description: Interface providing access to a storage account
77
8 For methods dealing with metadata, the representation8 For methods returning metadata, the representation
9 "(ssssia{sv})" is used, where the struct members are:9 "(sasssia{sv})" is used, where the struct members are:
10 - item_id10 - item_id
11 - parent_id11 - parent_ids
12 - name12 - name
13 - etag13 - etag
14 - type (enum: file, folder, root)14 - type (enum: file, folder, root)
15 - metadata15 - metadata
16
17 Note that parent_ids is a sequence of IDs instead of a single ID to allow the client to
18 navigate items in Google Drive, which permits more than one parent for a file or folder.
16 -->19 -->
17 <interface name="com.canonical.StorageFramework.Provider">20 <interface name="com.canonical.StorageFramework.Provider">
18 <!--21 <!--
@@ -25,7 +28,7 @@
25 of files, this list will contain a single item.28 of files, this list will contain a single item.
26 -->29 -->
27 <method name="Roots">30 <method name="Roots">
28 <arg type="a(ssssia{sv})" name="roots" direction="out"/>31 <arg type="a(sasssia{sv})" name="roots" direction="out"/>
29 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;unity::storage::internal::ItemMetadata&gt;"/>32 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;unity::storage::internal::ItemMetadata&gt;"/>
30 </method>33 </method>
3134
@@ -45,7 +48,7 @@
45 <method name="List">48 <method name="List">
46 <arg type="s" name="item_id" direction="in"/>49 <arg type="s" name="item_id" direction="in"/>
47 <arg type="s" name="page_token" direction="in"/>50 <arg type="s" name="page_token" direction="in"/>
48 <arg type="a(ssssia{sv})" name="children" direction="out"/>51 <arg type="a(sasssia{sv})" name="children" direction="out"/>
49 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;unity::storage::internal::ItemMetadata&gt;"/>52 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;unity::storage::internal::ItemMetadata&gt;"/>
50 <arg type="s" name="next_token" direction="out"/>53 <arg type="s" name="next_token" direction="out"/>
51 </method>54 </method>
@@ -60,7 +63,7 @@
60 <method name="Lookup">63 <method name="Lookup">
61 <arg type="s" name="parent_id" direction="in"/>64 <arg type="s" name="parent_id" direction="in"/>
62 <arg type="s" name="name" direction="in"/>65 <arg type="s" name="name" direction="in"/>
63 <arg type="a(ssssia{sv})" name="items" direction="out"/>66 <arg type="a(sasssia{sv})" name="items" direction="out"/>
64 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;unity::storage::internal::ItemMetadata&gt;"/>67 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;unity::storage::internal::ItemMetadata&gt;"/>
65 </method>68 </method>
6669
@@ -72,7 +75,7 @@
72 -->75 -->
73 <method name="Metadata">76 <method name="Metadata">
74 <arg type="s" name="item_id" direction="in"/>77 <arg type="s" name="item_id" direction="in"/>
75 <arg type="(ssssia{sv})" name="metadata" direction="out"/>78 <arg type="(sasssia{sv})" name="metadata" direction="out"/>
76 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="unity::storage::internal::ItemMetadata"/>79 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="unity::storage::internal::ItemMetadata"/>
77 </method>80 </method>
7881
@@ -86,7 +89,7 @@
86 <method name="CreateFolder">89 <method name="CreateFolder">
87 <arg type="s" name="parent_id" direction="in"/>90 <arg type="s" name="parent_id" direction="in"/>
88 <arg type="s" name="name" direction="in"/>91 <arg type="s" name="name" direction="in"/>
89 <arg type="(ssssia{sv})" name="metadata" direction="out"/>92 <arg type="(sasssia{sv})" name="metadata" direction="out"/>
90 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="unity::storage::internal::ItemMetadata"/>93 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="unity::storage::internal::ItemMetadata"/>
91 </method>94 </method>
9295
@@ -160,7 +163,7 @@
160 -->163 -->
161 <method name="FinishUpload">164 <method name="FinishUpload">
162 <arg type="s" name="upload_id" direction="in"/>165 <arg type="s" name="upload_id" direction="in"/>
163 <arg type="(ssssia{sv})" name="metadata" direction="out"/>166 <arg type="(sasssia{sv})" name="metadata" direction="out"/>
164 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="unity::storage::internal::ItemMetadata"/>167 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="unity::storage::internal::ItemMetadata"/>
165 </method>168 </method>
166169
167170
=== modified file 'debian/bileto_pre_release_hook'
--- debian/bileto_pre_release_hook 2016-07-22 04:23:08 +0000
+++ debian/bileto_pre_release_hook 2016-09-09 02:13:43 +0000
@@ -2,7 +2,7 @@
22
3set -eu3set -eu
44
5soversion=$(sh ./get-provider-soversion.sh)5soversion=$(sh ./tools/get-provider-soversion.sh)
66
7infile=./debian/control.in7infile=./debian/control.in
8outfile=./debian/control8outfile=./debian/control
99
=== modified file 'debian/changelog'
--- debian/changelog 2016-08-04 07:20:09 +0000
+++ debian/changelog 2016-09-09 02:13:43 +0000
@@ -1,3 +1,9 @@
1storage-framework (0.1+16.10.20160804.1-0ubuntu2) UNRELEASED; urgency=medium
2
3 * Merged devel at revision 64.
4
5 -- Michi Henning <michi.henning@canonical.com> Fri, 26 Aug 2016 14:03:02 +1000
6
1storage-framework (0.1+16.10.20160804.1-0ubuntu1) yakkety; urgency=medium7storage-framework (0.1+16.10.20160804.1-0ubuntu1) yakkety; urgency=medium
28
3 [ Michi Henning ]9 [ Michi Henning ]
410
=== modified file 'demo/provider_test/CMakeLists.txt'
--- demo/provider_test/CMakeLists.txt 2016-05-23 02:27:16 +0000
+++ demo/provider_test/CMakeLists.txt 2016-09-09 02:13:43 +0000
@@ -1,4 +1,3 @@
1
2add_definitions(-DBOOST_THREAD_VERSION=4)1add_definitions(-DBOOST_THREAD_VERSION=4)
32
4add_executable(provider-test provider-test.cpp)3add_executable(provider-test provider-test.cpp)
54
=== modified file 'demo/provider_test/provider-test.cpp'
--- demo/provider_test/provider-test.cpp 2016-07-26 03:30:05 +0000
+++ demo/provider_test/provider-test.cpp 2016-09-09 02:13:43 +0000
@@ -17,6 +17,8 @@
17 */17 */
1818
19#include <unity/storage/provider/DownloadJob.h>19#include <unity/storage/provider/DownloadJob.h>
20#include <unity/storage/provider/Exceptions.h>
21#include <unity/storage/provider/metadata_keys.h>
20#include <unity/storage/provider/ProviderBase.h>22#include <unity/storage/provider/ProviderBase.h>
21#include <unity/storage/provider/Server.h>23#include <unity/storage/provider/Server.h>
22#include <unity/storage/provider/TempfileUploadJob.h>24#include <unity/storage/provider/TempfileUploadJob.h>
@@ -32,47 +34,8 @@
32using namespace unity::storage::provider;34using namespace unity::storage::provider;
33using namespace std;35using namespace std;
3436
35#if BOOST_VERSION >= 105600
36using boost::make_ready_future;37using boost::make_ready_future;
37using boost::make_exceptional_future;38using boost::make_exceptional_future;
38#else
39namespace
40{
41
42boost::future<void> make_ready_future()
43{
44 boost::promise<void> p;
45 p.set_value();
46 return p.get_future();
47}
48
49template <typename T>
50boost::future<T> make_ready_future(T& value)
51{
52 boost::promise<T> p;
53 p.set_value(value);
54 return p.get_future();
55}
56
57template <typename T>
58boost::future<T> make_ready_future(T&& value)
59{
60 boost::promise<T> p;
61 p.set_value(std::move(value));
62 return p.get_future();
63}
64
65template <typename T, typename E>
66boost::future<T> make_exceptional_future(E const& ex)
67{
68 boost::promise<T> p;
69 p.set_exception(boost::copy_exception(ex));
70 return p.get_future();
71}
72
73}
74#endif
75
7639
77class MyProvider : public ProviderBase40class MyProvider : public ProviderBase
78{41{
@@ -140,7 +103,7 @@
140 printf("roots() called by %s (%d)\n", ctx.security_label.c_str(), ctx.pid);103 printf("roots() called by %s (%d)\n", ctx.security_label.c_str(), ctx.pid);
141 fflush(stdout);104 fflush(stdout);
142 ItemList roots = {105 ItemList roots = {
143 {"root_id", "", "Root", "etag", ItemType::root, {}},106 {"root_id", {}, "Root", "etag", ItemType::root, {}},
144 };107 };
145 return make_ready_future<ItemList>(roots);108 return make_ready_future<ItemList>(roots);
146}109}
@@ -153,14 +116,20 @@
153 fflush(stdout);116 fflush(stdout);
154 if (item_id != "root_id")117 if (item_id != "root_id")
155 {118 {
156 return make_exceptional_future<tuple<ItemList,string>>(runtime_error("unknown folder"));119 string msg = string("Item::list(): no such item: \"") + item_id + "\"";
120 return make_exceptional_future<tuple<ItemList,string>>(NotExistsException(msg, item_id));
157 }121 }
158 if (page_token != "")122 if (page_token != "")
159 {123 {
160 return make_exceptional_future<tuple<ItemList,string>>(runtime_error("unknown page token"));124 string msg = string("Item::list(): invalid page token: \"") + page_token + "\"";
125 return make_exceptional_future<tuple<ItemList,string>>(LogicException(msg));
161 }126 }
162 ItemList children = {127 ItemList children =
163 {"child_id", "root_id", "Child", "etag", ItemType::file, {}}128 {
129 {
130 "child_id", { "root_id" }, "Child", "etag", ItemType::file,
131 { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } }
132 }
164 };133 };
165 boost::promise<tuple<ItemList,string>> p;134 boost::promise<tuple<ItemList,string>> p;
166 p.set_value(make_tuple(children, string()));135 p.set_value(make_tuple(children, string()));
@@ -172,12 +141,20 @@
172{141{
173 printf("lookup('%s', '%s') called by %s (%d)\n", parent_id.c_str(), name.c_str(), ctx.security_label.c_str(), ctx.pid);142 printf("lookup('%s', '%s') called by %s (%d)\n", parent_id.c_str(), name.c_str(), ctx.security_label.c_str(), ctx.pid);
174 fflush(stdout);143 fflush(stdout);
175 if (parent_id != "root_id" || name != "Child")144 if (parent_id != "root_id")
176 {145 {
177 return make_exceptional_future<ItemList>(runtime_error("file not found"));146 string msg = string("Folder::lookup(): no such item: \"") + parent_id + "\"";
178 }147 return make_exceptional_future<ItemList>(NotExistsException(msg, parent_id));
179 ItemList children = {148 }
180 {"child_id", "root_id", "Child", "etag", ItemType::file, {}}149 if (name != "Child")
150 {
151 string msg = string("Folder::lookup(): no such item: \"") + name + "\"";
152 return make_exceptional_future<ItemList>(NotExistsException(msg, name));
153 }
154 ItemList children =
155 {
156 { "child_id", { "root_id" }, "Child", "etag", ItemType::file,
157 { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } }
181 };158 };
182 return make_ready_future<ItemList>(children);159 return make_ready_future<ItemList>(children);
183}160}
@@ -189,15 +166,24 @@
189 fflush(stdout);166 fflush(stdout);
190 if (item_id == "root_id")167 if (item_id == "root_id")
191 {168 {
192 Item metadata{"root_id", "", "Root", "etag", ItemType::root, {}};169 Item metadata{"root_id", {}, "Root", "etag", ItemType::root, {}};
193 return make_ready_future<Item>(metadata);170 return make_ready_future<Item>(metadata);
194 }171 }
195 else if (item_id == "child_id")172 else if (item_id == "child_id")
196 {173 {
197 Item metadata{"child_id", "root_id", "Child", "etag", ItemType::file, {}};174 Item metadata
198 return make_ready_future<Item>(metadata);175 {
199 }176 "child_id", { "root_id" }, "Child", "etag", ItemType::file,
200 return make_exceptional_future<Item>(runtime_error("no such file"));177 { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } }
178 };
179 return make_ready_future<Item>(metadata);
180 }
181 else if (item_id == "child_folder_id")
182 {
183 Item metadata{"child_folder_id", { "root_id" }, "Child_Folder", "etag", ItemType::folder, {}};
184 return make_ready_future<Item>(metadata);
185 }
186 return make_exceptional_future<Item>(NotExistsException("metadata(): no such item: " + item_id, item_id));
201}187}
202188
203boost::future<Item> MyProvider::create_folder(189boost::future<Item> MyProvider::create_folder(
@@ -206,7 +192,7 @@
206{192{
207 printf("create_folder('%s', '%s') called by %s (%d)\n", parent_id.c_str(), name.c_str(), ctx.security_label.c_str(), ctx.pid);193 printf("create_folder('%s', '%s') called by %s (%d)\n", parent_id.c_str(), name.c_str(), ctx.security_label.c_str(), ctx.pid);
208 fflush(stdout);194 fflush(stdout);
209 Item metadata{"new_folder_id", parent_id, name, "etag", ItemType::folder, {}};195 Item metadata{"new_folder_id", { parent_id }, name, "etag", ItemType::folder, {}};
210 return make_ready_future<Item>(metadata);196 return make_ready_future<Item>(metadata);
211}197}
212198
@@ -242,7 +228,12 @@
242228
243 unique_ptr<DownloadJob> job(new MyDownloadJob(make_job_id()));229 unique_ptr<DownloadJob> job(new MyDownloadJob(make_job_id()));
244 const char contents[] = "Hello world";230 const char contents[] = "Hello world";
245 write(job->write_socket(), contents, sizeof(contents));231 if (write(job->write_socket(), contents, sizeof(contents)) != sizeof(contents))
232 {
233 ResourceException e("download(): write failed", errno);
234 job->report_error(make_exception_ptr(e));
235 return make_exceptional_future<unique_ptr<DownloadJob>>(e);
236 }
246 job->report_complete();237 job->report_complete();
247 return make_ready_future(std::move(job));238 return make_ready_future(std::move(job));
248}239}
@@ -261,7 +252,7 @@
261{252{
262 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);253 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);
263 fflush(stdout);254 fflush(stdout);
264 Item metadata{item_id, new_parent_id, new_name, "etag", ItemType::file, {}};255 Item metadata{item_id, { new_parent_id }, new_name, "etag", ItemType::file, {}};
265 return make_ready_future(metadata);256 return make_ready_future(metadata);
266}257}
267258
@@ -271,7 +262,7 @@
271{262{
272 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);263 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);
273 fflush(stdout);264 fflush(stdout);
274 Item metadata{"new_item_id", new_parent_id, new_name, "etag", ItemType::file, {}};265 Item metadata{"new_item_id", { new_parent_id }, new_name, "etag", ItemType::file, {}};
275 return make_ready_future(metadata);266 return make_ready_future(metadata);
276}267}
277268
@@ -294,7 +285,11 @@
294 unlink(new_filename.c_str());285 unlink(new_filename.c_str());
295 link(old_filename.c_str(), new_filename.c_str());286 link(old_filename.c_str(), new_filename.c_str());
296287
297 Item metadata{"some_id", "", "some_upload", "etag", ItemType::file, {}};288 Item metadata
289 {
290 "some_id", { "root_id" }, "some_upload", "etag", ItemType::file,
291 { { SIZE_IN_BYTES, 10 }, { LAST_MODIFIED_TIME, "2011-04-05T14:30:10.005Z" } }
292 };
298 return make_ready_future(metadata);293 return make_ready_future(metadata);
299}294}
300295
301296
=== modified file 'include/unity/storage/internal/ItemMetadata.h'
--- include/unity/storage/internal/ItemMetadata.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/internal/ItemMetadata.h 2016-09-09 02:13:43 +0000
@@ -21,9 +21,12 @@
21#include <unity/storage/common.h>21#include <unity/storage/common.h>
2222
23#pragma GCC diagnostic push23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wcast-align"
24#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"25#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
26#pragma GCC diagnostic ignored "-Wswitch-default"
25#include <QMap>27#include <QMap>
26#include <QVariant>28#include <QVariant>
29#include <QVector>
27#pragma GCC diagnostic pop30#pragma GCC diagnostic pop
2831
29namespace unity32namespace unity
@@ -36,7 +39,7 @@
36struct ItemMetadata39struct ItemMetadata
37{40{
38 QString item_id;41 QString item_id;
39 QString parent_id;42 QVector<QString> parent_ids;
40 QString name;43 QString name;
41 QString etag;44 QString etag;
42 ItemType type;45 ItemType type;
4346
=== added file 'include/unity/storage/internal/TraceMessageHandler.h'
--- include/unity/storage/internal/TraceMessageHandler.h 1970-01-01 00:00:00 +0000
+++ include/unity/storage/internal/TraceMessageHandler.h 2016-09-09 02:13:43 +0000
@@ -0,0 +1,47 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#pragma GCC diagnostic push
22#pragma GCC diagnostic ignored "-Wcast-align"
23#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
24#pragma GCC diagnostic ignored "-Wswitch-default"
25#include <QDebug>
26#pragma GCC diagnostic pop
27
28namespace unity
29{
30namespace storage
31{
32namespace internal
33{
34
35class TraceMessageHandler final
36{
37public:
38 TraceMessageHandler(std::string const& prog_name);
39 ~TraceMessageHandler();
40
41private:
42 QtMessageHandler old_message_handler_;
43};
44
45} // namespace internal
46} // namespace storage
47} // namespace unity
048
=== added file 'include/unity/storage/internal/dbus_error.h'
--- include/unity/storage/internal/dbus_error.h 1970-01-01 00:00:00 +0000
+++ include/unity/storage/internal/dbus_error.h 2016-09-09 02:13:43 +0000
@@ -0,0 +1,32 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21namespace unity
22{
23namespace storage
24{
25namespace internal
26{
27
28constexpr char DBUS_ERROR_PREFIX[] = "com.canonical.StorageFramework.";
29
30} // namespace internal
31} // namespace storage
32} // namespace unity
033
=== added file 'include/unity/storage/internal/dbusmarshal.h'
--- include/unity/storage/internal/dbusmarshal.h 1970-01-01 00:00:00 +0000
+++ include/unity/storage/internal/dbusmarshal.h 2016-09-09 02:13:43 +0000
@@ -0,0 +1,44 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <unity/storage/internal/ItemMetadata.h>
22
23#include <QDBusArgument>
24#include <QMetaType>
25
26namespace unity
27{
28namespace storage
29{
30namespace internal
31{
32
33QDBusArgument& operator<<(QDBusArgument& argument, ItemMetadata const& metadata);
34QDBusArgument const& operator>>(QDBusArgument const& argument, ItemMetadata& metadata);
35
36QDBusArgument& operator<<(QDBusArgument& argument, QList<ItemMetadata> const& md_list);
37QDBusArgument const& operator>>(QDBusArgument const& argument, QList<ItemMetadata>& md_list);
38
39} // namespace internal
40} // storage
41} // unity
42
43Q_DECLARE_METATYPE(unity::storage::internal::ItemMetadata)
44Q_DECLARE_METATYPE(QList<unity::storage::internal::ItemMetadata>)
045
=== modified file 'include/unity/storage/provider/CMakeLists.txt'
--- include/unity/storage/provider/CMakeLists.txt 2016-07-11 03:28:40 +0000
+++ include/unity/storage/provider/CMakeLists.txt 2016-09-09 02:13:43 +0000
@@ -3,3 +3,5 @@
33
4install(FILES ${provider_headers}4install(FILES ${provider_headers}
5 DESTINATION ${provider_base_includedir}/${includeprefix})5 DESTINATION ${provider_base_includedir}/${includeprefix})
6
7add_subdirectory(testing)
68
=== added file 'include/unity/storage/provider/Exceptions.h'
--- include/unity/storage/provider/Exceptions.h 1970-01-01 00:00:00 +0000
+++ include/unity/storage/provider/Exceptions.h 2016-09-09 02:13:43 +0000
@@ -0,0 +1,187 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <unity/storage/visibility.h>
22
23#include <string>
24
25namespace unity
26{
27namespace storage
28{
29namespace provider
30{
31
32// Note: Adding new exception types also requires updating the marshaling and
33// unmarshaling code for exceptions in the client and server APIs.
34
35/**
36\brief Base exception class for all server-side exceptions.
37*/
38class UNITY_STORAGE_EXPORT StorageException : public std::exception
39{
40public:
41 StorageException(std::string const& exception_type, std::string const& error_message);
42 ~StorageException();
43
44 virtual char const* what() const noexcept override;
45
46 std::string type() const;
47 std::string error_message() const;
48
49private:
50 std::string what_string_;
51 std::string type_;
52 std::string error_message_;
53};
54
55/**
56\brief Indicates errors in the communication between the storage provider and the cloud service.
57*/
58class UNITY_STORAGE_EXPORT RemoteCommsException : public StorageException
59{
60public:
61 RemoteCommsException(std::string const& error_message);
62 ~RemoteCommsException();
63};
64
65/**
66\brief Indicates that an item does not exist or could not be found.
67*/
68class UNITY_STORAGE_EXPORT NotExistsException : public StorageException
69{
70public:
71 NotExistsException(std::string const& error_message, std::string const& key);
72 ~NotExistsException();
73
74 std::string key() const;
75
76private:
77 std::string key_;
78};
79
80/**
81\brief Indicates that an item cannot be created because it exists already.
82*/
83class UNITY_STORAGE_EXPORT ExistsException : public StorageException
84{
85public:
86 ExistsException(std::string const& error_message, std::string const& identity, std::string const& name);
87 ~ExistsException();
88
89 std::string native_identity() const;
90 std::string name() const;
91
92private:
93 std::string identity_;
94 std::string name_;
95};
96
97/**
98\brief Indicates that an upload detected a version mismatch.
99*/
100class UNITY_STORAGE_EXPORT ConflictException : public StorageException
101{
102public:
103 ConflictException(std::string const& error_message);
104 ~ConflictException();
105};
106
107/**
108\brief Indicates that an operation failed because of a permission problem.
109*/
110class UNITY_STORAGE_EXPORT PermissionException : public StorageException
111{
112public:
113 PermissionException(std::string const& error_message);
114 ~PermissionException();
115};
116
117/**
118\brief Indicates that an update failed because the provider ran out of space.
119*/
120class UNITY_STORAGE_EXPORT QuotaException : public StorageException
121{
122public:
123 QuotaException(std::string const& error_message);
124 ~QuotaException();
125};
126
127/**
128\brief Indicates that an upload or download was cancelled before it could complete.
129*/
130class UNITY_STORAGE_EXPORT CancelledException : public StorageException
131{
132public:
133 CancelledException(std::string const& error_message);
134 ~CancelledException();
135};
136
137/**
138\brief Indicates incorrect use of the API, such as calling methods in the wrong order.
139*/
140class UNITY_STORAGE_EXPORT LogicException : public StorageException
141{
142public:
143 LogicException(std::string const& error_message);
144 ~LogicException();
145};
146
147/**
148\brief Indicates an invalid parameter, such as a negative value when a positive one was
149expected, or a string that does not parse correctly or is empty when it should be non-empty.
150*/
151class UNITY_STORAGE_EXPORT InvalidArgumentException : public StorageException
152{
153public:
154 InvalidArgumentException(std::string const& error_message);
155 ~InvalidArgumentException();
156};
157
158/**
159\brief Indicates a system error, such as failure to create a file or folder,
160or any other (usually non-recoverable) kind of error that should not arise during normal operation.
161*/
162class UNITY_STORAGE_EXPORT ResourceException : public StorageException
163{
164public:
165 ResourceException(std::string const& error_message, int error_code);
166 ~ResourceException();
167
168 int error_code() const noexcept;
169
170private:
171 int error_code_;
172};
173
174/**
175\brief Indicates that the server side caught an exception that does not derive from
176StorageException, such as a std::exception, or caught some other unknown type (such as `int`).
177*/
178class UNITY_STORAGE_EXPORT UnknownException : public StorageException
179{
180public:
181 UnknownException(std::string const& error_message);
182 ~UnknownException();
183};
184
185} // namespace provider
186} // namespace storage
187} // namespace unity
0188
=== modified file 'include/unity/storage/provider/ProviderBase.h'
--- include/unity/storage/provider/ProviderBase.h 2016-07-14 00:17:14 +0000
+++ include/unity/storage/provider/ProviderBase.h 2016-09-09 02:13:43 +0000
@@ -23,6 +23,7 @@
23#include <unity/storage/provider/Credentials.h>23#include <unity/storage/provider/Credentials.h>
2424
25#include <boost/thread/future.hpp>25#include <boost/thread/future.hpp>
26#include <boost/variant.hpp>
2627
27#include <sys/types.h>28#include <sys/types.h>
28#include <string>29#include <string>
@@ -48,15 +49,18 @@
48 Credentials credentials;49 Credentials credentials;
49};50};
5051
52// Note: When growing the set of supported variant types, add new types
53// to the *end* of the list, and update the marshaling code in dbusmarshal.cpp.
54typedef boost::variant<std::string, int64_t> MetadataValue;
55
51struct UNITY_STORAGE_EXPORT Item56struct UNITY_STORAGE_EXPORT Item
52{57{
53 std::string item_id;58 std::string item_id;
54 std::string parent_id;59 std::vector<std::string> parent_ids;
55 std::string name;60 std::string name;
56 std::string etag;61 std::string etag;
57 unity::storage::ItemType type;62 unity::storage::ItemType type;
58 // Should be map<string,variant>63 std::map<std::string, MetadataValue> metadata;
59 std::map<std::string,std::string> metadata;
60};64};
6165
62typedef std::vector<Item> ItemList;66typedef std::vector<Item> ItemList;
6367
=== modified file 'include/unity/storage/provider/TempfileUploadJob.h'
--- include/unity/storage/provider/TempfileUploadJob.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/provider/TempfileUploadJob.h 2016-09-09 02:13:43 +0000
@@ -44,6 +44,12 @@
4444
45 std::string file_name() const;45 std::string file_name() const;
4646
47 // This function should be called from your finish()
48 // implementation to read the remaining data from the socket. If
49 // the client has not closed the socket as expected, LogicError
50 // will be thrown.
51 void drain();
52
47protected:53protected:
48 TempfileUploadJob(internal::TempfileUploadJobImpl *p) UNITY_STORAGE_HIDDEN;54 TempfileUploadJob(internal::TempfileUploadJobImpl *p) UNITY_STORAGE_HIDDEN;
49};55};
5056
=== modified file 'include/unity/storage/provider/internal/AccountData.h'
--- include/unity/storage/provider/internal/AccountData.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/provider/internal/AccountData.h 2016-09-09 02:13:43 +0000
@@ -20,10 +20,15 @@
2020
21#include <unity/storage/provider/Credentials.h>21#include <unity/storage/provider/Credentials.h>
2222
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wcast-align"
25#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
26#pragma GCC diagnostic ignored "-Wswitch-default"
23#include <OnlineAccounts/Account>27#include <OnlineAccounts/Account>
24#include <OnlineAccounts/PendingCallWatcher>28#include <OnlineAccounts/PendingCallWatcher>
25#include <QObject>29#include <QObject>
26#include <QDBusConnection>30#include <QDBusConnection>
31#pragma GCC diagnostic pop
2732
28#include <string>33#include <string>
2934
3035
=== modified file 'include/unity/storage/provider/internal/DBusPeerCache.h'
--- include/unity/storage/provider/internal/DBusPeerCache.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/provider/internal/DBusPeerCache.h 2016-09-09 02:13:43 +0000
@@ -20,8 +20,13 @@
20#pragma once20#pragma once
2121
22#include <boost/thread/future.hpp>22#include <boost/thread/future.hpp>
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wcast-align"
25#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
26#pragma GCC diagnostic ignored "-Wswitch-default"
23#include <QDBusConnection>27#include <QDBusConnection>
24#include <QDBusPendingReply>28#include <QDBusPendingReply>
29#pragma GCC diagnostic pop
25#include <QString>30#include <QString>
2631
27#include <functional>32#include <functional>
2833
=== modified file 'include/unity/storage/provider/internal/DownloadJobImpl.h'
--- include/unity/storage/provider/internal/DownloadJobImpl.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/provider/internal/DownloadJobImpl.h 2016-09-09 02:13:43 +0000
@@ -48,9 +48,6 @@
48 int write_socket() const;48 int write_socket() const;
49 int take_read_socket();49 int take_read_socket();
5050
51 std::string const& sender_bus_name() const;
52 void set_sender_bus_name(std::string const& bus_name);
53
54 void report_complete();51 void report_complete();
55 void report_error(std::exception_ptr p);52 void report_error(std::exception_ptr p);
56 boost::future<void> finish(DownloadJob& job);53 boost::future<void> finish(DownloadJob& job);
@@ -63,7 +60,6 @@
63 std::string const download_id_;60 std::string const download_id_;
64 int read_socket_ = -1;61 int read_socket_ = -1;
65 int write_socket_ = -1;62 int write_socket_ = -1;
66 std::string sender_bus_name_;
6763
68 std::mutex completion_lock_;64 std::mutex completion_lock_;
69 bool completed_ = false;65 bool completed_ = false;
7066
=== modified file 'include/unity/storage/provider/internal/Handler.h'
--- include/unity/storage/provider/internal/Handler.h 2016-07-19 07:08:50 +0000
+++ include/unity/storage/provider/internal/Handler.h 2016-09-09 02:13:43 +0000
@@ -63,6 +63,8 @@
63 void finished();63 void finished();
6464
65private:65private:
66 void marshal_exception(std::exception_ptr ep);
67
66 std::shared_ptr<AccountData> const account_;68 std::shared_ptr<AccountData> const account_;
67 Callback const callback_;69 Callback const callback_;
68 QDBusConnection const bus_;70 QDBusConnection const bus_;
6971
=== modified file 'include/unity/storage/provider/internal/MainLoopExecutor.h'
--- include/unity/storage/provider/internal/MainLoopExecutor.h 2016-07-19 03:26:36 +0000
+++ include/unity/storage/provider/internal/MainLoopExecutor.h 2016-09-09 02:13:43 +0000
@@ -19,13 +19,7 @@
19#pragma once19#pragma once
2020
21#include <boost/version.hpp>21#include <boost/version.hpp>
2222#include <boost/thread/executor.hpp>
23#if BOOST_VERSION >= 105600
24# define SF_SUPPORTS_EXECUTORS
25#endif
26#ifdef SF_SUPPORTS_EXECUTORS
27# include <boost/thread/executor.hpp>
28#endif
29#include <QObject>23#include <QObject>
3024
31#include <functional>25#include <functional>
@@ -39,8 +33,6 @@
39namespace internal33namespace internal
40{34{
4135
42#ifdef SF_SUPPORTS_EXECUTORS
43
44/* Declare future continuations like so to execute within the event36/* Declare future continuations like so to execute within the event
45 * loop if possible:37 * loop if possible:
46 *38 *
@@ -72,12 +64,6 @@
72 Q_DISABLE_COPY(MainLoopExecutor)64 Q_DISABLE_COPY(MainLoopExecutor)
73};65};
7466
75#else
76
77#define EXEC_IN_MAIN /*nothing*/
78
79#endif
80
81}67}
82}68}
83}69}
8470
=== modified file 'include/unity/storage/provider/internal/PendingJobs.h'
--- include/unity/storage/provider/internal/PendingJobs.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/provider/internal/PendingJobs.h 2016-09-09 02:13:43 +0000
@@ -18,14 +18,21 @@
1818
19#pragma once19#pragma once
2020
21#pragma GCC diagnostic push
22#pragma GCC diagnostic ignored "-Wcast-align"
23#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
24#pragma GCC diagnostic ignored "-Wswitch-default"
21#include <QDBusConnection>25#include <QDBusConnection>
22#include <QDBusServiceWatcher>26#include <QDBusServiceWatcher>
23#include <QObject>27#include <QObject>
28#include <QString>
29#pragma GCC diagnostic pop
2430
25#include <map>31#include <map>
26#include <memory>32#include <memory>
27#include <mutex>33#include <mutex>
28#include <string>34#include <string>
35#include <utility>
2936
30namespace unity37namespace unity
31{38{
@@ -49,27 +56,30 @@
49 explicit PendingJobs(QDBusConnection const& bus, QObject *parent=nullptr);56 explicit PendingJobs(QDBusConnection const& bus, QObject *parent=nullptr);
50 virtual ~PendingJobs();57 virtual ~PendingJobs();
5158
52 void add_download(std::unique_ptr<DownloadJob> &&job);59 void add_download(QString const& client_bus_name, std::unique_ptr<DownloadJob> &&job);
53 std::shared_ptr<DownloadJob> get_download(std::string const& download_id);60 std::shared_ptr<DownloadJob> remove_download(QString const& client_bus_name, std::string const& download_id);
54 std::shared_ptr<DownloadJob> remove_download(std::string const& download_id);
5561
56 void add_upload(std::unique_ptr<UploadJob> &&job);62 void add_upload(QString const& client_bus_name, std::unique_ptr<UploadJob> &&job);
57 std::shared_ptr<UploadJob> get_upload(std::string const& upload_id);63 std::shared_ptr<UploadJob> remove_upload(QString const& client_bus_name, std::string const& upload_id);
58 std::shared_ptr<UploadJob> remove_upload(std::string const& upload_id);
5964
60private Q_SLOTS:65private Q_SLOTS:
61 void service_disconnected(QString const& service_name);66 void service_disconnected(QString const& service_name);
6267
63private:68private:
64 void watch_peer(std::string const& bus_name);69 void watch_peer(QString const& bus_name);
65 void unwatch_peer(std::string const& bus_name);70 void unwatch_peer(QString const& bus_name);
71
72 template <typename Job>
73 void cancel_job(std::shared_ptr<Job> const& job,
74 std::string const& identifier);
6675
67 std::mutex lock_;76 std::mutex lock_;
68 std::map<std::string,std::shared_ptr<UploadJob>> uploads_;77 // Key is client_bus_name and upload or download ID.
69 std::map<std::string,std::shared_ptr<DownloadJob>> downloads_;78 std::map<std::pair<QString,std::string>,std::shared_ptr<UploadJob>> uploads_;
79 std::map<std::pair<QString,std::string>,std::shared_ptr<DownloadJob>> downloads_;
7080
71 QDBusServiceWatcher watcher_;81 QDBusServiceWatcher watcher_;
72 std::map<std::string,int> services_;82 std::map<QString,int> services_;
7383
74 Q_DISABLE_COPY(PendingJobs)84 Q_DISABLE_COPY(PendingJobs)
75};85};
7686
=== modified file 'include/unity/storage/provider/internal/ProviderInterface.h'
--- include/unity/storage/provider/internal/ProviderInterface.h 2016-07-14 00:17:14 +0000
+++ include/unity/storage/provider/internal/ProviderInterface.h 2016-09-09 02:13:43 +0000
@@ -21,11 +21,16 @@
21#include <unity/storage/internal/ItemMetadata.h>21#include <unity/storage/internal/ItemMetadata.h>
22#include <unity/storage/provider/internal/Handler.h>22#include <unity/storage/provider/internal/Handler.h>
2323
24#pragma GCC diagnostic push
25#pragma GCC diagnostic ignored "-Wcast-align"
26#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
27#pragma GCC diagnostic ignored "-Wswitch-default"
24#include <QObject>28#include <QObject>
25#include <QList>29#include <QList>
26#include <QDBusConnection>30#include <QDBusConnection>
27#include <QDBusContext>31#include <QDBusContext>
28#include <QDBusUnixFileDescriptor>32#include <QDBusUnixFileDescriptor>
33#pragma GCC diagnostic pop
2934
30#include <map>35#include <map>
31#include <memory>36#include <memory>
3237
=== modified file 'include/unity/storage/provider/internal/ServerImpl.h'
--- include/unity/storage/provider/internal/ServerImpl.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/provider/internal/ServerImpl.h 2016-09-09 02:13:43 +0000
@@ -19,6 +19,7 @@
19#pragma once19#pragma once
2020
21#include <unity/storage/provider/Server.h>21#include <unity/storage/provider/Server.h>
22#include <unity/storage/internal/TraceMessageHandler.h>
22#include <unity/storage/provider/internal/DBusPeerCache.h>23#include <unity/storage/provider/internal/DBusPeerCache.h>
23#include <unity/storage/provider/internal/ProviderInterface.h>24#include <unity/storage/provider/internal/ProviderInterface.h>
2425
@@ -58,6 +59,7 @@
58 ServerBase* const server_;59 ServerBase* const server_;
59 std::string const bus_name_;60 std::string const bus_name_;
60 std::string const service_id_;61 std::string const service_id_;
62 unity::storage::internal::TraceMessageHandler trace_message_handler_;
6163
62 std::unique_ptr<QCoreApplication> app_;64 std::unique_ptr<QCoreApplication> app_;
63 std::unique_ptr<OnlineAccounts::Manager> manager_;65 std::unique_ptr<OnlineAccounts::Manager> manager_;
6466
=== modified file 'include/unity/storage/provider/internal/TempfileUploadJobImpl.h'
--- include/unity/storage/provider/internal/TempfileUploadJobImpl.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/provider/internal/TempfileUploadJobImpl.h 2016-09-09 02:13:43 +0000
@@ -20,8 +20,12 @@
2020
21#include <unity/storage/provider/internal/UploadJobImpl.h>21#include <unity/storage/provider/internal/UploadJobImpl.h>
2222
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wcast-align"
25#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
23#include <QLocalSocket>26#include <QLocalSocket>
24#include <QTemporaryFile>27#include <QTemporaryFile>
28#pragma GCC diagnostic pop
2529
26#include <memory>30#include <memory>
27#include <string>31#include <string>
@@ -43,6 +47,7 @@
43 virtual ~TempfileUploadJobImpl();47 virtual ~TempfileUploadJobImpl();
4448
45 void complete_init() override;49 void complete_init() override;
50 void drain();
4651
47 std::string file_name() const;52 std::string file_name() const;
4853
@@ -51,8 +56,8 @@
51 void on_read_channel_finished();56 void on_read_channel_finished();
5257
53private:58private:
59 std::unique_ptr<QTemporaryFile> tmpfile_;
54 std::unique_ptr<QLocalSocket> reader_;60 std::unique_ptr<QLocalSocket> reader_;
55 std::unique_ptr<QTemporaryFile> tmpfile_;
5661
57 Q_DISABLE_COPY(TempfileUploadJobImpl)62 Q_DISABLE_COPY(TempfileUploadJobImpl)
58};63};
5964
=== added file 'include/unity/storage/provider/internal/TestServerImpl.h'
--- include/unity/storage/provider/internal/TestServerImpl.h 1970-01-01 00:00:00 +0000
+++ include/unity/storage/provider/internal/TestServerImpl.h 2016-09-09 02:13:43 +0000
@@ -0,0 +1,65 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: James Henstridge <james.henstridge@canonical.com>
17 */
18
19#pragma once
20
21#include <unity/storage/provider/testing/TestServer.h>
22
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wcast-align"
25#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
26#include <QDBusConnection>
27#pragma GCC diagnostic pop
28
29#include <memory>
30#include <string>
31
32namespace unity
33{
34namespace storage
35{
36namespace provider
37{
38namespace internal
39{
40
41class ProviderInterface;
42
43class TestServerImpl
44{
45public:
46 TestServerImpl(std::unique_ptr<ProviderBase>&& provider,
47 OnlineAccounts::Account* account,
48 QDBusConnection const& connection,
49 std::string const& object_path);
50 ~TestServerImpl();
51
52 QDBusConnection const& connection() const;
53 std::string const& object_path() const;
54
55private:
56 QDBusConnection connection_;
57 std::string const object_path_;
58
59 std::unique_ptr<ProviderInterface> interface_;
60};
61
62}
63}
64}
65}
066
=== modified file 'include/unity/storage/provider/internal/UploadJobImpl.h'
--- include/unity/storage/provider/internal/UploadJobImpl.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/provider/internal/UploadJobImpl.h 2016-09-09 02:13:43 +0000
@@ -21,7 +21,11 @@
21#include <unity/storage/provider/ProviderBase.h>21#include <unity/storage/provider/ProviderBase.h>
2222
23#include <boost/thread/future.hpp>23#include <boost/thread/future.hpp>
24#pragma GCC diagnostic push
25#pragma GCC diagnostic ignored "-Wcast-align"
26#pragma GCC diagnostic ignored "-Wswitch-default"
24#include <QObject>27#include <QObject>
28#pragma GCC diagnostic pop
2529
26#include <exception>30#include <exception>
27#include <mutex>31#include <mutex>
@@ -49,9 +53,6 @@
49 int read_socket() const;53 int read_socket() const;
50 int take_write_socket();54 int take_write_socket();
5155
52 std::string const& sender_bus_name() const;
53 void set_sender_bus_name(std::string const& bus_name);
54
55 void report_error(std::exception_ptr p);56 void report_error(std::exception_ptr p);
56 boost::future<Item> finish(UploadJob& job);57 boost::future<Item> finish(UploadJob& job);
57 boost::future<void> cancel(UploadJob& job);58 boost::future<void> cancel(UploadJob& job);
@@ -63,7 +64,6 @@
63 std::string const upload_id_;64 std::string const upload_id_;
64 int read_socket_ = -1;65 int read_socket_ = -1;
65 int write_socket_ = -1;66 int write_socket_ = -1;
66 std::string sender_bus_name_;
6767
68 std::mutex completion_lock_;68 std::mutex completion_lock_;
69 bool completed_ = false;69 bool completed_ = false;
7070
=== modified file 'include/unity/storage/provider/internal/dbusmarshal.h'
--- include/unity/storage/provider/internal/dbusmarshal.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/provider/internal/dbusmarshal.h 2016-09-09 02:13:43 +0000
@@ -18,8 +18,15 @@
1818
19#pragma once19#pragma once
2020
21#include <unity/storage/provider/ProviderBase.h>
22
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wcast-align"
25#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
21#include <QDBusArgument>26#include <QDBusArgument>
22#include <QVariant>27#include <QVariant>
28#pragma GCC diagnostic pop
29
23#include <vector>30#include <vector>
2431
25namespace unity32namespace unity
2633
=== renamed file 'include/unity/storage/internal/MetadataKeys.h' => 'include/unity/storage/provider/metadata_keys.h'
--- include/unity/storage/internal/MetadataKeys.h 2016-07-14 00:25:40 +0000
+++ include/unity/storage/provider/metadata_keys.h 2016-09-09 02:13:43 +0000
@@ -18,15 +18,28 @@
1818
19#pragma once19#pragma once
2020
21#include <unordered_map>
22
21namespace unity23namespace unity
22{24{
23namespace storage25namespace storage
24{26{
25namespace internal27namespace provider
26{28{
2729
28static char constexpr CREATION_TIME[] = "creation_time";30static char constexpr SIZE_IN_BYTES[] = "size_in_bytes"; // int64_t, >= 0
2931static char constexpr CREATION_TIME[] = "creation_time"; // String, ISO 8601 format
30} // namespace internal32static char constexpr LAST_MODIFIED_TIME[] = "last_modified_time"; // String, ISO 8601 format
33
34enum class MetadataType { int64, iso_8601_date_time };
35
36static std::unordered_map<std::string, MetadataType> known_metadata =
37{
38 { SIZE_IN_BYTES, MetadataType::int64 },
39 { CREATION_TIME, MetadataType::iso_8601_date_time },
40 { LAST_MODIFIED_TIME, MetadataType::iso_8601_date_time }
41};
42
43} // namespace provider
31} // namespace storage44} // namespace storage
32} // namespace unity45} // namespace unity
3346
=== added directory 'include/unity/storage/provider/testing'
=== added file 'include/unity/storage/provider/testing/CMakeLists.txt'
--- include/unity/storage/provider/testing/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ include/unity/storage/provider/testing/CMakeLists.txt 2016-09-09 02:13:43 +0000
@@ -0,0 +1,5 @@
1set(includeprefix unity/storage/provider/testing)
2file(GLOB provider_headers *.h)
3
4install(FILES ${provider_headers}
5 DESTINATION ${provider_base_includedir}/${includeprefix})
06
=== added file 'include/unity/storage/provider/testing/TestServer.h'
--- include/unity/storage/provider/testing/TestServer.h 1970-01-01 00:00:00 +0000
+++ include/unity/storage/provider/testing/TestServer.h 2016-09-09 02:13:43 +0000
@@ -0,0 +1,68 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: James Henstridge <james.henstridge@canonical.com>
17 */
18
19#pragma once
20
21#include <unity/storage/visibility.h>
22
23#include <memory>
24#include <string>
25
26namespace OnlineAccounts
27{
28class Account;
29}
30class QDBusConnection;
31
32namespace unity
33{
34namespace storage
35{
36namespace provider
37{
38
39class ProviderBase;
40
41namespace internal
42{
43class TestServerImpl;
44}
45
46namespace testing
47{
48
49class UNITY_STORAGE_EXPORT TestServer
50{
51public:
52 TestServer(std::unique_ptr<ProviderBase>&& provider,
53 OnlineAccounts::Account* account,
54 QDBusConnection const& connection,
55 std::string const& object_path);
56 ~TestServer();
57
58 QDBusConnection const& connection() const;
59 std::string const& object_path() const;
60
61private:
62 std::unique_ptr<internal::TestServerImpl> p_;
63};
64
65}
66}
67}
68}
069
=== modified file 'include/unity/storage/qt/client/Account.h'
--- include/unity/storage/qt/client/Account.h 2016-07-22 02:35:12 +0000
+++ include/unity/storage/qt/client/Account.h 2016-09-09 02:13:43 +0000
@@ -77,7 +77,7 @@
7777
78 typedef std::shared_ptr<Account> SPtr;78 typedef std::shared_ptr<Account> SPtr;
7979
80 Runtime* runtime() const;80 std::shared_ptr<Runtime> runtime() const;
8181
82 QString owner() const;82 QString owner() const;
83 QString owner_id() const;83 QString owner_id() const;
8484
=== modified file 'include/unity/storage/qt/client/Exceptions.h'
--- include/unity/storage/qt/client/Exceptions.h 2016-07-22 02:35:12 +0000
+++ include/unity/storage/qt/client/Exceptions.h 2016-09-09 02:13:43 +0000
@@ -20,7 +20,10 @@
2020
21#include <unity/storage/visibility.h>21#include <unity/storage/visibility.h>
2222
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wcast-align"
23#include <QException>25#include <QException>
26#pragma GCC diagnostic pop
24#include <QString>27#include <QString>
2528
26namespace unity29namespace unity
@@ -46,6 +49,8 @@
4649
47 virtual char const* what() const noexcept override;50 virtual char const* what() const noexcept override;
4851
52 QString error_message() const;
53
49private:54private:
50 std::string what_string_;55 std::string what_string_;
51 QString error_message_;56 QString error_message_;
@@ -83,18 +88,16 @@
83class UNITY_STORAGE_EXPORT DeletedException : public StorageException88class UNITY_STORAGE_EXPORT DeletedException : public StorageException
84{89{
85public:90public:
86 DeletedException(QString const& error_message, QString const& identity_, QString const& name_);91 DeletedException(QString const& error_message, QString const& identity_);
87 ~DeletedException();92 ~DeletedException();
8893
89 virtual DeletedException* clone() const override;94 virtual DeletedException* clone() const override;
90 virtual void raise() const override;95 virtual void raise() const override;
9196
92 QString native_identity() const;97 QString native_identity() const;
93 QString name() const;
9498
95private:99private:
96 QString identity_;100 QString identity_;
97 QString name_;
98};101};
99102
100/**103/**
@@ -228,17 +231,22 @@
228};231};
229232
230/**233/**
231\brief Indicates a system error, such as failure to to create a file or folder,234\brief Indicates a system error, such as failure to create a file or folder,
232or any other (usually non-recoverable) kind of error that should not arise during normal operation.235or any other (usually non-recoverable) kind of error that should not arise during normal operation.
233*/236*/
234class UNITY_STORAGE_EXPORT ResourceException : public StorageException237class UNITY_STORAGE_EXPORT ResourceException : public StorageException
235{238{
236public:239public:
237 ResourceException(QString const& error_message);240 ResourceException(QString const& error_message, int error_code);
238 ~ResourceException();241 ~ResourceException();
239242
240 virtual ResourceException* clone() const override;243 virtual ResourceException* clone() const override;
241 virtual void raise() const override;244 virtual void raise() const override;
245
246 int error_code() const noexcept;
247
248private:
249 int error_code_;
242};250};
243251
244} // namespace client252} // namespace client
245253
=== modified file 'include/unity/storage/qt/client/Item.h'
--- include/unity/storage/qt/client/Item.h 2016-07-22 02:45:24 +0000
+++ include/unity/storage/qt/client/Item.h 2016-09-09 02:13:43 +0000
@@ -103,7 +103,7 @@
103103
104 If this item is a root, the returned pointer points at this item.104 If this item is a root, the returned pointer points at this item.
105 */105 */
106 Root* root() const;106 std::shared_ptr<Root> root() const;
107107
108 /**108 /**
109 \brief Returns the type of the item.109 \brief Returns the type of the item.
110110
=== modified file 'include/unity/storage/qt/client/Root.h'
--- include/unity/storage/qt/client/Root.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/qt/client/Root.h 2016-09-09 02:13:43 +0000
@@ -70,7 +70,7 @@
70 /**70 /**
71 \brief Returns the account for this root.71 \brief Returns the account for this root.
72 */72 */
73 Account* account() const;73 std::shared_ptr<Account> account() const;
7474
75 QFuture<int64_t> free_space_bytes() const;75 QFuture<int64_t> free_space_bytes() const;
76 QFuture<int64_t> used_space_bytes() const;76 QFuture<int64_t> used_space_bytes() const;
7777
=== modified file 'include/unity/storage/qt/client/Runtime.h'
--- include/unity/storage/qt/client/Runtime.h 2016-07-22 02:35:12 +0000
+++ include/unity/storage/qt/client/Runtime.h 2016-09-09 02:13:43 +0000
@@ -44,6 +44,7 @@
44namespace internal44namespace internal
45{45{
4646
47class AccountBase;
47class RuntimeBase;48class RuntimeBase;
4849
49namespace remote_client50namespace remote_client
@@ -95,11 +96,23 @@
9596
96 QFuture<QVector<std::shared_ptr<Account>>> accounts();97 QFuture<QVector<std::shared_ptr<Account>>> accounts();
9798
99 /// @cond
100 /**
101 \brief Creates an Account object pointing at (bus_name, object_path)
102
103 This method is intended for use in tests, where you want to talk
104 to a provider that has already been set up on the bus.
105 */
106 std::shared_ptr<Account> make_test_account(QString const& bus_name,
107 QString const& object_path);
108 /// @endcond
109
98private:110private:
99 Runtime(internal::RuntimeBase* p) UNITY_STORAGE_HIDDEN;111 Runtime(internal::RuntimeBase* p) UNITY_STORAGE_HIDDEN;
100112
101 std::shared_ptr<internal::RuntimeBase> p_;113 std::shared_ptr<internal::RuntimeBase> p_;
102114
115 friend class internal::AccountBase;
103 friend class internal::remote_client::AccountImpl;116 friend class internal::remote_client::AccountImpl;
104};117};
105118
106119
=== modified file 'include/unity/storage/qt/client/Uploader.h'
--- include/unity/storage/qt/client/Uploader.h 2016-07-22 02:35:12 +0000
+++ include/unity/storage/qt/client/Uploader.h 2016-09-09 02:13:43 +0000
@@ -92,6 +92,14 @@
92 std::shared_ptr<QLocalSocket> socket() const;92 std::shared_ptr<QLocalSocket> socket() const;
9393
94 /**94 /**
95 \brief Returns the size that was passed to Folder::create_file() or File::create_uploader().
96
97 \return The number of bytes that the uploader expects to be written to the `QLocalSocket` returned
98 from socket().
99 */
100 int64_t size() const;
101
102 /**
95 \brief Finalizes the upload.103 \brief Finalizes the upload.
96104
97 Once you have written the file contents to the socket returned by socket(), you must call finish_upload(),105 Once you have written the file contents to the socket returned by socket(), you must call finish_upload(),
98106
=== modified file 'include/unity/storage/qt/client/internal/AccountBase.h'
--- include/unity/storage/qt/client/internal/AccountBase.h 2016-07-22 02:35:12 +0000
+++ include/unity/storage/qt/client/internal/AccountBase.h 2016-09-09 02:13:43 +0000
@@ -52,7 +52,7 @@
52 AccountBase(AccountBase const&) = delete;52 AccountBase(AccountBase const&) = delete;
53 AccountBase& operator=(AccountBase const&) = delete;53 AccountBase& operator=(AccountBase const&) = delete;
5454
55 Runtime* runtime() const;55 std::shared_ptr<Runtime> runtime() const;
56 virtual QString owner() const = 0;56 virtual QString owner() const = 0;
57 virtual QString owner_id() const = 0;57 virtual QString owner_id() const = 0;
58 virtual QString description() const = 0;58 virtual QString description() const = 0;
5959
=== modified file 'include/unity/storage/qt/client/internal/ItemBase.h'
--- include/unity/storage/qt/client/internal/ItemBase.h 2016-07-27 02:19:17 +0000
+++ include/unity/storage/qt/client/internal/ItemBase.h 2016-09-09 02:13:43 +0000
@@ -20,10 +20,10 @@
2020
21#include <unity/storage/common.h>21#include <unity/storage/common.h>
2222
23#include <QDateTime>
24#pragma GCC diagnostic push23#pragma GCC diagnostic push
25#pragma GCC diagnostic ignored "-Wcast-align"24#pragma GCC diagnostic ignored "-Wcast-align"
26#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"25#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
26#include <QDateTime>
27#include <QFuture>27#include <QFuture>
28#pragma GCC diagnostic pop28#pragma GCC diagnostic pop
29#include <QVariantMap>29#include <QVariantMap>
@@ -60,7 +60,7 @@
6060
61 QString native_identity() const;61 QString native_identity() const;
62 ItemType type() const;62 ItemType type() const;
63 Root* root() const;63 std::shared_ptr<Root> root() const;
6464
65 virtual QString name() const = 0;65 virtual QString name() const = 0;
66 virtual QString etag() const = 0;66 virtual QString etag() const = 0;
@@ -82,10 +82,14 @@
82 void set_public_instance(std::weak_ptr<Item> p);82 void set_public_instance(std::weak_ptr<Item> p);
8383
84protected:84protected:
85 std::shared_ptr<Root> get_root() const noexcept;
86 void throw_if_destroyed(QString const& method) const;
87
85 const QString identity_;88 const QString identity_;
86 const ItemType type_;89 const ItemType type_;
87 std::weak_ptr<Root> root_;90 std::weak_ptr<Root> root_;
88 std::weak_ptr<Item> public_instance_;91 std::weak_ptr<Item> public_instance_;
92 bool deleted_ = false;
8993
90 friend class ItemImpl;94 friend class ItemImpl;
91};95};
9296
=== modified file 'include/unity/storage/qt/client/internal/RootBase.h'
--- include/unity/storage/qt/client/internal/RootBase.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/qt/client/internal/RootBase.h 2016-09-09 02:13:43 +0000
@@ -46,7 +46,7 @@
46public:46public:
47 RootBase(QString const& identity, std::weak_ptr<Account> const& account);47 RootBase(QString const& identity, std::weak_ptr<Account> const& account);
4848
49 Account* account() const;49 std::shared_ptr<Account> account() const;
50 virtual QFuture<int64_t> free_space_bytes() const = 0;50 virtual QFuture<int64_t> free_space_bytes() const = 0;
51 virtual QFuture<int64_t> used_space_bytes() const = 0;51 virtual QFuture<int64_t> used_space_bytes() const = 0;
52 virtual QFuture<Item::SPtr> get(QString native_identity) const = 0;52 virtual QFuture<Item::SPtr> get(QString native_identity) const = 0;
5353
=== modified file 'include/unity/storage/qt/client/internal/RuntimeBase.h'
--- include/unity/storage/qt/client/internal/RuntimeBase.h 2016-07-22 02:35:12 +0000
+++ include/unity/storage/qt/client/internal/RuntimeBase.h 2016-09-09 02:13:43 +0000
@@ -25,7 +25,6 @@
25#pragma GCC diagnostic pop25#pragma GCC diagnostic pop
26#include <QVector>26#include <QVector>
2727
28#include <atomic>
29#include <memory>28#include <memory>
3029
31namespace unity30namespace unity
@@ -43,23 +42,29 @@
43namespace internal42namespace internal
44{43{
4544
45class AccountBase;
46
46class RuntimeBase : public QObject47class RuntimeBase : public QObject
47{48{
48public:49public:
49 RuntimeBase();50 RuntimeBase() = default;
50 virtual ~RuntimeBase() = default;51 virtual ~RuntimeBase() = default;
51 RuntimeBase(RuntimeBase const&) = delete;52 RuntimeBase(RuntimeBase const&) = delete;
52 RuntimeBase& operator=(RuntimeBase const&) = delete;53 RuntimeBase& operator=(RuntimeBase const&) = delete;
5354
54 virtual void shutdown() = 0;55 virtual void shutdown() = 0;
55 virtual QFuture<QVector<std::shared_ptr<Account>>> accounts() = 0;56 virtual QFuture<QVector<std::shared_ptr<Account>>> accounts() = 0;
57 virtual std::shared_ptr<Account> make_test_account(QString const& bus_name,
58 QString const& object_path) = 0;
5659
57 void set_public_instance(std::weak_ptr<Runtime> p);60 void set_public_instance(std::weak_ptr<Runtime> p);
5861
59protected:62protected:
60 std::atomic_bool destroyed_;63 bool destroyed_ = false;
61 QVector<std::shared_ptr<Account>> accounts_; // Immutable once set64 QVector<std::shared_ptr<Account>> accounts_;
62 std::weak_ptr<Runtime> public_instance_; // Immutable once set65 std::weak_ptr<Runtime> public_instance_; // Immutable once set
66
67 friend class unity::storage::qt::client::internal::AccountBase;
63};68};
6469
65} // namespace internal70} // namespace internal
6671
=== modified file 'include/unity/storage/qt/client/internal/UploaderBase.h'
--- include/unity/storage/qt/client/internal/UploaderBase.h 2016-07-22 02:35:12 +0000
+++ include/unity/storage/qt/client/internal/UploaderBase.h 2016-09-09 02:13:43 +0000
@@ -47,7 +47,7 @@
47class UploaderBase : public QObject47class UploaderBase : public QObject
48{48{
49public:49public:
50 UploaderBase(ConflictPolicy policy);50 UploaderBase(ConflictPolicy policy, int64_t size);
51 UploaderBase(UploaderBase&) = delete;51 UploaderBase(UploaderBase&) = delete;
52 UploaderBase& operator=(UploaderBase const&) = delete;52 UploaderBase& operator=(UploaderBase const&) = delete;
5353
@@ -55,8 +55,11 @@
55 virtual QFuture<std::shared_ptr<File>> finish_upload() = 0;55 virtual QFuture<std::shared_ptr<File>> finish_upload() = 0;
56 virtual QFuture<void> cancel() noexcept = 0;56 virtual QFuture<void> cancel() noexcept = 0;
5757
58 int64_t size() const;
59
58protected:60protected:
59 ConflictPolicy policy_;61 ConflictPolicy policy_;
62 int64_t size_;
60};63};
6164
62} // namespace internal65} // namespace internal
6366
=== modified file 'include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h'
--- include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h 2016-07-14 04:50:36 +0000
+++ include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h 2016-09-09 02:13:43 +0000
@@ -60,7 +60,7 @@
6060
61private:61private:
62 void read_and_write_chunk();62 void read_and_write_chunk();
63 void handle_error(QString const& msg);63 void handle_error(QString const& msg, int error_code);
6464
65 enum State { in_progress, finalized, cancelled, error };65 enum State { in_progress, finalized, cancelled, error };
6666
@@ -73,6 +73,7 @@
73 QFutureInterface<void>& worker_initialized_;73 QFutureInterface<void>& worker_initialized_;
74 qint64 bytes_to_write_;74 qint64 bytes_to_write_;
75 QString error_msg_;75 QString error_msg_;
76 int error_code_ = 0;
76};77};
7778
78class DownloadThread : public QThread79class DownloadThread : public QThread
7980
=== modified file 'include/unity/storage/qt/client/internal/local_client/FolderImpl.h'
--- include/unity/storage/qt/client/internal/local_client/FolderImpl.h 2016-07-14 00:17:14 +0000
+++ include/unity/storage/qt/client/internal/local_client/FolderImpl.h 2016-09-09 02:13:43 +0000
@@ -40,6 +40,7 @@
40 FolderImpl(QString const& identity);40 FolderImpl(QString const& identity);
41 FolderImpl(QString const& identity, ItemType type);41 FolderImpl(QString const& identity, ItemType type);
4242
43 virtual QString name() const override;
43 QFuture<QVector<std::shared_ptr<Item>>> list() const override;44 QFuture<QVector<std::shared_ptr<Item>>> list() const override;
44 QFuture<QVector<std::shared_ptr<Item>>> lookup(QString const& name) const override;45 QFuture<QVector<std::shared_ptr<Item>>> lookup(QString const& name) const override;
45 QFuture<std::shared_ptr<Folder>> create_folder(QString const& name) override;46 QFuture<std::shared_ptr<Folder>> create_folder(QString const& name) override;
4647
=== modified file 'include/unity/storage/qt/client/internal/local_client/ItemImpl.h'
--- include/unity/storage/qt/client/internal/local_client/ItemImpl.h 2016-07-27 02:19:17 +0000
+++ include/unity/storage/qt/client/internal/local_client/ItemImpl.h 2016-09-09 02:13:43 +0000
@@ -47,7 +47,6 @@
47 ItemImpl(QString const& identity, ItemType type);47 ItemImpl(QString const& identity, ItemType type);
48 virtual ~ItemImpl();48 virtual ~ItemImpl();
4949
50 virtual QString name() const override;
51 virtual QString etag() const override;50 virtual QString etag() const override;
52 virtual QVariantMap metadata() const override;51 virtual QVariantMap metadata() const override;
53 virtual QDateTime last_modified_time() const override;52 virtual QDateTime last_modified_time() const override;
@@ -65,20 +64,18 @@
65 void set_timestamps() noexcept;64 void set_timestamps() noexcept;
66 bool has_conflict() const noexcept;65 bool has_conflict() const noexcept;
6766
68 std::unique_lock<std::mutex> get_lock();
69
70protected:67protected:
71 static boost::filesystem::path sanitize(QString const& name, QString const& method);68 static boost::filesystem::path sanitize(QString const& name, QString const& method);
72 static bool is_reserved_path(boost::filesystem::path const& path) noexcept;69 static bool is_reserved_path(boost::filesystem::path const& path) noexcept;
7370
74 DeletedException deleted_ex(QString const& method) const noexcept;
75
76 bool deleted_;
77 QString name_;71 QString name_;
78 QString etag_;72 QString etag_;
79 QDateTime modified_time_;73 QDateTime modified_time_;
80 QVariantMap metadata_;74 QVariantMap metadata_;
81 std::mutex mutable mutex_;75 std::recursive_mutex mutable mutex_;
76
77private:
78 static void copy_recursively(boost::filesystem::path const& source, boost::filesystem::path const& target);
82};79};
8380
84} // namespace local_client81} // namespace local_client
8582
=== modified file 'include/unity/storage/qt/client/internal/local_client/RuntimeImpl.h'
--- include/unity/storage/qt/client/internal/local_client/RuntimeImpl.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/qt/client/internal/local_client/RuntimeImpl.h 2016-09-09 02:13:43 +0000
@@ -41,6 +41,8 @@
4141
42 virtual void shutdown() override;42 virtual void shutdown() override;
43 virtual QFuture<QVector<std::shared_ptr<Account>>> accounts() override;43 virtual QFuture<QVector<std::shared_ptr<Account>>> accounts() override;
44 virtual std::shared_ptr<Account> make_test_account(QString const& bus_name,
45 QString const& object_path) override;
44};46};
4547
46} // namespace local_client48} // namespace local_client
4749
=== modified file 'include/unity/storage/qt/client/internal/local_client/UploaderImpl.h'
--- include/unity/storage/qt/client/internal/local_client/UploaderImpl.h 2016-07-26 01:51:26 +0000
+++ include/unity/storage/qt/client/internal/local_client/UploaderImpl.h 2016-09-09 02:13:43 +0000
@@ -68,12 +68,11 @@
68private Q_SLOTS:68private Q_SLOTS:
69 void on_bytes_ready();69 void on_bytes_ready();
70 void on_read_channel_finished();70 void on_read_channel_finished();
71 void on_error();
7271
73private:72private:
74 void read_and_write_chunk();73 void read_and_write_chunk();
75 void finalize();74 void finalize();
76 void handle_error(QString const& msg);75 void handle_error(QString const& msg, int error_code);
7776
78 enum State { in_progress, finalized, cancelled, error };77 enum State { in_progress, finalized, cancelled, error };
7978
@@ -91,6 +90,7 @@
91 QFutureInterface<std::shared_ptr<File>>& qf_;90 QFutureInterface<std::shared_ptr<File>>& qf_;
92 QFutureInterface<void>& worker_initialized_;91 QFutureInterface<void>& worker_initialized_;
93 QString error_msg_;92 QString error_msg_;
93 int error_code_ = 0;
94 bool use_linkat_ = true;94 bool use_linkat_ = true;
95};95};
9696
9797
=== added file 'include/unity/storage/qt/client/internal/local_client/storage_exception.h'
--- include/unity/storage/qt/client/internal/local_client/storage_exception.h 1970-01-01 00:00:00 +0000
+++ include/unity/storage/qt/client/internal/local_client/storage_exception.h 2016-09-09 02:13:43 +0000
@@ -0,0 +1,94 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <unity/storage/qt/client/Exceptions.h>
22#include <unity/storage/qt/client/internal/local_client/boost_filesystem.h>
23
24#pragma GCC diagnostic push
25#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
26#pragma GCC diagnostic ignored "-Wcast-align"
27#include <QFuture>
28#pragma GCC diagnostic pop
29#include <QFutureInterface>
30
31class QString;
32
33namespace unity
34{
35namespace storage
36{
37namespace qt
38{
39namespace client
40{
41namespace internal
42{
43namespace local_client
44{
45
46void throw_storage_exception(QString const& method,
47 std::exception_ptr ep) __attribute__ ((noreturn));
48
49void throw_storage_exception(QString const& method,
50 std::exception_ptr ep,
51 QString const& key) __attribute__ ((noreturn));
52
53template<typename T>
54QFuture<T> make_exceptional_future(QString const& method, std::exception_ptr ep)
55{
56 try
57 {
58 throw_storage_exception(method, ep);
59 }
60 catch (StorageException const& e)
61 {
62 QFutureInterface<T> qf;
63 qf.reportException(e);
64 qf.reportFinished();
65 return qf.future();
66 }
67 abort(); // Impossible. // LCOV_EXCL_LINE
68}
69
70template<typename T>
71QFuture<T> make_exceptional_future(QString const& method,
72 std::exception_ptr ep,
73 QString const& key)
74{
75 try
76 {
77 throw_storage_exception(method, ep, key);
78 }
79 catch (StorageException const& e)
80 {
81 QFutureInterface<T> qf;
82 qf.reportException(e);
83 qf.reportFinished();
84 return qf.future();
85 }
86 abort(); // Impossible. // LCOV_EXCL_LINE
87}
88
89} // namespace local_client
90} // namespace internal
91} // namespace client
92} // namespace qt
93} // namespace storage
94} // namespace unity
095
=== renamed file 'include/unity/storage/qt/client/internal/local_client/tmpfile-prefix.h' => 'include/unity/storage/qt/client/internal/local_client/tmpfile_prefix.h'
=== modified file 'include/unity/storage/qt/client/internal/make_future.h'
--- include/unity/storage/qt/client/internal/make_future.h 2016-07-22 02:35:12 +0000
+++ include/unity/storage/qt/client/internal/make_future.h 2016-09-09 02:13:43 +0000
@@ -36,40 +36,30 @@
36namespace internal36namespace internal
37{37{
3838
39template<typename T>
40QFuture<T>
41__attribute__ ((warn_unused_result))
42make_ready_future(T const& val)
43{
44 QFutureInterface<T> qf;
45 qf.reportResult(val);
46 qf.reportFinished();
47 return qf.future();
48}
49
39template<typename T = void>50template<typename T = void>
40QFuture<T> make_ready_future()51QFuture<T>
52__attribute__ ((warn_unused_result))
53make_ready_future()
41{54{
42 QFutureInterface<void> qf;55 QFutureInterface<void> qf;
43 qf.reportFinished();56 return make_ready_future(qf);
44 return qf.future();
45}
46
47template<typename T = void>
48QFuture<T> make_ready_future(QFutureInterface<T> qf)
49{
50 qf.reportFinished();
51 return qf.future();
52}
53
54template<typename T>
55QFuture<T> make_ready_future(T const& val)
56{
57 QFutureInterface<T> qf;
58 qf.reportResult(val);
59 qf.reportFinished();
60 return qf.future();
61}
62
63template<typename T>
64QFuture<T> make_ready_future(QFutureInterface<T> qf, T const& val)
65{
66 qf.reportResult(val);
67 qf.reportFinished();
68 return qf.future();
69}57}
7058
71template<typename E>59template<typename E>
72QFuture<void> make_exceptional_future(E const& ex)60QFuture<void>
61__attribute__
62((warn_unused_result)) make_exceptional_future(E const& ex)
73{63{
74 QFutureInterface<void> qf;64 QFutureInterface<void> qf;
75 qf.reportException(ex);65 qf.reportException(ex);
@@ -78,7 +68,9 @@
78}68}
7969
80template<typename T, typename E>70template<typename T, typename E>
81QFuture<T> make_exceptional_future(E const& ex)71QFuture<T>
72__attribute__ ((warn_unused_result))
73make_exceptional_future(E const& ex)
82{74{
83 QFutureInterface<T> qf;75 QFutureInterface<T> qf;
84 qf.reportException(ex);76 qf.reportException(ex);
@@ -86,14 +78,6 @@
86 return qf.future();78 return qf.future();
87}79}
8880
89template<typename T, typename E>
90QFuture<T> make_exceptional_future(QFutureInterface<T> qf, E const& ex)
91{
92 qf.reportException(ex);
93 qf.reportFinished();
94 return qf.future();
95}
96
97} // namespace internal81} // namespace internal
98} // namespace client82} // namespace client
99} // namespace qt83} // namespace qt
10084
=== modified file 'include/unity/storage/qt/client/internal/remote_client/AccountImpl.h'
--- include/unity/storage/qt/client/internal/remote_client/AccountImpl.h 2016-07-15 03:56:14 +0000
+++ include/unity/storage/qt/client/internal/remote_client/AccountImpl.h 2016-09-09 02:13:43 +0000
@@ -39,7 +39,8 @@
39{39{
40public:40public:
41 AccountImpl(std::weak_ptr<Runtime> const& runtime,41 AccountImpl(std::weak_ptr<Runtime> const& runtime,
42 int account_id,42 QString const& bus_name,
43 QString const& object_path,
43 QString const& owner,44 QString const& owner,
44 QString const& owner_id,45 QString const& owner_id,
45 QString const& description);46 QString const& description);
4647
=== modified file 'include/unity/storage/qt/client/internal/remote_client/Handler.h'
--- include/unity/storage/qt/client/internal/remote_client/Handler.h 2016-07-15 03:58:35 +0000
+++ include/unity/storage/qt/client/internal/remote_client/Handler.h 2016-09-09 02:13:43 +0000
@@ -20,10 +20,13 @@
2020
21#include <unity/storage/qt/client/Exceptions.h>21#include <unity/storage/qt/client/Exceptions.h>
22#include <unity/storage/qt/client/internal/make_future.h>22#include <unity/storage/qt/client/internal/make_future.h>
23#include <unity/storage/qt/client/internal/remote_client/dbusmarshal.h>
23#include <unity/storage/qt/client/internal/remote_client/HandlerBase.h>24#include <unity/storage/qt/client/internal/remote_client/HandlerBase.h>
2425
25#include <QDBusPendingReply>26#include <QDBusPendingReply>
2627
28#include <cassert>
29
27namespace unity30namespace unity
28{31{
29namespace storage32namespace storage
@@ -72,8 +75,41 @@
72 {75 {
73 if (call.isError())76 if (call.isError())
74 {77 {
75 qDebug() << call.error().message(); // TODO, remove this78 try
76 make_exceptional_future<T>(ResourceException("DBus error return"));79 {
80 auto ep = unmarshal_exception(call);
81 std::rethrow_exception(ep);
82 }
83 // We catch some exceptions that are "surprising" so we can log those.
84 catch (LocalCommsException const& e)
85 {
86 qCritical() << "provider exception:" << e.what();
87 qf_.reportException(e);
88 qf_.reportFinished();
89 }
90 catch (RemoteCommsException const& e)
91 {
92 qCritical() << "provider exception:" << e.what();
93 qf_.reportException(e);
94 qf_.reportFinished();
95 }
96 catch (ResourceException const& e)
97 {
98 qCritical() << "provider exception:" << e.what();
99 qf_.reportException(e);
100 qf_.reportFinished();
101 }
102 catch (StorageException const& e)
103 {
104 qf_.reportException(e);
105 qf_.reportFinished();
106 }
107 // LCOV_EXCL_START
108 catch (...)
109 {
110 abort(); // Impossible.
111 }
112 // LCOV_EXCL_STOP
77 return;113 return;
78 }114 }
79 // TODO: See HACK above. Should just be closure(call, qf_);115 // TODO: See HACK above. Should just be closure(call, qf_);
80116
=== modified file 'include/unity/storage/qt/client/internal/remote_client/ItemImpl.h'
--- include/unity/storage/qt/client/internal/remote_client/ItemImpl.h 2016-07-22 00:17:24 +0000
+++ include/unity/storage/qt/client/internal/remote_client/ItemImpl.h 2016-09-09 02:13:43 +0000
@@ -66,9 +66,6 @@
66 static std::shared_ptr<Item> make_item(storage::internal::ItemMetadata const& md, std::weak_ptr<Root> root);66 static std::shared_ptr<Item> make_item(storage::internal::ItemMetadata const& md, std::weak_ptr<Root> root);
6767
68protected:68protected:
69 DeletedException deleted_ex(QString const& method) const noexcept;
70
71 bool deleted_ = false;
72 storage::internal::ItemMetadata md_;69 storage::internal::ItemMetadata md_;
7370
74 friend class DeleteHandler;71 friend class DeleteHandler;
7572
=== modified file 'include/unity/storage/qt/client/internal/remote_client/RuntimeImpl.h'
--- include/unity/storage/qt/client/internal/remote_client/RuntimeImpl.h 2016-07-22 00:17:24 +0000
+++ include/unity/storage/qt/client/internal/remote_client/RuntimeImpl.h 2016-09-09 02:13:43 +0000
@@ -50,6 +50,8 @@
5050
51 virtual void shutdown() override;51 virtual void shutdown() override;
52 virtual QFuture<QVector<std::shared_ptr<Account>>> accounts() override;52 virtual QFuture<QVector<std::shared_ptr<Account>>> accounts() override;
53 virtual std::shared_ptr<Account> make_test_account(QString const& bus_name,
54 QString const& object_path) override;
5355
54 QDBusConnection& connection();56 QDBusConnection& connection();
5557
@@ -58,6 +60,12 @@
58 virtual void timeout();60 virtual void timeout();
5961
60private:62private:
63 std::shared_ptr<Account> make_account(QString const& bus_name,
64 QString const& object_path,
65 QString const& owner,
66 QString const& owner_id,
67 QString const& description);
68
61 QDBusConnection conn_;69 QDBusConnection conn_;
62 std::unique_ptr<OnlineAccounts::Manager> manager_; // TODO: Hack until we can use the registry70 std::unique_ptr<OnlineAccounts::Manager> manager_; // TODO: Hack until we can use the registry
63 QTimer timer_;71 QTimer timer_;
6472
=== modified file 'include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h'
--- include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h 2016-07-22 00:17:24 +0000
+++ include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h 2016-09-09 02:13:43 +0000
@@ -65,13 +65,15 @@
65 std::shared_ptr<ProviderInterface> const& provider);65 std::shared_ptr<ProviderInterface> const& provider);
6666
67private:67private:
68 enum State { uploading, finalized };
69
68 QString upload_id_;70 QString upload_id_;
69 QDBusUnixFileDescriptor fd_;71 QDBusUnixFileDescriptor fd_;
70 int64_t size_;
71 QString old_etag_;72 QString old_etag_;
72 std::weak_ptr<Root> root_;73 std::shared_ptr<Root> root_;
73 std::shared_ptr<ProviderInterface> provider_;74 std::shared_ptr<ProviderInterface> provider_;
74 std::shared_ptr<QLocalSocket> write_socket_;75 std::shared_ptr<QLocalSocket> write_socket_;
76 State state_;
75};77};
7678
77} // namespace remote_client79} // namespace remote_client
7880
=== modified file 'include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h'
--- include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h 2016-07-12 02:22:05 +0000
+++ include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h 2016-09-09 02:13:43 +0000
@@ -18,29 +18,28 @@
1818
19#pragma once19#pragma once
2020
21#include <unity/storage/internal/ItemMetadata.h>21#include <exception>
2222
23#include <QDBusArgument>23class QDBusPendingCallWatcher;
24#include <QMetaType>
25#include <QVariant>
2624
27namespace unity25namespace unity
28{26{
29namespace storage27namespace storage
30{28{
29namespace qt
30{
31namespace client
32{
31namespace internal33namespace internal
32{34{
3335namespace remote_client
34struct ItemMetadata;36{
35QDBusArgument& operator<<(QDBusArgument& argument, storage::internal::ItemMetadata const& metadata);37
36QDBusArgument const& operator>>(QDBusArgument const& argument, storage::internal::ItemMetadata& metadata);38std::exception_ptr unmarshal_exception(QDBusPendingCallWatcher const& call);
3739
38QDBusArgument& operator<<(QDBusArgument& argument, QList<storage::internal::ItemMetadata> const& md_list);40} // namespace remote_client
39QDBusArgument const& operator>>(QDBusArgument const& argument, QList<storage::internal::ItemMetadata>& md_list);
40
41} // namespace internal41} // namespace internal
42} // namespace storage42} // client
43} // namespace unity43} // qt
4444} // storage
45Q_DECLARE_METATYPE(unity::storage::internal::ItemMetadata)45} // unity
46Q_DECLARE_METATYPE(QList<unity::storage::internal::ItemMetadata>)
4746
=== added file 'include/unity/storage/qt/client/internal/remote_client/validate.h'
--- include/unity/storage/qt/client/internal/remote_client/validate.h 1970-01-01 00:00:00 +0000
+++ include/unity/storage/qt/client/internal/remote_client/validate.h 2016-09-09 02:13:43 +0000
@@ -0,0 +1,51 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <QString>
22
23namespace unity
24{
25namespace storage
26{
27
28namespace internal
29{
30
31class ItemMetadata;
32
33} // namespace internal
34
35namespace qt
36{
37namespace client
38{
39namespace internal
40{
41namespace remote_client
42{
43
44void validate(QString const& method, unity::storage::internal::ItemMetadata const& md);
45
46} // namespace remote_client
47} // namespace internal
48} // namespace client
49} // namespace qt
50} // namespace storage
51} // namespace unity
052
=== modified file 'src/internal/CMakeLists.txt'
--- src/internal/CMakeLists.txt 2016-07-06 00:59:42 +0000
+++ src/internal/CMakeLists.txt 2016-09-09 02:13:43 +0000
@@ -1,5 +1,10 @@
1set(src1set(src
2 dbusmarshal.cpp
2 safe_strerror.cpp3 safe_strerror.cpp
4 TraceMessageHandler.cpp
3)5)
46
5add_library(storage-framework-common-internal STATIC ${src})7add_library(storage-framework-common-internal STATIC ${src})
8target_link_libraries(storage-framework-common-internal
9 Qt5::DBus
10)
611
=== added file 'src/internal/TraceMessageHandler.cpp'
--- src/internal/TraceMessageHandler.cpp 1970-01-01 00:00:00 +0000
+++ src/internal/TraceMessageHandler.cpp 2016-09-09 02:13:43 +0000
@@ -0,0 +1,96 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#include <unity/storage/internal/TraceMessageHandler.h>
20
21#include <chrono>
22#include <mutex>
23
24using namespace std;
25
26namespace unity
27{
28namespace storage
29{
30namespace internal
31{
32namespace
33{
34
35string prefix;
36
37void trace_message_handler(QtMsgType type, const QMessageLogContext& /*context*/, const QString& msg)
38{
39 using namespace std;
40 using namespace std::chrono;
41
42 static recursive_mutex mutex;
43 lock_guard<decltype(mutex)> lock(mutex);
44
45 auto now = system_clock::now();
46 auto sys_time = system_clock::to_time_t(now);
47 struct tm local_time;
48 localtime_r(&sys_time, &local_time);
49 int msecs = duration_cast<milliseconds>(now.time_since_epoch()).count() % 1000;
50
51 if (!prefix.empty())
52 {
53 fprintf(stderr, "%s: ", prefix.c_str());
54 }
55 char buf[100];
56 strftime(buf, sizeof(buf), "%T", &local_time);
57 fprintf(stderr, "[%s.%03d]", buf, msecs);
58 switch (type)
59 {
60 case QtWarningMsg:
61 fputs(" Warning:", stderr);
62 break;
63 case QtCriticalMsg:
64 fputs(" Critical:", stderr);
65 break;
66 // LCOV_EXCL_START
67 case QtFatalMsg:
68 fputs(" Fatal:", stderr);
69 break;
70 // LCOV_EXCL_STOP
71 default:
72 break; // No label for debug messages.
73 }
74 fprintf(stderr, " %s\n", msg.toLocal8Bit().constData());
75 if (type == QtFatalMsg)
76 {
77 abort(); // LCOV_EXCL_LINE
78 }
79}
80
81} // namespace
82
83TraceMessageHandler::TraceMessageHandler(string const& prog_name)
84{
85 prefix = prog_name;
86 old_message_handler_ = qInstallMessageHandler(trace_message_handler);
87}
88
89TraceMessageHandler::~TraceMessageHandler()
90{
91 qInstallMessageHandler(old_message_handler_);
92}
93
94} // namespace internal
95} // namespace storage
96} // namespace unity
097
=== added file 'src/internal/dbusmarshal.cpp'
--- src/internal/dbusmarshal.cpp 1970-01-01 00:00:00 +0000
+++ src/internal/dbusmarshal.cpp 2016-09-09 02:13:43 +0000
@@ -0,0 +1,113 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#include <unity/storage/internal/dbusmarshal.h>
20
21#include <QDebug>
22
23using namespace unity::storage::internal;
24using namespace std;
25
26namespace unity
27{
28namespace storage
29{
30namespace internal
31{
32
33QDBusArgument& operator<<(QDBusArgument& argument, storage::internal::ItemMetadata const& metadata)
34{
35 argument.beginStructure();
36 argument << metadata.item_id;
37 argument << metadata.parent_ids;
38 argument << metadata.name;
39 argument << metadata.etag;
40 argument << static_cast<int32_t>(metadata.type);
41 argument.beginMap(QVariant::String, qMetaTypeId<QDBusVariant>());
42 decltype(ItemMetadata::metadata)::const_iterator i = metadata.metadata.constBegin();
43 while (i != metadata.metadata.constEnd())
44 {
45 argument.beginMapEntry();
46 argument << i.key() << QDBusVariant(i.value());
47 argument.endMapEntry();
48 ++i;
49 }
50 argument.endMap();
51 argument.endStructure();
52 return argument;
53}
54
55QDBusArgument const& operator>>(QDBusArgument const& argument, storage::internal::ItemMetadata& metadata)
56{
57 argument.beginStructure();
58 argument >> metadata.item_id;
59 argument >> metadata.parent_ids;
60 argument >> metadata.name;
61 argument >> metadata.etag;
62 int32_t enum_val;
63 argument >> enum_val;
64 if (enum_val < 0 || enum_val >= int(ItemType::LAST_ENTRY__))
65 {
66 qCritical() << "unmarshaling error: impossible ItemType value: " + QString::number(enum_val);
67 return argument; // Forces error
68 }
69 metadata.type = static_cast<ItemType>(enum_val);
70 metadata.metadata.clear();
71 argument.beginMap();
72 while (!argument.atEnd())
73 {
74 QString key;
75 QVariant value;
76 argument.beginMapEntry();
77 argument >> key >> value;
78 argument.endMapEntry();
79 metadata.metadata.insert(key, value);
80 }
81 argument.endMap();
82 argument.endStructure();
83 return argument;
84}
85
86QDBusArgument& operator<<(QDBusArgument& argument, QList<storage::internal::ItemMetadata> const& md_list)
87{
88 argument.beginArray(qMetaTypeId<storage::internal::ItemMetadata>());
89 for (auto const& md : md_list)
90 {
91 argument << md;
92 }
93 argument.endArray();
94 return argument;
95}
96
97QDBusArgument const& operator>>(QDBusArgument const& argument, QList<storage::internal::ItemMetadata>& md_list)
98{
99 md_list.clear();
100 argument.beginArray();
101 while (!argument.atEnd())
102 {
103 ItemMetadata imd;
104 argument >> imd;
105 md_list.append(imd);
106 }
107 argument.endArray();
108 return argument;
109}
110
111} // namespace internal
112} // namespace storage
113} // namespace unity
0114
=== modified file 'src/provider/CMakeLists.txt'
--- src/provider/CMakeLists.txt 2016-07-22 03:29:45 +0000
+++ src/provider/CMakeLists.txt 2016-09-09 02:13:43 +0000
@@ -1,9 +1,3 @@
1
2add_definitions(
3 -DBOOST_THREAD_VERSION=4
4 -DBOOST_THREAD_PROVIDES_EXECUTORS
5 ${APPARMOR_DEPS_CFLAGS}
6 ${ONLINEACCOUNTS_DEPS_CFLAGS})
7include_directories(${CMAKE_CURRENT_BINARY_DIR})1include_directories(${CMAKE_CURRENT_BINARY_DIR})
82
9qt5_add_dbus_adaptor(generated_files ${CMAKE_SOURCE_DIR}/data/provider.xml unity/storage/provider/internal/ProviderInterface.h unity::storage::provider::internal::ProviderInterface)3qt5_add_dbus_adaptor(generated_files ${CMAKE_SOURCE_DIR}/data/provider.xml unity/storage/provider/internal/ProviderInterface.h unity::storage::provider::internal::ProviderInterface)
@@ -12,16 +6,20 @@
12qt5_add_dbus_interface(generated_files bus.xml businterface)6qt5_add_dbus_interface(generated_files bus.xml businterface)
137
14set_source_files_properties(${generated_files} PROPERTIES8set_source_files_properties(${generated_files} PROPERTIES
15 COMPILE_FLAGS "-Wno-ctor-dtor-privacy -Wmissing-field-initializers"9 COMPILE_FLAGS "-Wno-ctor-dtor-privacy -Wmissing-field-initializers"
16 GENERATED TRUE10 GENERATED TRUE
17)11)
1812
19add_library(storage-framework-provider SHARED13add_custom_target(sf-provider-generated-files DEPENDS ${generated_files})
14
15add_library(sf-provider-objects OBJECT
20 DownloadJob.cpp16 DownloadJob.cpp
17 Exceptions.cpp
21 ProviderBase.cpp18 ProviderBase.cpp
22 Server.cpp19 Server.cpp
23 TempfileUploadJob.cpp20 TempfileUploadJob.cpp
24 UploadJob.cpp21 UploadJob.cpp
22 testing/TestServer.cpp
25 internal/AccountData.cpp23 internal/AccountData.cpp
26 internal/DBusPeerCache.cpp24 internal/DBusPeerCache.cpp
27 internal/DownloadJobImpl.cpp25 internal/DownloadJobImpl.cpp
@@ -31,6 +29,7 @@
31 internal/ProviderInterface.cpp29 internal/ProviderInterface.cpp
32 internal/ServerImpl.cpp30 internal/ServerImpl.cpp
33 internal/TempfileUploadJobImpl.cpp31 internal/TempfileUploadJobImpl.cpp
32 internal/TestServerImpl.cpp
34 internal/UploadJobImpl.cpp33 internal/UploadJobImpl.cpp
35 internal/dbusmarshal.cpp34 internal/dbusmarshal.cpp
36 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/AccountData.h35 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/AccountData.h
@@ -42,6 +41,23 @@
42 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/ServerImpl.h41 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/ServerImpl.h
43 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/TempfileUploadJobImpl.h42 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/TempfileUploadJobImpl.h
44 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/UploadJobImpl.h43 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/UploadJobImpl.h
44)
45add_dependencies(sf-provider-objects sf-provider-generated-files)
46set_target_properties(sf-provider-objects PROPERTIES
47 AUTOMOC TRUE
48)
49target_compile_options(sf-provider-objects PUBLIC
50 -DBOOST_THREAD_VERSION=4
51 -DBOOST_THREAD_PROVIDES_EXECUTORS
52 ${APPARMOR_DEPS_CFLAGS}
53 ${ONLINEACCOUNTS_DEPS_CFLAGS})
54target_include_directories(sf-provider-objects PRIVATE
55 ${Qt5DBus_INCLUDE_DIRS}
56 ${Qt5Network_INCLUDE_DIRS}
57)
58
59add_library(storage-framework-provider SHARED
60 $<TARGET_OBJECTS:sf-provider-objects>
45 ${generated_files})61 ${generated_files})
4662
47set_target_properties(storage-framework-provider PROPERTIES63set_target_properties(storage-framework-provider PROPERTIES
@@ -51,7 +67,10 @@
51 SOVERSION ${SF_PROVIDER_SOVERSION}67 SOVERSION ${SF_PROVIDER_SOVERSION}
52 VERSION ${SF_PROVIDER_LIBVERSION}68 VERSION ${SF_PROVIDER_LIBVERSION}
53)69)
70target_compile_options(storage-framework-provider PUBLIC
71 $<TARGET_PROPERTY:sf-provider-objects,COMPILE_OPTIONS>)
54target_link_libraries(storage-framework-provider72target_link_libraries(storage-framework-provider
73 storage-framework-common-internal
55 Qt5::Core74 Qt5::Core
56 Qt5::DBus75 Qt5::DBus
57 Qt5::Network76 Qt5::Network
@@ -60,19 +79,31 @@
60 ${ONLINEACCOUNTS_DEPS_LDFLAGS}79 ${ONLINEACCOUNTS_DEPS_LDFLAGS}
61)80)
6281
63# moc does not know how to interpret the preprocessor logic in
64# MainLoopExecutor.h, so we reproduce it here.
65if(Boost_VERSION GREATER "105599")
66 set_target_properties(storage-framework-provider PROPERTIES
67 AUTOMOC_MOC_OPTIONS "-DSF_SUPPORTS_EXECUTORS"
68 )
69endif()
70
71install(82install(
72 TARGETS storage-framework-provider83 TARGETS storage-framework-provider
73 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}84 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
74)85)
7586
87# Build a static version of the library so that tests have access to
88# hidden visibility symbols.
89add_library(storage-framework-provider-static STATIC
90 $<TARGET_OBJECTS:sf-provider-objects>
91 ${generated_files})
92set_target_properties(storage-framework-provider-static PROPERTIES
93 AUTOMOC TRUE
94 )
95target_compile_options(storage-framework-provider-static PUBLIC
96 $<TARGET_PROPERTY:sf-provider-objects,COMPILE_OPTIONS>)
97target_link_libraries(storage-framework-provider-static
98 storage-framework-common-internal
99 Qt5::Core
100 Qt5::DBus
101 Qt5::Network
102 ${Boost_LIBRARIES}
103 ${APPARMOR_DEPS_LDFLAGS}
104 ${ONLINEACCOUNTS_DEPS_LDFLAGS}
105)
106
76configure_file(107configure_file(
77 storage-framework-provider.pc.in108 storage-framework-provider.pc.in
78 storage-framework-provider-${SF_PROVIDER_API_VERSION}.pc109 storage-framework-provider-${SF_PROVIDER_API_VERSION}.pc
79110
=== added file 'src/provider/Exceptions.cpp'
--- src/provider/Exceptions.cpp 1970-01-01 00:00:00 +0000
+++ src/provider/Exceptions.cpp 2016-09-09 02:13:43 +0000
@@ -0,0 +1,157 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#include <unity/storage/provider/Exceptions.h>
20
21using namespace std;
22
23namespace unity
24{
25namespace storage
26{
27namespace provider
28{
29
30StorageException::StorageException(std::string const& exception_type, string const& error_message)
31 : what_string_(string(exception_type) + ": " + error_message)
32 , type_(exception_type)
33 , error_message_(error_message)
34{
35}
36
37StorageException::~StorageException() = default;
38
39char const* StorageException::what() const noexcept
40{
41 return what_string_.c_str();
42}
43
44string StorageException::type() const
45{
46 return type_;
47}
48
49string StorageException::error_message() const
50{
51 return error_message_;
52}
53
54RemoteCommsException::RemoteCommsException(string const& error_message)
55 : StorageException("RemoteCommsException", error_message)
56{
57}
58
59RemoteCommsException::~RemoteCommsException() = default;
60
61NotExistsException::NotExistsException(string const& error_message, string const& key)
62 : StorageException("NotExistsException", error_message)
63 , key_(key)
64{
65}
66
67NotExistsException::~NotExistsException() = default;
68
69string NotExistsException::key() const
70{
71 return key_;
72}
73
74ExistsException::ExistsException(string const& error_message, string const& identity, string const& name)
75 : StorageException("ExistsException", error_message)
76 , identity_(identity)
77 , name_(name)
78{
79}
80
81ExistsException::~ExistsException() = default;
82
83string ExistsException::native_identity() const
84{
85 return identity_;
86}
87
88string ExistsException::name() const
89{
90 return name_;
91}
92
93ConflictException::ConflictException(string const& error_message)
94 : StorageException("ConflictException", error_message)
95{
96}
97
98ConflictException::~ConflictException() = default;
99
100PermissionException::PermissionException(string const& error_message)
101 : StorageException("PermissionException", error_message)
102{
103}
104
105PermissionException::~PermissionException() = default;
106
107QuotaException::QuotaException(string const& error_message)
108 : StorageException("QuotaException", error_message)
109{
110}
111
112QuotaException::~QuotaException() = default;
113
114CancelledException::CancelledException(string const& error_message)
115 : StorageException("CancelledException", error_message)
116{
117}
118
119CancelledException::~CancelledException() = default;
120
121LogicException::LogicException(string const& error_message)
122 : StorageException("LogicException", error_message)
123{
124}
125
126LogicException::~LogicException() = default;
127
128InvalidArgumentException::InvalidArgumentException(string const& error_message)
129 : StorageException("InvalidArgumentException", error_message)
130{
131}
132
133InvalidArgumentException::~InvalidArgumentException() = default;
134
135ResourceException::ResourceException(string const& error_message, int error_code)
136 : StorageException("ResourceException", error_message)
137 , error_code_(error_code)
138{
139}
140
141ResourceException::~ResourceException() = default;
142
143int ResourceException::error_code() const noexcept
144{
145 return error_code_;
146}
147
148UnknownException::UnknownException(string const& error_message)
149 : StorageException("UnknownException", error_message)
150{
151}
152
153UnknownException::~UnknownException() = default;
154
155} // namespace provider
156} // namespace storage
157} // namespace unity
0158
=== modified file 'src/provider/TempfileUploadJob.cpp'
--- src/provider/TempfileUploadJob.cpp 2016-07-12 02:22:05 +0000
+++ src/provider/TempfileUploadJob.cpp 2016-09-09 02:13:43 +0000
@@ -40,6 +40,11 @@
4040
41TempfileUploadJob::~TempfileUploadJob() = default;41TempfileUploadJob::~TempfileUploadJob() = default;
4242
43void TempfileUploadJob::drain()
44{
45 static_cast<internal::TempfileUploadJobImpl*>(p_)->drain();
46}
47
43string TempfileUploadJob::file_name() const48string TempfileUploadJob::file_name() const
44{49{
45 return static_cast<internal::TempfileUploadJobImpl*>(p_)->file_name();50 return static_cast<internal::TempfileUploadJobImpl*>(p_)->file_name();
4651
=== modified file 'src/provider/internal/DownloadJobImpl.cpp'
--- src/provider/internal/DownloadJobImpl.cpp 2016-07-12 02:22:05 +0000
+++ src/provider/internal/DownloadJobImpl.cpp 2016-09-09 02:13:43 +0000
@@ -17,7 +17,9 @@
17 */17 */
1818
19#include <unity/storage/provider/internal/DownloadJobImpl.h>19#include <unity/storage/provider/internal/DownloadJobImpl.h>
20#include <unity/storage/internal/safe_strerror.h>
20#include <unity/storage/provider/DownloadJob.h>21#include <unity/storage/provider/DownloadJob.h>
22#include <unity/storage/provider/Exceptions.h>
2123
22#include <sys/socket.h>24#include <sys/socket.h>
23#include <sys/types.h>25#include <sys/types.h>
@@ -26,6 +28,7 @@
26#include <stdexcept>28#include <stdexcept>
2729
28using namespace std;30using namespace std;
31using namespace unity::storage::internal;
2932
30namespace unity33namespace unity
31{34{
@@ -42,18 +45,30 @@
42 int socks[2];45 int socks[2];
43 if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) < 0)46 if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) < 0)
44 {47 {
45 throw runtime_error("could not create socketpair");48 int error_code = errno;
49 string msg = "could not create socketpair: " + safe_strerror(error_code);
50 throw ResourceException(msg, error_code);
46 }51 }
47 read_socket_ = socks[0];52 read_socket_ = socks[0];
48 write_socket_ = socks[1];53 write_socket_ = socks[1];
54
55#if 0
56 // TODO: We should be able to half-close the write channel of the read socket and the read channel of
57 // the write socket. But, if we do, QLocalSocket indicates that everything was closed, which causes
58 // failures on the client side. We suspect a QLocalSocket bug -- need to investigate.
49 if (shutdown(read_socket_, SHUT_WR) < 0)59 if (shutdown(read_socket_, SHUT_WR) < 0)
50 {60 {
51 throw runtime_error("Could not shut down write channel on read socket");61 int error_code = errno;
62 string msg = "Could not shut down write channel on read socket" + safe_strerror(error_code);
63 throw ResourceException(msg, error_code);
52 }64 }
53 if (shutdown(write_socket_, SHUT_RD) < 0)65 if (shutdown(write_socket_, SHUT_RD) < 0)
54 {66 {
55 throw runtime_error("Could not shut down read channel on write socket");67 int error_code = errno;
68 string msg = "Could not shut down read channel on write socket: " + safe_strerror(error_code);
69 throw ResourceException(msg, error_code);
56 }70 }
71#endif
57}72}
5873
59DownloadJobImpl::~DownloadJobImpl()74DownloadJobImpl::~DownloadJobImpl()
@@ -90,17 +105,6 @@
90 return sock;105 return sock;
91}106}
92107
93string const& DownloadJobImpl::sender_bus_name() const
94{
95 return sender_bus_name_;
96}
97
98void DownloadJobImpl::set_sender_bus_name(string const& bus_name)
99{
100 assert(bus_name[0] == ':');
101 sender_bus_name_ = bus_name;
102}
103
104void DownloadJobImpl::report_complete()108void DownloadJobImpl::report_complete()
105{109{
106 if (write_socket_ >= 0)110 if (write_socket_ >= 0)
@@ -124,7 +128,19 @@
124128
125 lock_guard<mutex> guard(completion_lock_);129 lock_guard<mutex> guard(completion_lock_);
126 completed_ = true;130 completed_ = true;
127 completion_promise_.set_exception(p);131 // Convert std::exception_ptr to boost::exception_ptr
132 try
133 {
134 std::rethrow_exception(p);
135 }
136 catch (StorageException const& e)
137 {
138 completion_promise_.set_exception(e);
139 }
140 catch (...)
141 {
142 completion_promise_.set_exception(boost::current_exception());
143 }
128}144}
129145
130boost::future<void> DownloadJobImpl::finish(DownloadJob& job)146boost::future<void> DownloadJobImpl::finish(DownloadJob& job)
131147
=== modified file 'src/provider/internal/Handler.cpp'
--- src/provider/internal/Handler.cpp 2016-07-20 02:20:53 +0000
+++ src/provider/internal/Handler.cpp 2016-09-09 02:13:43 +0000
@@ -17,20 +17,26 @@
17 */17 */
1818
19#include <unity/storage/provider/internal/Handler.h>19#include <unity/storage/provider/internal/Handler.h>
20
21#include <unity/storage/internal/dbus_error.h>
20#include <unity/storage/provider/internal/AccountData.h>22#include <unity/storage/provider/internal/AccountData.h>
23#include <unity/storage/provider/internal/dbusmarshal.h>
21#include <unity/storage/provider/internal/DBusPeerCache.h>24#include <unity/storage/provider/internal/DBusPeerCache.h>
22#include <unity/storage/provider/internal/MainLoopExecutor.h>25#include <unity/storage/provider/internal/MainLoopExecutor.h>
23#include <unity/storage/provider/ProviderBase.h>26#include <unity/storage/provider/ProviderBase.h>
27#include <unity/storage/provider/Exceptions.h>
28
29#pragma GCC diagnostic push
30#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
31#pragma GCC diagnostic ignored "-Wswitch-default"
32#include <QDebug>
33#pragma GCC diagnostic pop
2434
25#include <stdexcept>35#include <stdexcept>
2636
37using namespace unity::storage::internal;
27using namespace std;38using namespace std;
2839
29namespace
30{
31char const ERROR[] = "com.canonical.StorageFramework.Provider.Error";
32}
33
34namespace unity40namespace unity
35{41{
36namespace storage42namespace storage
@@ -53,7 +59,8 @@
53 auto peer_future = account_->dbus_peer().get(message_.service());59 auto peer_future = account_->dbus_peer().get(message_.service());
54 creds_future_ = peer_future.then(60 creds_future_ = peer_future.then(
55 EXEC_IN_MAIN61 EXEC_IN_MAIN
56 [this](decltype(peer_future) f) {62 [this](decltype(peer_future) f)
63 {
57 auto info = f.get();64 auto info = f.get();
58 if (info.valid)65 if (info.valid)
59 {66 {
@@ -64,8 +71,10 @@
64 }71 }
65 else72 else
66 {73 {
67 reply_ = message_.createErrorReply(74 string msg = "Handler::begin(): could not retrieve credentials";
68 ERROR, "Handler::begin(): could not retrieve credentials");75 qDebug() << QString::fromStdString(msg);
76 auto ep = make_exception_ptr(PermissionException(msg));
77 marshal_exception(ep);
69 QMetaObject::invokeMethod(this, "send_reply",78 QMetaObject::invokeMethod(this, "send_reply",
70 Qt::QueuedConnection);79 Qt::QueuedConnection);
71 }80 }
@@ -75,23 +84,29 @@
75void Handler::credentials_received()84void Handler::credentials_received()
76{85{
77 boost::future<QDBusMessage> msg_future;86 boost::future<QDBusMessage> msg_future;
78 try {87 try
88 {
79 msg_future = callback_(account_, context_, message_);89 msg_future = callback_(account_, context_, message_);
80 } catch (std::exception const& e) {90 }
81 reply_ = message_.createErrorReply(ERROR, e.what());91 catch (std::exception const& e)
92 {
93 qDebug() << "provider method threw an exception:" << e.what();
94 marshal_exception(current_exception());
82 QMetaObject::invokeMethod(this, "send_reply", Qt::QueuedConnection);95 QMetaObject::invokeMethod(this, "send_reply", Qt::QueuedConnection);
83 return;96 return;
84 }97 }
85 reply_future_ = msg_future.then(98 reply_future_ = msg_future.then(
86 EXEC_IN_MAIN99 EXEC_IN_MAIN
87 [this](decltype(msg_future) f) {100 [this](decltype(msg_future) f)
101 {
88 try102 try
89 {103 {
90 reply_ = f.get();104 reply_ = f.get();
91 }105 }
92 catch (std::exception const& e)106 catch (std::exception const& e)
93 {107 {
94 reply_ = message_.createErrorReply(ERROR, e.what());108 qDebug() << e.what();
109 marshal_exception(current_exception());
95 }110 }
96 QMetaObject::invokeMethod(this, "send_reply", Qt::QueuedConnection);111 QMetaObject::invokeMethod(this, "send_reply", Qt::QueuedConnection);
97 });112 });
@@ -103,6 +118,62 @@
103 Q_EMIT finished();118 Q_EMIT finished();
104}119}
105120
121void Handler::marshal_exception(exception_ptr ep)
122{
123 try
124 {
125 rethrow_exception(ep);
126 }
127 catch (StorageException const& e)
128 {
129 reply_ = message_.createErrorReply(QString(DBUS_ERROR_PREFIX) + QString::fromStdString(e.type()),
130 QString::fromStdString(e.error_message()));
131 try
132 {
133 throw;
134 }
135 catch (NotExistsException const& e)
136 {
137 reply_ << QVariant(QString::fromStdString(e.key()));
138 }
139 catch (ExistsException const& e)
140 {
141 reply_ << QVariant(QString::fromStdString(e.native_identity()));
142 reply_ << QVariant(QString::fromStdString(e.name()));
143 }
144 catch (ResourceException const& e)
145 {
146 qDebug() << e.what();
147 reply_ << QVariant(e.error_code());
148 }
149 catch (RemoteCommsException const& e)
150 {
151 qDebug() << e.what();
152 }
153 catch (UnknownException const& e)
154 {
155 qDebug() << e.what();
156 }
157 catch (StorageException const&)
158 {
159 // Some other sub-type of StorageException without additional data members,
160 // and we don't want to log this (not surprising) exception.
161 }
162 }
163 catch (std::exception const& e)
164 {
165 QString msg = QString("unknown exception thrown by provider: ") + e.what();
166 qDebug() << msg;
167 reply_ = message_.createErrorReply(QString(DBUS_ERROR_PREFIX) + "UnknownException", msg);
168 }
169 catch (...)
170 {
171 QString msg = "unknown exception thrown by provider";
172 qDebug() << msg;
173 reply_ = message_.createErrorReply(QString(DBUS_ERROR_PREFIX) + "UnknownException", msg);
174 }
175}
176
106}177}
107}178}
108}179}
109180
=== modified file 'src/provider/internal/MainLoopExecutor.cpp'
--- src/provider/internal/MainLoopExecutor.cpp 2016-07-19 03:29:15 +0000
+++ src/provider/internal/MainLoopExecutor.cpp 2016-09-09 02:13:43 +0000
@@ -23,8 +23,6 @@
2323
24#include <stdexcept>24#include <stdexcept>
2525
26#ifdef SF_SUPPORTS_EXECUTORS
27
28namespace {26namespace {
2927
30class WorkEvent : public QEvent {28class WorkEvent : public QEvent {
@@ -107,5 +105,3 @@
107}105}
108}106}
109}107}
110
111#endif /* SF_SUPPORTS_EXECUTORS */
112108
=== modified file 'src/provider/internal/PendingJobs.cpp'
--- src/provider/internal/PendingJobs.cpp 2016-07-19 03:26:36 +0000
+++ src/provider/internal/PendingJobs.cpp 2016-09-09 02:13:43 +0000
@@ -18,6 +18,7 @@
1818
19#include <unity/storage/provider/internal/PendingJobs.h>19#include <unity/storage/provider/internal/PendingJobs.h>
20#include <unity/storage/provider/DownloadJob.h>20#include <unity/storage/provider/DownloadJob.h>
21#include <unity/storage/provider/Exceptions.h>
21#include <unity/storage/provider/UploadJob.h>22#include <unity/storage/provider/UploadJob.h>
22#include <unity/storage/provider/internal/DownloadJobImpl.h>23#include <unity/storage/provider/internal/DownloadJobImpl.h>
23#include <unity/storage/provider/internal/MainLoopExecutor.h>24#include <unity/storage/provider/internal/MainLoopExecutor.h>
@@ -47,67 +48,79 @@
47 this, &PendingJobs::service_disconnected);48 this, &PendingJobs::service_disconnected);
48}49}
4950
50PendingJobs::~PendingJobs() = default;51PendingJobs::~PendingJobs()
52{
53 for (const auto& pair : downloads_)
54 {
55 cancel_job(pair.second, "download " + pair.second->download_id());
56 }
57 for (const auto& pair : uploads_)
58 {
59 cancel_job(pair.second, "upload " + pair.second->upload_id());
60 }
61}
5162
52void PendingJobs::add_download(unique_ptr<DownloadJob> &&job)63void PendingJobs::add_download(QString const& client_bus_name,
64 unique_ptr<DownloadJob> &&job)
53{65{
54 lock_guard<mutex> guard(lock_);66 lock_guard<mutex> guard(lock_);
5567
56 assert(!job->p_->sender_bus_name().empty());68 assert(!client_bus_name.isEmpty() && client_bus_name[0] == ':');
57 assert(downloads_.find(job->download_id()) == downloads_.end());69 const auto job_id = make_pair(client_bus_name, job->download_id());
70 assert(downloads_.find(job_id) == downloads_.end());
5871
59 shared_ptr<DownloadJob> j(std::move(job));72 shared_ptr<DownloadJob> j(std::move(job));
60 downloads_.emplace(j->download_id(), j);73 downloads_.emplace(job_id, j);
61 watch_peer(j->p_->sender_bus_name());74 watch_peer(client_bus_name);
62}75}
6376
64std::shared_ptr<DownloadJob> PendingJobs::get_download(std::string const& download_id)77shared_ptr<DownloadJob> PendingJobs::remove_download(QString const& client_bus_name,
65{78 string const& download_id)
66 lock_guard<mutex> guard(lock_);79{
6780 lock_guard<mutex> guard(lock_);
68 return downloads_.at(download_id);81
69}82 auto it = downloads_.find({client_bus_name, download_id});
7083 if (it == downloads_.cend())
71std::shared_ptr<DownloadJob> PendingJobs::remove_download(std::string const& download_id)84 {
72{85 throw LogicException("No such download: " + download_id);
73 lock_guard<mutex> guard(lock_);86 }
7487 auto job = it->second;
75 auto job = downloads_.at(download_id);88 downloads_.erase(it);
76 downloads_.erase(download_id);89 unwatch_peer(client_bus_name);
77 unwatch_peer(job->p_->sender_bus_name());
78 return job;90 return job;
79}91}
8092
81void PendingJobs::add_upload(unique_ptr<UploadJob> &&job)93void PendingJobs::add_upload(QString const& client_bus_name,
94 unique_ptr<UploadJob> &&job)
82{95{
83 lock_guard<mutex> guard(lock_);96 lock_guard<mutex> guard(lock_);
8497
85 assert(!job->p_->sender_bus_name().empty());98 assert(!client_bus_name.isEmpty() && client_bus_name[0] == ':');
86 assert(uploads_.find(job->upload_id()) == uploads_.end());99 const auto job_id = make_pair(client_bus_name, job->upload_id());
100 assert(uploads_.find(job_id) == uploads_.end());
87101
88 shared_ptr<UploadJob> j(std::move(job));102 shared_ptr<UploadJob> j(std::move(job));
89 uploads_.emplace(j->upload_id(), j);103 uploads_.emplace(job_id, j);
90 watch_peer(j->p_->sender_bus_name());104 watch_peer(client_bus_name);
91}105}
92106
93std::shared_ptr<UploadJob> PendingJobs::get_upload(std::string const& upload_id)107shared_ptr<UploadJob> PendingJobs::remove_upload(QString const& client_bus_name,
94{108 string const& upload_id)
95 lock_guard<mutex> guard(lock_);109{
96110 lock_guard<mutex> guard(lock_);
97 return uploads_.at(upload_id);111
98}112 auto it = uploads_.find({client_bus_name, upload_id});
99113 if (it == uploads_.cend())
100std::shared_ptr<UploadJob> PendingJobs::remove_upload(std::string const& upload_id)114 {
101{115 throw LogicException("No such upload: " + upload_id);
102 lock_guard<mutex> guard(lock_);116 }
103117 auto job = it->second;
104 auto job = uploads_.at(upload_id);118 uploads_.erase(it);
105 uploads_.erase(upload_id);119 unwatch_peer(client_bus_name);
106 unwatch_peer(job->p_->sender_bus_name());
107 return job;120 return job;
108}121}
109122
110void PendingJobs::watch_peer(string const& bus_name)123void PendingJobs::watch_peer(QString const& bus_name)
111{124{
112 auto it = services_.find(bus_name);125 auto it = services_.find(bus_name);
113 if (it != services_.end())126 if (it != services_.end())
@@ -116,12 +129,12 @@
116 }129 }
117 else130 else
118 {131 {
119 watcher_.addWatchedService(QString::fromStdString(bus_name));132 watcher_.addWatchedService(bus_name);
120 services_[bus_name] = 1;133 services_[bus_name] = 1;
121 }134 }
122}135}
123136
124void PendingJobs::unwatch_peer(string const& bus_name)137void PendingJobs::unwatch_peer(QString const& bus_name)
125{138{
126 auto it = services_.find(bus_name);139 auto it = services_.find(bus_name);
127 if (it == services_.end())140 if (it == services_.end())
@@ -132,72 +145,62 @@
132 if (it->second == 0)145 if (it->second == 0)
133 {146 {
134 services_.erase(it);147 services_.erase(it);
135 watcher_.removeWatchedService(QString::fromStdString(bus_name));148 watcher_.removeWatchedService(bus_name);
136 }149 }
137}150}
138151
139void PendingJobs::service_disconnected(QString const& service_name)152void PendingJobs::service_disconnected(QString const& service_name)
140{153{
141 lock_guard<mutex> guard(lock_);154 lock_guard<mutex> guard(lock_);
142 string const bus_name = service_name.toStdString();155
143156 services_.erase(service_name);
144 for (auto it = downloads_.cbegin(); it != downloads_.cend(); )157 watcher_.removeWatchedService(service_name);
145 {158
146 if (it->second->p_->sender_bus_name() == bus_name)159 const auto lower = make_pair(service_name, string());
147 {160
148 auto job = it->second;161 for (auto it = downloads_.lower_bound(lower);
149 it = downloads_.erase(it);162 it != downloads_.cend() && it->first.first == service_name; )
150 auto f = job->p_->cancel(*job);163 {
151 // This continuation also ensures that the job remains164 auto job = it->second;
152 // alive until the cancel method has completed.165 it = downloads_.erase(it);
153 f.then(166 cancel_job(job, "download " + job->download_id());
154 EXEC_IN_MAIN167 }
155 [job](decltype(f) f) {168
156 try169 for (auto it = uploads_.lower_bound(lower);
157 {170 it != uploads_.cend() && it->first.first == service_name; )
158 f.get();171 {
159 }172 auto job = it->second;
160 catch (std::exception const& e)173 it = uploads_.erase(it);
161 {174 cancel_job(job, "upload " + job->upload_id());
162 fprintf(stderr, "Error cancelling download job '%s': %s\n",175 }
163 job->download_id().c_str(), e.what());176}
164 }177
165 });178template<typename Job>
166 }179void PendingJobs::cancel_job(shared_ptr<Job> const& job, string const& identifier)
167 else180{
168 {181 auto f = job->p_->cancel(*job);
169 ++it;182 // This continuation also ensures that the job remains
170 }183 // alive until the cancel method has completed.
171 }184 auto cancel_future = std::make_shared<boost::future<void>>();
172185 *cancel_future = f.then(
173 for (auto it = uploads_.cbegin(); it != uploads_.cend(); )186 EXEC_IN_MAIN
174 {187 [job, identifier, cancel_future](decltype(f) f) {
175 if (it->second->p_->sender_bus_name() == bus_name)188 try
176 {189 {
177 auto job = it->second;190 f.get();
178 it = uploads_.erase(it);191 }
179 auto f = job->p_->cancel(*job);192 catch (std::exception const& e)
180 // This continuation also ensures that the job remains193 {
181 // alive until the cancel method has completed.194 fprintf(stderr, "Error cancelling job '%s': %s\n",
182 f.then(195 identifier.c_str(), e.what());
183 EXEC_IN_MAIN196 }
184 [job](decltype(f) f) {197
185 try198 // Break the reference cycle between the continuation
186 {199 // future and closure, while making sure the future
187 f.get();200 // survives long enough to be marked ready.
188 }201 auto fut = std::make_shared<boost::future<void>>(std::move(*cancel_future));
189 catch (std::exception const& e)202 MainLoopExecutor::instance().submit([fut]{});
190 {203 });
191 fprintf(stderr, "Error cancelling upload job '%s': %s\n",
192 job->upload_id().c_str(), e.what());
193 }
194 });
195 }
196 else
197 {
198 ++it;
199 }
200 }
201}204}
202205
203}206}
204207
=== modified file 'src/provider/internal/ProviderInterface.cpp'
--- src/provider/internal/ProviderInterface.cpp 2016-07-21 12:48:40 +0000
+++ src/provider/internal/ProviderInterface.cpp 2016-09-09 02:13:43 +0000
@@ -18,6 +18,7 @@
1818
19#include <unity/storage/provider/internal/ProviderInterface.h>19#include <unity/storage/provider/internal/ProviderInterface.h>
20#include <unity/storage/provider/DownloadJob.h>20#include <unity/storage/provider/DownloadJob.h>
21#include <unity/storage/provider/Exceptions.h>
21#include <unity/storage/provider/ProviderBase.h>22#include <unity/storage/provider/ProviderBase.h>
22#include <unity/storage/provider/UploadJob.h>23#include <unity/storage/provider/UploadJob.h>
23#include <unity/storage/provider/internal/AccountData.h>24#include <unity/storage/provider/internal/AccountData.h>
@@ -171,15 +172,13 @@
171 EXEC_IN_MAIN172 EXEC_IN_MAIN
172 [account, message](decltype(f) f) -> QDBusMessage {173 [account, message](decltype(f) f) -> QDBusMessage {
173 auto job = f.get();174 auto job = f.get();
174 job->p_->set_sender_bus_name(message.service().toStdString());
175
176 auto upload_id = QString::fromStdString(job->upload_id());175 auto upload_id = QString::fromStdString(job->upload_id());
177 QDBusUnixFileDescriptor file_desc;176 QDBusUnixFileDescriptor file_desc;
178 int fd = job->p_->take_write_socket();177 int fd = job->p_->take_write_socket();
179 file_desc.setFileDescriptor(fd);178 file_desc.setFileDescriptor(fd);
180 close(fd);179 close(fd);
181180
182 account->jobs().add_upload(std::move(job));181 account->jobs().add_upload(message.service(), std::move(job));
183 return message.createReply({182 return message.createReply({
184 QVariant(upload_id),183 QVariant(upload_id),
185 QVariant::fromValue(file_desc),184 QVariant::fromValue(file_desc),
@@ -198,15 +197,13 @@
198 EXEC_IN_MAIN197 EXEC_IN_MAIN
199 [account, message](decltype(f) f) -> QDBusMessage {198 [account, message](decltype(f) f) -> QDBusMessage {
200 auto job = f.get();199 auto job = f.get();
201 job->p_->set_sender_bus_name(message.service().toStdString());
202
203 auto upload_id = QString::fromStdString(job->upload_id());200 auto upload_id = QString::fromStdString(job->upload_id());
204 QDBusUnixFileDescriptor file_desc;201 QDBusUnixFileDescriptor file_desc;
205 int fd = job->p_->take_write_socket();202 int fd = job->p_->take_write_socket();
206 file_desc.setFileDescriptor(fd);203 file_desc.setFileDescriptor(fd);
207 close(fd);204 close(fd);
208205
209 account->jobs().add_upload(std::move(job));206 account->jobs().add_upload(message.service(), std::move(job));
210 return message.createReply({207 return message.createReply({
211 QVariant(upload_id),208 QVariant(upload_id),
212 QVariant::fromValue(file_desc),209 QVariant::fromValue(file_desc),
@@ -219,15 +216,10 @@
219ProviderInterface::IMD ProviderInterface::FinishUpload(QString const& upload_id)216ProviderInterface::IMD ProviderInterface::FinishUpload(QString const& upload_id)
220{217{
221 queue_request([upload_id](shared_ptr<AccountData> const& account, Context const& /*ctx*/, QDBusMessage const& message) {218 queue_request([upload_id](shared_ptr<AccountData> const& account, Context const& /*ctx*/, QDBusMessage const& message) {
222 // Throws if job is not available
223 auto job = account->jobs().get_upload(upload_id.toStdString());
224 if (job->p_->sender_bus_name() != message.service().toStdString())
225 {
226 throw runtime_error("Upload job belongs to a different client");
227 }
228 // FIXME: removing the job at this point means we can't219 // FIXME: removing the job at this point means we can't
229 // cancel during finish().220 // cancel during finish().
230 account->jobs().remove_upload(upload_id.toStdString());221 // Throws if job is not available
222 auto job = account->jobs().remove_upload(message.service(), upload_id.toStdString());
231 auto f = job->p_->finish(*job);223 auto f = job->p_->finish(*job);
232 return f.then(224 return f.then(
233 EXEC_IN_MAIN225 EXEC_IN_MAIN
@@ -243,12 +235,7 @@
243{235{
244 queue_request([upload_id](shared_ptr<AccountData> const& account, Context const& /*ctx*/, QDBusMessage const& message) {236 queue_request([upload_id](shared_ptr<AccountData> const& account, Context const& /*ctx*/, QDBusMessage const& message) {
245 // Throws if job is not available237 // Throws if job is not available
246 auto job = account->jobs().get_upload(upload_id.toStdString());238 auto job = account->jobs().remove_upload(message.service(), upload_id.toStdString());
247 if (job->p_->sender_bus_name() != message.service().toStdString())
248 {
249 throw runtime_error("Upload job belongs to a different client");
250 }
251 account->jobs().remove_upload(upload_id.toStdString());
252 auto f = job->p_->cancel(*job);239 auto f = job->p_->cancel(*job);
253 return f.then(240 return f.then(
254 EXEC_IN_MAIN241 EXEC_IN_MAIN
@@ -268,15 +255,13 @@
268 EXEC_IN_MAIN255 EXEC_IN_MAIN
269 [account, message](decltype(f) f) -> QDBusMessage {256 [account, message](decltype(f) f) -> QDBusMessage {
270 auto job = f.get();257 auto job = f.get();
271 job->p_->set_sender_bus_name(message.service().toStdString());
272
273 auto download_id = QString::fromStdString(job->download_id());258 auto download_id = QString::fromStdString(job->download_id());
274 QDBusUnixFileDescriptor file_desc;259 QDBusUnixFileDescriptor file_desc;
275 int fd = job->p_->take_read_socket();260 int fd = job->p_->take_read_socket();
276 file_desc.setFileDescriptor(fd);261 file_desc.setFileDescriptor(fd);
277 close(fd);262 close(fd);
278263
279 account->jobs().add_download(std::move(job));264 account->jobs().add_download(message.service(), std::move(job));
280 return message.createReply({265 return message.createReply({
281 QVariant(download_id),266 QVariant(download_id),
282 QVariant::fromValue(file_desc),267 QVariant::fromValue(file_desc),
@@ -289,15 +274,10 @@
289void ProviderInterface::FinishDownload(QString const& download_id)274void ProviderInterface::FinishDownload(QString const& download_id)
290{275{
291 queue_request([download_id](shared_ptr<AccountData> const& account, Context const& /*ctx*/, QDBusMessage const& message) {276 queue_request([download_id](shared_ptr<AccountData> const& account, Context const& /*ctx*/, QDBusMessage const& message) {
292 // Throws if job is not available
293 auto job = account->jobs().get_download(download_id.toStdString());
294 if (job->p_->sender_bus_name() != message.service().toStdString())
295 {
296 throw runtime_error("Download job belongs to a different client");
297 }
298 // FIXME: removing the job at this point means we can't277 // FIXME: removing the job at this point means we can't
299 // cancel during finish().278 // cancel during finish().
300 account->jobs().remove_download(download_id.toStdString());279 // Throws if job is not available
280 auto job = account->jobs().remove_download(message.service(), download_id.toStdString());
301 auto f = job->p_->finish(*job);281 auto f = job->p_->finish(*job);
302 return f.then(282 return f.then(
303 EXEC_IN_MAIN283 EXEC_IN_MAIN
304284
=== modified file 'src/provider/internal/ServerImpl.cpp'
--- src/provider/internal/ServerImpl.cpp 2016-07-21 04:00:29 +0000
+++ src/provider/internal/ServerImpl.cpp 2016-09-09 02:13:43 +0000
@@ -17,6 +17,7 @@
17 */17 */
1818
19#include <unity/storage/provider/internal/ServerImpl.h>19#include <unity/storage/provider/internal/ServerImpl.h>
20#include <unity/storage/provider/Exceptions.h>
20#include <unity/storage/provider/ProviderBase.h>21#include <unity/storage/provider/ProviderBase.h>
21#include <unity/storage/provider/internal/AccountData.h>22#include <unity/storage/provider/internal/AccountData.h>
22#include <unity/storage/provider/internal/MainLoopExecutor.h>23#include <unity/storage/provider/internal/MainLoopExecutor.h>
@@ -37,7 +38,10 @@
37{38{
3839
39ServerImpl::ServerImpl(ServerBase* server, string const& bus_name, string const& account_service_id)40ServerImpl::ServerImpl(ServerBase* server, string const& bus_name, string const& account_service_id)
40 : server_(server), bus_name_(bus_name), service_id_(account_service_id)41 : server_(server)
42 , bus_name_(bus_name)
43 , service_id_(account_service_id)
44 , trace_message_handler_("storage_provider")
41{45{
42 qDBusRegisterMetaType<Item>();46 qDBusRegisterMetaType<Item>();
43 qDBusRegisterMetaType<std::vector<Item>>();47 qDBusRegisterMetaType<std::vector<Item>>();
@@ -85,7 +89,8 @@
8589
86 if (!bus.registerService(QString::fromStdString(bus_name_)))90 if (!bus.registerService(QString::fromStdString(bus_name_)))
87 {91 {
88 throw runtime_error("Could not acquire bus name: " + bus_name_);92 string msg = string("Could not acquire bus name: ") + bus_name_ + ": " + bus.lastError().message().toStdString();
93 throw ResourceException(msg, int(bus.lastError().type()));
89 }94 }
90 // TODO: claim bus name95 // TODO: claim bus name
91 qDebug() << "Bus unique name:" << bus.baseService();96 qDebug() << "Bus unique name:" << bus.baseService();
9297
=== modified file 'src/provider/internal/TempfileUploadJobImpl.cpp'
--- src/provider/internal/TempfileUploadJobImpl.cpp 2016-07-12 02:22:05 +0000
+++ src/provider/internal/TempfileUploadJobImpl.cpp 2016-09-09 02:13:43 +0000
@@ -17,9 +17,10 @@
17 */17 */
1818
19#include <unity/storage/provider/internal/TempfileUploadJobImpl.h>19#include <unity/storage/provider/internal/TempfileUploadJobImpl.h>
20#include <unity/storage/provider/Exceptions.h>
2021
21#include <cassert>22#include <cassert>
22#include <stdexcept>23#include <exception>
2324
24using namespace std;25using namespace std;
2526
@@ -64,6 +65,25 @@
64 return tmpfile_->fileName().toStdString();65 return tmpfile_->fileName().toStdString();
65}66}
6667
68void TempfileUploadJobImpl::drain()
69{
70 while (true)
71 {
72 if (!tmpfile_->isOpen())
73 {
74 break;
75 }
76 if (!reader_->waitForReadyRead(0))
77 {
78 // Nothing was available to read: is the read channel still open?
79 if (tmpfile_->isOpen())
80 {
81 throw LogicException("Socket not closed");
82 }
83 }
84 }
85}
86
67void TempfileUploadJobImpl::on_ready_read()87void TempfileUploadJobImpl::on_ready_read()
68{88{
69 char buffer[4096];89 char buffer[4096];
7090
=== added file 'src/provider/internal/TestServerImpl.cpp'
--- src/provider/internal/TestServerImpl.cpp 1970-01-01 00:00:00 +0000
+++ src/provider/internal/TestServerImpl.cpp 2016-09-09 02:13:43 +0000
@@ -0,0 +1,84 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: James Henstridge <james.henstridge@canonical.com>
17 */
18
19#include <unity/storage/provider/internal/TestServerImpl.h>
20#include <unity/storage/provider/Exceptions.h>
21#include <unity/storage/provider/ProviderBase.h>
22#include <unity/storage/provider/internal/AccountData.h>
23#include <unity/storage/provider/internal/DBusPeerCache.h>
24#include <unity/storage/provider/internal/ProviderInterface.h>
25#include <unity/storage/provider/internal/dbusmarshal.h>
26#include "provideradaptor.h"
27
28#include <OnlineAccounts/Account>
29
30#include <stdexcept>
31
32using namespace std;
33
34namespace unity
35{
36namespace storage
37{
38namespace provider
39{
40namespace internal
41{
42
43TestServerImpl::TestServerImpl(unique_ptr<ProviderBase>&& provider,
44 OnlineAccounts::Account* account,
45 QDBusConnection const& connection,
46 string const& object_path)
47 : connection_(connection), object_path_(object_path)
48{
49 qDBusRegisterMetaType<Item>();
50 qDBusRegisterMetaType<std::vector<Item>>();
51
52 auto peer_cache = make_shared<DBusPeerCache>(connection_);
53 auto account_data = make_shared<AccountData>(
54 move(provider), peer_cache, connection_, account);
55 interface_.reset(new ProviderInterface(account_data));
56 new ProviderAdaptor(interface_.get());
57
58 if (!connection_.registerObject(QString::fromStdString(object_path_),
59 interface_.get()))
60 {
61 string msg = "Could not register provider on connection: " + connection_.lastError().message().toStdString();
62 throw ResourceException(msg, int(connection_.lastError().type()));
63 }
64}
65
66TestServerImpl::~TestServerImpl()
67{
68 connection_.unregisterObject(QString::fromStdString(object_path_));
69}
70
71QDBusConnection const& TestServerImpl::connection() const
72{
73 return connection_;
74}
75
76string const& TestServerImpl::object_path() const
77{
78 return object_path_;
79}
80
81}
82}
83}
84}
085
=== modified file 'src/provider/internal/UploadJobImpl.cpp'
--- src/provider/internal/UploadJobImpl.cpp 2016-07-12 02:22:05 +0000
+++ src/provider/internal/UploadJobImpl.cpp 2016-09-09 02:13:43 +0000
@@ -17,7 +17,10 @@
17 */17 */
1818
19#include <unity/storage/provider/internal/UploadJobImpl.h>19#include <unity/storage/provider/internal/UploadJobImpl.h>
20#include <unity/storage/internal/safe_strerror.h>
21#include <unity/storage/provider/Exceptions.h>
20#include <unity/storage/provider/UploadJob.h>22#include <unity/storage/provider/UploadJob.h>
23#include <unity/storage/provider/internal/MainLoopExecutor.h>
2124
22#include <sys/socket.h>25#include <sys/socket.h>
23#include <sys/types.h>26#include <sys/types.h>
@@ -26,6 +29,7 @@
26#include <stdexcept>29#include <stdexcept>
2730
28using namespace std;31using namespace std;
32using namespace unity::storage::internal;
2933
30namespace unity34namespace unity
31{35{
@@ -42,18 +46,30 @@
42 int socks[2];46 int socks[2];
43 if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) < 0)47 if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) < 0)
44 {48 {
45 throw runtime_error("could not create socketpair");49 int error_code = errno;
50 string msg = "could not create socketpair: " + safe_strerror(error_code);
51 throw ResourceException(msg, error_code);
46 }52 }
47 read_socket_ = socks[0];53 read_socket_ = socks[0];
48 write_socket_ = socks[1];54 write_socket_ = socks[1];
55
56#if 0
57 // TODO: We should be able to half-close the write channel of the read socket, and the read channel of
58 // the write socket. But, if we do, QLocalSocket indicates that everything was closed, which causes
59 // failures on the client side. We suspect a QLocalSocket bug -- need to investigate.
49 if (shutdown(read_socket_, SHUT_WR) < 0)60 if (shutdown(read_socket_, SHUT_WR) < 0)
50 {61 {
51 throw runtime_error("Could not shut down write channel on read socket");62 int error_code = errno;
63 string msg = "could not shut down write channel on read socket: " + safe_strerror(error_code);
64 throw ResourceException(msg, error_code);
52 }65 }
53 if (shutdown(write_socket_, SHUT_RD) < 0)66 if (shutdown(write_socket_, SHUT_RD) < 0)
54 {67 {
55 throw runtime_error("Could not shut down read channel on write socket");68 int error_code = errno;
69 string msg = "Could not shut down read channel on write socket" + safe_strerror(error_code);
70 throw ResourceException(msg, error_code);
56 }71 }
72#endif
57}73}
5874
59UploadJobImpl::~UploadJobImpl()75UploadJobImpl::~UploadJobImpl()
@@ -72,7 +88,7 @@
72{88{
73}89}
7490
75std::string const& UploadJobImpl::upload_id() const91string const& UploadJobImpl::upload_id() const
76{92{
77 return upload_id_;93 return upload_id_;
78}94}
@@ -90,28 +106,29 @@
90 return sock;106 return sock;
91}107}
92108
93string const& UploadJobImpl::sender_bus_name() const109void UploadJobImpl::report_error(exception_ptr p)
94{
95 return sender_bus_name_;
96}
97
98void UploadJobImpl::set_sender_bus_name(string const& bus_name)
99{
100 assert(bus_name[0] == ':');
101 sender_bus_name_ = bus_name;
102}
103
104void UploadJobImpl::report_error(std::exception_ptr p)
105{110{
106 if (read_socket_ >= 0)111 if (read_socket_ >= 0)
107 {112 {
108 close(write_socket_);113 close(read_socket_);
109 read_socket_ = -1;114 read_socket_ = -1;
110 }115 }
111116
112 lock_guard<mutex> guard(completion_lock_);117 lock_guard<mutex> guard(completion_lock_);
113 completed_ = true;118 completed_ = true;
114 completion_promise_.set_exception(p);119 // Convert std::exception_ptr to boost::exception_ptr
120 try
121 {
122 rethrow_exception(p);
123 }
124 catch (StorageException const& e)
125 {
126 completion_promise_.set_exception(e);
127 }
128 catch (...)
129 {
130 completion_promise_.set_exception(boost::current_exception());
131 }
115}132}
116133
117boost::future<Item> UploadJobImpl::finish(UploadJob& job)134boost::future<Item> UploadJobImpl::finish(UploadJob& job)
118135
=== modified file 'src/provider/internal/dbusmarshal.cpp'
--- src/provider/internal/dbusmarshal.cpp 2016-07-21 12:48:40 +0000
+++ src/provider/internal/dbusmarshal.cpp 2016-09-09 02:13:43 +0000
@@ -31,29 +31,57 @@
31namespace provider31namespace provider
32{32{
3333
34namespace
35{
36
37QDBusVariant to_qdbus_variant(MetadataValue const& v)
38{
39 switch (v.which())
40 {
41 case 0:
42 return QDBusVariant(QString::fromStdString(boost::get<string>(v)));
43 case 1:
44 return QDBusVariant(qlonglong(boost::get<int64_t>(v)));
45 default:
46 abort(); // Impossible. // LCOV_EXCL_LINE
47 }
48}
49
50} // namespace
51
34QDBusArgument& operator<<(QDBusArgument& argument, Item const& item)52QDBusArgument& operator<<(QDBusArgument& argument, Item const& item)
35{53{
36 argument.beginStructure();54 argument.beginStructure();
37 argument << QString::fromStdString(item.item_id);55 argument << QString::fromStdString(item.item_id);
38 argument << QString::fromStdString(item.parent_id);56 {
57 argument.beginArray(qMetaTypeId<QString>());
58 for (auto const& id : item.parent_ids)
59 {
60 argument << QString::fromStdString(id);
61 }
62 argument.endArray();
63 }
39 argument << QString::fromStdString(item.name);64 argument << QString::fromStdString(item.name);
40 argument << QString::fromStdString(item.etag);65 argument << QString::fromStdString(item.etag);
41 argument << static_cast<int32_t>(item.type);66 argument << static_cast<int32_t>(item.type);
42 argument.beginMap(QVariant::String, qMetaTypeId<QDBusVariant>());
43 for (auto const& pair : item.metadata)
44 {67 {
45 argument.beginMapEntry();68 argument.beginMap(QVariant::String, qMetaTypeId<QDBusVariant>());
46 argument << QString::fromStdString(pair.first) << QDBusVariant(QString::fromStdString(pair.second));69 for (auto const& pair : item.metadata)
47 argument.endMapEntry();70 {
71 argument.beginMapEntry();
72 argument << QString::fromStdString(pair.first) << to_qdbus_variant(pair.second);
73 argument.endMapEntry();
74 }
75 argument.endMap();
48 }76 }
49 argument.endMap();
50 argument.endStructure();77 argument.endStructure();
51 return argument;78 return argument;
52}79}
5380
54QDBusArgument const& operator>>(QDBusArgument const&, Item&)81QDBusArgument const& operator>>(QDBusArgument const&, Item&)
55{82{
56 throw std::runtime_error("Item decode not implemented");83 // We don't expect to ever have to unmarshal anything, only marshal it.
84 qFatal("unexpected call to operator>>(QDBusArgument const&, Item&)"); // LCOV_EXCL_LINE
57}85}
5886
59QDBusArgument& operator<<(QDBusArgument& argument, ItemList const& items)87QDBusArgument& operator<<(QDBusArgument& argument, ItemList const& items)
@@ -69,7 +97,8 @@
6997
70QDBusArgument const& operator>>(QDBusArgument const&, ItemList&)98QDBusArgument const& operator>>(QDBusArgument const&, ItemList&)
71{99{
72 throw std::runtime_error("std::vector<Item> decode not implemented");100 // We don't expect to ever have to unmarshal anything, only marshal it.
101 qFatal("unexpected call to operator>>(QDBusArgument const&, ItemList&)"); // LCOV_EXCL_LINE
73}102}
74103
75}104}
76105
=== added directory 'src/provider/testing'
=== added file 'src/provider/testing/TestServer.cpp'
--- src/provider/testing/TestServer.cpp 1970-01-01 00:00:00 +0000
+++ src/provider/testing/TestServer.cpp 2016-09-09 02:13:43 +0000
@@ -0,0 +1,60 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: James Henstridge <james.henstridge@canonical.com>
17 */
18
19#include <unity/storage/provider/testing/TestServer.h>
20#include <unity/storage/provider/internal/TestServerImpl.h>
21#include <unity/storage/provider/ProviderBase.h>
22
23#include <OnlineAccounts/Account>
24
25using namespace std;
26
27namespace unity
28{
29namespace storage
30{
31namespace provider
32{
33namespace testing
34{
35
36TestServer::TestServer(unique_ptr<ProviderBase>&& provider,
37 OnlineAccounts::Account* account,
38 QDBusConnection const& connection,
39 string const& object_path)
40 : p_(new internal::TestServerImpl(move(provider), account,
41 connection, object_path))
42{
43}
44
45TestServer::~TestServer() = default;
46
47QDBusConnection const& TestServer::connection() const
48{
49 return p_->connection();
50}
51
52string const& TestServer::object_path() const
53{
54 return p_->object_path();
55}
56
57}
58}
59}
60}
061
=== modified file 'src/qt/client/Account.cpp'
--- src/qt/client/Account.cpp 2016-07-12 02:22:05 +0000
+++ src/qt/client/Account.cpp 2016-09-09 02:13:43 +0000
@@ -41,7 +41,7 @@
4141
42Account::~Account() = default;42Account::~Account() = default;
4343
44Runtime* Account::runtime() const44shared_ptr<Runtime> Account::runtime() const
45{45{
46 return p_->runtime();46 return p_->runtime();
47}47}
4848
=== modified file 'src/qt/client/CMakeLists.txt'
--- src/qt/client/CMakeLists.txt 2016-07-27 02:19:17 +0000
+++ src/qt/client/CMakeLists.txt 2016-09-09 02:13:43 +0000
@@ -80,7 +80,7 @@
80# Build the remote client library80# Build the remote client library
81set_source_files_properties(${CMAKE_SOURCE_DIR}/data/provider.xml PROPERTIES81set_source_files_properties(${CMAKE_SOURCE_DIR}/data/provider.xml PROPERTIES
82 CLASSNAME ProviderInterface82 CLASSNAME ProviderInterface
83 INCLUDE unity/storage/qt/client/internal/remote_client/dbusmarshal.h83 INCLUDE unity/storage/internal/dbusmarshal.h
84)84)
8585
86qt5_add_dbus_interface(generated_files86qt5_add_dbus_interface(generated_files
@@ -109,6 +109,7 @@
109 VERSION ${SF_CLIENT_LIBVERSION}109 VERSION ${SF_CLIENT_LIBVERSION}
110)110)
111target_link_libraries(storage-framework-qt-client111target_link_libraries(storage-framework-qt-client
112 storage-framework-common-internal
112 Qt5::Concurrent113 Qt5::Concurrent
113 Qt5::Core114 Qt5::Core
114 Qt5::DBus115 Qt5::DBus
115116
=== modified file 'src/qt/client/Exceptions.cpp'
--- src/qt/client/Exceptions.cpp 2016-07-22 01:45:39 +0000
+++ src/qt/client/Exceptions.cpp 2016-09-09 02:13:43 +0000
@@ -42,6 +42,11 @@
42 return what_string_.c_str();42 return what_string_.c_str();
43}43}
4444
45QString StorageException::error_message() const
46{
47 return error_message_;
48}
49
45LocalCommsException::LocalCommsException(QString const& error_message)50LocalCommsException::LocalCommsException(QString const& error_message)
46 : StorageException("LocalCommsException", error_message)51 : StorageException("LocalCommsException", error_message)
47{52{
@@ -76,10 +81,9 @@
76 throw *this;81 throw *this;
77}82}
7883
79DeletedException::DeletedException(QString const& error_message, QString const& identity, QString const& name)84DeletedException::DeletedException(QString const& error_message, QString const& identity)
80 : StorageException("DeletedException", error_message)85 : StorageException("DeletedException", error_message)
81 , identity_(identity)86 , identity_(identity)
82 , name_(name)
83{87{
84}88}
8589
@@ -100,13 +104,8 @@
100 return identity_;104 return identity_;
101}105}
102106
103QString DeletedException::name() const
104{
105 return name_;
106}
107
108RuntimeDestroyedException::RuntimeDestroyedException(QString const& method)107RuntimeDestroyedException::RuntimeDestroyedException(QString const& method)
109 : StorageException("RuntimeDestroyedException", method + ": Runtime was destroyed previously")108 : StorageException("RuntimeDestroyedException", method + ": runtime was destroyed previously")
110{109{
111}110}
112111
@@ -276,8 +275,9 @@
276 throw *this;275 throw *this;
277}276}
278277
279ResourceException::ResourceException(QString const& error_message)278ResourceException::ResourceException(QString const& error_message, int error_code)
280 : StorageException("ResourceException", error_message)279 : StorageException("ResourceException", error_message)
280 , error_code_(error_code)
281{281{
282}282}
283283
@@ -293,6 +293,11 @@
293 throw *this;293 throw *this;
294}294}
295295
296int ResourceException::error_code() const noexcept
297{
298 return error_code_;
299}
300
296} // namespace client301} // namespace client
297} // namespace qt302} // namespace qt
298} // namespace storage303} // namespace storage
299304
=== modified file 'src/qt/client/Item.cpp'
--- src/qt/client/Item.cpp 2016-07-14 00:25:40 +0000
+++ src/qt/client/Item.cpp 2016-09-09 02:13:43 +0000
@@ -51,7 +51,7 @@
51 return p_->name();51 return p_->name();
52}52}
5353
54Root* Item::root() const54shared_ptr<Root> Item::root() const
55{55{
56 return p_->root();56 return p_->root();
57}57}
5858
=== modified file 'src/qt/client/Root.cpp'
--- src/qt/client/Root.cpp 2016-07-12 02:22:05 +0000
+++ src/qt/client/Root.cpp 2016-09-09 02:13:43 +0000
@@ -30,6 +30,7 @@
30{30{
3131
32using namespace internal;32using namespace internal;
33using namespace std;
3334
34Root::Root(RootBase* p)35Root::Root(RootBase* p)
35 : Folder(p)36 : Folder(p)
@@ -38,7 +39,7 @@
3839
39Root::~Root() = default;40Root::~Root() = default;
4041
41Account* Root::account() const42shared_ptr<Account> Root::account() const
42{43{
43 return dynamic_cast<RootBase*>(p_.get())->account();44 return dynamic_cast<RootBase*>(p_.get())->account();
44}45}
4546
=== modified file 'src/qt/client/Runtime.cpp'
--- src/qt/client/Runtime.cpp 2016-07-21 04:00:29 +0000
+++ src/qt/client/Runtime.cpp 2016-09-09 02:13:43 +0000
@@ -64,6 +64,12 @@
64 return p_->accounts();64 return p_->accounts();
65}65}
6666
67shared_ptr<Account> Runtime::make_test_account(QString const& bus_name,
68 QString const& object_path)
69{
70 return p_->make_test_account(bus_name, object_path);
71}
72
67} // namespace client73} // namespace client
68} // namespace qt74} // namespace qt
69} // namespace storage75} // namespace storage
7076
=== modified file 'src/qt/client/Uploader.cpp'
--- src/qt/client/Uploader.cpp 2016-07-12 02:22:05 +0000
+++ src/qt/client/Uploader.cpp 2016-09-09 02:13:43 +0000
@@ -46,6 +46,11 @@
46 return p_->socket();46 return p_->socket();
47}47}
4848
49int64_t Uploader::size() const
50{
51 return p_->size();
52}
53
49QFuture<shared_ptr<File>> Uploader::finish_upload()54QFuture<shared_ptr<File>> Uploader::finish_upload()
50{55{
51 return p_->finish_upload();56 return p_->finish_upload();
5257
=== modified file 'src/qt/client/internal/AccountBase.cpp'
--- src/qt/client/internal/AccountBase.cpp 2016-07-14 04:50:36 +0000
+++ src/qt/client/internal/AccountBase.cpp 2016-09-09 02:13:43 +0000
@@ -19,6 +19,8 @@
19#include <unity/storage/qt/client/internal/AccountBase.h>19#include <unity/storage/qt/client/internal/AccountBase.h>
2020
21#include <unity/storage/qt/client/Exceptions.h>21#include <unity/storage/qt/client/Exceptions.h>
22#include <unity/storage/qt/client/internal/RuntimeBase.h>
23#include <unity/storage/qt/client/Runtime.h>
2224
23#include <cassert>25#include <cassert>
2426
@@ -42,13 +44,18 @@
42 assert(runtime.lock());44 assert(runtime.lock());
43}45}
4446
45Runtime* AccountBase::runtime() const47shared_ptr<Runtime> AccountBase::runtime() const
46{48{
47 if (auto runtime = runtime_.lock())49 if (auto runtime = runtime_.lock())
48 {50 {
49 return runtime.get();51 auto runtime_base = runtime->p_;
52 if (runtime_base->destroyed_)
53 {
54 throw RuntimeDestroyedException("Account::runtime()");
55 }
56 return runtime;
50 }57 }
51 throw RuntimeDestroyedException("AccountBase::runtime()");58 throw RuntimeDestroyedException("Account::runtime()");
52}59}
5360
54void AccountBase::set_public_instance(weak_ptr<Account> const& p)61void AccountBase::set_public_instance(weak_ptr<Account> const& p)
5562
=== modified file 'src/qt/client/internal/ItemBase.cpp'
--- src/qt/client/internal/ItemBase.cpp 2016-07-14 04:50:36 +0000
+++ src/qt/client/internal/ItemBase.cpp 2016-09-09 02:13:43 +0000
@@ -18,7 +18,9 @@
1818
19#include <unity/storage/qt/client/internal/ItemBase.h>19#include <unity/storage/qt/client/internal/ItemBase.h>
2020
21#include <unity/storage/qt/client/Account.h>
21#include <unity/storage/qt/client/Exceptions.h>22#include <unity/storage/qt/client/Exceptions.h>
23#include <unity/storage/qt/client/Root.h>
2224
23#include <cassert>25#include <cassert>
2426
@@ -46,21 +48,24 @@
4648
47QString ItemBase::native_identity() const49QString ItemBase::native_identity() const
48{50{
51 throw_if_destroyed("Item::native_identity()");
49 return identity_;52 return identity_;
50}53}
5154
52ItemType ItemBase::type() const55ItemType ItemBase::type() const
53{56{
57 throw_if_destroyed("Item::type()");
54 return type_;58 return type_;
55}59}
5660
57Root* ItemBase::root() const61shared_ptr<Root> ItemBase::root() const
58{62{
59 if (auto r = root_.lock())63 auto root = get_root();
64 if (!root)
60 {65 {
61 return r.get();66 throw RuntimeDestroyedException("Item::root()");
62 }67 }
63 throw RuntimeDestroyedException("Item::root()");68 return root;
64}69}
6570
66void ItemBase::set_root(std::weak_ptr<Root> root)71void ItemBase::set_root(std::weak_ptr<Root> root)
@@ -75,6 +80,36 @@
75 public_instance_ = p;80 public_instance_ = p;
76}81}
7782
83shared_ptr<Root> ItemBase::get_root() const noexcept
84{
85 try
86 {
87 auto root = root_.lock();
88 if (root)
89 {
90 root->account(); // Throws if either account or runtime has been destroyed.
91 return root;
92 }
93 }
94 catch (RuntimeDestroyedException const&)
95 {
96 }
97 return nullptr;
98}
99
100void ItemBase::throw_if_destroyed(QString const& method) const
101{
102 if (deleted_)
103 {
104 QString msg = method + ": \"" + identity_ + "\" was deleted previously";
105 throw DeletedException(msg, identity_);
106 }
107 if (!get_root())
108 {
109 throw RuntimeDestroyedException(method);
110 }
111}
112
78} // namespace internal113} // namespace internal
79} // namespace client114} // namespace client
80} // namespace qt115} // namespace qt
81116
=== modified file 'src/qt/client/internal/RootBase.cpp'
--- src/qt/client/internal/RootBase.cpp 2016-07-27 02:19:17 +0000
+++ src/qt/client/internal/RootBase.cpp 2016-09-09 02:13:43 +0000
@@ -18,6 +18,7 @@
1818
19#include <unity/storage/qt/client/internal/RootBase.h>19#include <unity/storage/qt/client/internal/RootBase.h>
2020
21#include <unity/storage/qt/client/Account.h>
21#include <unity/storage/qt/client/Exceptions.h>22#include <unity/storage/qt/client/Exceptions.h>
2223
23#include <cassert>24#include <cassert>
@@ -43,11 +44,19 @@
43 assert(account.lock());44 assert(account.lock());
44}45}
4546
46Account* RootBase::account() const47shared_ptr<Account> RootBase::account() const
47{48{
48 if (auto acc = account_.lock())49 if (auto acc = account_.lock())
49 {50 {
50 return acc.get();51 try
52 {
53 acc->runtime();
54 }
55 catch (RuntimeDestroyedException const&)
56 {
57 throw RuntimeDestroyedException("Root::account()");
58 }
59 return acc;
51 }60 }
52 throw RuntimeDestroyedException("Root::account()");61 throw RuntimeDestroyedException("Root::account()");
53}62}
5463
=== modified file 'src/qt/client/internal/RuntimeBase.cpp'
--- src/qt/client/internal/RuntimeBase.cpp 2016-07-12 02:22:05 +0000
+++ src/qt/client/internal/RuntimeBase.cpp 2016-09-09 02:13:43 +0000
@@ -34,11 +34,6 @@
34namespace internal34namespace internal
35{35{
3636
37RuntimeBase::RuntimeBase()
38 : destroyed_(false)
39{
40}
41
42void RuntimeBase::set_public_instance(weak_ptr<Runtime> p)37void RuntimeBase::set_public_instance(weak_ptr<Runtime> p)
43{38{
44 assert(p.lock());39 assert(p.lock());
4540
=== modified file 'src/qt/client/internal/UploaderBase.cpp'
--- src/qt/client/internal/UploaderBase.cpp 2016-07-22 01:45:39 +0000
+++ src/qt/client/internal/UploaderBase.cpp 2016-09-09 02:13:43 +0000
@@ -25,6 +25,8 @@
25#include <QFuture>25#include <QFuture>
26#pragma GCC diagnostic pop26#pragma GCC diagnostic pop
2727
28#include <cassert>
29
28using namespace std;30using namespace std;
2931
30namespace unity32namespace unity
@@ -38,9 +40,16 @@
38namespace internal40namespace internal
39{41{
4042
41UploaderBase::UploaderBase(ConflictPolicy policy)43UploaderBase::UploaderBase(ConflictPolicy policy, int64_t size)
42 : policy_(policy)44 : policy_(policy)
43{45 , size_(size)
46{
47 assert(size >= 0);
48}
49
50int64_t UploaderBase::size() const
51{
52 return size_;
44}53}
4554
46} // namespace internal55} // namespace internal
4756
=== modified file 'src/qt/client/internal/local_client/AccountImpl.cpp'
--- src/qt/client/internal/local_client/AccountImpl.cpp 2016-07-14 04:50:36 +0000
+++ src/qt/client/internal/local_client/AccountImpl.cpp 2016-09-09 02:13:43 +0000
@@ -67,7 +67,7 @@
67 if (ec)67 if (ec)
68 {68 {
69 QString msg = "Account::roots(): Cannot stat " + QString(dir) + ": " + QString::fromStdString(ec.message());69 QString msg = "Account::roots(): Cannot stat " + QString(dir) + ": " + QString::fromStdString(ec.message());
70 throw ResourceException(msg);70 throw ResourceException(msg, errno);
71 }71 }
72 if (!is_dir)72 if (!is_dir)
73 {73 {
@@ -85,7 +85,7 @@
85 {85 {
86 QString msg = "Account::roots(): Cannot create " + QString(dir) + ": "86 QString msg = "Account::roots(): Cannot create " + QString(dir) + ": "
87 + QString::fromStdString(ec.message());87 + QString::fromStdString(ec.message());
88 throw ResourceException(msg);88 throw ResourceException(msg, ec.value());
89 }89 }
90 }90 }
91 return data_dir;91 return data_dir;
@@ -109,22 +109,32 @@
109109
110QString AccountImpl::owner() const110QString AccountImpl::owner() const
111{111{
112 runtime(); // Throws RuntimeDestroyedException if runtime was destroyed.
112 return owner_;113 return owner_;
113}114}
114115
115QString AccountImpl::owner_id() const116QString AccountImpl::owner_id() const
116{117{
118 runtime(); // Throws RuntimeDestroyedException if runtime was destroyed.
117 return owner_id_;119 return owner_id_;
118}120}
119121
120QString AccountImpl::description() const122QString AccountImpl::description() const
121{123{
124 runtime(); // Throws RuntimeDestroyedException if runtime was destroyed.
122 return description_;125 return description_;
123}126}
124127
125QFuture<QVector<Root::SPtr>> AccountImpl::roots()128QFuture<QVector<Root::SPtr>> AccountImpl::roots()
126{129{
127 using namespace boost::filesystem;130 try
131 {
132 runtime(); // Throws RuntimeDestroyedException if runtime was destroyed.
133 }
134 catch (RuntimeDestroyedException const& e)
135 {
136 return make_exceptional_future<QVector<Root::SPtr>>(e);
137 }
128138
129 if (!roots_.isEmpty())139 if (!roots_.isEmpty())
130 {140 {
@@ -132,6 +142,9 @@
132 }142 }
133143
134 // Create the root on first access.144 // Create the root on first access.
145
146 using namespace boost::filesystem;
147
135 auto rpath = canonical(get_data_dir()).native();148 auto rpath = canonical(get_data_dir()).native();
136 auto root = RootImpl::make_root(QString::fromStdString(rpath), public_instance_);149 auto root = RootImpl::make_root(QString::fromStdString(rpath), public_instance_);
137 roots_.append(root);150 roots_.append(root);
138151
=== modified file 'src/qt/client/internal/local_client/CMakeLists.txt'
--- src/qt/client/internal/local_client/CMakeLists.txt 2016-07-22 00:17:24 +0000
+++ src/qt/client/internal/local_client/CMakeLists.txt 2016-09-09 02:13:43 +0000
@@ -7,6 +7,7 @@
7 ${CMAKE_CURRENT_SOURCE_DIR}/RootImpl.cpp7 ${CMAKE_CURRENT_SOURCE_DIR}/RootImpl.cpp
8 ${CMAKE_CURRENT_SOURCE_DIR}/Runtime_create.cpp8 ${CMAKE_CURRENT_SOURCE_DIR}/Runtime_create.cpp
9 ${CMAKE_CURRENT_SOURCE_DIR}/RuntimeImpl.cpp9 ${CMAKE_CURRENT_SOURCE_DIR}/RuntimeImpl.cpp
10 ${CMAKE_CURRENT_SOURCE_DIR}/storage_exception.cpp
10 ${CMAKE_CURRENT_SOURCE_DIR}/UploaderImpl.cpp11 ${CMAKE_CURRENT_SOURCE_DIR}/UploaderImpl.cpp
11 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h12 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h
12 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/client/internal/local_client/UploaderImpl.h13 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/client/internal/local_client/UploaderImpl.h
1314
=== modified file 'src/qt/client/internal/local_client/DownloaderImpl.cpp'
--- src/qt/client/internal/local_client/DownloaderImpl.cpp 2016-07-22 00:17:24 +0000
+++ src/qt/client/internal/local_client/DownloaderImpl.cpp 2016-09-09 02:13:43 +0000
@@ -23,7 +23,10 @@
23#include <unity/storage/qt/client/File.h>23#include <unity/storage/qt/client/File.h>
24#include <unity/storage/qt/client/internal/make_future.h>24#include <unity/storage/qt/client/internal/make_future.h>
2525
26#pragma GCC diagnostic push
27#pragma GCC diagnostic ignored "-Wcast-align"
26#include <QLocalSocket>28#include <QLocalSocket>
29#pragma GCC diagnostic pop
2730
28#include <cassert>31#include <cassert>
2932
@@ -79,8 +82,10 @@
79 input_file_.reset(new QFile(filename_));82 input_file_.reset(new QFile(filename_));
80 if (!input_file_->open(QIODevice::ReadOnly))83 if (!input_file_->open(QIODevice::ReadOnly))
81 {84 {
82 handle_error("cannot open " + filename_ + ": " + input_file_->errorString());85 // LCOV_EXCL_START
86 handle_error("cannot open " + filename_ + ": " + input_file_->errorString(), input_file_->error());
83 return;87 return;
88 // LCOV_EXCL_STOP
84 }89 }
85 bytes_to_write_ = input_file_->size();90 bytes_to_write_ = input_file_->size();
8691
@@ -116,7 +121,7 @@
116 + QString::number(written) + " byte";121 + QString::number(written) + " byte";
117 msg += written == 1 ? " was" : "s were";122 msg += written == 1 ? " was" : "s were";
118 msg += " consumed.";123 msg += " consumed.";
119 make_exceptional_future(qf_, LogicException(msg));124 qf_.reportException(LogicException(msg));
120 }125 }
121 else126 else
122 {127 {
@@ -131,12 +136,12 @@
131 case cancelled:136 case cancelled:
132 {137 {
133 QString msg = "Downloader::finish_download(): download of " + filename_ + " was cancelled";138 QString msg = "Downloader::finish_download(): download of " + filename_ + " was cancelled";
134 make_exceptional_future(qf_, CancelledException(msg));139 qf_.reportException(CancelledException(msg));
135 break;140 break;
136 }141 }
137 case error:142 case error:
138 {143 {
139 make_exceptional_future(qf_, ResourceException(error_msg_));144 qf_.reportException(ResourceException(error_msg_, error_code_));
140 break;145 break;
141 }146 }
142 default:147 default:
@@ -144,7 +149,7 @@
144 abort(); // LCOV_EXCL_LINE // Impossible149 abort(); // LCOV_EXCL_LINE // Impossible
145 }150 }
146 }151 }
147 make_ready_future(qf_);152 qf_.reportFinished();
148 QThread::currentThread()->quit();153 QThread::currentThread()->quit();
149}154}
150155
@@ -189,7 +194,8 @@
189194
190void DownloadWorker::on_error()195void DownloadWorker::on_error()
191{196{
192 handle_error(write_socket_->errorString());197 disconnect(write_socket_.get(), nullptr, this, nullptr);
198 handle_error(write_socket_->errorString(), write_socket_->error());
193}199}
194200
195// Read the next chunk of data from the input file and write it to the socket.201// Read the next chunk of data from the input file and write it to the socket.
@@ -203,25 +209,31 @@
203 auto bytes_read = input_file_->read(buf.data(), buf.size());209 auto bytes_read = input_file_->read(buf.data(), buf.size());
204 if (bytes_read == -1)210 if (bytes_read == -1)
205 {211 {
206 handle_error(filename_ + ": read error: " + input_file_->errorString());212 // LCOV_EXCL_START
213 handle_error(filename_ + ": read error: " + input_file_->errorString(), input_file_->error());
207 return;214 return;
215 // LCOV_EXCL_STOP
208 }216 }
209 buf.resize(bytes_read);217 buf.resize(bytes_read);
210218
211 auto bytes_written = write_socket_->write(buf);219 auto bytes_written = write_socket_->write(buf);
212 if (bytes_written == -1)220 if (bytes_written == -1)
213 {221 {
214 handle_error(filename_ + ": socket error: " + write_socket_->errorString());222 // LCOV_EXCL_START
223 handle_error(filename_ + ": socket error: " + write_socket_->errorString(), write_socket_->error());
224 // LCOV_EXCL_STOP
215 }225 }
216 else if (bytes_written != bytes_read)226 else if (bytes_written != bytes_read)
217 {227 {
228 // LCOV_EXCL_START
218 QString msg = filename_ + ": write error, requested " + bytes_read + " B, but wrote only "229 QString msg = filename_ + ": write error, requested " + bytes_read + " B, but wrote only "
219 + bytes_written + " B.";230 + bytes_written + " B.";
220 handle_error(msg);231 handle_error(msg, 0);
232 // LCOV_EXCL_STOP
221 }233 }
222}234}
223235
224void DownloadWorker::handle_error(QString const& msg)236void DownloadWorker::handle_error(QString const& msg, int error_code)
225{237{
226 if (state_ == in_progress)238 if (state_ == in_progress)
227 {239 {
@@ -229,6 +241,7 @@
229 }241 }
230 state_ = error;242 state_ = error;
231 error_msg_ = "Downloader: " + msg;243 error_msg_ = "Downloader: " + msg;
244 error_code_ = error_code;
232 do_finish();245 do_finish();
233}246}
234247
@@ -245,17 +258,18 @@
245258
246DownloaderImpl::DownloaderImpl(weak_ptr<File> file)259DownloaderImpl::DownloaderImpl(weak_ptr<File> file)
247 : DownloaderBase(file)260 : DownloaderBase(file)
248 , read_socket_(new QLocalSocket)261 , read_socket_(new QLocalSocket, [](QLocalSocket* s){ s->deleteLater(); })
249{262{
250 // Set up socket pair.263 // Set up socket pair.
251 int fds[2];264 int fds[2];
252 int rc = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds);265 int rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
253 if (rc == -1)266 if (rc == -1)
254 {267 {
255 // LCOV_EXCL_START268 // LCOV_EXCL_START
256 QString msg = "Downloader: cannot create socket pair: "269 QString msg = "Downloader: cannot create socket pair: "
257 + QString::fromStdString(storage::internal::safe_strerror(errno));270 + QString::fromStdString(storage::internal::safe_strerror(errno));
258 make_exceptional_future(qf_, ResourceException(msg));271 qf_.reportException(ResourceException(msg, errno));
272 qf_.reportFinished();
259 return;273 return;
260 // LCOV_EXCL_STOP274 // LCOV_EXCL_STOP
261 }275 }
262276
=== modified file 'src/qt/client/internal/local_client/FileImpl.cpp'
--- src/qt/client/internal/local_client/FileImpl.cpp 2016-07-22 01:45:39 +0000
+++ src/qt/client/internal/local_client/FileImpl.cpp 2016-09-09 02:13:43 +0000
@@ -22,6 +22,7 @@
22#include <unity/storage/qt/client/Exceptions.h>22#include <unity/storage/qt/client/Exceptions.h>
23#include <unity/storage/qt/client/File.h>23#include <unity/storage/qt/client/File.h>
24#include <unity/storage/qt/client/internal/local_client/DownloaderImpl.h>24#include <unity/storage/qt/client/internal/local_client/DownloaderImpl.h>
25#include <unity/storage/qt/client/internal/local_client/storage_exception.h>
25#include <unity/storage/qt/client/internal/local_client/UploaderImpl.h>26#include <unity/storage/qt/client/internal/local_client/UploaderImpl.h>
26#include <unity/storage/qt/client/internal/make_future.h>27#include <unity/storage/qt/client/internal/make_future.h>
27#include <unity/storage/qt/client/Uploader.h>28#include <unity/storage/qt/client/Uploader.h>
@@ -50,47 +51,44 @@
5051
51QString FileImpl::name() const52QString FileImpl::name() const
52{53{
53 lock_guard<mutex> guard(mutex_);54 lock_guard<decltype(mutex_)> guard(mutex_);
5455
55 if (deleted_)56 throw_if_destroyed("File::name()");
56 {
57 throw deleted_ex("File::name()");
58 }
59 return name_;57 return name_;
60}58}
6159
62int64_t FileImpl::size() const60int64_t FileImpl::size() const
63{61{
64 lock_guard<mutex> guard(mutex_);62 lock_guard<decltype(mutex_)> guard(mutex_);
6563
66 if (deleted_)64 throw_if_destroyed("File::size()");
67 {
68 throw deleted_ex("File::size()");
69 }
70
71 try65 try
72 {66 {
73 boost::filesystem::path p = identity_.toStdString();67 boost::filesystem::path p = identity_.toStdString();
74 return file_size(p);68 return file_size(p);
75 }69 }
76 catch (std::exception const& e)70 catch (std::exception const&)
77 {71 {
78 throw ResourceException(e.what());72 throw_storage_exception(QString("File::size()"), current_exception());
79 }73 }
80}74}
8175
82QFuture<Uploader::SPtr> FileImpl::create_uploader(ConflictPolicy policy, int64_t size)76QFuture<Uploader::SPtr> FileImpl::create_uploader(ConflictPolicy policy, int64_t size)
83{77{
84 lock_guard<mutex> guard(mutex_);78 lock_guard<decltype(mutex_)> guard(mutex_);
8579
86 if (deleted_)80 try
87 {81 {
88 return make_exceptional_future<Uploader::SPtr>(deleted_ex("File::create_uploader()"));82 throw_if_destroyed("File::create_uploader()");
83 }
84 catch (StorageException const& e)
85 {
86 return internal::make_exceptional_future<Uploader::SPtr>(e);
89 }87 }
90 if (size < 0)88 if (size < 0)
91 {89 {
92 QString msg = "File::create_uploader(): size must be >= 0";90 QString msg = "File::create_uploader(): size must be >= 0";
93 return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg));91 return internal::make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg));
94 }92 }
9593
96 auto file = dynamic_pointer_cast<File>(public_instance_.lock());94 auto file = dynamic_pointer_cast<File>(public_instance_.lock());
@@ -102,11 +100,15 @@
102100
103QFuture<Downloader::SPtr> FileImpl::create_downloader()101QFuture<Downloader::SPtr> FileImpl::create_downloader()
104{102{
105 lock_guard<mutex> guard(mutex_);103 lock_guard<decltype(mutex_)> guard(mutex_);
106104
107 if (deleted_)105 try
108 {106 {
109 return make_exceptional_future<Downloader::SPtr>(deleted_ex("File::create_downloader()"));107 throw_if_destroyed("File::create_downloader()");
108 }
109 catch (StorageException const& e)
110 {
111 return internal::make_exceptional_future<Downloader::SPtr>(e);
110 }112 }
111113
112 auto pi = public_instance_.lock();114 auto pi = public_instance_.lock();
113115
=== modified file 'src/qt/client/internal/local_client/FolderImpl.cpp'
--- src/qt/client/internal/local_client/FolderImpl.cpp 2016-07-22 01:45:39 +0000
+++ src/qt/client/internal/local_client/FolderImpl.cpp 2016-09-09 02:13:43 +0000
@@ -24,7 +24,8 @@
24#include <unity/storage/qt/client/Uploader.h>24#include <unity/storage/qt/client/Uploader.h>
25#include <unity/storage/qt/client/internal/make_future.h>25#include <unity/storage/qt/client/internal/make_future.h>
26#include <unity/storage/qt/client/internal/local_client/FileImpl.h>26#include <unity/storage/qt/client/internal/local_client/FileImpl.h>
27#include <unity/storage/qt/client/internal/local_client/tmpfile-prefix.h>27#include <unity/storage/qt/client/internal/local_client/storage_exception.h>
28#include <unity/storage/qt/client/internal/local_client/tmpfile_prefix.h>
28#include <unity/storage/qt/client/internal/local_client/UploaderImpl.h>29#include <unity/storage/qt/client/internal/local_client/UploaderImpl.h>
2930
30#include <boost/algorithm/string/predicate.hpp>31#include <boost/algorithm/string/predicate.hpp>
@@ -62,22 +63,36 @@
62{63{
63}64}
6465
66QString FolderImpl::name() const
67{
68 lock_guard<decltype(mutex_)> guard(mutex_);
69
70 throw_if_destroyed("Item::name()");
71 return name_;
72}
73
65QFuture<QVector<Item::SPtr>> FolderImpl::list() const74QFuture<QVector<Item::SPtr>> FolderImpl::list() const
66{75{
76 try
77 {
78 throw_if_destroyed("Folder::list()");
79 }
80 catch (StorageException const& e)
81 {
82 return internal::make_exceptional_future<QVector<Item::SPtr>>(e);
83 }
84
67 auto This = dynamic_pointer_cast<FolderImpl const>(shared_from_this()); // Keep this folder alive while the lambda is alive.85 auto This = dynamic_pointer_cast<FolderImpl const>(shared_from_this()); // Keep this folder alive while the lambda is alive.
68 auto list = [This]()86 auto list = [This]()
69 {87 {
70 lock_guard<mutex> guard(This->mutex_);88 lock_guard<decltype(mutex_)> guard(This->mutex_);
7189
72 if (This->deleted_)90 This->throw_if_destroyed("Folder::list()");
73 {
74 throw This->deleted_ex("Folder::list()");
75 }
76
77 try91 try
78 {92 {
79 using namespace boost::filesystem;93 using namespace boost::filesystem;
8094
95 auto root = This->root_.lock();
81 QVector<Item::SPtr> results;96 QVector<Item::SPtr> results;
82 for (directory_iterator it(This->native_identity().toStdString()); it != directory_iterator(); ++it)97 for (directory_iterator it(This->native_identity().toStdString()); it != directory_iterator(); ++it)
83 {98 {
@@ -90,11 +105,11 @@
90 QString path = QString::fromStdString(dirent.path().native());105 QString path = QString::fromStdString(dirent.path().native());
91 if (is_directory(s))106 if (is_directory(s))
92 {107 {
93 results.append(make_folder(path, This->root_));108 results.append(make_folder(path, root));
94 }109 }
95 else if (is_regular_file(s))110 else if (is_regular_file(s))
96 {111 {
97 results.append(FileImpl::make_file(path, This->root_));112 results.append(FileImpl::make_file(path, root));
98 }113 }
99 else114 else
100 {115 {
@@ -103,9 +118,9 @@
103 }118 }
104 return results;119 return results;
105 }120 }
106 catch (std::exception const& e)121 catch (std::exception const&)
107 {122 {
108 throw ResourceException(QString("Folder::list(): ") + e.what());123 throw_storage_exception("Folder::list()", current_exception());
109 }124 }
110 };125 };
111 return QtConcurrent::run(list);126 return QtConcurrent::run(list);
@@ -113,49 +128,51 @@
113128
114QFuture<QVector<Item::SPtr>> FolderImpl::lookup(QString const& name) const129QFuture<QVector<Item::SPtr>> FolderImpl::lookup(QString const& name) const
115{130{
131 try
132 {
133 throw_if_destroyed("Folder::lookup()");
134 }
135 catch (StorageException const& e)
136 {
137 return internal::make_exceptional_future<QVector<Item::SPtr>>(e);
138 }
139
116 auto This = dynamic_pointer_cast<FolderImpl const>(shared_from_this()); // Keep this folder alive while the lambda is alive.140 auto This = dynamic_pointer_cast<FolderImpl const>(shared_from_this()); // Keep this folder alive while the lambda is alive.
117 auto lookup = [This, name]() -> QVector<Item::SPtr>141 auto lookup = [This, name]() -> QVector<Item::SPtr>
118 {142 {
119 lock_guard<mutex> guard(This->mutex_);143 lock_guard<decltype(mutex_)> guard(This->mutex_);
120144
121 if (This->deleted_)145 This->throw_if_destroyed("Folder::lookup()"); // LCOV_EXCL_LINE
122 {
123 throw This->deleted_ex("Folder::lookup()");
124 }
125
126 try146 try
127 {147 {
128 using namespace boost::filesystem;148 using namespace boost::filesystem;
129149
150 auto root = This->root_.lock();
130 path p = This->native_identity().toStdString();151 path p = This->native_identity().toStdString();
131 auto sanitized_name = sanitize(name, "Folder::lookup()");152 auto sanitized_name = sanitize(name, "Folder::lookup()");
132 if (is_reserved_path(sanitized_name))153 if (is_reserved_path(sanitized_name))
133 {154 {
134 throw NotExistsException("Folder::lookup(): no such item: " + name, name);155 throw NotExistsException("Folder::lookup(): no such item: \"" + name + "\"", name);
135 }156 }
136 p /= sanitized_name;157 p /= sanitized_name;
137 file_status s = status(p);158 file_status s = status(p);
138 if (is_directory(s))159 if (is_directory(s))
139 {160 {
140 QVector<Item::SPtr> v;161 QVector<Item::SPtr> v;
141 v.append(make_folder(QString::fromStdString(p.native()), This->root_));162 v.append(make_folder(QString::fromStdString(p.native()), root));
142 return v;163 return v;
143 }164 }
144 if (is_regular_file(s))165 if (is_regular_file(s))
145 {166 {
146 QVector<Item::SPtr> v;167 QVector<Item::SPtr> v;
147 v.append(FileImpl::make_file(QString::fromStdString(p.native()), This->root_));168 v.append(FileImpl::make_file(QString::fromStdString(p.native()), root));
148 return v;169 return v;
149 }170 }
150 throw NotExistsException("Folder::lookup(): no such item: " + name, name);171 throw NotExistsException("Folder::lookup(): no such item: \"" + name + "\"", name);
151 }172 }
152 catch (StorageException const&)173 catch (std::exception const&)
153 {174 {
154 throw;175 throw_storage_exception("Folder::lookup()", current_exception());
155 }
156 catch (std::exception const& e)
157 {
158 throw ResourceException(QString("Folder::lookup(): ") + e.what());
159 }176 }
160 };177 };
161 return QtConcurrent::run(lookup);178 return QtConcurrent::run(lookup);
@@ -163,12 +180,15 @@
163180
164QFuture<Folder::SPtr> FolderImpl::create_folder(QString const& name)181QFuture<Folder::SPtr> FolderImpl::create_folder(QString const& name)
165{182{
166 lock_guard<mutex> guard(mutex_);183 lock_guard<decltype(mutex_)> guard(mutex_);
167184
168 QFutureInterface<Folder::SPtr> qf;185 try
169 if (deleted_)186 {
170 {187 throw_if_destroyed("Folder::create_folder()");
171 return make_exceptional_future<Folder::SPtr>(deleted_ex("Folder::create_folder()"));188 }
189 catch (StorageException const& e)
190 {
191 return internal::make_exceptional_future<Folder::SPtr>(e);
172 }192 }
173193
174 try194 try
@@ -179,31 +199,40 @@
179 auto sanitized_name = sanitize(name, "Folder::create_folder()");199 auto sanitized_name = sanitize(name, "Folder::create_folder()");
180 if (is_reserved_path(sanitized_name))200 if (is_reserved_path(sanitized_name))
181 {201 {
182 QString msg = "Folder::create_folder(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved";202 QString msg = "Folder::create_folder(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved";
183 return make_exceptional_future<Folder::SPtr>(InvalidArgumentException(msg));203 throw InvalidArgumentException(msg);
184 }204 }
185 p /= sanitized_name;205 p /= sanitized_name;
206 if (exists(p))
207 {
208 QString msg = "Folder::create_folder(): item with name \"" + name + "\" exists already";
209 throw ExistsException(msg, native_identity() + "/" + name, name);
210 }
186 create_directory(p);211 create_directory(p);
187 return make_ready_future(make_folder(QString::fromStdString(p.native()), root_));212 return make_ready_future(make_folder(QString::fromStdString(p.native()), root_));
188 }213 }
189 catch (std::exception const& e)214 catch (std::exception const&)
190 {215 {
191 return make_exceptional_future<Folder::SPtr>(ResourceException(QString("Folder::create_folder: ") + e.what()));216 return make_exceptional_future<Folder::SPtr>("Folder::create_folder()", current_exception());
192 }217 }
193}218}
194219
195QFuture<shared_ptr<Uploader>> FolderImpl::create_file(QString const& name, int64_t size)220QFuture<shared_ptr<Uploader>> FolderImpl::create_file(QString const& name, int64_t size)
196{221{
197 unique_lock<mutex> guard(mutex_);222 lock_guard<decltype(mutex_)> guard(mutex_);
198223
199 if (deleted_)224 try
200 {225 {
201 return make_exceptional_future<Uploader::SPtr>(deleted_ex("Folder::create_file()"));226 throw_if_destroyed("Folder::create_file()");
227 }
228 catch (StorageException const& e)
229 {
230 return internal::make_exceptional_future<shared_ptr<Uploader>>(e);
202 }231 }
203 if (size < 0)232 if (size < 0)
204 {233 {
205 QString msg = "Folder::create_file(): size must be >= 0";234 QString msg = "Folder::create_file(): size must be >= 0";
206 return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg));235 return internal::make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg));
207 }236 }
208237
209 try238 try
@@ -214,14 +243,14 @@
214 auto sanitized_name = sanitize(name, "Folder::create_file()");243 auto sanitized_name = sanitize(name, "Folder::create_file()");
215 if (is_reserved_path(sanitized_name))244 if (is_reserved_path(sanitized_name))
216 {245 {
217 QString msg = "Folder::create_file(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved";246 QString msg = "Folder::create_file(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved";
218 return make_exceptional_future<Uploader::SPtr>(InvalidArgumentException(msg));247 throw InvalidArgumentException(msg);
219 }248 }
220 p /= sanitized_name;249 p /= sanitized_name;
221 if (exists(p))250 if (exists(p))
222 {251 {
223 QString msg = "Folder::create_file(): item with name \"" + name + "\" exists already";252 QString msg = "Folder::create_file(): item with name \"" + name + "\" exists already";
224 return make_exceptional_future<Uploader::SPtr>(ExistsException(msg, native_identity(), name));253 throw ExistsException(msg, native_identity() + "/" + name, name);
225 }254 }
226 auto impl = new UploaderImpl(shared_ptr<File>(),255 auto impl = new UploaderImpl(shared_ptr<File>(),
227 size,256 size,
@@ -231,9 +260,9 @@
231 Uploader::SPtr uploader(new Uploader(impl));260 Uploader::SPtr uploader(new Uploader(impl));
232 return make_ready_future(uploader);261 return make_ready_future(uploader);
233 }262 }
234 catch (std::exception const& e)263 catch (std::exception const&)
235 {264 {
236 return make_exceptional_future<Uploader::SPtr>(ResourceException(QString("Folder::create_file: ") + e.what()));265 return make_exceptional_future<Uploader::SPtr>("Folder::create_file()", current_exception());
237 }266 }
238}267}
239268
240269
=== modified file 'src/qt/client/internal/local_client/ItemImpl.cpp'
--- src/qt/client/internal/local_client/ItemImpl.cpp 2016-07-22 00:17:24 +0000
+++ src/qt/client/internal/local_client/ItemImpl.cpp 2016-09-09 02:13:43 +0000
@@ -21,14 +21,16 @@
21#include <unity/storage/internal/safe_strerror.h>21#include <unity/storage/internal/safe_strerror.h>
22#include <unity/storage/qt/client/Account.h>22#include <unity/storage/qt/client/Account.h>
23#include <unity/storage/qt/client/Exceptions.h>23#include <unity/storage/qt/client/Exceptions.h>
24#include <unity/storage/qt/client/internal/make_future.h>
25#include <unity/storage/qt/client/internal/local_client/AccountImpl.h>24#include <unity/storage/qt/client/internal/local_client/AccountImpl.h>
26#include <unity/storage/qt/client/internal/local_client/FileImpl.h>25#include <unity/storage/qt/client/internal/local_client/FileImpl.h>
27#include <unity/storage/qt/client/internal/local_client/RootImpl.h>26#include <unity/storage/qt/client/internal/local_client/RootImpl.h>
28#include <unity/storage/qt/client/internal/local_client/tmpfile-prefix.h>27#include <unity/storage/qt/client/internal/local_client/storage_exception.h>
28#include <unity/storage/qt/client/internal/local_client/tmpfile_prefix.h>
29#include <unity/storage/qt/client/internal/make_future.h>
2930
30#include <boost/algorithm/string/predicate.hpp>31#include <boost/algorithm/string/predicate.hpp>
31#pragma GCC diagnostic push32#pragma GCC diagnostic push
33#pragma GCC diagnostic ignored "-Wcast-align"
32#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"34#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
33#include <QtConcurrent>35#include <QtConcurrent>
34#pragma GCC diagnostic pop36#pragma GCC diagnostic pop
@@ -54,7 +56,6 @@
5456
55ItemImpl::ItemImpl(QString const& identity, ItemType type)57ItemImpl::ItemImpl(QString const& identity, ItemType type)
56 : ItemBase(identity, type)58 : ItemBase(identity, type)
57 , deleted_(false)
58{59{
59 assert(!identity.isEmpty());60 assert(!identity.isEmpty());
60 auto path = boost::filesystem::canonical(identity.toStdString());61 auto path = boost::filesystem::canonical(identity.toStdString());
@@ -64,102 +65,70 @@
6465
65ItemImpl::~ItemImpl() = default;66ItemImpl::~ItemImpl() = default;
6667
67QString ItemImpl::name() const
68{
69 lock_guard<mutex> guard(mutex_);
70
71 if (deleted_)
72 {
73 throw deleted_ex("Item::name()");
74 }
75 return name_;
76}
77
78QString ItemImpl::etag() const68QString ItemImpl::etag() const
79{69{
80 lock_guard<mutex> guard(mutex_);70 lock_guard<decltype(mutex_)> guard(mutex_);
8171
82 if (deleted_)72 throw_if_destroyed("Item::etag()");
83 {
84 throw deleted_ex("Item::etag()");
85 }
86 return etag_;73 return etag_;
87}74}
8875
89QVariantMap ItemImpl::metadata() const76QVariantMap ItemImpl::metadata() const
90{77{
91 lock_guard<mutex> guard(mutex_);78 lock_guard<decltype(mutex_)> guard(mutex_);
9279
93 if (deleted_)80 throw_if_destroyed("Item::metadata()");
94 {
95 throw deleted_ex("Item::metadata()");
96 }
97 return metadata_;81 return metadata_;
98}82}
9983
100QDateTime ItemImpl::last_modified_time() const84QDateTime ItemImpl::last_modified_time() const
101{85{
102 lock_guard<mutex> guard(mutex_);86 lock_guard<decltype(mutex_)> guard(mutex_);
10387
104 if (deleted_)88 throw_if_destroyed("Item::last_modified_time()");
105 {
106 throw deleted_ex("Item::last_modified_time()");
107 }
108 return modified_time_;89 return modified_time_;
109}90}
11091
111namespace
112{
113
114using namespace boost::filesystem;
115
116void copy_recursively(path const& source, path const& target)
117{
118 auto s = status(source);
119 if (is_regular_file(s))
120 {
121 copy_file(source, target);
122 return;
123 }
124 else if (is_directory(s))
125 {
126 copy_directory(source, target); // Poorly named in boost; this creates the target dir without recursion
127 for (directory_iterator it(source); it != directory_iterator(); ++it)
128 {
129 path source_entry = it->path();
130 path target_entry = target;
131 target_entry /= source_entry.filename();
132 copy_recursively(source_entry, target_entry);
133 }
134 }
135 else
136 {
137 // Ignore everything that's not a directory or file.
138 }
139}
140
141} // namespace
142
143QFuture<shared_ptr<Item>> ItemImpl::copy(shared_ptr<Folder> const& new_parent, QString const& new_name)92QFuture<shared_ptr<Item>> ItemImpl::copy(shared_ptr<Folder> const& new_parent, QString const& new_name)
144{93{
94 if (!new_parent)
95 {
96 QString msg = "Item::copy(): new_parent cannot be nullptr";
97 return internal::make_exceptional_future<shared_ptr<Item>>(InvalidArgumentException(msg));
98 }
99 auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_);
100
101 lock(mutex_, new_parent_impl->mutex_);
102 lock_guard<decltype(mutex_)> this_guard(mutex_, std::adopt_lock);
103 lock_guard<decltype(mutex_)> other_guard(new_parent_impl->mutex_, adopt_lock);
104
105 try
106 {
107 throw_if_destroyed("Item::copy()");
108 new_parent_impl->throw_if_destroyed("Item::copy()");
109 }
110 catch (StorageException const& e)
111 {
112 return internal::make_exceptional_future<shared_ptr<Item>>(e);
113 }
114
145 auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive.115 auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive.
146 auto copy = [This, new_parent, new_name]() -> Item::SPtr116 auto copy = [This, new_parent, new_name]() -> Item::SPtr
147 {117 {
148 auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_);118 auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_);
149119
150 lock(This->mutex_, new_parent_impl->mutex_);120 lock(This->mutex_, new_parent_impl->mutex_);
151 lock_guard<mutex> this_guard(This->mutex_, std::adopt_lock);121 lock_guard<decltype(mutex_)> this_guard(This->mutex_, std::adopt_lock);
152 lock_guard<mutex> other_guard(new_parent_impl->mutex_, adopt_lock);122 lock_guard<decltype(mutex_)> other_guard(new_parent_impl->mutex_, adopt_lock);
153123
154 if (This->deleted_ || new_parent_impl->deleted_)124 This->throw_if_destroyed("Item::copy()");
155 {125 new_parent_impl->throw_if_destroyed("Item::copy()");
156 throw This->deleted_ex("Item::copy");126
157 }127 // TODO: This needs to deeply compare account identity because the client may have refreshed the accounts list.
158128 if (This->root()->account() != new_parent->root()->account()) // Throws if account or runtime were destroyed.
159 if (This->root()->account() != new_parent->root()->account())
160 {129 {
161 // Can't do cross-account copy.130 // Can't do cross-account copy.
162 QString msg = QString("Item::copy(): Source (") + This->name_ + ") and target ("131 QString msg = QString("Item::copy(): source (") + This->name_ + ") and target ("
163 + new_name + ") must belong to the same account";132 + new_name + ") must belong to the same account";
164 throw LogicException(msg);133 throw LogicException(msg);
165 }134 }
@@ -175,22 +144,22 @@
175 target_path /= sanitized_name;144 target_path /= sanitized_name;
176 if (is_reserved_path(target_path))145 if (is_reserved_path(target_path))
177 {146 {
178 QString msg = "Item::copy(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved";147 QString msg = "Item::copy(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved";
179 throw InvalidArgumentException(msg);148 throw InvalidArgumentException(msg);
180 }149 }
181150
151 if (exists(target_path))
152 {
153 QString msg = "Item::copy(): item with name \"" + new_name + "\" exists already";
154 throw ExistsException(msg, This->identity_, This->name_);
155 }
156
182 if (This->type_ == ItemType::file)157 if (This->type_ == ItemType::file)
183 {158 {
184 copy_file(source_path, target_path);159 copy_file(source_path, target_path);
185 return FileImpl::make_file(QString::fromStdString(target_path.native()), new_parent_impl->root_);160 return FileImpl::make_file(QString::fromStdString(target_path.native()), new_parent_impl->root_);
186 }161 }
187162
188 if (exists(target_path))
189 {
190 QString msg = "Item::copy(): item with name \"" + new_name + "\" exists already";
191 throw ExistsException(msg, This->identity_, This->name_);
192 }
193
194 // For recursive copy, we create a temporary directory in lieu of target_path and recursively copy163 // For recursive copy, we create a temporary directory in lieu of target_path and recursively copy
195 // everything into the temporary directory. This ensures that we don't invalidate directory iterators164 // everything into the temporary directory. This ensures that we don't invalidate directory iterators
196 // by creating things while we are iterating, potentially getting trapped in an infinite loop.165 // by creating things while we are iterating, potentially getting trapped in an infinite loop.
@@ -199,7 +168,7 @@
199 create_directories(tmp_path);168 create_directories(tmp_path);
200 for (directory_iterator it(source_path); it != directory_iterator(); ++it)169 for (directory_iterator it(source_path); it != directory_iterator(); ++it)
201 {170 {
202 if (tmp_path.compare(canonical(it->path())) == 0)171 if (is_reserved_path(it->path()))
203 {172 {
204 continue; // Don't recurse into the temporary directory173 continue; // Don't recurse into the temporary directory
205 }174 }
@@ -209,15 +178,15 @@
209 path source_entry = it->path();178 path source_entry = it->path();
210 path target_entry = tmp_path;179 path target_entry = tmp_path;
211 target_entry /= source_entry.filename();180 target_entry /= source_entry.filename();
212 copy_recursively(source_entry, target_entry);181 ItemImpl::copy_recursively(source_entry, target_entry);
213 }182 }
214 }183 }
215 rename(tmp_path, target_path);184 rename(tmp_path, target_path);
216 return FolderImpl::make_folder(QString::fromStdString(target_path.native()), new_parent_impl->root_);185 return FolderImpl::make_folder(QString::fromStdString(target_path.native()), new_parent_impl->root_);
217 }186 }
218 catch (std::exception const& e)187 catch (std::exception const&)
219 {188 {
220 throw ResourceException(QString("Item::copy(): ") + e.what());189 throw_storage_exception("Item::copy()", current_exception());
221 }190 }
222 };191 };
223 return QtConcurrent::run(copy);192 return QtConcurrent::run(copy);
@@ -225,31 +194,51 @@
225194
226QFuture<shared_ptr<Item>> ItemImpl::move(shared_ptr<Folder> const& new_parent, QString const& new_name)195QFuture<shared_ptr<Item>> ItemImpl::move(shared_ptr<Folder> const& new_parent, QString const& new_name)
227{196{
197 if (!new_parent)
198 {
199 QString msg = "Item::move(): new_parent cannot be nullptr";
200 return internal::make_exceptional_future<shared_ptr<Item>>(InvalidArgumentException(msg));
201 }
202 auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_);
203
204 lock(mutex_, new_parent_impl->mutex_);
205 lock_guard<decltype(mutex_)> this_guard(mutex_, std::adopt_lock);
206 lock_guard<decltype(mutex_)> other_guard(new_parent_impl->mutex_, adopt_lock);
207
208 try
209 {
210 throw_if_destroyed("Item::move()");
211 new_parent_impl->throw_if_destroyed("Item::move()");
212 }
213 catch (StorageException const& e)
214 {
215 return internal::make_exceptional_future<shared_ptr<Item>>(e);
216 }
217
228 auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive.218 auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive.
229 auto move = [This, new_parent, new_name]() -> Item::SPtr219 auto move = [This, new_parent, new_name]() -> Item::SPtr
230 {220 {
231 auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_);221 auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_);
232222
233 lock(This->mutex_, new_parent_impl->mutex_);223 lock(This->mutex_, new_parent_impl->mutex_);
234 lock_guard<mutex> this_guard(This->mutex_, std::adopt_lock);224 lock_guard<decltype(mutex_)> this_guard(This->mutex_, std::adopt_lock);
235 lock_guard<mutex> other_guard(new_parent_impl->mutex_, adopt_lock);225 lock_guard<decltype(mutex_)> other_guard(new_parent_impl->mutex_, adopt_lock);
236226
237 if (This->deleted_ || new_parent_impl->deleted_)227 This->throw_if_destroyed("Item::move()");
238 {228 new_parent_impl->throw_if_destroyed("Item::move()");
239 throw This->deleted_ex("Item::move");229
240 }230 // TODO: This needs to deeply compare account identity because the client may have refreshed the accounts list.
241231 if (This->root()->account() != new_parent->root()->account()) // Throws if account or runtime were destroyed.
242 if (This->root()->account() != new_parent->root()->account())
243 {232 {
244 // Can't do cross-account move.233 // Can't do cross-account move.
245 QString msg = QString("Item::move(): Source (") + This->name_ + ") and target ("234 QString msg = QString("Item::move(): source (") + This->name_ + ") and target ("
246 + new_name + ") must belong to the same account";235 + new_name + ") must belong to the same account";
247 throw LogicException(msg);236 throw LogicException(msg);
248 }237 }
249 if (This->type_ == ItemType::root)238 if (This->type_ == ItemType::root)
250 {239 {
251 // Can't move a root.240 // Can't move a root.
252 throw LogicException("Item::move(): Cannot move root folder");241 throw LogicException("Item::move(): cannot move root folder");
253 }242 }
254243
255 try244 try
@@ -265,7 +254,7 @@
265 }254 }
266 if (is_reserved_path(target_path))255 if (is_reserved_path(target_path))
267 {256 {
268 QString msg = "Item::move(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved";257 QString msg = "Item::move(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved";
269 throw InvalidArgumentException(msg);258 throw InvalidArgumentException(msg);
270 }259 }
271 rename(This->native_identity().toStdString(), target_path);260 rename(This->native_identity().toStdString(), target_path);
@@ -276,9 +265,9 @@
276 }265 }
277 return FileImpl::make_file(QString::fromStdString(target_path.native()), new_parent_impl->root_);266 return FileImpl::make_file(QString::fromStdString(target_path.native()), new_parent_impl->root_);
278 }267 }
279 catch (std::exception const& e)268 catch (std::exception const&)
280 {269 {
281 throw ResourceException(QString("Item::move(): ") + e.what());270 throw_storage_exception(QString("Item::move(): "), current_exception());
282 }271 }
283 };272 };
284 return QtConcurrent::run(move);273 return QtConcurrent::run(move);
@@ -286,18 +275,15 @@
286275
287QFuture<QVector<Folder::SPtr>> ItemImpl::parents() const276QFuture<QVector<Folder::SPtr>> ItemImpl::parents() const
288{277{
289 lock_guard<mutex> guard(mutex_);278 lock_guard<decltype(mutex_)> guard(mutex_);
290279
291 QFutureInterface<QVector<Folder::SPtr>> qf;280 try
292 if (deleted_)
293 {281 {
294 return make_exceptional_future<QVector<Folder::SPtr>>(deleted_ex("Item::parents()"));282 throw_if_destroyed("Item::parents()");
295 }283 }
296284 catch (StorageException const& e)
297 Root::SPtr root = root_.lock();
298 if (!root)
299 {285 {
300 return make_exceptional_future<QVector<Folder::SPtr>>(RuntimeDestroyedException("Item::parents()"));286 return internal::make_exceptional_future<QVector<Folder::SPtr>>(e);
301 }287 }
302288
303 using namespace boost::filesystem;289 using namespace boost::filesystem;
@@ -306,10 +292,11 @@
306 path p = native_identity().toStdString();292 path p = native_identity().toStdString();
307 QString parent_path = QString::fromStdString(p.parent_path().native());293 QString parent_path = QString::fromStdString(p.parent_path().native());
308294
295 auto root = root_.lock();
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: