Merge lp:~gary-wzl77/mcloud/job_uuid into lp:mcloud/devel

Proposed by Gary.Wang
Status: Merged
Approved by: Zhang Enwei
Approved revision: 60
Merged at revision: 16
Proposed branch: lp:~gary-wzl77/mcloud/job_uuid
Merge into: lp:mcloud/devel
Diff against target: 8284 lines (+2819/-2895)
52 files modified
CMakeLists.txt (+1/-1)
debian/VERSION (+1/-1)
debian/VERSION.vivid (+1/-1)
debian/changelog (+13/-2)
debian/control (+2/-0)
debian/control.in (+2/-0)
debian/libmcloud0.install (+0/-3)
debian/libmcloud1.install (+0/-3)
debian/libmcloud2.install (+3/-0)
include/mcloud/api/client.h (+32/-34)
include/mcloud/api/cloudcontent.h (+18/-18)
include/mcloud/api/cloudfolder.h (+14/-14)
include/mcloud/api/cloudresource.h (+13/-13)
include/mcloud/api/diskinfo.h (+7/-6)
include/mcloud/api/downloadtask.h (+16/-19)
include/mcloud/api/exceptions.h (+49/-49)
include/mcloud/api/outlink.h (+9/-9)
include/mcloud/api/syncmanager.h (+12/-12)
include/mcloud/api/task.h (+10/-10)
include/mcloud/api/taskqueue.h (+11/-10)
include/mcloud/api/uploadtask.h (+18/-22)
provider/CMakeLists.txt (+2/-2)
provider/McloudProvider.cpp (+0/-666)
provider/McloudProvider.h (+0/-82)
provider/main.cpp (+10/-12)
provider/mcloudprovider.cpp (+648/-0)
provider/mcloudprovider.h (+82/-0)
src/mcloud/api/client.cpp (+45/-53)
src/mcloud/api/client_priv.cpp (+628/-632)
src/mcloud/api/client_priv.h (+63/-63)
src/mcloud/api/cloudcontent.cpp (+53/-50)
src/mcloud/api/cloudfolder.cpp (+40/-38)
src/mcloud/api/diskinfo.cpp (+8/-5)
src/mcloud/api/downloadtask.cpp (+10/-11)
src/mcloud/api/downloadtask_priv.cpp (+44/-44)
src/mcloud/api/downloadtask_priv.h (+28/-28)
src/mcloud/api/outlink.cpp (+11/-8)
src/mcloud/api/syncmanager.cpp (+10/-7)
src/mcloud/api/syncmanager_priv.cpp (+6/-10)
src/mcloud/api/syncmanager_priv.h (+10/-11)
src/mcloud/api/syncthread.cpp (+107/-116)
src/mcloud/api/syncthread.h (+3/-3)
src/mcloud/api/taskhandler.h (+32/-24)
src/mcloud/api/uploadtask.cpp (+10/-11)
src/mcloud/api/uploadtask_priv.cpp (+46/-46)
src/mcloud/api/uploadtask_priv.h (+33/-33)
tests/server/server.py (+1/-1)
tests/unit/mcloud-provider/CMakeLists.txt (+1/-1)
tests/unit/mcloud-provider/mcloud-provider-unit-tests.cpp (+133/-163)
tests/unit/mcloud/CMakeLists.txt (+0/-3)
tests/unit/mcloud/api/mcloud-rest-test.cpp (+217/-233)
tests/unit/mcloud/api/mcloud-sync-test.cpp (+306/-312)
To merge this branch: bzr merge lp:~gary-wzl77/mcloud/job_uuid
Reviewer Review Type Date Requested Status
unity-api-1-bot continuous-integration Approve
Zhang Enwei (community) Approve
Review via email: mp+308474@code.launchpad.net

Commit message

1.generate job id with uuid.
2.reduce the size of temporary generated file.

Description of the change

1.generate job id with uuid.
2.reduce the size of temporary generated file.

To post a comment you must log in.
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:54
https://jenkins.canonical.com/unity-api-1/job/lp-mcloud-ci/26/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/886
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/893
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/699
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/699/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/699
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/699/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/699
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/699/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/699
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/699/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/699
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/699/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/699
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/699/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/699
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/699/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/699
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/699/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/699
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/699/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-mcloud-ci/26/rebuild

review: Approve (continuous-integration)
lp:~gary-wzl77/mcloud/job_uuid updated
55. By Gary.Wang

little printout fixed

56. By Gary.Wang

making code look better.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:56
https://jenkins.canonical.com/unity-api-1/job/lp-mcloud-ci/27/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/888
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/895
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/701
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/701/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/701
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/701/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/701
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/701/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/701
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/701/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/701
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/701/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/701
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/701/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/701
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/701/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/701
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/701/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/701
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/701/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-mcloud-ci/27/rebuild

review: Approve (continuous-integration)
Revision history for this message
Zhang Enwei (zhangew401) wrote :

LGTM

review: Approve
lp:~gary-wzl77/mcloud/job_uuid updated
57. By Gary.Wang

get rid of std::bind and use lamda.

58. By Gary.Wang

code formatting.

59. By Gary.Wang

1.more unique_ptr instead of shared_ptr
2.code formatting.

60. By Gary.Wang

