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