Merge lp:~xavi-garcia-mena/keeper/restore into lp:keeper/devel
- restore
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Charles Kerr |
Approved revision: | 142 |
Merged at revision: | 121 |
Proposed branch: | lp:~xavi-garcia-mena/keeper/restore |
Merge into: | lp:keeper/devel |
Prerequisite: | lp:~xavi-garcia-mena/keeper/manifest-after-last-task |
Diff against target: |
1993 lines (+1234/-88) 37 files modified
data/helper-registry.json.in (+6/-1) include/helper/data-dir-registry.h (+2/-0) include/helper/metadata.h (+1/-0) include/helper/registry.h (+1/-0) include/helper/restore-helper.h (+62/-0) src/helper/CMakeLists.txt (+2/-0) src/helper/data-dir-registry.cpp (+43/-11) src/helper/metadata.cpp (+1/-0) src/helper/restore-helper.cpp (+366/-0) src/service/CMakeLists.txt (+1/-0) src/service/keeper-helper.cpp (+5/-2) src/service/keeper-task-restore.cpp (+130/-0) src/service/keeper-task-restore.h (+46/-0) src/service/keeper-user.cpp (+8/-2) src/service/keeper.cpp (+79/-33) src/service/keeper.h (+6/-0) src/service/manifest.cpp (+3/-3) src/service/task-manager.cpp (+30/-3) src/service/task-manager.h (+2/-0) src/storage-framework/CMakeLists.txt (+3/-0) src/storage-framework/downloader.h (+46/-0) src/storage-framework/sf-downloader.cpp (+56/-0) src/storage-framework/sf-downloader.h (+48/-0) src/storage-framework/storage_framework_client.cpp (+21/-20) src/storage-framework/storage_framework_client.h (+2/-1) tests/CMakeLists.txt (+6/-0) tests/fakes/CMakeLists.txt (+9/-0) tests/fakes/fake-restore-helper.cpp (+130/-0) tests/fakes/fake-restore-helper.h (+27/-0) tests/integration/helpers/CMakeLists.txt (+4/-0) tests/integration/helpers/helpers-test.cc (+34/-0) tests/integration/helpers/test-helpers-base.cpp (+8/-3) tests/unit/manifest/manifest-test.cpp (+1/-1) tests/unit/storage-framework/create-uploader-test.cpp (+6/-7) tests/utils/file-utils.cpp (+1/-1) tests/utils/storage-framework-local.cpp (+34/-0) tests/utils/storage-framework-local.h (+4/-0) |
To merge this branch: | bzr merge lp:~xavi-garcia-mena/keeper/restore |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
unity-api-1-bot | continuous-integration | Approve | |
Charles Kerr (community) | Approve | ||
Review via email: mp+310653@code.launchpad.net |
Commit message
First version of restore.
Description of the change
This branch adds the first version of restore, with a fake restore helper to test it.
The branch adds the restore-
It also includes a fake restore helper that just reads the contents of the restore file that keeper reads from storage-framework, so we can compare if the download process is fine.
The integration test now runs a backup, checks it, and finally executes a restore based on the restore entries that we get from keeper using the dbus calls.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
- 122. By Xavi Garcia
-
commit just to test on jenkins as it does not fail on the destop
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:122
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 123. By Xavi Garcia
-
more pointers to integration test
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:123
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 124. By Xavi Garcia
-
More tests, this is not intended to be the final solution
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:124
https:/
Executed test runs:
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:124
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:/
- 125. By Xavi Garcia
-
test reading in separated thread
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:125
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:/
- 126. By Xavi Garcia
-
Added simple downloader test
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:126
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:/
- 127. By Xavi Garcia
-
a litle tidy up
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:127
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 128. By Xavi Garcia
-
Fix copyright issue
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:128
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 129. By Xavi Garcia
-
Changed the way we create the socket between keeper and restore helper
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:129
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 130. By Xavi Garcia
-
Removed test exec
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:130
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:/
Click here to trigger a rebuild:
https:/
- 131. By Xavi Garcia
-
Modified back to original version, without QLocalServer
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:131
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 132. By Xavi Garcia
-
clean up the code a bit
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:132
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 133. By Xavi Garcia
-
More cleanup and decreased file sizes to transfers to avoid race conditions in slow boxes
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:133
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 134. By Xavi Garcia
-
Added extra log information
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:134
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 135. By Xavi Garcia
-
Changed sockets to be in a shared pointer
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:135
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 136. By Xavi Garcia
-
Closing socket after setting it to the dbus reply
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:136
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:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:136
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:/
Click here to trigger a rebuild:
https:/
- 137. By Xavi Garcia
-
Removed QLocalSocket to store the socket to send to the helper as QLocalSocket buffers data and makes that the helper misses packets
- 138. By Xavi Garcia
-
Removed test dbus method for waiting to the helper to be ready
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:138
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:/
Click here to trigger a rebuild:
https:/
- 139. By Xavi Garcia
-
Removed extra debug statements
- 140. By Xavi Garcia
-
Removed extra lines
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:139
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:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:140
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:/
Click here to trigger a rebuild:
https:/
Charles Kerr (charlesk) wrote : | # |
inline: one bugfix, some questions, several meddling suggestions
- 141. By Xavi Garcia
-
Changed as suggested after review
Xavi Garcia (xavi-garcia-mena) wrote : | # |
Thanks for the review, Charles...
I'm sorry the branch was a bit messy, specially the test part and too many debug statements.
Comments inline....
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:141
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:/
Click here to trigger a rebuild:
https:/
- 142. By Xavi Garcia
-
Storage framework client bug fixed. A couple of variables needed to be captured
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:142
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Charles Kerr (charlesk) wrote : | # |
Thanks for the cleanups Xavi!
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:
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:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'data/helper-registry.json.in' |
2 | --- data/helper-registry.json.in 2016-08-09 04:20:33 +0000 |
3 | +++ data/helper-registry.json.in 2016-11-24 14:48:54 +0000 |
4 | @@ -4,5 +4,10 @@ |
5 | "@FOLDER_BACKUP_EXEC@", |
6 | "${subtype}" |
7 | ] |
8 | - } |
9 | + , |
10 | + "restore-urls": [ |
11 | + "@FOLDER_RESTORE_EXEC@", |
12 | + "${subtype}" |
13 | + ] |
14 | + } |
15 | } |
16 | |
17 | === modified file 'include/helper/data-dir-registry.h' |
18 | --- include/helper/data-dir-registry.h 2016-08-09 05:44:25 +0000 |
19 | +++ include/helper/data-dir-registry.h 2016-11-24 14:48:54 +0000 |
20 | @@ -39,6 +39,8 @@ |
21 | |
22 | QStringList get_backup_helper_urls(Metadata const& metadata) override; |
23 | |
24 | + QStringList get_restore_helper_urls(Metadata const& metadata) override; |
25 | + |
26 | private: |
27 | class Impl; |
28 | friend class Impl; |
29 | |
30 | === modified file 'include/helper/metadata.h' |
31 | --- include/helper/metadata.h 2016-10-14 09:23:11 +0000 |
32 | +++ include/helper/metadata.h 2016-11-24 14:48:54 +0000 |
33 | @@ -42,6 +42,7 @@ |
34 | static QString const TITLE_KEY; |
35 | static QString const VERSION_KEY; |
36 | static QString const FILE_NAME_KEY; |
37 | + static QString const DIR_NAME_KEY; |
38 | static QString const DISPLAY_NAME_KEY; |
39 | |
40 | // metadata values |
41 | |
42 | === modified file 'include/helper/registry.h' |
43 | --- include/helper/registry.h 2016-08-08 04:56:35 +0000 |
44 | +++ include/helper/registry.h 2016-11-24 14:48:54 +0000 |
45 | @@ -30,6 +30,7 @@ |
46 | Q_DISABLE_COPY(HelperRegistry) |
47 | |
48 | virtual QStringList get_backup_helper_urls(Metadata const& task) =0; |
49 | + virtual QStringList get_restore_helper_urls(Metadata const& task) =0; |
50 | |
51 | protected: |
52 | HelperRegistry() =default; |
53 | |
54 | === added file 'include/helper/restore-helper.h' |
55 | --- include/helper/restore-helper.h 1970-01-01 00:00:00 +0000 |
56 | +++ include/helper/restore-helper.h 2016-11-24 14:48:54 +0000 |
57 | @@ -0,0 +1,62 @@ |
58 | +/* |
59 | + * Copyright (C) 2016 Canonical, Ltd. |
60 | + * |
61 | + * This program is free software: you can redistribute it and/or modify it |
62 | + * under the terms of the GNU General Public License version 3, as published |
63 | + * by the Free Software Foundation. |
64 | + * |
65 | + * This program is distributed in the hope that it will be useful, but |
66 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
67 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
68 | + * PURPOSE. See the GNU General Public License for more details. |
69 | + * |
70 | + * You should have received a copy of the GNU General Public License along |
71 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
72 | + * |
73 | + * Authors: |
74 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
75 | + * Charles Kerr <charles.kerr@canonical.com> |
76 | + */ |
77 | + |
78 | +#pragma once |
79 | + |
80 | +#include "storage-framework/downloader.h" |
81 | +#include "helper/helper.h" // parent class |
82 | +#include "helper/registry.h" |
83 | + |
84 | +#include <QObject> |
85 | +#include <QScopedPointer> |
86 | +#include <QString> |
87 | + |
88 | +#include <memory> |
89 | + |
90 | +class RestoreHelperPrivate; |
91 | +class RestoreHelper final: public Helper |
92 | +{ |
93 | + Q_OBJECT |
94 | + Q_DECLARE_PRIVATE(RestoreHelper) |
95 | + |
96 | +public: |
97 | + RestoreHelper( |
98 | + QString const & appid, |
99 | + clock_func const & clock=Helper::default_clock, |
100 | + QObject * parent=nullptr |
101 | + ); |
102 | + virtual ~RestoreHelper(); |
103 | + Q_DISABLE_COPY(RestoreHelper) |
104 | + |
105 | + static constexpr int MAX_INACTIVITY_TIME = 15000; |
106 | + |
107 | + void set_downloader(std::shared_ptr<Downloader> const& downloader); |
108 | + |
109 | + void start(QStringList const& urls) override; |
110 | + void stop() override; |
111 | + int get_helper_socket() const; |
112 | + QString to_string(Helper::State state) const override; |
113 | + void set_state(State) override; |
114 | +protected: |
115 | + void on_helper_finished() override; |
116 | + |
117 | +private: |
118 | + QScopedPointer<RestoreHelperPrivate> const d_ptr; |
119 | +}; |
120 | |
121 | === modified file 'src/helper/CMakeLists.txt' |
122 | --- src/helper/CMakeLists.txt 2016-09-06 01:31:59 +0000 |
123 | +++ src/helper/CMakeLists.txt 2016-11-24 14:48:54 +0000 |
124 | @@ -48,10 +48,12 @@ |
125 | ${HELPER_LIB} |
126 | STATIC |
127 | backup-helper.cpp |
128 | + restore-helper.cpp |
129 | data-dir-registry.cpp |
130 | helper.cpp |
131 | metadata.cpp |
132 | ${CMAKE_SOURCE_DIR}/include/helper/backup-helper.h |
133 | + ${CMAKE_SOURCE_DIR}/include/helper/restore-helper.h |
134 | ${CMAKE_SOURCE_DIR}/include/helper/data-dir-registry.h |
135 | ${CMAKE_SOURCE_DIR}/include/helper/helper.h |
136 | ${CMAKE_SOURCE_DIR}/include/helper/registry.h |
137 | |
138 | === modified file 'src/helper/data-dir-registry.cpp' |
139 | --- src/helper/data-dir-registry.cpp 2016-08-10 02:29:17 +0000 |
140 | +++ src/helper/data-dir-registry.cpp 2016-11-24 14:48:54 +0000 |
141 | @@ -49,15 +49,27 @@ |
142 | |
143 | QStringList get_backup_helper_urls(Metadata const& task) |
144 | { |
145 | + return get_helper_urls(task, "backup"); |
146 | + } |
147 | + |
148 | + QStringList get_restore_helper_urls(Metadata const& task) |
149 | + { |
150 | + return get_helper_urls(task, "restore"); |
151 | + } |
152 | + |
153 | +private: |
154 | + |
155 | + QStringList get_helper_urls(Metadata const& task, QString const & prop) |
156 | + { |
157 | QStringList ret; |
158 | |
159 | QString type; |
160 | if (task.get_property(Metadata::TYPE_KEY, type)) |
161 | { |
162 | - auto it = registry_.find(std::make_pair(type,QStringLiteral("backup"))); |
163 | + auto it = registry_.find(std::make_pair(type,prop)); |
164 | if (it == registry_.end()) |
165 | { |
166 | - qCritical() << "can't get backup helper urls for unhandled type" << type; |
167 | + qCritical() << "can't get " << prop << " helper urls for unhandled type" << type; |
168 | } |
169 | else |
170 | { |
171 | @@ -73,8 +85,6 @@ |
172 | return ret; |
173 | } |
174 | |
175 | -private: |
176 | - |
177 | // replace "${key}" with task.get_property("key") |
178 | QStringList perform_url_substitution(Metadata const& task, QStringList const& urls_in) |
179 | { |
180 | @@ -139,6 +149,10 @@ |
181 | * "backup-urls": [ |
182 | * "/path/to/helper.sh", |
183 | * "${subtype}" |
184 | + * ], |
185 | + * "restore-urls": [ |
186 | + * "/path/to/helper.sh", |
187 | + * "${subtype}" |
188 | * ] |
189 | * } |
190 | * } |
191 | @@ -156,25 +170,37 @@ |
192 | if (error.error != QJsonParseError::NoError) |
193 | qCritical() << path << "parse error at offset" << error.offset << error.errorString(); |
194 | |
195 | - auto obj = doc.object(); |
196 | + const auto obj = doc.object(); |
197 | for (auto tit=obj.begin(), tend=obj.end(); tit!=tend; ++tit) |
198 | { |
199 | auto const type = tit.key(); |
200 | - auto& info = registry_[std::make_pair(type,QStringLiteral("backup"))]; |
201 | - |
202 | auto const props = tit.value().toObject(); |
203 | - auto const urls_jsonval = props["backup-urls"]; |
204 | + |
205 | + auto const &urls_jsonval = props["backup-urls"]; |
206 | if (urls_jsonval.isArray()) |
207 | { |
208 | + auto& info = registry_[std::make_pair(type,QStringLiteral("backup"))]; |
209 | for (auto url_jsonval : urls_jsonval.toArray()) |
210 | { |
211 | info.urls.push_back(url_jsonval.toString()); |
212 | } |
213 | + qDebug() << "loaded" << type << "backup urls from" << path; |
214 | + for(auto const& url : info.urls) |
215 | + qDebug() << "\turl:" << url; |
216 | } |
217 | |
218 | - qDebug() << "loaded" << type << "backup urls from" << path; |
219 | - for(auto const& url : info.urls) |
220 | - qDebug() << "\turl:" << url; |
221 | + auto const &urls_jsonval_restore = props["restore-urls"]; |
222 | + if (urls_jsonval_restore.isArray()) |
223 | + { |
224 | + auto& info = registry_[std::make_pair(type,QStringLiteral("restore"))]; |
225 | + for (auto url_jsonval : urls_jsonval_restore.toArray()) |
226 | + { |
227 | + info.urls.push_back(url_jsonval.toString()); |
228 | + } |
229 | + qDebug() << "loaded" << type << "restore urls from" << path; |
230 | + for(auto const& url : info.urls) |
231 | + qDebug() << "\turl:" << url; |
232 | + } |
233 | } |
234 | } |
235 | } |
236 | @@ -198,3 +224,9 @@ |
237 | { |
238 | return impl_->get_backup_helper_urls(task); |
239 | } |
240 | + |
241 | +QStringList |
242 | +DataDirRegistry::get_restore_helper_urls(Metadata const& task) |
243 | +{ |
244 | + return impl_->get_restore_helper_urls(task); |
245 | +} |
246 | |
247 | === modified file 'src/helper/metadata.cpp' |
248 | --- src/helper/metadata.cpp 2016-10-14 09:23:11 +0000 |
249 | +++ src/helper/metadata.cpp 2016-11-24 14:48:54 +0000 |
250 | @@ -42,6 +42,7 @@ |
251 | const QString Metadata::TITLE_KEY = QStringLiteral("title"); |
252 | const QString Metadata::VERSION_KEY = QStringLiteral("version"); |
253 | const QString Metadata::FILE_NAME_KEY = QStringLiteral("file-name"); |
254 | +const QString Metadata::DIR_NAME_KEY = QStringLiteral("dir-name"); |
255 | const QString Metadata::DISPLAY_NAME_KEY = QStringLiteral("display-name"); |
256 | |
257 | // Metadata values |
258 | |
259 | === added file 'src/helper/restore-helper.cpp' |
260 | --- src/helper/restore-helper.cpp 1970-01-01 00:00:00 +0000 |
261 | +++ src/helper/restore-helper.cpp 2016-11-24 14:48:54 +0000 |
262 | @@ -0,0 +1,366 @@ |
263 | +/* |
264 | + * Copyright (C) 2016 Canonical, Ltd. |
265 | + * |
266 | + * This program is free software: you can redistribute it and/or modify it |
267 | + * under the terms of the GNU General Public License version 3, as published |
268 | + * by the Free Software Foundation. |
269 | + * |
270 | + * This program is distributed in the hope that it will be useful, but |
271 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
272 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
273 | + * PURPOSE. See the GNU General Public License for more details. |
274 | + * |
275 | + * You should have received a copy of the GNU General Public License along |
276 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
277 | + * |
278 | + * Authors: |
279 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
280 | + * Charles Kerr <charles.kerr@canonical.com> |
281 | + */ |
282 | + |
283 | +#include "util/connection-helper.h" |
284 | +#include "helper/restore-helper.h" |
285 | +#include "service/app-const.h" // HELPER_TYPE |
286 | + |
287 | +#include <QByteArray> |
288 | +#include <QDebug> |
289 | +#include <QLocalSocket> |
290 | +#include <QMap> |
291 | +#include <QObject> |
292 | +#include <QString> |
293 | +#include <QTimer> |
294 | +#include <QVector> |
295 | + |
296 | +#include <fcntl.h> |
297 | +#include <sys/types.h> |
298 | +#include <sys/socket.h> |
299 | + |
300 | +#include <functional> // std::bind() |
301 | + |
302 | + |
303 | +class RestoreHelperPrivate |
304 | +{ |
305 | +public: |
306 | + |
307 | + explicit RestoreHelperPrivate( |
308 | + RestoreHelper* backup_helper |
309 | + ) |
310 | + : q_ptr(backup_helper) |
311 | + { |
312 | + // listen for inactivity from storage framework |
313 | + QObject::connect(&timer_, &QTimer::timeout, |
314 | + std::bind(&RestoreHelperPrivate::on_inactivity_detected, this) |
315 | + ); |
316 | + |
317 | + // fire up the sockets |
318 | + int fds[2]; |
319 | + int rc = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds); |
320 | + if (rc == -1) |
321 | + { |
322 | + // TODO throw exception. |
323 | + qWarning() << "RestoreHelperPrivate: error creating socket pair to communicate with helper "; |
324 | + return; |
325 | + } |
326 | + |
327 | + // helper socket is for the client. |
328 | + // We don't use a QLocalSocket here as it buffers data and it makes the helper miss packets. |
329 | + helper_socket_ = fds[1]; |
330 | + |
331 | + write_socket_.setSocketDescriptor(fds[0], QLocalSocket::ConnectedState, QIODevice::WriteOnly); |
332 | + } |
333 | + |
334 | + ~RestoreHelperPrivate() = default; |
335 | + |
336 | + Q_DISABLE_COPY(RestoreHelperPrivate) |
337 | + |
338 | + void start(QStringList const& urls) |
339 | + { |
340 | + q_ptr->Helper::start(urls); |
341 | + reset_inactivity_timer(); |
342 | + } |
343 | + |
344 | + void set_downloader(std::shared_ptr<Downloader> const& downloader) |
345 | + { |
346 | + n_read_ = 0; |
347 | + n_uploaded_ = 0; |
348 | + read_error_ = false; |
349 | + write_error_ = false; |
350 | + cancelled_ = false; |
351 | + |
352 | + q_ptr->set_expected_size(downloader->file_size()); |
353 | + downloader_ = downloader; |
354 | + |
355 | + connections_.remember(QObject::connect( |
356 | + &write_socket_, &QLocalSocket::bytesWritten, |
357 | + std::bind(&RestoreHelperPrivate::on_data_uploaded, this, std::placeholders::_1) |
358 | + )); |
359 | + |
360 | + // listen for data ready to read |
361 | + QObject::connect(downloader_->socket().get(), &QLocalSocket::readyRead, |
362 | + std::bind(&RestoreHelperPrivate::on_ready_read, this) |
363 | + ); |
364 | + |
365 | + // maybe there's data already to be read |
366 | + process_more(); |
367 | + |
368 | + reset_inactivity_timer(); |
369 | + } |
370 | + |
371 | + void stop() |
372 | + { |
373 | + write_socket_.disconnectFromServer(); |
374 | + cancelled_ = true; |
375 | + q_ptr->Helper::stop(); |
376 | + } |
377 | + |
378 | + int get_helper_socket() const |
379 | + { |
380 | + return helper_socket_; |
381 | + } |
382 | + |
383 | + QString to_string(Helper::State state) const |
384 | + { |
385 | + return state == Helper::State::STARTED |
386 | + ? QStringLiteral("restoring") |
387 | + : q_ptr->Helper::to_string(state); |
388 | + } |
389 | + |
390 | + void on_state_changed(Helper::State state) |
391 | + { |
392 | + switch (state) |
393 | + { |
394 | + case Helper::State::CANCELLED: |
395 | + case Helper::State::FAILED: |
396 | + qDebug() << "cancelled/failed, calling downloader_.reset()"; |
397 | + downloader_.reset(); |
398 | + break; |
399 | + |
400 | + case Helper::State::DATA_COMPLETE: { |
401 | + qDebug() << "Restore helper finished, calling downloader_.finish()"; |
402 | + write_socket_.disconnectFromServer(); |
403 | + downloader_->finish(); |
404 | + downloader_.reset(); |
405 | + break; |
406 | + } |
407 | + |
408 | + //case Helper::State::NOT_STARTED: |
409 | + //case Helper::State::STARTED: |
410 | + default: |
411 | + break; |
412 | + } |
413 | + } |
414 | + |
415 | + void on_helper_finished() |
416 | + { |
417 | + stop_inactivity_timer(); |
418 | + check_for_done(); |
419 | + } |
420 | + |
421 | +private: |
422 | + |
423 | + void on_inactivity_detected() |
424 | + { |
425 | + stop_inactivity_timer(); |
426 | + qWarning() << "Inactivity detected in the helper...stopping it"; |
427 | + stop(); |
428 | + } |
429 | + |
430 | + void on_ready_read() |
431 | + { |
432 | + process_more(); |
433 | + } |
434 | + |
435 | + void on_data_uploaded(qint64 n) |
436 | + { |
437 | + n_uploaded_ += n; |
438 | + q_ptr->record_data_transferred(n); |
439 | + qDebug("n_read %zu n_uploaded %zu (newly uploaded %zu)", size_t(n_read_), size_t(n_uploaded_), size_t(n)); |
440 | + process_more(); |
441 | + check_for_done(); |
442 | + } |
443 | + |
444 | + void process_more() |
445 | + { |
446 | + if (!downloader_) |
447 | + return; |
448 | + |
449 | + char readbuf[UPLOAD_BUFFER_MAX_]; |
450 | + auto socket = downloader_->socket(); |
451 | + while(socket->bytesAvailable() || upload_buffer_.size()) |
452 | + { |
453 | + if (socket->bytesAvailable()) |
454 | + { |
455 | + // try to fill the upload buf |
456 | + int max_bytes = UPLOAD_BUFFER_MAX_ - upload_buffer_.size(); |
457 | + if (max_bytes > 0) { |
458 | + const auto n = socket->read(readbuf, max_bytes); |
459 | + if (n > 0) { |
460 | + n_read_ += n; |
461 | + upload_buffer_.append(readbuf, int(n)); |
462 | + qDebug("upload_buffer_.size() is %zu after reading %zu from helper", size_t(upload_buffer_.size()), size_t(n)); |
463 | + } |
464 | + else if (n < 0) { |
465 | + read_error_ = true; |
466 | + qDebug() << "Read error in restore helper: " << socket->errorString(); |
467 | + stop(); |
468 | + return; |
469 | + } |
470 | + } |
471 | + } |
472 | + |
473 | + if (upload_buffer_.size()) |
474 | + { |
475 | + // try to empty the upload buf |
476 | + const auto n = write_socket_.write(upload_buffer_); |
477 | + if (n > 0) { |
478 | + upload_buffer_.remove(0, int(n)); |
479 | + qDebug("upload_buffer_.size() is %zu after writing %zu to cloud", size_t(upload_buffer_.size()), size_t(n)); |
480 | + continue; |
481 | + } |
482 | + else { |
483 | + if (n < 0) { |
484 | + write_error_ = true; |
485 | + qWarning() << "Write error:" << write_socket_.errorString(); |
486 | + stop(); |
487 | + } |
488 | + break; |
489 | + } |
490 | + } |
491 | + } |
492 | + |
493 | + reset_inactivity_timer(); |
494 | + } |
495 | + |
496 | + void reset_inactivity_timer() |
497 | + { |
498 | + static constexpr int MAX_TIME_WAITING_FOR_DATA {RestoreHelper::MAX_INACTIVITY_TIME}; |
499 | + timer_.start(MAX_TIME_WAITING_FOR_DATA); |
500 | + } |
501 | + |
502 | + void stop_inactivity_timer() |
503 | + { |
504 | + timer_.stop(); |
505 | + } |
506 | + |
507 | + void check_for_done() |
508 | + { |
509 | + if (cancelled_) |
510 | + { |
511 | + q_ptr->set_state(Helper::State::CANCELLED); |
512 | + } |
513 | + else if (read_error_ || write_error_ || n_uploaded_ > q_ptr->expected_size()) |
514 | + { |
515 | + if (!q_ptr->is_helper_running()) |
516 | + { |
517 | + q_ptr->set_state(Helper::State::FAILED); |
518 | + } |
519 | + } |
520 | + else if (n_uploaded_ == q_ptr->expected_size()) |
521 | + { |
522 | + if (downloader_) |
523 | + { |
524 | + if (q_ptr->is_helper_running()) |
525 | + { |
526 | + // only in the case that the helper process finished we move to the next state |
527 | + // this is to prevent to start the next task too early |
528 | + q_ptr->set_state(Helper::State::DATA_COMPLETE); |
529 | + stop_inactivity_timer(); |
530 | + } |
531 | + } |
532 | + else |
533 | + q_ptr->set_state(Helper::State::COMPLETE); |
534 | + } |
535 | + } |
536 | + |
537 | + /*** |
538 | + **** |
539 | + ***/ |
540 | + |
541 | + static constexpr int UPLOAD_BUFFER_MAX_ {1024*16}; |
542 | + |
543 | + RestoreHelper * const q_ptr; |
544 | + QTimer timer_; |
545 | + std::shared_ptr<Downloader> downloader_; |
546 | + int helper_socket_ = -1; |
547 | + QLocalSocket write_socket_; |
548 | + QByteArray upload_buffer_; |
549 | + qint64 n_read_ = 0; |
550 | + qint64 n_uploaded_ = 0; |
551 | + bool read_error_ = false; |
552 | + bool write_error_ = false; |
553 | + bool cancelled_ = false; |
554 | + ConnectionHelper connections_; |
555 | +}; |
556 | + |
557 | +/*** |
558 | +**** |
559 | +***/ |
560 | + |
561 | +RestoreHelper::RestoreHelper( |
562 | + QString const & appid, |
563 | + clock_func const & clock, |
564 | + QObject * parent |
565 | +) |
566 | + : Helper(appid, clock, parent) |
567 | + , d_ptr(new RestoreHelperPrivate(this)) |
568 | +{ |
569 | +} |
570 | + |
571 | +RestoreHelper::~RestoreHelper() =default; |
572 | + |
573 | +void |
574 | +RestoreHelper::start(QStringList const& url) |
575 | +{ |
576 | + Q_D(RestoreHelper); |
577 | + |
578 | + d->start(url); |
579 | +} |
580 | + |
581 | +void |
582 | +RestoreHelper::stop() |
583 | +{ |
584 | + Q_D(RestoreHelper); |
585 | + |
586 | + d->stop(); |
587 | +} |
588 | + |
589 | +void |
590 | +RestoreHelper::set_downloader(std::shared_ptr<Downloader> const& downloader) |
591 | +{ |
592 | + Q_D(RestoreHelper); |
593 | + |
594 | + d->set_downloader(downloader); |
595 | +} |
596 | + |
597 | +int |
598 | +RestoreHelper::get_helper_socket() const |
599 | +{ |
600 | + Q_D(const RestoreHelper); |
601 | + |
602 | + return d->get_helper_socket(); |
603 | +} |
604 | + |
605 | +QString |
606 | +RestoreHelper::to_string(Helper::State state) const |
607 | +{ |
608 | + Q_D(const RestoreHelper); |
609 | + |
610 | + return d->to_string(state); |
611 | +} |
612 | + |
613 | +void |
614 | +RestoreHelper::set_state(Helper::State state) |
615 | +{ |
616 | + Q_D(RestoreHelper); |
617 | + |
618 | + Helper::set_state(state); |
619 | + d->on_state_changed(state); |
620 | +} |
621 | + |
622 | +void RestoreHelper::on_helper_finished() |
623 | +{ |
624 | + Q_D(RestoreHelper); |
625 | + |
626 | + Helper::on_helper_finished(); |
627 | + d->on_helper_finished(); |
628 | +} |
629 | |
630 | === modified file 'src/service/CMakeLists.txt' |
631 | --- src/service/CMakeLists.txt 2016-10-28 15:11:21 +0000 |
632 | +++ src/service/CMakeLists.txt 2016-11-24 14:48:54 +0000 |
633 | @@ -15,6 +15,7 @@ |
634 | task-manager.cpp |
635 | keeper-task.cpp |
636 | keeper-task-backup.cpp |
637 | + keeper-task-restore.cpp |
638 | manifest.cpp |
639 | metadata-provider.h |
640 | ) |
641 | |
642 | === modified file 'src/service/keeper-helper.cpp' |
643 | --- src/service/keeper-helper.cpp 2016-08-10 02:06:08 +0000 |
644 | +++ src/service/keeper-helper.cpp 2016-11-24 14:48:54 +0000 |
645 | @@ -44,8 +44,11 @@ |
646 | |
647 | QDBusUnixFileDescriptor KeeperHelper::StartRestore() |
648 | { |
649 | - // TODO get the file descriptor of the item in storage framework |
650 | - return QDBusUnixFileDescriptor(); |
651 | + // pass it back to Keeper to do the work |
652 | + Q_ASSERT(calledFromDBus()); |
653 | + auto bus = connection(); |
654 | + auto& msg = message(); |
655 | + return keeper_.StartRestore(bus, msg); |
656 | } |
657 | |
658 | void KeeperHelper::UpdateStatus(const QString &app_id, const QString &status, double percentage) |
659 | |
660 | === added file 'src/service/keeper-task-restore.cpp' |
661 | --- src/service/keeper-task-restore.cpp 1970-01-01 00:00:00 +0000 |
662 | +++ src/service/keeper-task-restore.cpp 2016-11-24 14:48:54 +0000 |
663 | @@ -0,0 +1,130 @@ |
664 | +/* |
665 | + * Copyright (C) 2016 Canonical, Ltd. |
666 | + * |
667 | + * This program is free software: you can redistribute it and/or modify it |
668 | + * under the terms of the GNU General Public License version 3, as published |
669 | + * by the Free Software Foundation. |
670 | + * |
671 | + * This program is distributed in the hope that it will be useful, but |
672 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
673 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
674 | + * PURPOSE. See the GNU General Public License for more details. |
675 | + * |
676 | + * You should have received a copy of the GNU General Public License along |
677 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
678 | + * |
679 | + * Authors: |
680 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
681 | + * Charles Kerr <charles.kerr@canonical.com> |
682 | + */ |
683 | + |
684 | +#include "util/connection-helper.h" |
685 | +#include "storage-framework/storage_framework_client.h" |
686 | +#include "helper/restore-helper.h" |
687 | +#include "service/app-const.h" // DEKKO_APP_ID |
688 | +#include "service/keeper-task-restore.h" |
689 | +#include "service/keeper-task.h" |
690 | +#include "service/private/keeper-task_p.h" |
691 | + |
692 | +namespace sf = unity::storage::qt::client; |
693 | + |
694 | +class KeeperTaskRestorePrivate : public KeeperTaskPrivate |
695 | +{ |
696 | + Q_DECLARE_PUBLIC(KeeperTaskRestore) |
697 | +public: |
698 | + KeeperTaskRestorePrivate(KeeperTask * keeper_task, |
699 | + KeeperTask::TaskData & task_data, |
700 | + QSharedPointer<HelperRegistry> const & helper_registry, |
701 | + QSharedPointer<StorageFrameworkClient> const & storage) |
702 | + : KeeperTaskPrivate(keeper_task, task_data, helper_registry, storage) |
703 | + { |
704 | + } |
705 | + |
706 | + ~KeeperTaskRestorePrivate() = default; |
707 | + |
708 | + QStringList get_helper_urls() const |
709 | + { |
710 | + return helper_registry_->get_restore_helper_urls(task_data_.metadata); |
711 | + } |
712 | + |
713 | + void init_helper() |
714 | + { |
715 | + qDebug() << "Initializing a restore helper"; |
716 | + helper_.reset(new RestoreHelper(DEKKO_APP_ID), [](Helper *h){h->deleteLater();}); |
717 | + qDebug() << "Helper " << static_cast<void*>(helper_.data()) << " was created"; |
718 | + } |
719 | + |
720 | + void ask_for_downloader() |
721 | + { |
722 | + qDebug() << "asking storage framework for a socket for reading"; |
723 | + |
724 | + QString file_name; |
725 | + task_data_.metadata.get_property(Metadata::FILE_NAME_KEY, file_name); |
726 | + if (file_name.isEmpty()) |
727 | + { |
728 | + qWarning() << "ERROR: the restore task does not provide a valid file name to read from."; |
729 | + return; |
730 | + } |
731 | + |
732 | + QString dir_name; |
733 | + task_data_.metadata.get_property(Metadata::DIR_NAME_KEY, dir_name); |
734 | + if (dir_name.isEmpty()) |
735 | + { |
736 | + qWarning() << "ERROR: the restore task does not provide a valid directory name."; |
737 | + return; |
738 | + } |
739 | + |
740 | + // extract the dir_name. |
741 | + connections_.connect_future( |
742 | + storage_->get_new_downloader(dir_name, file_name), |
743 | + std::function<void(std::shared_ptr<Downloader> const&)>{ |
744 | + [this](std::shared_ptr<Downloader> const& downloader){ |
745 | + qDebug() << "Downloader is" << static_cast<void*>(downloader.get()); |
746 | + int fd {-1}; |
747 | + if (downloader) { |
748 | + qDebug() << "Helper is " << static_cast<void*>(helper_.data()); |
749 | + auto restore_helper = qSharedPointerDynamicCast<RestoreHelper>(helper_); |
750 | + restore_helper->set_downloader(downloader); |
751 | + fd = restore_helper->get_helper_socket(); |
752 | + } |
753 | + qDebug("emitting task_socket_ready(socket=%d)", fd); |
754 | + Q_EMIT(q_ptr->task_socket_ready(fd)); |
755 | + } |
756 | + } |
757 | + ); |
758 | + } |
759 | + |
760 | +private: |
761 | + ConnectionHelper connections_; |
762 | +}; |
763 | + |
764 | +KeeperTaskRestore::KeeperTaskRestore(TaskData & task_data, |
765 | + QSharedPointer<HelperRegistry> const & helper_registry, |
766 | + QSharedPointer<StorageFrameworkClient> const & storage, |
767 | + QObject *parent) |
768 | + : KeeperTask(*new KeeperTaskRestorePrivate(this, task_data, helper_registry, storage), parent) |
769 | +{ |
770 | +} |
771 | + |
772 | +KeeperTaskRestore::~KeeperTaskRestore() = default; |
773 | + |
774 | +QStringList KeeperTaskRestore::get_helper_urls() const |
775 | +{ |
776 | + Q_D(const KeeperTaskRestore); |
777 | + |
778 | + return d->get_helper_urls(); |
779 | +} |
780 | + |
781 | +void KeeperTaskRestore::init_helper() |
782 | +{ |
783 | + Q_D(KeeperTaskRestore); |
784 | + |
785 | + d->init_helper(); |
786 | +} |
787 | + |
788 | +void KeeperTaskRestore::ask_for_downloader() |
789 | +{ |
790 | + Q_D(KeeperTaskRestore); |
791 | + |
792 | + d->ask_for_downloader(); |
793 | +} |
794 | |
795 | === added file 'src/service/keeper-task-restore.h' |
796 | --- src/service/keeper-task-restore.h 1970-01-01 00:00:00 +0000 |
797 | +++ src/service/keeper-task-restore.h 2016-11-24 14:48:54 +0000 |
798 | @@ -0,0 +1,46 @@ |
799 | +/* |
800 | + * Copyright (C) 2016 Canonical, Ltd. |
801 | + * |
802 | + * This program is free software: you can redistribute it and/or modify it |
803 | + * under the terms of the GNU General Public License version 3, as published |
804 | + * by the Free Software Foundation. |
805 | + * |
806 | + * This program is distributed in the hope that it will be useful, but |
807 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
808 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
809 | + * PURPOSE. See the GNU General Public License for more details. |
810 | + * |
811 | + * You should have received a copy of the GNU General Public License along |
812 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
813 | + * |
814 | + * Authors: |
815 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
816 | + * Charles Kerr <charles.kerr@canonical.com> |
817 | + */ |
818 | +#pragma once |
819 | + |
820 | +#include "keeper-task.h" |
821 | + |
822 | +class KeeperTaskRestorePrivate; |
823 | + |
824 | +class KeeperTaskRestore : public KeeperTask |
825 | +{ |
826 | + Q_OBJECT |
827 | + Q_DECLARE_PRIVATE(KeeperTaskRestore) |
828 | +public: |
829 | + |
830 | + KeeperTaskRestore(TaskData & task_data, |
831 | + QSharedPointer<HelperRegistry> const & helper_registry, |
832 | + QSharedPointer<StorageFrameworkClient> const & storage, |
833 | + QObject *parent = nullptr); |
834 | + virtual ~KeeperTaskRestore(); |
835 | + |
836 | + Q_DISABLE_COPY(KeeperTaskRestore) |
837 | + |
838 | + void ask_for_downloader(); |
839 | + |
840 | +protected: |
841 | + QStringList get_helper_urls() const override; |
842 | + void init_helper() override; |
843 | + |
844 | +}; |
845 | |
846 | === modified file 'src/service/keeper-user.cpp' |
847 | --- src/service/keeper-user.cpp 2016-10-28 15:11:21 +0000 |
848 | +++ src/service/keeper-user.cpp 2016-11-24 14:48:54 +0000 |
849 | @@ -70,9 +70,15 @@ |
850 | void |
851 | KeeperUser::StartRestore (const QStringList& keys) |
852 | { |
853 | - // FIXME: writeme |
854 | + Q_ASSERT(calledFromDBus()); |
855 | |
856 | - qDebug() << keys; |
857 | + auto bus = connection(); |
858 | + auto& msg = message(); |
859 | + // if we start a restore right after a backup the uuid |
860 | + // will be found as a backup uuid. |
861 | + // Just clear the backup cache to avoid that. |
862 | + keeper_.invalidate_choices_cache(); |
863 | + keeper_.start_tasks(keys, bus, msg); |
864 | } |
865 | |
866 | QVariantDictMap |
867 | |
868 | === modified file 'src/service/keeper.cpp' |
869 | --- src/service/keeper.cpp 2016-11-24 14:48:54 +0000 |
870 | +++ src/service/keeper.cpp 2016-11-24 14:48:54 +0000 |
871 | @@ -32,6 +32,7 @@ |
872 | #include <QVector> |
873 | |
874 | #include <algorithm> // std::find_if |
875 | +#include <unistd.h> |
876 | |
877 | namespace |
878 | { |
879 | @@ -83,8 +84,8 @@ |
880 | Q_DISABLE_COPY(KeeperPrivate) |
881 | |
882 | void start_tasks(QStringList const & uuids, |
883 | - QDBusConnection bus, |
884 | - QDBusMessage const & msg) |
885 | + QDBusConnection bus, |
886 | + QDBusMessage const & msg) |
887 | { |
888 | auto get_tasks = [](const QVector<Metadata>& pool, QStringList const& keys){ |
889 | QMap<QString,Metadata> tasks; |
890 | @@ -97,9 +98,10 @@ |
891 | }; |
892 | |
893 | // async part |
894 | + qDebug() << "Looking for backup options...."; |
895 | connections_.connect_oneshot( |
896 | this, |
897 | - &KeeperPrivate::choices_ready, |
898 | + &KeeperPrivate::backup_choices_ready, |
899 | std::function<void()>{[this, uuids, msg, bus, get_tasks](){ |
900 | auto tasks = get_tasks(cached_backup_choices_, uuids); |
901 | if (!tasks.empty()) |
902 | @@ -116,12 +118,15 @@ |
903 | } |
904 | else // restore |
905 | { |
906 | + qDebug() << "Looking for restore options...."; |
907 | connections_.connect_oneshot( |
908 | this, |
909 | - &KeeperPrivate::choices_ready, |
910 | + &KeeperPrivate::restore_choices_ready, |
911 | std::function<void()>{[this, uuids, msg, bus, get_tasks](){ |
912 | + qDebug() << "Choices ready"; |
913 | auto unhandled = QSet<QString>::fromList(uuids); |
914 | auto restore_tasks = get_tasks(cached_restore_choices_, uuids); |
915 | + qDebug() << "After getting tasks..."; |
916 | if (!restore_tasks.empty() && task_manager_.start_restore(restore_tasks.values())) |
917 | unhandled.subtract(QSet<QString>::fromList(restore_tasks.keys())); |
918 | |
919 | @@ -141,6 +146,18 @@ |
920 | msg.setDelayedReply(true); |
921 | } |
922 | |
923 | + void emit_choices_ready(ChoicesType type) |
924 | + { |
925 | + switch(type) |
926 | + { |
927 | + case KeeperPrivate::ChoicesType::BACKUP_CHOICES: |
928 | + Q_EMIT(backup_choices_ready()); |
929 | + break; |
930 | + case KeeperPrivate::ChoicesType::RESTORES_CHOICES: |
931 | + Q_EMIT(restore_choices_ready()); |
932 | + break; |
933 | + } |
934 | + } |
935 | void get_choices(const QSharedPointer<MetadataProvider> & provider, ChoicesType type) |
936 | { |
937 | bool check_empty = (type == KeeperPrivate::ChoicesType::BACKUP_CHOICES) |
938 | @@ -161,7 +178,7 @@ |
939 | cached_restore_choices_ = provider->get_backups(); |
940 | break; |
941 | }; |
942 | - Q_EMIT(choices_ready()); |
943 | + emit_choices_ready(type); |
944 | }} |
945 | ); |
946 | |
947 | @@ -169,7 +186,7 @@ |
948 | } |
949 | else |
950 | { |
951 | - Q_EMIT(choices_ready()); |
952 | + emit_choices_ready(type); |
953 | } |
954 | } |
955 | |
956 | @@ -178,7 +195,7 @@ |
957 | { |
958 | connections_.connect_oneshot( |
959 | this, |
960 | - &KeeperPrivate::choices_ready, |
961 | + &KeeperPrivate::backup_choices_ready, |
962 | std::function<void()>{[this, msg, bus](){ |
963 | qDebug() << "Backup choices are ready"; |
964 | // reply now to the dbus call |
965 | @@ -198,7 +215,7 @@ |
966 | { |
967 | connections_.connect_oneshot( |
968 | this, |
969 | - &KeeperPrivate::choices_ready, |
970 | + &KeeperPrivate::restore_choices_ready, |
971 | std::function<void()>{[this, msg, bus](){ |
972 | qDebug() << "Restore choices are ready"; |
973 | // reply now to the dbus call |
974 | @@ -213,29 +230,6 @@ |
975 | return QVariantDictMap(); |
976 | } |
977 | |
978 | - // TODO REFACTOR THIS TO USE THE SAME METHOD POR RESTORES AND BACKUPS |
979 | - void get_restore_choices() |
980 | - { |
981 | - if (cached_restore_choices_.isEmpty()) |
982 | - { |
983 | - connections_.connect_oneshot( |
984 | - restore_choices_.data(), |
985 | - &MetadataProvider::finished, |
986 | - std::function<void()>{[this](){ |
987 | - qDebug() << "Get restores finished"; |
988 | - cached_restore_choices_ = restore_choices_->get_backups(); |
989 | - Q_EMIT(choices_ready()); |
990 | - }} |
991 | - ); |
992 | - |
993 | - restore_choices_->get_backups_async(); |
994 | - } |
995 | - else |
996 | - { |
997 | - Q_EMIT(choices_ready()); |
998 | - } |
999 | - } |
1000 | - |
1001 | QVariantDictMap get_state() const |
1002 | { |
1003 | return task_manager_.get_state(); |
1004 | @@ -260,7 +254,7 @@ |
1005 | } |
1006 | ); |
1007 | |
1008 | - qDebug() << "Asking for an storage framework socket to the task manager"; |
1009 | + qDebug() << "Asking for a storage framework socket from the task manager"; |
1010 | task_manager_.ask_for_uploader(n_bytes); |
1011 | |
1012 | // tell the caller that we'll be responding async |
1013 | @@ -268,12 +262,47 @@ |
1014 | return QDBusUnixFileDescriptor(0); |
1015 | } |
1016 | |
1017 | + |
1018 | + QDBusUnixFileDescriptor start_restore(QDBusConnection bus, |
1019 | + QDBusMessage const & msg) |
1020 | + { |
1021 | + qDebug() << "Keeper::StartRestore()"; |
1022 | + |
1023 | + connections_.connect_oneshot( |
1024 | + &task_manager_, |
1025 | + &TaskManager::socket_ready, |
1026 | + std::function<void(int)>{ |
1027 | + [bus,msg](int fd){ |
1028 | + qDebug("RestoreManager returned socket %d", fd); |
1029 | + auto reply = msg.createReply(); |
1030 | + reply << QVariant::fromValue(QDBusUnixFileDescriptor(fd)); |
1031 | + close(fd); |
1032 | + bus.send(reply); |
1033 | + } |
1034 | + } |
1035 | + ); |
1036 | + |
1037 | + qDebug() << "Asking for a storage framework socket from the task manager"; |
1038 | + task_manager_.ask_for_downloader(); |
1039 | + |
1040 | + // tell the caller that we'll be responding async |
1041 | + msg.setDelayedReply(true); |
1042 | + return QDBusUnixFileDescriptor(0); |
1043 | + } |
1044 | + |
1045 | void cancel() |
1046 | { |
1047 | task_manager_.cancel(); |
1048 | } |
1049 | + |
1050 | + void invalidate_choices_cache() |
1051 | + { |
1052 | + cached_backup_choices_.clear(); |
1053 | + } |
1054 | + |
1055 | Q_SIGNALS: |
1056 | - void choices_ready(); |
1057 | + void backup_choices_ready(); |
1058 | + void restore_choices_ready(); |
1059 | |
1060 | private: |
1061 | |
1062 | @@ -334,6 +363,15 @@ |
1063 | return d->start_backup(bus, msg, n_bytes); |
1064 | } |
1065 | |
1066 | +QDBusUnixFileDescriptor |
1067 | +Keeper::StartRestore(QDBusConnection bus, |
1068 | + QDBusMessage const & msg) |
1069 | +{ |
1070 | + Q_D(Keeper); |
1071 | + |
1072 | + return d->start_restore(bus, msg); |
1073 | +} |
1074 | + |
1075 | QVariantDictMap |
1076 | Keeper::get_backup_choices_var_dict_map(QDBusConnection bus, |
1077 | QDBusMessage const & msg) |
1078 | @@ -368,4 +406,12 @@ |
1079 | return d->cancel(); |
1080 | } |
1081 | |
1082 | +void |
1083 | +Keeper::invalidate_choices_cache() |
1084 | +{ |
1085 | + Q_D(Keeper); |
1086 | + |
1087 | + d->invalidate_choices_cache(); |
1088 | +} |
1089 | + |
1090 | #include "keeper.moc" |
1091 | |
1092 | === modified file 'src/service/keeper.h' |
1093 | --- src/service/keeper.h 2016-10-28 15:11:21 +0000 |
1094 | +++ src/service/keeper.h 2016-11-24 14:48:54 +0000 |
1095 | @@ -59,6 +59,10 @@ |
1096 | QDBusMessage const & message, |
1097 | quint64 nbytes); |
1098 | |
1099 | + |
1100 | + QDBusUnixFileDescriptor StartRestore(QDBusConnection, |
1101 | + QDBusMessage const & message); |
1102 | + |
1103 | void start_tasks(QStringList const & uuids, |
1104 | QDBusConnection bus, |
1105 | QDBusMessage const & msg); |
1106 | @@ -67,6 +71,8 @@ |
1107 | |
1108 | void cancel(); |
1109 | |
1110 | + void invalidate_choices_cache(); |
1111 | + |
1112 | private: |
1113 | QScopedPointer<KeeperPrivate> const d_ptr; |
1114 | }; |
1115 | |
1116 | === modified file 'src/service/manifest.cpp' |
1117 | --- src/service/manifest.cpp 2016-10-13 12:22:31 +0000 |
1118 | +++ src/service/manifest.cpp 2016-11-24 14:48:54 +0000 |
1119 | @@ -110,8 +110,8 @@ |
1120 | { |
1121 | connections_.connect_future( |
1122 | storage_->get_new_downloader(dir_, MANIFEST_FILE_NAME), |
1123 | - std::function<void(sf::Downloader::SPtr const&)>{ |
1124 | - [this](sf::Downloader::SPtr const& downloader){ |
1125 | + std::function<void(std::shared_ptr<Downloader> const&)>{ |
1126 | + [this](std::shared_ptr<Downloader> const& downloader){ |
1127 | qDebug() << "Manifest downloader is" << static_cast<void*>(downloader.get()); |
1128 | if (downloader) |
1129 | { |
1130 | @@ -125,7 +125,7 @@ |
1131 | } |
1132 | auto json_content = socket->readAll(); |
1133 | from_json(json_content); |
1134 | - downloader->finish_download(); |
1135 | + downloader->finish(); |
1136 | finish(); |
1137 | } |
1138 | else |
1139 | |
1140 | === modified file 'src/service/task-manager.cpp' |
1141 | --- src/service/task-manager.cpp 2016-11-24 14:48:54 +0000 |
1142 | +++ src/service/task-manager.cpp 2016-11-24 14:48:54 +0000 |
1143 | @@ -20,6 +20,7 @@ |
1144 | |
1145 | #include "helper/metadata.h" |
1146 | #include "keeper-task-backup.h" |
1147 | +#include "keeper-task-restore.h" |
1148 | #include "manifest.h" |
1149 | #include "storage-framework/storage_framework_client.h" |
1150 | #include "task-manager.h" |
1151 | @@ -50,6 +51,7 @@ |
1152 | |
1153 | bool start_restore(QList<Metadata> const& tasks) |
1154 | { |
1155 | + qDebug() << "Starting restore..."; |
1156 | return start_tasks(tasks, Mode::RESTORE); |
1157 | } |
1158 | |
1159 | @@ -78,6 +80,22 @@ |
1160 | } |
1161 | } |
1162 | |
1163 | + void ask_for_downloader() |
1164 | + { |
1165 | + qDebug() << "Starting restore"; |
1166 | + if (task_) |
1167 | + { |
1168 | + auto restore_task_ = qSharedPointerDynamicCast<KeeperTaskRestore>(task_); |
1169 | + if (!restore_task_) |
1170 | + { |
1171 | + qWarning() << "Only restore tasks are allowed to ask for storage framework downloaders"; |
1172 | + // TODO Mark this as an error at the current task and move to the next task |
1173 | + return; |
1174 | + } |
1175 | + restore_task_->ask_for_downloader(); |
1176 | + } |
1177 | + } |
1178 | + |
1179 | void cancel() |
1180 | { |
1181 | if (task_) |
1182 | @@ -158,7 +176,6 @@ |
1183 | |
1184 | void on_helper_state_changed(Helper::State state) |
1185 | { |
1186 | - qDebug() << "Task State changed"; |
1187 | auto backup_task_ = qSharedPointerDynamicCast<KeeperTaskBackup>(task_); |
1188 | auto& td = task_data_[current_task_]; |
1189 | update_task_state(td); |
1190 | @@ -174,6 +191,7 @@ |
1191 | { |
1192 | qDebug() << "Backup task finished. The file created in storage framework is: [" << backup_task_->get_file_name() << "]"; |
1193 | td.metadata.set_property(Metadata::FILE_NAME_KEY, backup_task_->get_file_name()); |
1194 | + td.metadata.set_property(Metadata::DIR_NAME_KEY, backup_dir_name_); |
1195 | active_manifest_->add_entry(td.metadata); |
1196 | } |
1197 | if (remaining_tasks_.size()) |
1198 | @@ -217,14 +235,16 @@ |
1199 | qDebug() << "Creating task for uuid = " << uuid; |
1200 | // initialize a new task |
1201 | |
1202 | - task_.data()->disconnect(); |
1203 | + if (task_) |
1204 | + task_.data()->disconnect(); |
1205 | + |
1206 | if (mode_ == Mode::BACKUP) |
1207 | { |
1208 | task_.reset(new KeeperTaskBackup(td, helper_registry_, storage_)); |
1209 | } |
1210 | else |
1211 | { |
1212 | - // TODO initialize a Restore task |
1213 | + task_.reset(new KeeperTaskRestore(td, helper_registry_, storage_)); |
1214 | } |
1215 | |
1216 | qDebug() << "task created: " << state_; |
1217 | @@ -396,6 +416,13 @@ |
1218 | d->ask_for_uploader(n_bytes); |
1219 | } |
1220 | |
1221 | +void TaskManager::ask_for_downloader() |
1222 | +{ |
1223 | + Q_D(TaskManager); |
1224 | + |
1225 | + d->ask_for_downloader(); |
1226 | +} |
1227 | + |
1228 | void TaskManager::cancel() |
1229 | { |
1230 | Q_D(TaskManager); |
1231 | |
1232 | === modified file 'src/service/task-manager.h' |
1233 | --- src/service/task-manager.h 2016-09-28 13:42:21 +0000 |
1234 | +++ src/service/task-manager.h 2016-11-24 14:48:54 +0000 |
1235 | @@ -58,6 +58,8 @@ |
1236 | |
1237 | void ask_for_uploader(quint64 n_bytes); |
1238 | |
1239 | + void ask_for_downloader(); |
1240 | + |
1241 | void cancel(); |
1242 | |
1243 | Q_SIGNALS: |
1244 | |
1245 | === modified file 'src/storage-framework/CMakeLists.txt' |
1246 | --- src/storage-framework/CMakeLists.txt 2016-09-05 17:24:18 +0000 |
1247 | +++ src/storage-framework/CMakeLists.txt 2016-11-24 14:48:54 +0000 |
1248 | @@ -11,6 +11,9 @@ |
1249 | uploader.h |
1250 | sf-uploader.cpp |
1251 | sf-uploader.h |
1252 | + downloader.h |
1253 | + sf-downloader.cpp |
1254 | + sf-downloader.h |
1255 | ) |
1256 | |
1257 | set_target_properties( |
1258 | |
1259 | === added file 'src/storage-framework/downloader.h' |
1260 | --- src/storage-framework/downloader.h 1970-01-01 00:00:00 +0000 |
1261 | +++ src/storage-framework/downloader.h 2016-11-24 14:48:54 +0000 |
1262 | @@ -0,0 +1,46 @@ |
1263 | +/* |
1264 | + * Copyright (C) 2016 Canonical, Ltd. |
1265 | + * |
1266 | + * This program is free software: you can redistribute it and/or modify it |
1267 | + * under the terms of the GNU General Public License version 3, as published |
1268 | + * by the Free Software Foundation. |
1269 | + * |
1270 | + * This program is distributed in the hope that it will be useful, but |
1271 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1272 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1273 | + * PURPOSE. See the GNU General Public License for more details. |
1274 | + * |
1275 | + * You should have received a copy of the GNU General Public License along |
1276 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1277 | + * |
1278 | + * Authors: |
1279 | + * Charles Kerr <charles.kerr@canonical.com> |
1280 | + * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> |
1281 | + */ |
1282 | + |
1283 | +#pragma once |
1284 | + |
1285 | +#include <QLocalSocket> |
1286 | +#include <QObject> |
1287 | + |
1288 | +#include <memory> |
1289 | + |
1290 | +class Downloader: public QObject |
1291 | +{ |
1292 | + Q_OBJECT |
1293 | + |
1294 | +public: |
1295 | + |
1296 | + Q_DISABLE_COPY(Downloader) |
1297 | + |
1298 | + Downloader(QObject *parent=nullptr): QObject(parent) {} |
1299 | + virtual ~Downloader() =default; |
1300 | + |
1301 | + virtual std::shared_ptr<QLocalSocket> socket() =0; |
1302 | + virtual void finish() =0; |
1303 | + virtual qint64 file_size() const =0; |
1304 | + |
1305 | +Q_SIGNALS: |
1306 | + |
1307 | + void download_finished(); |
1308 | +}; |
1309 | |
1310 | === added file 'src/storage-framework/sf-downloader.cpp' |
1311 | --- src/storage-framework/sf-downloader.cpp 1970-01-01 00:00:00 +0000 |
1312 | +++ src/storage-framework/sf-downloader.cpp 2016-11-24 14:48:54 +0000 |
1313 | @@ -0,0 +1,56 @@ |
1314 | +/* |
1315 | + * Copyright (C) 2016 Canonical, Ltd. |
1316 | + * |
1317 | + * This program is free software: you can redistribute it and/or modify it |
1318 | + * under the terms of the GNU General Public License version 3, as published |
1319 | + * by the Free Software Foundation. |
1320 | + * |
1321 | + * This program is distributed in the hope that it will be useful, but |
1322 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1323 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1324 | + * PURPOSE. See the GNU General Public License for more details. |
1325 | + * |
1326 | + * You should have received a copy of the GNU General Public License along |
1327 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1328 | + * |
1329 | + * Authors: |
1330 | + * Charles Kerr <charles.kerr@canonical.com> |
1331 | + * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> |
1332 | + */ |
1333 | + |
1334 | +#include "storage-framework/sf-downloader.h" |
1335 | + |
1336 | +#include <QFuture> |
1337 | +#include <QFutureWatcher> |
1338 | + |
1339 | +StorageFrameworkDownloader::StorageFrameworkDownloader( |
1340 | + unity::storage::qt::client::Downloader::SPtr const& downloader, |
1341 | + qint64 file_size, |
1342 | + QObject *parent |
1343 | +): |
1344 | + Downloader{parent}, |
1345 | + downloader_{downloader}, |
1346 | + file_size_{file_size} |
1347 | +{ |
1348 | + qDebug() << "StorageFrameworkDownloader"; |
1349 | +} |
1350 | + |
1351 | +std::shared_ptr<QLocalSocket> |
1352 | +StorageFrameworkDownloader::socket() |
1353 | +{ |
1354 | + return downloader_->socket(); |
1355 | +} |
1356 | + |
1357 | +void |
1358 | +StorageFrameworkDownloader::finish() |
1359 | +{ |
1360 | + qDebug() << Q_FUNC_INFO << "is finishing"; |
1361 | + downloader_->finish_download(); |
1362 | + Q_EMIT(download_finished()); // TODO add the code to call finish_download |
1363 | +} |
1364 | + |
1365 | +qint64 |
1366 | +StorageFrameworkDownloader::file_size() const |
1367 | +{ |
1368 | + return file_size_; |
1369 | +} |
1370 | |
1371 | === added file 'src/storage-framework/sf-downloader.h' |
1372 | --- src/storage-framework/sf-downloader.h 1970-01-01 00:00:00 +0000 |
1373 | +++ src/storage-framework/sf-downloader.h 2016-11-24 14:48:54 +0000 |
1374 | @@ -0,0 +1,48 @@ |
1375 | +/* |
1376 | + * Copyright (C) 2016 Canonical, Ltd. |
1377 | + * |
1378 | + * This program is free software: you can redistribute it and/or modify it |
1379 | + * under the terms of the GNU General Public License version 3, as published |
1380 | + * by the Free Software Foundation. |
1381 | + * |
1382 | + * This program is distributed in the hope that it will be useful, but |
1383 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1384 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1385 | + * PURPOSE. See the GNU General Public License for more details. |
1386 | + * |
1387 | + * You should have received a copy of the GNU General Public License along |
1388 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1389 | + * |
1390 | + * Authors: |
1391 | + * Charles Kerr <charles.kerr@canonical.com> |
1392 | + */ |
1393 | + |
1394 | +#pragma once |
1395 | + |
1396 | +#include "util/connection-helper.h" |
1397 | +#include "storage-framework/downloader.h" |
1398 | + |
1399 | +#include <unity/storage/qt/client/client-api.h> |
1400 | + |
1401 | +#include <QLocalSocket> |
1402 | + |
1403 | +#include <memory> |
1404 | + |
1405 | +class StorageFrameworkDownloader final: public Downloader |
1406 | +{ |
1407 | +public: |
1408 | + |
1409 | + StorageFrameworkDownloader(unity::storage::qt::client::Downloader::SPtr const& uploader, |
1410 | + qint64 file_size, |
1411 | + QObject * parent = nullptr); |
1412 | + std::shared_ptr<QLocalSocket> socket() override; |
1413 | + void finish() override; |
1414 | + qint64 file_size() const override; |
1415 | + |
1416 | +private: |
1417 | + |
1418 | + unity::storage::qt::client::Downloader::SPtr const downloader_; |
1419 | + qint64 file_size_; |
1420 | + |
1421 | + ConnectionHelper connections_; |
1422 | +}; |
1423 | |
1424 | === modified file 'src/storage-framework/storage_framework_client.cpp' |
1425 | --- src/storage-framework/storage_framework_client.cpp 2016-11-03 10:32:49 +0000 |
1426 | +++ src/storage-framework/storage_framework_client.cpp 2016-11-24 14:48:54 +0000 |
1427 | @@ -19,6 +19,7 @@ |
1428 | */ |
1429 | |
1430 | #include "storage-framework/storage_framework_client.h" |
1431 | +#include "storage-framework/sf-downloader.h" |
1432 | #include "storage-framework/sf-uploader.h" |
1433 | |
1434 | #include <QDateTime> |
1435 | @@ -39,7 +40,7 @@ |
1436 | { |
1437 | } |
1438 | |
1439 | -StorageFrameworkClient::~StorageFrameworkClient() =default; |
1440 | +StorageFrameworkClient::~StorageFrameworkClient() = default; |
1441 | |
1442 | /*** |
1443 | **** |
1444 | @@ -115,8 +116,8 @@ |
1445 | connection_helper_.connect_future( |
1446 | get_keeper_folder(root, dir_name, true), |
1447 | std::function<void(sf::Folder::SPtr const&)>{ |
1448 | - [this, fi, n_bytes, file_name](sf::Folder::SPtr const& keeper_root){ |
1449 | - if (!keeper_root) |
1450 | + [this, fi, n_bytes, file_name,root](sf::Folder::SPtr const& keeper_folder){ |
1451 | + if (!keeper_folder) |
1452 | { |
1453 | qWarning() << "Error creating keeper root folder"; |
1454 | std::shared_ptr<Uploader> ret; |
1455 | @@ -127,9 +128,9 @@ |
1456 | else |
1457 | { |
1458 | connection_helper_.connect_future( |
1459 | - keeper_root->create_file(file_name, n_bytes), |
1460 | + keeper_folder->create_file(file_name, n_bytes), |
1461 | std::function<void(std::shared_ptr<sf::Uploader> const&)>{ |
1462 | - [this, fi](std::shared_ptr<sf::Uploader> const& sf_uploader){ |
1463 | + [this, fi, keeper_folder](std::shared_ptr<sf::Uploader> const& sf_uploader){ |
1464 | qDebug() << "keeper_root->create_file() finished"; |
1465 | std::shared_ptr<Uploader> ret; |
1466 | if (sf_uploader) { |
1467 | @@ -154,10 +155,10 @@ |
1468 | return fi.future(); |
1469 | } |
1470 | |
1471 | -QFuture<sf::Downloader::SPtr> |
1472 | +QFuture<std::shared_ptr<Downloader>> |
1473 | StorageFrameworkClient::get_new_downloader(QString const & dir_name, QString const & file_name) |
1474 | { |
1475 | - QFutureInterface<sf::Downloader::SPtr> fi; |
1476 | + QFutureInterface<std::shared_ptr<Downloader>> fi; |
1477 | |
1478 | add_roots_task([this, fi, dir_name, file_name](QVector<sf::Root::SPtr> const& roots) |
1479 | { |
1480 | @@ -171,7 +172,7 @@ |
1481 | if (!keeper_root) |
1482 | { |
1483 | qWarning() << "Error accessing keeper root folder"; |
1484 | - sf::Downloader::SPtr ret; |
1485 | + std::shared_ptr<Downloader> ret; |
1486 | QFutureInterface<decltype(ret)> qfi(fi); |
1487 | qfi.reportResult(ret); |
1488 | qfi.reportFinished(); |
1489 | @@ -183,27 +184,27 @@ |
1490 | get_storage_framework_file(keeper_root, file_name), |
1491 | std::function<void(sf::File::SPtr const&)>{ |
1492 | [this, fi](sf::File::SPtr const& sf_file){ |
1493 | - sf::Downloader::SPtr ret_null; |
1494 | if (sf_file) { |
1495 | connection_helper_.connect_future( |
1496 | sf_file->create_downloader(), |
1497 | std::function<void(sf::Downloader::SPtr const&)>{ |
1498 | - [this, fi, ret_null](sf::Downloader::SPtr const& sf_downloader){ |
1499 | - QFutureInterface<decltype(ret_null)> qfi(fi); |
1500 | + [this, fi, sf_file](sf::Downloader::SPtr const& sf_downloader){ |
1501 | + std::shared_ptr<Downloader> ret; |
1502 | if (sf_downloader) |
1503 | { |
1504 | - qfi.reportResult(sf_downloader); |
1505 | - qfi.reportFinished(); |
1506 | - } |
1507 | - else |
1508 | - { |
1509 | - qfi.reportResult(ret_null); |
1510 | - qfi.reportFinished(); |
1511 | - } |
1512 | + ret.reset( |
1513 | + new StorageFrameworkDownloader(sf_downloader, sf_file->size(), this), |
1514 | + [](Downloader* d){d->deleteLater();} |
1515 | + ); |
1516 | + } |
1517 | + QFutureInterface<decltype(ret)> qfi(fi); |
1518 | + qfi.reportResult(ret); |
1519 | + qfi.reportFinished(); |
1520 | } |
1521 | } |
1522 | ); |
1523 | } else { |
1524 | + std::shared_ptr<Downloader> ret_null; |
1525 | QFutureInterface<decltype(ret_null)> qfi(fi); |
1526 | qfi.reportResult(ret_null); |
1527 | qfi.reportFinished(); |
1528 | @@ -341,7 +342,7 @@ |
1529 | connection_helper_.connect_future( |
1530 | root->create_folder(dir_name), |
1531 | std::function<void(sf::Folder::SPtr const &)>{ |
1532 | - [this, fi, res](sf::Folder::SPtr const & folder){ |
1533 | + [this, fi, res, root](sf::Folder::SPtr const & folder){ |
1534 | QFutureInterface<decltype(res)> qfi(fi); |
1535 | qfi.reportResult(folder); |
1536 | qfi.reportFinished(); |
1537 | |
1538 | === modified file 'src/storage-framework/storage_framework_client.h' |
1539 | --- src/storage-framework/storage_framework_client.h 2016-11-03 10:32:49 +0000 |
1540 | +++ src/storage-framework/storage_framework_client.h 2016-11-24 14:48:54 +0000 |
1541 | @@ -22,6 +22,7 @@ |
1542 | |
1543 | #include "util/connection-helper.h" |
1544 | #include "storage-framework/uploader.h" |
1545 | +#include "storage-framework/downloader.h" |
1546 | |
1547 | #include <unity/storage/qt/client/client-api.h> |
1548 | |
1549 | @@ -43,7 +44,7 @@ |
1550 | virtual ~StorageFrameworkClient(); |
1551 | |
1552 | QFuture<std::shared_ptr<Uploader>> get_new_uploader(int64_t n_bytes, QString const & dir_name, QString const & file_name); |
1553 | - QFuture<unity::storage::qt::client::Downloader::SPtr> get_new_downloader(QString const & dir_name, QString const & file_name); |
1554 | + QFuture<std::shared_ptr<Downloader>> get_new_downloader(QString const & dir_name, QString const & file_name); |
1555 | QFuture<QVector<QString>> get_keeper_dirs(); |
1556 | |
1557 | static QString const KEEPER_FOLDER; |
1558 | |
1559 | === modified file 'tests/CMakeLists.txt' |
1560 | --- tests/CMakeLists.txt 2016-09-05 13:54:15 +0000 |
1561 | +++ tests/CMakeLists.txt 2016-11-24 14:48:54 +0000 |
1562 | @@ -20,6 +20,11 @@ |
1563 | ) |
1564 | |
1565 | set( |
1566 | + RESTORE_HELPER |
1567 | + fake-restore-helper |
1568 | +) |
1569 | + |
1570 | +set( |
1571 | BACKUP_HELPER_FAILURE |
1572 | fake-backup-helper-failure |
1573 | ) |
1574 | @@ -27,6 +32,7 @@ |
1575 | set(KEEPER_TAR_CREATE_BIN ${CMAKE_BINARY_DIR}/src/tar/keeper-tar-create) |
1576 | set(KEEPER_HELPER_TEST_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/helpers-test.sh) |
1577 | set(BACKUP_HELPER_FAILURE_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/${BACKUP_HELPER_FAILURE}) |
1578 | +set(RESTORE_HELPER_TEST_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/${RESTORE_HELPER}) |
1579 | |
1580 | add_definitions( |
1581 | -DCMAKE_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}" |
1582 | |
1583 | === modified file 'tests/fakes/CMakeLists.txt' |
1584 | --- tests/fakes/CMakeLists.txt 2016-08-30 12:50:46 +0000 |
1585 | +++ tests/fakes/CMakeLists.txt 2016-11-24 14:48:54 +0000 |
1586 | @@ -30,6 +30,15 @@ |
1587 | ) |
1588 | |
1589 | add_executable( |
1590 | + ${RESTORE_HELPER} |
1591 | + fake-restore-helper.cpp |
1592 | +) |
1593 | +target_link_libraries( |
1594 | + ${RESTORE_HELPER} |
1595 | + ${LINK_LIBS} |
1596 | +) |
1597 | + |
1598 | +add_executable( |
1599 | ${BACKUP_HELPER_FAILURE} |
1600 | fake-backup-helper.cpp |
1601 | ) |
1602 | |
1603 | === added file 'tests/fakes/fake-restore-helper.cpp' |
1604 | --- tests/fakes/fake-restore-helper.cpp 1970-01-01 00:00:00 +0000 |
1605 | +++ tests/fakes/fake-restore-helper.cpp 2016-11-24 14:48:54 +0000 |
1606 | @@ -0,0 +1,130 @@ |
1607 | +/* |
1608 | + * Copyright (C) 2016 Canonical, Ltd. |
1609 | + * |
1610 | + * This program is free software: you can redistribute it and/or modify it |
1611 | + * under the terms of the GNU General Public License version 3, as published |
1612 | + * by the Free Software Foundation. |
1613 | + * |
1614 | + * This program is distributed in the hope that it will be useful, but |
1615 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1616 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1617 | + * PURPOSE. See the GNU General Public License for more details. |
1618 | + * |
1619 | + * You should have received a copy of the GNU General Public License along |
1620 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1621 | + * |
1622 | + * Authors: |
1623 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
1624 | + */ |
1625 | + |
1626 | +#include "fake-restore-helper.h" |
1627 | + |
1628 | +#include <qdbus-stubs/dbus-types.h> |
1629 | +#include <qdbus-stubs/keeper_helper_interface.h> |
1630 | + |
1631 | +#include <QCoreApplication> |
1632 | +#include <QDebug> |
1633 | +#include <QDBusConnection> |
1634 | +#include <QDBusInterface> |
1635 | +#include <QDBusReply> |
1636 | +#include <QProcessEnvironment> |
1637 | +#include <QLocalSocket> |
1638 | +#include <QtGlobal> |
1639 | + |
1640 | +#include <unistd.h> |
1641 | +#include <sys/ioctl.h> |
1642 | + |
1643 | +constexpr int UPLOAD_BUFFER_MAX_ = 64 * 1024; |
1644 | + |
1645 | +void myMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & msg) |
1646 | +{ |
1647 | + QString txt; |
1648 | + switch (type) { |
1649 | + case QtDebugMsg: |
1650 | + txt = QString("Debug: %1").arg(msg); |
1651 | + break; |
1652 | + case QtWarningMsg: |
1653 | + txt = QString("Warning: %1").arg(msg); |
1654 | + break; |
1655 | + case QtCriticalMsg: |
1656 | + txt = QString("Critical: %1").arg(msg); |
1657 | + break; |
1658 | + case QtFatalMsg: |
1659 | + txt = QString("Fatal: %1").arg(msg); |
1660 | + abort(); |
1661 | + } |
1662 | + QFile outFile(TEST_RESTORE_LOG_FILE_PATH); |
1663 | + outFile.open(QIODevice::WriteOnly); |
1664 | + QTextStream ts(&outFile); |
1665 | + ts << txt << endl; |
1666 | +} |
1667 | + |
1668 | +int |
1669 | +main(int argc, char **argv) |
1670 | +{ |
1671 | + QCoreApplication app(argc, argv); |
1672 | + qInstallMessageHandler(myMessageHandler); |
1673 | + |
1674 | + // dump the inputs to stdout |
1675 | + qDebug() << "argc:" << argc; |
1676 | + for(int i=0; i<argc; ++i) |
1677 | + qDebug() << "argv[" << i << "] is" << argv[i]; |
1678 | + const auto env = QProcessEnvironment::systemEnvironment(); |
1679 | + for(const auto& key : env.keys()) |
1680 | + qDebug() << "env" << qPrintable(key) << "is" << qPrintable(env.value(key)); |
1681 | + |
1682 | + qDebug() << "Retrieving connection"; |
1683 | + |
1684 | + // ask the service for a socket |
1685 | + auto conn = QDBusConnection::connectToBus(QDBusConnection::SessionBus, DBusTypes::KEEPER_SERVICE); |
1686 | + const auto object_path = QString::fromUtf8(DBusTypes::KEEPER_HELPER_PATH); |
1687 | + QSharedPointer<DBusInterfaceKeeperHelper> helper_iface (new DBusInterfaceKeeperHelper(DBusTypes::KEEPER_SERVICE, object_path, conn)); |
1688 | + |
1689 | + qDebug() << "Is valid:" << helper_iface->isValid(); |
1690 | + |
1691 | + auto fd_reply = helper_iface->StartRestore(); |
1692 | + fd_reply.waitForFinished(); |
1693 | + if (fd_reply.isError()) |
1694 | + { |
1695 | + qFatal("Call to '%s.StartRestore() at '%s' call failed: %s", |
1696 | + DBusTypes::KEEPER_SERVICE, |
1697 | + qPrintable(object_path), |
1698 | + qPrintable(fd_reply.error().message()) |
1699 | + ); |
1700 | + } |
1701 | + const auto ufd = fd_reply.value(); |
1702 | + const auto fd = ufd.fileDescriptor(); |
1703 | + qDebug() << "The file descriptor obtained is: " << fd; |
1704 | + |
1705 | + char buffer[UPLOAD_BUFFER_MAX_]; |
1706 | + int n_bytes_read = 0; |
1707 | + QFile file(TEST_RESTORE_FILE_PATH); |
1708 | + file.open(QIODevice::WriteOnly); |
1709 | + for(;;) |
1710 | + { |
1711 | + // Read data into buffer. We may not have enough to fill up buffer, so we |
1712 | + // store how many bytes were actually read in bytes_read. |
1713 | + int bytes_read = read(fd, buffer, sizeof(buffer)); |
1714 | + if (bytes_read == 0) // We're done reading from the file |
1715 | + { |
1716 | + qDebug() << "Returned 0 bytes read"; |
1717 | + QCoreApplication::exit(0); |
1718 | + break; |
1719 | + } |
1720 | + |
1721 | + else if (bytes_read < 0) |
1722 | + { |
1723 | + if (errno != EAGAIN) |
1724 | + qWarning() << "Error reading from the socket: " << strerror(errno); |
1725 | + } |
1726 | + else |
1727 | + { |
1728 | + n_bytes_read += bytes_read; |
1729 | + qDebug() << "Read: " << bytes_read << " Total: " << n_bytes_read; |
1730 | + file.write(buffer, bytes_read); |
1731 | + file.flush(); |
1732 | + } |
1733 | + } |
1734 | + file.close(); |
1735 | + return 0; |
1736 | +} |
1737 | |
1738 | === added file 'tests/fakes/fake-restore-helper.h' |
1739 | --- tests/fakes/fake-restore-helper.h 1970-01-01 00:00:00 +0000 |
1740 | +++ tests/fakes/fake-restore-helper.h 2016-11-24 14:48:54 +0000 |
1741 | @@ -0,0 +1,27 @@ |
1742 | +/* |
1743 | + * Copyright (C) 2016 Canonical, Ltd. |
1744 | + * |
1745 | + * This program is free software: you can redistribute it and/or modify it |
1746 | + * under the terms of the GNU General Public License version 3, as published |
1747 | + * by the Free Software Foundation. |
1748 | + * |
1749 | + * This program is distributed in the hope that it will be useful, but |
1750 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1751 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1752 | + * PURPOSE. See the GNU General Public License for more details. |
1753 | + * |
1754 | + * You should have received a copy of the GNU General Public License along |
1755 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1756 | + * |
1757 | + * Authors: |
1758 | + * Charles Kerr <charles.kerr@canonical.com> |
1759 | + */ |
1760 | + |
1761 | +#pragma once |
1762 | + |
1763 | +namespace |
1764 | +{ |
1765 | +static char const TEST_RESTORE_FILE_PATH[] = "/tmp/test-restore-helper"; |
1766 | +static char const TEST_RESTORE_LOG_FILE_PATH[] = "/tmp/restore-helper-output"; |
1767 | + |
1768 | +} |
1769 | |
1770 | === modified file 'tests/integration/helpers/CMakeLists.txt' |
1771 | --- tests/integration/helpers/CMakeLists.txt 2016-10-28 15:11:21 +0000 |
1772 | +++ tests/integration/helpers/CMakeLists.txt 2016-11-24 14:48:54 +0000 |
1773 | @@ -65,6 +65,10 @@ |
1774 | FOLDER_BACKUP_EXEC |
1775 | ${KEEPER_HELPER_TEST_LOCATION} |
1776 | ) |
1777 | +set( |
1778 | + FOLDER_RESTORE_EXEC |
1779 | + ${RESTORE_HELPER_TEST_LOCATION} |
1780 | +) |
1781 | configure_file( |
1782 | ${CMAKE_SOURCE_DIR}/data/${HELPER_REGISTRY_FILENAME}.in |
1783 | ${HELPERS_TEST}-registry.json |
1784 | |
1785 | === modified file 'tests/integration/helpers/helpers-test.cc' |
1786 | --- tests/integration/helpers/helpers-test.cc 2016-11-02 14:01:23 +0000 |
1787 | +++ tests/integration/helpers/helpers-test.cc 2016-11-24 14:48:54 +0000 |
1788 | @@ -20,6 +20,7 @@ |
1789 | */ |
1790 | |
1791 | #include "test-helpers-base.h" |
1792 | +#include "tests/fakes/fake-restore-helper.h" |
1793 | |
1794 | class TestHelpers: public TestHelpersBase |
1795 | { |
1796 | @@ -140,6 +141,39 @@ |
1797 | |
1798 | // finally check that we have a valid manifest file. |
1799 | EXPECT_TRUE(check_manifest_file(backup_items)); |
1800 | + |
1801 | + QDBusPendingReply<QVariantDictMap> restore_choices_reply = user_iface->call("GetRestoreChoices"); |
1802 | + restore_choices_reply.waitForFinished(); |
1803 | + EXPECT_TRUE(restore_choices_reply.isValid()) << qPrintable(choices.error().message()); |
1804 | + |
1805 | + const auto restore_choices = restore_choices_reply.value(); |
1806 | + EXPECT_EQ(2, restore_choices.size()); |
1807 | + |
1808 | + // check that we have the first uuid that we did the backup |
1809 | + const auto iter_restore = restore_choices.find(user_folder_uuid); |
1810 | + EXPECT_NE(iter_restore, restore_choices.end()); |
1811 | + EXPECT_EQ(user_folder_uuid, iter_restore.key()); |
1812 | + |
1813 | + // ask to restore that uuid |
1814 | + QDBusPendingReply<void> restore_reply = user_iface->call("StartRestore", QStringList{iter_restore.key()}); |
1815 | + restore_reply.waitForFinished(); |
1816 | + ASSERT_TRUE(restore_reply.isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message()); |
1817 | + |
1818 | + // waits until all tasks are complete, recording PropertiesChanged signals |
1819 | + // and checks all the recorded values |
1820 | + EXPECT_TRUE(capture_and_check_state_until_all_tasks_complete(spy, {iter_restore.key()}, "complete")); |
1821 | + |
1822 | + // verify that the file that the fake restore helper creates is one of the ones in storage framework |
1823 | + QString storage_framework_file_path; |
1824 | + EXPECT_TRUE(StorageFrameworkLocalUtils::get_storage_frameowork_file_equal_to(TEST_RESTORE_FILE_PATH, storage_framework_file_path)); |
1825 | + |
1826 | + // Finally check that the storage framework file that matched is the right one |
1827 | + // Keeper uses the display name plus .keeper extension for the files it creates |
1828 | + QFileInfo sf_file_info(storage_framework_file_path); |
1829 | + EXPECT_EQ(sf_file_info.fileName(), QStringLiteral("%1.keeper").arg(get_display_name_for_xdg_folder_path(user_dir, choices.value()))); |
1830 | + |
1831 | + auto show_helper_ouput_cmd = QStringLiteral("cat %1").arg(TEST_RESTORE_LOG_FILE_PATH); |
1832 | + system(show_helper_ouput_cmd.toStdString().c_str()); |
1833 | } |
1834 | |
1835 | TEST_F(TestHelpers, StartFullTestCancelling) |
1836 | |
1837 | === modified file 'tests/integration/helpers/test-helpers-base.cpp' |
1838 | --- tests/integration/helpers/test-helpers-base.cpp 2016-11-03 08:58:51 +0000 |
1839 | +++ tests/integration/helpers/test-helpers-base.cpp 2016-11-24 14:48:54 +0000 |
1840 | @@ -179,15 +179,19 @@ |
1841 | { |
1842 | return previous == "saving" || previous == "queued"; |
1843 | } |
1844 | + else if (current == "restoring") |
1845 | + { |
1846 | + return previous == "restoring" || previous == "queued"; |
1847 | + } |
1848 | else if (current == "finishing") |
1849 | { |
1850 | - return previous == "finishing" || previous == "saving"; |
1851 | + return previous == "finishing" || previous == "saving" || previous == "restoring"; |
1852 | } |
1853 | else if (current == "complete") |
1854 | { |
1855 | // we may pass from "saving" to "complete" if we don't have enough time |
1856 | // to emit the "finishing" state change |
1857 | - return previous == "complete" || previous == "finishing" || previous == "saving"; |
1858 | + return previous == "complete" || previous == "finishing" || previous == "saving" || previous == "restoring"; |
1859 | } |
1860 | else if (current == "failed") |
1861 | { |
1862 | @@ -704,7 +708,7 @@ |
1863 | return false; |
1864 | } |
1865 | |
1866 | - QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient); |
1867 | + QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient, [](StorageFrameworkClient* sf){sf->deleteLater();}); |
1868 | Manifest manifest_read(sf_client, dir_name); |
1869 | QSignalSpy spy_read(&manifest_read, &Manifest::finished); |
1870 | |
1871 | @@ -716,6 +720,7 @@ |
1872 | if (!spy_read.count()) |
1873 | { |
1874 | qWarning() << "Failed reading manifest file"; |
1875 | + sf_client.reset(); |
1876 | return false; |
1877 | } |
1878 | |
1879 | |
1880 | === modified file 'tests/unit/manifest/manifest-test.cpp' |
1881 | --- tests/unit/manifest/manifest-test.cpp 2016-10-06 14:53:44 +0000 |
1882 | +++ tests/unit/manifest/manifest-test.cpp 2016-11-24 14:48:54 +0000 |
1883 | @@ -78,7 +78,7 @@ |
1884 | |
1885 | g_setenv("XDG_DATA_HOME", tmp_dir.path().toLatin1().data(), true); |
1886 | |
1887 | - QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient); |
1888 | + QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient, [](StorageFrameworkClient* sf){sf->deleteLater();}); |
1889 | Manifest manifest(sf_client, test_dir); |
1890 | |
1891 | auto objects_to_test = 10; |
1892 | |
1893 | === modified file 'tests/unit/storage-framework/create-uploader-test.cpp' |
1894 | --- tests/unit/storage-framework/create-uploader-test.cpp 2016-11-02 11:31:09 +0000 |
1895 | +++ tests/unit/storage-framework/create-uploader-test.cpp 2016-11-24 14:48:54 +0000 |
1896 | @@ -86,7 +86,7 @@ |
1897 | // create a downloader |
1898 | auto downloader_fut = sf_client.get_new_downloader(test_dir, test_file_name); |
1899 | { |
1900 | - QFutureWatcher<sf::Downloader::SPtr> w; |
1901 | + QFutureWatcher<std::shared_ptr<Downloader>> w; |
1902 | QSignalSpy spy(&w, &decltype(w)::finished); |
1903 | w.setFuture(downloader_fut); |
1904 | assert(spy.wait()); |
1905 | @@ -107,14 +107,13 @@ |
1906 | |
1907 | EXPECT_EQ(downloader_content, test_content); |
1908 | |
1909 | - auto finish_downloader_fut = downloader->finish_download(); |
1910 | + QSignalSpy spy_downloader(downloader.get(), &Downloader::download_finished); |
1911 | + downloader->finish(); |
1912 | + if (!spy_downloader.count()) |
1913 | { |
1914 | - QFutureWatcher<void> w; |
1915 | - QSignalSpy spy(&w, &decltype(w)::finished); |
1916 | - w.setFuture(finish_downloader_fut); |
1917 | - assert(spy.wait()); |
1918 | - ASSERT_EQ(spy.count(), 1); |
1919 | + spy_downloader.wait(); |
1920 | } |
1921 | + EXPECT_EQ(1, spy_downloader.count()); |
1922 | |
1923 | // get another uploader |
1924 | QString test_file_name_2 = QStringLiteral("test_file2"); |
1925 | |
1926 | === modified file 'tests/utils/file-utils.cpp' |
1927 | --- tests/utils/file-utils.cpp 2016-11-02 10:43:30 +0000 |
1928 | +++ tests/utils/file-utils.cpp 2016-11-24 14:48:54 +0000 |
1929 | @@ -199,7 +199,7 @@ |
1930 | return false; |
1931 | } |
1932 | auto checksum1 = calculate_checksum(filePath1, QCryptographicHash::Md5); |
1933 | - auto checksum2 = calculate_checksum(filePath1, QCryptographicHash::Md5); |
1934 | + auto checksum2 = calculate_checksum(filePath2, QCryptographicHash::Md5); |
1935 | if (checksum1 != checksum2) |
1936 | { |
1937 | qWarning() << "Checksum for file:" << filePath1 << "differ"; |
1938 | |
1939 | === modified file 'tests/utils/storage-framework-local.cpp' |
1940 | --- tests/utils/storage-framework-local.cpp 2016-10-28 15:11:21 +0000 |
1941 | +++ tests/utils/storage-framework-local.cpp 2016-11-24 14:48:54 +0000 |
1942 | @@ -170,4 +170,38 @@ |
1943 | : ""; |
1944 | } |
1945 | |
1946 | +bool get_storage_frameowork_file_equal_to(QString const & file_path, QString & path) |
1947 | +{ |
1948 | + auto const backups = get_storage_framework_files(); |
1949 | + for (auto const& backup : backups) |
1950 | + { |
1951 | + auto const backup_filename = backup.absoluteFilePath(); |
1952 | + if (FileUtils::compareFiles(file_path, backup_filename)) |
1953 | + { |
1954 | + path = backup_filename; |
1955 | + return true; |
1956 | + } |
1957 | + } |
1958 | + return false; |
1959 | +} |
1960 | + |
1961 | +bool get_storage_frameowork_file_equal_in_size_to(QString const & file_path, QString & path) |
1962 | +{ |
1963 | + auto const backups = get_storage_framework_files(); |
1964 | + for (auto const& backup : backups) |
1965 | + { |
1966 | + auto const backup_filename = backup.absoluteFilePath(); |
1967 | + QFileInfo info1(backup_filename); |
1968 | + QFileInfo info2(file_path); |
1969 | + qDebug() << "File 1 size = " << info1.size(); |
1970 | + qDebug() << "File 2 size = " << info2.size(); |
1971 | + if (info1.size() == info2.size()) |
1972 | + { |
1973 | + path = backup_filename; |
1974 | + return true; |
1975 | + } |
1976 | + } |
1977 | + return false; |
1978 | +} |
1979 | + |
1980 | } // namespace StorageFrameworkLocalUtils |
1981 | |
1982 | === modified file 'tests/utils/storage-framework-local.h' |
1983 | --- tests/utils/storage-framework-local.h 2016-10-28 15:11:21 +0000 |
1984 | +++ tests/utils/storage-framework-local.h 2016-11-24 14:48:54 +0000 |
1985 | @@ -41,4 +41,8 @@ |
1986 | QFileInfoList get_storage_framework_files(); |
1987 | |
1988 | QString get_storage_framework_dir_name(); |
1989 | + |
1990 | + bool get_storage_frameowork_file_equal_to(QString const & file_path, QString & path); |
1991 | + |
1992 | + bool get_storage_frameowork_file_equal_in_size_to(QString const & file_path, QString & path); |
1993 | } |
FAILED: Continuous integration, rev:121 /jenkins. canonical. com/unity- api-1/job/ lp-keeper- ci/115/ /jenkins. canonical. com/unity- api-1/job/ build/1059/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/1066 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 855/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 855/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 855 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 855/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 855/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 855/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 855/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 855 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 855/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 855 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 855/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 855/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-keeper- ci/115/ rebuild
https:/