1.add missing dependency(account-plugin-mcloud)
2.generate job upload id with uuid.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:60
https://jenkins.canonical.com/unity-api-1/job/lp-mcloud-ci/28/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/911
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/918
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/721
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/721/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/721
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/721/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/721
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/721/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/721
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/721/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/721
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/721/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/721
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/721/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/721
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/721/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/721
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/721/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/721
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/721/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-mcloud-ci/28/rebuild

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-09-17 14:21:57 +0000
3+++ CMakeLists.txt 2016-10-26 10:36:06 +0000
4@@ -28,7 +28,7 @@
5 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -fno-strict-aliasing -fvisibility=hidden -fvisibility-inlines-hidden -pedantic -Wextra")
6 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
7
8-set(MCLOUD_LIB_VERSION_MAJOR 1)
9+set(MCLOUD_LIB_VERSION_MAJOR 2)
10 set(MCLOUD_LIB_VERSION_MINOR 0)
11 set(MCLOUD_LIB_VERSION_PATCH 0)
12
13
14=== modified file 'debian/VERSION'
15--- debian/VERSION 2016-09-17 14:21:57 +0000
16+++ debian/VERSION 2016-10-26 10:36:06 +0000
17@@ -1,1 +1,1 @@
18-1
19+2
20
21=== modified file 'debian/VERSION.vivid'
22--- debian/VERSION.vivid 2016-09-17 14:21:57 +0000
23+++ debian/VERSION.vivid 2016-10-26 10:36:06 +0000
24@@ -1,1 +1,1 @@
25-0
26+1
27
28=== modified file 'debian/changelog'
29--- debian/changelog 2016-09-17 14:21:57 +0000
30+++ debian/changelog 2016-10-26 10:36:06 +0000
31@@ -1,4 +1,12 @@
32-mcloud (1.0.0-0ubuntu1) UNRELEASED; urgency=medium
33+mcloud (2.0.0-0ubuntu1) UNRELEASED; urgency=medium
34+
35+ [ Gary.Wzl]
36+ * add missing dependency(account-plugin-mcloud)
37+ * generate job upload id with uuid.
38+
39+ -- Gary.Wang <gary.wang@canonical.com> Wed, 26 Oct 2016 16:58:11 +0800
40+
41+mcloud (1.0.0+16.10.20160927.3-0ubuntu1) yakkety; urgency=medium
42
43 [ Gary Wang ]
44 * Update provider to enable data streaming directly without local cache.
45@@ -29,4 +37,7 @@
46 * Add status handler for download and upload task.
47 * Remove deprecated API(set_auth_info).
48
49- -- Gary Wang <gary.wang@canonical.com> Mon, 04 Jul 2016 16:09:14 +0800
50+ [ Gary.Wzl ]
51+ * First landing of mcloud library.
52+
53+ -- Gary.Wang <gary.wang@canonical.com> Tue, 27 Sep 2016 04:44:02 +0000
54
55=== modified file 'debian/control'
56--- debian/control 2016-09-17 14:21:57 +0000
57+++ debian/control 2016-10-26 10:36:06 +0000
58@@ -30,6 +30,7 @@
59 python3-dbus,
60 python3-gi,
61 libglib2.0-dev,
62+ lsb-release,
63 Standards-Version: 3.9.5
64 Section: libs
65 Homepage: https://launchpad.net/mcloud
66@@ -42,6 +43,7 @@
67 Pre-Depends: ${misc:Pre-Depends},
68 Depends: ${misc:Depends},
69 ${shlibs:Depends},
70+ account-plugin-mcloud,
71 Description: A C++ library for open API of cmcc mcloud service
72 Mcloud API provides developers easily access to authenticated
73 user's cmcc mcloud resources.
74
75=== modified file 'debian/control.in'
76--- debian/control.in 2016-09-17 14:21:57 +0000
77+++ debian/control.in 2016-10-26 10:36:06 +0000
78@@ -25,6 +25,7 @@
79 python3-dbus,
80 python3-gi,
81 libglib2.0-dev,
82+ lsb-release,
83 Standards-Version: 3.9.5
84 Section: libs
85 Homepage: https://launchpad.net/mcloud
86@@ -37,6 +38,7 @@
87 Pre-Depends: ${misc:Pre-Depends},
88 Depends: ${misc:Depends},
89 ${shlibs:Depends},
90+ account-plugin-mcloud,
91 Description: A C++ library for open API of cmcc mcloud service
92 Mcloud API provides developers easily access to authenticated
93 user's cmcc mcloud resources.
94
95=== removed file 'debian/libmcloud0.install'
96--- debian/libmcloud0.install 2016-09-13 02:13:23 +0000
97+++ debian/libmcloud0.install 1970-01-01 00:00:00 +0000
98@@ -1,3 +0,0 @@
99-usr/lib/*/lib*.so.*
100-usr/bin/*
101-usr/share/dbus-1/services/*
102
103=== added file 'debian/libmcloud1.install'
104--- debian/libmcloud1.install 1970-01-01 00:00:00 +0000
105+++ debian/libmcloud1.install 2016-10-26 10:36:06 +0000
106@@ -0,0 +1,3 @@
107+usr/lib/*/lib*.so.*
108+usr/bin/*
109+usr/share/dbus-1/services/*
110
111=== removed file 'debian/libmcloud1.install'
112--- debian/libmcloud1.install 2016-09-17 14:21:57 +0000
113+++ debian/libmcloud1.install 1970-01-01 00:00:00 +0000
114@@ -1,3 +0,0 @@
115-usr/lib/*/lib*.so.*
116-usr/bin/*
117-usr/share/dbus-1/services/*
118
119=== added file 'debian/libmcloud2.install'
120--- debian/libmcloud2.install 1970-01-01 00:00:00 +0000
121+++ debian/libmcloud2.install 2016-10-26 10:36:06 +0000
122@@ -0,0 +1,3 @@
123+usr/lib/*/lib*.so.*
124+usr/bin/*
125+usr/share/dbus-1/services/*
126
127=== modified file 'include/mcloud/api/client.h'
128--- include/mcloud/api/client.h 2016-09-26 01:43:23 +0000
129+++ include/mcloud/api/client.h 2016-10-26 10:36:06 +0000
130@@ -31,8 +31,6 @@
131 #include <mcloud/api/syncmanager.h>
132
133 #include <deque>
134-/*#include <future>*/
135-/*#include <thread>*/
136
137 namespace mcloud {
138 namespace api {
139@@ -59,7 +57,7 @@
140
141 \note Mcloud API covers cloud resourece access and content sync-up between local and cloud. It does not take
142 responsibility of account authentication. So before using mcloud APIs, developers need to call \sa set_access_token to
143- manually set a valid access_token or \sa refresh_token to fetch access token,
144+ manually set a valid access_token or \sa refresh_token to fetch access token,
145 which is used to call mcloud APIs internally to pass through authentication.
146 */
147
148@@ -90,7 +88,7 @@
149 * \brief Set \a access_token to authenticate all mcloud API calls with the bearer HTTP authorization scheme.
150 * The access token can be fetched through ubuntu sso services.
151 */
152- void set_access_token(const std::string &access_token);
153+ void set_access_token(const std::string& access_token);
154
155 /*!
156 * \brief Retrieves and refreshes access token by using \a refresh_token.
157@@ -98,14 +96,14 @@
158 * \throw std::runtime_error if error occurs.
159 * \returns true if access token is refreshed, otherwise returns false.
160 */
161- bool refresh_token(const std::string &refresh_token);
162+ bool refresh_token(const std::string& refresh_token);
163
164 /*!
165 * \brief Returns login user's clcoud storage info.
166 * \throw std::runtime_error if error occurs.
167 * @sa DiskInfo
168 */
169- DiskInfo disk_info();
170+ DiskInfo::Ptr disk_info();
171
172 /*!
173 * \brief Returns root folder id on mlcoud for third-party app to use, such as mcloud-lib.
174@@ -128,7 +126,7 @@
175 ResourceList cloud_content_list(int start_index,
176 int count,
177 CloudContent::Type content_type = CloudContent::Type::All,
178- const std::string &folder_id = std::string());
179+ const std::string& folder_id = std::string());
180
181 /*!
182 * \brief Returns a cloud content object if a content \a content_id exists on mcloud.
183@@ -136,7 +134,7 @@
184 * \throw std::runtime_error if error occurs.
185 * \sa delete_contents(), move_items()
186 */
187- CloudContent::Ptr content_info(const std::string & content_id);
188+ CloudContent::Ptr content_info(const std::string& content_id);
189
190 /*!
191 * \brief Returns a cloud folder object if a folder with \a folder_name is created under a given \a folder_id folder.
192@@ -144,8 +142,8 @@
193 * \throw std::runtime_error if error occurs.
194 * \sa delete_contents(), move_items()
195 */
196- CloudFolder::Ptr create_folder(const std::string &folder_name,
197- const std::string &folder_id);
198+ CloudFolder::Ptr create_folder(const std::string& folder_name,
199+ const std::string& folder_id);
200
201 /*!
202 * \brief Returns a cloud item list if there are available items that matches with \a name under a given \a folder_id folder.
203@@ -155,25 +153,25 @@
204 */
205
206 [[gnu::deprecated("cmcc closes this api for security reason")]]
207- Client::ResourceList look_up(const std::string &name,
208- const std::string &folder_id,
209+ Client::ResourceList look_up(const std::string& name,
210+ const std::string& folder_id,
211 CloudResource::Property property = CloudResource::Property::Content);
212
213 /*!
214- * \brief Creates folders extranet link object with a given \a folder_ids.
215+ * \brief Creates folders sharing url object with a given \a folder_ids.
216 * \throw std::runtime_error if error occurs.
217- * \sa create_content_extranet_link()
218- * \return a list of Outlink after extranet links are created.
219+ * \sa create_content_sharing_url()
220+ * \return a list of Outlink after sharing urls are created.
221 */
222- OutlinkList create_folder_extranet_link(const Stringlist &folder_ids);
223+ OutlinkList create_folder_sharing_url(const Stringlist& folder_ids);
224
225 /*!
226- * \brief Creates a content_extranet link object with a given \a content_ids.
227+ * \brief Creates a content_sharing url object with a given \a content_ids.
228 * \throw std::runtime_error if error occurs.
229- * \sa create_folder_extranet_link()
230- * \return a list of Outlink after extranet links are created.
231+ * \sa create_folder_sharing_url()
232+ * \return a list of Outlink after sharing urls are created.
233 */
234- OutlinkList create_content_extranet_link(const Stringlist &content_ids);
235+ OutlinkList create_content_sharing_url(const Stringlist& content_ids);
236
237 /*!
238 * \brief Returns folder id list if folders \a folder_ids are copies to another folder with a given \a folder_id on mcloud
239@@ -181,8 +179,8 @@
240 * \note the destination folder \a folder_id should not be the same as the folders' \a folder_ids folder ids.
241 * \sa move_items(), update_folder(), copy_contents()
242 */
243- Client::Stringlist copy_folders(const Stringlist &folder_ids,
244- const std::string &_folder_id);
245+ Client::Stringlist copy_folders(const Stringlist& folder_ids,
246+ const std::string& folder_id);
247
248 /*!
249 * \brief Returns content id list if contents \a content_ids are copies to another folder with a given \a folder_id on mcloud.
250@@ -190,8 +188,8 @@
251 * \note the destination folder \a folder_id should not be the same as the contents' \a contents_ids folder id.
252 * \sa move_items(), update_folder(), copy_folders()
253 */
254- Client::Stringlist copy_contents(const Stringlist &contents_ids,
255- const std::string &folder_id);
256+ Client::Stringlist copy_contents(const Stringlist& contents_ids,
257+ const std::string& folder_id);
258
259 /*!
260 * \brief Returns true if \a folders with a given folder_ids and \a contents with a given \a content_ids
261@@ -199,32 +197,32 @@
262 * \throw std::runtime_error if error occurs.
263 * \sa delete_contents(), copy_folders(), copy_contents()
264 */
265- bool move_items(const Stringlist &folder_ids,
266- const Stringlist &content_ids,
267- const std::string &folder_id);
268+ bool move_items(const Stringlist& folder_ids,
269+ const Stringlist& content_ids,
270+ const std::string& folder_id);
271
272 /*!
273 * \brief Returns true if folder \a folder_id are updated with \a new_folder_name, otherwise return false.
274 * \throw std::runtime_error if error occurs.
275 * \sa delete_contents(), copy_folders(),
276 */
277- bool update_folder(const std::string &folder_id,
278- const std::string &new_folder_name);
279+ bool update_folder(const std::string& folder_id,
280+ const std::string& new_folder_name);
281
282 /*!
283 * \brief Returns true if contents \a content_ids are deleted, otherwise return false.
284 * \throw std::runtime_error if error occurs.
285 * \sa move_items(), content_info(), copy_contents()
286 */
287- bool delete_contents(const Stringlist &content_ids);
288+ bool delete_contents(const Stringlist& content_ids);
289
290 /*!
291- * \brief Returns true if a local file \a file_path exists in folder with \a folder_id on cloud,
292+ * \brief Returns true if a local file \a file_path exists in folder with \a folder_id on cloud,
293 * otherwise return false. Searches root folder if folder_id is empty();
294 * \throw std::runtime_error if error occurs.
295 */
296- bool exist_on_cloud(const std::string &file_path,
297- const std::string &folder_id = std::string());
298+ bool exist_on_cloud(const std::string& file_path,
299+ const std::string& folder_id = std::string());
300
301 /*!
302 * \brief Returns a sync-up manager running on the background.
303@@ -233,7 +231,7 @@
304 SyncManager::Ptr syncmanager() const;
305
306 private:
307- std::shared_ptr<ClientPriv> p_;
308+ std::unique_ptr<ClientPriv> p_;
309
310 };
311
312
313=== modified file 'include/mcloud/api/cloudcontent.h'
314--- include/mcloud/api/cloudcontent.h 2016-09-26 01:43:23 +0000
315+++ include/mcloud/api/cloudcontent.h 2016-10-26 10:36:06 +0000
316@@ -23,7 +23,7 @@
317 #include <mcloud/api/visibility.h>
318
319 namespace tinyxml2 {
320- class XMLElement;
321+class XMLElement;
322 }
323
324 namespace mcloud {
325@@ -36,7 +36,7 @@
326 */
327
328 class MCLOUD_API_DLL_PUBLIC CloudContent: public CloudResource {
329-public:
330+ public:
331 typedef std::shared_ptr<CloudContent> Ptr;
332
333 /*!
334@@ -53,42 +53,42 @@
335 PPT ///< ppt content
336 };
337
338- virtual ~CloudContent() = default;
339+ ~CloudContent();
340
341 /*!
342 * \brief Returns a unique id of cloud content object.
343 */
344- const std::string &id() const override;
345+ const std::string& id() const override;
346
347 /*!
348 * \brief Returns the name of cloud content object.
349 */
350- const std::string &name() const override;
351+ const std::string& name() const override;
352
353 /*!
354 * \brief Returns the datetime when content was created.
355 */
356- const std::time_t &created_date() const override;
357+ const std::time_t& created_date() const override;
358
359 /*!
360 * \brief Returns the datetime when content was updated.
361 */
362- const std::time_t &updated_date() const override;
363+ const std::time_t& updated_date() const override;
364
365 /*!
366 * \brief Returns a unique parent folder id of cloud content object.
367 */
368- const std::string &parent_catalog_id() const override;
369+ const std::string& parent_catalog_id() const override;
370
371 /*!
372 * \brief Returns etag of a content object.
373 */
374- const std::string &etag() const override;
375+ const std::string& etag() const override;
376
377 /*!
378 * \brief Returns owner id of a content object.
379 */
380- const std::string &owner() const override;
381+ const std::string& owner() const override;
382
383 /*!
384 * \brief Returns resource type of an object.
385@@ -98,7 +98,7 @@
386 /*!
387 * \brief Returns extension of a content object.
388 */
389- const std::string &suffix() const;
390+ const std::string& suffix() const;
391
392 /*!
393 * \brief Returns content type of an object.
394@@ -113,33 +113,33 @@
395 /*!
396 * \brief Returns the description of a content object.
397 */
398- const std::string &description() const;
399+ const std::string& description() const;
400
401 /*!
402 * \brief Returns thumbnail link of a content object.
403 * It will be empty if there is no such a field in response.
404 */
405- const std::string &thumbnail_url() const;
406+ const std::string& thumbnail_url() const;
407
408 /*!
409 * \brief Returns big thumbnail link of a content object,
410 * It will be empty if there is no such a field in response.
411 */
412- const std::string &big_thumbnail_url() const;
413+ const std::string& big_thumbnail_url() const;
414
415 /*!
416 * \brief Returns a external playable link of a media content object,
417 * It will be empty if there is no such a field in response.
418 */
419- const std::string &present_url() const;
420+ const std::string& present_url() const;
421
422-private:
423- CloudContent(const tinyxml2::XMLElement *root);
424+ private:
425+ CloudContent(const tinyxml2::XMLElement* root);
426
427 friend class ClientPriv;
428
429 class Priv;
430- std::shared_ptr<Priv> p;
431+ std::unique_ptr<Priv> p;
432 };
433
434 }
435
436=== modified file 'include/mcloud/api/cloudfolder.h'
437--- include/mcloud/api/cloudfolder.h 2016-09-26 01:43:23 +0000
438+++ include/mcloud/api/cloudfolder.h 2016-10-26 10:36:06 +0000
439@@ -23,7 +23,7 @@
440 #include <mcloud/api/visibility.h>
441
442 namespace tinyxml2 {
443- class XMLElement;
444+class XMLElement;
445 }
446
447 namespace mcloud {
448@@ -35,7 +35,7 @@
449 */
450
451 class MCLOUD_API_DLL_PUBLIC CloudFolder : public CloudResource {
452-public:
453+ public:
454 enum class Type {
455 Normal = 0,
456 Pictures,
457@@ -49,42 +49,42 @@
458
459 typedef std::shared_ptr<CloudFolder> Ptr;
460
461- virtual ~CloudFolder() = default;
462+ ~CloudFolder();
463
464 /*!
465 * \brief Returns a unique id of cloud folder object.
466 */
467- const std::string &id() const override;
468+ const std::string& id() const override;
469
470 /*!
471 * \brief Returns the name of cloud folder object.
472 */
473- const std::string &name() const override;
474+ const std::string& name() const override;
475
476 /*!
477 * \brief Returns the datetime when folder was created.
478 */
479- const std::time_t &created_date() const override;
480+ const std::time_t& created_date() const override;
481
482 /*!
483 * \brief Returns the datetime when folder was updated.
484 */
485- const std::time_t &updated_date() const override;
486+ const std::time_t& updated_date() const override;
487
488 /*!
489 * \brief Returns a unique id of the parent folder.
490 */
491- const std::string &parent_catalog_id() const override;
492+ const std::string& parent_catalog_id() const override;
493
494 /*!
495 * \brief Returns etag of a folder object.
496 */
497- const std::string &etag() const override;
498+ const std::string& etag() const override;
499
500 /*!
501 * \brief Returns owner id of a folder object.
502 */
503- const std::string &owner() const override;
504+ const std::string& owner() const override;
505
506 /*!
507 * \brief Returns resource property of an object.
508@@ -101,15 +101,15 @@
509 /*!
510 * \brief Returns a current folder's path.
511 */
512- const std::string &folder_path() const;
513+ const std::string& folder_path() const;
514
515-private:
516- CloudFolder(const tinyxml2::XMLElement *root);
517+ private:
518+ CloudFolder(const tinyxml2::XMLElement* root);
519
520 friend class ClientPriv;
521
522 class Priv;
523- std::shared_ptr<Priv> p_;
524+ std::unique_ptr<Priv> p_;
525 };
526
527 }
528
529=== modified file 'include/mcloud/api/cloudresource.h'
530--- include/mcloud/api/cloudresource.h 2016-09-26 01:43:23 +0000
531+++ include/mcloud/api/cloudresource.h 2016-10-26 10:36:06 +0000
532@@ -42,19 +42,19 @@
533
534 virtual ~CloudResource() = default;
535
536- virtual const std::string &id() const = 0;
537-
538- virtual const std::string &name() const = 0;
539-
540- virtual const std::time_t &created_date() const = 0;
541-
542- virtual const std::time_t &updated_date() const = 0;
543-
544- virtual const std::string &parent_catalog_id() const = 0;
545-
546- virtual const std::string &etag() const = 0;
547-
548- virtual const std::string &owner() const = 0;
549+ virtual const std::string& id() const = 0;
550+
551+ virtual const std::string& name() const = 0;
552+
553+ virtual const std::time_t& created_date() const = 0;
554+
555+ virtual const std::time_t& updated_date() const = 0;
556+
557+ virtual const std::string& parent_catalog_id() const = 0;
558+
559+ virtual const std::string& etag() const = 0;
560+
561+ virtual const std::string& owner() const = 0;
562
563 virtual Property property() const = 0;
564 };
565
566=== modified file 'include/mcloud/api/diskinfo.h'
567--- include/mcloud/api/diskinfo.h 2016-09-26 01:43:23 +0000
568+++ include/mcloud/api/diskinfo.h 2016-10-26 10:36:06 +0000
569@@ -24,7 +24,7 @@
570 #include <memory>
571
572 namespace tinyxml2 {
573- class XMLElement;
574+class XMLElement;
575 }
576
577 namespace mcloud {
578@@ -36,8 +36,9 @@
579 */
580
581 class MCLOUD_API_DLL_PUBLIC DiskInfo {
582-public:
583- virtual ~DiskInfo() = default;
584+ public:
585+ typedef std::shared_ptr<DiskInfo> Ptr;
586+ ~DiskInfo();
587
588 /*!
589 * \brief Returns available free disk size of user cloud storage in MB.
590@@ -49,13 +50,13 @@
591 */
592 int disk_size() const;
593
594-private:
595- DiskInfo(const tinyxml2::XMLElement *root);
596+ private:
597+ DiskInfo(const tinyxml2::XMLElement* root);
598
599 friend class ClientPriv;
600
601 class Priv;
602- std::shared_ptr<Priv> p_;
603+ std::unique_ptr<Priv> p_;
604 };
605
606 }
607
608=== modified file 'include/mcloud/api/downloadtask.h'
609--- include/mcloud/api/downloadtask.h 2016-09-26 01:43:23 +0000
610+++ include/mcloud/api/downloadtask.h 2016-10-26 10:36:06 +0000
611@@ -33,8 +33,7 @@
612 \struct DownloadBufferCb
613 \brief DownloadBufferCb is a download request object which consists of a content id and writing callback function allows content data can be received in buffering via call back function.
614 */
615-struct MCLOUD_API_DLL_PUBLIC DownloadBufferCb
616-{
617+struct MCLOUD_API_DLL_PUBLIC DownloadBufferCb {
618 std::string content_id;
619 Task::Buffer_Callback write_cb;
620 };
621@@ -48,45 +47,43 @@
622 basic download item information, also it's used for content download by sync manager.
623 */
624 class MCLOUD_API_DLL_PUBLIC DownloadTask : public Task {
625-public:
626+ public:
627 typedef std::shared_ptr<DownloadTask> Ptr;
628
629- virtual ~DownloadTask() = default;
630-
631- DownloadTask(const DownloadTask& ) = delete;
632-
633- DownloadTask& operator=(const DownloadTask& ) = delete;
634+ DownloadTask(const DownloadTask&) = delete;
635+
636+ DownloadTask& operator=(const DownloadTask&) = delete;
637
638 /*!
639 * Returns an unique id of download task.
640 */
641- const std::string & task_id() const override;
642+ const std::string& task_id() const override;
643
644 /*!
645 * \brief Returns an unique id of cloud content on mcloud.
646 */
647- const std::string & content_id() const override;
648+ const std::string& content_id() const override;
649
650 /*!
651 * \brief Returns a display name of cloud content on mcloud.
652 */
653- const std::string & content_name() const override;
654+ const std::string& content_name() const override;
655
656 /*!
657 * \brief Returns cloud content local storage file path.
658 */
659- const std::string & file_path() const override;
660+ const std::string& file_path() const override;
661
662 /*!
663 * \brief Returns download url assigned by mcloud for this task.
664 * \note this url will be expried after a period of time.
665 */
666- const std::string & task_url() const override;
667+ const std::string& task_url() const override;
668
669 /*!
670 * \brief Contains the error string if an error occurs during content download.
671 */
672- const std::string & error_string() const override;
673+ const std::string& error_string() const override;
674
675 /*!
676 * \brief Returns current sync-up status for this task.
677@@ -98,22 +95,22 @@
678 * \brief Handler for download progress of a task.
679 * \sa Task::ProgressHandler
680 */
681- Task::ProgressHandler & progress_changed() override;
682+ Task::ProgressHandler& progress_changed() override;
683
684 /*!
685 * \brief Handler for download status of a task.
686 * \sa Task::StatusHandler
687 */
688- Task::StatusHandler & status_changed() override;
689+ Task::StatusHandler& status_changed() override;
690
691- /*!
692+ /*!
693 * \brief cancel the task.
694 * \sa Task::StatusHandler
695 */
696 void cancel() override;
697
698-private:
699- DownloadTask(std::shared_ptr<DownloadTaskPriv> p);
700+ private:
701+ DownloadTask(const std::shared_ptr<DownloadTaskPriv>& p);
702
703 friend class SyncManagerPriv;
704
705
706=== modified file 'include/mcloud/api/exceptions.h'
707--- include/mcloud/api/exceptions.h 2016-08-29 04:15:08 +0000
708+++ include/mcloud/api/exceptions.h 2016-10-26 10:36:06 +0000
709@@ -26,55 +26,55 @@
710 namespace mcloud {
711 namespace api {
712
713- /**
714- * \brief Indicates an invalid content id when querying content infomation by an id.
715- * or an invalid folder id when listing or looup content in one specific folder.
716- */
717-
718- class MCLOUD_API_DLL_PUBLIC InvalidIDException : public std::runtime_error {
719- public:
720- using runtime_error::runtime_error;
721- };
722-
723- /*
724- * \brief Indicates a content or folder can not be found on mcloud.
725- */
726- class MCLOUD_API_DLL_PUBLIC NonExistentException : public std::runtime_error {
727- public:
728- using runtime_error::runtime_error;
729- };
730-
731- /**
732- * \brief User ran out of space on mcloud storage.
733- */
734- class MCLOUD_API_DLL_PUBLIC OutofSpaceException : public std::runtime_error {
735- public:
736- using runtime_error::runtime_error;
737- };
738-
739- /**
740- * \brief Indicates a timeout on HTTP requests.
741- */
742- class MCLOUD_API_DLL_PUBLIC HttpTimeoutException : public std::runtime_error {
743- public:
744- using runtime_error::runtime_error;
745- };
746-
747- /*
748- * \brief Indicates one or more http request parameters are invalid.
749- */
750- class MCLOUD_API_DLL_PUBLIC ParameterInvalidException : public std::runtime_error {
751- public:
752- using runtime_error::runtime_error;
753- };
754-
755- /*
756- * \brief Indicates access token is invalid or expired.
757- */
758- class MCLOUD_API_DLL_PUBLIC CredentialException : public std::runtime_error {
759- public:
760- using runtime_error::runtime_error;
761- };
762+/**
763+ * \brief Indicates an invalid content id when querying content infomation by an id.
764+ * or an invalid folder id when listing or looup content in one specific folder.
765+ */
766+
767+class MCLOUD_API_DLL_PUBLIC InvalidIDException : public std::runtime_error {
768+ public:
769+ using runtime_error::runtime_error;
770+};
771+
772+/*
773+ * \brief Indicates a content or folder can not be found on mcloud.
774+ */
775+class MCLOUD_API_DLL_PUBLIC NonExistentException : public std::runtime_error {
776+ public:
777+ using runtime_error::runtime_error;
778+};
779+
780+/**
781+ * \brief User ran out of space on mcloud storage.
782+ */
783+class MCLOUD_API_DLL_PUBLIC OutofSpaceException : public std::runtime_error {
784+ public:
785+ using runtime_error::runtime_error;
786+};
787+
788+/**
789+ * \brief Indicates a timeout on HTTP requests.
790+ */
791+class MCLOUD_API_DLL_PUBLIC HttpTimeoutException : public std::runtime_error {
792+ public:
793+ using runtime_error::runtime_error;
794+};
795+
796+/*
797+ * \brief Indicates one or more http request parameters are invalid.
798+ */
799+class MCLOUD_API_DLL_PUBLIC ParameterInvalidException : public std::runtime_error {
800+ public:
801+ using runtime_error::runtime_error;
802+};
803+
804+/*
805+ * \brief Indicates access token is invalid or expired.
806+ */
807+class MCLOUD_API_DLL_PUBLIC CredentialException : public std::runtime_error {
808+ public:
809+ using runtime_error::runtime_error;
810+};
811
812 }
813 }
814
815=== modified file 'include/mcloud/api/outlink.h'
816--- include/mcloud/api/outlink.h 2016-09-06 09:12:43 +0000
817+++ include/mcloud/api/outlink.h 2016-10-26 10:36:06 +0000
818@@ -25,7 +25,7 @@
819 #include <string>
820
821 namespace tinyxml2 {
822- class XMLElement;
823+class XMLElement;
824 }
825
826 namespace mcloud {
827@@ -33,32 +33,32 @@
828
829 /*!
830 \class Outlink
831- \brief Outlink is a cloud extranet link that contains extranet link which can be share by user to others.
832+ \brief Outlink is a link object that contains extranet link which can be share by user to others.
833 */
834
835 class MCLOUD_API_DLL_PUBLIC Outlink {
836-public:
837+ public:
838 typedef std::shared_ptr<Outlink> Ptr;
839
840- virtual ~Outlink() = default;
841+ ~Outlink();
842
843 /*!
844 * \brief Returns a unique id of extranet object assigned by mcloud.
845 */
846- const std::string &id() const;
847+ const std::string& id() const;
848
849 /*!
850 * \brief Returns a unique id of extranet link assigned by mcloud.
851 */
852- const std::string &link() const;
853+ const std::string& link() const;
854
855-private:
856- Outlink(const tinyxml2::XMLElement *root);
857+ private:
858+ Outlink(const tinyxml2::XMLElement* root);
859
860 friend class ClientPriv;
861
862 class Priv;
863- std::shared_ptr<Priv> p_;
864+ std::unique_ptr<Priv> p_;
865 };
866
867 }
868
869=== modified file 'include/mcloud/api/syncmanager.h'
870--- include/mcloud/api/syncmanager.h 2016-09-26 01:43:23 +0000
871+++ include/mcloud/api/syncmanager.h 2016-10-26 10:36:06 +0000
872@@ -35,8 +35,8 @@
873
874 /*!
875 \class SyncManager
876- \brief SyncManager handles all the requests to upload and download.
877- It's constructed around two threads for content synchronization. One for content uploading to cloud, another for cloud item downloading to local.
878+ \brief SyncManager handles all the requests to upload and download.
879+ It's constructed around two threads for content synchronization. One for content uploading to cloud, another for cloud item downloading to local.
880 Both thread are running asynchronously.
881 Calls \sa add_download_tasks() by passing a content id list for cloud content download,
882 Calls \sa add_upload_tasks() by passing a local file list path for local content upload.
883@@ -52,11 +52,11 @@
884
885 typedef std::vector<std::string> Stringlist;
886
887- virtual ~SyncManager() = default;
888+ ~SyncManager();
889
890 SyncManager(const SyncManager&) = delete;
891
892- SyncManager& operator=(const SyncManager &) = delete;
893+ SyncManager& operator=(const SyncManager&) = delete;
894
895 /*!
896 * \brief Starts to run download or upload tasks from sync-up thread.
897@@ -85,7 +85,7 @@
898 * \throw std::runtime_error if error occurs.
899 * \sa add_download_tasks(), DownloadTask
900 */
901- DownloadTask::Ptr add_download_task(const std::string &content_id);
902+ DownloadTask::Ptr add_download_task(const std::string& content_id);
903
904 /*!
905 * \brief Pushes a download buffer callback item \a buffer_cb to sync manager and add regarding upload task into download queue.
906@@ -99,7 +99,7 @@
907 * \throw std::runtime_error if error occurs.
908 * \sa add_download_tasks(), DownloadTask
909 */
910- DownloadTask::Ptr add_download_task(const DownloadBufferCb &buffer_cb);
911+ DownloadTask::Ptr add_download_task(const DownloadBufferCb& buffer_cb);
912
913 /*!
914 * \brief Pushes a upload request item \a request_item to sync manager and add regarding upload task into upload queue.
915@@ -116,11 +116,11 @@
916 * \throw std::runtime_error if error occurs.
917 * \note A file name can not contain any of following characters:
918 * '\', '/', ':', '*', '?', '"', '<', '>', '|'
919- * \note Sync manager will detect if the uploading file is already existing on cloud,
920+ * \note Sync manager will detect if the uploading file is already existing on cloud,
921 * if so, it simply sets the status of upload task completed to avoid duplicated upload.
922 * \sa add_download_tasks(), UploadRequest, UploadTask,
923 */
924- UploadTask::Ptr add_upload_task(const UploadRequest &request_item);
925+ UploadTask::Ptr add_upload_task(const UploadRequest& request_item);
926
927 /*!
928 * \brief Pushes a new upload request object \a buffer_cb to sync manager and add regarding upload task into upload queue.
929@@ -141,7 +141,7 @@
930 * '\', '/', ':', '*', '?', '"', '<', '>', '|'
931 * \sa add_download_tasks(), UploadRequest, UploadTask,
932 */
933- UploadTask::Ptr add_upload_task(const UploadBufferCb &buffer_cb);
934+ UploadTask::Ptr add_upload_task(const UploadBufferCb& buffer_cb);
935
936 /*!
937 * \brief Returns a download task list hold by sync up manager.
938@@ -151,18 +151,18 @@
939 DownloadList download_queue();
940
941 /*!
942- * \brief Returns a upload task list hold by sync up manager.
943+ * \brief Returns a upload task list hold by sync up manager.
944 * Each item in the list contains basic information of associated task.
945 * \sa download_queue(), UploadTask
946 */
947 UploadList upload_queue();
948
949-private:
950+ private:
951 SyncManager(ClientPriv* client_priv);
952
953 friend class ClientPriv;
954
955- std::shared_ptr<SyncManagerPriv> p_;
956+ std::unique_ptr<SyncManagerPriv> p_;
957 };
958
959 }
960
961=== modified file 'include/mcloud/api/task.h'
962--- include/mcloud/api/task.h 2016-09-26 01:43:23 +0000
963+++ include/mcloud/api/task.h 2016-10-26 10:36:06 +0000
964@@ -32,7 +32,7 @@
965 */
966
967 class MCLOUD_API_DLL_PUBLIC Task {
968-public:
969+ public:
970 /*!
971 * \brief The Status enum indicates current status of this task.
972 */
973@@ -49,40 +49,40 @@
974
975 typedef std::function<void(Status)> StatusHandler;
976
977- typedef std::function<size_t(void *dest, size_t buf_size)> Buffer_Callback;
978+ typedef std::function<size_t(void* dest, size_t buf_size)> Buffer_Callback;
979
980 virtual ~Task() = default;
981
982 /*!
983 * \brief Returns an unique id of task.
984 */
985- virtual const std::string & task_id() const = 0;
986+ virtual const std::string& task_id() const = 0;
987
988 /*!
989 * \brief Returns an unique id of cloud content on mcloud.
990 */
991- virtual const std::string & content_id() const = 0;
992+ virtual const std::string& content_id() const = 0;
993
994 /*!
995 * \brief Returns a display name of cloud content on mcloud.
996 */
997- virtual const std::string & content_name() const = 0;
998+ virtual const std::string& content_name() const = 0;
999
1000 /*!
1001 * \brief Returns cloud content local storage file path.
1002 */
1003- virtual const std::string & file_path() const = 0;
1004+ virtual const std::string& file_path() const = 0;
1005
1006 /*!
1007 * \brief Contains the error string if an error occurs during task running.
1008 */
1009- virtual const std::string & error_string() const = 0;
1010+ virtual const std::string& error_string() const = 0;
1011
1012 /*!
1013 * \brief Returns a item url assigned by mcloud.
1014 * \note the url will be expried after a period of time.
1015 */
1016- virtual const std::string & task_url() const = 0;
1017+ virtual const std::string& task_url() const = 0;
1018
1019 /*!
1020 * \brief Returns current download or upload item sync-up status.
1021@@ -93,13 +93,13 @@
1022 * \brief Handler for download or upload progress of a task.
1023 * \sa Task::ProgressHandler
1024 */
1025- virtual Task::ProgressHandler & progress_changed() = 0;
1026+ virtual Task::ProgressHandler& progress_changed() = 0;
1027
1028 /*!
1029 * \brief Handler for download or upload progress of a task.
1030 * \sa Task::StatusHandler
1031 */
1032- virtual Task::StatusHandler & status_changed() = 0;
1033+ virtual Task::StatusHandler& status_changed() = 0;
1034
1035 /*!
1036 * \brief Cancels the task.
1037
1038=== modified file 'include/mcloud/api/taskqueue.h'
1039--- include/mcloud/api/taskqueue.h 2016-05-26 10:47:12 +0000
1040+++ include/mcloud/api/taskqueue.h 2016-10-26 10:36:06 +0000
1041@@ -41,17 +41,17 @@
1042
1043 virtual ~TaskQueue() = default;
1044
1045- TaskQueue(TaskQueue &&queue) {
1046+ TaskQueue(TaskQueue&& queue) {
1047 std::lock_guard<std::mutex> lock(mutex_);
1048 tasks_ = std::move(queue.tasks_);
1049 }
1050
1051- TaskQueue(const TaskQueue &queue) {
1052+ TaskQueue(const TaskQueue& queue) {
1053 std::lock_guard<std::mutex> lock(mutex_);
1054 tasks_ = queue.tasks_;
1055 }
1056
1057- TaskQueue &operator= (const TaskQueue &queue) {
1058+ TaskQueue& operator= (const TaskQueue& queue) {
1059 if (this != &queue) {
1060 std::lock_guard<std::mutex> lock1(mutex_);
1061 std::lock_guard<std::mutex> lock2(queue.mutex_);
1062@@ -91,30 +91,31 @@
1063 return tasks_.empty();
1064 }
1065
1066- void push(const T &task) {
1067+ void push(const T& task) {
1068 std::lock_guard<std::mutex> lock(mutex_);
1069 tasks_.push_back(task);
1070 }
1071
1072- void push(const TaskQueue & queue) {
1073+ void push(const TaskQueue& queue) {
1074 std::lock_guard<std::mutex> lock(mutex_);
1075- for (const T & task: queue.tasks_){
1076+ for (const T& task : queue.tasks_) {
1077 tasks_.push_back(task);
1078 }
1079 }
1080
1081- bool try_pop(T &task) {
1082+ bool try_pop(T& task) {
1083 std::lock_guard<std::mutex> lock(mutex_);
1084
1085- if (tasks_.empty())
1086- return false;
1087+ if (tasks_.empty()) {
1088+ return false;
1089+ }
1090
1091 task = tasks_.front();
1092 tasks_.pop_front();
1093 return true;
1094 }
1095
1096- const T & operator[](int index) const {
1097+ const T& operator[](int index) const {
1098 std::lock_guard<std::mutex> lock(mutex_);
1099 return tasks_[index];
1100 }
1101
1102=== modified file 'include/mcloud/api/uploadtask.h'
1103--- include/mcloud/api/uploadtask.h 2016-09-26 01:43:23 +0000
1104+++ include/mcloud/api/uploadtask.h 2016-10-26 10:36:06 +0000
1105@@ -32,10 +32,9 @@
1106
1107 /*!
1108 \struct UploadRequest
1109- \brief UploadRequest is a upload request item which consists of a upload folder id, up-front buffer size, upload content name
1110+ \brief UploadRequest is a upload request item which consists of a upload folder id, up-front buffer size, upload content name
1111 */
1112-struct MCLOUD_API_DLL_PUBLIC UploadRequest
1113-{
1114+struct MCLOUD_API_DLL_PUBLIC UploadRequest {
1115 std::string file_path;
1116 std::string folder_id;
1117 std::string content_name;
1118@@ -44,10 +43,9 @@
1119
1120 /*!
1121 \struct UploadBufferCb
1122- \brief UploadBufferCb is a upload request item which consists of a upload folder id, upload buffer size, upload content name and reading callback function allows content data can be received in buffering via call back function.
1123+ \brief UploadBufferCb is a upload request item which consists of a upload folder id, upload buffer size, upload content name and reading callback function allows content data can be received in buffering via call back function.
1124 */
1125-struct MCLOUD_API_DLL_PUBLIC UploadBufferCb
1126-{
1127+struct MCLOUD_API_DLL_PUBLIC UploadBufferCb {
1128 Task::Buffer_Callback read_cb;
1129 size_t buffer_size;
1130 std::string folder_id;
1131@@ -64,45 +62,43 @@
1132 basic upload item information, also it's used for content upload by sync manager.
1133 */
1134 class MCLOUD_API_DLL_PUBLIC UploadTask : public Task {
1135-public:
1136+ public:
1137 typedef std::shared_ptr<UploadTask> Ptr;
1138
1139- virtual ~UploadTask() = default;
1140-
1141- UploadTask(const UploadTask& ) = delete;
1142-
1143- UploadTask& operator=(const UploadTask& ) = delete;
1144+ UploadTask(const UploadTask&) = delete;
1145+
1146+ UploadTask& operator=(const UploadTask&) = delete;
1147
1148 /*!
1149 * \brief Returns an unique id of upload task.
1150 */
1151- const std::string & task_id() const override;
1152+ const std::string& task_id() const override;
1153
1154 /*!
1155 * \brief Returns an unique id of cloud content on mcloud.
1156 */
1157- const std::string & content_id() const override;
1158+ const std::string& content_id() const override;
1159
1160 /*!
1161 * \brief Returns a display name of local content.
1162 */
1163- const std::string & content_name() const override;
1164+ const std::string& content_name() const override;
1165
1166 /*!
1167 * \brief Returns uploaded local content file path.
1168 */
1169- const std::string & file_path() const override;
1170+ const std::string& file_path() const override;
1171
1172 /*!
1173 * \brief Contains the error string if an error occurs during content uploading.
1174 */
1175- const std::string & error_string() const override;
1176+ const std::string& error_string() const override;
1177
1178 /*!
1179 * \brief Returns upload url assigned by mcloud for this task.
1180 * \note the url will be expired after a period of time.
1181 */
1182- const std::string & task_url() const override;
1183+ const std::string& task_url() const override;
1184
1185 /*!
1186 * \brief Returns current sync-up status for this task.
1187@@ -113,13 +109,13 @@
1188 * \brief Handler for upload progress of a task.
1189 * \sa Task::ProgressHandler
1190 */
1191- Task::ProgressHandler & progress_changed() override;
1192+ Task::ProgressHandler& progress_changed() override;
1193
1194 /*!
1195 * \brief Handler for upload status of a task.
1196 * \sa Task::StatusHandler
1197 */
1198- Task::StatusHandler & status_changed() override;
1199+ Task::StatusHandler& status_changed() override;
1200
1201 /*!
1202 * \brief cancel the task.
1203@@ -137,8 +133,8 @@
1204 */
1205 bool is_need_upload() const;
1206
1207-private:
1208- UploadTask(std::shared_ptr<UploadTaskPriv> p);
1209+ private:
1210+ UploadTask(const std::shared_ptr<UploadTaskPriv>& p);
1211
1212 friend class SyncManagerPriv;
1213
1214
1215=== modified file 'provider/CMakeLists.txt'
1216--- provider/CMakeLists.txt 2016-09-20 02:39:38 +0000
1217+++ provider/CMakeLists.txt 2016-10-26 10:36:06 +0000
1218@@ -7,9 +7,9 @@
1219
1220 add_definitions(-DBOOST_THREAD_VERSION=4)
1221
1222-add_executable(mcloud-provider main.cpp McloudProvider.cpp)
1223+add_library(mcloud-provider-static STATIC mcloudprovider.cpp)
1224
1225-add_library(mcloud-provider-static STATIC McloudProvider.cpp)
1226+add_executable(mcloud-provider main.cpp mcloudprovider.cpp)
1227
1228 target_link_libraries(
1229 mcloud-provider
1230
1231=== removed file 'provider/McloudProvider.cpp'
1232--- provider/McloudProvider.cpp 2016-09-26 01:43:23 +0000
1233+++ provider/McloudProvider.cpp 1970-01-01 00:00:00 +0000
1234@@ -1,666 +0,0 @@
1235-/*
1236- * Copyright (C) 2016 Canonical Ltd
1237- *
1238- * This program is free software: you can redistribute it and/or modify
1239- * it under the terms of the GNU Lesser General Public License version 3 as
1240- * published by the Free Software Foundation.
1241- *
1242- * This program is distributed in the hope that it will be useful,
1243- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1244- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1245- * GNU Lesser General Public License for more details.
1246- *
1247- * You should have received a copy of the GNU Lesser General Public License
1248- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1249- *
1250- * Authors: Gary Wang <gary.wang@canonical.com>
1251- */
1252-
1253-#include "McloudProvider.h"
1254-#include <unity/storage/provider/ProviderBase.h>
1255-#include <unity/storage/provider/TempfileUploadJob.h>
1256-#include <unity/storage/provider/UploadJob.h>
1257-#include <unity/storage/provider/DownloadJob.h>
1258-#include <unity/storage/provider/metadata_keys.h>
1259-#include <unity/storage/provider/Exceptions.h>
1260-
1261-#include <boost/thread.hpp>
1262-#include <boost/thread/future.hpp>
1263-#include <boost/filesystem.hpp>
1264-#include <boost/make_shared.hpp>
1265-
1266-#include <unistd.h>
1267-#include <sys/socket.h>
1268-#include <iostream>
1269-#include <memory>
1270-#include <mutex>
1271-#include <stdexcept>
1272-
1273-#include <mcloud/api/client.h>
1274-#include <mcloud/api/uploadtask.h>
1275-#include <mcloud/api/syncmanager.h>
1276-#include <mcloud/api/cloudresource.h>
1277-#include <mcloud/api/cloudcontent.h>
1278-#include <mcloud/api/cloudfolder.h>
1279-#include <mcloud/api/exceptions.h>
1280-
1281-using namespace std;
1282-using namespace unity::storage;
1283-using namespace unity::storage::provider;
1284-using namespace mcloud::api;
1285-
1286-using boost::make_ready_future;
1287-using boost::make_exceptional_future;
1288-
1289-namespace {
1290- static const int TIME_OUT = 10;
1291- static const int CLIENT_COUNT = 3;
1292-
1293- static const char *FOLDER_TYPE[] = {"normal", "pictures", "music", "videos", "message", "docs", "app", "sync"};
1294- static const char *CONTENT_TYPE[] = {"all", "image", "audio", "video", "other", "doc", "spreadsheet", "ppt"};
1295- static const char *STATUS[] = {"unstart", "running", "canceled", "paused", "broken", "complete"};
1296-
1297- string make_job_id()
1298- {
1299- static int last_upload_id = 0;
1300- return to_string(++last_upload_id);
1301- }
1302-
1303- string status_to_string(Task::Status status)
1304- {
1305- return STATUS[int(status)];
1306- }
1307-
1308- string folder_type_to_string(CloudFolder::Type type)
1309- {
1310- return FOLDER_TYPE[int(type)];
1311- }
1312-
1313- string content_type_to_string(CloudContent::Type type)
1314- {
1315- return CONTENT_TYPE[int(type)];
1316- }
1317-
1318- string time_to_iso(time_t t)
1319- {
1320- char buf[sizeof "2016-08-11T15:10:07+0000"];
1321- strftime(buf, sizeof buf, "%FT%T%z", gmtime(&t));
1322- return buf;
1323- }
1324-
1325- int pending_jobs_count(Client::Ptr client, McloudProvider::JobMode mode)
1326- {
1327- int count = 0;
1328- auto syncmanager = client->syncmanager();
1329- if (mode == McloudProvider::JobMode::Download) {
1330- auto download_task_queue = syncmanager->download_queue();
1331- for (auto & item_ptr : download_task_queue) {
1332- if (item_ptr->status() == Task::Status::Running
1333- || item_ptr->status() == Task::Status::Paused
1334- || item_ptr->status() == Task::Status::Unstart) {
1335- count++;
1336- }
1337- }
1338- } else if (mode == McloudProvider::JobMode::Upload) {
1339- auto upload_task_queue = syncmanager->upload_queue();
1340- for (auto & item_ptr : upload_task_queue) {
1341- if (item_ptr->status() == Task::Status::Running
1342- || item_ptr->status() == Task::Status::Paused
1343- || item_ptr->status() == Task::Status::Unstart) {
1344- count++;
1345- }
1346- }
1347- }
1348-
1349- return count;
1350- }
1351-
1352- Item content_to_item(CloudResource::Ptr resource)
1353- {
1354- Item item;
1355- item.item_id = resource->id();
1356- item.parent_ids = {resource->parent_catalog_id()};
1357- item.name = resource->name();
1358- item.etag = resource->etag();
1359- item.metadata["owner"] = resource->owner();
1360- item.metadata[provider::CREATION_TIME] = time_to_iso(resource->created_date());
1361- item.metadata[provider::LAST_MODIFIED_TIME] = time_to_iso(resource->updated_date());
1362- if (resource->property() == CloudResource::Property::Folder) {
1363- item.type = ItemType::folder;
1364- auto folder = std::static_pointer_cast<mcloud::api::CloudFolder>(resource);
1365- item.metadata["folder_type"] = folder_type_to_string(folder->folder_type());
1366- item.metadata["folder_path"] = folder->folder_path();
1367- } else if (resource->property() == CloudResource::Property::Content){
1368- item.type = ItemType::file;
1369- auto file = std::static_pointer_cast<mcloud::api::CloudContent>(resource);
1370- item.metadata["suffix"] = file->suffix();
1371- item.metadata["content_type"] = content_type_to_string(file->type());
1372-
1373- item.metadata[provider::SIZE_IN_BYTES] = file->content_size();
1374- item.metadata["description"] = file->description();
1375- item.metadata["thumbnail_url"] = file->thumbnail_url();
1376- item.metadata["big_thumbnail_url"] = file->big_thumbnail_url();
1377- item.metadata["present_url"] = file->big_thumbnail_url();
1378- }
1379-
1380- return item;
1381- }
1382-}
1383-
1384-class McloudUploadJob : public UploadJob
1385-{
1386-public:
1387- McloudUploadJob(string const& upload_id,
1388- string const& parent_id,
1389- string const& file_name,
1390- int64_t size,
1391- bool allow_overwrite,
1392- Client::Ptr client);
1393-
1394- boost::future<void> cancel() override;
1395- boost::future<Item> finish() override;
1396-private:
1397- boost::future<tuple<bool, string>> upload_data();
1398- void stop_and_cancel();
1399-private:
1400- ssize_t feed_size;
1401- string parent_id_;
1402- string file_name_;
1403- int64_t upload_size_;
1404- bool allow_overwrite_;
1405-
1406- boost::future<tuple<bool, string>> upload_future_;
1407-
1408- std::mutex mutex_;
1409-
1410- UploadTask::Ptr task_;
1411- Client::Ptr client_;
1412-};
1413-
1414-class McloudDownloadJob : public DownloadJob
1415-{
1416-public:
1417- McloudDownloadJob(string const& download_id,
1418- string const& item_id,
1419- Client::Ptr client);
1420-
1421- boost::future<void> cancel() override;
1422- boost::future<void> finish() override;
1423-private:
1424- boost::future<tuple<bool, string>> download_data();
1425- void send_data();
1426- void stop_and_cancel();
1427-private:
1428- string item_id_;
1429- boost::future<tuple<bool, string>> download_future_;
1430-
1431- std::mutex mutex_;
1432-
1433- DownloadTask::Ptr task_;
1434- Client::Ptr client_;
1435-};
1436-
1437-McloudProvider::McloudProvider()
1438- : client_list_(CLIENT_COUNT, std::make_shared<Client>(TIME_OUT))
1439-{
1440-}
1441-
1442-boost::future<ItemList> McloudProvider::roots(Context const& ctx)
1443-{
1444- return boost::async([this, ctx](){
1445- try {
1446- auto client = assign_client(ctx);
1447- auto root_folder_id = client->cloud_root_folder_id();
1448-
1449- ItemList roots = {
1450- {root_folder_id, {}, "root", "", ItemType::root, {}}
1451- };
1452-
1453- return make_ready_future<ItemList>(roots);
1454- } catch (runtime_error &e) {
1455- return make_exceptional_future<ItemList>(
1456- RemoteCommsException(string("McloudProvider::roots(): failed: ") + e.what()));
1457- }
1458- });
1459-}
1460-
1461-boost::future<tuple<ItemList,string>> McloudProvider::list(
1462- string const& item_id, string const& page_token,
1463- Context const& ctx)
1464-{
1465- int page_token_index = 0;
1466- if (!page_token.empty()) {
1467- try {
1468- page_token_index = stoi(page_token);
1469- } catch (invalid_argument &e) {
1470- return make_exceptional_future<tuple<ItemList,string>>(
1471- InvalidArgumentException(string("McloudProvider::list(): invalid page token: ") + e.what()));
1472- }
1473- }
1474-
1475- return boost::async([this, item_id, page_token_index, ctx](){
1476- try {
1477- const int count_per_page = 50;
1478- int start_index = 1 + page_token_index * count_per_page;
1479- auto client = assign_client(ctx);
1480- auto content_list = client->cloud_content_list(start_index, count_per_page,
1481- CloudContent::Type::All, item_id);
1482-
1483- ItemList roots;
1484- for (const auto & content: content_list) {
1485- roots.push_back(content_to_item(content));
1486- }
1487-
1488- int offset = 0;
1489- boost::promise<tuple<ItemList,string>> prom;
1490- if (content_list.size() >= count_per_page) {
1491- offset++;
1492- }
1493- prom.set_value(make_tuple(roots, std::to_string(page_token_index + offset)));
1494-
1495- return prom.get_future();
1496- } catch (InvalidIDException &e) {
1497- return make_exceptional_future<tuple<ItemList,string>>(
1498- NotExistsException(string("McloudProvider::list(): failed: ") + e.what(), item_id));
1499- } catch (runtime_error &e) {
1500- return make_exceptional_future<tuple<ItemList,string>>(
1501- RemoteCommsException(string("McloudProvider::list(): failed: ") + e.what()));
1502- }
1503- });
1504-}
1505-
1506-boost::future<ItemList> McloudProvider::lookup(
1507- string const& parent_id, string const& name,
1508- Context const& ctx)
1509-{
1510- return boost::async([this, parent_id, name, ctx](){
1511- try {
1512- const int count_per_page = 50;
1513- int page_token_index = 0;
1514- int start_index = 0;
1515-
1516- ItemList roots;
1517- do {
1518- page_token_index++;
1519- start_index = 1 + (page_token_index - 1) * count_per_page;
1520- auto client = assign_client(ctx);
1521- auto content_list = client->cloud_content_list(start_index, count_per_page,
1522- CloudContent::Type::All, parent_id);
1523-
1524- for (const auto & content: content_list) {
1525- if (content->name().find(name) != string::npos) {
1526- roots.push_back(content_to_item(content));
1527- }
1528- }
1529-
1530- if (content_list.size() < count_per_page)
1531- break;
1532- } while (true);
1533-
1534- return make_ready_future<ItemList>(roots);
1535- } catch (InvalidIDException &e) {
1536- return make_exceptional_future<ItemList>(
1537- NotExistsException(string("McloudProvider::lookup(): folder not exists: ") + e.what(), parent_id));
1538- } catch (runtime_error &e) {
1539- return make_exceptional_future<ItemList>(
1540- RemoteCommsException(string("McloudProvider::lookup(): failed: ") + e.what()));
1541- }
1542- });
1543-}
1544-
1545-boost::future<Item> McloudProvider::metadata(string const& item_id,
1546- Context const& ctx)
1547-{
1548- return boost::async([this, item_id, ctx](){
1549- try {
1550- auto client = assign_client(ctx);
1551- auto content = client->content_info(item_id);
1552- return make_ready_future<Item>(content_to_item(content));
1553- } catch (NonExistentException &e) {
1554- return make_exceptional_future<Item>(
1555- NotExistsException(string("McloudProvider::metadata(): content not exists: ") + e.what(), item_id));
1556- } catch (runtime_error &e) {
1557- return make_exceptional_future<Item>(
1558- RemoteCommsException(string("McloudProvider::metadata(): failed: ") + e.what()));
1559- }
1560- });
1561-}
1562-
1563-boost::future<Item> McloudProvider::create_folder(
1564- string const& parent_id, string const& name,
1565- Context const& ctx)
1566-{
1567- return boost::async([this, parent_id, name, ctx](){
1568- try {
1569- auto client = assign_client(ctx);
1570- auto content = client->create_folder(name, parent_id);
1571- return make_ready_future<Item>(content_to_item(content));
1572- } catch (NonExistentException &e) {
1573- return make_exceptional_future<Item>(
1574- NotExistsException(string("McloudProvider::create_folder(): name: ") + e.what(), name));
1575- } catch (runtime_error &e) {
1576- return make_exceptional_future<Item>(
1577- RemoteCommsException(string("McloudProvider::create_folder(): failed: ") + e.what()));
1578- }
1579- });
1580-}
1581-
1582-boost::future<unique_ptr<UploadJob>> McloudProvider::create_file(
1583- string const& parent_id, string const& name,
1584- int64_t size, string const& /*content_type*/, bool allow_overwrite,
1585- Context const& ctx)
1586-{
1587- auto client = assign_client(ctx, JobMode::Upload);
1588- return make_ready_future(unique_ptr<UploadJob>(new McloudUploadJob(make_job_id(), parent_id, name,
1589- size, allow_overwrite, client)));
1590-}
1591-
1592-boost::future<unique_ptr<UploadJob>> McloudProvider::update(
1593- string const& item_id, int64_t size, string const& /*old_etag*/,
1594- Context const& ctx)
1595-{
1596- //mcloud doesn't have update API so do some workarounds.
1597- //1.fetch metadata to get the content name and parent folder id;
1598- //2.delete that file
1599- //3.create a new file in the original folder with the same file name.
1600- //side effect: the original item id is changed after updated.
1601-
1602- return boost::async([this, item_id, size, ctx](){
1603- try {
1604- auto client = assign_client(ctx);
1605- auto content = client->content_info(item_id);
1606- auto file_name = content->name();
1607- auto parent_id = content->parent_catalog_id();
1608-
1609- delete_item(item_id, ctx);
1610-
1611- return create_file(parent_id, file_name, size, "", true, ctx);
1612- } catch (runtime_error &e) {
1613- return make_exceptional_future<unique_ptr<UploadJob>>(
1614- RemoteCommsException(string("McloudProvider::update(): failed: ") + e.what()));
1615- }
1616- });
1617-}
1618-
1619-boost::future<unique_ptr<DownloadJob>> McloudProvider::download(
1620- string const& item_id, Context const& ctx)
1621-{
1622- auto client = assign_client(ctx, JobMode::Download);
1623- return make_ready_future(unique_ptr<DownloadJob>(new McloudDownloadJob(make_job_id(), item_id, client)));
1624-}
1625-
1626-boost::future<void> McloudProvider::delete_item(
1627- string const& item_id, Context const& ctx)
1628-{
1629- return boost::async([this, item_id, ctx](){
1630- try {
1631- auto client = assign_client(ctx);
1632- Client::Stringlist content_id_list{{item_id}};
1633- client->delete_contents(content_id_list);
1634- return make_ready_future();
1635- } catch (ParameterInvalidException &e) {
1636- return make_exceptional_future<void>(
1637- NotExistsException(string("McloudProvider::delete_item(): failed: ") + e.what(), item_id));
1638- } catch (runtime_error &e) {
1639- return make_exceptional_future<void>(
1640- RemoteCommsException(string("McloudProvider::delete_item(): failed: ") + e.what()));
1641- }
1642- });
1643-}
1644-
1645-boost::future<Item> McloudProvider::move(
1646- string const& item_id, string const& new_parent_id,
1647- string const& /*new_name*/, Context const& ctx)
1648-{
1649- //Mcloud doens't support changing content name when moving content
1650- return boost::async([this, item_id, new_parent_id, ctx](){
1651- try {
1652- auto client = assign_client(ctx);
1653- Client::Stringlist folderlist;
1654- Client::Stringlist contentlist{{item_id}};
1655- client->move_items(folderlist, contentlist, new_parent_id);
1656- auto content = client->content_info(item_id);
1657- return make_ready_future<Item>(content_to_item(content));
1658- } catch (NonExistentException &e) {
1659- return make_exceptional_future<Item>(
1660- NotExistsException(string("McloudProvider::move(): content or folder not exist: ") + e.what(), ""));
1661- } catch (runtime_error &e) {
1662- return make_exceptional_future<Item>(
1663- RemoteCommsException(string("McloudProvider::move(): failed: ") + e.what()));
1664- }
1665- });
1666-}
1667-
1668-boost::future<Item> McloudProvider::copy(
1669- string const& item_id, string const& new_parent_id,
1670- string const& /*new_name*/, Context const& ctx)
1671-{
1672- //Mcloud doens't support changing content name when copying content
1673- return boost::async([this, item_id, new_parent_id, ctx](){
1674- try {
1675- Client::Stringlist content_list{{item_id}};
1676- auto client = assign_client(ctx);
1677- auto content_id = client->copy_contents(content_list, new_parent_id)[0];
1678- auto content = client->content_info(content_id);
1679- return make_ready_future<Item>(content_to_item(content));
1680- } catch (NonExistentException &e) {
1681- return make_exceptional_future<Item>(
1682- NotExistsException(string("McloudProvider::copy(): content or folder not exist: ") + e.what(), item_id));
1683- } catch (runtime_error &e) {
1684- return make_exceptional_future<Item>(
1685- RemoteCommsException(string("McloudProvider::copy(): failed: ") + e.what()));
1686- }
1687- });
1688-}
1689-
1690-Client::Ptr McloudProvider::assign_client(Context const& ctx, JobMode mode) {
1691- auto access_token = boost::get<OAuth2Credentials>(ctx.credentials).access_token;
1692- if (getenv("MCLOUD_LOCAL_SERVER_URL")) {
1693- access_token = "valid_token";
1694- }
1695-
1696- std::cout <<"mcloud access_token: " << access_token << std::endl;
1697-
1698- int index = 0;
1699- if (mode == JobMode::Unknown) {
1700- static int c_index = 0; c_index++; c_index %= CLIENT_COUNT;
1701- index = c_index;
1702- } else {
1703- int min_count = 0;
1704- for (size_t i = 0; i < client_list_.size(); i++) {
1705- auto client_ptr = client_list_[i];
1706- auto pending_count = pending_jobs_count(client_ptr, mode);
1707- if (i == 0 || pending_count < min_count) {
1708- min_count = pending_count;
1709- index = i;
1710- }
1711- }
1712- }
1713-
1714- auto client = client_list_[index];
1715- client->set_access_token(access_token);
1716- return client;
1717-}
1718-
1719-McloudUploadJob::McloudUploadJob(string const &upload_id,
1720- string const& parent_id,
1721- string const& file_name,
1722- int64_t size,
1723- bool allow_overwrite,
1724- Client::Ptr client)
1725- : UploadJob(upload_id)
1726- , parent_id_(parent_id)
1727- , file_name_(file_name)
1728- , upload_size_(size)
1729- , allow_overwrite_(allow_overwrite)
1730- , task_(nullptr)
1731- , client_(client)
1732-{
1733- upload_future_ = upload_data();
1734-}
1735-
1736-boost::future<void> McloudUploadJob::cancel()
1737-{
1738- printf("cancel_upload('%s')\n", upload_id().c_str());
1739- stop_and_cancel();
1740-
1741- return make_ready_future();
1742-}
1743-
1744-boost::future<Item> McloudUploadJob::finish()
1745-{
1746- printf("finish_upload('%s')\n", upload_id().c_str());
1747- return boost::async([this](){
1748- try {
1749- auto upload_ctx = upload_future_.get();
1750- auto upload_ok = get<0>(upload_ctx);
1751- auto error_str = get<1>(upload_ctx);
1752- if (upload_ok){
1753- auto content = client_->content_info(task_->content_id());
1754- return make_ready_future<Item>(content_to_item(content));
1755- }
1756-
1757- return make_exceptional_future<Item>(
1758- RemoteCommsException(string("McloudUploadJob::finish(): failed: ") + error_str));
1759- } catch (runtime_error &e) {
1760- return make_exceptional_future<Item>(
1761- RemoteCommsException(string("McloudUploadJob::finish(): failed: ") + e.what()));
1762- }
1763- });
1764-}
1765-
1766-boost::future<tuple<bool, string>> McloudUploadJob::upload_data()
1767-{
1768- auto prom = boost::make_shared<boost::promise<tuple<bool, string>>>();
1769-
1770- return boost::async([this, prom](){
1771- std::lock_guard<std::mutex> guard(mutex_);
1772-
1773- int socket_fd = read_socket();
1774- UploadBufferCb buffer_cb{[socket_fd](void *dest, size_t buf_size) -> size_t {
1775- //data reading callback.
1776- size_t read_size = read(socket_fd, dest, buf_size);
1777- //explicitly send EOF(-1) if read_size == 0 to notify net-cpp to throw an exception if
1778- //sth wrong with data reading to avoid hangs here.
1779- if (read_size == 0) {
1780- return -1;
1781- }
1782- return read_size;
1783- }, (size_t)upload_size_, parent_id_, file_name_};
1784-
1785- try {
1786- task_ = client_->syncmanager()->add_upload_task(buffer_cb);
1787- task_->status_changed() = [this, prom](Task::Status status) {
1788- std::cout << " status: " << status_to_string(status) << std::endl;
1789- if (status == Task::Status::Complete){
1790- prom->set_value(make_tuple(true, string()));
1791- } else if (status == Task::Status::Canceled ||
1792- status == Task::Status::Broken) {
1793- prom->set_value(make_tuple(false, task_->error_string()));
1794- }
1795- };
1796- task_->progress_changed() = [this](float percent) {
1797- cout<< "uploading: " << task_->content_name() << " " << percent << endl;
1798- };
1799- } catch (runtime_error & e) {
1800- prom->set_value(make_tuple(false, e.what()));
1801- }
1802-
1803- return prom->get_future();
1804- });
1805-}
1806-
1807-void McloudUploadJob::stop_and_cancel()
1808-{
1809- std::lock_guard<std::mutex> guard(mutex_);
1810-
1811- if (task_ != nullptr &&
1812- (task_->status() != Task::Status::Broken &&
1813- task_->status() != Task::Status::Complete)) {
1814- task_->cancel();
1815- }
1816-}
1817-
1818-McloudDownloadJob::McloudDownloadJob(string const &download_id,
1819- string const &item_id,
1820- Client::Ptr client)
1821- : DownloadJob(download_id)
1822- , item_id_(item_id)
1823- , task_(nullptr)
1824- , client_(client)
1825-{
1826- download_future_ = download_data();
1827-}
1828-
1829-boost::future<void> McloudDownloadJob::cancel()
1830-{
1831- stop_and_cancel();
1832-
1833- printf("cancel_download('%s')\n", download_id().c_str());
1834- return make_ready_future();
1835-}
1836-
1837-boost::future<void> McloudDownloadJob::finish()
1838-{
1839- return boost::async([this]() {
1840- auto download_ctx = download_future_.get();
1841- auto download_ok = get<0>(download_ctx);
1842- auto error_str = get<1>(download_ctx);
1843- if (download_ok){
1844- return make_ready_future();
1845- }
1846-
1847- return make_exceptional_future<void>(
1848- RemoteCommsException(string("failed to download from mcloud: ") + error_str));
1849- });
1850-}
1851-
1852-boost::future<tuple<bool, string>> McloudDownloadJob::download_data()
1853-{
1854- auto prom = boost::make_shared<boost::promise<tuple<bool, string>>>();
1855-
1856- return boost::async([this, prom](){
1857- std::lock_guard<std::mutex> guard(mutex_);
1858-
1859- int socket_fd = write_socket();
1860- DownloadBufferCb buffer_cb{item_id_,
1861- [socket_fd](void *dest, size_t buf_size) -> size_t {
1862- //data writing callback.
1863- return write(socket_fd, dest, buf_size);
1864- }
1865- };
1866-
1867- try {
1868- task_ = client_->syncmanager()->add_download_task(buffer_cb);
1869- task_->status_changed() = [this, prom](Task::Status status) {
1870- std::cout << " status: " << status_to_string(status) << std::endl;
1871- if (status == Task::Status::Complete) {
1872- report_complete();
1873- prom->set_value(make_tuple(true, string()));
1874- } else if (status == Task::Status::Canceled ||
1875- status == Task::Status::Broken) {
1876- prom->set_value(make_tuple(false, task_->error_string()));
1877- }
1878- };
1879- task_->progress_changed() = [this](float percent) {
1880- cout<< "downloading: " << task_->content_name() << " " << percent << endl;
1881- };
1882- } catch (runtime_error & e) {
1883- prom->set_value(make_tuple(false, e.what()));
1884- }
1885-
1886- return prom->get_future();
1887- });
1888-}
1889-
1890-void McloudDownloadJob::stop_and_cancel()
1891-{
1892- std::lock_guard<std::mutex> guard(mutex_);
1893-
1894- if (task_ != nullptr &&
1895- (task_->status() != Task::Status::Broken &&
1896- task_->status() != Task::Status::Complete)) {
1897- task_->cancel();
1898- }
1899-}
1900-
1901
1902=== removed file 'provider/McloudProvider.h'
1903--- provider/McloudProvider.h 2016-09-16 03:38:16 +0000
1904+++ provider/McloudProvider.h 1970-01-01 00:00:00 +0000
1905@@ -1,82 +0,0 @@
1906-/*
1907- * Copyright (C) 2016 Canonical Ltd
1908- *
1909- * This program is free software: you can redistribute it and/or modify
1910- * it under the terms of the GNU Lesser General Public License version 3 as
1911- * published by the Free Software Foundation.
1912- *
1913- * This program is distributed in the hope that it will be useful,
1914- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1915- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1916- * GNU Lesser General Public License for more details.
1917- *
1918- * You should have received a copy of the GNU Lesser General Public License
1919- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1920- *
1921- * Authors: Gary Wang <gary.wang@canonical.com>
1922- */
1923-
1924-#pragma once
1925-
1926-#include <unity/storage/provider/ProviderBase.h>
1927-#include <mcloud/api/client.h>
1928-
1929-using namespace std;
1930-using namespace mcloud::api;
1931-using unity::storage::provider::Context;
1932-using unity::storage::provider::DownloadJob;
1933-using unity::storage::provider::ProviderBase;
1934-using unity::storage::provider::Item;
1935-using unity::storage::provider::ItemList;
1936-using unity::storage::provider::UploadJob;
1937-
1938-
1939-class McloudProvider : public ProviderBase {
1940-public:
1941-
1942- enum class JobMode {
1943- Upload,
1944- Download,
1945- Unknown
1946- };
1947-
1948- McloudProvider();
1949-
1950- boost::future<ItemList> roots(Context const& ctx) override;
1951- boost::future<tuple<ItemList,string>> list(
1952- string const& item_id, string const& page_token,
1953- Context const& ctx) override;
1954- boost::future<ItemList> lookup(
1955- string const& parent_id, string const& name,
1956- Context const& ctx) override;
1957- boost::future<Item> metadata(
1958- string const& item_id, Context const& ctx) override;
1959- boost::future<Item> create_folder(
1960- string const& parent_id, string const& name,
1961- Context const& ctx) override;
1962-
1963- boost::future<unique_ptr<UploadJob>> create_file(
1964- string const& parent_id, string const& name,
1965- int64_t size, string const& content_type, bool allow_overwrite,
1966- Context const& ctx) override;
1967- boost::future<unique_ptr<UploadJob>> update(
1968- string const& item_id, int64_t size, string const& old_etag,
1969- Context const& ctx) override;
1970-
1971- boost::future<unique_ptr<DownloadJob>> download(
1972- string const& item_id, Context const& ctx) override;
1973-
1974- boost::future<void> delete_item(
1975- string const& item_id, Context const& ctx) override;
1976- boost::future<Item> move(
1977- string const& item_id, string const& new_parent_id,
1978- string const& new_name, Context const& ctx) override;
1979- boost::future<Item> copy(
1980- string const& item_id, string const& new_parent_id,
1981- string const& new_name, Context const& ctx) override;
1982-
1983-private:
1984- Client::Ptr assign_client(Context const& ctx, JobMode job = JobMode::Unknown);
1985-private:
1986- vector<Client::Ptr> client_list_;
1987-};
1988
1989=== modified file 'provider/main.cpp'
1990--- provider/main.cpp 2016-09-13 06:55:27 +0000
1991+++ provider/main.cpp 2016-10-26 10:36:06 +0000
1992@@ -1,20 +1,18 @@
1993-#include "McloudProvider.h"
1994+#include "mcloudprovider.h"
1995 #include <unity/storage/provider/Server.h>
1996
1997 using namespace std;
1998 using namespace unity::storage::provider;
1999
2000-int main(int argc, char **argv)
2001+int main(int argc, char** argv)
2002 {
2003- const string bus_name = "com.canonical.StorageFramework.Provider.McloudProvider";
2004- string account_service_id = "com.canonical.scopes.mcloud_mcloud_mcloud";
2005- if (argc > 1)
2006- {
2007- account_service_id = argv[1];
2008- }
2009+ const string bus_name = "com.canonical.StorageFramework.Provider.McloudProvider";
2010+ string account_service_id = "com.canonical.scopes.mcloud_mcloud_mcloud";
2011+ if (argc > 1) {
2012+ account_service_id = argv[1];
2013+ }
2014
2015- Server<McloudProvider> server(bus_name, account_service_id);
2016- server.init(argc, argv);
2017- server.run();
2018+ Server<McloudProvider> server(bus_name, account_service_id);
2019+ server.init(argc, argv);
2020+ server.run();
2021 }
2022-
2023
2024=== added file 'provider/mcloudprovider.cpp'
2025--- provider/mcloudprovider.cpp 1970-01-01 00:00:00 +0000
2026+++ provider/mcloudprovider.cpp 2016-10-26 10:36:06 +0000
2027@@ -0,0 +1,648 @@
2028+/*
2029+ * Copyright (C) 2016 Canonical Ltd
2030+ *
2031+ * This program is free software: you can redistribute it and/or modify
2032+ * it under the terms of the GNU Lesser General Public License version 3 as
2033+ * published by the Free Software Foundation.
2034+ *
2035+ * This program is distributed in the hope that it will be useful,
2036+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2037+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2038+ * GNU Lesser General Public License for more details.
2039+ *
2040+ * You should have received a copy of the GNU Lesser General Public License
2041+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2042+ *
2043+ * Authors: Gary Wang <gary.wang@canonical.com>
2044+ */
2045+
2046+#include "mcloudprovider.h"
2047+#include <unity/storage/provider/ProviderBase.h>
2048+#include <unity/storage/provider/TempfileUploadJob.h>
2049+#include <unity/storage/provider/UploadJob.h>
2050+#include <unity/storage/provider/DownloadJob.h>
2051+#include <unity/storage/provider/metadata_keys.h>
2052+#include <unity/storage/provider/Exceptions.h>
2053+
2054+#include <boost/thread.hpp>
2055+#include <boost/thread/future.hpp>
2056+#include <boost/filesystem.hpp>
2057+#include <boost/make_shared.hpp>
2058+#include <boost/uuid/uuid_generators.hpp>
2059+#include <boost/uuid/uuid_io.hpp>
2060+
2061+#include <unistd.h>
2062+#include <sys/socket.h>
2063+#include <iostream>
2064+#include <memory>
2065+#include <mutex>
2066+#include <stdexcept>
2067+
2068+#include <mcloud/api/client.h>
2069+#include <mcloud/api/uploadtask.h>
2070+#include <mcloud/api/syncmanager.h>
2071+#include <mcloud/api/cloudresource.h>
2072+#include <mcloud/api/cloudcontent.h>
2073+#include <mcloud/api/cloudfolder.h>
2074+#include <mcloud/api/exceptions.h>
2075+
2076+using namespace std;
2077+using namespace unity::storage;
2078+using namespace unity::storage::provider;
2079+using namespace mcloud::api;
2080+using namespace boost::uuids;
2081+
2082+using boost::make_ready_future;
2083+using boost::make_exceptional_future;
2084+
2085+namespace {
2086+ static constexpr const int TIME_OUT = 10;
2087+ static constexpr const int CLIENT_COUNT = 3;
2088+
2089+ static const char* FOLDER_TYPE[] = {"normal", "pictures", "music", "videos", "message", "docs", "app", "sync"};
2090+ static const char* CONTENT_TYPE[] = {"all", "image", "audio", "video", "other", "doc", "spreadsheet", "ppt"};
2091+ static const char* STATUS[] = {"unstart", "running", "canceled", "paused", "broken", "complete"};
2092+
2093+ string make_job_id() {
2094+ auto uuid = random_generator()();
2095+ return to_string(uuid);
2096+ }
2097+
2098+ string status_to_string(Task::Status status) {
2099+ return STATUS[int(status)];
2100+ }
2101+
2102+ string folder_type_to_string(CloudFolder::Type type) {
2103+ return FOLDER_TYPE[int(type)];
2104+ }
2105+
2106+ string content_type_to_string(CloudContent::Type type) {
2107+ return CONTENT_TYPE[int(type)];
2108+ }
2109+
2110+ string time_to_iso(time_t t) {
2111+ char buf[sizeof "2016-08-11T15:10:07+0000"];
2112+ strftime(buf, sizeof buf, "%FT%T%z", gmtime(&t));
2113+ return buf;
2114+ }
2115+
2116+ int pending_jobs_count(Client::Ptr client, McloudProvider::JobMode mode) {
2117+ int count = 0;
2118+ auto syncmanager = client->syncmanager();
2119+ if (mode == McloudProvider::JobMode::Download) {
2120+ auto download_task_queue = syncmanager->download_queue();
2121+ for (auto& item_ptr : download_task_queue) {
2122+ if (item_ptr->status() == Task::Status::Running
2123+ || item_ptr->status() == Task::Status::Paused
2124+ || item_ptr->status() == Task::Status::Unstart) {
2125+ count++;
2126+ }
2127+ }
2128+ } else if (mode == McloudProvider::JobMode::Upload) {
2129+ auto upload_task_queue = syncmanager->upload_queue();
2130+ for (auto& item_ptr : upload_task_queue) {
2131+ if (item_ptr->status() == Task::Status::Running
2132+ || item_ptr->status() == Task::Status::Paused
2133+ || item_ptr->status() == Task::Status::Unstart) {
2134+ count++;
2135+ }
2136+ }
2137+ }
2138+
2139+ return count;
2140+ }
2141+
2142+ Item content_to_item(CloudResource::Ptr resource) {
2143+ Item item;
2144+ item.item_id = resource->id();
2145+ item.parent_ids = {resource->parent_catalog_id()};
2146+ item.name = resource->name();
2147+ item.etag = resource->etag();
2148+ item.metadata["owner"] = resource->owner();
2149+ item.metadata[provider::CREATION_TIME] = time_to_iso(resource->created_date());
2150+ item.metadata[provider::LAST_MODIFIED_TIME] = time_to_iso(resource->updated_date());
2151+ if (resource->property() == CloudResource::Property::Folder) {
2152+ item.type = ItemType::folder;
2153+ auto folder = std::static_pointer_cast<mcloud::api::CloudFolder>(resource);
2154+ item.metadata["folder_type"] = folder_type_to_string(folder->folder_type());
2155+ item.metadata["folder_path"] = folder->folder_path();
2156+ } else if (resource->property() == CloudResource::Property::Content) {
2157+ item.type = ItemType::file;
2158+ auto file = std::static_pointer_cast<mcloud::api::CloudContent>(resource);
2159+ item.metadata["suffix"] = file->suffix();
2160+ item.metadata["content_type"] = content_type_to_string(file->type());
2161+
2162+ item.metadata[provider::SIZE_IN_BYTES] = file->content_size();
2163+ item.metadata["description"] = file->description();
2164+ item.metadata["thumbnail_url"] = file->thumbnail_url();
2165+ item.metadata["big_thumbnail_url"] = file->big_thumbnail_url();
2166+ item.metadata["present_url"] = file->big_thumbnail_url();
2167+ }
2168+
2169+ return item;
2170+ }
2171+}
2172+
2173+class McloudUploadJob : public UploadJob {
2174+ public:
2175+ McloudUploadJob(string const& upload_id,
2176+ string const& parent_id,
2177+ string const& file_name,
2178+ int64_t size,
2179+ bool allow_overwrite,
2180+ Client::Ptr client);
2181+
2182+ boost::future<void> cancel() override;
2183+ boost::future<Item> finish() override;
2184+ private:
2185+ boost::future<tuple<bool, string>> upload_data();
2186+ void stop_and_cancel();
2187+ private:
2188+ ssize_t feed_size;
2189+ string parent_id_;
2190+ string file_name_;
2191+ int64_t upload_size_;
2192+ bool allow_overwrite_;
2193+
2194+ std::mutex mutex_;
2195+ UploadTask::Ptr task_;
2196+ Client::Ptr client_;
2197+ boost::future<tuple<bool, string>> upload_future_;
2198+};
2199+
2200+class McloudDownloadJob : public DownloadJob {
2201+ public:
2202+ McloudDownloadJob(string const& download_id,
2203+ string const& item_id,
2204+ Client::Ptr client);
2205+
2206+ boost::future<void> cancel() override;
2207+ boost::future<void> finish() override;
2208+ private:
2209+ boost::future<tuple<bool, string>> download_data();
2210+ void send_data();
2211+ void stop_and_cancel();
2212+ private:
2213+ string item_id_;
2214+
2215+ std::mutex mutex_;
2216+ DownloadTask::Ptr task_;
2217+ Client::Ptr client_;
2218+ boost::future<tuple<bool, string>> download_future_;
2219+};
2220+
2221+McloudProvider::McloudProvider()
2222+ : client_list_(CLIENT_COUNT, std::make_shared<Client>(TIME_OUT)) {
2223+}
2224+
2225+boost::future<ItemList> McloudProvider::roots(Context const& ctx) {
2226+ return boost::async([this, ctx]() {
2227+ try {
2228+ auto client = assign_client(ctx);
2229+ auto root_folder_id = client->cloud_root_folder_id();
2230+
2231+ ItemList roots = {
2232+ {root_folder_id, {}, "root", "", ItemType::root, {}}
2233+ };
2234+
2235+ return make_ready_future<ItemList>(roots);
2236+ } catch (runtime_error& e) {
2237+ return make_exceptional_future<ItemList>(
2238+ RemoteCommsException(string("McloudProvider::roots() failed: ") + e.what()));
2239+ }
2240+ });
2241+}
2242+
2243+boost::future<tuple<ItemList, string>> McloudProvider::list(string const& item_id,
2244+ string const& page_token,
2245+ Context const& ctx) {
2246+ int page_token_index = 0;
2247+ if (!page_token.empty()) {
2248+ try {
2249+ page_token_index = stoi(page_token);
2250+ } catch (invalid_argument& e) {
2251+ return make_exceptional_future<tuple<ItemList, string>>(
2252+ InvalidArgumentException(string("McloudProvider::list() invalid page token: ") + e.what()));
2253+ }
2254+ }
2255+
2256+ return boost::async([this, item_id, page_token_index, ctx]() {
2257+ try {
2258+ const int count_per_page = 50;
2259+ int start_index = 1 + page_token_index * count_per_page;
2260+ auto client = assign_client(ctx);
2261+ auto content_list = client->cloud_content_list(start_index, count_per_page,
2262+ CloudContent::Type::All, item_id);
2263+
2264+ ItemList items;
2265+ for (const auto& content : content_list) {
2266+ items.push_back(content_to_item(content));
2267+ }
2268+
2269+ int offset = 0;
2270+ boost::promise<tuple<ItemList, string>> prom;
2271+ if (content_list.size() >= count_per_page) {
2272+ offset++;
2273+ }
2274+ prom.set_value(make_tuple(items, std::to_string(page_token_index + offset)));
2275+
2276+ return prom.get_future();
2277+ } catch (InvalidIDException& e) {
2278+ return make_exceptional_future<tuple<ItemList, string>>(
2279+ NotExistsException(string("McloudProvider::list() failed: ") + e.what(), item_id));
2280+ } catch (runtime_error& e) {
2281+ return make_exceptional_future<tuple<ItemList, string>>(
2282+ RemoteCommsException(string("McloudProvider::list() failed: ") + e.what()));
2283+ }
2284+ });
2285+}
2286+
2287+boost::future<ItemList> McloudProvider::lookup(string const& parent_id,
2288+ string const& name,
2289+ Context const& ctx) {
2290+ return boost::async([this, parent_id, name, ctx]() {
2291+ try {
2292+ const int count_per_page = 50;
2293+ int page_token_index = 0;
2294+ int start_index = 0;
2295+
2296+ ItemList items;
2297+ do {
2298+ page_token_index++;
2299+ start_index = 1 + (page_token_index - 1) * count_per_page;
2300+ auto client = assign_client(ctx);
2301+ auto content_list = client->cloud_content_list(start_index, count_per_page,
2302+ CloudContent::Type::All, parent_id);
2303+
2304+ for (const auto& content : content_list) {
2305+ if (content->name().find(name) != string::npos) {
2306+ items.push_back(content_to_item(content));
2307+ }
2308+ }
2309+
2310+ if (content_list.size() < count_per_page) {
2311+ break;
2312+ }
2313+ } while (true);
2314+
2315+ return make_ready_future<ItemList>(items);
2316+ } catch (InvalidIDException& e) {
2317+ return make_exceptional_future<ItemList>(
2318+ NotExistsException(string("McloudProvider::lookup() folder not exists: ") + e.what(), parent_id));
2319+ } catch (runtime_error& e) {
2320+ return make_exceptional_future<ItemList>(
2321+ RemoteCommsException(string("McloudProvider::lookup() failed: ") + e.what()));
2322+ }
2323+ });
2324+}
2325+
2326+boost::future<Item> McloudProvider::metadata(string const& item_id,
2327+ Context const& ctx) {
2328+ return boost::async([this, item_id, ctx]() {
2329+ try {
2330+ auto client = assign_client(ctx);
2331+ auto content = client->content_info(item_id);
2332+ return make_ready_future<Item>(content_to_item(content));
2333+ } catch (NonExistentException& e) {
2334+ return make_exceptional_future<Item>(
2335+ NotExistsException(string("McloudProvider::metadata() content not exists: ") + e.what(), item_id));
2336+ } catch (runtime_error& e) {
2337+ return make_exceptional_future<Item>(
2338+ RemoteCommsException(string("McloudProvider::metadata() failed: ") + e.what()));
2339+ }
2340+ });
2341+}
2342+
2343+boost::future<Item> McloudProvider::create_folder(string const& parent_id,
2344+ string const& name,
2345+ Context const& ctx) {
2346+ return boost::async([this, parent_id, name, ctx]() {
2347+ try {
2348+ auto client = assign_client(ctx);
2349+ auto content = client->create_folder(name, parent_id);
2350+ return make_ready_future<Item>(content_to_item(content));
2351+ } catch (NonExistentException& e) {
2352+ return make_exceptional_future<Item>(
2353+ NotExistsException(string("McloudProvider::create_folder() failed: ") + e.what(), name));
2354+ } catch (runtime_error& e) {
2355+ return make_exceptional_future<Item>(
2356+ RemoteCommsException(string("McloudProvider::create_folder() failed: ") + e.what()));
2357+ }
2358+ });
2359+}
2360+
2361+boost::future<unique_ptr<UploadJob>> McloudProvider::create_file(string const& parent_id,
2362+ string const& name,
2363+ int64_t size,
2364+ string const& /*content_type*/,
2365+ bool allow_overwrite,
2366+ Context const& ctx) {
2367+ auto client = assign_client(ctx, JobMode::Upload);
2368+ return make_ready_future(unique_ptr<UploadJob>(new McloudUploadJob(make_job_id(), parent_id, name,
2369+ size, allow_overwrite, client)));
2370+}
2371+
2372+boost::future<unique_ptr<UploadJob>> McloudProvider::update(string const& item_id,
2373+ int64_t size,
2374+ string const& /*old_etag*/,
2375+ Context const& ctx) {
2376+ //mcloud doesn't have update API so do some workarounds.
2377+ //1.fetch metadata to get the content name and parent folder id;
2378+ //2.delete that file
2379+ //3.create a new file in the original folder with the same file name.
2380+ //side effect: the original item id is changed after updated.
2381+
2382+ return boost::async([this, item_id, size, ctx]() {
2383+ try {
2384+ auto client = assign_client(ctx);
2385+ auto content = client->content_info(item_id);
2386+ auto file_name = content->name();
2387+ auto parent_id = content->parent_catalog_id();
2388+
2389+ delete_item(item_id, ctx);
2390+
2391+ return create_file(parent_id, file_name, size, "", true, ctx);
2392+ } catch (runtime_error& e) {
2393+ return make_exceptional_future<unique_ptr<UploadJob>>(
2394+ RemoteCommsException(string("McloudProvider::update() failed: ") + e.what()));
2395+ }
2396+ });
2397+}
2398+
2399+boost::future<unique_ptr<DownloadJob>> McloudProvider::download(string const& item_id,
2400+ Context const& ctx) {
2401+ auto client = assign_client(ctx, JobMode::Download);
2402+ return make_ready_future(unique_ptr<DownloadJob>(new McloudDownloadJob(make_job_id(), item_id,
2403+ client)));
2404+}
2405+
2406+boost::future<void> McloudProvider::delete_item(string const& item_id,
2407+ Context const& ctx) {
2408+ return boost::async([this, item_id, ctx]() {
2409+ try {
2410+ auto client = assign_client(ctx);
2411+ Client::Stringlist content_id_list{{item_id}};
2412+ client->delete_contents(content_id_list);
2413+ return make_ready_future();
2414+ } catch (ParameterInvalidException& e) {
2415+ return make_exceptional_future<void>(
2416+ NotExistsException(string("McloudProvider::delete_item() failed: ") + e.what(), item_id));
2417+ } catch (runtime_error& e) {
2418+ return make_exceptional_future<void>(
2419+ RemoteCommsException(string("McloudProvider::delete_item() failed: ") + e.what()));
2420+ }
2421+ });
2422+}
2423+
2424+boost::future<Item> McloudProvider::move(string const& item_id,
2425+ string const& new_parent_id,
2426+ string const& /*new_name*/,
2427+ Context const& ctx) {
2428+ //Mcloud doens't support changing content name when moving content
2429+ return boost::async([this, item_id, new_parent_id, ctx]() {
2430+ try {
2431+ auto client = assign_client(ctx);
2432+ Client::Stringlist folderlist;
2433+ Client::Stringlist contentlist{{item_id}};
2434+ client->move_items(folderlist, contentlist, new_parent_id);
2435+ auto content = client->content_info(item_id);
2436+ return make_ready_future<Item>(content_to_item(content));
2437+ } catch (NonExistentException& e) {
2438+ return make_exceptional_future<Item>(
2439+ NotExistsException(string("McloudProvider::move() content or folder not exist: ") + e.what(), ""));
2440+ } catch (runtime_error& e) {
2441+ return make_exceptional_future<Item>(
2442+ RemoteCommsException(string("McloudProvider::move() failed: ") + e.what()));
2443+ }
2444+ });
2445+}
2446+
2447+boost::future<Item> McloudProvider::copy(string const& item_id,
2448+ string const& new_parent_id,
2449+ string const& /*new_name*/,
2450+ Context const& ctx) {
2451+ //Mcloud doens't support changing content name when copying content
2452+ return boost::async([this, item_id, new_parent_id, ctx]() {
2453+ try {
2454+ Client::Stringlist content_list{{item_id}};
2455+ auto client = assign_client(ctx);
2456+ auto content_id = client->copy_contents(content_list, new_parent_id)[0];
2457+ auto content = client->content_info(content_id);
2458+ return make_ready_future<Item>(content_to_item(content));
2459+ } catch (NonExistentException& e) {
2460+ return make_exceptional_future<Item>(
2461+ NotExistsException(string("McloudProvider::copy() content or folder not exist: ") + e.what(),
2462+ item_id));
2463+ } catch (runtime_error& e) {
2464+ return make_exceptional_future<Item>(
2465+ RemoteCommsException(string("McloudProvider::copy() failed: ") + e.what()));
2466+ }
2467+ });
2468+}
2469+
2470+Client::Ptr McloudProvider::assign_client(Context const& ctx, JobMode mode) {
2471+ auto access_token = boost::get<OAuth2Credentials>(ctx.credentials).access_token;
2472+ if (getenv("MCLOUD_LOCAL_SERVER_URL")) {
2473+ access_token = "valid_token";
2474+ }
2475+
2476+ std::cout << "mcloud access_token: " << access_token << std::endl;
2477+
2478+ int index = 0;
2479+ if (mode == JobMode::Unknown) {
2480+ static int c_index = 0; c_index++; c_index %= CLIENT_COUNT;
2481+ index = c_index;
2482+ } else {
2483+ int min_count = 0;
2484+ for (size_t i = 0; i < client_list_.size(); i++) {
2485+ auto client_ptr = client_list_[i];
2486+ auto pending_count = pending_jobs_count(client_ptr, mode);
2487+ if (i == 0 || pending_count < min_count) {
2488+ min_count = pending_count;
2489+ index = i;
2490+ }
2491+ }
2492+ }
2493+
2494+ auto client = client_list_[index];
2495+ client->set_access_token(access_token);
2496+ return client;
2497+}
2498+
2499+McloudUploadJob::McloudUploadJob(string const& upload_id,
2500+ string const& parent_id,
2501+ string const& file_name,
2502+ int64_t size,
2503+ bool allow_overwrite,
2504+ Client::Ptr client)
2505+ : UploadJob(upload_id)
2506+ , parent_id_(parent_id)
2507+ , file_name_(file_name)
2508+ , upload_size_(size)
2509+ , allow_overwrite_(allow_overwrite)
2510+ , task_(nullptr)
2511+ , client_(client)
2512+ , upload_future_(upload_data()) {
2513+}
2514+
2515+boost::future<void> McloudUploadJob::cancel() {
2516+ printf("cancel_upload('%s')\n", upload_id().c_str());
2517+ stop_and_cancel();
2518+
2519+ return make_ready_future();
2520+}
2521+
2522+boost::future<Item> McloudUploadJob::finish() {
2523+ printf("finish_upload('%s')\n", upload_id().c_str());
2524+ return boost::async([this]() {
2525+ try {
2526+ auto upload_ctx = upload_future_.get();
2527+
2528+ static constexpr const size_t succ_index = 0;
2529+ static constexpr const size_t err_index = 1;
2530+ auto upload_ok = get<succ_index>(upload_ctx);
2531+ auto error_str = get<err_index>(upload_ctx);
2532+ if (upload_ok) {
2533+ auto content = client_->content_info(task_->content_id());
2534+ return make_ready_future<Item>(content_to_item(content));
2535+ }
2536+
2537+ return make_exceptional_future<Item>(
2538+ RemoteCommsException(string("McloudUploadJob::finish() failed: ") + error_str));
2539+ } catch (runtime_error& e) {
2540+ return make_exceptional_future<Item>(
2541+ RemoteCommsException(string("McloudUploadJob::finish() failed: ") + e.what()));
2542+ }
2543+ });
2544+}
2545+
2546+boost::future<tuple<bool, string>> McloudUploadJob::upload_data() {
2547+ auto prom = boost::make_shared<boost::promise<tuple<bool, string>>>();
2548+
2549+ return boost::async([this, prom]() {
2550+ std::lock_guard<std::mutex> guard(mutex_);
2551+
2552+ int socket_fd = read_socket();
2553+ UploadBufferCb buffer_cb{[socket_fd](void* dest, size_t buf_size) -> size_t {
2554+ //data reading callback.
2555+ size_t read_size = read(socket_fd, dest, buf_size);
2556+ //explicitly send EOF(-1) if read_size == 0 to notify net-cpp to throw an exception if
2557+ //sth wrong with data reading to avoid hangs here.
2558+ if (read_size == 0) {
2559+ return -1;
2560+ }
2561+ return read_size;
2562+ }, (size_t)upload_size_, parent_id_, file_name_};
2563+
2564+ try {
2565+ task_ = client_->syncmanager()->add_upload_task(buffer_cb);
2566+ task_->status_changed() = [this, prom](Task::Status status) {
2567+ std::cout << " status: " << status_to_string(status) << std::endl;
2568+ if (status == Task::Status::Complete) {
2569+ prom->set_value(make_tuple(true, string()));
2570+ } else if (status == Task::Status::Canceled ||
2571+ status == Task::Status::Broken) {
2572+ prom->set_value(make_tuple(false, task_->error_string()));
2573+ }
2574+ };
2575+ task_->progress_changed() = [this](float percent) {
2576+ cout << "uploading: " << task_->content_name() << " " << percent << endl;
2577+ };
2578+ } catch (runtime_error& e) {
2579+ prom->set_value(make_tuple(false, e.what()));
2580+ }
2581+
2582+ return prom->get_future();
2583+ });
2584+}
2585+
2586+void McloudUploadJob::stop_and_cancel() {
2587+ std::lock_guard<std::mutex> guard(mutex_);
2588+
2589+ if (task_ != nullptr &&
2590+ (task_->status() != Task::Status::Broken &&
2591+ task_->status() != Task::Status::Complete)) {
2592+ task_->cancel();
2593+ }
2594+}
2595+
2596+McloudDownloadJob::McloudDownloadJob(string const& download_id,
2597+ string const& item_id,
2598+ Client::Ptr client)
2599+ : DownloadJob(download_id)
2600+ , item_id_(item_id)
2601+ , task_(nullptr)
2602+ , client_(client)
2603+ , download_future_(download_data()) {
2604+}
2605+
2606+boost::future<void> McloudDownloadJob::cancel() {
2607+ stop_and_cancel();
2608+
2609+ printf("cancel_download('%s')\n", download_id().c_str());
2610+ return make_ready_future();
2611+}
2612+
2613+boost::future<void> McloudDownloadJob::finish() {
2614+ return boost::async([this]() {
2615+ auto download_ctx = download_future_.get();
2616+
2617+ static constexpr const size_t succ_index = 0;
2618+ static constexpr const size_t err_index = 1;
2619+ auto download_ok = get<succ_index>(download_ctx);
2620+ auto error_str = get<err_index>(download_ctx);
2621+ if (download_ok) {
2622+ return make_ready_future();
2623+ }
2624+
2625+ return make_exceptional_future<void>(
2626+ RemoteCommsException(string("failed to download from mcloud: ") + error_str));
2627+ });
2628+}
2629+
2630+boost::future<tuple<bool, string>> McloudDownloadJob::download_data() {
2631+ auto prom = boost::make_shared<boost::promise<tuple<bool, string>>>();
2632+
2633+ return boost::async([this, prom]() {
2634+ std::lock_guard<std::mutex> guard(mutex_);
2635+
2636+ int socket_fd = write_socket();
2637+ DownloadBufferCb buffer_cb{item_id_,
2638+ [socket_fd](void* dest, size_t buf_size) -> size_t {
2639+ //data writing callback.
2640+ return write(socket_fd, dest, buf_size);
2641+ }
2642+ };
2643+
2644+ try {
2645+ task_ = client_->syncmanager()->add_download_task(buffer_cb);
2646+ task_->status_changed() = [this, prom](Task::Status status) {
2647+ std::cout << " status: " << status_to_string(status) << std::endl;
2648+ if (status == Task::Status::Complete) {
2649+ report_complete();
2650+ prom->set_value(make_tuple(true, string()));
2651+ } else if (status == Task::Status::Canceled ||
2652+ status == Task::Status::Broken) {
2653+ prom->set_value(make_tuple(false, task_->error_string()));
2654+ }
2655+ };
2656+ task_->progress_changed() = [this](float percent) {
2657+ cout << "downloading: " << task_->content_name() << " " << percent << endl;
2658+ };
2659+ } catch (runtime_error& e) {
2660+ prom->set_value(make_tuple(false, e.what()));
2661+ }
2662+
2663+ return prom->get_future();
2664+ });
2665+}
2666+
2667+void McloudDownloadJob::stop_and_cancel() {
2668+ std::lock_guard<std::mutex> guard(mutex_);
2669+
2670+ if (task_ != nullptr &&
2671+ (task_->status() != Task::Status::Broken &&
2672+ task_->status() != Task::Status::Complete)) {
2673+ task_->cancel();
2674+ }
2675+}
2676
2677=== added file 'provider/mcloudprovider.h'
2678--- provider/mcloudprovider.h 1970-01-01 00:00:00 +0000
2679+++ provider/mcloudprovider.h 2016-10-26 10:36:06 +0000
2680@@ -0,0 +1,82 @@
2681+/*
2682+ * Copyright (C) 2016 Canonical Ltd
2683+ *
2684+ * This program is free software: you can redistribute it and/or modify
2685+ * it under the terms of the GNU Lesser General Public License version 3 as
2686+ * published by the Free Software Foundation.
2687+ *
2688+ * This program is distributed in the hope that it will be useful,
2689+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2690+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2691+ * GNU Lesser General Public License for more details.
2692+ *
2693+ * You should have received a copy of the GNU Lesser General Public License
2694+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2695+ *
2696+ * Authors: Gary Wang <gary.wang@canonical.com>
2697+ */
2698+
2699+#pragma once
2700+
2701+#include <unity/storage/provider/ProviderBase.h>
2702+#include <mcloud/api/client.h>
2703+
2704+using namespace std;
2705+using namespace mcloud::api;
2706+
2707+using unity::storage::provider::Context;
2708+using unity::storage::provider::DownloadJob;
2709+using unity::storage::provider::ProviderBase;
2710+using unity::storage::provider::Item;
2711+using unity::storage::provider::ItemList;
2712+using unity::storage::provider::UploadJob;
2713+
2714+
2715+class McloudProvider : public ProviderBase {
2716+ public:
2717+
2718+ enum class JobMode {
2719+ Upload,
2720+ Download,
2721+ Unknown
2722+ };
2723+
2724+ McloudProvider();
2725+
2726+ boost::future<ItemList> roots(Context const& ctx) override;
2727+ boost::future<tuple<ItemList, string>> list(
2728+ string const& item_id, string const& page_token,
2729+ Context const& ctx) override;
2730+ boost::future<ItemList> lookup(
2731+ string const& parent_id, string const& name,
2732+ Context const& ctx) override;
2733+ boost::future<Item> metadata(
2734+ string const& item_id, Context const& ctx) override;
2735+ boost::future<Item> create_folder(
2736+ string const& parent_id, string const& name,
2737+ Context const& ctx) override;
2738+
2739+ boost::future<unique_ptr<UploadJob>> create_file(
2740+ string const& parent_id, string const& name,
2741+ int64_t size, string const& content_type,
2742+ bool allow_overwrite, Context const& ctx) override;
2743+ boost::future<unique_ptr<UploadJob>> update(
2744+ string const& item_id, int64_t size,
2745+ string const& old_etag,Context const& ctx) override;
2746+
2747+ boost::future<unique_ptr<DownloadJob>> download(
2748+ string const& item_id, Context const& ctx) override;
2749+ boost::future<void> delete_item(
2750+ string const& item_id, Context const& ctx) override;
2751+ boost::future<Item> move(
2752+ string const& item_id, string const& new_parent_id,
2753+ string const& new_name, Context const& ctx) override;
2754+ boost::future<Item> copy(
2755+ string const& item_id, string const& new_parent_id,
2756+ string const& new_name, Context const& ctx) override;
2757+
2758+ private:
2759+ Client::Ptr assign_client(Context const& ctx, JobMode job = JobMode::Unknown);
2760+ private:
2761+ vector<Client::Ptr> client_list_;
2762+};
2763
2764=== modified file 'src/mcloud/api/client.cpp'
2765--- src/mcloud/api/client.cpp 2016-09-26 01:43:23 +0000
2766+++ src/mcloud/api/client.cpp 2016-10-26 10:36:06 +0000
2767@@ -18,103 +18,95 @@
2768
2769 #include <mcloud/api/client.h>
2770
2771-#include <core/net/error.h>
2772-#include <core/net/uri.h>
2773-#include <core/net/http/client.h>
2774-#include <core/net/http/request.h>
2775-#include <core/net/http/response.h>
2776-
2777-#include <boost/filesystem.hpp>
2778-#include <boost/algorithm/string.hpp>
2779-
2780 #include "client_priv.h"
2781
2782 using namespace mcloud::api;
2783 using namespace std;
2784
2785 Client::Client(int request_timeout)
2786- : p_(std::make_shared<ClientPriv>(request_timeout)) {
2787+ : p_(new ClientPriv(request_timeout)) {
2788 }
2789
2790 Client::~Client() {
2791 p_->sync_manager()->cancel();
2792 }
2793
2794-void Client::set_access_token(const string &access_token) {
2795+void Client::set_access_token(const string& access_token) {
2796 p_->set_access_token(access_token);
2797 }
2798
2799+bool Client::refresh_token(const string& refresh_token) {
2800+ return p_->refersh_token(refresh_token);
2801+}
2802+
2803 string Client::cloud_root_folder_id() {
2804 return p_->cloud_sync_folder_id();
2805 }
2806
2807-bool Client::exist_on_cloud(const string &file_path, const string &folder_id) {
2808- return p_->exist_on_cloud(file_path, folder_id);
2809-}
2810-
2811-DiskInfo Client::disk_info() {
2812+DiskInfo::Ptr Client::disk_info() {
2813 return p_->disk_info();
2814 }
2815
2816 Client::ResourceList Client::cloud_content_list(int start_index,
2817 int count,
2818 CloudContent::Type type,
2819- const std::string & folder_id) {
2820+ const string& folder_id) {
2821 return p_->cloud_content_list(start_index, count, type, folder_id);
2822 }
2823
2824-CloudContent::Ptr Client::content_info(const string &content_id) {
2825+CloudContent::Ptr Client::content_info(const string& content_id) {
2826 return p_->content_info(content_id);
2827 }
2828
2829-CloudFolder::Ptr Client::create_folder(const string &folder_name,
2830- const string &folder_id) {
2831+CloudFolder::Ptr Client::create_folder(const string& folder_name,
2832+ const string& folder_id) {
2833 return p_->create_folder(folder_name, folder_id);
2834 }
2835
2836-Client::ResourceList Client::look_up(const string &name,
2837- const string &folder_id,
2838+Client::ResourceList Client::look_up(const string& name,
2839+ const string& folder_id,
2840 CloudResource::Property property) {
2841 return p_->look_up(name, folder_id, property);
2842 }
2843
2844-bool Client::move_items(const Client::Stringlist &folder_ids,
2845- const Client::Stringlist &content_ids,
2846- const std::string &folder_id) {
2847+Client::OutlinkList Client::create_folder_sharing_url(const Stringlist& folder_ids) {
2848+ return p_->create_folder_sharing_url(folder_ids);
2849+}
2850+
2851+Client::OutlinkList Client::create_content_sharing_url(const Stringlist& content_ids) {
2852+ return p_->create_content_sharing_url(content_ids);
2853+}
2854+
2855+Client::Stringlist Client::copy_folders(const Stringlist& folder_ids,
2856+ const string& folder_id) {
2857+ return p_->copy_folders(folder_ids, folder_id);
2858+}
2859+
2860+Client::Stringlist Client::copy_contents(const Stringlist& contents_ids,
2861+ const string& folder_id) {
2862+ return p_->copy_contents(contents_ids, folder_id);
2863+}
2864+
2865+bool Client::move_items(const Stringlist& folder_ids,
2866+ const Stringlist& content_ids,
2867+ const string& folder_id) {
2868 return p_->move_items(folder_ids, content_ids, folder_id);
2869 }
2870
2871-bool Client::update_folder(const std::string &folder_id,
2872- const std::string &new_folder_name) {
2873+bool Client::update_folder(const string& folder_id,
2874+ const string& new_folder_name) {
2875 return p_->update_folder(folder_id, new_folder_name);
2876 }
2877
2878+bool Client::delete_contents(const vector<string>& content_ids) {
2879+ return p_->delete_contents(content_ids);
2880+}
2881+
2882+bool Client::exist_on_cloud(const string& file_path,
2883+ const string& folder_id) {
2884+ return p_->exist_on_cloud(file_path, folder_id);
2885+}
2886+
2887 SyncManager::Ptr Client::syncmanager() const {
2888 return p_->sync_manager();
2889 }
2890-
2891-bool Client::delete_contents(const vector<string> &content_ids) {
2892- return p_->delete_contents(content_ids);
2893-}
2894-
2895-Client::OutlinkList Client::create_folder_extranet_link(const Stringlist &folder_ids) {
2896- return p_->create_folder_extranet_link(folder_ids);
2897-}
2898-
2899-Client::OutlinkList Client::create_content_extranet_link(const Stringlist &content_ids) {
2900- return p_->create_content_extranet_link(content_ids);
2901-}
2902-
2903-Client::Stringlist Client::copy_folders(const Client::Stringlist &folder_ids,
2904- const std::string &folder_id) {
2905- return p_->copy_folders(folder_ids, folder_id);
2906-}
2907-
2908-Client::Stringlist Client::copy_contents(const Client::Stringlist &contents_ids,
2909- const string &folder_id) {
2910- return p_->copy_contents(contents_ids, folder_id);
2911-}
2912-
2913-bool Client::refresh_token(const string &refresh_token) {
2914- return p_->refersh_token(refresh_token);
2915-}
2916
2917=== modified file 'src/mcloud/api/client_priv.cpp'
2918--- src/mcloud/api/client_priv.cpp 2016-09-26 01:43:23 +0000
2919+++ src/mcloud/api/client_priv.cpp 2016-10-26 10:36:06 +0000
2920@@ -27,7 +27,6 @@
2921 #include <mcloud/api/uploadtask.h>
2922 #include <mcloud/api/cloudresource.h>
2923 #include <mcloud/api/outlink.h>
2924-#include <mcloud/api/syncmanager.h>
2925 #include <mcloud/api/exceptions.h>
2926
2927 #include <core/net/error.h>
2928@@ -56,422 +55,424 @@
2929 namespace alg = boost::algorithm;
2930
2931 using namespace mcloud::api;
2932+using namespace boost::archive::iterators;
2933 using namespace std;
2934
2935 namespace {
2936-
2937-void log(const std::string &info) {
2938+ void log(const string& info) {
2939 #ifndef NDEBUG
2940- cout << info << endl;
2941+ cout << info << endl;
2942 #else
2943- (void)(info);
2944+ (void)(info);
2945 #endif
2946-}
2947-
2948-static constexpr const char * content_type = "text/xml;UTF-8";
2949-static constexpr const char * register_app_name = "和彩云ubuntu";
2950-static constexpr const char * thirdparty_anonymous_account = "thirdparty_anonymous_account";
2951-
2952-std::string encode64(const string& val) {
2953- using namespace boost::archive::iterators;
2954- typedef base64_from_binary<transform_width<std::string::const_iterator, 6, 8>> iter;
2955- auto tmp = std::string(iter(std::begin(val)), iter(std::end(val)));
2956- return tmp.append((3 - val.size() % 3) % 3, '=');
2957-}
2958-
2959-static std::string md5sum(std::string filepath) {
2960- std::ifstream ifs(filepath, std::ios::binary);
2961-
2962- if (!ifs.good()) {
2963- std::cerr << "file is invalid: " << filepath << std::endl;
2964- return std::string();
2965- }
2966-
2967- unsigned char hash[MD5_DIGEST_LENGTH];
2968- MD5_CTX mdContext;
2969- char data[1024];
2970-
2971- MD5_Init(&mdContext);
2972- while(ifs.good()) {
2973- ifs.read(data, sizeof(data));
2974- MD5_Update (&mdContext, data, ifs.gcount());
2975- }
2976- MD5_Final (hash,&mdContext);
2977-
2978- std::stringstream stream;
2979- for(int i = 0; i < MD5_DIGEST_LENGTH; i++) {
2980- stream << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
2981- }
2982-
2983- return stream.str();
2984-}
2985-
2986-static void append_child(tinyxml2::XMLPrinter &printer,
2987- const std::string & field,
2988- const std::string & value) {
2989- printer.OpenElement(field.c_str());
2990- printer.PushText(value.c_str());
2991- printer.CloseElement();
2992-}
2993-
2994-static string generate_diskinfo_body() {
2995- tinyxml2::XMLPrinter printer;
2996- printer.OpenElement("getDiskInfo");
2997- append_child(printer, "MSISDN", thirdparty_anonymous_account);
2998- printer.CloseElement();
2999-
3000- return string(printer.CStr());
3001-}
3002-
3003-static string generate_content_list_body(int start_index = -1,
3004+ }
3005+
3006+ static constexpr const char* content_type = "text/xml;UTF-8";
3007+ static constexpr const char* register_app_name = "和彩云ubuntu";
3008+ static constexpr const char* thirdparty_anonymous_account = "thirdparty_anonymous_account";
3009+
3010+ string encode64(const string& val) {
3011+ typedef base64_from_binary<transform_width<string::const_iterator, 6, 8>> iter;
3012+ auto tmp = string(iter(std::begin(val)), iter(std::end(val)));
3013+ return tmp.append((3 - val.size() % 3) % 3, '=');
3014+ }
3015+
3016+ static string md5sum(string filepath) {
3017+ std::ifstream ifs(filepath, std::ios::binary);
3018+
3019+ if (!ifs.good()) {
3020+ std::cerr << "file is invalid: " << filepath << std::endl;
3021+ return string();
3022+ }
3023+
3024+ unsigned char hash[MD5_DIGEST_LENGTH];
3025+ MD5_CTX mdContext;
3026+ char data[1024];
3027+
3028+ MD5_Init(&mdContext);
3029+ while (ifs.good()) {
3030+ ifs.read(data, sizeof(data));
3031+ MD5_Update(&mdContext, data, ifs.gcount());
3032+ }
3033+ MD5_Final(hash, &mdContext);
3034+
3035+ stringstream stream;
3036+ for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
3037+ stream << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
3038+ }
3039+
3040+ return stream.str();
3041+ }
3042+
3043+ static void append_child(tinyxml2::XMLPrinter& printer,
3044+ const string& field,
3045+ const string& value) {
3046+ printer.OpenElement(field.c_str());
3047+ printer.PushText(value.c_str());
3048+ printer.CloseElement();
3049+ }
3050+
3051+ static string generate_diskinfo_body() {
3052+ tinyxml2::XMLPrinter printer;
3053+ printer.OpenElement("getDiskInfo");
3054+ append_child(printer, "MSISDN", thirdparty_anonymous_account);
3055+ printer.CloseElement();
3056+
3057+ return string(printer.CStr());
3058+ }
3059+
3060+ static string generate_contents_body(int start_index = -1,
3061 int count = 200,
3062 CloudContent::Type content_type = CloudContent::Type::All,
3063- const std::string & shared_folder_id = std::string()) {
3064- tinyxml2::XMLPrinter printer;
3065- printer.OpenElement("getDisk");
3066-
3067- //index on mcloud starts from 1, not 0
3068- if (start_index == 0)
3069- start_index = 1;
3070-
3071- append_child(printer, "MSISDN", thirdparty_anonymous_account);
3072- append_child(printer, "catalogID", shared_folder_id.empty() ? "root" : shared_folder_id.c_str());
3073- append_child(printer, "filterType", "0");
3074- append_child(printer, "catalogSortType", "0");
3075- append_child(printer, "contentType", std::to_string((int)content_type).c_str());
3076- append_child(printer, "contentSortType", "0");
3077- append_child(printer, "sortDirection", "1");
3078- append_child(printer, "startNumber",std::to_string(start_index).c_str());
3079- append_child(printer, "endNumber", std::to_string(start_index + count - 1).c_str());
3080- append_child(printer, "catalogType", "-1");
3081-
3082- printer.CloseElement();
3083-
3084- return string(printer.CStr());
3085-}
3086-
3087-static string generate_content_body(const std::string &content_id) {
3088- tinyxml2::XMLPrinter printer;
3089- printer.OpenElement("getContentInfo");
3090- append_child(printer, "ContentID", content_id);
3091- append_child(printer, "CatalogID", "");
3092- append_child(printer, "ownerMSISDN", thirdparty_anonymous_account);
3093- printer.CloseElement();
3094-
3095- return string(printer.CStr());
3096-}
3097-
3098-static string generate_delete_body(const std::vector<std::string> &item_ids) {
3099- tinyxml2::XMLPrinter printer;
3100- printer.OpenElement("delCatalogContent");
3101-
3102- append_child(printer, "MSISDN", thirdparty_anonymous_account);
3103- printer.OpenElement("catalogIDs");
3104- printer.PushAttribute("length", std::to_string(item_ids.size()).c_str());
3105- for (auto & item_id: item_ids) {
3106- append_child(printer, "ID", item_id.c_str());
3107- }
3108- printer.CloseElement();
3109-
3110- printer.OpenElement("contentIDs");
3111- printer.PushAttribute("length", std::to_string(item_ids.size()).c_str());
3112- for (auto & content_id: item_ids) {
3113- append_child(printer, "ID", content_id.c_str());
3114- }
3115- printer.CloseElement();
3116-
3117- printer.CloseElement();
3118-
3119- return string(printer.CStr());
3120-}
3121-
3122-static string generate_copy_body(const std::vector<std::string> &dir_ids,
3123- const std::vector<std::string> &content_ids,
3124- const std::string &new_folder_id) {
3125- tinyxml2::XMLPrinter printer;
3126- printer.OpenElement("copyContentCatalog");
3127-
3128- append_child(printer, "MSISDN", thirdparty_anonymous_account);
3129- printer.OpenElement("contentInfoList");
3130- printer.PushAttribute("length", std::to_string(content_ids.size()).c_str());
3131- for (auto & content_id: content_ids) {
3132- append_child(printer, "ID", content_id.c_str());
3133- }
3134- printer.CloseElement();
3135-
3136- printer.OpenElement("catalogInfoList");
3137- printer.PushAttribute("length", std::to_string(dir_ids.size()).c_str());
3138- for (auto & dir_id: dir_ids) {
3139- append_child(printer, "ID", dir_id.c_str());
3140- }
3141- printer.CloseElement();
3142-
3143- append_child(printer, "newCatalogID", new_folder_id);
3144-
3145- printer.CloseElement();
3146-
3147- return string(printer.CStr());
3148-}
3149-
3150-static string generate_update_folder_body(const std::string &folder_id,
3151- const std::string &new_folder_name) {
3152- tinyxml2::XMLPrinter printer;
3153- printer.OpenElement("updateCatalogInfo");
3154- append_child(printer, "MSISDN", thirdparty_anonymous_account);
3155- append_child(printer, "catalogID", folder_id);
3156- append_child(printer, "catalogName", new_folder_name);
3157- printer.CloseElement();
3158-
3159- return string(printer.CStr());
3160-}
3161-
3162-static string generate_create_folder_body(const std::string &folder_name,
3163- const std::string &folder_id) {
3164- tinyxml2::XMLPrinter printer;
3165- printer.OpenElement("createCatalogExt");
3166- printer.OpenElement("createCatalogExtReq");
3167-
3168- append_child(printer, "parentCatalogID", folder_id);
3169- append_child(printer, "newCatalogName", folder_name);
3170- append_child(printer, "ownerMSISDN", thirdparty_anonymous_account);
3171- append_child(printer, "catalogType", "0");
3172-
3173- printer.CloseElement();
3174- printer.CloseElement();
3175-
3176- return string(printer.CStr());
3177-}
3178-
3179-static string generate_look_up_body(const std::string &name,
3180- const std::string &folder_id,
3181- CloudResource::Property property) {
3182+ const string& shared_folder_id = string()) {
3183+ tinyxml2::XMLPrinter printer;
3184+ printer.OpenElement("getDisk");
3185+
3186+ //index on mcloud starts from 1, not 0
3187+ if (start_index == 0) {
3188+ start_index = 1;
3189+ }
3190+
3191+ append_child(printer, "MSISDN", thirdparty_anonymous_account);
3192+ append_child(printer, "catalogID", shared_folder_id.empty() ? "root" : shared_folder_id.c_str());
3193+ append_child(printer, "filterType", "0");
3194+ append_child(printer, "catalogSortType", "0");
3195+ append_child(printer, "contentType", std::to_string((int)content_type).c_str());
3196+ append_child(printer, "contentSortType", "0");
3197+ append_child(printer, "sortDirection", "1");
3198+ append_child(printer, "startNumber", std::to_string(start_index).c_str());
3199+ append_child(printer, "endNumber", std::to_string(start_index + count - 1).c_str());
3200+ append_child(printer, "catalogType", "-1");
3201+
3202+ printer.CloseElement();
3203+
3204+ return string(printer.CStr());
3205+ }
3206+
3207+ static string generate_content_body(const string& content_id) {
3208+ tinyxml2::XMLPrinter printer;
3209+ printer.OpenElement("getContentInfo");
3210+ append_child(printer, "ContentID", content_id);
3211+ append_child(printer, "CatalogID", "");
3212+ append_child(printer, "ownerMSISDN", thirdparty_anonymous_account);
3213+ printer.CloseElement();
3214+
3215+ return string(printer.CStr());
3216+ }
3217+
3218+ static string generate_delete_body(const std::vector<string>& item_ids) {
3219+ tinyxml2::XMLPrinter printer;
3220+ printer.OpenElement("delCatalogContent");
3221+
3222+ append_child(printer, "MSISDN", thirdparty_anonymous_account);
3223+ printer.OpenElement("catalogIDs");
3224+ printer.PushAttribute("length", std::to_string(item_ids.size()).c_str());
3225+ for (auto& item_id : item_ids) {
3226+ append_child(printer, "ID", item_id.c_str());
3227+ }
3228+ printer.CloseElement();
3229+
3230+ printer.OpenElement("contentIDs");
3231+ printer.PushAttribute("length", std::to_string(item_ids.size()).c_str());
3232+ for (auto& content_id : item_ids) {
3233+ append_child(printer, "ID", content_id.c_str());
3234+ }
3235+ printer.CloseElement();
3236+
3237+ printer.CloseElement();
3238+
3239+ return string(printer.CStr());
3240+ }
3241+
3242+ static string generate_copy_body(const vector<string>& dir_ids,
3243+ const vector<string>& content_ids,
3244+ const string& new_folder_id) {
3245+ tinyxml2::XMLPrinter printer;
3246+ printer.OpenElement("copyContentCatalog");
3247+
3248+ append_child(printer, "MSISDN", thirdparty_anonymous_account);
3249+ printer.OpenElement("contentInfoList");
3250+ printer.PushAttribute("length", std::to_string(content_ids.size()).c_str());
3251+ for (auto& content_id : content_ids) {
3252+ append_child(printer, "ID", content_id.c_str());
3253+ }
3254+ printer.CloseElement();
3255+
3256+ printer.OpenElement("catalogInfoList");
3257+ printer.PushAttribute("length", std::to_string(dir_ids.size()).c_str());
3258+ for (auto& dir_id : dir_ids) {
3259+ append_child(printer, "ID", dir_id.c_str());
3260+ }
3261+ printer.CloseElement();
3262+
3263+ append_child(printer, "newCatalogID", new_folder_id);
3264+
3265+ printer.CloseElement();
3266+
3267+ return string(printer.CStr());
3268+ }
3269+
3270+ static string generate_update_folder_body(const string& folder_id,
3271+ const string& new_folder_name) {
3272+ tinyxml2::XMLPrinter printer;
3273+ printer.OpenElement("updateCatalogInfo");
3274+ append_child(printer, "MSISDN", thirdparty_anonymous_account);
3275+ append_child(printer, "catalogID", folder_id);
3276+ append_child(printer, "catalogName", new_folder_name);
3277+ printer.CloseElement();
3278+
3279+ return string(printer.CStr());
3280+ }
3281+
3282+ static string generate_create_folder_body(const string& folder_name,
3283+ const string& folder_id) {
3284+ tinyxml2::XMLPrinter printer;
3285+ printer.OpenElement("createCatalogExt");
3286+ printer.OpenElement("createCatalogExtReq");
3287+
3288+ append_child(printer, "parentCatalogID", folder_id);
3289+ append_child(printer, "newCatalogName", folder_name);
3290+ append_child(printer, "ownerMSISDN", thirdparty_anonymous_account);
3291+ append_child(printer, "catalogType", "0");
3292+
3293+ printer.CloseElement();
3294+ printer.CloseElement();
3295+
3296+ return string(printer.CStr());
3297+ }
3298+
3299+ static string generate_look_up_body(const string& name,
3300+ const string& folder_id,
3301+ CloudResource::Property property) {
3302 #if 1
3303- tinyxml2::XMLPrinter printer;
3304- printer.OpenElement("advanceSearch");
3305- printer.OpenElement("advanceSearchReq");
3306-
3307- append_child(printer, "account", thirdparty_anonymous_account);
3308- append_child(printer, "scope", std::to_string((int)property));
3309-
3310- printer.OpenElement("fileCond");
3311-
3312- append_child(printer, "prtCtlgID", folder_id);
3313- append_child(printer, "name", name);
3314-
3315- printer.CloseElement();
3316-
3317- printer.CloseElement();
3318- printer.CloseElement();
3319+ tinyxml2::XMLPrinter printer;
3320+ printer.OpenElement("advanceSearch");
3321+ printer.OpenElement("advanceSearchReq");
3322+
3323+ append_child(printer, "account", thirdparty_anonymous_account);
3324+ append_child(printer, "scope", std::to_string((int)property));
3325+
3326+ printer.OpenElement("fileCond");
3327+
3328+ append_child(printer, "prtCtlgID", folder_id);
3329+ append_child(printer, "name", name);
3330+
3331+ printer.CloseElement();
3332+
3333+ printer.CloseElement();
3334+ printer.CloseElement();
3335 #else
3336- tinyxml2::XMLPrinter printer;
3337- printer.OpenElement("simpleSearch");
3338- printer.OpenElement("simpleSearchReq");
3339-
3340- append_child(printer, "account", thirdparty_anonymous_account);
3341- append_child(printer, "scope", "1100000000000000");
3342- append_child(printer, "keyword", name);
3343-
3344- printer.CloseElement();
3345- printer.CloseElement();
3346+ tinyxml2::XMLPrinter printer;
3347+ printer.OpenElement("simpleSearch");
3348+ printer.OpenElement("simpleSearchReq");
3349+
3350+ append_child(printer, "account", thirdparty_anonymous_account);
3351+ append_child(printer, "scope", "1100000000000000");
3352+ append_child(printer, "keyword", name);
3353+
3354+ printer.CloseElement();
3355+ printer.CloseElement();
3356 #endif
3357- return string(printer.CStr());
3358-}
3359-
3360-static string generate_move_body(const Client::Stringlist &dir_ids,
3361- const Client::Stringlist &content_ids,
3362- const std::string &folder_id) {
3363- tinyxml2::XMLPrinter printer;
3364- printer.OpenElement("moveContentCatalog");
3365-
3366- append_child(printer, "MSISDN", thirdparty_anonymous_account);
3367-
3368- printer.OpenElement("contentInfoList");
3369- printer.PushAttribute("length", std::to_string(content_ids.size()).c_str());
3370- for (auto & content_id: content_ids) {
3371- append_child(printer, "ID", content_id.c_str());
3372- }
3373- printer.CloseElement();
3374-
3375- printer.OpenElement("catalogInfoList");
3376- printer.PushAttribute("length", std::to_string(dir_ids.size()).c_str());
3377- for (auto & dir_id: dir_ids) {
3378- append_child(printer, "ID", dir_id.c_str());
3379- }
3380- printer.CloseElement();
3381-
3382- append_child(printer, "newCatalogID", folder_id);
3383-
3384- printer.CloseElement();
3385-
3386- return string(printer.CStr());
3387-}
3388-
3389-static string generate_extranet_body(const Client::Stringlist &dir_ids,
3390- const Client::Stringlist &content_ids) {
3391- tinyxml2::XMLPrinter printer;
3392- printer.OpenElement("getOutLink");
3393- printer.OpenElement("getOutLinkReq");
3394-
3395- append_child(printer, "account", thirdparty_anonymous_account);
3396- printer.OpenElement("caIDLst");
3397- printer.PushAttribute("length", std::to_string(dir_ids.size()).c_str());
3398- for (auto & dir_id: dir_ids) {
3399- append_child(printer, "item", dir_id.c_str());
3400- }
3401- printer.CloseElement();
3402-
3403- printer.OpenElement("coIDLst");
3404- printer.PushAttribute("length", std::to_string(content_ids.size()).c_str());
3405- for (auto & content_id: content_ids) {
3406- append_child(printer, "item", content_id.c_str());
3407- }
3408- printer.CloseElement();
3409-
3410- append_child(printer, "pubType", "1");
3411-
3412- printer.CloseElement();
3413- printer.CloseElement();
3414-
3415- return string(printer.CStr());
3416-}
3417-
3418-static string generate_download_body(const std::string &content_id) {
3419- tinyxml2::XMLPrinter printer;
3420- printer.OpenElement("downloadRequest");
3421- append_child(printer, "appName", register_app_name);
3422- append_child(printer, "MSISDN", thirdparty_anonymous_account);
3423-
3424- vector<string> content_ids = {{content_id}};
3425- string content_list = alg::join(content_ids, "|");
3426-
3427- append_child(printer, "contentID", content_list.c_str());
3428- append_child(printer, "OwnerMSISDN", "");
3429- append_child(printer, "entryShareCatalogID", "");
3430- append_child(printer, "operation", "0");
3431- append_child(printer, "fileVersion", "-1");
3432-
3433- printer.CloseElement();
3434-
3435- return string(printer.CStr());
3436-}
3437-
3438-static string generate_upload_body(const UploadRequest & request_item) {
3439- tinyxml2::XMLPrinter printer;
3440- printer.OpenElement("pcUploadFileRequest");
3441- append_child(printer, "ownerMSISDN", thirdparty_anonymous_account);
3442- append_child(printer, "fileCount", "1");
3443-
3444- int64_t file_size = 0;
3445- if (fs::exists(request_item.file_path)) {
3446- file_size = fs::file_size(request_item.file_path);
3447- } else {
3448- throw std::runtime_error("file not exists");
3449- }
3450- append_child(printer, "totalSize", std::to_string(file_size).c_str());
3451-
3452- printer.OpenElement("uploadContentList");
3453- printer.PushAttribute("length", "1");
3454-
3455- printer.OpenElement("uploadContentInfo");
3456- append_child(printer, "contentName", request_item.content_name.empty() ?
3457- fs::path(request_item.file_path).filename().c_str() : request_item.content_name);
3458- append_child(printer, "contentSize", std::to_string(file_size).c_str());
3459- append_child(printer, "contentDesc", "");
3460- append_child(printer, "contentTAGList", "");
3461-
3462- //The parameter to check upload files' md5sum
3463- //"isNeedupload" field in response body will indicate if the file exists in mcloud.
3464- append_child(printer, "digest", md5sum(request_item.file_path));
3465-
3466- printer.CloseElement();
3467- printer.CloseElement();
3468-
3469- append_child(printer, "newCatalogName", "");
3470- append_child(printer, "parentCatalogID", request_item.folder_id);
3471- printer.CloseElement();
3472-
3473- return string(printer.CStr());
3474-}
3475-
3476-static string generate_upload_body(const UploadBufferCb & buffer_cb) {
3477- tinyxml2::XMLPrinter printer;
3478- printer.OpenElement("pcUploadFileRequest");
3479- append_child(printer, "ownerMSISDN", thirdparty_anonymous_account);
3480- append_child(printer, "fileCount", "1");
3481-
3482- append_child(printer, "totalSize", std::to_string(buffer_cb.buffer_size).c_str());
3483-
3484- printer.OpenElement("uploadContentList");
3485- printer.PushAttribute("length", "1");
3486-
3487- printer.OpenElement("uploadContentInfo");
3488- append_child(printer, "contentName", buffer_cb.content_name);
3489- append_child(printer, "contentSize", std::to_string(buffer_cb.buffer_size).c_str());
3490- append_child(printer, "contentDesc", "");
3491- append_child(printer, "contentTAGList", "");
3492-
3493- printer.CloseElement();
3494-
3495- printer.CloseElement();
3496-
3497- append_child(printer, "newCatalogName", "");
3498- append_child(printer, "parentCatalogID", buffer_cb.folder_id);
3499- printer.CloseElement();
3500-
3501- return string(printer.CStr());
3502-}
3503-
3504-template<typename T>
3505-static void set_auth_exception(std::shared_ptr<std::promise<T>> prom,
3506- const std::string json_data) {
3507-
3508- std::string error_info = json_data;
3509- boost::cmatch cap;
3510- const boost::regex exp("{\"error\":\"(.*?)\".*");
3511- if(boost::regex_match(json_data.c_str(), cap, exp)){
3512- error_info = cap[1];
3513- }
3514-
3515- prom->set_exception(make_exception_ptr(CredentialException(error_info)));
3516-}
3517-
3518-template<typename T>
3519-static void set_exception(std::shared_ptr<std::promise<T>> prom,
3520- const tinyxml2::XMLElement *root) {
3521- ClientPriv::ServerCode err_code= (ClientPriv::ServerCode)stoi(root->Attribute("resultCode"));
3522- switch(err_code) {
3523- case ClientPriv::ServerCode::CATALOGID_INVALID:
3524- case ClientPriv::ServerCode::CONTENTID_INVALID:
3525- prom->set_exception(make_exception_ptr(InvalidIDException(root->Attribute("desc"))));
3526- break;
3527- case ClientPriv::ServerCode::CATALOG_NOT_EXIST:
3528- case ClientPriv::ServerCode::CONTENT_AND_CATALOG_NOT_EXIST:
3529- case ClientPriv::ServerCode::CONTENT_NOT_EXIST:
3530- prom->set_exception(make_exception_ptr(NonExistentException(root->Attribute("desc"))));
3531- break;
3532- case ClientPriv::ServerCode::USER_SPACE_LACKED:
3533- prom->set_exception(make_exception_ptr(OutofSpaceException(root->Attribute("desc"))));
3534- break;
3535- case ClientPriv::ServerCode::PARAMETER_INVALID:
3536- prom->set_exception(make_exception_ptr(ParameterInvalidException(root->Attribute("desc"))));
3537- break;
3538- case ClientPriv::ServerCode::CREDENTIAL_FAILED:
3539- prom->set_exception(make_exception_ptr(CredentialException(root->Attribute("desc"))));
3540- break;
3541- default:
3542- prom->set_exception(make_exception_ptr(runtime_error(root->Attribute("desc"))));
3543- break;
3544- }
3545-}
3546+ return string(printer.CStr());
3547+ }
3548+
3549+ static string generate_move_body(const Client::Stringlist& dir_ids,
3550+ const Client::Stringlist& content_ids,
3551+ const string& folder_id) {
3552+ tinyxml2::XMLPrinter printer;
3553+ printer.OpenElement("moveContentCatalog");
3554+
3555+ append_child(printer, "MSISDN", thirdparty_anonymous_account);
3556+
3557+ printer.OpenElement("contentInfoList");
3558+ printer.PushAttribute("length", std::to_string(content_ids.size()).c_str());
3559+ for (auto& content_id : content_ids) {
3560+ append_child(printer, "ID", content_id.c_str());
3561+ }
3562+ printer.CloseElement();
3563+
3564+ printer.OpenElement("catalogInfoList");
3565+ printer.PushAttribute("length", std::to_string(dir_ids.size()).c_str());
3566+ for (auto& dir_id : dir_ids) {
3567+ append_child(printer, "ID", dir_id.c_str());
3568+ }
3569+ printer.CloseElement();
3570+
3571+ append_child(printer, "newCatalogID", folder_id);
3572+
3573+ printer.CloseElement();
3574+
3575+ return string(printer.CStr());
3576+ }
3577+
3578+ static string generate_extranet_body(const Client::Stringlist& dir_ids,
3579+ const Client::Stringlist& content_ids) {
3580+ tinyxml2::XMLPrinter printer;
3581+ printer.OpenElement("getOutLink");
3582+ printer.OpenElement("getOutLinkReq");
3583+
3584+ append_child(printer, "account", thirdparty_anonymous_account);
3585+ printer.OpenElement("caIDLst");
3586+ printer.PushAttribute("length", std::to_string(dir_ids.size()).c_str());
3587+ for (auto& dir_id : dir_ids) {
3588+ append_child(printer, "item", dir_id.c_str());
3589+ }
3590+ printer.CloseElement();
3591+
3592+ printer.OpenElement("coIDLst");
3593+ printer.PushAttribute("length", std::to_string(content_ids.size()).c_str());
3594+ for (auto& content_id : content_ids) {
3595+ append_child(printer, "item", content_id.c_str());
3596+ }
3597+ printer.CloseElement();
3598+
3599+ append_child(printer, "pubType", "1");
3600+
3601+ printer.CloseElement();
3602+ printer.CloseElement();
3603+
3604+ return string(printer.CStr());
3605+ }
3606+
3607+ static string generate_download_body(const string& content_id) {
3608+ tinyxml2::XMLPrinter printer;
3609+ printer.OpenElement("downloadRequest");
3610+ append_child(printer, "appName", register_app_name);
3611+ append_child(printer, "MSISDN", thirdparty_anonymous_account);
3612+
3613+ vector<string> content_ids = {{content_id}};
3614+ string content_list = alg::join(content_ids, "|");
3615+
3616+ append_child(printer, "contentID", content_list.c_str());
3617+ append_child(printer, "OwnerMSISDN", "");
3618+ append_child(printer, "entryShareCatalogID", "");
3619+ append_child(printer, "operation", "0");
3620+ append_child(printer, "fileVersion", "-1");
3621+
3622+ printer.CloseElement();
3623+
3624+ return string(printer.CStr());
3625+ }
3626+
3627+ static string generate_upload_body(const UploadRequest& request_item) {
3628+ tinyxml2::XMLPrinter printer;
3629+ printer.OpenElement("pcUploadFileRequest");
3630+ append_child(printer, "ownerMSISDN", thirdparty_anonymous_account);
3631+ append_child(printer, "fileCount", "1");
3632+
3633+ int64_t file_size = 0;
3634+ if (fs::exists(request_item.file_path)) {
3635+ file_size = fs::file_size(request_item.file_path);
3636+ } else {
3637+ throw std::runtime_error("file not exists");
3638+ }
3639+ append_child(printer, "totalSize", std::to_string(file_size).c_str());
3640+
3641+ printer.OpenElement("uploadContentList");
3642+ printer.PushAttribute("length", "1");
3643+
3644+ printer.OpenElement("uploadContentInfo");
3645+ append_child(printer, "contentName", request_item.content_name.empty() ?
3646+ fs::path(request_item.file_path).filename().c_str() : request_item.content_name);
3647+ append_child(printer, "contentSize", std::to_string(file_size).c_str());
3648+ append_child(printer, "contentDesc", "");
3649+ append_child(printer, "contentTAGList", "");
3650+
3651+ //The parameter to check upload files' md5sum
3652+ //"isNeedupload" field in response body will indicate if the file exists in mcloud.
3653+ append_child(printer, "digest", md5sum(request_item.file_path));
3654+
3655+ printer.CloseElement();
3656+ printer.CloseElement();
3657+
3658+ append_child(printer, "newCatalogName", "");
3659+ append_child(printer, "parentCatalogID", request_item.folder_id);
3660+ printer.CloseElement();
3661+
3662+ return string(printer.CStr());
3663+ }
3664+
3665+ static string generate_upload_body(const UploadBufferCb& buffer_cb) {
3666+ tinyxml2::XMLPrinter printer;
3667+ printer.OpenElement("pcUploadFileRequest");
3668+ append_child(printer, "ownerMSISDN", thirdparty_anonymous_account);
3669+ append_child(printer, "fileCount", "1");
3670+
3671+ append_child(printer, "totalSize", std::to_string(buffer_cb.buffer_size).c_str());
3672+
3673+ printer.OpenElement("uploadContentList");
3674+ printer.PushAttribute("length", "1");
3675+
3676+ printer.OpenElement("uploadContentInfo");
3677+ append_child(printer, "contentName", buffer_cb.content_name);
3678+ append_child(printer, "contentSize", std::to_string(buffer_cb.buffer_size).c_str());
3679+ append_child(printer, "contentDesc", "");
3680+ append_child(printer, "contentTAGList", "");
3681+
3682+ printer.CloseElement();
3683+
3684+ printer.CloseElement();
3685+
3686+ append_child(printer, "newCatalogName", "");
3687+ append_child(printer, "parentCatalogID", buffer_cb.folder_id);
3688+ printer.CloseElement();
3689+
3690+ return string(printer.CStr());
3691+ }
3692+
3693+ template<typename T>
3694+ static void set_auth_exception(const shared_ptr<std::promise<T>>& prom,
3695+ const string json_data) {
3696+
3697+ string error_info = json_data;
3698+ boost::cmatch cap;
3699+ const boost::regex exp("{\"error\":\"(.*?)\".*");
3700+ if (boost::regex_match(json_data.c_str(), cap, exp)) {
3701+ error_info = cap[1];
3702+ }
3703+
3704+ prom->set_exception(make_exception_ptr(CredentialException(error_info)));
3705+ }
3706+
3707+ template<typename T>
3708+ static void set_exception(const shared_ptr<std::promise<T>>& prom,
3709+ const tinyxml2::XMLElement* root) {
3710+ ClientPriv::ServerCode err_code = (ClientPriv::ServerCode)stoi(root->Attribute("resultCode"));
3711+ switch (err_code) {
3712+ case ClientPriv::ServerCode::CATALOGID_INVALID:
3713+ case ClientPriv::ServerCode::CONTENTID_INVALID:
3714+ prom->set_exception(make_exception_ptr(InvalidIDException(root->Attribute("desc"))));
3715+ break;
3716+ case ClientPriv::ServerCode::CATALOG_NOT_EXIST:
3717+ case ClientPriv::ServerCode::CONTENT_AND_CATALOG_NOT_EXIST:
3718+ case ClientPriv::ServerCode::CONTENT_NOT_EXIST:
3719+ prom->set_exception(make_exception_ptr(NonExistentException(root->Attribute("desc"))));
3720+ break;
3721+ case ClientPriv::ServerCode::USER_SPACE_LACKED:
3722+ prom->set_exception(make_exception_ptr(OutofSpaceException(root->Attribute("desc"))));
3723+ break;
3724+ case ClientPriv::ServerCode::PARAMETER_INVALID:
3725+ prom->set_exception(make_exception_ptr(ParameterInvalidException(root->Attribute("desc"))));
3726+ break;
3727+ case ClientPriv::ServerCode::CREDENTIAL_FAILED:
3728+ prom->set_exception(make_exception_ptr(CredentialException(root->Attribute("desc"))));
3729+ break;
3730+ default:
3731+ prom->set_exception(make_exception_ptr(runtime_error(root->Attribute("desc"))));
3732+ break;
3733+ }
3734+ }
3735
3736 }
3737
3738 class ClientPriv::HttpClient {
3739-public:
3740+ public:
3741 HttpClient(int request_timeout) :
3742 client_(http::make_client()),
3743- worker_ { [this]() {client_->run();} },
3744- cancelled_(false) {
3745+ cancelled_(false),
3746+ worker_ {[this]() {
3747+ client_->run();
3748+ }} {
3749 config_.request_timeout = request_timeout;
3750 }
3751
3752@@ -482,9 +483,7 @@
3753 }
3754 }
3755
3756- std::shared_ptr<core::net::http::Client> client_;
3757-
3758- std::thread worker_;
3759+ std::shared_ptr<http::Client> client_;
3760
3761 Config config_;
3762
3763@@ -492,9 +491,11 @@
3764
3765 std::atomic<bool> cancelled_;
3766
3767- void get(const net::Uri::Path &path,
3768- const net::Uri::QueryParameters &parameters,
3769- http::Request::Handler &handler) {
3770+ std::thread worker_;
3771+
3772+ void get(const net::Uri::Path& path,
3773+ const net::Uri::QueryParameters& parameters,
3774+ http::Request::Handler& handler) {
3775 auto configuration = net_config(path, parameters);
3776 configuration.header.add("User-Agent", config_.user_agent);
3777
3778@@ -502,11 +503,11 @@
3779 request->async_execute(handler);
3780 }
3781
3782- void post(const net::Uri::Path &path,
3783- const net::Uri::QueryParameters &parameters,
3784- const std::string &postbody,
3785- const std::string &content_type,
3786- http::Request::Handler &handler) {
3787+ void post(const net::Uri::Path& path,
3788+ const net::Uri::QueryParameters& parameters,
3789+ const string& postbody,
3790+ const string& content_type,
3791+ http::Request::Handler& handler) {
3792 std::lock_guard<std::mutex> lock(config_mutex_);
3793 http::Request::Configuration configuration = net_config(path, parameters);
3794 configuration.header.add("User-Agent", config_.user_agent);
3795@@ -517,16 +518,16 @@
3796 request->async_execute(handler);
3797 }
3798
3799- http::Request::Configuration net_config(const net::Uri::Path &path,
3800- const net::Uri::QueryParameters &parameters) {
3801+ http::Request::Configuration net_config(const net::Uri::Path& path,
3802+ const net::Uri::QueryParameters& parameters) {
3803 http::Request::Configuration configuration;
3804 net::Uri::QueryParameters complete_parameters(parameters);
3805 if (!config_.access_token.empty()) {
3806 configuration.header.add("Authorization",
3807- "Bearer " + config_.access_token);
3808+ "Bearer " + config_.access_token);
3809 } else {
3810 configuration.header.add("Authorization",
3811- "Basic " + encode64(config_.client_id + ":" + config_.client_password));
3812+ "Basic " + encode64(config_.client_id + ":" + config_.client_password));
3813 }
3814
3815 if (getenv("MCLOUD_LOCAL_SERVER_URL")) {
3816@@ -535,48 +536,42 @@
3817 }
3818
3819 net::Uri uri = net::make_uri(config_.apiroot, path,
3820- complete_parameters);
3821+ complete_parameters);
3822 configuration.uri = client_->uri_to_string(uri);
3823
3824 return configuration;
3825 }
3826
3827- http::Request::Progress::Next progress_changed(
3828- const http::Request::Progress&) {
3829- return cancelled_ ?
3830- http::Request::Progress::Next::abort_operation :
3831- http::Request::Progress::Next::continue_operation;
3832- }
3833-
3834 template<typename T>
3835- future<T> async_get(const net::Uri::Path &path,
3836- const net::Uri::QueryParameters &parameters,
3837- const function<T(const tinyxml2::XMLElement *root)> &func) {
3838+ future<T> async_get(const net::Uri::Path& path,
3839+ const net::Uri::QueryParameters& parameters,
3840+ const function<T(const tinyxml2::XMLElement* root)>& func) {
3841 auto prom = make_shared<promise<T>>();
3842
3843 http::Request::Handler handler;
3844 handler.on_progress(
3845- bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1));
3846- handler.on_error([prom](const net::Error& e)
3847- {
3848+ [this](const http::Request::Progress& /*progress*/) {
3849+ return cancelled_ ?
3850+ http::Request::Progress::Next::abort_operation :
3851+ http::Request::Progress::Next::continue_operation;
3852+ });
3853+ handler.on_error([prom](const net::Error & e) {
3854 prom->set_exception(make_exception_ptr(runtime_error(e.what())));
3855 });
3856 handler.on_response(
3857- [prom,func](const http::Response& response)
3858- {
3859- tinyxml2::XMLDocument doc;
3860- tinyxml2::XMLError error = doc.Parse(response.body.c_str());
3861- const tinyxml2::XMLElement *root = doc.FirstChildElement();
3862+ [prom, func](const http::Response & response) {
3863+ tinyxml2::XMLDocument doc;
3864+ tinyxml2::XMLError error = doc.Parse(response.body.c_str());
3865+ const tinyxml2::XMLElement* root = doc.FirstChildElement();
3866
3867- if (error != tinyxml2::XML_SUCCESS) {
3868- prom->set_exception(make_exception_ptr(runtime_error("xml parse failed")));
3869- } else if (response.status != http::Status::ok) {
3870- prom->set_exception(make_exception_ptr(runtime_error(root->GetText())));
3871- } else {
3872- prom->set_value(func(root));
3873- }
3874+ if (error != tinyxml2::XML_SUCCESS) {
3875+ prom->set_exception(make_exception_ptr(runtime_error("xml parse failed")));
3876+ } else if (response.status != http::Status::ok) {
3877+ prom->set_exception(make_exception_ptr(runtime_error(root->GetText())));
3878+ } else {
3879+ prom->set_value(func(root));
3880 }
3881- );
3882+ });
3883
3884 get(path, parameters, handler);
3885
3886@@ -584,53 +579,54 @@
3887 }
3888
3889 template<typename T>
3890- future<T> async_post(const net::Uri::Path &path,
3891- const net::Uri::QueryParameters &parameters,
3892- const std::string &postmsg,
3893- const std::string &content_type,
3894- const function<T(const tinyxml2::XMLElement *root)> &func) {
3895+ future<T> async_post(const net::Uri::Path& path,
3896+ const net::Uri::QueryParameters& parameters,
3897+ const string& postmsg,
3898+ const string& content_type,
3899+ const function<T(const tinyxml2::XMLElement* root)>& func) {
3900 auto prom = make_shared<promise<T>>();
3901
3902 http::Request::Handler handler;
3903 handler.on_progress(
3904- bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1));
3905- handler.on_error([prom](const net::Error& e)
3906- {
3907+ [this](const http::Request::Progress& /*progress*/) {
3908+ return cancelled_ ?
3909+ http::Request::Progress::Next::abort_operation :
3910+ http::Request::Progress::Next::continue_operation;
3911+ });
3912+ handler.on_error([prom](const net::Error & e) {
3913 prom->set_exception(make_exception_ptr(runtime_error(e.what())));
3914 });
3915 handler.on_response(
3916- [path, prom,func](const http::Response& response)
3917- {
3918- auto iter = std::find_if(path.cbegin(), path.cend(), [=](const string & pathitem){
3919- return (pathitem == "OAuth2");
3920- });
3921-
3922- //mcloud seperate authentication server and content server,
3923- //1.if authentication failed, responses server gives it back are json-based data.
3924- //2.for generaic content access, responses server gives it back are xml-based data,
3925- //just as API document mentioned.
3926- tinyxml2::XMLDocument doc;
3927- tinyxml2::XMLError error = tinyxml2::XML_SUCCESS;
3928- if (iter != path.end()) {
3929- std::string xml_response = "<result resultCode=\"0\"><![CDATA[" + response.body + "]]></result>";
3930- error = doc.Parse(xml_response.c_str());
3931- } else {
3932- error = doc.Parse(response.body.c_str());
3933- }
3934- const tinyxml2::XMLElement *result = doc.FirstChildElement();
3935-
3936- if (error != tinyxml2::XML_SUCCESS) {
3937- set_auth_exception(prom, response.body);
3938- } else if ((response.status != http::Status::created &&
3939- response.status != http::Status::ok &&
3940- response.status != http::Status::no_content ) ||
3941+ [path, prom, func](const http::Response & response) {
3942+ auto iter = std::find_if(path.cbegin(), path.cend(), [ = ](const string & pathitem) {
3943+ return (pathitem == "OAuth2");
3944+ });
3945+
3946+ //mcloud seperate authentication server and content server,
3947+ //1.if authentication failed, responses server gives it back are json-based data.
3948+ //2.for generaic content access, responses server gives it back are xml-based data,
3949+ //just as API document mentioned.
3950+ tinyxml2::XMLDocument doc;
3951+ tinyxml2::XMLError error = tinyxml2::XML_SUCCESS;
3952+ if (iter != path.end()) {
3953+ string xml_response = "<result resultCode=\"0\"><![CDATA[" + response.body + "]]></result>";
3954+ error = doc.Parse(xml_response.c_str());
3955+ } else {
3956+ error = doc.Parse(response.body.c_str());
3957+ }
3958+ const tinyxml2::XMLElement* result = doc.FirstChildElement();
3959+
3960+ if (error != tinyxml2::XML_SUCCESS) {
3961+ set_auth_exception(prom, response.body);
3962+ } else if ((response.status != http::Status::created &&
3963+ response.status != http::Status::ok &&
3964+ response.status != http::Status::no_content) ||
3965 strcmp(result->Attribute("resultCode"), "0") != 0) {
3966- set_exception(prom, result);
3967- } else {
3968- prom->set_value(func(result));
3969- }
3970+ set_exception(prom, result);
3971+ } else {
3972+ prom->set_value(func(result));
3973 }
3974- );
3975+ });
3976
3977 post(path, parameters, postmsg, content_type, handler);
3978
3979@@ -639,8 +635,8 @@
3980 };
3981
3982 ClientPriv::ClientPriv(int request_timeout)
3983- : httpclient_(std::make_shared<HttpClient>(request_timeout))
3984- , sync_manager_(std::shared_ptr<SyncManager>(new SyncManager(this))) {
3985+ : httpclient_(new HttpClient(request_timeout))
3986+ , sync_manager_(new SyncManager(this)) {
3987 }
3988
3989 ClientPriv::~ClientPriv() {
3990@@ -649,24 +645,25 @@
3991
3992 string ClientPriv::cloud_sync_folder_id() {
3993 Client::ResourceList folderlist = cloud_root_folder_list();
3994- for (auto &folder: folderlist) {
3995- mcloud::api::CloudFolder::Ptr cloudfolder = std::static_pointer_cast<mcloud::api::CloudFolder>(folder);
3996- if (cloudfolder->folder_type() == mcloud::api::CloudFolder::Type::Sync){
3997+ for (auto& folder : folderlist) {
3998+ CloudFolder::Ptr cloudfolder = std::static_pointer_cast<CloudFolder>(folder);
3999+ if (cloudfolder->folder_type() == CloudFolder::Type::Sync) {
4000 return cloudfolder->id();
4001 }
4002 }
4003
4004- return std::string();
4005+ return string();
4006 }
4007
4008-void ClientPriv::set_access_token(const string &access_token) {
4009+void ClientPriv::set_access_token(const string& access_token) {
4010 httpclient_->config_.access_token = access_token;
4011 }
4012
4013-bool ClientPriv::exist_on_cloud(const std::string &file_path,
4014- const std::string &folder_id) {
4015- if (!fs::exists(file_path))
4016+bool ClientPriv::exist_on_cloud(const string& file_path,
4017+ const string& folder_id) {
4018+ if (!fs::exists(file_path)) {
4019 throw std::runtime_error(string("file not exists: ").append(file_path));
4020+ }
4021
4022 UploadRequest request_item{file_path, folder_id, ""};
4023 string postbody = generate_upload_body(request_item);
4024@@ -674,107 +671,105 @@
4025 return exist_on_cloud_internal(postbody);
4026 }
4027
4028-DiskInfo ClientPriv::disk_info() {
4029- std::string postbody = generate_diskinfo_body();
4030+DiskInfo::Ptr ClientPriv::disk_info() {
4031+ string postbody = generate_diskinfo_body();
4032
4033 log(postbody);
4034
4035- auto disk_future = httpclient_->async_post<DiskInfo>(
4036+ auto disk_future = httpclient_->async_post<DiskInfo::Ptr>(
4037 { "richlifeApp", "devapp", "IUser" }, { }, postbody, content_type,
4038- [](const tinyxml2::XMLElement *root) {
4039- return DiskInfo(root);
4040+ [](const tinyxml2::XMLElement * root) {
4041+ return std::shared_ptr<DiskInfo>(new DiskInfo(root));
4042 });
4043
4044 return get_or_throw(disk_future);
4045 }
4046
4047 Client::ResourceList ClientPriv::cloud_content_list(int start_index,
4048- int count,
4049- CloudContent::Type type,
4050- const std::string & folder_id) {
4051- std::string postbody = generate_content_list_body(start_index,
4052- count,
4053- type,
4054- folder_id);
4055+ int count,
4056+ CloudContent::Type type,
4057+ const string& folder_id) {
4058+ string postbody = generate_contents_body(start_index,
4059+ count,
4060+ type,
4061+ folder_id);
4062 return cloud_content_list_internal(postbody);
4063 }
4064
4065-CloudContent::Ptr ClientPriv::content_info(const string &content_id) {
4066+CloudContent::Ptr ClientPriv::content_info(const string& content_id) {
4067 string postbody = generate_content_body(content_id);
4068 return content_item_internal(postbody);
4069 }
4070
4071-CloudFolder::Ptr ClientPriv::create_folder(const string &folder_name,
4072- const string &folder_id) {
4073+CloudFolder::Ptr ClientPriv::create_folder(const string& folder_name,
4074+ const string& folder_id) {
4075 string postbody = generate_create_folder_body(folder_name, folder_id);
4076 return create_folder_internal(postbody);
4077 }
4078
4079-Client::ResourceList ClientPriv::look_up(const string &name,
4080- const string &folder_id,
4081+Client::ResourceList ClientPriv::look_up(const string& name,
4082+ const string& folder_id,
4083 CloudResource::Property property) {
4084 string postbody = generate_look_up_body(name, folder_id, property);
4085 return look_up_internal(postbody);
4086 }
4087
4088-bool ClientPriv::move_items(const Client::Stringlist &folder_ids,
4089- const Client::Stringlist &content_ids,
4090- const std::string &folder_id) {
4091+bool ClientPriv::move_items(const Client::Stringlist& folder_ids,
4092+ const Client::Stringlist& content_ids,
4093+ const string& folder_id) {
4094 string postbody = generate_move_body(folder_ids, content_ids,
4095 folder_id);
4096 return move_items_internal(postbody);
4097 }
4098
4099-bool ClientPriv::update_folder(const string &folder_id,
4100- const string &new_folder_name) {
4101+bool ClientPriv::update_folder(const string& folder_id,
4102+ const string& new_folder_name) {
4103 string postbody = generate_update_folder_body(folder_id, new_folder_name);
4104 return update_internal(postbody);
4105 }
4106
4107-bool ClientPriv::delete_contents(const Client::Stringlist &content_ids) {
4108+bool ClientPriv::delete_contents(const Client::Stringlist& content_ids) {
4109 string postbody = generate_delete_body(content_ids);
4110 return delete_internal(postbody);
4111 }
4112
4113-Client::Stringlist ClientPriv::copy_folders(const Client::Stringlist &folder_ids,
4114- const std::string &folder_id) {
4115- string postbody = generate_copy_body(folder_ids, vector<string>{},
4116- folder_id);
4117- return copy_internal(postbody);
4118-}
4119-
4120-Client::Stringlist ClientPriv::copy_contents(const Client::Stringlist &content_ids,
4121- const std::string &folder_id) {
4122- string postbody = generate_copy_body(vector<string>{}, content_ids,
4123- folder_id);
4124- return copy_internal(postbody);
4125-}
4126-
4127-Client::OutlinkList ClientPriv::create_folder_extranet_link(
4128- const Client::Stringlist &folder_ids) {
4129+Client::Stringlist ClientPriv::copy_folders(const Client::Stringlist& folder_ids,
4130+ const string& folder_id) {
4131+ string postbody = generate_copy_body(folder_ids, vector<string> {},
4132+ folder_id);
4133+ return copy_internal(postbody);
4134+}
4135+
4136+Client::Stringlist ClientPriv::copy_contents(const Client::Stringlist& content_ids,
4137+ const string& folder_id) {
4138+ string postbody = generate_copy_body(Client::Stringlist{}, content_ids,
4139+ folder_id);
4140+ return copy_internal(postbody);
4141+}
4142+
4143+Client::OutlinkList ClientPriv::create_folder_sharing_url(const Client::Stringlist& folder_ids) {
4144 string postbody = generate_extranet_body(folder_ids, Client::Stringlist{});
4145- return create_extranet_internal(postbody);
4146+ return create_url_internal(postbody);
4147 }
4148
4149-Client::OutlinkList ClientPriv::create_content_extranet_link(
4150- const Client::Stringlist &content_ids) {
4151+Client::OutlinkList ClientPriv::create_content_sharing_url(const Client::Stringlist& content_ids) {
4152 string postbody = generate_extranet_body(Client::Stringlist{}, content_ids);
4153- return create_extranet_internal(postbody);
4154+ return create_url_internal(postbody);
4155 }
4156
4157-DownloadTaskPriv::Ptr ClientPriv::create_download_link(const string &content_id) {
4158+DownloadTaskPriv::Ptr ClientPriv::create_download_link(const string& content_id) {
4159 string postbody = generate_download_body({{content_id}});
4160
4161 log(postbody);
4162
4163 auto future = httpclient_->async_post<DownloadTaskPriv::Ptr>(
4164- { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
4165- [](const tinyxml2::XMLElement *root) {
4166+ { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
4167+ [](const tinyxml2::XMLElement * root) {
4168
4169 auto link_list = root->FirstChildElement("String");
4170 if (link_list) {
4171 auto link = link_list->FirstChildElement();
4172- while(link) {
4173+ while (link) {
4174 return std::make_shared<DownloadTaskPriv>(link);
4175 }
4176
4177@@ -788,19 +783,19 @@
4178 return get_or_throw(future);
4179 }
4180
4181-DownloadTaskPriv::Ptr ClientPriv::create_download_link(const DownloadBufferCb &buffer_cb) {
4182+DownloadTaskPriv::Ptr ClientPriv::create_download_link(const DownloadBufferCb& buffer_cb) {
4183 string postbody = generate_download_body(buffer_cb.content_id);
4184
4185 log(postbody);
4186
4187 auto future = httpclient_->async_post<DownloadTaskPriv::Ptr>(
4188- { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
4189- [buffer_cb](const tinyxml2::XMLElement *root) {
4190+ { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
4191+ [buffer_cb](const tinyxml2::XMLElement * root) {
4192
4193 auto link_list = root->FirstChildElement("String");
4194 if (link_list) {
4195 auto link = link_list->FirstChildElement();
4196- while(link) {
4197+ while (link) {
4198 return std::make_shared<DownloadTaskPriv>(link, buffer_cb.write_cb);
4199 }
4200
4201@@ -814,20 +809,21 @@
4202 return get_or_throw(future);
4203 }
4204
4205-UploadTaskPriv::Ptr ClientPriv::create_upload_link(const UploadRequest &request_item) {
4206- if (!fs::exists(request_item.file_path))
4207+UploadTaskPriv::Ptr ClientPriv::create_upload_link(const UploadRequest& request_item) {
4208+ if (!fs::exists(request_item.file_path)) {
4209 throw std::runtime_error(string("file not exists: ").append(request_item.file_path));
4210-
4211+ }
4212+
4213 string postbody = generate_upload_body(request_item);
4214
4215 log(postbody);
4216
4217 auto future = httpclient_->async_post<UploadTaskPriv::Ptr>(
4218- { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
4219- [request_item](const tinyxml2::XMLElement *root) {
4220+ { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
4221+ [request_item](const tinyxml2::XMLElement * root) {
4222 auto upload_res = root->FirstChildElement("uploadResult");
4223- std::string task_id = upload_res->FirstChildElement("uploadTaskID")->GetText();
4224- std::string redirection_url;
4225+ string task_id = upload_res->FirstChildElement("uploadTaskID")->GetText();
4226+ string redirection_url;
4227 if (upload_res->FirstChildElement("redirectionUrl")) {
4228 redirection_url = upload_res->FirstChildElement("redirectionUrl")->GetText();
4229 }
4230@@ -835,7 +831,7 @@
4231 auto content_list = upload_res->FirstChildElement("newContentIDList");
4232 if (content_list) {
4233 auto content = content_list->FirstChildElement();
4234- while(content) {
4235+ while (content) {
4236 return std::make_shared<UploadTaskPriv>(content,
4237 task_id,
4238 redirection_url,
4239@@ -849,20 +845,20 @@
4240 return get_or_throw(future);
4241 }
4242
4243-UploadTaskPriv::Ptr ClientPriv::create_upload_link(const UploadBufferCb &buffer_cb) {
4244+UploadTaskPriv::Ptr ClientPriv::create_upload_link(const UploadBufferCb& buffer_cb) {
4245 string postbody = generate_upload_body(buffer_cb);
4246
4247 log(postbody);
4248
4249 auto future = httpclient_->async_post<UploadTaskPriv::Ptr>(
4250- { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
4251- [buffer_cb](const tinyxml2::XMLElement *root) {
4252+ { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
4253+ [buffer_cb](const tinyxml2::XMLElement * root) {
4254 SyncManager::UploadList results;
4255
4256 auto upload_res = root->FirstChildElement("uploadResult");
4257- std::string task_id = upload_res->FirstChildElement("uploadTaskID")->GetText();
4258+ string task_id = upload_res->FirstChildElement("uploadTaskID")->GetText();
4259
4260- std::string redirection_url;
4261+ string redirection_url;
4262 if (upload_res->FirstChildElement("redirectionUrl")) {
4263 redirection_url = upload_res->FirstChildElement("redirectionUrl")->GetText();
4264 }
4265@@ -870,12 +866,12 @@
4266 auto content_list = upload_res->FirstChildElement("newContentIDList");
4267 if (content_list) {
4268 auto content = content_list->FirstChildElement();
4269- while(content) {
4270+ while (content) {
4271 return std::make_shared<UploadTaskPriv>(content,
4272- task_id,
4273- redirection_url,
4274- buffer_cb.buffer_size,
4275- buffer_cb.read_cb);
4276+ task_id,
4277+ redirection_url,
4278+ buffer_cb.buffer_size,
4279+ buffer_cb.read_cb);
4280 }
4281 }
4282
4283@@ -886,20 +882,20 @@
4284 }
4285
4286 Client::ResourceList ClientPriv::cloud_root_folder_list() {
4287- std::string postbody = generate_content_list_body();
4288+ string postbody = generate_contents_body();
4289
4290 log(postbody);
4291
4292 auto future = httpclient_->async_post<Client::ResourceList>(
4293- { "richlifeApp", "devapp", "ICatalog" }, { }, postbody, content_type,
4294- [](const tinyxml2::XMLElement *res) {
4295+ { "richlifeApp", "devapp", "ICatalog" }, { }, postbody, content_type,
4296+ [](const tinyxml2::XMLElement * res) {
4297 auto root = res->FirstChildElement();
4298 Client::ResourceList results;
4299
4300 auto folder_list = root->FirstChildElement("catalogList");
4301 if (folder_list) {
4302 auto folder = folder_list->FirstChildElement();
4303- while(folder) {
4304+ while (folder) {
4305 results.emplace_back(std::shared_ptr<CloudFolder>(new CloudFolder(folder)));
4306 folder = folder->NextSiblingElement();
4307 }
4308@@ -911,19 +907,19 @@
4309 return get_or_throw(future);
4310 }
4311
4312-Client::ResourceList ClientPriv::cloud_content_list_internal(const string &postbody) {
4313+Client::ResourceList ClientPriv::cloud_content_list_internal(const string& postbody) {
4314 log(postbody);
4315
4316 auto future = httpclient_->async_post<Client::ResourceList>(
4317- { "richlifeApp", "devapp", "ICatalog" }, { }, postbody, content_type,
4318- [](const tinyxml2::XMLElement *root) {
4319+ { "richlifeApp", "devapp", "ICatalog" }, { }, postbody, content_type,
4320+ [](const tinyxml2::XMLElement * root) -> Client::ResourceList {
4321 Client::ResourceList results;
4322
4323 auto res = root->FirstChildElement();
4324 auto folder_list = res->FirstChildElement("catalogList");
4325 if (folder_list) {
4326 auto folder_ele = folder_list->FirstChildElement();
4327- while(folder_ele) {
4328+ while (folder_ele) {
4329 results.emplace_back(std::shared_ptr<CloudFolder>(
4330 new CloudFolder(folder_ele)));
4331 folder_ele = folder_ele->NextSiblingElement();
4332@@ -933,9 +929,8 @@
4333 auto content_list = res->FirstChildElement("contentList");
4334 if (content_list) {
4335 auto content = content_list->FirstChildElement();
4336- while(content) {
4337- results.emplace_back(std::shared_ptr<CloudContent>(
4338- new CloudContent(content)));
4339+ while (content) {
4340+ results.emplace_back(std::shared_ptr<CloudContent>(new CloudContent(content)));
4341 content = content->NextSiblingElement();
4342 }
4343 }
4344@@ -946,12 +941,12 @@
4345 return get_or_throw(future);
4346 }
4347
4348-CloudContent::Ptr ClientPriv::content_item_internal(const string &postbody) {
4349+CloudContent::Ptr ClientPriv::content_item_internal(const string& postbody) {
4350 log(postbody);
4351
4352 auto future = httpclient_->async_post<CloudContent::Ptr>(
4353- { "richlifeApp", "devapp", "IContent" }, { }, postbody, content_type,
4354- [](const tinyxml2::XMLElement *root) -> CloudContent::Ptr {
4355+ { "richlifeApp", "devapp", "IContent" }, { }, postbody, content_type,
4356+ [](const tinyxml2::XMLElement * root) -> CloudContent::Ptr {
4357 if (strcmp(root->Attribute("resultCode"), "0"))
4358 return nullptr;
4359
4360@@ -962,12 +957,12 @@
4361 return get_or_throw(future);
4362 }
4363
4364-CloudFolder::Ptr ClientPriv::create_folder_internal(const string &postbody) {
4365+CloudFolder::Ptr ClientPriv::create_folder_internal(const string& postbody) {
4366 log(postbody);
4367
4368 auto future = httpclient_->async_post<CloudFolder::Ptr>(
4369- { "richlifeApp", "devapp", "ICatalog" }, { }, postbody, content_type,
4370- [](const tinyxml2::XMLElement *root) -> CloudFolder::Ptr {
4371+ { "richlifeApp", "devapp", "ICatalog" }, { }, postbody, content_type,
4372+ [](const tinyxml2::XMLElement * root) -> CloudFolder::Ptr {
4373 if (strcmp(root->Attribute("resultCode"), "0"))
4374 return nullptr;
4375
4376@@ -978,19 +973,19 @@
4377 return get_or_throw(future);
4378 }
4379
4380-Client::ResourceList ClientPriv::look_up_internal(const string &postbody) {
4381+Client::ResourceList ClientPriv::look_up_internal(const string& postbody) {
4382 log(postbody);
4383
4384 auto future = httpclient_->async_post<Client::ResourceList>(
4385- { "richlifeApp", "devapp", "ISearch" }, { }, postbody, content_type,
4386- [](const tinyxml2::XMLElement *root) {
4387+ { "richlifeApp", "devapp", "ISearch" }, { }, postbody, content_type,
4388+ [](const tinyxml2::XMLElement * root) -> Client::ResourceList {
4389 Client::ResourceList results;
4390
4391 auto res = root->FirstChildElement();
4392 auto folder_list = res->FirstChildElement("srchCtlgList");
4393 if (folder_list) {
4394 auto folder_ele = folder_list->FirstChildElement();
4395- while(folder_ele) {
4396+ while (folder_ele) {
4397 results.emplace_back(std::shared_ptr<CloudFolder>(
4398 new CloudFolder(folder_ele)));
4399 folder_ele = folder_ele->NextSiblingElement();
4400@@ -1000,9 +995,8 @@
4401 auto content_list = res->FirstChildElement("srchCntList");
4402 if (content_list) {
4403 auto content_ele = content_list->FirstChildElement();
4404- while(content_ele) {
4405- results.emplace_back(std::shared_ptr<CloudContent>(
4406- new CloudContent(content_ele)));
4407+ while (content_ele) {
4408+ results.emplace_back(std::shared_ptr<CloudContent>(new CloudContent(content_ele)));
4409 content_ele = content_ele->NextSiblingElement();
4410 }
4411 }
4412@@ -1013,19 +1007,19 @@
4413 return get_or_throw(future);
4414 }
4415
4416-bool ClientPriv::exist_on_cloud_internal(const string &postbody) {
4417+bool ClientPriv::exist_on_cloud_internal(const string& postbody) {
4418 log(postbody);
4419
4420 auto future = httpclient_->async_post<bool>(
4421- { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
4422- [](const tinyxml2::XMLElement *root) {
4423+ { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
4424+ [](const tinyxml2::XMLElement * root) {
4425 bool is_exists = false;
4426
4427 auto upload_ele = root->FirstChildElement("uploadResult");
4428 auto new_content_list = upload_ele->FirstChildElement("newContentIDList");
4429 if (new_content_list) {
4430 auto new_content_ele = new_content_list->FirstChildElement();
4431- if(new_content_ele) {
4432+ if (new_content_ele) {
4433 is_exists = strcmp(new_content_ele->FirstChildElement("isNeedUpload")->GetText(), "1");
4434 }
4435 }
4436@@ -1036,43 +1030,44 @@
4437 return get_or_throw(future);
4438 }
4439
4440-bool ClientPriv::move_items_internal(const string &postbody) {
4441+bool ClientPriv::move_items_internal(const string& postbody) {
4442 return update_internal(postbody);
4443 }
4444
4445-bool ClientPriv::update_internal(const string &postbody) {
4446- log(postbody);
4447-
4448- auto future = httpclient_->async_post<bool>(
4449- { "richlifeApp", "devapp", "ICatalog" }, { }, postbody, content_type,
4450- [](const tinyxml2::XMLElement *root) {
4451- return !strcmp(root->Attribute("resultCode"), "0");
4452- });
4453-
4454- return get_or_throw(future);
4455-}
4456-
4457-bool ClientPriv::delete_internal(const string &postbody) {
4458- log(postbody);
4459-
4460- auto future = httpclient_->async_post<bool>(
4461- { "richlifeApp", "devapp", "IContent" }, { }, postbody, content_type,
4462- [](const tinyxml2::XMLElement *root) {
4463- return !strcmp(root->Attribute("resultCode"), "0");
4464- });
4465-
4466- return get_or_throw(future);
4467-}
4468-
4469-Client::Stringlist ClientPriv::copy_internal(const string &postbody) {
4470+bool ClientPriv::update_internal(const string& postbody) {
4471+ log(postbody);
4472+
4473+ auto future = httpclient_->async_post<bool>(
4474+ { "richlifeApp", "devapp", "ICatalog" }, { }, postbody, content_type,
4475+ [](const tinyxml2::XMLElement * root) {
4476+ return !strcmp(root->Attribute("resultCode"), "0");
4477+ });
4478+
4479+ return get_or_throw(future);
4480+}
4481+
4482+bool ClientPriv::delete_internal(const string& postbody) {
4483+ log(postbody);
4484+
4485+ auto future = httpclient_->async_post<bool>(
4486+ { "richlifeApp", "devapp", "IContent" }, { }, postbody, content_type,
4487+ [](const tinyxml2::XMLElement * root) {
4488+ return !strcmp(root->Attribute("resultCode"), "0");
4489+ });
4490+
4491+ return get_or_throw(future);
4492+}
4493+
4494+Client::Stringlist ClientPriv::copy_internal(const string& postbody) {
4495 log(postbody);
4496
4497 auto future = httpclient_->async_post<Client::Stringlist>(
4498- { "richlifeApp", "devapp", "ICatalog" }, { }, postbody, content_type,
4499- [](const tinyxml2::XMLElement *root) {
4500+ { "richlifeApp", "devapp", "ICatalog" }, { }, postbody, content_type,
4501+ [](const tinyxml2::XMLElement * root) -> Client::Stringlist {
4502 Client::Stringlist results;
4503- if (strcmp(root->Attribute("resultCode"), "0"))
4504+ if (strcmp(root->Attribute("resultCode"), "0")) {
4505 return results;
4506+ }
4507
4508 auto new_item = root->FirstChildElement("array")->FirstChildElement("item");
4509 while (new_item) {
4510@@ -1086,18 +1081,18 @@
4511 return get_or_throw(future);
4512 }
4513
4514-Client::OutlinkList ClientPriv::create_extranet_internal(const string &postbody) {
4515+Client::OutlinkList ClientPriv::create_url_internal(const string& postbody) {
4516 log(postbody);
4517
4518 auto future = httpclient_->async_post<Client::OutlinkList>(
4519- { "richlifeApp", "devapp", "IOutLink" }, { }, postbody, content_type,
4520- [](const tinyxml2::XMLElement *root) {
4521+ { "richlifeApp", "devapp", "IOutLink" }, { }, postbody, content_type,
4522+ [](const tinyxml2::XMLElement * root) {
4523 Client::OutlinkList results;
4524
4525 auto link_list = root->FirstChildElement("getOutLinkRes")->FirstChildElement("getOutLinkResSet");
4526 if (link_list) {
4527 auto link = link_list->FirstChildElement();
4528- while(link) {
4529+ while (link) {
4530 results.emplace_back(new Outlink(link));
4531 link = link->NextSiblingElement();
4532 }
4533@@ -1109,15 +1104,15 @@
4534 return get_or_throw(future);
4535 }
4536
4537-bool ClientPriv::refersh_token(const string &refresh_token) {
4538- const std::string content_type = "application/x-www-form-urlencoded";
4539- const std::string postbody = "grant_type=refresh_token&refresh_token="
4540- + refresh_token;
4541+bool ClientPriv::refersh_token(const string& refresh_token) {
4542+ const string content_type = "application/x-www-form-urlencoded";
4543+ const string postbody = "grant_type=refresh_token&refresh_token="
4544+ + refresh_token;
4545 log(postbody);
4546
4547 auto future = httpclient_->async_post<bool>(
4548- { "oauthApp", "OAuth2", "refreshToken" }, { }, postbody, content_type,
4549- [this](const tinyxml2::XMLElement *root) {
4550+ { "oauthApp", "OAuth2", "refreshToken" }, { }, postbody, content_type,
4551+ [this](const tinyxml2::XMLElement * root) {
4552 boost::cmatch cap;
4553 const boost::regex exp(".*\"(.*?)\"\\}");
4554 if (boost::regex_match(root->GetText(), cap, exp)) {
4555@@ -1130,16 +1125,17 @@
4556 return get_or_throw(future);
4557 }
4558
4559-void ClientPriv::cancel() {
4560- httpclient_->cancelled_ = true;
4561-}
4562-
4563 SyncManager::Ptr ClientPriv::sync_manager() {
4564 return sync_manager_;
4565 }
4566
4567-template<typename T> T ClientPriv::get_or_throw(std::future<T> &f) {
4568- if (f.wait_for(std::chrono::seconds(httpclient_->config_.request_timeout)) != std::future_status::ready) {
4569+void ClientPriv::cancel() {
4570+ httpclient_->cancelled_ = true;
4571+}
4572+
4573+template<typename T> T ClientPriv::get_or_throw(std::future<T>& f) {
4574+ if (f.wait_for(std::chrono::seconds(httpclient_->config_.request_timeout)) !=
4575+ std::future_status::ready) {
4576 throw HttpTimeoutException("HTTP request timeout");
4577 }
4578
4579
4580=== modified file 'src/mcloud/api/client_priv.h'
4581--- src/mcloud/api/client_priv.h 2016-09-26 01:43:23 +0000
4582+++ src/mcloud/api/client_priv.h 2016-10-26 10:36:06 +0000
4583@@ -53,94 +53,94 @@
4584
4585 virtual ~ClientPriv();
4586
4587- DiskInfo disk_info();
4588+ DiskInfo::Ptr disk_info();
4589
4590 std::string cloud_sync_folder_id();
4591
4592- void set_access_token(const std::string &access_token);
4593-
4594- CloudContent::Ptr content_info(const std::string &content_id);
4595-
4596- CloudFolder::Ptr create_folder(const std::string &folder_name,
4597- const std::string &folder_id);
4598-
4599- Client::ResourceList look_up(const std::string &name,
4600- const std::string &folder_id,
4601+ void set_access_token(const std::string& access_token);
4602+
4603+ CloudContent::Ptr content_info(const std::string& content_id);
4604+
4605+ CloudFolder::Ptr create_folder(const std::string& folder_name,
4606+ const std::string& folder_id);
4607+
4608+ Client::ResourceList look_up(const std::string& name,
4609+ const std::string& folder_id,
4610 CloudResource::Property property = CloudResource::Property::Content);
4611
4612- bool refersh_token(const std::string &refresh_token);
4613-
4614- bool move_items(const Client::Stringlist &folder_ids,
4615- const Client::Stringlist &content_ids,
4616- const std::string &folder_id);
4617-
4618- bool exist_on_cloud(const std::string &file_path, const std::string &folder_id);
4619-
4620- bool update_folder(const std::string &folder_id,
4621- const std::string &new_name);
4622-
4623- bool delete_contents(const Client::Stringlist &content_ids);
4624-
4625- Client::Stringlist copy_folders(const Client::Stringlist &folder_ids,
4626- const std::string &folder_id);
4627-
4628- Client::Stringlist copy_contents(const Client::Stringlist &content_ids,
4629- const std::string &folder_id);
4630+ bool refersh_token(const std::string& refresh_token);
4631+
4632+ bool move_items(const Client::Stringlist& folder_ids,
4633+ const Client::Stringlist& content_ids,
4634+ const std::string& folder_id);
4635+
4636+ bool exist_on_cloud(const std::string& file_path, const std::string& folder_id);
4637+
4638+ bool update_folder(const std::string& folder_id,
4639+ const std::string& new_name);
4640+
4641+ bool delete_contents(const Client::Stringlist& content_ids);
4642+
4643+ Client::Stringlist copy_folders(const Client::Stringlist& folder_ids,
4644+ const std::string& folder_id);
4645+
4646+ Client::Stringlist copy_contents(const Client::Stringlist& content_ids,
4647+ const std::string& folder_id);
4648
4649 Client::ResourceList cloud_content_list(int start_index,
4650 int count,
4651 CloudContent::Type content_type = CloudContent::Type::All,
4652- const std::string &folder_id = std::string());
4653-
4654- Client::OutlinkList create_folder_extranet_link(const Client::Stringlist &folder_ids);
4655-
4656- Client::OutlinkList create_content_extranet_link(const Client::Stringlist &content_ids);
4657-
4658- DownloadTaskPriv::Ptr create_download_link(const std::string &content_id);
4659-
4660- DownloadTaskPriv::Ptr create_download_link(const DownloadBufferCb &buffer_cb);
4661+ const std::string& folder_id = std::string());
4662+
4663+ Client::OutlinkList create_folder_sharing_url(const Client::Stringlist& folder_ids);
4664+
4665+ Client::OutlinkList create_content_sharing_url(const Client::Stringlist& content_ids);
4666+
4667+ DownloadTaskPriv::Ptr create_download_link(const std::string& content_id);
4668+
4669+ DownloadTaskPriv::Ptr create_download_link(const DownloadBufferCb& buffer_cb);
4670
4671 //Same name files in different directories are not allowed to upload to mcloud because of file names conflicts.
4672- UploadTaskPriv::Ptr create_upload_link(const UploadRequest &reqeust_item);
4673+ UploadTaskPriv::Ptr create_upload_link(const UploadRequest& reqeust_item);
4674
4675- UploadTaskPriv::Ptr create_upload_link(const UploadBufferCb &buffer_cb);
4676+ UploadTaskPriv::Ptr create_upload_link(const UploadBufferCb& buffer_cb);
4677
4678 void cancel();
4679
4680- std::shared_ptr<SyncManager> sync_manager();
4681+ SyncManager::Ptr sync_manager();
4682
4683 private:
4684 Client::ResourceList cloud_root_folder_list();
4685
4686- Client::ResourceList cloud_content_list_internal(const std::string &postbody);
4687-
4688- CloudContent::Ptr content_item_internal(const std::string &postbody);
4689-
4690- CloudFolder::Ptr create_folder_internal(const std::string &postbody);
4691-
4692- Client::ResourceList look_up_internal(const std::string &postbody);
4693-
4694- bool exist_on_cloud_internal(const std::string &postbody);
4695-
4696- bool move_items_internal(const std::string &postbody);
4697-
4698- bool update_internal(const std::string &postbody);
4699-
4700- bool delete_internal(const std::string &postbody);
4701-
4702- Client::Stringlist copy_internal(const std::string &postbody);
4703-
4704- Client::OutlinkList create_extranet_internal(const std::string &postbody);
4705-
4706- template<typename T> T get_or_throw(std::future<T> &f);
4707+ Client::ResourceList cloud_content_list_internal(const std::string& postbody);
4708+
4709+ CloudContent::Ptr content_item_internal(const std::string& postbody);
4710+
4711+ CloudFolder::Ptr create_folder_internal(const std::string& postbody);
4712+
4713+ Client::ResourceList look_up_internal(const std::string& postbody);
4714+
4715+ bool exist_on_cloud_internal(const std::string& postbody);
4716+
4717+ bool move_items_internal(const std::string& postbody);
4718+
4719+ bool update_internal(const std::string& postbody);
4720+
4721+ bool delete_internal(const std::string& postbody);
4722+
4723+ Client::Stringlist copy_internal(const std::string& postbody);
4724+
4725+ Client::OutlinkList create_url_internal(const std::string& postbody);
4726+
4727+ template<typename T> T get_or_throw(std::future<T>& f);
4728
4729 private:
4730
4731 class HttpClient;
4732
4733- std::shared_ptr<HttpClient> httpclient_;
4734+ std::unique_ptr<HttpClient> httpclient_;
4735
4736- std::shared_ptr<SyncManager> sync_manager_;
4737+ SyncManager::Ptr sync_manager_;
4738 };
4739
4740 }
4741
4742=== modified file 'src/mcloud/api/cloudcontent.cpp'
4743--- src/mcloud/api/cloudcontent.cpp 2016-09-26 01:43:23 +0000
4744+++ src/mcloud/api/cloudcontent.cpp 2016-10-26 10:36:06 +0000
4745@@ -23,12 +23,12 @@
4746 using namespace mcloud::api;
4747 using namespace std;
4748
4749-extern std::time_t string_to_time(const std::string dt);
4750+extern time_t string_to_time(const string& dt);
4751
4752 class CloudContent::Priv {
4753-public:
4754- Priv(const tinyxml2::XMLElement *root) {
4755- name_= root->FirstChildElement("contentName")->GetText();
4756+ public:
4757+ Priv(const tinyxml2::XMLElement* root) {
4758+ name_ = root->FirstChildElement("contentName")->GetText();
4759 id_ = root->FirstChildElement("contentID")->GetText();
4760 created_date_ = string_to_time(root->FirstChildElement("uploadTime")->GetText());
4761 updated_date_ = string_to_time(root->FirstChildElement("updateTime")->GetText());
4762@@ -67,69 +67,72 @@
4763 etag_ = etag_ele->GetText();
4764 }
4765
4766- #ifndef NDEBUG
4767- cout << "id: "<< id_ << " name: " << name_ << " etag: "<< etag_ << endl;
4768- #endif
4769+#ifndef NDEBUG
4770+ cout << "id: " << id_ << " name: " << name_ << " etag: " << etag_ << endl;
4771+#endif
4772 }
4773
4774- std::string id_;
4775-
4776- std::string name_;
4777-
4778- std::time_t created_date_;
4779-
4780- std::time_t updated_date_;
4781-
4782- std::string etag_;
4783-
4784- std::string owner_;
4785-
4786- std::string suffix_;
4787-
4788- CloudContent::Type type_;
4789-
4790- int64_t content_size_;
4791-
4792- std::string description_;
4793-
4794- std::string thumbnail_url_;
4795-
4796- std::string big_thumbnail_url_;
4797-
4798- std::string present_url_;
4799-
4800- std::string parent_catalog_id_;
4801+ string id_;
4802+
4803+ string name_;
4804+
4805+ time_t created_date_;
4806+
4807+ time_t updated_date_;
4808+
4809+ string etag_;
4810+
4811+ string owner_;
4812+
4813+ string suffix_;
4814+
4815+ CloudContent::Type type_;
4816+
4817+ int64_t content_size_;
4818+
4819+ string description_;
4820+
4821+ string thumbnail_url_;
4822+
4823+ string big_thumbnail_url_;
4824+
4825+ string present_url_;
4826+
4827+ string parent_catalog_id_;
4828 };
4829
4830-CloudContent::CloudContent(const tinyxml2::XMLElement *root)
4831- : p(std::make_shared<Priv>(root)){
4832-}
4833-
4834-const string &CloudContent::id() const {
4835+CloudContent::CloudContent(const tinyxml2::XMLElement* root)
4836+ : p(new Priv(root)) {
4837+}
4838+
4839+CloudContent::~CloudContent() {
4840+}
4841+
4842+const string& CloudContent::id() const {
4843 return p->id_;
4844 }
4845
4846-const string &CloudContent::name() const {
4847+const string& CloudContent::name() const {
4848 return p->name_;
4849 }
4850
4851-const time_t &CloudContent::created_date() const {
4852+const time_t& CloudContent::created_date() const {
4853 return p->created_date_;
4854 }
4855
4856-const time_t &CloudContent::updated_date() const {
4857+const time_t& CloudContent::updated_date() const {
4858 return p->updated_date_;
4859 }
4860
4861-const string &CloudContent::parent_catalog_id() const {
4862+const string& CloudContent::parent_catalog_id() const {
4863 return p->parent_catalog_id_;
4864 }
4865
4866-const string &CloudContent::etag() const {
4867+const string& CloudContent::etag() const {
4868 return p->etag_;
4869 }
4870
4871-const string &CloudContent::owner() const {
4872+const string& CloudContent::owner() const {
4873 return p->owner_;
4874 }
4875
4876@@ -137,7 +140,7 @@
4877 return CloudResource::Property::Content;
4878 }
4879
4880-const string &CloudContent::suffix() const {
4881+const string& CloudContent::suffix() const {
4882 return p->suffix_;
4883 }
4884
4885@@ -149,18 +152,18 @@
4886 return p->content_size_;
4887 }
4888
4889-const string &CloudContent::description() const {
4890+const string& CloudContent::description() const {
4891 return p->description_;
4892 }
4893
4894-const string &CloudContent::thumbnail_url() const {
4895+const string& CloudContent::thumbnail_url() const {
4896 return p->thumbnail_url_;
4897 }
4898
4899-const string &CloudContent::big_thumbnail_url() const {
4900+const string& CloudContent::big_thumbnail_url() const {
4901 return p->big_thumbnail_url_;
4902 }
4903
4904-const string &CloudContent::present_url() const {
4905+const string& CloudContent::present_url() const {
4906 return p->present_url_;
4907 }
4908
4909=== modified file 'src/mcloud/api/cloudfolder.cpp'
4910--- src/mcloud/api/cloudfolder.cpp 2016-09-26 01:43:23 +0000
4911+++ src/mcloud/api/cloudfolder.cpp 2016-10-26 10:36:06 +0000
4912@@ -27,17 +27,17 @@
4913 using namespace mcloud::api;
4914 using namespace std;
4915
4916-std::time_t string_to_time(const std::string dt) {
4917- struct std::tm tm;
4918- std::istringstream ss(dt);
4919- strptime(dt.c_str(), "%Y%m%d%H%M%S",&tm); // std::get std::put only available in GCC 5
4920- return std::mktime(&tm);
4921+time_t string_to_time(const string& dt) {
4922+ struct tm tm;
4923+ istringstream ss(dt);
4924+ strptime(dt.c_str(), "%Y%m%d%H%M%S", &tm); // get put only available in GCC 5
4925+ return mktime(&tm);
4926 }
4927
4928 class CloudFolder::Priv {
4929-public:
4930- Priv(const tinyxml2::XMLElement *root) {
4931- name_= root->FirstChildElement("catalogName")->GetText();
4932+ public:
4933+ Priv(const tinyxml2::XMLElement* root) {
4934+ name_ = root->FirstChildElement("catalogName")->GetText();
4935 id_ = root->FirstChildElement("catalogID")->GetText();
4936 created_date_ = string_to_time(root->FirstChildElement("createTime")->GetText());
4937 update_date_ = string_to_time(root->FirstChildElement("updateTime")->GetText());
4938@@ -72,64 +72,67 @@
4939 folder_type_ = (Type)atoi(root->FirstChildElement("catalogType")->GetText());
4940
4941
4942- #ifndef NDEBUG
4943- cout << "id: "<< id_ << " name: " << name_ << " etag: "<< etag_ << endl;
4944- #endif
4945+#ifndef NDEBUG
4946+ cout << "id: " << id_ << " name: " << name_ << " etag: " << etag_ << endl;
4947+#endif
4948
4949 }
4950
4951- std::string id_;
4952-
4953- std::string name_;
4954-
4955- std::time_t created_date_;
4956-
4957- std::time_t update_date_;
4958-
4959- std::string parent_catalog_id_;
4960-
4961- std::string etag_;
4962-
4963- std::string owner_;
4964+ string id_;
4965+
4966+ string name_;
4967+
4968+ time_t created_date_;
4969+
4970+ time_t update_date_;
4971+
4972+ string parent_catalog_id_;
4973+
4974+ string etag_;
4975+
4976+ string owner_;
4977
4978 CloudFolder::Type folder_type_;
4979
4980- std::string folder_path_;
4981+ string folder_path_;
4982 };
4983
4984-CloudFolder::CloudFolder(const tinyxml2::XMLElement *root)
4985- :p_(std::make_shared<Priv>(root)){
4986-}
4987-
4988-const string &CloudFolder::id() const {
4989+CloudFolder::CloudFolder(const tinyxml2::XMLElement* root)
4990+ : p_(new Priv(root)) {
4991+}
4992+
4993+CloudFolder::~CloudFolder() {
4994+}
4995+
4996+const string& CloudFolder::id() const {
4997 return p_->id_;
4998 }
4999
5000-const string &CloudFolder::name() const {
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: