Status: | Merged |
---|---|
Approved by: | Charles Kerr |
Approved revision: | 129 |
Merged at revision: | 94 |
Proposed branch: | lp:keeper/devel |
Merge into: | lp:keeper |
Diff against target: |
11619 lines (+7871/-1027) 124 files modified
CMakeLists.txt (+1/-1) data/CMakeLists.txt (+6/-0) data/helper-registry.json.in (+6/-1) debian/changelog (+14/-0) debian/control (+5/-1) debian/keeper.install (+3/-1) include/client/client.h (+18/-4) include/client/keeper-errors.h (+57/-0) include/client/keeper-items.h (+102/-0) include/helper/backup-helper.h (+1/-0) include/helper/data-dir-registry.h (+2/-0) include/helper/helper.h (+3/-1) include/helper/metadata.h (+6/-27) include/helper/registry.h (+1/-0) include/helper/restore-helper.h (+62/-0) src/cli/CMakeLists.txt (+4/-0) src/cli/command-line-client-view.cpp (+194/-0) src/cli/command-line-client-view.h (+60/-0) src/cli/command-line-client.cpp (+250/-0) src/cli/command-line-client.h (+58/-0) src/cli/command-line.cpp (+234/-0) src/cli/command-line.h (+55/-0) src/cli/main.cpp (+40/-46) src/client/CMakeLists.txt (+22/-0) src/client/client.cpp (+223/-60) src/client/items.cpp (+196/-0) src/client/keeper-errors.cpp (+74/-0) src/client/qml-plugin/CMakeLists.txt (+1/-1) src/helper/CMakeLists.txt (+18/-1) src/helper/backup-helper.cpp (+30/-8) src/helper/data-dir-registry.cpp (+54/-22) src/helper/folder-backup.sh.in (+1/-1) src/helper/folder-restore.sh.in (+23/-0) src/helper/helper.cpp (+6/-8) src/helper/metadata.cpp (+45/-50) src/helper/restore-helper.cpp (+377/-0) src/qdbus-stubs/CMakeLists.txt (+19/-1) src/qdbus-stubs/com.canonical.keeper.User.xml (+47/-3) src/qdbus-stubs/dbus-types.h (+6/-2) src/qdbus-stubs/org.freedesktop.DBus.Properties.xml (+27/-0) src/service/CMakeLists.txt (+4/-0) src/service/backup-choices.cpp (+20/-12) src/service/backup-choices.h (+2/-1) src/service/keeper-helper.cpp (+5/-2) src/service/keeper-task-backup.cpp (+40/-11) src/service/keeper-task-backup.h (+4/-2) src/service/keeper-task-restore.cpp (+130/-0) src/service/keeper-task-restore.h (+46/-0) src/service/keeper-task.cpp (+96/-23) src/service/keeper-task.h (+10/-2) src/service/keeper-user.cpp (+37/-45) src/service/keeper-user.h (+8/-6) src/service/keeper.cpp (+365/-62) src/service/keeper.h (+19/-5) src/service/main.cpp (+2/-1) src/service/manifest.cpp (+248/-0) src/service/manifest.h (+51/-0) src/service/metadata-provider.h (+10/-2) src/service/private/keeper-task_p.h (+10/-2) src/service/restore-choices.cpp (+55/-93) src/service/restore-choices.h (+10/-5) src/service/task-manager.cpp (+170/-25) src/service/task-manager.h (+12/-6) src/storage-framework/CMakeLists.txt (+3/-0) src/storage-framework/downloader.h (+46/-0) src/storage-framework/sf-downloader.cpp (+54/-0) src/storage-framework/sf-downloader.h (+48/-0) src/storage-framework/sf-uploader.cpp (+12/-2) src/storage-framework/sf-uploader.h (+3/-0) src/storage-framework/storage_framework_client.cpp (+444/-36) src/storage-framework/storage_framework_client.h (+25/-5) src/storage-framework/uploader.h (+1/-0) src/tar/CMakeLists.txt (+72/-27) src/tar/tar-creator.cpp (+31/-29) src/tar/untar-main.cpp (+169/-0) src/tar/untar.cpp (+144/-0) src/tar/untar.h (+38/-0) src/util/connection-helper.h (+9/-4) tests/CMakeLists.txt (+9/-1) tests/com_canonical_keeper.py (+80/-45) tests/dbusmock/keeper-template-test.cpp (+113/-102) tests/fakes/CMakeLists.txt (+14/-0) tests/fakes/fake-restore-helper.cpp (+136/-0) tests/fakes/fake-restore-helper.h (+27/-0) tests/fakes/folder-restore.sh.in (+41/-0) tests/fakes/helper-test.sh.in (+16/-0) tests/fakes/upstart/upstart-job-mock.cpp (+4/-1) tests/integration/helpers/CMakeLists.txt (+94/-1) tests/integration/helpers/helpers-test-failure.cpp (+20/-8) tests/integration/helpers/helpers-test.cc (+289/-9) tests/integration/helpers/restore-test.cpp (+126/-0) tests/integration/helpers/state-change-test-manager.h (+55/-0) tests/integration/helpers/state-change-test.cpp (+56/-0) tests/integration/helpers/state-test-helper.h (+55/-0) tests/integration/helpers/test-helpers-base.cpp (+363/-135) tests/integration/helpers/test-helpers-base.h (+22/-13) tests/unit/CMakeLists.txt (+3/-0) tests/unit/helper/CMakeLists.txt (+1/-5) tests/unit/helper/speed-test.cpp (+3/-3) tests/unit/manifest/CMakeLists.txt (+45/-0) tests/unit/manifest/manifest-test.cpp (+170/-0) tests/unit/metadata-providers/CMakeLists.txt (+3/-0) tests/unit/metadata-providers/user-dirs-test.cpp (+19/-12) tests/unit/metadata/CMakeLists.txt (+44/-0) tests/unit/metadata/metadata-json-test.cpp (+100/-0) tests/unit/storage-framework/CMakeLists.txt (+73/-0) tests/unit/storage-framework/create-uploader-test.cpp (+147/-0) tests/unit/storage-framework/folders-test.cpp (+109/-0) tests/unit/tar/CMakeLists.txt (+104/-29) tests/unit/tar/keeper-tar-test.cpp (+5/-5) tests/unit/tar/keeper-untar-test.cpp (+232/-0) tests/unit/tar/ku-invoke-nobus.sh.in (+1/-0) tests/unit/tar/ku-invoke.sh.in (+1/-0) tests/unit/tar/tar-creator-libarchive-failure-test.cpp (+5/-1) tests/unit/tar/tar-creator-test.cpp (+1/-1) tests/unit/tar/untar-test.cpp (+120/-0) tests/utils/CMakeLists.txt (+2/-0) tests/utils/file-utils.cpp (+88/-6) tests/utils/file-utils.h (+5/-1) tests/utils/keeper-dbusmock-fixture.h (+9/-0) tests/utils/main.cpp (+1/-1) tests/utils/storage-framework-local.cpp (+207/-0) tests/utils/storage-framework-local.h (+48/-0) tests/utils/xdg-user-dirs-sandbox.cpp (+1/-1) |
To merge this branch: | bzr merge lp:keeper/devel |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Charles Kerr (community) | Approve | ||
Review via email:
|
Commit message
Description of the change
This is just to merge what's in devel (which has apparently already mostly been released to zesty/xenial+
To post a comment you must log in.
lp:keeper/devel
updated
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Charles Kerr (charlesk) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2016-08-26 09:30:11 +0000 | |||
3 | +++ CMakeLists.txt 2017-02-27 19:05:17 +0000 | |||
4 | @@ -272,7 +272,7 @@ | |||
5 | 272 | include(CTest) | 272 | include(CTest) |
6 | 273 | enable_testing() | 273 | enable_testing() |
7 | 274 | 274 | ||
9 | 275 | include(EnableCoverageReport) | 275 | find_package(CoverageReport) |
10 | 276 | 276 | ||
11 | 277 | add_subdirectory(data) | 277 | add_subdirectory(data) |
12 | 278 | add_subdirectory(src) | 278 | add_subdirectory(src) |
13 | 279 | 279 | ||
14 | === modified file 'data/CMakeLists.txt' | |||
15 | --- data/CMakeLists.txt 2016-08-10 07:43:36 +0000 | |||
16 | +++ data/CMakeLists.txt 2017-02-27 19:05:17 +0000 | |||
17 | @@ -6,6 +6,12 @@ | |||
18 | 6 | FOLDER_BACKUP_EXEC | 6 | FOLDER_BACKUP_EXEC |
19 | 7 | ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}/folder-backup.sh | 7 | ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}/folder-backup.sh |
20 | 8 | ) | 8 | ) |
21 | 9 | |||
22 | 10 | set( | ||
23 | 11 | FOLDER_RESTORE_EXEC | ||
24 | 12 | ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}/folder-restore.sh | ||
25 | 13 | ) | ||
26 | 14 | |||
27 | 9 | configure_file( | 15 | configure_file( |
28 | 10 | ${HELPER_REGISTRY_FILENAME}.in | 16 | ${HELPER_REGISTRY_FILENAME}.in |
29 | 11 | ${HELPER_REGISTRY_FILENAME} | 17 | ${HELPER_REGISTRY_FILENAME} |
30 | 12 | 18 | ||
31 | === modified file 'data/helper-registry.json.in' | |||
32 | --- data/helper-registry.json.in 2016-08-09 04:20:33 +0000 | |||
33 | +++ data/helper-registry.json.in 2017-02-27 19:05:17 +0000 | |||
34 | @@ -4,5 +4,10 @@ | |||
35 | 4 | "@FOLDER_BACKUP_EXEC@", | 4 | "@FOLDER_BACKUP_EXEC@", |
36 | 5 | "${subtype}" | 5 | "${subtype}" |
37 | 6 | ] | 6 | ] |
39 | 7 | } | 7 | , |
40 | 8 | "restore-urls": [ | ||
41 | 9 | "@FOLDER_RESTORE_EXEC@", | ||
42 | 10 | "${subtype}" | ||
43 | 11 | ] | ||
44 | 12 | } | ||
45 | 8 | } | 13 | } |
46 | 9 | 14 | ||
47 | === modified file 'debian/changelog' | |||
48 | --- debian/changelog 2016-09-15 19:20:14 +0000 | |||
49 | +++ debian/changelog 2017-02-27 19:05:17 +0000 | |||
50 | @@ -1,3 +1,17 @@ | |||
51 | 1 | keeper (0.1.1-0ubuntu1) UNRELEASED; urgency=medium | ||
52 | 2 | |||
53 | 3 | [ Ken Vandine ] | ||
54 | 4 | * Update to handle the API/ABI break in ubuntu-app-launch. | ||
55 | 5 | |||
56 | 6 | -- Rodney Dawes <rodney.dawes@canonical.com> Mon, 27 Feb 2017 13:46:45 -0500 | ||
57 | 7 | |||
58 | 8 | keeper (0.1.0+17.04.20170213.1-0ubuntu1) zesty; urgency=medium | ||
59 | 9 | |||
60 | 10 | [ Charles Kerr, Xavi Garcia, Xavi Garcia Mena ] | ||
61 | 11 | * Adds integration tests for restore and restore cancellation. | ||
62 | 12 | |||
63 | 13 | -- Xavi Garcia <xavi.garcia.mena@canonical.com> Mon, 13 Feb 2017 08:57:47 +0000 | ||
64 | 14 | |||
65 | 1 | keeper (0.1.0+16.10.20160915.3-0ubuntu1) yakkety; urgency=medium | 15 | keeper (0.1.0+16.10.20160915.3-0ubuntu1) yakkety; urgency=medium |
66 | 2 | 16 | ||
67 | 3 | * Initial release. | 17 | * Initial release. |
68 | 4 | 18 | ||
69 | === modified file 'debian/control' | |||
70 | --- debian/control 2016-08-26 08:48:05 +0000 | |||
71 | +++ debian/control 2017-02-27 19:05:17 +0000 | |||
72 | @@ -9,7 +9,7 @@ | |||
73 | 9 | # for building the code: | 9 | # for building the code: |
74 | 10 | libarchive-dev (>= 3.1.2), | 10 | libarchive-dev (>= 3.1.2), |
75 | 11 | libproperties-cpp-dev, | 11 | libproperties-cpp-dev, |
77 | 12 | libubuntu-app-launch2-dev (>= 0.9), | 12 | libubuntu-app-launch3-dev, |
78 | 13 | storage-framework-client-dev, | 13 | storage-framework-client-dev, |
79 | 14 | libclick-0.4-dev, | 14 | libclick-0.4-dev, |
80 | 15 | uuid-dev, | 15 | uuid-dev, |
81 | @@ -45,6 +45,8 @@ | |||
82 | 45 | Depends: ${shlibs:Depends}, | 45 | Depends: ${shlibs:Depends}, |
83 | 46 | ${misc:Depends}, | 46 | ${misc:Depends}, |
84 | 47 | systemd | systemd-shim, | 47 | systemd | systemd-shim, |
85 | 48 | tar, | ||
86 | 49 | xz-utils | ||
87 | 48 | Description: Backup Tool | 50 | Description: Backup Tool |
88 | 49 | A backup/restore utility for Ubuntu | 51 | A backup/restore utility for Ubuntu |
89 | 50 | 52 | ||
90 | @@ -53,6 +55,8 @@ | |||
91 | 53 | Depends: ${shlibs:Depends}, | 55 | Depends: ${shlibs:Depends}, |
92 | 54 | ${misc:Depends}, | 56 | ${misc:Depends}, |
93 | 55 | systemd | systemd-shim, | 57 | systemd | systemd-shim, |
94 | 58 | tar, | ||
95 | 59 | xz-utils | ||
96 | 56 | Description: Backup Tool | 60 | Description: Backup Tool |
97 | 57 | A backup/restore utility for Ubuntu (client application) | 61 | A backup/restore utility for Ubuntu (client application) |
98 | 58 | 62 | ||
99 | 59 | 63 | ||
100 | === modified file 'debian/keeper.install' | |||
101 | --- debian/keeper.install 2016-08-10 07:43:36 +0000 | |||
102 | +++ debian/keeper.install 2017-02-27 19:05:17 +0000 | |||
103 | @@ -1,6 +1,8 @@ | |||
104 | 1 | /usr/lib/*/keeper/folder-backup.sh | 1 | /usr/lib/*/keeper/folder-backup.sh |
105 | 2 | /usr/lib/*/keeper/folder-restore.sh | ||
106 | 2 | /usr/lib/*/keeper/keeper-service | 3 | /usr/lib/*/keeper/keeper-service |
108 | 3 | /usr/lib/*/keeper/keeper-tar-create | 4 | /usr/lib/*/keeper/keeper-tar |
109 | 5 | /usr/lib/*/keeper/keeper-untar | ||
110 | 4 | /usr/lib/*/ubuntu-app-launch/backup-helper/exec-tool | 6 | /usr/lib/*/ubuntu-app-launch/backup-helper/exec-tool |
111 | 5 | /usr/share/keeper/helper-registry.json | 7 | /usr/share/keeper/helper-registry.json |
112 | 6 | /usr/share/dbus-1/services/com.canonical.keeper.service | 8 | /usr/share/dbus-1/services/com.canonical.keeper.service |
113 | 7 | 9 | ||
114 | === modified file 'include/client/client.h' | |||
115 | --- include/client/client.h 2016-09-06 18:28:45 +0000 | |||
116 | +++ include/client/client.h 2017-02-27 19:05:17 +0000 | |||
117 | @@ -19,10 +19,13 @@ | |||
118 | 19 | 19 | ||
119 | 20 | #pragma once | 20 | #pragma once |
120 | 21 | 21 | ||
121 | 22 | #include "keeper-errors.h" | ||
122 | 23 | |||
123 | 22 | #include <QObject> | 24 | #include <QObject> |
124 | 23 | #include <QScopedPointer> | 25 | #include <QScopedPointer> |
125 | 24 | #include <QStringList> | 26 | #include <QStringList> |
126 | 25 | #include <QVariant> | 27 | #include <QVariant> |
127 | 28 | #include "keeper-items.h" | ||
128 | 26 | 29 | ||
129 | 27 | struct KeeperClientPrivate; | 30 | struct KeeperClientPrivate; |
130 | 28 | 31 | ||
131 | @@ -53,14 +56,22 @@ | |||
132 | 53 | 56 | ||
133 | 54 | Q_INVOKABLE QString getBackupName(QString uuid); | 57 | Q_INVOKABLE QString getBackupName(QString uuid); |
134 | 55 | Q_INVOKABLE void enableBackup(QString uuid, bool enabled); | 58 | Q_INVOKABLE void enableBackup(QString uuid, bool enabled); |
136 | 56 | Q_INVOKABLE void startBackup(); | 59 | Q_INVOKABLE void startBackup(QString const & storage); |
137 | 60 | |||
138 | 61 | Q_INVOKABLE void enableRestore(QString uuid, bool enabled); | ||
139 | 62 | Q_INVOKABLE void startRestore(QString const & storage); | ||
140 | 63 | |||
141 | 64 | Q_INVOKABLE void cancel(); | ||
142 | 57 | 65 | ||
143 | 58 | // C++ | 66 | // C++ |
144 | 59 | public: | 67 | public: |
147 | 60 | QMap<QString, QVariantMap> getBackupChoices() const; | 68 | keeper::Items getBackupChoices(keeper::Error & error) const; |
148 | 61 | void startBackup(QStringList const& uuids) const; | 69 | keeper::Items getRestoreChoices(QString const & storage, keeper::Error & error) const; |
149 | 70 | void startBackup(QStringList const& uuids, QString const & storage) const; | ||
150 | 71 | void startRestore(QStringList const& uuids, QString const & storage) const; | ||
151 | 62 | 72 | ||
153 | 63 | QMap<QString, QVariantMap> getState() const; | 73 | keeper::Items getState() const; |
154 | 74 | QStringList getStorageAccounts() const; | ||
155 | 64 | 75 | ||
156 | 65 | Q_SIGNALS: | 76 | Q_SIGNALS: |
157 | 66 | void statusChanged(); | 77 | void statusChanged(); |
158 | @@ -68,6 +79,9 @@ | |||
159 | 68 | void readyToBackupChanged(); | 79 | void readyToBackupChanged(); |
160 | 69 | void backupBusyChanged(); | 80 | void backupBusyChanged(); |
161 | 70 | 81 | ||
162 | 82 | void taskStatusChanged(QString const & displayName, QString const & status, double percentage, keeper::Error error); | ||
163 | 83 | void finished(); | ||
164 | 84 | |||
165 | 71 | private Q_SLOTS: | 85 | private Q_SLOTS: |
166 | 72 | void stateUpdated(); | 86 | void stateUpdated(); |
167 | 73 | 87 | ||
168 | 74 | 88 | ||
169 | === added file 'include/client/keeper-errors.h' | |||
170 | --- include/client/keeper-errors.h 1970-01-01 00:00:00 +0000 | |||
171 | +++ include/client/keeper-errors.h 2017-02-27 19:05:17 +0000 | |||
172 | @@ -0,0 +1,57 @@ | |||
173 | 1 | /* | ||
174 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
175 | 3 | * | ||
176 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
177 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
178 | 6 | * by the Free Software Foundation. | ||
179 | 7 | * | ||
180 | 8 | * This program is distributed in the hope that it will be useful, but | ||
181 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
182 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
183 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
184 | 12 | * | ||
185 | 13 | * You should have received a copy of the GNU General Public License along | ||
186 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
187 | 15 | * | ||
188 | 16 | * Authors: | ||
189 | 17 | * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> | ||
190 | 18 | */ | ||
191 | 19 | |||
192 | 20 | #pragma once | ||
193 | 21 | |||
194 | 22 | #include <QDBusArgument> | ||
195 | 23 | #include <QMetaType> | ||
196 | 24 | |||
197 | 25 | namespace keeper | ||
198 | 26 | { | ||
199 | 27 | |||
200 | 28 | enum class Error | ||
201 | 29 | { | ||
202 | 30 | OK, | ||
203 | 31 | UNKNOWN, | ||
204 | 32 | HELPER_READ, | ||
205 | 33 | HELPER_WRITE, | ||
206 | 34 | HELPER_INACTIVITY_DETECTED, | ||
207 | 35 | HELPER_SOCKET, | ||
208 | 36 | HELPER_START_TIMEOUT, | ||
209 | 37 | NO_HELPER_INFORMATION_IN_REGISTRY, | ||
210 | 38 | HELPER_BAD_URL, | ||
211 | 39 | MANIFEST_STORAGE, | ||
212 | 40 | COMMITTING_DATA, | ||
213 | 41 | |||
214 | 42 | CREATING_REMOTE_DIR, | ||
215 | 43 | CREATING_REMOTE_FILE, | ||
216 | 44 | READING_REMOTE_FILE, | ||
217 | 45 | REMOTE_DIR_NOT_EXISTS, | ||
218 | 46 | NO_REMOTE_ACCOUNTS, | ||
219 | 47 | NO_REMOTE_ROOTS, | ||
220 | 48 | ACCOUNT_NOT_FOUND | ||
221 | 49 | }; | ||
222 | 50 | |||
223 | 51 | Error convert_from_dbus_variant(const QVariant & value, bool *conversion_ok = nullptr); | ||
224 | 52 | } // namespace keeper | ||
225 | 53 | |||
226 | 54 | QDBusArgument &operator<<(QDBusArgument &argument, keeper::Error value); | ||
227 | 55 | const QDBusArgument &operator>>(const QDBusArgument &argument, keeper::Error &val); | ||
228 | 56 | |||
229 | 57 | Q_DECLARE_METATYPE(keeper::Error) | ||
230 | 0 | 58 | ||
231 | === added file 'include/client/keeper-items.h' | |||
232 | --- include/client/keeper-items.h 1970-01-01 00:00:00 +0000 | |||
233 | +++ include/client/keeper-items.h 2017-02-27 19:05:17 +0000 | |||
234 | @@ -0,0 +1,102 @@ | |||
235 | 1 | /* | ||
236 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
237 | 3 | * | ||
238 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
239 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
240 | 6 | * by the Free Software Foundation. | ||
241 | 7 | * | ||
242 | 8 | * This program is distributed in the hope that it will be useful, but | ||
243 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
244 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
245 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
246 | 12 | * | ||
247 | 13 | * You should have received a copy of the GNU General Public License along | ||
248 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
249 | 15 | * | ||
250 | 16 | * Authors: | ||
251 | 17 | * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> | ||
252 | 18 | */ | ||
253 | 19 | |||
254 | 20 | #pragma once | ||
255 | 21 | |||
256 | 22 | #include "client/keeper-errors.h" | ||
257 | 23 | |||
258 | 24 | #include <QJsonObject> | ||
259 | 25 | |||
260 | 26 | typedef QMap<QString, QVariantMap> QVariantDictMap; | ||
261 | 27 | |||
262 | 28 | namespace keeper | ||
263 | 29 | { | ||
264 | 30 | |||
265 | 31 | class Item : public QVariantMap | ||
266 | 32 | { | ||
267 | 33 | public: | ||
268 | 34 | Item(); | ||
269 | 35 | ~Item(); | ||
270 | 36 | explicit Item(QVariantMap const & values); | ||
271 | 37 | |||
272 | 38 | // keys | ||
273 | 39 | static QString const UUID_KEY; | ||
274 | 40 | static QString const TYPE_KEY; | ||
275 | 41 | static QString const SUBTYPE_KEY; | ||
276 | 42 | static QString const NAME_KEY; | ||
277 | 43 | static QString const PACKAGE_KEY; | ||
278 | 44 | static QString const TITLE_KEY; | ||
279 | 45 | static QString const VERSION_KEY; | ||
280 | 46 | static QString const FILE_NAME_KEY; | ||
281 | 47 | static QString const DIR_NAME_KEY; | ||
282 | 48 | static QString const DISPLAY_NAME_KEY; | ||
283 | 49 | static QString const STATUS_KEY; | ||
284 | 50 | static QString const ERROR_KEY; | ||
285 | 51 | static QString const PERCENT_DONE_KEY; | ||
286 | 52 | static QString const SPEED_KEY; | ||
287 | 53 | |||
288 | 54 | // values | ||
289 | 55 | static QString const FOLDER_VALUE; | ||
290 | 56 | static QString const SYSTEM_DATA_VALUE; | ||
291 | 57 | static QString const APPLICATION_VALUE; | ||
292 | 58 | |||
293 | 59 | |||
294 | 60 | // methods created for convenience | ||
295 | 61 | bool has_property(QString const & property) const; | ||
296 | 62 | template<typename T> T get_property(QString const & property, bool * valid) const; | ||
297 | 63 | QVariant get_property_value(QString const & property) const; | ||
298 | 64 | void set_property_value(QString const& property, QVariant const& value); | ||
299 | 65 | |||
300 | 66 | // checks that the item is valid | ||
301 | 67 | bool is_valid() const; | ||
302 | 68 | |||
303 | 69 | // predefined properties | ||
304 | 70 | QString get_uuid(bool *valid = nullptr) const; | ||
305 | 71 | QString get_type(bool *valid = nullptr) const; | ||
306 | 72 | QString get_display_name(bool *valid = nullptr) const; | ||
307 | 73 | QString get_dir_name(bool *valid = nullptr) const; | ||
308 | 74 | QString get_status(bool *valid = nullptr) const; | ||
309 | 75 | double get_percent_done(bool *valid = nullptr) const; | ||
310 | 76 | keeper::Error get_error(bool *valid = nullptr) const; | ||
311 | 77 | QString get_file_name(bool *valid = nullptr) const; | ||
312 | 78 | |||
313 | 79 | // d-bus | ||
314 | 80 | static void registerMetaType(); | ||
315 | 81 | }; | ||
316 | 82 | |||
317 | 83 | class Items : public QMap<QString, Item> | ||
318 | 84 | { | ||
319 | 85 | public: | ||
320 | 86 | Items(); | ||
321 | 87 | ~Items(); | ||
322 | 88 | explicit Items(Error error); | ||
323 | 89 | |||
324 | 90 | QStringList get_uuids() const; | ||
325 | 91 | |||
326 | 92 | // d-bus | ||
327 | 93 | static void registerMetaType(); | ||
328 | 94 | |||
329 | 95 | private: | ||
330 | 96 | Error error_ = Error::OK; | ||
331 | 97 | }; | ||
332 | 98 | |||
333 | 99 | } // namespace keeper | ||
334 | 100 | |||
335 | 101 | Q_DECLARE_METATYPE(keeper::Item) | ||
336 | 102 | Q_DECLARE_METATYPE(keeper::Items) | ||
337 | 0 | 103 | ||
338 | === modified file 'include/helper/backup-helper.h' | |||
339 | --- include/helper/backup-helper.h 2016-09-15 16:02:54 +0000 | |||
340 | +++ include/helper/backup-helper.h 2017-02-27 19:05:17 +0000 | |||
341 | @@ -53,6 +53,7 @@ | |||
342 | 53 | int get_helper_socket() const; | 53 | int get_helper_socket() const; |
343 | 54 | QString to_string(Helper::State state) const override; | 54 | QString to_string(Helper::State state) const override; |
344 | 55 | void set_state(State) override; | 55 | void set_state(State) override; |
345 | 56 | QString get_uploader_committed_file_name() const; | ||
346 | 56 | protected: | 57 | protected: |
347 | 57 | void on_helper_finished() override; | 58 | void on_helper_finished() override; |
348 | 58 | 59 | ||
349 | 59 | 60 | ||
350 | === modified file 'include/helper/data-dir-registry.h' | |||
351 | --- include/helper/data-dir-registry.h 2016-08-09 05:44:25 +0000 | |||
352 | +++ include/helper/data-dir-registry.h 2017-02-27 19:05:17 +0000 | |||
353 | @@ -39,6 +39,8 @@ | |||
354 | 39 | 39 | ||
355 | 40 | QStringList get_backup_helper_urls(Metadata const& metadata) override; | 40 | QStringList get_backup_helper_urls(Metadata const& metadata) override; |
356 | 41 | 41 | ||
357 | 42 | QStringList get_restore_helper_urls(Metadata const& metadata) override; | ||
358 | 43 | |||
359 | 42 | private: | 44 | private: |
360 | 43 | class Impl; | 45 | class Impl; |
361 | 44 | friend class Impl; | 46 | friend class Impl; |
362 | 45 | 47 | ||
363 | === modified file 'include/helper/helper.h' | |||
364 | --- include/helper/helper.h 2016-09-15 16:02:54 +0000 | |||
365 | +++ include/helper/helper.h 2017-02-27 19:05:17 +0000 | |||
366 | @@ -19,6 +19,7 @@ | |||
367 | 19 | 19 | ||
368 | 20 | #pragma once | 20 | #pragma once |
369 | 21 | 21 | ||
370 | 22 | #include <client/keeper-errors.h> | ||
371 | 22 | #include <util/attributes.h> | 23 | #include <util/attributes.h> |
372 | 23 | 24 | ||
373 | 24 | #include <QObject> | 25 | #include <QObject> |
374 | @@ -64,11 +65,12 @@ | |||
375 | 64 | virtual void start(QStringList const& urls); | 65 | virtual void start(QStringList const& urls); |
376 | 65 | virtual void stop(); | 66 | virtual void stop(); |
377 | 66 | 67 | ||
379 | 67 | static constexpr int MAX_UAL_WAIT_TIME = 5000; | 68 | static constexpr int MAX_UAL_WAIT_TIME = 10000; |
380 | 68 | 69 | ||
381 | 69 | Q_SIGNALS: | 70 | Q_SIGNALS: |
382 | 70 | void state_changed(Helper::State); | 71 | void state_changed(Helper::State); |
383 | 71 | void percent_done_changed(float); | 72 | void percent_done_changed(float); |
384 | 73 | void error(keeper::Error error); | ||
385 | 72 | 74 | ||
386 | 73 | protected: | 75 | protected: |
387 | 74 | Helper(QString const & appid, const clock_func& clock=default_clock, QObject *parent=nullptr); | 76 | Helper(QString const & appid, const clock_func& clock=default_clock, QObject *parent=nullptr); |
388 | 75 | 77 | ||
389 | === modified file 'include/helper/metadata.h' | |||
390 | --- include/helper/metadata.h 2016-09-06 18:51:30 +0000 | |||
391 | +++ include/helper/metadata.h 2017-02-27 19:05:17 +0000 | |||
392 | @@ -19,42 +19,21 @@ | |||
393 | 19 | 19 | ||
394 | 20 | #pragma once | 20 | #pragma once |
395 | 21 | 21 | ||
396 | 22 | #include "client/keeper-items.h" | ||
397 | 23 | #include <QJsonObject> | ||
398 | 22 | #include <QMap> | 24 | #include <QMap> |
399 | 23 | #include <QString> | 25 | #include <QString> |
400 | 24 | 26 | ||
401 | 25 | /** | 27 | /** |
403 | 26 | * Information about a backup | 28 | * Information about a backup or restore item |
404 | 27 | */ | 29 | */ |
406 | 28 | class Metadata | 30 | class Metadata : public keeper::Item |
407 | 29 | { | 31 | { |
408 | 30 | public: | 32 | public: |
409 | 31 | 33 | ||
410 | 32 | Metadata(); | 34 | Metadata(); |
411 | 35 | explicit Metadata(QJsonObject const & json_object); | ||
412 | 33 | Metadata(QString const& uuid, QString const& display_name); | 36 | Metadata(QString const& uuid, QString const& display_name); |
413 | 34 | 37 | ||
439 | 35 | // metadata keys | 38 | QJsonObject json() const; |
415 | 36 | static QString const TYPE_KEY; | ||
416 | 37 | static QString const SUBTYPE_KEY; | ||
417 | 38 | static QString const NAME_KEY; | ||
418 | 39 | static QString const PACKAGE_KEY; | ||
419 | 40 | static QString const TITLE_KEY; | ||
420 | 41 | static QString const VERSION_KEY; | ||
421 | 42 | |||
422 | 43 | // metadata values | ||
423 | 44 | static QString const FOLDER_VALUE; | ||
424 | 45 | static QString const SYSTEM_DATA_VALUE; | ||
425 | 46 | static QString const APPLICATION_VALUE; | ||
426 | 47 | |||
427 | 48 | QString uuid() const { return uuid_; } | ||
428 | 49 | QString display_name() const { return display_name_; } | ||
429 | 50 | bool get_property(QString const& property_name, QString& setme_value) const; | ||
430 | 51 | void set_property(QString const& property_name, QString const& value); | ||
431 | 52 | |||
432 | 53 | QMap<QString,QString> get_public_properties() const; | ||
433 | 54 | |||
434 | 55 | private: | ||
435 | 56 | |||
436 | 57 | QString uuid_; | ||
437 | 58 | QString display_name_; | ||
438 | 59 | QMap<QString,QString> properties_{}; | ||
440 | 60 | }; | 39 | }; |
441 | 61 | 40 | ||
442 | === modified file 'include/helper/registry.h' | |||
443 | --- include/helper/registry.h 2016-08-08 04:56:35 +0000 | |||
444 | +++ include/helper/registry.h 2017-02-27 19:05:17 +0000 | |||
445 | @@ -30,6 +30,7 @@ | |||
446 | 30 | Q_DISABLE_COPY(HelperRegistry) | 30 | Q_DISABLE_COPY(HelperRegistry) |
447 | 31 | 31 | ||
448 | 32 | virtual QStringList get_backup_helper_urls(Metadata const& task) =0; | 32 | virtual QStringList get_backup_helper_urls(Metadata const& task) =0; |
449 | 33 | virtual QStringList get_restore_helper_urls(Metadata const& task) =0; | ||
450 | 33 | 34 | ||
451 | 34 | protected: | 35 | protected: |
452 | 35 | HelperRegistry() =default; | 36 | HelperRegistry() =default; |
453 | 36 | 37 | ||
454 | === added file 'include/helper/restore-helper.h' | |||
455 | --- include/helper/restore-helper.h 1970-01-01 00:00:00 +0000 | |||
456 | +++ include/helper/restore-helper.h 2017-02-27 19:05:17 +0000 | |||
457 | @@ -0,0 +1,62 @@ | |||
458 | 1 | /* | ||
459 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
460 | 3 | * | ||
461 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
462 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
463 | 6 | * by the Free Software Foundation. | ||
464 | 7 | * | ||
465 | 8 | * This program is distributed in the hope that it will be useful, but | ||
466 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
467 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
468 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
469 | 12 | * | ||
470 | 13 | * You should have received a copy of the GNU General Public License along | ||
471 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
472 | 15 | * | ||
473 | 16 | * Authors: | ||
474 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
475 | 18 | * Charles Kerr <charles.kerr@canonical.com> | ||
476 | 19 | */ | ||
477 | 20 | |||
478 | 21 | #pragma once | ||
479 | 22 | |||
480 | 23 | #include "storage-framework/downloader.h" | ||
481 | 24 | #include "helper/helper.h" // parent class | ||
482 | 25 | #include "helper/registry.h" | ||
483 | 26 | |||
484 | 27 | #include <QObject> | ||
485 | 28 | #include <QScopedPointer> | ||
486 | 29 | #include <QString> | ||
487 | 30 | |||
488 | 31 | #include <memory> | ||
489 | 32 | |||
490 | 33 | class RestoreHelperPrivate; | ||
491 | 34 | class RestoreHelper final: public Helper | ||
492 | 35 | { | ||
493 | 36 | Q_OBJECT | ||
494 | 37 | Q_DECLARE_PRIVATE(RestoreHelper) | ||
495 | 38 | |||
496 | 39 | public: | ||
497 | 40 | RestoreHelper( | ||
498 | 41 | QString const & appid, | ||
499 | 42 | clock_func const & clock=Helper::default_clock, | ||
500 | 43 | QObject * parent=nullptr | ||
501 | 44 | ); | ||
502 | 45 | virtual ~RestoreHelper(); | ||
503 | 46 | Q_DISABLE_COPY(RestoreHelper) | ||
504 | 47 | |||
505 | 48 | static constexpr int MAX_INACTIVITY_TIME = 15000; | ||
506 | 49 | |||
507 | 50 | void set_downloader(std::shared_ptr<Downloader> const& downloader); | ||
508 | 51 | |||
509 | 52 | void start(QStringList const& urls) override; | ||
510 | 53 | void stop() override; | ||
511 | 54 | int get_helper_socket() const; | ||
512 | 55 | QString to_string(Helper::State state) const override; | ||
513 | 56 | void set_state(State) override; | ||
514 | 57 | protected: | ||
515 | 58 | void on_helper_finished() override; | ||
516 | 59 | |||
517 | 60 | private: | ||
518 | 61 | QScopedPointer<RestoreHelperPrivate> const d_ptr; | ||
519 | 62 | }; | ||
520 | 0 | 63 | ||
521 | === modified file 'src/cli/CMakeLists.txt' | |||
522 | --- src/cli/CMakeLists.txt 2016-09-06 01:31:59 +0000 | |||
523 | +++ src/cli/CMakeLists.txt 2017-02-27 19:05:17 +0000 | |||
524 | @@ -5,6 +5,9 @@ | |||
525 | 5 | 5 | ||
526 | 6 | set(CLI_SOURCES | 6 | set(CLI_SOURCES |
527 | 7 | main.cpp | 7 | main.cpp |
528 | 8 | command-line.cpp | ||
529 | 9 | command-line-client.cpp | ||
530 | 10 | command-line-client-view.cpp | ||
531 | 8 | ) | 11 | ) |
532 | 9 | 12 | ||
533 | 10 | add_executable( | 13 | add_executable( |
534 | @@ -19,6 +22,7 @@ | |||
535 | 19 | util | 22 | util |
536 | 20 | qdbus-stubs | 23 | qdbus-stubs |
537 | 21 | ${SERVICE_DEVEL_SF_DEPS_LIBRARIES} | 24 | ${SERVICE_DEVEL_SF_DEPS_LIBRARIES} |
538 | 25 | ${KEEPER_CLIENT_LIB} | ||
539 | 22 | Qt5::Core | 26 | Qt5::Core |
540 | 23 | Qt5::DBus | 27 | Qt5::DBus |
541 | 24 | ) | 28 | ) |
542 | 25 | 29 | ||
543 | === added file 'src/cli/command-line-client-view.cpp' | |||
544 | --- src/cli/command-line-client-view.cpp 1970-01-01 00:00:00 +0000 | |||
545 | +++ src/cli/command-line-client-view.cpp 2017-02-27 19:05:17 +0000 | |||
546 | @@ -0,0 +1,194 @@ | |||
547 | 1 | /* | ||
548 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
549 | 3 | * | ||
550 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
551 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
552 | 6 | * by the Free Software Foundation. | ||
553 | 7 | * | ||
554 | 8 | * This program is distributed in the hope that it will be useful, but | ||
555 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
556 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
557 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
558 | 12 | * | ||
559 | 13 | * You should have received a copy of the GNU General Public License along | ||
560 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
561 | 15 | * | ||
562 | 16 | * Authors: | ||
563 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
564 | 18 | */ | ||
565 | 19 | #include "command-line-client-view.h" | ||
566 | 20 | |||
567 | 21 | #include <client/client.h> | ||
568 | 22 | |||
569 | 23 | #include <iostream> | ||
570 | 24 | #include <iomanip> | ||
571 | 25 | |||
572 | 26 | CommandLineClientView::CommandLineClientView(QObject * parent) | ||
573 | 27 | : QObject(parent) | ||
574 | 28 | { | ||
575 | 29 | connect(&timer_status_, &QTimer::timeout, this, &CommandLineClientView::show_info); | ||
576 | 30 | |||
577 | 31 | // TODO see if we can do this in a better way | ||
578 | 32 | // This line is for the global progress status and percentage | ||
579 | 33 | std::cout << std::endl; | ||
580 | 34 | } | ||
581 | 35 | |||
582 | 36 | void CommandLineClientView::progress_changed(double percentage) | ||
583 | 37 | { | ||
584 | 38 | percentage_ = percentage * 100; | ||
585 | 39 | } | ||
586 | 40 | |||
587 | 41 | void CommandLineClientView::status_changed(QString const & status) | ||
588 | 42 | { | ||
589 | 43 | if (status_ != status) | ||
590 | 44 | { | ||
591 | 45 | status_ = status; | ||
592 | 46 | } | ||
593 | 47 | } | ||
594 | 48 | |||
595 | 49 | void CommandLineClientView::add_task(QString const & display_name, QString const & initial_status, double initial_percentage) | ||
596 | 50 | { | ||
597 | 51 | tasks_strings_[display_name] = get_task_string(display_name, initial_status, initial_percentage, keeper::Error::OK); | ||
598 | 52 | // TODO see if we can do this in a better way | ||
599 | 53 | // We add a line per each backup task | ||
600 | 54 | std::cout << std::endl; | ||
601 | 55 | } | ||
602 | 56 | |||
603 | 57 | void CommandLineClientView::clear_all_tasks() | ||
604 | 58 | { | ||
605 | 59 | tasks_strings_.clear(); | ||
606 | 60 | } | ||
607 | 61 | |||
608 | 62 | void CommandLineClientView::start_printing_tasks() | ||
609 | 63 | { | ||
610 | 64 | timer_status_.start(300); | ||
611 | 65 | } | ||
612 | 66 | |||
613 | 67 | void CommandLineClientView::clear_all() | ||
614 | 68 | { | ||
615 | 69 | timer_status_.stop(); | ||
616 | 70 | std::cout << std::endl; | ||
617 | 71 | } | ||
618 | 72 | |||
619 | 73 | void CommandLineClientView::print_sections(QStringList const & sections) | ||
620 | 74 | { | ||
621 | 75 | for (auto const & section : sections) | ||
622 | 76 | { | ||
623 | 77 | std::cout << section.toStdString() << std::endl; | ||
624 | 78 | } | ||
625 | 79 | } | ||
626 | 80 | |||
627 | 81 | void CommandLineClientView::print_error_message(QString const & error_message) | ||
628 | 82 | { | ||
629 | 83 | std::cerr << error_message.toStdString() << std::endl; | ||
630 | 84 | } | ||
631 | 85 | |||
632 | 86 | void CommandLineClientView::show_info() | ||
633 | 87 | { | ||
634 | 88 | // TODO Revisit this code to see if we can do this in a different way | ||
635 | 89 | // Maybe using ncurses? | ||
636 | 90 | |||
637 | 91 | // Rewind to the beginning | ||
638 | 92 | std::cout << '\r' << std::flush; | ||
639 | 93 | // For every backup task we go up 1 line | ||
640 | 94 | for (auto i = 0; i < tasks_strings_.size(); ++i) | ||
641 | 95 | { | ||
642 | 96 | std::cout << "\e[A"; | ||
643 | 97 | } | ||
644 | 98 | // print the tasks | ||
645 | 99 | for (auto iter = tasks_strings_.begin(); iter != tasks_strings_.end(); ++iter) | ||
646 | 100 | { | ||
647 | 101 | std::cout << (*iter).toStdString() << std::setfill(' ') << std::endl; | ||
648 | 102 | } | ||
649 | 103 | std::cout << '\r' << std::fixed << std::setw(30) << status_.toStdString() << std::setprecision(3) | ||
650 | 104 | << std::setfill(' ') << " " << percentage_ << " % " << get_next_spin_char() << " " << std::flush; | ||
651 | 105 | } | ||
652 | 106 | |||
653 | 107 | char CommandLineClientView::get_next_spin_char() | ||
654 | 108 | { | ||
655 | 109 | char cursor[4]={'/','-','\\','|'}; | ||
656 | 110 | auto ret = cursor[spin_value_]; | ||
657 | 111 | spin_value_ = (spin_value_ + 1) % 4; | ||
658 | 112 | return ret; | ||
659 | 113 | } | ||
660 | 114 | |||
661 | 115 | QString CommandLineClientView::get_task_string(QString const & displayName, QString const & status, double percentage, keeper::Error error) | ||
662 | 116 | { | ||
663 | 117 | |||
664 | 118 | if (error == keeper::Error::OK) | ||
665 | 119 | return QStringLiteral("%1 %2 % %3").arg(displayName, 15).arg((percentage * 100), 10, 'f', 2, ' ').arg(status, -15); | ||
666 | 120 | else | ||
667 | 121 | return QStringLiteral("%1 %2 % %3 %4").arg(displayName, 15).arg((percentage * 100), 10, 'f', 2, ' ').arg(status, -15).arg(get_error_string(error)); | ||
668 | 122 | } | ||
669 | 123 | |||
670 | 124 | QString CommandLineClientView::get_error_string(keeper::Error error) | ||
671 | 125 | { | ||
672 | 126 | QString ret; | ||
673 | 127 | switch(error) | ||
674 | 128 | { | ||
675 | 129 | case keeper::Error::UNKNOWN: | ||
676 | 130 | ret = QStringLiteral("Unknown error"); | ||
677 | 131 | break; | ||
678 | 132 | case keeper::Error::HELPER_BAD_URL: | ||
679 | 133 | ret = QStringLiteral("Bad URL for keeper helper"); | ||
680 | 134 | break; | ||
681 | 135 | case keeper::Error::HELPER_INACTIVITY_DETECTED: | ||
682 | 136 | ret = QStringLiteral("Inactivity detected in task"); | ||
683 | 137 | break; | ||
684 | 138 | case keeper::Error::HELPER_START_TIMEOUT: | ||
685 | 139 | ret = QStringLiteral("Task failed to start"); | ||
686 | 140 | break; | ||
687 | 141 | case keeper::Error::HELPER_READ: | ||
688 | 142 | ret = QStringLiteral("Read error"); | ||
689 | 143 | break; | ||
690 | 144 | case keeper::Error::HELPER_SOCKET: | ||
691 | 145 | ret = QStringLiteral("Error creating internal socket"); | ||
692 | 146 | break; | ||
693 | 147 | case keeper::Error::HELPER_WRITE: | ||
694 | 148 | ret = QStringLiteral("Write error"); | ||
695 | 149 | break; | ||
696 | 150 | case keeper::Error::MANIFEST_STORAGE: | ||
697 | 151 | ret = QStringLiteral("Error storing manifest file"); | ||
698 | 152 | break; | ||
699 | 153 | case keeper::Error::NO_HELPER_INFORMATION_IN_REGISTRY: | ||
700 | 154 | ret = QStringLiteral("No helper information in registry"); | ||
701 | 155 | break; | ||
702 | 156 | case keeper::Error::OK: | ||
703 | 157 | ret = QStringLiteral("Success"); | ||
704 | 158 | break; | ||
705 | 159 | case keeper::Error::COMMITTING_DATA: | ||
706 | 160 | ret = QStringLiteral("Error uploading data"); | ||
707 | 161 | break; | ||
708 | 162 | case keeper::Error::CREATING_REMOTE_DIR: | ||
709 | 163 | ret = QStringLiteral("Error creating remote directory"); | ||
710 | 164 | break; | ||
711 | 165 | case keeper::Error::CREATING_REMOTE_FILE: | ||
712 | 166 | ret = QStringLiteral("Error creating remote file"); | ||
713 | 167 | break; | ||
714 | 168 | case keeper::Error::READING_REMOTE_FILE: | ||
715 | 169 | ret = QStringLiteral("Error reading remote file"); | ||
716 | 170 | break; | ||
717 | 171 | case keeper::Error::REMOTE_DIR_NOT_EXISTS: | ||
718 | 172 | ret = QStringLiteral("Remote directory does not exist"); | ||
719 | 173 | break; | ||
720 | 174 | case keeper::Error::NO_REMOTE_ACCOUNTS: | ||
721 | 175 | ret = QStringLiteral("No remote accounts were found"); | ||
722 | 176 | break; | ||
723 | 177 | case keeper::Error::NO_REMOTE_ROOTS: | ||
724 | 178 | ret = QStringLiteral("No remote root accounts were found"); | ||
725 | 179 | break; | ||
726 | 180 | case keeper::Error::ACCOUNT_NOT_FOUND: | ||
727 | 181 | ret = QStringLiteral("The storage account was not found"); | ||
728 | 182 | break; | ||
729 | 183 | } | ||
730 | 184 | return ret; | ||
731 | 185 | } | ||
732 | 186 | |||
733 | 187 | void CommandLineClientView::on_task_state_changed(QString const & displayName, QString const & status, double percentage, keeper::Error error) | ||
734 | 188 | { | ||
735 | 189 | auto iter = tasks_strings_.find(displayName); | ||
736 | 190 | if (iter != tasks_strings_.end()) | ||
737 | 191 | { | ||
738 | 192 | tasks_strings_[displayName] = get_task_string(displayName, status, percentage, error); | ||
739 | 193 | } | ||
740 | 194 | } | ||
741 | 0 | 195 | ||
742 | === added file 'src/cli/command-line-client-view.h' | |||
743 | --- src/cli/command-line-client-view.h 1970-01-01 00:00:00 +0000 | |||
744 | +++ src/cli/command-line-client-view.h 2017-02-27 19:05:17 +0000 | |||
745 | @@ -0,0 +1,60 @@ | |||
746 | 1 | /* | ||
747 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
748 | 3 | * | ||
749 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
750 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
751 | 6 | * by the Free Software Foundation. | ||
752 | 7 | * | ||
753 | 8 | * This program is distributed in the hope that it will be useful, but | ||
754 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
755 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
756 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
757 | 12 | * | ||
758 | 13 | * You should have received a copy of the GNU General Public License along | ||
759 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
760 | 15 | * | ||
761 | 16 | * Authors: | ||
762 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
763 | 18 | */ | ||
764 | 19 | #pragma once | ||
765 | 20 | |||
766 | 21 | #include <client/keeper-errors.h> | ||
767 | 22 | |||
768 | 23 | #include <QMap> | ||
769 | 24 | #include <QObject> | ||
770 | 25 | #include <QTimer> | ||
771 | 26 | |||
772 | 27 | class CommandLineClientView : public QObject | ||
773 | 28 | { | ||
774 | 29 | Q_OBJECT | ||
775 | 30 | public: | ||
776 | 31 | explicit CommandLineClientView(QObject * parent = nullptr); | ||
777 | 32 | ~CommandLineClientView() = default; | ||
778 | 33 | |||
779 | 34 | Q_DISABLE_COPY(CommandLineClientView) | ||
780 | 35 | |||
781 | 36 | void progress_changed(double percentage); | ||
782 | 37 | void status_changed(QString const & status); | ||
783 | 38 | |||
784 | 39 | void add_task(QString const & display_name, QString const & initial_status, double initial_percentage); | ||
785 | 40 | void clear_all_tasks(); | ||
786 | 41 | void start_printing_tasks(); | ||
787 | 42 | void clear_all(); | ||
788 | 43 | void print_sections(QStringList const & sections); | ||
789 | 44 | void print_error_message(QString const & error_message); | ||
790 | 45 | QString get_error_string(keeper::Error error); | ||
791 | 46 | |||
792 | 47 | public Q_SLOTS: | ||
793 | 48 | void show_info(); | ||
794 | 49 | void on_task_state_changed(QString const & displayName, QString const & status, double percentage, keeper::Error error); | ||
795 | 50 | |||
796 | 51 | private: | ||
797 | 52 | char get_next_spin_char(); | ||
798 | 53 | QString get_task_string(QString const & displayName, QString const & status, double percentage, keeper::Error error); | ||
799 | 54 | |||
800 | 55 | QString status_; | ||
801 | 56 | QTimer timer_status_; | ||
802 | 57 | double percentage_ = 0.0; | ||
803 | 58 | int spin_value_ = 0; | ||
804 | 59 | QMap<QString, QString> tasks_strings_; | ||
805 | 60 | }; | ||
806 | 0 | 61 | ||
807 | === added file 'src/cli/command-line-client.cpp' | |||
808 | --- src/cli/command-line-client.cpp 1970-01-01 00:00:00 +0000 | |||
809 | +++ src/cli/command-line-client.cpp 2017-02-27 19:05:17 +0000 | |||
810 | @@ -0,0 +1,250 @@ | |||
811 | 1 | /* | ||
812 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
813 | 3 | * | ||
814 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
815 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
816 | 6 | * by the Free Software Foundation. | ||
817 | 7 | * | ||
818 | 8 | * This program is distributed in the hope that it will be useful, but | ||
819 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
820 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
821 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
822 | 12 | * | ||
823 | 13 | * You should have received a copy of the GNU General Public License along | ||
824 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
825 | 15 | * | ||
826 | 16 | * Authors: | ||
827 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
828 | 18 | */ | ||
829 | 19 | #include "command-line-client.h" | ||
830 | 20 | #include "command-line-client-view.h" | ||
831 | 21 | |||
832 | 22 | #include <client/client.h> | ||
833 | 23 | |||
834 | 24 | #include <QCoreApplication> | ||
835 | 25 | #include <QDebug> | ||
836 | 26 | |||
837 | 27 | #include <iostream> | ||
838 | 28 | #include <iomanip> | ||
839 | 29 | |||
840 | 30 | CommandLineClient::CommandLineClient(QObject * parent) | ||
841 | 31 | : QObject(parent) | ||
842 | 32 | , keeper_client_(new KeeperClient(this)) | ||
843 | 33 | , view_(new CommandLineClientView(this)) | ||
844 | 34 | { | ||
845 | 35 | connect(keeper_client_.data(), &KeeperClient::statusChanged, this, &CommandLineClient::on_status_changed); | ||
846 | 36 | connect(keeper_client_.data(), &KeeperClient::progressChanged, this, &CommandLineClient::on_progress_changed); | ||
847 | 37 | connect(keeper_client_.data(), &KeeperClient::finished, this, &CommandLineClient::on_keeper_client_finished); | ||
848 | 38 | connect(keeper_client_.data(), &KeeperClient::taskStatusChanged, view_.data(), &CommandLineClientView::on_task_state_changed); | ||
849 | 39 | } | ||
850 | 40 | |||
851 | 41 | CommandLineClient::~CommandLineClient() = default; | ||
852 | 42 | |||
853 | 43 | void CommandLineClient::run_list_sections(bool remote, QString const & storage) | ||
854 | 44 | { | ||
855 | 45 | keeper::Items choices_values; | ||
856 | 46 | keeper::Error error; | ||
857 | 47 | if(!remote) | ||
858 | 48 | { | ||
859 | 49 | choices_values = keeper_client_->getBackupChoices(error); | ||
860 | 50 | check_for_choices_error(error); | ||
861 | 51 | list_backup_sections(choices_values); | ||
862 | 52 | } | ||
863 | 53 | else | ||
864 | 54 | { | ||
865 | 55 | choices_values = keeper_client_->getRestoreChoices(storage, error); | ||
866 | 56 | check_for_choices_error(error); | ||
867 | 57 | list_restore_sections(choices_values); | ||
868 | 58 | } | ||
869 | 59 | } | ||
870 | 60 | |||
871 | 61 | void CommandLineClient::run_list_storage_accounts() | ||
872 | 62 | { | ||
873 | 63 | list_storage_accounts(keeper_client_->getStorageAccounts()); | ||
874 | 64 | } | ||
875 | 65 | |||
876 | 66 | void CommandLineClient::run_backup(QStringList & sections, QString const & storage) | ||
877 | 67 | { | ||
878 | 68 | auto unhandled_sections = sections; | ||
879 | 69 | keeper::Error error; | ||
880 | 70 | auto choices_values = keeper_client_->getBackupChoices(error); | ||
881 | 71 | check_for_choices_error(error); | ||
882 | 72 | QStringList uuids; | ||
883 | 73 | |||
884 | 74 | auto uuids_choices = choices_values.get_uuids(); | ||
885 | 75 | for(auto iter = uuids_choices.begin(); iter != uuids_choices.end() && unhandled_sections.size(); ++iter) | ||
886 | 76 | { | ||
887 | 77 | const auto& values = choices_values[(*iter)]; | ||
888 | 78 | |||
889 | 79 | if (values.is_valid() && values.get_type() == keeper::Item::FOLDER_VALUE) | ||
890 | 80 | { | ||
891 | 81 | |||
892 | 82 | auto display_name = values.get_display_name(); | ||
893 | 83 | auto index = unhandled_sections.indexOf(display_name); | ||
894 | 84 | if (index != -1) | ||
895 | 85 | { | ||
896 | 86 | // we have to backup this section | ||
897 | 87 | uuids << (*iter); | ||
898 | 88 | unhandled_sections.removeAt(index); | ||
899 | 89 | view_->add_task(display_name, "waiting", 0.0); | ||
900 | 90 | } | ||
901 | 91 | } | ||
902 | 92 | } | ||
903 | 93 | |||
904 | 94 | if (!unhandled_sections.isEmpty()) | ||
905 | 95 | { | ||
906 | 96 | QString error_message("The following sections were not found: \n"); | ||
907 | 97 | for (auto const & section : unhandled_sections) | ||
908 | 98 | { | ||
909 | 99 | error_message += QStringLiteral("\t %1 \n").arg(section); | ||
910 | 100 | } | ||
911 | 101 | view_->print_error_message(error_message); | ||
912 | 102 | exit(1); | ||
913 | 103 | } | ||
914 | 104 | |||
915 | 105 | for (auto const & uuid: uuids) | ||
916 | 106 | { | ||
917 | 107 | keeper_client_->enableBackup(uuid, true); | ||
918 | 108 | } | ||
919 | 109 | keeper_client_->startBackup(storage); | ||
920 | 110 | view_->start_printing_tasks(); | ||
921 | 111 | } | ||
922 | 112 | |||
923 | 113 | void CommandLineClient::run_restore(QStringList & sections, QString const & storage) | ||
924 | 114 | { | ||
925 | 115 | auto unhandled_sections = sections; | ||
926 | 116 | keeper::Error error; | ||
927 | 117 | |||
928 | 118 | auto choices_values = keeper_client_->getRestoreChoices(storage, error); | ||
929 | 119 | check_for_choices_error(error); | ||
930 | 120 | QStringList uuids; | ||
931 | 121 | |||
932 | 122 | auto uuids_choices = choices_values.get_uuids(); | ||
933 | 123 | for(auto iter = uuids_choices.begin(); iter != uuids_choices.end(); ++iter) | ||
934 | 124 | { | ||
935 | 125 | const auto& values = choices_values[(*iter)]; | ||
936 | 126 | |||
937 | 127 | if (values.is_valid() && values.get_type() == keeper::Item::FOLDER_VALUE) | ||
938 | 128 | { | ||
939 | 129 | auto display_name = values.get_display_name(); | ||
940 | 130 | auto dir_name = values.get_dir_name(); | ||
941 | 131 | |||
942 | 132 | auto section_name = QStringLiteral("%1:%2").arg(display_name).arg(dir_name); | ||
943 | 133 | auto index = unhandled_sections.indexOf(section_name); | ||
944 | 134 | if (index != -1) | ||
945 | 135 | { | ||
946 | 136 | // we have to restore this section | ||
947 | 137 | uuids << (*iter); | ||
948 | 138 | unhandled_sections.removeAt(index); | ||
949 | 139 | view_->add_task(display_name, "waiting", 0.0); | ||
950 | 140 | } | ||
951 | 141 | } | ||
952 | 142 | } | ||
953 | 143 | if (!unhandled_sections.isEmpty()) | ||
954 | 144 | { | ||
955 | 145 | QString error_message("The following sections were not found: \n"); | ||
956 | 146 | for (auto const & section : unhandled_sections) | ||
957 | 147 | { | ||
958 | 148 | error_message += QStringLiteral("\t %1 \n").arg(section); | ||
959 | 149 | } | ||
960 | 150 | view_->print_error_message(error_message); | ||
961 | 151 | exit(1); | ||
962 | 152 | } | ||
963 | 153 | |||
964 | 154 | for (auto const & uuid: uuids) | ||
965 | 155 | { | ||
966 | 156 | keeper_client_->enableRestore(uuid, true); | ||
967 | 157 | } | ||
968 | 158 | keeper_client_->startRestore(storage); | ||
969 | 159 | view_->start_printing_tasks(); | ||
970 | 160 | } | ||
971 | 161 | |||
972 | 162 | void CommandLineClient::run_cancel() const | ||
973 | 163 | { | ||
974 | 164 | keeper_client_->cancel(); | ||
975 | 165 | } | ||
976 | 166 | |||
977 | 167 | void CommandLineClient::list_backup_sections(keeper::Items const & choices_values) | ||
978 | 168 | { | ||
979 | 169 | QStringList sections; | ||
980 | 170 | for(auto iter = choices_values.begin(); iter != choices_values.end(); ++iter) | ||
981 | 171 | { | ||
982 | 172 | if ((*iter).is_valid() && (*iter).get_type() == keeper::Item::FOLDER_VALUE) | ||
983 | 173 | { | ||
984 | 174 | sections << (*iter).get_display_name(); | ||
985 | 175 | } | ||
986 | 176 | } | ||
987 | 177 | view_->print_sections(sections); | ||
988 | 178 | } | ||
989 | 179 | |||
990 | 180 | void CommandLineClient::list_restore_sections(keeper::Items const & choices_values) | ||
991 | 181 | { | ||
992 | 182 | QMap<QString, QList<keeper::Item>> values_per_dir; | ||
993 | 183 | |||
994 | 184 | for(auto iter = choices_values.begin(); iter != choices_values.end(); ++iter) | ||
995 | 185 | { | ||
996 | 186 | if ((*iter).is_valid() && (*iter).get_type() == keeper::Item::FOLDER_VALUE) | ||
997 | 187 | { | ||
998 | 188 | auto dir_name = (*iter).get_dir_name(); | ||
999 | 189 | if (!dir_name.isEmpty()) | ||
1000 | 190 | { | ||
1001 | 191 | values_per_dir[dir_name].push_back((*iter)); | ||
1002 | 192 | } | ||
1003 | 193 | } | ||
1004 | 194 | } | ||
1005 | 195 | |||
1006 | 196 | QStringList sections; | ||
1007 | 197 | for(auto iter = values_per_dir.begin(); iter != values_per_dir.end(); ++iter) | ||
1008 | 198 | { | ||
1009 | 199 | for(auto iter_items = (*iter).begin(); iter_items != (*iter).end(); ++iter_items) | ||
1010 | 200 | { | ||
1011 | 201 | const auto& values = (*iter_items); | ||
1012 | 202 | sections << QStringLiteral("%1:%2").arg(values.get_display_name()).arg(iter.key()); | ||
1013 | 203 | } | ||
1014 | 204 | sections << ""; | ||
1015 | 205 | } | ||
1016 | 206 | view_->print_sections(sections); | ||
1017 | 207 | } | ||
1018 | 208 | |||
1019 | 209 | void CommandLineClient::list_storage_accounts(QStringList const & accounts) | ||
1020 | 210 | { | ||
1021 | 211 | view_->print_sections(accounts); | ||
1022 | 212 | } | ||
1023 | 213 | |||
1024 | 214 | void CommandLineClient::on_progress_changed() | ||
1025 | 215 | { | ||
1026 | 216 | view_->progress_changed(keeper_client_->progress()); | ||
1027 | 217 | } | ||
1028 | 218 | |||
1029 | 219 | void CommandLineClient::on_status_changed() | ||
1030 | 220 | { | ||
1031 | 221 | view_->status_changed(keeper_client_->status()); | ||
1032 | 222 | } | ||
1033 | 223 | |||
1034 | 224 | void CommandLineClient::on_keeper_client_finished() | ||
1035 | 225 | { | ||
1036 | 226 | QCoreApplication::processEvents(); | ||
1037 | 227 | view_->show_info(); | ||
1038 | 228 | view_->clear_all(); | ||
1039 | 229 | QCoreApplication::exit(0); | ||
1040 | 230 | } | ||
1041 | 231 | |||
1042 | 232 | bool CommandLineClient::find_choice_value(QVariantMap const & choice, QString const & id, QVariant & value) | ||
1043 | 233 | { | ||
1044 | 234 | auto iter = choice.find(id); | ||
1045 | 235 | if (iter == choice.end()) | ||
1046 | 236 | return false; | ||
1047 | 237 | value = (*iter); | ||
1048 | 238 | return true; | ||
1049 | 239 | } | ||
1050 | 240 | |||
1051 | 241 | void CommandLineClient::check_for_choices_error(keeper::Error error) | ||
1052 | 242 | { | ||
1053 | 243 | if (error != keeper::Error::OK) | ||
1054 | 244 | { | ||
1055 | 245 | // an error occurred | ||
1056 | 246 | auto error_message = QStringLiteral("Error obtaining keeper choices: %1").arg(view_->get_error_string(error)); | ||
1057 | 247 | view_->print_error_message(error_message); | ||
1058 | 248 | return; | ||
1059 | 249 | } | ||
1060 | 250 | } | ||
1061 | 0 | 251 | ||
1062 | === added file 'src/cli/command-line-client.h' | |||
1063 | --- src/cli/command-line-client.h 1970-01-01 00:00:00 +0000 | |||
1064 | +++ src/cli/command-line-client.h 2017-02-27 19:05:17 +0000 | |||
1065 | @@ -0,0 +1,58 @@ | |||
1066 | 1 | /* | ||
1067 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1068 | 3 | * | ||
1069 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1070 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
1071 | 6 | * by the Free Software Foundation. | ||
1072 | 7 | * | ||
1073 | 8 | * This program is distributed in the hope that it will be useful, but | ||
1074 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1075 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1076 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
1077 | 12 | * | ||
1078 | 13 | * You should have received a copy of the GNU General Public License along | ||
1079 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1080 | 15 | * | ||
1081 | 16 | * Authors: | ||
1082 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
1083 | 18 | */ | ||
1084 | 19 | #pragma once | ||
1085 | 20 | |||
1086 | 21 | #include <QMap> | ||
1087 | 22 | #include <QObject> | ||
1088 | 23 | #include <QScopedPointer> | ||
1089 | 24 | #include <QTimer> | ||
1090 | 25 | #include "../../include/client/keeper-items.h" | ||
1091 | 26 | |||
1092 | 27 | class KeeperClient; | ||
1093 | 28 | class CommandLineClientView; | ||
1094 | 29 | |||
1095 | 30 | class CommandLineClient : public QObject | ||
1096 | 31 | { | ||
1097 | 32 | Q_OBJECT | ||
1098 | 33 | public: | ||
1099 | 34 | explicit CommandLineClient(QObject * parent = nullptr); | ||
1100 | 35 | ~CommandLineClient(); | ||
1101 | 36 | |||
1102 | 37 | Q_DISABLE_COPY(CommandLineClient) | ||
1103 | 38 | |||
1104 | 39 | void run_list_sections(bool remote, QString const & storage = ""); | ||
1105 | 40 | void run_list_storage_accounts(); | ||
1106 | 41 | void run_backup(QStringList & sections, QString const & storage); | ||
1107 | 42 | void run_restore(QStringList & sections, QString const & storage); | ||
1108 | 43 | void run_cancel() const; | ||
1109 | 44 | |||
1110 | 45 | private Q_SLOTS: | ||
1111 | 46 | void on_progress_changed(); | ||
1112 | 47 | void on_status_changed(); | ||
1113 | 48 | void on_keeper_client_finished(); | ||
1114 | 49 | |||
1115 | 50 | private: | ||
1116 | 51 | bool find_choice_value(QVariantMap const & choice, QString const & id, QVariant & value); | ||
1117 | 52 | void list_backup_sections(keeper::Items const & choices); | ||
1118 | 53 | void list_restore_sections(keeper::Items const & choices); | ||
1119 | 54 | void list_storage_accounts(QStringList const & accounts); | ||
1120 | 55 | void check_for_choices_error(keeper::Error error); | ||
1121 | 56 | QScopedPointer<KeeperClient> keeper_client_; | ||
1122 | 57 | QScopedPointer<CommandLineClientView> view_; | ||
1123 | 58 | }; | ||
1124 | 0 | 59 | ||
1125 | === added file 'src/cli/command-line.cpp' | |||
1126 | --- src/cli/command-line.cpp 1970-01-01 00:00:00 +0000 | |||
1127 | +++ src/cli/command-line.cpp 2017-02-27 19:05:17 +0000 | |||
1128 | @@ -0,0 +1,234 @@ | |||
1129 | 1 | /* | ||
1130 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1131 | 3 | * | ||
1132 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1133 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
1134 | 6 | * by the Free Software Foundation. | ||
1135 | 7 | * | ||
1136 | 8 | * This program is distributed in the hope that it will be useful, but | ||
1137 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1138 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1139 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
1140 | 12 | * | ||
1141 | 13 | * You should have received a copy of the GNU General Public License along | ||
1142 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1143 | 15 | * | ||
1144 | 16 | * Authors: | ||
1145 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
1146 | 18 | */ | ||
1147 | 19 | #include "command-line.h" | ||
1148 | 20 | |||
1149 | 21 | #include <QCommandLineParser> | ||
1150 | 22 | #include <QDebug> | ||
1151 | 23 | |||
1152 | 24 | #include <iostream> | ||
1153 | 25 | |||
1154 | 26 | namespace | ||
1155 | 27 | { | ||
1156 | 28 | // arguments | ||
1157 | 29 | constexpr const char ARGUMENT_LIST_SECTIONS[] = "list-sections"; | ||
1158 | 30 | constexpr const char ARGUMENT_LIST_STORAGE_ACCOUNTS[] = "list-storage-configs"; | ||
1159 | 31 | constexpr const char ARGUMENT_BACKUP[] = "backup"; | ||
1160 | 32 | constexpr const char ARGUMENT_RESTORE[] = "restore"; | ||
1161 | 33 | |||
1162 | 34 | // argument descriptions | ||
1163 | 35 | constexpr const char ARGUMENT_LIST_SECTIONS_DESCRIPTION[] = "List the sections available to backup"; | ||
1164 | 36 | constexpr const char ARGUMENT_LIST_STORAGE_ACCOUNTS_DESCRIPTION[] = "List the available storage accounts"; | ||
1165 | 37 | constexpr const char ARGUMENT_BACKUP_DESCRIPTION[] = "Starts a backup"; | ||
1166 | 38 | constexpr const char ARGUMENT_RESTORE_DESCRIPTION[] = "Starts a restore"; | ||
1167 | 39 | |||
1168 | 40 | // options | ||
1169 | 41 | constexpr const char OPTION_STORAGE[] = "storage"; | ||
1170 | 42 | constexpr const char OPTION_SECTIONS[] = "sections"; | ||
1171 | 43 | |||
1172 | 44 | // option descriptions | ||
1173 | 45 | constexpr const char OPTION_STORAGE_DESCRIPTION[] = "Defines the available storage to use. Pass 'default' to use the default one"; | ||
1174 | 46 | constexpr const char OPTION_SECTIONS_DESCRIPTION[] = "Lists the sections to backup or restore"; | ||
1175 | 47 | } | ||
1176 | 48 | |||
1177 | 49 | CommandLineParser::CommandLineParser() | ||
1178 | 50 | : parser_(new QCommandLineParser) | ||
1179 | 51 | { | ||
1180 | 52 | parser_->setApplicationDescription("Keeper command line client"); | ||
1181 | 53 | parser_->addHelpOption(); | ||
1182 | 54 | parser_->addVersionOption(); | ||
1183 | 55 | parser_->addPositionalArgument(ARGUMENT_LIST_SECTIONS, QCoreApplication::translate("main", ARGUMENT_LIST_SECTIONS_DESCRIPTION)); | ||
1184 | 56 | parser_->addPositionalArgument(ARGUMENT_LIST_STORAGE_ACCOUNTS, QCoreApplication::translate("main", ARGUMENT_LIST_STORAGE_ACCOUNTS_DESCRIPTION)); | ||
1185 | 57 | parser_->addPositionalArgument(ARGUMENT_BACKUP, QCoreApplication::translate("main", ARGUMENT_BACKUP_DESCRIPTION)); | ||
1186 | 58 | parser_->addPositionalArgument(ARGUMENT_RESTORE, QCoreApplication::translate("main", ARGUMENT_RESTORE_DESCRIPTION)); | ||
1187 | 59 | } | ||
1188 | 60 | |||
1189 | 61 | bool CommandLineParser::parse(QStringList const & arguments, QCoreApplication const & app, CommandLineParser::CommandArgs & cmd_args) | ||
1190 | 62 | { | ||
1191 | 63 | parser_->parse(arguments); | ||
1192 | 64 | const QStringList args = parser_->positionalArguments(); | ||
1193 | 65 | if (!check_number_of_args(args)) | ||
1194 | 66 | { | ||
1195 | 67 | return false; | ||
1196 | 68 | } | ||
1197 | 69 | |||
1198 | 70 | if (args.size() == 1) | ||
1199 | 71 | { | ||
1200 | 72 | // if something fails at the process call the process exists | ||
1201 | 73 | if (args.at(0) == ARGUMENT_LIST_SECTIONS) | ||
1202 | 74 | { | ||
1203 | 75 | return handle_list_sections(app, cmd_args); | ||
1204 | 76 | } | ||
1205 | 77 | else if (args.at(0) == ARGUMENT_LIST_STORAGE_ACCOUNTS) | ||
1206 | 78 | { | ||
1207 | 79 | return handle_list_storage_accounts(app, cmd_args); | ||
1208 | 80 | } | ||
1209 | 81 | else if (args.at(0) == ARGUMENT_BACKUP) | ||
1210 | 82 | { | ||
1211 | 83 | return handle_backup(app, cmd_args); | ||
1212 | 84 | } | ||
1213 | 85 | else if (args.at(0) == ARGUMENT_RESTORE) | ||
1214 | 86 | { | ||
1215 | 87 | return handle_restore(app, cmd_args); | ||
1216 | 88 | } | ||
1217 | 89 | else | ||
1218 | 90 | { | ||
1219 | 91 | std::cerr << "Bad argument." << std::endl; | ||
1220 | 92 | std::cerr << parser_->errorText().toStdString() << std::endl; | ||
1221 | 93 | exit(1); | ||
1222 | 94 | } | ||
1223 | 95 | } | ||
1224 | 96 | else | ||
1225 | 97 | { | ||
1226 | 98 | qDebug() << "More or none arguments"; | ||
1227 | 99 | // maybe we have the version or help options | ||
1228 | 100 | parser_->process(app); | ||
1229 | 101 | } | ||
1230 | 102 | |||
1231 | 103 | return false; | ||
1232 | 104 | } | ||
1233 | 105 | |||
1234 | 106 | bool CommandLineParser::handle_list_sections(QCoreApplication const & app, CommandLineParser::CommandArgs & cmd_args) | ||
1235 | 107 | { | ||
1236 | 108 | parser_->clearPositionalArguments(); | ||
1237 | 109 | parser_->addPositionalArgument(ARGUMENT_LIST_SECTIONS, QCoreApplication::translate("main", ARGUMENT_LIST_SECTIONS_DESCRIPTION)); | ||
1238 | 110 | |||
1239 | 111 | parser_->addOptions({ | ||
1240 | 112 | {{"r", OPTION_STORAGE}, | ||
1241 | 113 | QCoreApplication::translate("main", OPTION_STORAGE_DESCRIPTION), | ||
1242 | 114 | QCoreApplication::translate("main", OPTION_STORAGE_DESCRIPTION) | ||
1243 | 115 | }, | ||
1244 | 116 | }); | ||
1245 | 117 | parser_->process(app); | ||
1246 | 118 | |||
1247 | 119 | // it didn't exit... we're good | ||
1248 | 120 | cmd_args.sections.clear(); | ||
1249 | 121 | cmd_args.storage.clear(); | ||
1250 | 122 | if (parser_->isSet(OPTION_STORAGE)) | ||
1251 | 123 | { | ||
1252 | 124 | cmd_args.cmd = CommandLineParser::Command::LIST_REMOTE_SECTIONS; | ||
1253 | 125 | cmd_args.storage = get_storage_string(parser_->value(OPTION_STORAGE)); | ||
1254 | 126 | } | ||
1255 | 127 | else | ||
1256 | 128 | { | ||
1257 | 129 | cmd_args.cmd = CommandLineParser::Command::LIST_LOCAL_SECTIONS; | ||
1258 | 130 | } | ||
1259 | 131 | |||
1260 | 132 | return true; | ||
1261 | 133 | } | ||
1262 | 134 | |||
1263 | 135 | bool CommandLineParser::handle_list_storage_accounts(QCoreApplication const & app, CommandArgs & cmd_args) | ||
1264 | 136 | { | ||
1265 | 137 | parser_->process(app); | ||
1266 | 138 | // it didn't exit... we're good | ||
1267 | 139 | cmd_args.sections.clear(); | ||
1268 | 140 | cmd_args.storage.clear(); | ||
1269 | 141 | cmd_args.cmd = CommandLineParser::Command::LIST_STORAGE_ACCOUNTS; | ||
1270 | 142 | |||
1271 | 143 | return true; | ||
1272 | 144 | } | ||
1273 | 145 | |||
1274 | 146 | bool CommandLineParser::handle_backup(QCoreApplication const & app, CommandLineParser::CommandArgs & cmd_args) | ||
1275 | 147 | { | ||
1276 | 148 | parser_->clearPositionalArguments(); | ||
1277 | 149 | parser_->addPositionalArgument(ARGUMENT_BACKUP, QCoreApplication::translate("main", ARGUMENT_BACKUP_DESCRIPTION)); | ||
1278 | 150 | |||
1279 | 151 | parser_->addOptions({ | ||
1280 | 152 | {{"s", OPTION_SECTIONS}, | ||
1281 | 153 | QCoreApplication::translate("main", OPTION_SECTIONS_DESCRIPTION), | ||
1282 | 154 | QCoreApplication::translate("main", OPTION_SECTIONS_DESCRIPTION) | ||
1283 | 155 | }, | ||
1284 | 156 | {{"r", OPTION_STORAGE}, | ||
1285 | 157 | QCoreApplication::translate("main", OPTION_STORAGE_DESCRIPTION), | ||
1286 | 158 | QCoreApplication::translate("main", OPTION_STORAGE_DESCRIPTION) | ||
1287 | 159 | }, | ||
1288 | 160 | }); | ||
1289 | 161 | parser_->process(app); | ||
1290 | 162 | |||
1291 | 163 | // it didn't exit... we're good | ||
1292 | 164 | cmd_args.sections.clear(); | ||
1293 | 165 | cmd_args.storage.clear(); | ||
1294 | 166 | cmd_args.cmd = CommandLineParser::Command::BACKUP; | ||
1295 | 167 | if (!parser_->isSet(OPTION_SECTIONS)) | ||
1296 | 168 | { | ||
1297 | 169 | std::cerr << "You need to specify some sections to run a backup." << std::endl; | ||
1298 | 170 | return false; | ||
1299 | 171 | } | ||
1300 | 172 | if (parser_->isSet(OPTION_STORAGE)) | ||
1301 | 173 | { | ||
1302 | 174 | cmd_args.storage = get_storage_string(parser_->value(OPTION_STORAGE)); | ||
1303 | 175 | } | ||
1304 | 176 | cmd_args.sections = parser_->value(OPTION_SECTIONS).split(','); | ||
1305 | 177 | |||
1306 | 178 | return true; | ||
1307 | 179 | } | ||
1308 | 180 | |||
1309 | 181 | bool CommandLineParser::handle_restore(QCoreApplication const & app, CommandLineParser::CommandArgs & cmd_args) | ||
1310 | 182 | { | ||
1311 | 183 | parser_->clearPositionalArguments(); | ||
1312 | 184 | parser_->addPositionalArgument(ARGUMENT_RESTORE, QCoreApplication::translate("main", ARGUMENT_RESTORE_DESCRIPTION)); | ||
1313 | 185 | |||
1314 | 186 | parser_->addOptions({ | ||
1315 | 187 | {{"s", OPTION_SECTIONS}, | ||
1316 | 188 | QCoreApplication::translate("main", OPTION_SECTIONS_DESCRIPTION), | ||
1317 | 189 | QCoreApplication::translate("main", OPTION_SECTIONS_DESCRIPTION) | ||
1318 | 190 | }, | ||
1319 | 191 | {{"r", OPTION_STORAGE}, | ||
1320 | 192 | QCoreApplication::translate("main", OPTION_STORAGE_DESCRIPTION), | ||
1321 | 193 | QCoreApplication::translate("main", OPTION_STORAGE_DESCRIPTION) | ||
1322 | 194 | }, | ||
1323 | 195 | }); | ||
1324 | 196 | parser_->process(app); | ||
1325 | 197 | |||
1326 | 198 | // it didn't exit... we're good | ||
1327 | 199 | cmd_args.sections.clear(); | ||
1328 | 200 | cmd_args.storage.clear(); | ||
1329 | 201 | cmd_args.cmd = CommandLineParser::Command::RESTORE; | ||
1330 | 202 | if (!parser_->isSet(OPTION_SECTIONS)) | ||
1331 | 203 | { | ||
1332 | 204 | std::cerr << "You need to specify some sections to run a restore." << std::endl; | ||
1333 | 205 | return false; | ||
1334 | 206 | } | ||
1335 | 207 | if (parser_->isSet(OPTION_STORAGE)) | ||
1336 | 208 | { | ||
1337 | 209 | cmd_args.storage = get_storage_string(parser_->value(OPTION_STORAGE)); | ||
1338 | 210 | } | ||
1339 | 211 | cmd_args.sections = parser_->value(OPTION_SECTIONS).split(','); | ||
1340 | 212 | |||
1341 | 213 | return true; | ||
1342 | 214 | } | ||
1343 | 215 | |||
1344 | 216 | bool CommandLineParser::check_number_of_args(QStringList const & args) | ||
1345 | 217 | { | ||
1346 | 218 | if (args.size() > 1) | ||
1347 | 219 | { | ||
1348 | 220 | std::cerr << "Please, pass only one argument." << std::endl; | ||
1349 | 221 | std::cerr << parser_->helpText().toStdString() << std::endl; | ||
1350 | 222 | return false; | ||
1351 | 223 | } | ||
1352 | 224 | return true; | ||
1353 | 225 | } | ||
1354 | 226 | |||
1355 | 227 | QString CommandLineParser::get_storage_string(QString const & value) | ||
1356 | 228 | { | ||
1357 | 229 | if (value == "default") | ||
1358 | 230 | { | ||
1359 | 231 | return QString(); | ||
1360 | 232 | } | ||
1361 | 233 | return value; | ||
1362 | 234 | } | ||
1363 | 0 | 235 | ||
1364 | === added file 'src/cli/command-line.h' | |||
1365 | --- src/cli/command-line.h 1970-01-01 00:00:00 +0000 | |||
1366 | +++ src/cli/command-line.h 2017-02-27 19:05:17 +0000 | |||
1367 | @@ -0,0 +1,55 @@ | |||
1368 | 1 | /* | ||
1369 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1370 | 3 | * | ||
1371 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1372 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
1373 | 6 | * by the Free Software Foundation. | ||
1374 | 7 | * | ||
1375 | 8 | * This program is distributed in the hope that it will be useful, but | ||
1376 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1377 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1378 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
1379 | 12 | * | ||
1380 | 13 | * You should have received a copy of the GNU General Public License along | ||
1381 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1382 | 15 | * | ||
1383 | 16 | * Authors: | ||
1384 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
1385 | 18 | */ | ||
1386 | 19 | #pragma once | ||
1387 | 20 | |||
1388 | 21 | #include <QCoreApplication> | ||
1389 | 22 | #include <QSharedPointer> | ||
1390 | 23 | |||
1391 | 24 | class QCommandLineParser; | ||
1392 | 25 | |||
1393 | 26 | class CommandLineParser | ||
1394 | 27 | { | ||
1395 | 28 | public: | ||
1396 | 29 | Q_ENUMS(Command) | ||
1397 | 30 | enum class Command {LIST_LOCAL_SECTIONS, LIST_REMOTE_SECTIONS, LIST_STORAGE_ACCOUNTS, BACKUP, RESTORE}; | ||
1398 | 31 | struct CommandArgs | ||
1399 | 32 | { | ||
1400 | 33 | Command cmd; | ||
1401 | 34 | QStringList sections; | ||
1402 | 35 | QString storage; | ||
1403 | 36 | }; | ||
1404 | 37 | |||
1405 | 38 | CommandLineParser(); | ||
1406 | 39 | ~CommandLineParser() = default; | ||
1407 | 40 | Q_DISABLE_COPY(CommandLineParser) | ||
1408 | 41 | |||
1409 | 42 | bool parse(QStringList const & arguments, QCoreApplication const & app, CommandArgs & cmd_args); | ||
1410 | 43 | |||
1411 | 44 | private: | ||
1412 | 45 | bool handle_list_sections(QCoreApplication const & app, CommandArgs & cmd_args); | ||
1413 | 46 | bool handle_list_storage_accounts(QCoreApplication const & app, CommandArgs & cmd_args); | ||
1414 | 47 | bool handle_backup(QCoreApplication const & app, CommandArgs & cmd_args); | ||
1415 | 48 | bool handle_restore(QCoreApplication const & app, CommandArgs & cmd_args); | ||
1416 | 49 | |||
1417 | 50 | bool check_number_of_args(QStringList const & args); | ||
1418 | 51 | |||
1419 | 52 | QString get_storage_string(QString const & value); | ||
1420 | 53 | |||
1421 | 54 | QSharedPointer<QCommandLineParser> parser_; | ||
1422 | 55 | }; | ||
1423 | 0 | 56 | ||
1424 | === modified file 'src/cli/main.cpp' | |||
1425 | --- src/cli/main.cpp 2016-08-30 14:16:19 +0000 | |||
1426 | +++ src/cli/main.cpp 2017-02-27 19:05:17 +0000 | |||
1427 | @@ -17,9 +17,12 @@ | |||
1428 | 17 | * Charles Kerr <charles.kerr@canonical.com> | 17 | * Charles Kerr <charles.kerr@canonical.com> |
1429 | 18 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | 18 | * Xavi Garcia <xavi.garcia.mena@canonical.com> |
1430 | 19 | */ | 19 | */ |
1431 | 20 | #include "command-line.h" | ||
1432 | 21 | #include "command-line-client.h" | ||
1433 | 20 | 22 | ||
1434 | 21 | #include <dbus-types.h> | 23 | #include <dbus-types.h> |
1435 | 22 | #include <util/logging.h> | 24 | #include <util/logging.h> |
1436 | 25 | #include "util/unix-signal-handler.h" | ||
1437 | 23 | 26 | ||
1438 | 24 | #include <keeper_user_interface.h> | 27 | #include <keeper_user_interface.h> |
1439 | 25 | 28 | ||
1440 | @@ -29,6 +32,8 @@ | |||
1441 | 29 | #include <libintl.h> | 32 | #include <libintl.h> |
1442 | 30 | #include <cstdlib> | 33 | #include <cstdlib> |
1443 | 31 | #include <ctime> | 34 | #include <ctime> |
1444 | 35 | #include <iostream> | ||
1445 | 36 | |||
1446 | 32 | 37 | ||
1447 | 33 | int | 38 | int |
1448 | 34 | main(int argc, char **argv) | 39 | main(int argc, char **argv) |
1449 | @@ -37,60 +42,49 @@ | |||
1450 | 37 | 42 | ||
1451 | 38 | QCoreApplication app(argc, argv); | 43 | QCoreApplication app(argc, argv); |
1452 | 39 | DBusTypes::registerMetaTypes(); | 44 | DBusTypes::registerMetaTypes(); |
1453 | 40 | // Variant::registerMetaTypes(); | ||
1454 | 41 | std::srand(unsigned(std::time(nullptr))); | 45 | std::srand(unsigned(std::time(nullptr))); |
1455 | 42 | 46 | ||
1456 | 47 | util::UnixSignalHandler handler([]{ | ||
1457 | 48 | CommandLineClient client; | ||
1458 | 49 | client.run_cancel(); | ||
1459 | 50 | }); | ||
1460 | 51 | handler.setupUnixSignalHandlers(); | ||
1461 | 52 | |||
1462 | 43 | // boilerplate locale | 53 | // boilerplate locale |
1463 | 44 | bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); | 54 | bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); |
1464 | 45 | setlocale(LC_ALL, ""); | 55 | setlocale(LC_ALL, ""); |
1465 | 46 | bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); | 56 | bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); |
1466 | 47 | textdomain(GETTEXT_PACKAGE); | 57 | textdomain(GETTEXT_PACKAGE); |
1467 | 48 | 58 | ||
1513 | 49 | if (argc == 2 && QString("--print-address") == argv[1]) | 59 | QCoreApplication::setApplicationName("keeper"); |
1514 | 50 | { | 60 | QCoreApplication::setApplicationVersion("1.0"); |
1515 | 51 | qDebug() << QDBusConnection::sessionBus().baseService(); | 61 | |
1516 | 52 | } | 62 | CommandLineParser parser; |
1517 | 53 | 63 | CommandLineClient client; | |
1518 | 54 | qDebug() << "Argc =" << argc; | 64 | CommandLineParser::CommandArgs cmd_args; |
1519 | 55 | if (argc == 2 && QString("--use-uuids") == argv[1]) | 65 | if (parser.parse(QCoreApplication::arguments(), app, cmd_args)) |
1520 | 56 | { | 66 | { |
1521 | 57 | QScopedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser( | 67 | switch(cmd_args.cmd) |
1522 | 58 | DBusTypes::KEEPER_SERVICE, | 68 | { |
1523 | 59 | DBusTypes::KEEPER_USER_PATH, | 69 | case CommandLineParser::Command::LIST_LOCAL_SECTIONS: |
1524 | 60 | QDBusConnection::sessionBus() | 70 | client.run_list_sections(false); |
1525 | 61 | ) ); | 71 | exit(0); |
1526 | 62 | QDBusReply<QVariantDictMap> choices = user_iface->call("GetBackupChoices"); | 72 | break; |
1527 | 63 | if (!choices.isValid()) | 73 | case CommandLineParser::Command::LIST_STORAGE_ACCOUNTS: |
1528 | 64 | { | 74 | client.run_list_storage_accounts(); |
1529 | 65 | qWarning() << "Error getting backup choices:" << choices.error().message(); | 75 | exit(0); |
1530 | 66 | } | 76 | break; |
1531 | 67 | 77 | case CommandLineParser::Command::LIST_REMOTE_SECTIONS: | |
1532 | 68 | QStringList uuids; | 78 | client.run_list_sections(true, cmd_args.storage); |
1533 | 69 | auto choices_values = choices.value(); | 79 | exit(0); |
1534 | 70 | for(auto iter = choices_values.begin(); iter != choices_values.end(); ++iter) | 80 | break; |
1535 | 71 | { | 81 | case CommandLineParser::Command::BACKUP: |
1536 | 72 | const auto& values = iter.value(); | 82 | client.run_backup(cmd_args.sections, cmd_args.storage); |
1537 | 73 | auto iter_values = values.find("type"); | 83 | break; |
1538 | 74 | if (iter_values != values.end()) | 84 | case CommandLineParser::Command::RESTORE: |
1539 | 75 | { | 85 | client.run_restore(cmd_args.sections, cmd_args.storage); |
1540 | 76 | if (iter_values.value().toString() == "folder") | 86 | break; |
1541 | 77 | { | 87 | }; |
1497 | 78 | qDebug() << "Adding uuid" << iter.key() << "with type:" << "folder"; | ||
1498 | 79 | uuids << iter.key(); | ||
1499 | 80 | } | ||
1500 | 81 | } | ||
1501 | 82 | } | ||
1502 | 83 | |||
1503 | 84 | QDBusReply<void> backup_reply = user_iface->call("StartBackup", uuids); | ||
1504 | 85 | |||
1505 | 86 | if (!backup_reply.isValid()) | ||
1506 | 87 | { | ||
1507 | 88 | qWarning() << "Error starting backup:" << backup_reply.error().message(); | ||
1508 | 89 | } | ||
1509 | 90 | } | ||
1510 | 91 | else | ||
1511 | 92 | { | ||
1512 | 93 | qWarning() << "FIXME"; | ||
1542 | 94 | } | 88 | } |
1543 | 95 | 89 | ||
1544 | 96 | 90 | ||
1545 | 97 | 91 | ||
1546 | === modified file 'src/client/CMakeLists.txt' | |||
1547 | --- src/client/CMakeLists.txt 2016-08-26 09:30:11 +0000 | |||
1548 | +++ src/client/CMakeLists.txt 2017-02-27 19:05:17 +0000 | |||
1549 | @@ -1,8 +1,24 @@ | |||
1550 | 1 | add_subdirectory(qml-plugin) | 1 | add_subdirectory(qml-plugin) |
1551 | 2 | 2 | ||
1552 | 3 | set( | 3 | set( |
1553 | 4 | KEEPER_ERRORS_LIB | ||
1554 | 5 | keeper-errors-lib | ||
1555 | 6 | ) | ||
1556 | 7 | |||
1557 | 8 | add_library( | ||
1558 | 9 | ${KEEPER_ERRORS_LIB} | ||
1559 | 10 | STATIC | ||
1560 | 11 | keeper-errors.cpp | ||
1561 | 12 | ${CMAKE_SOURCE_DIR}/include/client/keeper-errors.h | ||
1562 | 13 | ${CMAKE_SOURCE_DIR}/include/client/keeper-items.h | ||
1563 | 14 | items.cpp | ||
1564 | 15 | ) | ||
1565 | 16 | |||
1566 | 17 | set( | ||
1567 | 4 | CLIENT_HEADERS | 18 | CLIENT_HEADERS |
1568 | 5 | ${CMAKE_SOURCE_DIR}/include/client/client.h | 19 | ${CMAKE_SOURCE_DIR}/include/client/client.h |
1569 | 20 | ${CMAKE_SOURCE_DIR}/include/client/keeper-errors.h | ||
1570 | 21 | ${CMAKE_SOURCE_DIR}/include/client/keeper-items.h | ||
1571 | 6 | ) | 22 | ) |
1572 | 7 | 23 | ||
1573 | 8 | add_library( | 24 | add_library( |
1574 | @@ -11,8 +27,14 @@ | |||
1575 | 11 | ${CLIENT_HEADERS} | 27 | ${CLIENT_HEADERS} |
1576 | 12 | ) | 28 | ) |
1577 | 13 | 29 | ||
1578 | 30 | set_target_properties(${KEEPER_CLIENT_LIB} PROPERTIES | ||
1579 | 31 | AUTOMOC TRUE | ||
1580 | 32 | LINK_FLAGS "-Wl,--no-undefined" | ||
1581 | 33 | ) | ||
1582 | 34 | |||
1583 | 14 | target_link_libraries( | 35 | target_link_libraries( |
1584 | 15 | ${KEEPER_CLIENT_LIB} | 36 | ${KEEPER_CLIENT_LIB} |
1585 | 37 | ${KEEPER_ERRORS_LIB} | ||
1586 | 16 | qdbus-stubs | 38 | qdbus-stubs |
1587 | 17 | Qt5::Core | 39 | Qt5::Core |
1588 | 18 | Qt5::DBus | 40 | Qt5::DBus |
1589 | 19 | 41 | ||
1590 | === modified file 'src/client/client.cpp' | |||
1591 | --- src/client/client.cpp 2016-08-26 08:48:05 +0000 | |||
1592 | +++ src/client/client.cpp 2017-02-27 19:05:17 +0000 | |||
1593 | @@ -22,34 +22,100 @@ | |||
1594 | 22 | #include <client/client.h> | 22 | #include <client/client.h> |
1595 | 23 | 23 | ||
1596 | 24 | #include <qdbus-stubs/keeper_user_interface.h> | 24 | #include <qdbus-stubs/keeper_user_interface.h> |
1597 | 25 | #include <qdbus-stubs/DBusPropertiesInterface.h> | ||
1598 | 26 | #include <qdbus-stubs/dbus-types.h> | ||
1599 | 25 | 27 | ||
1600 | 26 | struct KeeperClientPrivate final | 28 | struct KeeperClientPrivate final |
1601 | 27 | { | 29 | { |
1602 | 28 | Q_DISABLE_COPY(KeeperClientPrivate) | 30 | Q_DISABLE_COPY(KeeperClientPrivate) |
1603 | 29 | 31 | ||
1605 | 30 | KeeperClientPrivate(QObject* parent) | 32 | enum class TasksMode { IDLE_MODE, BACKUP_MODE, RESTORE_MODE }; |
1606 | 33 | |||
1607 | 34 | explicit KeeperClientPrivate(QObject* /* parent */) | ||
1608 | 31 | : userIface(new DBusInterfaceKeeperUser( | 35 | : userIface(new DBusInterfaceKeeperUser( |
1609 | 32 | DBusTypes::KEEPER_SERVICE, | 36 | DBusTypes::KEEPER_SERVICE, |
1610 | 33 | DBusTypes::KEEPER_USER_PATH, | 37 | DBusTypes::KEEPER_USER_PATH, |
1611 | 34 | QDBusConnection::sessionBus() | 38 | QDBusConnection::sessionBus() |
1618 | 35 | )), | 39 | )) |
1619 | 36 | status(""), | 40 | , propertiesIface(new DBusPropertiesInterface( |
1620 | 37 | progress(0), | 41 | DBusTypes::KEEPER_SERVICE, |
1621 | 38 | readyToBackup(false), | 42 | DBusTypes::KEEPER_USER_PATH, |
1622 | 39 | backupBusy(false), | 43 | QDBusConnection::sessionBus() |
1623 | 40 | stateTimer(parent) | 44 | )) |
1624 | 41 | { | 45 | { |
1625 | 42 | } | 46 | } |
1626 | 43 | 47 | ||
1627 | 44 | ~KeeperClientPrivate() = default; | 48 | ~KeeperClientPrivate() = default; |
1628 | 45 | 49 | ||
1629 | 50 | struct TaskStatus | ||
1630 | 51 | { | ||
1631 | 52 | QString status; | ||
1632 | 53 | double percentage; | ||
1633 | 54 | }; | ||
1634 | 55 | |||
1635 | 56 | static bool stateIsFinal(QString const & stateString) | ||
1636 | 57 | { | ||
1637 | 58 | return (stateString == "complete" || stateString == "cancelled" || stateString == "failed"); | ||
1638 | 59 | } | ||
1639 | 60 | |||
1640 | 61 | bool checkAllTasksFinished(keeper::Items const & state) const | ||
1641 | 62 | { | ||
1642 | 63 | bool ret = true; | ||
1643 | 64 | for (auto iter = state.begin(); ret && (iter != state.end()); ++iter) | ||
1644 | 65 | { | ||
1645 | 66 | auto statusString = (*iter).get_status(); | ||
1646 | 67 | ret = stateIsFinal(statusString); | ||
1647 | 68 | } | ||
1648 | 69 | return ret; | ||
1649 | 70 | } | ||
1650 | 71 | |||
1651 | 72 | static keeper::Items getValue(QDBusMessage const & message, keeper::Error & error) | ||
1652 | 73 | { | ||
1653 | 74 | if (message.errorMessage().isEmpty()) | ||
1654 | 75 | { | ||
1655 | 76 | if (message.arguments().count() != 1) | ||
1656 | 77 | { | ||
1657 | 78 | error = keeper::Error::UNKNOWN; | ||
1658 | 79 | return keeper::Items(); | ||
1659 | 80 | } | ||
1660 | 81 | |||
1661 | 82 | auto value = message.arguments().at(0); | ||
1662 | 83 | if (value.typeName() != QStringLiteral("QDBusArgument")) | ||
1663 | 84 | { | ||
1664 | 85 | error = keeper::Error::UNKNOWN; | ||
1665 | 86 | return keeper::Items(); | ||
1666 | 87 | } | ||
1667 | 88 | auto dbus_arg = value.value<QDBusArgument>(); | ||
1668 | 89 | error = keeper::Error::OK; | ||
1669 | 90 | keeper::Items ret; | ||
1670 | 91 | dbus_arg >> ret; | ||
1671 | 92 | return ret; | ||
1672 | 93 | } | ||
1673 | 94 | if (message.arguments().count() != 2) | ||
1674 | 95 | { | ||
1675 | 96 | error = keeper::Error::UNKNOWN; | ||
1676 | 97 | return keeper::Items(); | ||
1677 | 98 | } | ||
1678 | 99 | |||
1679 | 100 | // pick up the error | ||
1680 | 101 | bool valid; | ||
1681 | 102 | error = keeper::convert_from_dbus_variant(message.arguments().at(1), &valid); | ||
1682 | 103 | if (!valid) | ||
1683 | 104 | { | ||
1684 | 105 | error = keeper::Error::UNKNOWN; | ||
1685 | 106 | } | ||
1686 | 107 | return keeper::Items(); | ||
1687 | 108 | } | ||
1688 | 109 | |||
1689 | 46 | QScopedPointer<DBusInterfaceKeeperUser> userIface; | 110 | QScopedPointer<DBusInterfaceKeeperUser> userIface; |
1690 | 111 | QScopedPointer<DBusPropertiesInterface> propertiesIface; | ||
1691 | 47 | QString status; | 112 | QString status; |
1697 | 48 | QMap<QString, QVariantMap> backups; | 113 | keeper::Items backups; |
1698 | 49 | double progress; | 114 | double progress = 0; |
1699 | 50 | bool readyToBackup; | 115 | bool readyToBackup = false; |
1700 | 51 | bool backupBusy; | 116 | bool backupBusy = false; |
1701 | 52 | QTimer stateTimer; | 117 | QMap<QString, TaskStatus> taskStatus; |
1702 | 118 | TasksMode mode = TasksMode::IDLE_MODE; | ||
1703 | 53 | }; | 119 | }; |
1704 | 54 | 120 | ||
1705 | 55 | KeeperClient::KeeperClient(QObject* parent) : | 121 | KeeperClient::KeeperClient(QObject* parent) : |
1706 | @@ -60,13 +126,15 @@ | |||
1707 | 60 | 126 | ||
1708 | 61 | // Store backups list locally with an additional "enabled" pair to keep track enabled states | 127 | // Store backups list locally with an additional "enabled" pair to keep track enabled states |
1709 | 62 | // TODO: We should be listening to a backupChoicesChanged signal to keep this list updated | 128 | // TODO: We should be listening to a backupChoicesChanged signal to keep this list updated |
1711 | 63 | d->backups = getBackupChoices(); | 129 | keeper::Error error; |
1712 | 130 | d->backups = getBackupChoices(error); | ||
1713 | 131 | |||
1714 | 64 | for(auto iter = d->backups.begin(); iter != d->backups.end(); ++iter) | 132 | for(auto iter = d->backups.begin(); iter != d->backups.end(); ++iter) |
1715 | 65 | { | 133 | { |
1716 | 66 | iter.value()["enabled"] = false; | 134 | iter.value()["enabled"] = false; |
1717 | 67 | } | 135 | } |
1718 | 68 | 136 | ||
1720 | 69 | connect(&d->stateTimer, &QTimer::timeout, this, &KeeperClient::stateUpdated); | 137 | connect(d->propertiesIface.data(), &DBusPropertiesInterface::PropertiesChanged, this, &KeeperClient::stateUpdated); |
1721 | 70 | } | 138 | } |
1722 | 71 | 139 | ||
1723 | 72 | KeeperClient::~KeeperClient() = default; | 140 | KeeperClient::~KeeperClient() = default; |
1724 | @@ -77,7 +145,7 @@ | |||
1725 | 77 | for(auto iter = d->backups.begin(); iter != d->backups.end(); ++iter) | 145 | for(auto iter = d->backups.begin(); iter != d->backups.end(); ++iter) |
1726 | 78 | { | 146 | { |
1727 | 79 | // TODO: We currently only support "folder" type backups | 147 | // TODO: We currently only support "folder" type backups |
1729 | 80 | if (iter.value().value("type").toString() == "folder") | 148 | if (iter.value().get_type() == keeper::Item::FOLDER_VALUE) |
1730 | 81 | { | 149 | { |
1731 | 82 | returnList.append(iter.key()); | 150 | returnList.append(iter.key()); |
1732 | 83 | } | 151 | } |
1733 | @@ -120,17 +188,19 @@ | |||
1734 | 120 | } | 188 | } |
1735 | 121 | } | 189 | } |
1736 | 122 | 190 | ||
1737 | 191 | d->taskStatus[uuid] = KeeperClientPrivate::TaskStatus{"", 0.0}; | ||
1738 | 192 | |||
1739 | 123 | Q_EMIT readyToBackupChanged(); | 193 | Q_EMIT readyToBackupChanged(); |
1740 | 124 | } | 194 | } |
1741 | 125 | 195 | ||
1743 | 126 | void KeeperClient::startBackup() | 196 | void KeeperClient::enableRestore(QString uuid, bool enabled) |
1744 | 127 | { | 197 | { |
1750 | 128 | // TODO: Instead of polling for state, we should be listening to a stateChanged signal | 198 | // Until we re-design the client we treat restores as backups |
1751 | 129 | if (!d->stateTimer.isActive()) | 199 | enableBackup(uuid, enabled); |
1752 | 130 | { | 200 | } |
1748 | 131 | d->stateTimer.start(200); | ||
1749 | 132 | } | ||
1753 | 133 | 201 | ||
1754 | 202 | void KeeperClient::startBackup(QString const & storage) | ||
1755 | 203 | { | ||
1756 | 134 | // Determine which backups are enabled, and start only those | 204 | // Determine which backups are enabled, and start only those |
1757 | 135 | QStringList backupList; | 205 | QStringList backupList; |
1758 | 136 | for(auto iter = d->backups.begin(); iter != d->backups.end(); ++iter) | 206 | for(auto iter = d->backups.begin(); iter != d->backups.end(); ++iter) |
1759 | @@ -143,8 +213,9 @@ | |||
1760 | 143 | 213 | ||
1761 | 144 | if (!backupList.empty()) | 214 | if (!backupList.empty()) |
1762 | 145 | { | 215 | { |
1764 | 146 | startBackup(backupList); | 216 | startBackup(backupList, storage); |
1765 | 147 | 217 | ||
1766 | 218 | d->mode = KeeperClientPrivate::TasksMode::BACKUP_MODE; | ||
1767 | 148 | d->status = "Preparing Backup..."; | 219 | d->status = "Preparing Backup..."; |
1768 | 149 | Q_EMIT statusChanged(); | 220 | Q_EMIT statusChanged(); |
1769 | 150 | d->backupBusy = true; | 221 | d->backupBusy = true; |
1770 | @@ -152,27 +223,60 @@ | |||
1771 | 152 | } | 223 | } |
1772 | 153 | } | 224 | } |
1773 | 154 | 225 | ||
1774 | 226 | void KeeperClient::startRestore(QString const & storage) | ||
1775 | 227 | { | ||
1776 | 228 | // Determine which restores are enabled, and start only those | ||
1777 | 229 | QStringList restoreList; | ||
1778 | 230 | for(auto iter = d->backups.begin(); iter != d->backups.end(); ++iter) | ||
1779 | 231 | { | ||
1780 | 232 | if (iter.value().value("enabled").toBool()) | ||
1781 | 233 | { | ||
1782 | 234 | restoreList.append(iter.key()); | ||
1783 | 235 | } | ||
1784 | 236 | } | ||
1785 | 237 | |||
1786 | 238 | if (!restoreList.empty()) | ||
1787 | 239 | { | ||
1788 | 240 | startRestore(restoreList, storage); | ||
1789 | 241 | |||
1790 | 242 | d->mode = KeeperClientPrivate::TasksMode::RESTORE_MODE; | ||
1791 | 243 | d->status = "Preparing Restore..."; | ||
1792 | 244 | Q_EMIT statusChanged(); | ||
1793 | 245 | d->backupBusy = true; | ||
1794 | 246 | Q_EMIT backupBusyChanged(); | ||
1795 | 247 | } | ||
1796 | 248 | } | ||
1797 | 249 | |||
1798 | 250 | void KeeperClient::cancel() | ||
1799 | 251 | { | ||
1800 | 252 | QDBusReply<void> cancelReply = d->userIface->call("Cancel"); | ||
1801 | 253 | |||
1802 | 254 | if (!cancelReply.isValid()) | ||
1803 | 255 | { | ||
1804 | 256 | qWarning() << "Error canceling" << cancelReply.error().message(); | ||
1805 | 257 | } | ||
1806 | 258 | } | ||
1807 | 259 | |||
1808 | 155 | QString KeeperClient::getBackupName(QString uuid) | 260 | QString KeeperClient::getBackupName(QString uuid) |
1809 | 156 | { | 261 | { |
1829 | 157 | return d->backups.value(uuid).value("display-name").toString(); | 262 | return d->backups.value(uuid).get_display_name(); |
1830 | 158 | } | 263 | } |
1831 | 159 | 264 | ||
1832 | 160 | QMap<QString, QVariantMap> KeeperClient::getBackupChoices() const | 265 | keeper::Items KeeperClient::getBackupChoices(keeper::Error & error) const |
1833 | 161 | { | 266 | { |
1834 | 162 | QDBusReply<QMap<QString, QVariantMap>> choices = d->userIface->call("GetBackupChoices"); | 267 | QDBusMessage choices = d->userIface->call("GetBackupChoices"); |
1835 | 163 | 268 | return KeeperClientPrivate::getValue(choices, error); | |
1836 | 164 | if (!choices.isValid()) | 269 | } |
1837 | 165 | { | 270 | |
1838 | 166 | qWarning() << "Error getting backup choices:" << choices.error().message(); | 271 | keeper::Items KeeperClient::getRestoreChoices(QString const & storage, keeper::Error & error) const |
1839 | 167 | return QMap<QString, QVariantMap>(); | 272 | { |
1840 | 168 | } | 273 | QDBusMessage choices = d->userIface->call("GetRestoreChoices", storage); |
1841 | 169 | 274 | return KeeperClientPrivate::getValue(choices, error); | |
1842 | 170 | return choices.value(); | 275 | } |
1843 | 171 | } | 276 | |
1844 | 172 | 277 | void KeeperClient::startBackup(const QStringList& uuids, QString const & storage) const | |
1845 | 173 | void KeeperClient::startBackup(const QStringList& uuids) const | 278 | { |
1846 | 174 | { | 279 | QDBusReply<void> backupReply = d->userIface->call("StartBackup", uuids, storage); |
1828 | 175 | QDBusReply<void> backupReply = d->userIface->call("StartBackup", uuids); | ||
1847 | 176 | 280 | ||
1848 | 177 | if (!backupReply.isValid()) | 281 | if (!backupReply.isValid()) |
1849 | 178 | { | 282 | { |
1850 | @@ -180,51 +284,110 @@ | |||
1851 | 180 | } | 284 | } |
1852 | 181 | } | 285 | } |
1853 | 182 | 286 | ||
1855 | 183 | QMap<QString, QVariantMap> KeeperClient::getState() const | 287 | void KeeperClient::startRestore(const QStringList& uuids, QString const & storage) const |
1856 | 288 | { | ||
1857 | 289 | QDBusReply<void> backupReply = d->userIface->call("StartRestore", uuids, storage); | ||
1858 | 290 | |||
1859 | 291 | if (!backupReply.isValid()) | ||
1860 | 292 | { | ||
1861 | 293 | qWarning() << "Error starting restore:" << backupReply.error().message(); | ||
1862 | 294 | } | ||
1863 | 295 | } | ||
1864 | 296 | |||
1865 | 297 | keeper::Items KeeperClient::getState() const | ||
1866 | 184 | { | 298 | { |
1867 | 185 | return d->userIface->state(); | 299 | return d->userIface->state(); |
1868 | 186 | } | 300 | } |
1869 | 187 | 301 | ||
1870 | 302 | QStringList KeeperClient::getStorageAccounts() const | ||
1871 | 303 | { | ||
1872 | 304 | QDBusPendingReply<QStringList> accountsReply = d->userIface->call("GetStorageAccounts"); | ||
1873 | 305 | |||
1874 | 306 | accountsReply.waitForFinished(); | ||
1875 | 307 | if (!accountsReply.isValid()) | ||
1876 | 308 | { | ||
1877 | 309 | qWarning() << "Error retrieving storage accounts:" << accountsReply.error().message(); | ||
1878 | 310 | } | ||
1879 | 311 | |||
1880 | 312 | return accountsReply.value(); | ||
1881 | 313 | } | ||
1882 | 314 | |||
1883 | 188 | void KeeperClient::stateUpdated() | 315 | void KeeperClient::stateUpdated() |
1884 | 189 | { | 316 | { |
1885 | 190 | auto states = getState(); | 317 | auto states = getState(); |
1886 | 191 | 318 | ||
1887 | 192 | if (!states.empty()) | 319 | if (!states.empty()) |
1888 | 193 | { | 320 | { |
1892 | 194 | // Calculate current total progress | 321 | for (auto const & uuid : d->taskStatus.keys()) |
1893 | 195 | // TODO: May be better to monitor each backup's progress separately instead of total | 322 | { |
1894 | 196 | // to avoid irregular jumps in progress between larger and smaller backups | 323 | auto iter_state = states.find(uuid); |
1895 | 324 | if (iter_state == states.end()) | ||
1896 | 325 | { | ||
1897 | 326 | qWarning() << "State for uuid: " << uuid << " was not found"; | ||
1898 | 327 | } | ||
1899 | 328 | keeper::Item keeper_item((*iter_state)); | ||
1900 | 329 | auto progress = keeper_item.get_percent_done(); | ||
1901 | 330 | auto status = keeper_item.get_status(); | ||
1902 | 331 | auto keeper_error = keeper_item.get_error(); | ||
1903 | 332 | |||
1904 | 333 | auto current_state = d->taskStatus[uuid]; | ||
1905 | 334 | if (current_state.status != status || current_state.percentage < progress) | ||
1906 | 335 | { | ||
1907 | 336 | d->taskStatus[uuid].status = status; | ||
1908 | 337 | d->taskStatus[uuid].percentage = progress; | ||
1909 | 338 | Q_EMIT(taskStatusChanged(keeper_item.get_display_name(), status, progress, keeper_error)); | ||
1910 | 339 | } | ||
1911 | 340 | } | ||
1912 | 341 | |||
1913 | 197 | double totalProgress = 0; | 342 | double totalProgress = 0; |
1914 | 198 | for (auto const& state : states) | 343 | for (auto const& state : states) |
1915 | 199 | { | 344 | { |
1917 | 200 | totalProgress += state.value("percent-done").toDouble(); | 345 | keeper::Item keeper_item(state); |
1918 | 346 | totalProgress += keeper_item.get_percent_done(); | ||
1919 | 201 | } | 347 | } |
1920 | 202 | 348 | ||
1921 | 203 | d->progress = totalProgress / states.count(); | 349 | d->progress = totalProgress / states.count(); |
1922 | 204 | Q_EMIT progressChanged(); | 350 | Q_EMIT progressChanged(); |
1923 | 205 | 351 | ||
1924 | 352 | auto allTasksFinished = d->checkAllTasksFinished(states); | ||
1925 | 206 | // Update backup status | 353 | // Update backup status |
1926 | 354 | QString statusString; | ||
1927 | 355 | if (d->mode == KeeperClientPrivate::TasksMode::BACKUP_MODE) | ||
1928 | 356 | { | ||
1929 | 357 | statusString = QStringLiteral("Backup"); | ||
1930 | 358 | } | ||
1931 | 359 | else if (d->mode == KeeperClientPrivate::TasksMode::RESTORE_MODE) | ||
1932 | 360 | { | ||
1933 | 361 | statusString = QStringLiteral("Restore"); | ||
1934 | 362 | } | ||
1935 | 207 | if (d->progress > 0 && d->progress < 1) | 363 | if (d->progress > 0 && d->progress < 1) |
1936 | 208 | { | 364 | { |
1946 | 209 | d->status = "Backup In Progress..."; | 365 | d->status = statusString + QStringLiteral(" In Progress..."); |
1947 | 210 | Q_EMIT statusChanged(); | 366 | Q_EMIT statusChanged(); |
1948 | 211 | 367 | ||
1949 | 212 | d->backupBusy = true; | 368 | d->backupBusy = true; |
1950 | 213 | Q_EMIT backupBusyChanged(); | 369 | Q_EMIT backupBusyChanged(); |
1951 | 214 | } | 370 | } |
1952 | 215 | else if (d->progress >= 1) | 371 | else if (d->progress >= 1 && !allTasksFinished) |
1953 | 216 | { | 372 | { |
1954 | 217 | d->status = "Backup Complete"; | 373 | d->status = statusString + QStringLiteral(" Finishing..."); |
1955 | 374 | Q_EMIT statusChanged(); | ||
1956 | 375 | |||
1957 | 376 | d->backupBusy = true; | ||
1958 | 377 | Q_EMIT backupBusyChanged(); | ||
1959 | 378 | } | ||
1960 | 379 | else if (allTasksFinished) | ||
1961 | 380 | { | ||
1962 | 381 | d->status = statusString + QStringLiteral(" Complete"); | ||
1963 | 218 | Q_EMIT statusChanged(); | 382 | Q_EMIT statusChanged(); |
1964 | 219 | 383 | ||
1965 | 220 | d->backupBusy = false; | 384 | d->backupBusy = false; |
1966 | 221 | Q_EMIT backupBusyChanged(); | 385 | Q_EMIT backupBusyChanged(); |
1967 | 386 | } | ||
1968 | 222 | 387 | ||
1974 | 223 | // Stop state timer | 388 | if (d->checkAllTasksFinished(states)) |
1975 | 224 | if (d->stateTimer.isActive()) | 389 | { |
1976 | 225 | { | 390 | Q_EMIT(finished()); |
1972 | 226 | d->stateTimer.stop(); | ||
1973 | 227 | } | ||
1977 | 228 | } | 391 | } |
1978 | 229 | } | 392 | } |
1979 | 230 | } | 393 | } |
1980 | 231 | 394 | ||
1981 | === added file 'src/client/items.cpp' | |||
1982 | --- src/client/items.cpp 1970-01-01 00:00:00 +0000 | |||
1983 | +++ src/client/items.cpp 2017-02-27 19:05:17 +0000 | |||
1984 | @@ -0,0 +1,196 @@ | |||
1985 | 1 | /* | ||
1986 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1987 | 3 | * | ||
1988 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1989 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
1990 | 6 | * by the Free Software Foundation. | ||
1991 | 7 | * | ||
1992 | 8 | * This program is distributed in the hope that it will be useful, but | ||
1993 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1994 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1995 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
1996 | 12 | * | ||
1997 | 13 | * You should have received a copy of the GNU General Public License along | ||
1998 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1999 | 15 | * | ||
2000 | 16 | * Authors: | ||
2001 | 17 | * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> | ||
2002 | 18 | */ | ||
2003 | 19 | |||
2004 | 20 | #include "client/keeper-items.h" | ||
2005 | 21 | |||
2006 | 22 | #include <QtDBus> | ||
2007 | 23 | #include <QVariantMap> | ||
2008 | 24 | |||
2009 | 25 | namespace keeper | ||
2010 | 26 | { | ||
2011 | 27 | // json keys | ||
2012 | 28 | constexpr const char PROPERTIES_KEY[] = "properties"; | ||
2013 | 29 | |||
2014 | 30 | // keys | ||
2015 | 31 | const QString Item::UUID_KEY = QStringLiteral("uuid"); | ||
2016 | 32 | const QString Item::TYPE_KEY = QStringLiteral("type"); | ||
2017 | 33 | const QString Item::SUBTYPE_KEY = QStringLiteral("subtype"); | ||
2018 | 34 | const QString Item::NAME_KEY = QStringLiteral("name"); | ||
2019 | 35 | const QString Item::PACKAGE_KEY = QStringLiteral("package"); | ||
2020 | 36 | const QString Item::TITLE_KEY = QStringLiteral("title"); | ||
2021 | 37 | const QString Item::VERSION_KEY = QStringLiteral("version"); | ||
2022 | 38 | const QString Item::FILE_NAME_KEY = QStringLiteral("file-name"); | ||
2023 | 39 | const QString Item::DIR_NAME_KEY = QStringLiteral("dir-name"); | ||
2024 | 40 | const QString Item::DISPLAY_NAME_KEY = QStringLiteral("display-name"); | ||
2025 | 41 | const QString Item::STATUS_KEY = QStringLiteral("action"); | ||
2026 | 42 | const QString Item::ERROR_KEY = QStringLiteral("error"); | ||
2027 | 43 | const QString Item::PERCENT_DONE_KEY = QStringLiteral("percent-done"); | ||
2028 | 44 | const QString Item::SPEED_KEY = QStringLiteral("speed"); | ||
2029 | 45 | |||
2030 | 46 | |||
2031 | 47 | // values | ||
2032 | 48 | const QString Item::FOLDER_VALUE = QStringLiteral("folder"); | ||
2033 | 49 | const QString Item::SYSTEM_DATA_VALUE = QStringLiteral("system-data"); | ||
2034 | 50 | const QString Item::APPLICATION_VALUE = QStringLiteral("application"); | ||
2035 | 51 | |||
2036 | 52 | Item::Item() = default; | ||
2037 | 53 | |||
2038 | 54 | Item::Item(QVariantMap const & values) | ||
2039 | 55 | : QVariantMap(values) | ||
2040 | 56 | { | ||
2041 | 57 | } | ||
2042 | 58 | |||
2043 | 59 | Item::~Item() = default; | ||
2044 | 60 | |||
2045 | 61 | QVariant Item::get_property_value(QString const & property) const | ||
2046 | 62 | { | ||
2047 | 63 | auto iter = this->find(property); | ||
2048 | 64 | if (iter != this->end()) | ||
2049 | 65 | { | ||
2050 | 66 | return (*iter); | ||
2051 | 67 | } | ||
2052 | 68 | else | ||
2053 | 69 | { | ||
2054 | 70 | return QVariant(); | ||
2055 | 71 | } | ||
2056 | 72 | } | ||
2057 | 73 | |||
2058 | 74 | void Item::set_property_value(QString const& property, QVariant const& value) | ||
2059 | 75 | { | ||
2060 | 76 | this->insert(property, value); | ||
2061 | 77 | } | ||
2062 | 78 | |||
2063 | 79 | template<typename T> T Item::get_property(QString const & property, bool * valid) const | ||
2064 | 80 | { | ||
2065 | 81 | auto it = this->find(property); | ||
2066 | 82 | |||
2067 | 83 | if (it == this->end()) | ||
2068 | 84 | { | ||
2069 | 85 | if (valid != nullptr) | ||
2070 | 86 | *valid = false; | ||
2071 | 87 | |||
2072 | 88 | return T{}; | ||
2073 | 89 | } | ||
2074 | 90 | |||
2075 | 91 | if (valid != nullptr) | ||
2076 | 92 | *valid = true; | ||
2077 | 93 | |||
2078 | 94 | return it->value<T>(); | ||
2079 | 95 | } | ||
2080 | 96 | |||
2081 | 97 | bool Item::is_valid()const | ||
2082 | 98 | { | ||
2083 | 99 | // check for required properties | ||
2084 | 100 | for (auto& property : {TYPE_KEY, DISPLAY_NAME_KEY}) | ||
2085 | 101 | if (!this->has_property(property)) | ||
2086 | 102 | return false; | ||
2087 | 103 | |||
2088 | 104 | return true; | ||
2089 | 105 | } | ||
2090 | 106 | |||
2091 | 107 | bool Item::has_property(QString const & property) const | ||
2092 | 108 | { | ||
2093 | 109 | return this->contains(property); | ||
2094 | 110 | } | ||
2095 | 111 | |||
2096 | 112 | QString Item::get_uuid(bool *valid) const | ||
2097 | 113 | { | ||
2098 | 114 | return get_property<QString>(UUID_KEY, valid); | ||
2099 | 115 | } | ||
2100 | 116 | |||
2101 | 117 | QString Item::get_type(bool *valid) const | ||
2102 | 118 | { | ||
2103 | 119 | return get_property<QString>(TYPE_KEY, valid); | ||
2104 | 120 | } | ||
2105 | 121 | |||
2106 | 122 | QString Item::get_display_name(bool *valid) const | ||
2107 | 123 | { | ||
2108 | 124 | return get_property<QString>(DISPLAY_NAME_KEY, valid); | ||
2109 | 125 | } | ||
2110 | 126 | |||
2111 | 127 | QString Item::get_dir_name(bool *valid) const | ||
2112 | 128 | { | ||
2113 | 129 | return get_property<QString>(DIR_NAME_KEY, valid); | ||
2114 | 130 | } | ||
2115 | 131 | |||
2116 | 132 | QString Item::get_status(bool *valid) const | ||
2117 | 133 | { | ||
2118 | 134 | return get_property<QString>(STATUS_KEY, valid); | ||
2119 | 135 | } | ||
2120 | 136 | |||
2121 | 137 | double Item::get_percent_done(bool *valid) const | ||
2122 | 138 | { | ||
2123 | 139 | return get_property<double>(PERCENT_DONE_KEY, valid); | ||
2124 | 140 | } | ||
2125 | 141 | |||
2126 | 142 | keeper::Error Item::get_error(bool *valid) const | ||
2127 | 143 | { | ||
2128 | 144 | auto it = this->find(ERROR_KEY); | ||
2129 | 145 | |||
2130 | 146 | // if no error was sent, things must be OK | ||
2131 | 147 | if (it == this->end()) | ||
2132 | 148 | { | ||
2133 | 149 | return keeper::Error::OK; | ||
2134 | 150 | } | ||
2135 | 151 | |||
2136 | 152 | return keeper::convert_from_dbus_variant(*it, valid); | ||
2137 | 153 | } | ||
2138 | 154 | |||
2139 | 155 | QString Item::get_file_name(bool *valid) const | ||
2140 | 156 | { | ||
2141 | 157 | return get_property<QString>(FILE_NAME_KEY, valid); | ||
2142 | 158 | } | ||
2143 | 159 | |||
2144 | 160 | void Item::registerMetaType() | ||
2145 | 161 | { | ||
2146 | 162 | qRegisterMetaType<Item>("Item"); | ||
2147 | 163 | |||
2148 | 164 | qDBusRegisterMetaType<Item>(); | ||
2149 | 165 | } | ||
2150 | 166 | |||
2151 | 167 | ///// | ||
2152 | 168 | // Items | ||
2153 | 169 | ///// | ||
2154 | 170 | |||
2155 | 171 | |||
2156 | 172 | Items::Items() =default; | ||
2157 | 173 | |||
2158 | 174 | Items::~Items() =default; | ||
2159 | 175 | |||
2160 | 176 | |||
2161 | 177 | Items::Items(Error error) | ||
2162 | 178 | : error_{error} | ||
2163 | 179 | { | ||
2164 | 180 | } | ||
2165 | 181 | |||
2166 | 182 | QStringList Items::get_uuids() const | ||
2167 | 183 | { | ||
2168 | 184 | return this->keys(); | ||
2169 | 185 | } | ||
2170 | 186 | |||
2171 | 187 | void Items::registerMetaType() | ||
2172 | 188 | { | ||
2173 | 189 | qRegisterMetaType<Items>("Items"); | ||
2174 | 190 | |||
2175 | 191 | qDBusRegisterMetaType<Items>(); | ||
2176 | 192 | |||
2177 | 193 | Item::registerMetaType(); | ||
2178 | 194 | } | ||
2179 | 195 | |||
2180 | 196 | } // namespace keeper | ||
2181 | 0 | 197 | ||
2182 | === added file 'src/client/keeper-errors.cpp' | |||
2183 | --- src/client/keeper-errors.cpp 1970-01-01 00:00:00 +0000 | |||
2184 | +++ src/client/keeper-errors.cpp 2017-02-27 19:05:17 +0000 | |||
2185 | @@ -0,0 +1,74 @@ | |||
2186 | 1 | /* | ||
2187 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
2188 | 3 | * | ||
2189 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
2190 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
2191 | 6 | * by the Free Software Foundation. | ||
2192 | 7 | * | ||
2193 | 8 | * This program is distributed in the hope that it will be useful, but | ||
2194 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
2195 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
2196 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
2197 | 12 | * | ||
2198 | 13 | * You should have received a copy of the GNU General Public License along | ||
2199 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2200 | 15 | * | ||
2201 | 16 | * Authors: | ||
2202 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
2203 | 18 | */ | ||
2204 | 19 | |||
2205 | 20 | #include <client/keeper-errors.h> | ||
2206 | 21 | |||
2207 | 22 | #include <QDebug> | ||
2208 | 23 | |||
2209 | 24 | QDBusArgument &operator<<(QDBusArgument &argument, keeper::Error value) | ||
2210 | 25 | { | ||
2211 | 26 | argument.beginStructure(); | ||
2212 | 27 | argument << static_cast<int>(value); | ||
2213 | 28 | argument.endStructure(); | ||
2214 | 29 | return argument; | ||
2215 | 30 | } | ||
2216 | 31 | |||
2217 | 32 | const QDBusArgument &operator>>(const QDBusArgument &argument, keeper::Error &val) | ||
2218 | 33 | { | ||
2219 | 34 | int int_val; | ||
2220 | 35 | argument.beginStructure(); | ||
2221 | 36 | argument >> int_val; | ||
2222 | 37 | val = static_cast<keeper::Error>(int_val); | ||
2223 | 38 | argument.endStructure(); | ||
2224 | 39 | return argument; | ||
2225 | 40 | } | ||
2226 | 41 | |||
2227 | 42 | namespace keeper | ||
2228 | 43 | { | ||
2229 | 44 | Error convert_from_dbus_variant(const QVariant & value, bool *conversion_ok) | ||
2230 | 45 | { | ||
2231 | 46 | if (value.typeName() != QStringLiteral("QDBusArgument")) | ||
2232 | 47 | { | ||
2233 | 48 | qWarning() << Q_FUNC_INFO | ||
2234 | 49 | << " Error converting dbus QVariant to Error, expected type is [ QDBusArgument ] and current type is: [" | ||
2235 | 50 | << value.typeName() << "]"; | ||
2236 | 51 | if (conversion_ok) | ||
2237 | 52 | *conversion_ok = false; | ||
2238 | 53 | return Error(keeper::Error::UNKNOWN); | ||
2239 | 54 | } | ||
2240 | 55 | auto dbus_arg = value.value<QDBusArgument>(); | ||
2241 | 56 | |||
2242 | 57 | if (dbus_arg.currentSignature() != "(i)") | ||
2243 | 58 | { | ||
2244 | 59 | qWarning() << Q_FUNC_INFO | ||
2245 | 60 | << " Error converting dbus QVariant to Error, expected signature is \"(i)\" and current signature is: \"" | ||
2246 | 61 | << dbus_arg.currentSignature() << "\""; | ||
2247 | 62 | if (conversion_ok) | ||
2248 | 63 | *conversion_ok = false; | ||
2249 | 64 | return Error(keeper::Error::UNKNOWN); | ||
2250 | 65 | } | ||
2251 | 66 | Error ret; | ||
2252 | 67 | dbus_arg >> ret; | ||
2253 | 68 | |||
2254 | 69 | if (conversion_ok) | ||
2255 | 70 | *conversion_ok = true; | ||
2256 | 71 | |||
2257 | 72 | return ret; | ||
2258 | 73 | } | ||
2259 | 74 | } | ||
2260 | 0 | 75 | ||
2261 | === modified file 'src/client/qml-plugin/CMakeLists.txt' | |||
2262 | --- src/client/qml-plugin/CMakeLists.txt 2016-08-26 09:30:11 +0000 | |||
2263 | +++ src/client/qml-plugin/CMakeLists.txt 2017-02-27 19:05:17 +0000 | |||
2264 | @@ -6,7 +6,7 @@ | |||
2265 | 6 | add_definitions(-DKEEPER_MAJOR=${KEEPER_MAJOR}) | 6 | add_definitions(-DKEEPER_MAJOR=${KEEPER_MAJOR}) |
2266 | 7 | add_definitions(-DKEEPER_MINOR=${KEEPER_MINOR}) | 7 | add_definitions(-DKEEPER_MINOR=${KEEPER_MINOR}) |
2267 | 8 | 8 | ||
2269 | 9 | include(QmlPlugins) | 9 | find_package(QmlPlugins) |
2270 | 10 | 10 | ||
2271 | 11 | find_package(Qt5Quick REQUIRED) | 11 | find_package(Qt5Quick REQUIRED) |
2272 | 12 | 12 | ||
2273 | 13 | 13 | ||
2274 | === modified file 'src/helper/CMakeLists.txt' | |||
2275 | --- src/helper/CMakeLists.txt 2016-09-06 01:31:59 +0000 | |||
2276 | +++ src/helper/CMakeLists.txt 2017-02-27 19:05:17 +0000 | |||
2277 | @@ -18,6 +18,21 @@ | |||
2278 | 18 | ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR} | 18 | ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR} |
2279 | 19 | ) | 19 | ) |
2280 | 20 | 20 | ||
2281 | 21 | set( | ||
2282 | 22 | FOLDER_RESTORE | ||
2283 | 23 | folder-restore.sh | ||
2284 | 24 | ) | ||
2285 | 25 | configure_file( | ||
2286 | 26 | ${CMAKE_CURRENT_SOURCE_DIR}/${FOLDER_RESTORE}.in | ||
2287 | 27 | ${CMAKE_CURRENT_BINARY_DIR}/${FOLDER_RESTORE} | ||
2288 | 28 | ) | ||
2289 | 29 | |||
2290 | 30 | install( | ||
2291 | 31 | PROGRAMS | ||
2292 | 32 | ${CMAKE_CURRENT_BINARY_DIR}/${FOLDER_RESTORE} | ||
2293 | 33 | DESTINATION | ||
2294 | 34 | ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR} | ||
2295 | 35 | ) | ||
2296 | 21 | 36 | ||
2297 | 22 | # | 37 | # |
2298 | 23 | # the library | 38 | # the library |
2299 | @@ -30,7 +45,7 @@ | |||
2300 | 30 | 45 | ||
2301 | 31 | include(FindPkgConfig) | 46 | include(FindPkgConfig) |
2302 | 32 | pkg_check_modules(BACKUP_HELPER_DEPENDENCIES REQUIRED | 47 | pkg_check_modules(BACKUP_HELPER_DEPENDENCIES REQUIRED |
2304 | 33 | ubuntu-app-launch-2 | 48 | ubuntu-app-launch-3 |
2305 | 34 | properties-cpp | 49 | properties-cpp |
2306 | 35 | ) | 50 | ) |
2307 | 36 | 51 | ||
2308 | @@ -48,10 +63,12 @@ | |||
2309 | 48 | ${HELPER_LIB} | 63 | ${HELPER_LIB} |
2310 | 49 | STATIC | 64 | STATIC |
2311 | 50 | backup-helper.cpp | 65 | backup-helper.cpp |
2312 | 66 | restore-helper.cpp | ||
2313 | 51 | data-dir-registry.cpp | 67 | data-dir-registry.cpp |
2314 | 52 | helper.cpp | 68 | helper.cpp |
2315 | 53 | metadata.cpp | 69 | metadata.cpp |
2316 | 54 | ${CMAKE_SOURCE_DIR}/include/helper/backup-helper.h | 70 | ${CMAKE_SOURCE_DIR}/include/helper/backup-helper.h |
2317 | 71 | ${CMAKE_SOURCE_DIR}/include/helper/restore-helper.h | ||
2318 | 55 | ${CMAKE_SOURCE_DIR}/include/helper/data-dir-registry.h | 72 | ${CMAKE_SOURCE_DIR}/include/helper/data-dir-registry.h |
2319 | 56 | ${CMAKE_SOURCE_DIR}/include/helper/helper.h | 73 | ${CMAKE_SOURCE_DIR}/include/helper/helper.h |
2320 | 57 | ${CMAKE_SOURCE_DIR}/include/helper/registry.h | 74 | ${CMAKE_SOURCE_DIR}/include/helper/registry.h |
2321 | 58 | 75 | ||
2322 | === modified file 'src/helper/backup-helper.cpp' | |||
2323 | --- src/helper/backup-helper.cpp 2016-09-12 15:13:33 +0000 | |||
2324 | +++ src/helper/backup-helper.cpp 2017-02-27 19:05:17 +0000 | |||
2325 | @@ -62,8 +62,8 @@ | |||
2326 | 62 | int rc = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds); | 62 | int rc = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds); |
2327 | 63 | if (rc == -1) | 63 | if (rc == -1) |
2328 | 64 | { | 64 | { |
2331 | 65 | // TODO throw exception. | 65 | qWarning() << QStringLiteral("Error creating socket to communicate with helper");; |
2332 | 66 | qWarning() << "BackupHelperPrivate: error creating socket pair to communicate with helper "; | 66 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_SOCKET)); |
2333 | 67 | return; | 67 | return; |
2334 | 68 | } | 68 | } |
2335 | 69 | 69 | ||
2336 | @@ -139,9 +139,14 @@ | |||
2337 | 139 | &Uploader::commit_finished, | 139 | &Uploader::commit_finished, |
2338 | 140 | std::function<void(bool)>{[this](bool success){ | 140 | std::function<void(bool)>{[this](bool success){ |
2339 | 141 | qDebug() << "Commit finished"; | 141 | qDebug() << "Commit finished"; |
2340 | 142 | uploader_.reset(); | ||
2341 | 143 | if (!success) | 142 | if (!success) |
2342 | 143 | { | ||
2343 | 144 | write_error_ = true; | 144 | write_error_ = true; |
2344 | 145 | Q_EMIT(q_ptr->error(keeper::Error::COMMITTING_DATA)); | ||
2345 | 146 | } | ||
2346 | 147 | else | ||
2347 | 148 | uploader_committed_file_name_ = uploader_->file_name(); | ||
2348 | 149 | uploader_.reset(); | ||
2349 | 145 | check_for_done(); | 150 | check_for_done(); |
2350 | 146 | }} | 151 | }} |
2351 | 147 | ); | 152 | ); |
2352 | @@ -162,12 +167,18 @@ | |||
2353 | 162 | check_for_done(); | 167 | check_for_done(); |
2354 | 163 | } | 168 | } |
2355 | 164 | 169 | ||
2356 | 170 | QString get_uploader_committed_file_name() const | ||
2357 | 171 | { | ||
2358 | 172 | return uploader_committed_file_name_; | ||
2359 | 173 | } | ||
2360 | 174 | |||
2361 | 165 | private: | 175 | private: |
2362 | 166 | 176 | ||
2363 | 167 | void on_inactivity_detected() | 177 | void on_inactivity_detected() |
2364 | 168 | { | 178 | { |
2365 | 169 | stop_inactivity_timer(); | 179 | stop_inactivity_timer(); |
2366 | 170 | qWarning() << "Inactivity detected in the helper...stopping it"; | 180 | qWarning() << "Inactivity detected in the helper...stopping it"; |
2367 | 181 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_INACTIVITY_DETECTED)); | ||
2368 | 171 | stop(); | 182 | stop(); |
2369 | 172 | } | 183 | } |
2370 | 173 | 184 | ||
2371 | @@ -180,7 +191,6 @@ | |||
2372 | 180 | { | 191 | { |
2373 | 181 | n_uploaded_ += n; | 192 | n_uploaded_ += n; |
2374 | 182 | q_ptr->record_data_transferred(n); | 193 | q_ptr->record_data_transferred(n); |
2375 | 183 | qDebug("n_read %zu n_uploaded %zu (newly uploaded %zu)", size_t(n_read_), size_t(n_uploaded_), size_t(n)); | ||
2376 | 184 | process_more(); | 194 | process_more(); |
2377 | 185 | check_for_done(); | 195 | check_for_done(); |
2378 | 186 | } | 196 | } |
2379 | @@ -201,10 +211,10 @@ | |||
2380 | 201 | if (n > 0) { | 211 | if (n > 0) { |
2381 | 202 | n_read_ += n; | 212 | n_read_ += n; |
2382 | 203 | upload_buffer_.append(readbuf, int(n)); | 213 | upload_buffer_.append(readbuf, int(n)); |
2383 | 204 | qDebug("upload_buffer_.size() is %zu after reading %zu from helper", size_t(upload_buffer_.size()), size_t(n)); | ||
2384 | 205 | } | 214 | } |
2385 | 206 | else if (n < 0) { | 215 | else if (n < 0) { |
2386 | 207 | read_error_ = true; | 216 | read_error_ = true; |
2387 | 217 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_READ)); | ||
2388 | 208 | stop(); | 218 | stop(); |
2389 | 209 | return; | 219 | return; |
2390 | 210 | } | 220 | } |
2391 | @@ -214,13 +224,13 @@ | |||
2392 | 214 | const auto n = socket->write(upload_buffer_); | 224 | const auto n = socket->write(upload_buffer_); |
2393 | 215 | if (n > 0) { | 225 | if (n > 0) { |
2394 | 216 | upload_buffer_.remove(0, int(n)); | 226 | upload_buffer_.remove(0, int(n)); |
2395 | 217 | qDebug("upload_buffer_.size() is %zu after writing %zu to cloud", size_t(upload_buffer_.size()), size_t(n)); | ||
2396 | 218 | continue; | 227 | continue; |
2397 | 219 | } | 228 | } |
2398 | 220 | else { | 229 | else { |
2399 | 221 | if (n < 0) { | 230 | if (n < 0) { |
2400 | 222 | write_error_ = true; | 231 | write_error_ = true; |
2401 | 223 | qWarning() << "Write error:" << socket->errorString(); | 232 | qWarning() << "Write error:" << socket->errorString(); |
2402 | 233 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_WRITE)); | ||
2403 | 224 | stop(); | 234 | stop(); |
2404 | 225 | } | 235 | } |
2405 | 226 | break; | 236 | break; |
2406 | @@ -251,6 +261,10 @@ | |||
2407 | 251 | { | 261 | { |
2408 | 252 | if (!q_ptr->is_helper_running()) | 262 | if (!q_ptr->is_helper_running()) |
2409 | 253 | { | 263 | { |
2410 | 264 | if (n_uploaded_ > q_ptr->expected_size()) | ||
2411 | 265 | { | ||
2412 | 266 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_WRITE)); | ||
2413 | 267 | } | ||
2414 | 254 | q_ptr->set_state(Helper::State::FAILED); | 268 | q_ptr->set_state(Helper::State::FAILED); |
2415 | 255 | } | 269 | } |
2416 | 256 | } | 270 | } |
2417 | @@ -289,6 +303,7 @@ | |||
2418 | 289 | bool write_error_ = false; | 303 | bool write_error_ = false; |
2419 | 290 | bool cancelled_ = false; | 304 | bool cancelled_ = false; |
2420 | 291 | ConnectionHelper connections_; | 305 | ConnectionHelper connections_; |
2421 | 306 | QString uploader_committed_file_name_; | ||
2422 | 292 | }; | 307 | }; |
2423 | 293 | 308 | ||
2424 | 294 | /*** | 309 | /*** |
2425 | @@ -352,14 +367,21 @@ | |||
2426 | 352 | { | 367 | { |
2427 | 353 | Q_D(BackupHelper); | 368 | Q_D(BackupHelper); |
2428 | 354 | 369 | ||
2430 | 355 | qDebug() << Q_FUNC_INFO; | 370 | Helper::set_state(state); |
2431 | 356 | d->on_state_changed(state); | 371 | d->on_state_changed(state); |
2432 | 357 | Helper::set_state(state); | ||
2433 | 358 | } | 372 | } |
2434 | 359 | 373 | ||
2435 | 360 | void BackupHelper::on_helper_finished() | 374 | void BackupHelper::on_helper_finished() |
2436 | 361 | { | 375 | { |
2437 | 362 | Q_D(BackupHelper); | 376 | Q_D(BackupHelper); |
2438 | 377 | |||
2439 | 363 | Helper::on_helper_finished(); | 378 | Helper::on_helper_finished(); |
2440 | 364 | d->on_helper_finished(); | 379 | d->on_helper_finished(); |
2441 | 365 | } | 380 | } |
2442 | 381 | |||
2443 | 382 | QString BackupHelper::get_uploader_committed_file_name() const | ||
2444 | 383 | { | ||
2445 | 384 | Q_D(const BackupHelper); | ||
2446 | 385 | |||
2447 | 386 | return d->get_uploader_committed_file_name(); | ||
2448 | 387 | } | ||
2449 | 366 | 388 | ||
2450 | === modified file 'src/helper/data-dir-registry.cpp' | |||
2451 | --- src/helper/data-dir-registry.cpp 2016-08-10 02:29:17 +0000 | |||
2452 | +++ src/helper/data-dir-registry.cpp 2017-02-27 19:05:17 +0000 | |||
2453 | @@ -49,15 +49,27 @@ | |||
2454 | 49 | 49 | ||
2455 | 50 | QStringList get_backup_helper_urls(Metadata const& task) | 50 | QStringList get_backup_helper_urls(Metadata const& task) |
2456 | 51 | { | 51 | { |
2457 | 52 | return get_helper_urls(task, "backup"); | ||
2458 | 53 | } | ||
2459 | 54 | |||
2460 | 55 | QStringList get_restore_helper_urls(Metadata const& task) | ||
2461 | 56 | { | ||
2462 | 57 | return get_helper_urls(task, "restore"); | ||
2463 | 58 | } | ||
2464 | 59 | |||
2465 | 60 | private: | ||
2466 | 61 | |||
2467 | 62 | QStringList get_helper_urls(Metadata const& task, QString const & prop) | ||
2468 | 63 | { | ||
2469 | 52 | QStringList ret; | 64 | QStringList ret; |
2470 | 53 | 65 | ||
2473 | 54 | QString type; | 66 | auto type = task.get_type(); |
2474 | 55 | if (task.get_property(Metadata::TYPE_KEY, type)) | 67 | if (!type.isEmpty()) |
2475 | 56 | { | 68 | { |
2477 | 57 | auto it = registry_.find(std::make_pair(type,QStringLiteral("backup"))); | 69 | auto it = registry_.find(std::make_pair(type,prop)); |
2478 | 58 | if (it == registry_.end()) | 70 | if (it == registry_.end()) |
2479 | 59 | { | 71 | { |
2481 | 60 | qCritical() << "can't get backup helper urls for unhandled type" << type; | 72 | qCritical() << "can't get " << prop << " helper urls for unhandled type" << type; |
2482 | 61 | } | 73 | } |
2483 | 62 | else | 74 | else |
2484 | 63 | { | 75 | { |
2485 | @@ -73,30 +85,28 @@ | |||
2486 | 73 | return ret; | 85 | return ret; |
2487 | 74 | } | 86 | } |
2488 | 75 | 87 | ||
2489 | 76 | private: | ||
2490 | 77 | |||
2491 | 78 | // replace "${key}" with task.get_property("key") | 88 | // replace "${key}" with task.get_property("key") |
2492 | 79 | QStringList perform_url_substitution(Metadata const& task, QStringList const& urls_in) | 89 | QStringList perform_url_substitution(Metadata const& task, QStringList const& urls_in) |
2493 | 80 | { | 90 | { |
2494 | 81 | std::array<QString,6> keys = { | 91 | std::array<QString,6> keys = { |
2501 | 82 | Metadata::TYPE_KEY, | 92 | keeper::Item::TYPE_KEY, |
2502 | 83 | Metadata::SUBTYPE_KEY, | 93 | keeper::Item::SUBTYPE_KEY, |
2503 | 84 | Metadata::NAME_KEY, | 94 | keeper::Item::NAME_KEY, |
2504 | 85 | Metadata::PACKAGE_KEY, | 95 | keeper::Item::PACKAGE_KEY, |
2505 | 86 | Metadata::TITLE_KEY, | 96 | keeper::Item::TITLE_KEY, |
2506 | 87 | Metadata::VERSION_KEY | 97 | keeper::Item::VERSION_KEY |
2507 | 88 | }; | 98 | }; |
2508 | 89 | 99 | ||
2509 | 90 | QStringList urls {urls_in}; | 100 | QStringList urls {urls_in}; |
2510 | 91 | 101 | ||
2511 | 92 | for (auto const& key : keys) | 102 | for (auto const& key : keys) |
2512 | 93 | { | 103 | { |
2515 | 94 | QString after; | 104 | QVariant after = task.get_property_value(key); |
2516 | 95 | if (task.get_property(key, after)) | 105 | if (after.isValid()) |
2517 | 96 | { | 106 | { |
2518 | 97 | QString before = QStringLiteral("${%1}").arg(key); | 107 | QString before = QStringLiteral("${%1}").arg(key); |
2519 | 98 | for (auto& url : urls) | 108 | for (auto& url : urls) |
2521 | 99 | url.replace(before, after); | 109 | url.replace(before, after.toString()); |
2522 | 100 | } | 110 | } |
2523 | 101 | } | 111 | } |
2524 | 102 | 112 | ||
2525 | @@ -139,6 +149,10 @@ | |||
2526 | 139 | * "backup-urls": [ | 149 | * "backup-urls": [ |
2527 | 140 | * "/path/to/helper.sh", | 150 | * "/path/to/helper.sh", |
2528 | 141 | * "${subtype}" | 151 | * "${subtype}" |
2529 | 152 | * ], | ||
2530 | 153 | * "restore-urls": [ | ||
2531 | 154 | * "/path/to/helper.sh", | ||
2532 | 155 | * "${subtype}" | ||
2533 | 142 | * ] | 156 | * ] |
2534 | 143 | * } | 157 | * } |
2535 | 144 | * } | 158 | * } |
2536 | @@ -156,25 +170,37 @@ | |||
2537 | 156 | if (error.error != QJsonParseError::NoError) | 170 | if (error.error != QJsonParseError::NoError) |
2538 | 157 | qCritical() << path << "parse error at offset" << error.offset << error.errorString(); | 171 | qCritical() << path << "parse error at offset" << error.offset << error.errorString(); |
2539 | 158 | 172 | ||
2541 | 159 | auto obj = doc.object(); | 173 | const auto obj = doc.object(); |
2542 | 160 | for (auto tit=obj.begin(), tend=obj.end(); tit!=tend; ++tit) | 174 | for (auto tit=obj.begin(), tend=obj.end(); tit!=tend; ++tit) |
2543 | 161 | { | 175 | { |
2544 | 162 | auto const type = tit.key(); | 176 | auto const type = tit.key(); |
2545 | 163 | auto& info = registry_[std::make_pair(type,QStringLiteral("backup"))]; | ||
2546 | 164 | |||
2547 | 165 | auto const props = tit.value().toObject(); | 177 | auto const props = tit.value().toObject(); |
2549 | 166 | auto const urls_jsonval = props["backup-urls"]; | 178 | |
2550 | 179 | auto const &urls_jsonval = props["backup-urls"]; | ||
2551 | 167 | if (urls_jsonval.isArray()) | 180 | if (urls_jsonval.isArray()) |
2552 | 168 | { | 181 | { |
2553 | 182 | auto& info = registry_[std::make_pair(type,QStringLiteral("backup"))]; | ||
2554 | 169 | for (auto url_jsonval : urls_jsonval.toArray()) | 183 | for (auto url_jsonval : urls_jsonval.toArray()) |
2555 | 170 | { | 184 | { |
2556 | 171 | info.urls.push_back(url_jsonval.toString()); | 185 | info.urls.push_back(url_jsonval.toString()); |
2557 | 172 | } | 186 | } |
2558 | 187 | qDebug() << "loaded" << type << "backup urls from" << path; | ||
2559 | 188 | for(auto const& url : info.urls) | ||
2560 | 189 | qDebug() << "\turl:" << url; | ||
2561 | 173 | } | 190 | } |
2562 | 174 | 191 | ||
2566 | 175 | qDebug() << "loaded" << type << "backup urls from" << path; | 192 | auto const &urls_jsonval_restore = props["restore-urls"]; |
2567 | 176 | for(auto const& url : info.urls) | 193 | if (urls_jsonval_restore.isArray()) |
2568 | 177 | qDebug() << "\turl:" << url; | 194 | { |
2569 | 195 | auto& info = registry_[std::make_pair(type,QStringLiteral("restore"))]; | ||
2570 | 196 | for (auto url_jsonval : urls_jsonval_restore.toArray()) | ||
2571 | 197 | { | ||
2572 | 198 | info.urls.push_back(url_jsonval.toString()); | ||
2573 | 199 | } | ||
2574 | 200 | qDebug() << "loaded" << type << "restore urls from" << path; | ||
2575 | 201 | for(auto const& url : info.urls) | ||
2576 | 202 | qDebug() << "\turl:" << url; | ||
2577 | 203 | } | ||
2578 | 178 | } | 204 | } |
2579 | 179 | } | 205 | } |
2580 | 180 | } | 206 | } |
2581 | @@ -198,3 +224,9 @@ | |||
2582 | 198 | { | 224 | { |
2583 | 199 | return impl_->get_backup_helper_urls(task); | 225 | return impl_->get_backup_helper_urls(task); |
2584 | 200 | } | 226 | } |
2585 | 227 | |||
2586 | 228 | QStringList | ||
2587 | 229 | DataDirRegistry::get_restore_helper_urls(Metadata const& task) | ||
2588 | 230 | { | ||
2589 | 231 | return impl_->get_restore_helper_urls(task); | ||
2590 | 232 | } | ||
2591 | 201 | 233 | ||
2592 | === modified file 'src/helper/folder-backup.sh.in' | |||
2593 | --- src/helper/folder-backup.sh.in 2016-08-10 05:01:08 +0000 | |||
2594 | +++ src/helper/folder-backup.sh.in 2017-02-27 19:05:17 +0000 | |||
2595 | @@ -20,4 +20,4 @@ | |||
2596 | 20 | # | 20 | # |
2597 | 21 | 21 | ||
2598 | 22 | echo $PWD | 22 | echo $PWD |
2600 | 23 | find ./ -type f -print0 | @CMAKE_INSTALL_FULL_PKGLIBEXECDIR@/keeper-tar-create -a /com/canonical/keeper/helper | 23 | find ./ -type f -print0 | @CMAKE_INSTALL_FULL_PKGLIBEXECDIR@/keeper-tar -a /com/canonical/keeper/helper |
2601 | 24 | 24 | ||
2602 | === added file 'src/helper/folder-restore.sh.in' | |||
2603 | --- src/helper/folder-restore.sh.in 1970-01-01 00:00:00 +0000 | |||
2604 | +++ src/helper/folder-restore.sh.in 2017-02-27 19:05:17 +0000 | |||
2605 | @@ -0,0 +1,23 @@ | |||
2606 | 1 | #!/bin/bash | ||
2607 | 2 | # | ||
2608 | 3 | # Copyright (C) 2016 Canonical, Ltd. | ||
2609 | 4 | # | ||
2610 | 5 | # This program is free software: you can redistribute it and/or modify it | ||
2611 | 6 | # under the terms of the GNU General Public License version 3, as published | ||
2612 | 7 | # by the Free Software Foundation. | ||
2613 | 8 | # | ||
2614 | 9 | # This program is distributed in the hope that it will be useful, but | ||
2615 | 10 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
2616 | 11 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
2617 | 12 | # PURPOSE. See the GNU General Public License for more details. | ||
2618 | 13 | # | ||
2619 | 14 | # You should have received a copy of the GNU General Public License along | ||
2620 | 15 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2621 | 16 | # | ||
2622 | 17 | # Authors: | ||
2623 | 18 | # Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
2624 | 19 | # Charles Kerr <charles.kerr@canonical.com> | ||
2625 | 20 | # | ||
2626 | 21 | |||
2627 | 22 | echo $PWD | ||
2628 | 23 | @CMAKE_INSTALL_FULL_PKGLIBEXECDIR@/keeper-untar -a /com/canonical/keeper/helper | ||
2629 | 0 | 24 | ||
2630 | === modified file 'src/helper/helper.cpp' | |||
2631 | --- src/helper/helper.cpp 2016-09-12 15:13:33 +0000 | |||
2632 | +++ src/helper/helper.cpp 2017-02-27 19:05:17 +0000 | |||
2633 | @@ -75,7 +75,6 @@ | |||
2634 | 75 | uint32_t | 75 | uint32_t |
2635 | 76 | speed_bytes_per_second(uint64_t now, unsigned int interval_msec=HISTORY_MSEC) const | 76 | speed_bytes_per_second(uint64_t now, unsigned int interval_msec=HISTORY_MSEC) const |
2636 | 77 | { | 77 | { |
2637 | 78 | qDebug() << "now" << now << "cache_time" << cache_time << "interval_msec" << interval_msec; | ||
2638 | 79 | if (cache_time != now) | 78 | if (cache_time != now) |
2639 | 80 | { | 79 | { |
2640 | 81 | auto i = newest; | 80 | auto i = newest; |
2641 | @@ -88,22 +87,18 @@ | |||
2642 | 88 | break; | 87 | break; |
2643 | 89 | 88 | ||
2644 | 90 | bytes += transfers[i].size; | 89 | bytes += transfers[i].size; |
2645 | 91 | qDebug() << "i" << i << "transfers[i] .date" << transfers[i].date << ".size" << transfers[i].size << "sum" << bytes; | ||
2646 | 92 | 90 | ||
2647 | 93 | if (--i == -1) { | 91 | if (--i == -1) { |
2648 | 94 | i = HISTORY_SIZE - 1; // circular history | 92 | i = HISTORY_SIZE - 1; // circular history |
2649 | 95 | qDebug() << "circular history"; | ||
2650 | 96 | } | 93 | } |
2651 | 97 | 94 | ||
2652 | 98 | if (i == newest) { | 95 | if (i == newest) { |
2653 | 99 | qDebug() << "i" << i << "transfers[i] .date" << transfers[i].date << ".size" << transfers[i].size << "sum" << bytes; | ||
2654 | 100 | break; // we've come all the way around | 96 | break; // we've come all the way around |
2655 | 101 | } | 97 | } |
2656 | 102 | } | 98 | } |
2657 | 103 | 99 | ||
2658 | 104 | cache_val = uint32_t((bytes * 1000u) / interval_msec); | 100 | cache_val = uint32_t((bytes * 1000u) / interval_msec); |
2659 | 105 | cache_time = now; | 101 | cache_time = now; |
2660 | 106 | qDebug() << "cache_val" << cache_val << "cache_time" << cache_time; | ||
2661 | 107 | } | 102 | } |
2662 | 108 | 103 | ||
2663 | 109 | return cache_val; | 104 | return cache_val; |
2664 | @@ -170,7 +165,10 @@ | |||
2665 | 170 | { | 165 | { |
2666 | 171 | qDebug() << "changing state of helper" << static_cast<void*>(this) << "from" << q_ptr->to_string(state_) << "to" << q_ptr->to_string(state); | 166 | qDebug() << "changing state of helper" << static_cast<void*>(this) << "from" << q_ptr->to_string(state_) << "to" << q_ptr->to_string(state); |
2667 | 172 | state_ = state; | 167 | state_ = state; |
2669 | 173 | q_ptr->state_changed(state); | 168 | QMetaObject::invokeMethod(q_ptr, |
2670 | 169 | "state_changed", | ||
2671 | 170 | Qt::QueuedConnection, | ||
2672 | 171 | Q_ARG(Helper::State, state)); | ||
2673 | 174 | } | 172 | } |
2674 | 175 | } | 173 | } |
2675 | 176 | 174 | ||
2676 | @@ -337,7 +335,6 @@ | |||
2677 | 337 | 335 | ||
2678 | 338 | if (is_noteworthy) | 336 | if (is_noteworthy) |
2679 | 339 | { | 337 | { |
2680 | 340 | qDebug() << "emitting percent-done-changed" << percent_done_; | ||
2681 | 341 | Q_EMIT(q_ptr->percent_done_changed(percent_done_)); | 338 | Q_EMIT(q_ptr->percent_done_changed(percent_done_)); |
2682 | 342 | last_notified_percent_done_ = percent_done_; | 339 | last_notified_percent_done_ = percent_done_; |
2683 | 343 | } | 340 | } |
2684 | @@ -356,7 +353,8 @@ | |||
2685 | 356 | 353 | ||
2686 | 357 | void on_max_time_waiting_for_ual_started() | 354 | void on_max_time_waiting_for_ual_started() |
2687 | 358 | { | 355 | { |
2689 | 359 | qDebug() << "Max time reached waiting for UAL to start"; | 356 | qWarning() << "Maximum time reached waiting for the helper to start."; |
2690 | 357 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_START_TIMEOUT)); | ||
2691 | 360 | q_ptr->set_state(Helper::State::FAILED); | 358 | q_ptr->set_state(Helper::State::FAILED); |
2692 | 361 | stop_wait_for_ual_timer(); | 359 | stop_wait_for_ual_timer(); |
2693 | 362 | } | 360 | } |
2694 | 363 | 361 | ||
2695 | === modified file 'src/helper/metadata.cpp' | |||
2696 | --- src/helper/metadata.cpp 2016-09-06 18:51:30 +0000 | |||
2697 | +++ src/helper/metadata.cpp 2017-02-27 19:05:17 +0000 | |||
2698 | @@ -19,63 +19,58 @@ | |||
2699 | 19 | 19 | ||
2700 | 20 | #include "helper/metadata.h" | 20 | #include "helper/metadata.h" |
2701 | 21 | 21 | ||
2717 | 22 | /// | 22 | #include <QDebug> |
2718 | 23 | /// | 23 | #include <QJsonArray> |
2719 | 24 | 24 | #include <QJsonDocument> | |
2720 | 25 | // Metadata keys | 25 | |
2721 | 26 | const QString Metadata::TYPE_KEY = QStringLiteral("type"); | 26 | /// |
2722 | 27 | const QString Metadata::SUBTYPE_KEY = QStringLiteral("subtype"); | 27 | /// |
2723 | 28 | const QString Metadata::NAME_KEY = QStringLiteral("name"); | 28 | |
2724 | 29 | const QString Metadata::PACKAGE_KEY = QStringLiteral("package"); | 29 | // JSON Keys |
2725 | 30 | const QString Metadata::TITLE_KEY = QStringLiteral("title"); | 30 | namespace |
2726 | 31 | const QString Metadata::VERSION_KEY = QStringLiteral("version"); | 31 | { |
2727 | 32 | 32 | constexpr const char PROPERTIES_KEY[] = "properties"; | |
2728 | 33 | // Metadata values | 33 | } |
2714 | 34 | const QString Metadata::FOLDER_VALUE = QStringLiteral("folder"); | ||
2715 | 35 | const QString Metadata::SYSTEM_DATA_VALUE = QStringLiteral("system-data"); | ||
2716 | 36 | const QString Metadata::APPLICATION_VALUE = QStringLiteral("application"); | ||
2729 | 37 | 34 | ||
2730 | 38 | /// | 35 | /// |
2731 | 39 | /// | 36 | /// |
2732 | 40 | 37 | ||
2733 | 41 | Metadata::Metadata() | 38 | Metadata::Metadata() |
2738 | 42 | : uuid_() | 39 | : keeper::Item() |
2739 | 43 | , display_name_() | 40 | { |
2740 | 44 | , properties_() | 41 | } |
2741 | 45 | { | 42 | |
2742 | 43 | Metadata::Metadata(QJsonObject const & json) | ||
2743 | 44 | : keeper::Item() | ||
2744 | 45 | { | ||
2745 | 46 | auto properties = json[PROPERTIES_KEY].toObject(); | ||
2746 | 47 | for (auto const & key : properties.keys()) | ||
2747 | 48 | { | ||
2748 | 49 | this->insert(key, properties[key].toString()); | ||
2749 | 50 | } | ||
2750 | 46 | } | 51 | } |
2751 | 47 | 52 | ||
2752 | 48 | Metadata::Metadata(QString const& uuid, QString const& display_name) | 53 | Metadata::Metadata(QString const& uuid, QString const& display_name) |
2784 | 49 | : uuid_(uuid) | 54 | : keeper::Item() |
2785 | 50 | , display_name_(display_name) | 55 | { |
2786 | 51 | , properties_() | 56 | this->insert(keeper::Item::UUID_KEY, uuid); |
2787 | 52 | { | 57 | this->insert(keeper::Item::DISPLAY_NAME_KEY, display_name); |
2788 | 53 | } | 58 | } |
2789 | 54 | 59 | ||
2790 | 55 | bool | 60 | QJsonObject |
2791 | 56 | Metadata::get_property(QString const& property_name, QString& setme) const | 61 | Metadata::json() const |
2792 | 57 | { | 62 | { |
2793 | 58 | auto it = properties_.constFind(property_name); | 63 | QJsonArray json_properties; |
2794 | 59 | const bool found = it != properties_.end(); | 64 | QJsonObject properties_obj; |
2795 | 60 | 65 | for (auto iter = this->begin(); iter != this->end(); ++iter) | |
2796 | 61 | if (found) | 66 | { |
2797 | 62 | setme = it.value(); | 67 | properties_obj[iter.key()] = (*iter).toString(); |
2798 | 63 | 68 | } | |
2799 | 64 | return found; | 69 | |
2800 | 65 | } | 70 | QJsonObject ret |
2801 | 66 | 71 | { | |
2802 | 67 | void | 72 | { PROPERTIES_KEY, properties_obj } |
2803 | 68 | Metadata::set_property(QString const& property_name, QString const& value) | 73 | }; |
2804 | 69 | { | 74 | |
2774 | 70 | properties_.insert(property_name, value); | ||
2775 | 71 | } | ||
2776 | 72 | |||
2777 | 73 | QMap<QString,QString> | ||
2778 | 74 | Metadata::get_public_properties() const | ||
2779 | 75 | { | ||
2780 | 76 | // they're all public so far... | ||
2781 | 77 | auto ret = properties_; | ||
2782 | 78 | ret.insert(QStringLiteral("uuid"), uuid_); | ||
2783 | 79 | ret.insert(QStringLiteral("display-name"), display_name_); | ||
2805 | 80 | return ret; | 75 | return ret; |
2806 | 81 | } | 76 | } |
2807 | 82 | 77 | ||
2808 | === added file 'src/helper/restore-helper.cpp' | |||
2809 | --- src/helper/restore-helper.cpp 1970-01-01 00:00:00 +0000 | |||
2810 | +++ src/helper/restore-helper.cpp 2017-02-27 19:05:17 +0000 | |||
2811 | @@ -0,0 +1,377 @@ | |||
2812 | 1 | /* | ||
2813 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
2814 | 3 | * | ||
2815 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
2816 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
2817 | 6 | * by the Free Software Foundation. | ||
2818 | 7 | * | ||
2819 | 8 | * This program is distributed in the hope that it will be useful, but | ||
2820 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
2821 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
2822 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
2823 | 12 | * | ||
2824 | 13 | * You should have received a copy of the GNU General Public License along | ||
2825 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2826 | 15 | * | ||
2827 | 16 | * Authors: | ||
2828 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
2829 | 18 | * Charles Kerr <charles.kerr@canonical.com> | ||
2830 | 19 | */ | ||
2831 | 20 | |||
2832 | 21 | #include "util/connection-helper.h" | ||
2833 | 22 | #include "helper/restore-helper.h" | ||
2834 | 23 | #include "service/app-const.h" // HELPER_TYPE | ||
2835 | 24 | |||
2836 | 25 | #include <QByteArray> | ||
2837 | 26 | #include <QDebug> | ||
2838 | 27 | #include <QLocalSocket> | ||
2839 | 28 | #include <QMap> | ||
2840 | 29 | #include <QObject> | ||
2841 | 30 | #include <QString> | ||
2842 | 31 | #include <QTimer> | ||
2843 | 32 | #include <QVector> | ||
2844 | 33 | |||
2845 | 34 | #include <fcntl.h> | ||
2846 | 35 | #include <sys/types.h> | ||
2847 | 36 | #include <sys/socket.h> | ||
2848 | 37 | |||
2849 | 38 | #include <functional> // std::bind() | ||
2850 | 39 | |||
2851 | 40 | |||
2852 | 41 | class RestoreHelperPrivate | ||
2853 | 42 | { | ||
2854 | 43 | public: | ||
2855 | 44 | |||
2856 | 45 | explicit RestoreHelperPrivate( | ||
2857 | 46 | RestoreHelper* backup_helper | ||
2858 | 47 | ) | ||
2859 | 48 | : q_ptr(backup_helper) | ||
2860 | 49 | { | ||
2861 | 50 | // listen for inactivity from storage framework | ||
2862 | 51 | QObject::connect(&timer_, &QTimer::timeout, | ||
2863 | 52 | std::bind(&RestoreHelperPrivate::on_inactivity_detected, this) | ||
2864 | 53 | ); | ||
2865 | 54 | |||
2866 | 55 | // fire up the sockets | ||
2867 | 56 | int fds[2]; | ||
2868 | 57 | int rc = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds); | ||
2869 | 58 | if (rc == -1) | ||
2870 | 59 | { | ||
2871 | 60 | qWarning() << QStringLiteral("Error creating socket to communicate with helper");; | ||
2872 | 61 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_SOCKET)); | ||
2873 | 62 | return; | ||
2874 | 63 | } | ||
2875 | 64 | |||
2876 | 65 | // helper socket is for the client. | ||
2877 | 66 | // We don't use a QLocalSocket here as it buffers data and it makes the helper miss packets. | ||
2878 | 67 | helper_socket_ = fds[1]; | ||
2879 | 68 | |||
2880 | 69 | write_socket_.setSocketDescriptor(fds[0], QLocalSocket::ConnectedState, QIODevice::WriteOnly); | ||
2881 | 70 | } | ||
2882 | 71 | |||
2883 | 72 | ~RestoreHelperPrivate() = default; | ||
2884 | 73 | |||
2885 | 74 | Q_DISABLE_COPY(RestoreHelperPrivate) | ||
2886 | 75 | |||
2887 | 76 | void start(QStringList const& urls) | ||
2888 | 77 | { | ||
2889 | 78 | q_ptr->Helper::start(urls); | ||
2890 | 79 | reset_inactivity_timer(); | ||
2891 | 80 | } | ||
2892 | 81 | |||
2893 | 82 | void set_downloader(std::shared_ptr<Downloader> const& downloader) | ||
2894 | 83 | { | ||
2895 | 84 | n_read_ = 0; | ||
2896 | 85 | n_uploaded_ = 0; | ||
2897 | 86 | read_error_ = false; | ||
2898 | 87 | write_error_ = false; | ||
2899 | 88 | cancelled_ = false; | ||
2900 | 89 | |||
2901 | 90 | q_ptr->set_expected_size(downloader->file_size()); | ||
2902 | 91 | downloader_ = downloader; | ||
2903 | 92 | |||
2904 | 93 | connections_.remember(QObject::connect( | ||
2905 | 94 | &write_socket_, &QLocalSocket::bytesWritten, | ||
2906 | 95 | std::bind(&RestoreHelperPrivate::on_data_uploaded, this, std::placeholders::_1) | ||
2907 | 96 | )); | ||
2908 | 97 | |||
2909 | 98 | // listen for data ready to read | ||
2910 | 99 | QObject::connect(downloader_->socket().get(), &QLocalSocket::readyRead, | ||
2911 | 100 | std::bind(&RestoreHelperPrivate::on_ready_read, this) | ||
2912 | 101 | ); | ||
2913 | 102 | |||
2914 | 103 | // TODO investigate why UAL takes so long to call the helper started callback | ||
2915 | 104 | // At this point we are sure that the helper started, as it is the helper | ||
2916 | 105 | // the ones that asks for a downloader socket. | ||
2917 | 106 | q_ptr->Helper::on_helper_started(); | ||
2918 | 107 | |||
2919 | 108 | // maybe there's data already to be read | ||
2920 | 109 | process_more(); | ||
2921 | 110 | |||
2922 | 111 | reset_inactivity_timer(); | ||
2923 | 112 | } | ||
2924 | 113 | |||
2925 | 114 | void stop() | ||
2926 | 115 | { | ||
2927 | 116 | write_socket_.disconnectFromServer(); | ||
2928 | 117 | cancelled_ = true; | ||
2929 | 118 | q_ptr->Helper::stop(); | ||
2930 | 119 | } | ||
2931 | 120 | |||
2932 | 121 | int get_helper_socket() const | ||
2933 | 122 | { | ||
2934 | 123 | return helper_socket_; | ||
2935 | 124 | } | ||
2936 | 125 | |||
2937 | 126 | QString to_string(Helper::State state) const | ||
2938 | 127 | { | ||
2939 | 128 | return state == Helper::State::STARTED | ||
2940 | 129 | ? QStringLiteral("restoring") | ||
2941 | 130 | : q_ptr->Helper::to_string(state); | ||
2942 | 131 | } | ||
2943 | 132 | |||
2944 | 133 | void on_state_changed(Helper::State state) | ||
2945 | 134 | { | ||
2946 | 135 | switch (state) | ||
2947 | 136 | { | ||
2948 | 137 | case Helper::State::CANCELLED: | ||
2949 | 138 | case Helper::State::FAILED: | ||
2950 | 139 | qDebug() << "cancelled/failed, calling downloader_.reset()"; | ||
2951 | 140 | downloader_.reset(); | ||
2952 | 141 | break; | ||
2953 | 142 | |||
2954 | 143 | case Helper::State::DATA_COMPLETE: { | ||
2955 | 144 | qDebug() << "Restore helper finished, calling downloader_.finish()"; | ||
2956 | 145 | write_socket_.disconnectFromServer(); | ||
2957 | 146 | downloader_->finish(); | ||
2958 | 147 | downloader_.reset(); | ||
2959 | 148 | break; | ||
2960 | 149 | } | ||
2961 | 150 | |||
2962 | 151 | //case Helper::State::NOT_STARTED: | ||
2963 | 152 | //case Helper::State::STARTED: | ||
2964 | 153 | default: | ||
2965 | 154 | break; | ||
2966 | 155 | } | ||
2967 | 156 | } | ||
2968 | 157 | |||
2969 | 158 | void on_helper_finished() | ||
2970 | 159 | { | ||
2971 | 160 | stop_inactivity_timer(); | ||
2972 | 161 | check_for_done(); | ||
2973 | 162 | } | ||
2974 | 163 | |||
2975 | 164 | private: | ||
2976 | 165 | |||
2977 | 166 | void on_inactivity_detected() | ||
2978 | 167 | { | ||
2979 | 168 | stop_inactivity_timer(); | ||
2980 | 169 | qWarning() << "Inactivity detected in the helper...stopping it"; | ||
2981 | 170 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_INACTIVITY_DETECTED)); | ||
2982 | 171 | stop(); | ||
2983 | 172 | } | ||
2984 | 173 | |||
2985 | 174 | void on_ready_read() | ||
2986 | 175 | { | ||
2987 | 176 | process_more(); | ||
2988 | 177 | } | ||
2989 | 178 | |||
2990 | 179 | void on_data_uploaded(qint64 n) | ||
2991 | 180 | { | ||
2992 | 181 | n_uploaded_ += n; | ||
2993 | 182 | q_ptr->record_data_transferred(n); | ||
2994 | 183 | process_more(); | ||
2995 | 184 | check_for_done(); | ||
2996 | 185 | } | ||
2997 | 186 | |||
2998 | 187 | void process_more() | ||
2999 | 188 | { | ||
3000 | 189 | if (!downloader_) | ||
3001 | 190 | return; | ||
3002 | 191 | |||
3003 | 192 | char readbuf[UPLOAD_BUFFER_MAX_]; | ||
3004 | 193 | auto socket = downloader_->socket(); | ||
3005 | 194 | while(socket->bytesAvailable() || upload_buffer_.size()) | ||
3006 | 195 | { | ||
3007 | 196 | if (socket->bytesAvailable()) | ||
3008 | 197 | { | ||
3009 | 198 | // try to fill the upload buf | ||
3010 | 199 | int max_bytes = UPLOAD_BUFFER_MAX_ - upload_buffer_.size(); | ||
3011 | 200 | if (max_bytes > 0) { | ||
3012 | 201 | const auto n = socket->read(readbuf, max_bytes); | ||
3013 | 202 | if (n > 0) { | ||
3014 | 203 | n_read_ += n; | ||
3015 | 204 | upload_buffer_.append(readbuf, int(n)); | ||
3016 | 205 | } | ||
3017 | 206 | else if (n < 0) { | ||
3018 | 207 | read_error_ = true; | ||
3019 | 208 | qDebug() << "Read error in restore helper: " << socket->errorString(); | ||
3020 | 209 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_READ)); | ||
3021 | 210 | stop(); | ||
3022 | 211 | check_for_done(); | ||
3023 | 212 | return; | ||
3024 | 213 | } | ||
3025 | 214 | } | ||
3026 | 215 | } | ||
3027 | 216 | |||
3028 | 217 | if (upload_buffer_.size()) | ||
3029 | 218 | { | ||
3030 | 219 | // try to empty the upload buf | ||
3031 | 220 | const auto n = write_socket_.write(upload_buffer_); | ||
3032 | 221 | if (n > 0) { | ||
3033 | 222 | upload_buffer_.remove(0, int(n)); | ||
3034 | 223 | continue; | ||
3035 | 224 | } | ||
3036 | 225 | else { | ||
3037 | 226 | if (n < 0) { | ||
3038 | 227 | write_error_ = true; | ||
3039 | 228 | qWarning() << "Write error:" << write_socket_.errorString(); | ||
3040 | 229 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_WRITE)); | ||
3041 | 230 | stop(); | ||
3042 | 231 | check_for_done(); | ||
3043 | 232 | } | ||
3044 | 233 | break; | ||
3045 | 234 | } | ||
3046 | 235 | } | ||
3047 | 236 | } | ||
3048 | 237 | |||
3049 | 238 | reset_inactivity_timer(); | ||
3050 | 239 | } | ||
3051 | 240 | |||
3052 | 241 | void reset_inactivity_timer() | ||
3053 | 242 | { | ||
3054 | 243 | static constexpr int MAX_TIME_WAITING_FOR_DATA {RestoreHelper::MAX_INACTIVITY_TIME}; | ||
3055 | 244 | timer_.start(MAX_TIME_WAITING_FOR_DATA); | ||
3056 | 245 | } | ||
3057 | 246 | |||
3058 | 247 | void stop_inactivity_timer() | ||
3059 | 248 | { | ||
3060 | 249 | timer_.stop(); | ||
3061 | 250 | } | ||
3062 | 251 | |||
3063 | 252 | void check_for_done() | ||
3064 | 253 | { | ||
3065 | 254 | if (cancelled_) | ||
3066 | 255 | { | ||
3067 | 256 | q_ptr->set_state(Helper::State::CANCELLED); | ||
3068 | 257 | } | ||
3069 | 258 | else if (read_error_ || write_error_ || n_uploaded_ > q_ptr->expected_size()) | ||
3070 | 259 | { | ||
3071 | 260 | if (!q_ptr->is_helper_running()) | ||
3072 | 261 | { | ||
3073 | 262 | if (n_uploaded_ > q_ptr->expected_size()) | ||
3074 | 263 | { | ||
3075 | 264 | Q_EMIT(q_ptr->error(keeper::Error::HELPER_WRITE)); | ||
3076 | 265 | } | ||
3077 | 266 | q_ptr->set_state(Helper::State::FAILED); | ||
3078 | 267 | } | ||
3079 | 268 | } | ||
3080 | 269 | else if (n_uploaded_ == q_ptr->expected_size()) | ||
3081 | 270 | { | ||
3082 | 271 | if (downloader_) | ||
3083 | 272 | { | ||
3084 | 273 | if (q_ptr->is_helper_running()) | ||
3085 | 274 | { | ||
3086 | 275 | // only in the case that the helper process finished we move to the next state | ||
3087 | 276 | // this is to prevent to start the next task too early | ||
3088 | 277 | q_ptr->set_state(Helper::State::DATA_COMPLETE); | ||
3089 | 278 | stop_inactivity_timer(); | ||
3090 | 279 | } | ||
3091 | 280 | } | ||
3092 | 281 | else | ||
3093 | 282 | q_ptr->set_state(Helper::State::COMPLETE); | ||
3094 | 283 | } | ||
3095 | 284 | } | ||
3096 | 285 | |||
3097 | 286 | /*** | ||
3098 | 287 | **** | ||
3099 | 288 | ***/ | ||
3100 | 289 | |||
3101 | 290 | static constexpr int UPLOAD_BUFFER_MAX_ {1024*16}; | ||
3102 | 291 | |||
3103 | 292 | RestoreHelper * const q_ptr; | ||
3104 | 293 | QTimer timer_; | ||
3105 | 294 | std::shared_ptr<Downloader> downloader_; | ||
3106 | 295 | int helper_socket_ = -1; | ||
3107 | 296 | QLocalSocket write_socket_; | ||
3108 | 297 | QByteArray upload_buffer_; | ||
3109 | 298 | qint64 n_read_ = 0; | ||
3110 | 299 | qint64 n_uploaded_ = 0; | ||
3111 | 300 | bool read_error_ = false; | ||
3112 | 301 | bool write_error_ = false; | ||
3113 | 302 | bool cancelled_ = false; | ||
3114 | 303 | ConnectionHelper connections_; | ||
3115 | 304 | }; | ||
3116 | 305 | |||
3117 | 306 | /*** | ||
3118 | 307 | **** | ||
3119 | 308 | ***/ | ||
3120 | 309 | |||
3121 | 310 | RestoreHelper::RestoreHelper( | ||
3122 | 311 | QString const & appid, | ||
3123 | 312 | clock_func const & clock, | ||
3124 | 313 | QObject * parent | ||
3125 | 314 | ) | ||
3126 | 315 | : Helper(appid, clock, parent) | ||
3127 | 316 | , d_ptr(new RestoreHelperPrivate(this)) | ||
3128 | 317 | { | ||
3129 | 318 | } | ||
3130 | 319 | |||
3131 | 320 | RestoreHelper::~RestoreHelper() =default; | ||
3132 | 321 | |||
3133 | 322 | void | ||
3134 | 323 | RestoreHelper::start(QStringList const& url) | ||
3135 | 324 | { | ||
3136 | 325 | Q_D(RestoreHelper); | ||
3137 | 326 | |||
3138 | 327 | d->start(url); | ||
3139 | 328 | } | ||
3140 | 329 | |||
3141 | 330 | void | ||
3142 | 331 | RestoreHelper::stop() | ||
3143 | 332 | { | ||
3144 | 333 | Q_D(RestoreHelper); | ||
3145 | 334 | |||
3146 | 335 | d->stop(); | ||
3147 | 336 | } | ||
3148 | 337 | |||
3149 | 338 | void | ||
3150 | 339 | RestoreHelper::set_downloader(std::shared_ptr<Downloader> const& downloader) | ||
3151 | 340 | { | ||
3152 | 341 | Q_D(RestoreHelper); | ||
3153 | 342 | |||
3154 | 343 | d->set_downloader(downloader); | ||
3155 | 344 | } | ||
3156 | 345 | |||
3157 | 346 | int | ||
3158 | 347 | RestoreHelper::get_helper_socket() const | ||
3159 | 348 | { | ||
3160 | 349 | Q_D(const RestoreHelper); | ||
3161 | 350 | |||
3162 | 351 | return d->get_helper_socket(); | ||
3163 | 352 | } | ||
3164 | 353 | |||
3165 | 354 | QString | ||
3166 | 355 | RestoreHelper::to_string(Helper::State state) const | ||
3167 | 356 | { | ||
3168 | 357 | Q_D(const RestoreHelper); | ||
3169 | 358 | |||
3170 | 359 | return d->to_string(state); | ||
3171 | 360 | } | ||
3172 | 361 | |||
3173 | 362 | void | ||
3174 | 363 | RestoreHelper::set_state(Helper::State state) | ||
3175 | 364 | { | ||
3176 | 365 | Q_D(RestoreHelper); | ||
3177 | 366 | |||
3178 | 367 | Helper::set_state(state); | ||
3179 | 368 | d->on_state_changed(state); | ||
3180 | 369 | } | ||
3181 | 370 | |||
3182 | 371 | void RestoreHelper::on_helper_finished() | ||
3183 | 372 | { | ||
3184 | 373 | Q_D(RestoreHelper); | ||
3185 | 374 | |||
3186 | 375 | Helper::on_helper_finished(); | ||
3187 | 376 | d->on_helper_finished(); | ||
3188 | 377 | } | ||
3189 | 0 | 378 | ||
3190 | === modified file 'src/qdbus-stubs/CMakeLists.txt' | |||
3191 | --- src/qdbus-stubs/CMakeLists.txt 2016-08-10 05:41:26 +0000 | |||
3192 | +++ src/qdbus-stubs/CMakeLists.txt 2017-02-27 19:05:17 +0000 | |||
3193 | @@ -67,6 +67,7 @@ | |||
3194 | 67 | ${user_xml} | 67 | ${user_xml} |
3195 | 68 | PROPERTIES | 68 | PROPERTIES |
3196 | 69 | CLASSNAME DBusInterfaceKeeperUser | 69 | CLASSNAME DBusInterfaceKeeperUser |
3197 | 70 | INCLUDE "client/keeper-items.h" | ||
3198 | 70 | ) | 71 | ) |
3199 | 71 | 72 | ||
3200 | 72 | qt5_add_dbus_interface( | 73 | qt5_add_dbus_interface( |
3201 | @@ -84,6 +85,23 @@ | |||
3202 | 84 | KeeperUserAdaptor | 85 | KeeperUserAdaptor |
3203 | 85 | ) | 86 | ) |
3204 | 86 | 87 | ||
3205 | 88 | set( | ||
3206 | 89 | properties_xml | ||
3207 | 90 | "org.freedesktop.DBus.Properties.xml" | ||
3208 | 91 | ) | ||
3209 | 92 | |||
3210 | 93 | set_source_files_properties( | ||
3211 | 94 | "${properties_xml}" | ||
3212 | 95 | PROPERTIES | ||
3213 | 96 | NO_NAMESPACE YES | ||
3214 | 97 | CLASSNAME DBusPropertiesInterface | ||
3215 | 98 | ) | ||
3216 | 99 | |||
3217 | 100 | qt5_add_dbus_interface( | ||
3218 | 101 | interface_files | ||
3219 | 102 | ${properties_xml} | ||
3220 | 103 | DBusPropertiesInterface | ||
3221 | 104 | ) | ||
3222 | 87 | # | 105 | # |
3223 | 88 | # | 106 | # |
3224 | 89 | 107 | ||
3225 | @@ -101,5 +119,5 @@ | |||
3226 | 101 | 119 | ||
3227 | 102 | target_link_libraries( | 120 | target_link_libraries( |
3228 | 103 | ${STUBS_LIB} | 121 | ${STUBS_LIB} |
3230 | 104 | backup-helper | 122 | keeper-errors-lib |
3231 | 105 | ) | 123 | ) |
3232 | 106 | 124 | ||
3233 | === modified file 'src/qdbus-stubs/com.canonical.keeper.User.xml' | |||
3234 | --- src/qdbus-stubs/com.canonical.keeper.User.xml 2016-07-28 19:44:52 +0000 | |||
3235 | +++ src/qdbus-stubs/com.canonical.keeper.User.xml 2017-02-27 19:05:17 +0000 | |||
3236 | @@ -5,7 +5,7 @@ | |||
3237 | 5 | <interface name="com.canonical.keeper.User"> | 5 | <interface name="com.canonical.keeper.User"> |
3238 | 6 | 6 | ||
3239 | 7 | <method name="GetBackupChoices"> | 7 | <method name="GetBackupChoices"> |
3241 | 8 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantDictMap"/> | 8 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="keeper::Items"/> |
3242 | 9 | <arg direction="out" name="backups" type="a{sa{sv}}"> | 9 | <arg direction="out" name="backups" type="a{sa{sv}}"> |
3243 | 10 | <doc:doc> | 10 | <doc:doc> |
3244 | 11 | <doc:summary>A list of backup possibilities for the user to choose from</doc:summary> | 11 | <doc:summary>A list of backup possibilities for the user to choose from</doc:summary> |
3245 | @@ -32,10 +32,32 @@ | |||
3246 | 32 | </doc:description> | 32 | </doc:description> |
3247 | 33 | </doc:doc> | 33 | </doc:doc> |
3248 | 34 | </arg> | 34 | </arg> |
3249 | 35 | <arg direction="in" name="storage" type="s"> | ||
3250 | 36 | <doc:doc> | ||
3251 | 37 | <doc:summary>The storage identifier</doc:summary> | ||
3252 | 38 | <doc:description> | ||
3253 | 39 | <doc:para>Because keeper supports multiple storage providers the user can define | ||
3254 | 40 | which is the storage provider to use. | ||
3255 | 41 | If the passed storage id is an empty string the default storage provider | ||
3256 | 42 | will be used.</doc:para> | ||
3257 | 43 | </doc:description> | ||
3258 | 44 | </doc:doc> | ||
3259 | 45 | </arg> | ||
3260 | 35 | </method> | 46 | </method> |
3261 | 36 | 47 | ||
3262 | 37 | <method name="GetRestoreChoices"> | 48 | <method name="GetRestoreChoices"> |
3264 | 38 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantDictMap"/> | 49 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="keeper::Items"/> |
3265 | 50 | <arg direction="in" name="storage" type="s"> | ||
3266 | 51 | <doc:doc> | ||
3267 | 52 | <doc:summary>The storage identifier</doc:summary> | ||
3268 | 53 | <doc:description> | ||
3269 | 54 | <doc:para>Because keeper supports multiple storage providers the user can define | ||
3270 | 55 | which is the storage provider to use. | ||
3271 | 56 | If the passed storage id is an empty string the default storage provider | ||
3272 | 57 | will be used.</doc:para> | ||
3273 | 58 | </doc:description> | ||
3274 | 59 | </doc:doc> | ||
3275 | 60 | </arg> | ||
3276 | 39 | <arg direction="out" name="backups" type="a{sa{sv}}"> | 61 | <arg direction="out" name="backups" type="a{sa{sv}}"> |
3277 | 40 | <doc:doc> | 62 | <doc:doc> |
3278 | 41 | <doc:summary>The backups which already exist and can be restored</doc:summary> | 63 | <doc:summary>The backups which already exist and can be restored</doc:summary> |
3279 | @@ -62,10 +84,21 @@ | |||
3280 | 62 | </doc:description> | 84 | </doc:description> |
3281 | 63 | </doc:doc> | 85 | </doc:doc> |
3282 | 64 | </arg> | 86 | </arg> |
3283 | 87 | <arg direction="in" name="storage" type="s"> | ||
3284 | 88 | <doc:doc> | ||
3285 | 89 | <doc:summary>The storage identifier</doc:summary> | ||
3286 | 90 | <doc:description> | ||
3287 | 91 | <doc:para>Because keeper supports multiple storage providers the user can define | ||
3288 | 92 | which is the storage provider to use. | ||
3289 | 93 | If the passed storage id is an empty string the default storage provider | ||
3290 | 94 | will be used.</doc:para> | ||
3291 | 95 | </doc:description> | ||
3292 | 96 | </doc:doc> | ||
3293 | 97 | </arg> | ||
3294 | 65 | </method> | 98 | </method> |
3295 | 66 | 99 | ||
3296 | 67 | <property name="State" type="a{sa{sv}}" access="read"> | 100 | <property name="State" type="a{sa{sv}}" access="read"> |
3298 | 68 | <annotation name="org.qtproject.QtDBus.QtTypeName" value="QVariantDictMap"/> | 101 | <annotation name="org.qtproject.QtDBus.QtTypeName" value="keeper::Items"/> |
3299 | 69 | <doc:doc> | 102 | <doc:doc> |
3300 | 70 | <doc:description> | 103 | <doc:description> |
3301 | 71 | <doc:para>Provides state information so the user interface can show | 104 | <doc:para>Provides state information so the user interface can show |
3302 | @@ -86,6 +119,17 @@ | |||
3303 | 86 | </doc:doc> | 119 | </doc:doc> |
3304 | 87 | </property> | 120 | </property> |
3305 | 88 | 121 | ||
3306 | 122 | <method name="GetStorageAccounts"> | ||
3307 | 123 | <arg direction="out" name="accounts" type="as"> | ||
3308 | 124 | <doc:doc> | ||
3309 | 125 | <doc:summary>The list of available storage accounts.</doc:summary> | ||
3310 | 126 | <doc:description> | ||
3311 | 127 | <doc:para>An array of the available accounts to choose from to backup/restore</doc:para> | ||
3312 | 128 | </doc:description> | ||
3313 | 129 | </doc:doc> | ||
3314 | 130 | </arg> | ||
3315 | 131 | </method> | ||
3316 | 132 | |||
3317 | 89 | <method name="Cancel"> | 133 | <method name="Cancel"> |
3318 | 90 | <doc:doc> | 134 | <doc:doc> |
3319 | 91 | <doc:summary>Cancels the current backup or restore actions.</doc:summary> | 135 | <doc:summary>Cancels the current backup or restore actions.</doc:summary> |
3320 | 92 | 136 | ||
3321 | === modified file 'src/qdbus-stubs/dbus-types.h' | |||
3322 | --- src/qdbus-stubs/dbus-types.h 2016-07-14 15:31:11 +0000 | |||
3323 | +++ src/qdbus-stubs/dbus-types.h 2017-02-27 19:05:17 +0000 | |||
3324 | @@ -22,7 +22,8 @@ | |||
3325 | 22 | #include <QtCore> | 22 | #include <QtCore> |
3326 | 23 | #include <QString> | 23 | #include <QString> |
3327 | 24 | #include <QVariantMap> | 24 | #include <QVariantMap> |
3329 | 25 | #include <helper/helper.h> | 25 | #include <client/keeper-errors.h> |
3330 | 26 | #include "client/keeper-items.h" | ||
3331 | 26 | 27 | ||
3332 | 27 | typedef QMap<QString, QVariantMap> QVariantDictMap; | 28 | typedef QMap<QString, QVariantMap> QVariantDictMap; |
3333 | 28 | Q_DECLARE_METATYPE(QVariantDictMap) | 29 | Q_DECLARE_METATYPE(QVariantDictMap) |
3334 | @@ -36,10 +37,13 @@ | |||
3335 | 36 | { | 37 | { |
3336 | 37 | qRegisterMetaType<QVariantDictMap>("QVariantDictMap"); | 38 | qRegisterMetaType<QVariantDictMap>("QVariantDictMap"); |
3337 | 38 | qRegisterMetaType<QStringMap>("QStringMap"); | 39 | qRegisterMetaType<QStringMap>("QStringMap"); |
3338 | 40 | qRegisterMetaType<keeper::Error>("keeper::Error"); | ||
3339 | 39 | 41 | ||
3340 | 40 | qDBusRegisterMetaType<QVariantDictMap>(); | 42 | qDBusRegisterMetaType<QVariantDictMap>(); |
3341 | 41 | qDBusRegisterMetaType<QStringMap>(); | 43 | qDBusRegisterMetaType<QStringMap>(); |
3343 | 42 | Helper::registerMetaTypes(); | 44 | qDBusRegisterMetaType<keeper::Error>(); |
3344 | 45 | |||
3345 | 46 | keeper::Items::registerMetaType(); | ||
3346 | 43 | } | 47 | } |
3347 | 44 | 48 | ||
3348 | 45 | constexpr const char KEEPER_SERVICE[] = "com.canonical.keeper"; | 49 | constexpr const char KEEPER_SERVICE[] = "com.canonical.keeper"; |
3349 | 46 | 50 | ||
3350 | === added file 'src/qdbus-stubs/org.freedesktop.DBus.Properties.xml' | |||
3351 | --- src/qdbus-stubs/org.freedesktop.DBus.Properties.xml 1970-01-01 00:00:00 +0000 | |||
3352 | +++ src/qdbus-stubs/org.freedesktop.DBus.Properties.xml 2017-02-27 19:05:17 +0000 | |||
3353 | @@ -0,0 +1,27 @@ | |||
3354 | 1 | <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" | ||
3355 | 2 | "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> | ||
3356 | 3 | <node> | ||
3357 | 4 | <interface name="org.freedesktop.DBus.Properties"> | ||
3358 | 5 | <method name="Get"> | ||
3359 | 6 | <arg type="s" name="interface_name" direction="in"/> | ||
3360 | 7 | <arg type="s" name="property_name" direction="in"/> | ||
3361 | 8 | <arg type="v" name="value" direction="out"/> | ||
3362 | 9 | </method> | ||
3363 | 10 | <method name="GetAll"> | ||
3364 | 11 | <arg type="s" name="interface_name" direction="in"/> | ||
3365 | 12 | <arg type="a{sv}" name="properties" direction="out"/> | ||
3366 | 13 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/> | ||
3367 | 14 | </method> | ||
3368 | 15 | <method name="Set"> | ||
3369 | 16 | <arg type="s" name="interface_name" direction="in"/> | ||
3370 | 17 | <arg type="s" name="property_name" direction="in"/> | ||
3371 | 18 | <arg type="v" name="value" direction="in"/> | ||
3372 | 19 | </method> | ||
3373 | 20 | <signal name="PropertiesChanged"> | ||
3374 | 21 | <arg type="s" name="interface_name"/> | ||
3375 | 22 | <arg type="a{sv}" name="changed_properties"/> | ||
3376 | 23 | <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/> | ||
3377 | 24 | <arg type="as" name="invalidated_properties"/> | ||
3378 | 25 | </signal> | ||
3379 | 26 | </interface> | ||
3380 | 27 | </node> | ||
3381 | 0 | 28 | ||
3382 | === modified file 'src/service/CMakeLists.txt' | |||
3383 | --- src/service/CMakeLists.txt 2016-09-06 01:31:59 +0000 | |||
3384 | +++ src/service/CMakeLists.txt 2017-02-27 19:05:17 +0000 | |||
3385 | @@ -15,6 +15,9 @@ | |||
3386 | 15 | task-manager.cpp | 15 | task-manager.cpp |
3387 | 16 | keeper-task.cpp | 16 | keeper-task.cpp |
3388 | 17 | keeper-task-backup.cpp | 17 | keeper-task-backup.cpp |
3389 | 18 | keeper-task-restore.cpp | ||
3390 | 19 | manifest.cpp | ||
3391 | 20 | metadata-provider.h | ||
3392 | 18 | ) | 21 | ) |
3393 | 19 | add_library( | 22 | add_library( |
3394 | 20 | ${SERVICE_LIB} | 23 | ${SERVICE_LIB} |
3395 | @@ -46,6 +49,7 @@ | |||
3396 | 46 | storage-framework | 49 | storage-framework |
3397 | 47 | util | 50 | util |
3398 | 48 | qdbus-stubs | 51 | qdbus-stubs |
3399 | 52 | keeper-errors-lib | ||
3400 | 49 | ) | 53 | ) |
3401 | 50 | 54 | ||
3402 | 51 | target_link_libraries( | 55 | target_link_libraries( |
3403 | 52 | 56 | ||
3404 | === modified file 'src/service/backup-choices.cpp' | |||
3405 | --- src/service/backup-choices.cpp 2016-09-05 18:38:36 +0000 | |||
3406 | +++ src/service/backup-choices.cpp 2017-02-27 19:05:17 +0000 | |||
3407 | @@ -45,22 +45,30 @@ | |||
3408 | 45 | } | 45 | } |
3409 | 46 | } | 46 | } |
3410 | 47 | 47 | ||
3412 | 48 | BackupChoices::BackupChoices() =default; | 48 | BackupChoices::BackupChoices(QObject *parent) |
3413 | 49 | : MetadataProvider(parent) | ||
3414 | 50 | { | ||
3415 | 51 | } | ||
3416 | 49 | 52 | ||
3417 | 50 | BackupChoices::~BackupChoices() =default; | 53 | BackupChoices::~BackupChoices() =default; |
3418 | 51 | 54 | ||
3419 | 52 | QVector<Metadata> | 55 | QVector<Metadata> |
3420 | 53 | BackupChoices::get_backups() const | 56 | BackupChoices::get_backups() const |
3421 | 54 | { | 57 | { |
3423 | 55 | QVector<Metadata> ret; | 58 | return backups_; |
3424 | 59 | } | ||
3425 | 56 | 60 | ||
3426 | 61 | void | ||
3427 | 62 | BackupChoices::get_backups_async(QString const & /*storage*/) | ||
3428 | 63 | { | ||
3429 | 64 | backups_.clear(); | ||
3430 | 57 | // | 65 | // |
3431 | 58 | // System Data | 66 | // System Data |
3432 | 59 | // | 67 | // |
3433 | 60 | { | 68 | { |
3434 | 61 | Metadata m(generate_new_uuid(), "System Data"); // FIXME: how to i18n in a Qt DBus service? | 69 | Metadata m(generate_new_uuid(), "System Data"); // FIXME: how to i18n in a Qt DBus service? |
3437 | 62 | m.set_property(Metadata::TYPE_KEY, Metadata::SYSTEM_DATA_VALUE); | 70 | m.set_property_value(Metadata::TYPE_KEY, Metadata::SYSTEM_DATA_VALUE); |
3438 | 63 | ret.push_back(m); | 71 | backups_.push_back(m); |
3439 | 64 | } | 72 | } |
3440 | 65 | 73 | ||
3441 | 66 | // | 74 | // |
3442 | @@ -112,13 +120,13 @@ | |||
3443 | 112 | display_name = QStringLiteral("%1 (%2)").arg(display_name).arg(version.toString()); | 120 | display_name = QStringLiteral("%1 (%2)").arg(display_name).arg(version.toString()); |
3444 | 113 | 121 | ||
3445 | 114 | Metadata m(generate_new_uuid(), display_name); | 122 | Metadata m(generate_new_uuid(), display_name); |
3448 | 115 | m.set_property(Metadata::PACKAGE_KEY, name.toString()); | 123 | m.set_property_value(Metadata::PACKAGE_KEY, name.toString()); |
3449 | 116 | m.set_property(Metadata::TYPE_KEY, Metadata::APPLICATION_VALUE); | 124 | m.set_property_value(Metadata::TYPE_KEY, Metadata::APPLICATION_VALUE); |
3450 | 117 | 125 | ||
3451 | 118 | if (version != QJsonValue::Undefined) | 126 | if (version != QJsonValue::Undefined) |
3453 | 119 | m.set_property(Metadata::VERSION_KEY, version.toString()); | 127 | m.set_property_value(Metadata::VERSION_KEY, version.toString()); |
3454 | 120 | 128 | ||
3456 | 121 | ret.push_back(m); | 129 | backups_.push_back(m); |
3457 | 122 | } | 130 | } |
3458 | 123 | } | 131 | } |
3459 | 124 | } | 132 | } |
3460 | @@ -146,11 +154,11 @@ | |||
3461 | 146 | { | 154 | { |
3462 | 147 | const auto keystr = generate_new_uuid(); | 155 | const auto keystr = generate_new_uuid(); |
3463 | 148 | Metadata m(keystr, name); | 156 | Metadata m(keystr, name); |
3467 | 149 | m.set_property(Metadata::TYPE_KEY, Metadata::FOLDER_VALUE); | 157 | m.set_property_value(Metadata::TYPE_KEY, Metadata::FOLDER_VALUE); |
3468 | 150 | m.set_property(Metadata::SUBTYPE_KEY, locations.front()); | 158 | m.set_property_value(Metadata::SUBTYPE_KEY, locations.front()); |
3469 | 151 | ret.push_back(m); | 159 | backups_.push_back(m); |
3470 | 152 | } | 160 | } |
3471 | 153 | } | 161 | } |
3472 | 154 | 162 | ||
3474 | 155 | return ret; | 163 | Q_EMIT(finished(keeper::Error::OK)); |
3475 | 156 | } | 164 | } |
3476 | 157 | 165 | ||
3477 | === modified file 'src/service/backup-choices.h' | |||
3478 | --- src/service/backup-choices.h 2016-09-05 18:38:36 +0000 | |||
3479 | +++ src/service/backup-choices.h 2017-02-27 19:05:17 +0000 | |||
3480 | @@ -27,7 +27,8 @@ | |||
3481 | 27 | class BackupChoices: public MetadataProvider | 27 | class BackupChoices: public MetadataProvider |
3482 | 28 | { | 28 | { |
3483 | 29 | public: | 29 | public: |
3485 | 30 | BackupChoices(); | 30 | explicit BackupChoices(QObject *parent = nullptr); |
3486 | 31 | virtual ~BackupChoices(); | 31 | virtual ~BackupChoices(); |
3487 | 32 | QVector<Metadata> get_backups() const override; | 32 | QVector<Metadata> get_backups() const override; |
3488 | 33 | void get_backups_async(QString const & storage = "") override; | ||
3489 | 33 | }; | 34 | }; |
3490 | 34 | 35 | ||
3491 | === modified file 'src/service/keeper-helper.cpp' | |||
3492 | --- src/service/keeper-helper.cpp 2016-08-10 02:06:08 +0000 | |||
3493 | +++ src/service/keeper-helper.cpp 2017-02-27 19:05:17 +0000 | |||
3494 | @@ -44,8 +44,11 @@ | |||
3495 | 44 | 44 | ||
3496 | 45 | QDBusUnixFileDescriptor KeeperHelper::StartRestore() | 45 | QDBusUnixFileDescriptor KeeperHelper::StartRestore() |
3497 | 46 | { | 46 | { |
3500 | 47 | // TODO get the file descriptor of the item in storage framework | 47 | // pass it back to Keeper to do the work |
3501 | 48 | return QDBusUnixFileDescriptor(); | 48 | Q_ASSERT(calledFromDBus()); |
3502 | 49 | auto bus = connection(); | ||
3503 | 50 | auto& msg = message(); | ||
3504 | 51 | return keeper_.StartRestore(bus, msg); | ||
3505 | 49 | } | 52 | } |
3506 | 50 | 53 | ||
3507 | 51 | void KeeperHelper::UpdateStatus(const QString &app_id, const QString &status, double percentage) | 54 | void KeeperHelper::UpdateStatus(const QString &app_id, const QString &status, double percentage) |
3508 | 52 | 55 | ||
3509 | === modified file 'src/service/keeper-task-backup.cpp' | |||
3510 | --- src/service/keeper-task-backup.cpp 2016-09-06 20:08:14 +0000 | |||
3511 | +++ src/service/keeper-task-backup.cpp 2017-02-27 19:05:17 +0000 | |||
3512 | @@ -31,7 +31,7 @@ | |||
3513 | 31 | Q_DECLARE_PUBLIC(KeeperTaskBackup) | 31 | Q_DECLARE_PUBLIC(KeeperTaskBackup) |
3514 | 32 | public: | 32 | public: |
3515 | 33 | KeeperTaskBackupPrivate(KeeperTask * keeper_task, | 33 | KeeperTaskBackupPrivate(KeeperTask * keeper_task, |
3517 | 34 | KeeperTask::TaskData const & task_data, | 34 | KeeperTask::TaskData & task_data, |
3518 | 35 | QSharedPointer<HelperRegistry> const & helper_registry, | 35 | QSharedPointer<HelperRegistry> const & helper_registry, |
3519 | 36 | QSharedPointer<StorageFrameworkClient> const & storage) | 36 | QSharedPointer<StorageFrameworkClient> const & storage) |
3520 | 37 | : KeeperTaskPrivate(keeper_task, task_data, helper_registry, storage) | 37 | : KeeperTaskPrivate(keeper_task, task_data, helper_registry, storage) |
3521 | @@ -50,33 +50,52 @@ | |||
3522 | 50 | qDebug() << "Initializing a backup helper"; | 50 | qDebug() << "Initializing a backup helper"; |
3523 | 51 | helper_.reset(new BackupHelper(DEKKO_APP_ID), [](Helper *h){h->deleteLater();}); | 51 | helper_.reset(new BackupHelper(DEKKO_APP_ID), [](Helper *h){h->deleteLater();}); |
3524 | 52 | qDebug() << "Helper " << static_cast<void*>(helper_.data()) << " was created"; | 52 | qDebug() << "Helper " << static_cast<void*>(helper_.data()) << " was created"; |
3525 | 53 | QObject::connect(helper_.data(), &Helper::error, [this](keeper::Error error){ error_ = error;}); | ||
3526 | 53 | } | 54 | } |
3527 | 54 | 55 | ||
3529 | 55 | void ask_for_uploader(quint64 n_bytes) | 56 | void ask_for_uploader(quint64 n_bytes, QString const & dir_name) |
3530 | 56 | { | 57 | { |
3531 | 57 | qDebug() << "asking storage framework for a socket"; | 58 | qDebug() << "asking storage framework for a socket"; |
3532 | 58 | 59 | ||
3533 | 59 | helper_->set_expected_size(n_bytes); | 60 | helper_->set_expected_size(n_bytes); |
3534 | 60 | 61 | ||
3535 | 62 | const auto file_name = QString("%1.keeper").arg(task_data_.metadata.get_display_name()); | ||
3536 | 63 | |||
3537 | 61 | connections_.connect_future( | 64 | connections_.connect_future( |
3539 | 62 | storage_->get_new_uploader(n_bytes), | 65 | storage_->get_new_uploader(n_bytes, dir_name, file_name), |
3540 | 63 | std::function<void(std::shared_ptr<Uploader> const&)>{ | 66 | std::function<void(std::shared_ptr<Uploader> const&)>{ |
3541 | 64 | [this](std::shared_ptr<Uploader> const& uploader){ | 67 | [this](std::shared_ptr<Uploader> const& uploader){ |
3547 | 65 | qDebug("calling helper.set_storage_framework_socket(socket=%d)", int(uploader->socket()->socketDescriptor())); | 68 | auto fd {-1}; |
3548 | 66 | qDebug() << "Helper is " << static_cast<void*>(helper_.data()); | 69 | if (uploader) { |
3549 | 67 | auto backup_helper = qSharedPointerDynamicCast<BackupHelper>(helper_); | 70 | auto backup_helper = qSharedPointerDynamicCast<BackupHelper>(helper_); |
3550 | 68 | backup_helper->set_uploader(uploader); | 71 | backup_helper->set_uploader(uploader); |
3551 | 69 | Q_EMIT(q_ptr->task_socket_ready(backup_helper->get_helper_socket())); | 72 | fd = backup_helper->get_helper_socket(); |
3552 | 73 | qDebug("emitting task_socket_ready(socket=%d)", fd); | ||
3553 | 74 | Q_EMIT(q_ptr->task_socket_ready(fd)); | ||
3554 | 75 | } | ||
3555 | 76 | else | ||
3556 | 77 | { | ||
3557 | 78 | error_ = storage_->get_last_error(); | ||
3558 | 79 | qDebug("Emitting task_socket_error(error=%d)", static_cast<int>(error_)); | ||
3559 | 80 | Q_EMIT(q_ptr->task_socket_error(error_)); | ||
3560 | 81 | } | ||
3561 | 70 | } | 82 | } |
3562 | 71 | } | 83 | } |
3563 | 72 | ); | 84 | ); |
3564 | 73 | } | 85 | } |
3565 | 74 | 86 | ||
3566 | 87 | QString get_file_name() const | ||
3567 | 88 | { | ||
3568 | 89 | auto backup_helper = qSharedPointerDynamicCast<BackupHelper>(helper_); | ||
3569 | 90 | return backup_helper->get_uploader_committed_file_name(); | ||
3570 | 91 | } | ||
3571 | 92 | |||
3572 | 75 | private: | 93 | private: |
3573 | 76 | ConnectionHelper connections_; | 94 | ConnectionHelper connections_; |
3574 | 95 | QString file_name_; | ||
3575 | 77 | }; | 96 | }; |
3576 | 78 | 97 | ||
3578 | 79 | KeeperTaskBackup::KeeperTaskBackup(TaskData const & task_data, | 98 | KeeperTaskBackup::KeeperTaskBackup(TaskData & task_data, |
3579 | 80 | QSharedPointer<HelperRegistry> const & helper_registry, | 99 | QSharedPointer<HelperRegistry> const & helper_registry, |
3580 | 81 | QSharedPointer<StorageFrameworkClient> const & storage, | 100 | QSharedPointer<StorageFrameworkClient> const & storage, |
3581 | 82 | QObject *parent) | 101 | QObject *parent) |
3582 | @@ -89,17 +108,27 @@ | |||
3583 | 89 | QStringList KeeperTaskBackup::get_helper_urls() const | 108 | QStringList KeeperTaskBackup::get_helper_urls() const |
3584 | 90 | { | 109 | { |
3585 | 91 | Q_D(const KeeperTaskBackup); | 110 | Q_D(const KeeperTaskBackup); |
3586 | 111 | |||
3587 | 92 | return d->get_helper_urls(); | 112 | return d->get_helper_urls(); |
3588 | 93 | } | 113 | } |
3589 | 94 | 114 | ||
3590 | 95 | void KeeperTaskBackup::init_helper() | 115 | void KeeperTaskBackup::init_helper() |
3591 | 96 | { | 116 | { |
3592 | 97 | Q_D(KeeperTaskBackup); | 117 | Q_D(KeeperTaskBackup); |
3593 | 118 | |||
3594 | 98 | d->init_helper(); | 119 | d->init_helper(); |
3595 | 99 | } | 120 | } |
3596 | 100 | 121 | ||
3598 | 101 | void KeeperTaskBackup::ask_for_uploader(quint64 n_bytes) | 122 | void KeeperTaskBackup::ask_for_uploader(quint64 n_bytes, QString const & dir_name) |
3599 | 102 | { | 123 | { |
3600 | 103 | Q_D(KeeperTaskBackup); | 124 | Q_D(KeeperTaskBackup); |
3602 | 104 | d->ask_for_uploader(n_bytes); | 125 | |
3603 | 126 | d->ask_for_uploader(n_bytes, dir_name); | ||
3604 | 127 | } | ||
3605 | 128 | |||
3606 | 129 | QString KeeperTaskBackup::get_file_name() const | ||
3607 | 130 | { | ||
3608 | 131 | Q_D(const KeeperTaskBackup); | ||
3609 | 132 | |||
3610 | 133 | return d->get_file_name(); | ||
3611 | 105 | } | 134 | } |
3612 | 106 | 135 | ||
3613 | === modified file 'src/service/keeper-task-backup.h' | |||
3614 | --- src/service/keeper-task-backup.h 2016-09-06 02:13:34 +0000 | |||
3615 | +++ src/service/keeper-task-backup.h 2017-02-27 19:05:17 +0000 | |||
3616 | @@ -29,7 +29,7 @@ | |||
3617 | 29 | Q_DECLARE_PRIVATE(KeeperTaskBackup) | 29 | Q_DECLARE_PRIVATE(KeeperTaskBackup) |
3618 | 30 | public: | 30 | public: |
3619 | 31 | 31 | ||
3621 | 32 | KeeperTaskBackup(TaskData const & task_data, | 32 | KeeperTaskBackup(TaskData & task_data, |
3622 | 33 | QSharedPointer<HelperRegistry> const & helper_registry, | 33 | QSharedPointer<HelperRegistry> const & helper_registry, |
3623 | 34 | QSharedPointer<StorageFrameworkClient> const & storage, | 34 | QSharedPointer<StorageFrameworkClient> const & storage, |
3624 | 35 | QObject *parent = nullptr); | 35 | QObject *parent = nullptr); |
3625 | @@ -37,7 +37,9 @@ | |||
3626 | 37 | 37 | ||
3627 | 38 | Q_DISABLE_COPY(KeeperTaskBackup) | 38 | Q_DISABLE_COPY(KeeperTaskBackup) |
3628 | 39 | 39 | ||
3630 | 40 | void ask_for_uploader(quint64 n_bytes); | 40 | void ask_for_uploader(quint64 n_bytes, QString const & dir_name); |
3631 | 41 | |||
3632 | 42 | QString get_file_name() const; | ||
3633 | 41 | 43 | ||
3634 | 42 | protected: | 44 | protected: |
3635 | 43 | QStringList get_helper_urls() const override; | 45 | QStringList get_helper_urls() const override; |
3636 | 44 | 46 | ||
3637 | === added file 'src/service/keeper-task-restore.cpp' | |||
3638 | --- src/service/keeper-task-restore.cpp 1970-01-01 00:00:00 +0000 | |||
3639 | +++ src/service/keeper-task-restore.cpp 2017-02-27 19:05:17 +0000 | |||
3640 | @@ -0,0 +1,130 @@ | |||
3641 | 1 | /* | ||
3642 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
3643 | 3 | * | ||
3644 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
3645 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
3646 | 6 | * by the Free Software Foundation. | ||
3647 | 7 | * | ||
3648 | 8 | * This program is distributed in the hope that it will be useful, but | ||
3649 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
3650 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
3651 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
3652 | 12 | * | ||
3653 | 13 | * You should have received a copy of the GNU General Public License along | ||
3654 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3655 | 15 | * | ||
3656 | 16 | * Authors: | ||
3657 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
3658 | 18 | * Charles Kerr <charles.kerr@canonical.com> | ||
3659 | 19 | */ | ||
3660 | 20 | |||
3661 | 21 | #include "util/connection-helper.h" | ||
3662 | 22 | #include "storage-framework/storage_framework_client.h" | ||
3663 | 23 | #include "helper/restore-helper.h" | ||
3664 | 24 | #include "service/app-const.h" // DEKKO_APP_ID | ||
3665 | 25 | #include "service/keeper-task-restore.h" | ||
3666 | 26 | #include "service/keeper-task.h" | ||
3667 | 27 | #include "service/private/keeper-task_p.h" | ||
3668 | 28 | |||
3669 | 29 | namespace sf = unity::storage::qt::client; | ||
3670 | 30 | |||
3671 | 31 | class KeeperTaskRestorePrivate : public KeeperTaskPrivate | ||
3672 | 32 | { | ||
3673 | 33 | Q_DECLARE_PUBLIC(KeeperTaskRestore) | ||
3674 | 34 | public: | ||
3675 | 35 | KeeperTaskRestorePrivate(KeeperTask * keeper_task, | ||
3676 | 36 | KeeperTask::TaskData & task_data, | ||
3677 | 37 | QSharedPointer<HelperRegistry> const & helper_registry, | ||
3678 | 38 | QSharedPointer<StorageFrameworkClient> const & storage) | ||
3679 | 39 | : KeeperTaskPrivate(keeper_task, task_data, helper_registry, storage) | ||
3680 | 40 | { | ||
3681 | 41 | } | ||
3682 | 42 | |||
3683 | 43 | ~KeeperTaskRestorePrivate() = default; | ||
3684 | 44 | |||
3685 | 45 | QStringList get_helper_urls() const | ||
3686 | 46 | { | ||
3687 | 47 | return helper_registry_->get_restore_helper_urls(task_data_.metadata); | ||
3688 | 48 | } | ||
3689 | 49 | |||
3690 | 50 | void init_helper() | ||
3691 | 51 | { | ||
3692 | 52 | helper_.reset(new RestoreHelper(DEKKO_APP_ID), [](Helper *h){h->deleteLater();}); | ||
3693 | 53 | qDebug() << "Helper " << static_cast<void*>(helper_.data()) << " was created"; | ||
3694 | 54 | } | ||
3695 | 55 | |||
3696 | 56 | void ask_for_downloader() | ||
3697 | 57 | { | ||
3698 | 58 | qDebug() << "asking storage framework for a socket for reading"; | ||
3699 | 59 | |||
3700 | 60 | auto file_name = task_data_.metadata.get_file_name(); | ||
3701 | 61 | if (file_name.isEmpty()) | ||
3702 | 62 | { | ||
3703 | 63 | qWarning() << "ERROR: the restore task does not provide a valid file name to read from."; | ||
3704 | 64 | return; | ||
3705 | 65 | } | ||
3706 | 66 | |||
3707 | 67 | auto dir_name = task_data_.metadata.get_dir_name(); | ||
3708 | 68 | if (dir_name.isEmpty()) | ||
3709 | 69 | { | ||
3710 | 70 | qWarning() << "ERROR: the restore task does not provide a valid directory name."; | ||
3711 | 71 | return; | ||
3712 | 72 | } | ||
3713 | 73 | |||
3714 | 74 | // extract the dir_name. | ||
3715 | 75 | connections_.connect_future( | ||
3716 | 76 | storage_->get_new_downloader(dir_name, file_name), | ||
3717 | 77 | std::function<void(std::shared_ptr<Downloader> const&)>{ | ||
3718 | 78 | [this](std::shared_ptr<Downloader> const& downloader){ | ||
3719 | 79 | auto fd {-1}; | ||
3720 | 80 | if (downloader) { | ||
3721 | 81 | auto restore_helper = qSharedPointerDynamicCast<RestoreHelper>(helper_); | ||
3722 | 82 | restore_helper->set_downloader(downloader); | ||
3723 | 83 | fd = restore_helper->get_helper_socket(); | ||
3724 | 84 | Q_EMIT(q_ptr->task_socket_ready(fd)); | ||
3725 | 85 | } | ||
3726 | 86 | else | ||
3727 | 87 | { | ||
3728 | 88 | error_ = storage_->get_last_error(); | ||
3729 | 89 | qDebug("Emitting task_socket_error(error=%d)", static_cast<int>(error_)); | ||
3730 | 90 | Q_EMIT(q_ptr->task_socket_error(error_)); | ||
3731 | 91 | } | ||
3732 | 92 | } | ||
3733 | 93 | } | ||
3734 | 94 | ); | ||
3735 | 95 | } | ||
3736 | 96 | |||
3737 | 97 | private: | ||
3738 | 98 | ConnectionHelper connections_; | ||
3739 | 99 | }; | ||
3740 | 100 | |||
3741 | 101 | KeeperTaskRestore::KeeperTaskRestore(TaskData & task_data, | ||
3742 | 102 | QSharedPointer<HelperRegistry> const & helper_registry, | ||
3743 | 103 | QSharedPointer<StorageFrameworkClient> const & storage, | ||
3744 | 104 | QObject *parent) | ||
3745 | 105 | : KeeperTask(*new KeeperTaskRestorePrivate(this, task_data, helper_registry, storage), parent) | ||
3746 | 106 | { | ||
3747 | 107 | } | ||
3748 | 108 | |||
3749 | 109 | KeeperTaskRestore::~KeeperTaskRestore() = default; | ||
3750 | 110 | |||
3751 | 111 | QStringList KeeperTaskRestore::get_helper_urls() const | ||
3752 | 112 | { | ||
3753 | 113 | Q_D(const KeeperTaskRestore); | ||
3754 | 114 | |||
3755 | 115 | return d->get_helper_urls(); | ||
3756 | 116 | } | ||
3757 | 117 | |||
3758 | 118 | void KeeperTaskRestore::init_helper() | ||
3759 | 119 | { | ||
3760 | 120 | Q_D(KeeperTaskRestore); | ||
3761 | 121 | |||
3762 | 122 | d->init_helper(); | ||
3763 | 123 | } | ||
3764 | 124 | |||
3765 | 125 | void KeeperTaskRestore::ask_for_downloader() | ||
3766 | 126 | { | ||
3767 | 127 | Q_D(KeeperTaskRestore); | ||
3768 | 128 | |||
3769 | 129 | d->ask_for_downloader(); | ||
3770 | 130 | } | ||
3771 | 0 | 131 | ||
3772 | === added file 'src/service/keeper-task-restore.h' | |||
3773 | --- src/service/keeper-task-restore.h 1970-01-01 00:00:00 +0000 | |||
3774 | +++ src/service/keeper-task-restore.h 2017-02-27 19:05:17 +0000 | |||
3775 | @@ -0,0 +1,46 @@ | |||
3776 | 1 | /* | ||
3777 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
3778 | 3 | * | ||
3779 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
3780 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
3781 | 6 | * by the Free Software Foundation. | ||
3782 | 7 | * | ||
3783 | 8 | * This program is distributed in the hope that it will be useful, but | ||
3784 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
3785 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
3786 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
3787 | 12 | * | ||
3788 | 13 | * You should have received a copy of the GNU General Public License along | ||
3789 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3790 | 15 | * | ||
3791 | 16 | * Authors: | ||
3792 | 17 | * Xavi Garcia <xavi.garcia.mena@canonical.com> | ||
3793 | 18 | * Charles Kerr <charles.kerr@canonical.com> | ||
3794 | 19 | */ | ||
3795 | 20 | #pragma once | ||
3796 | 21 | |||
3797 | 22 | #include "keeper-task.h" | ||
3798 | 23 | |||
3799 | 24 | class KeeperTaskRestorePrivate; | ||
3800 | 25 | |||
3801 | 26 | class KeeperTaskRestore : public KeeperTask | ||
3802 | 27 | { | ||
3803 | 28 | Q_OBJECT | ||
3804 | 29 | Q_DECLARE_PRIVATE(KeeperTaskRestore) | ||
3805 | 30 | public: | ||
3806 | 31 | |||
3807 | 32 | KeeperTaskRestore(TaskData & task_data, | ||
3808 | 33 | QSharedPointer<HelperRegistry> const & helper_registry, | ||
3809 | 34 | QSharedPointer<StorageFrameworkClient> const & storage, | ||
3810 | 35 | QObject *parent = nullptr); | ||
3811 | 36 | virtual ~KeeperTaskRestore(); | ||
3812 | 37 | |||
3813 | 38 | Q_DISABLE_COPY(KeeperTaskRestore) | ||
3814 | 39 | |||
3815 | 40 | void ask_for_downloader(); | ||
3816 | 41 | |||
3817 | 42 | protected: | ||
3818 | 43 | QStringList get_helper_urls() const override; | ||
3819 | 44 | void init_helper() override; | ||
3820 | 45 | |||
3821 | 46 | }; | ||
3822 | 0 | 47 | ||
3823 | === modified file 'src/service/keeper-task.cpp' | |||
3824 | --- src/service/keeper-task.cpp 2016-09-13 08:47:14 +0000 | |||
3825 | +++ src/service/keeper-task.cpp 2017-02-27 19:05:17 +0000 | |||
3826 | @@ -28,13 +28,14 @@ | |||
3827 | 28 | #include <QString> | 28 | #include <QString> |
3828 | 29 | 29 | ||
3829 | 30 | KeeperTaskPrivate::KeeperTaskPrivate(KeeperTask * keeper_task, | 30 | KeeperTaskPrivate::KeeperTaskPrivate(KeeperTask * keeper_task, |
3831 | 31 | KeeperTask::TaskData const & task_data, | 31 | KeeperTask::TaskData & task_data, |
3832 | 32 | QSharedPointer<HelperRegistry> const & helper_registry, | 32 | QSharedPointer<HelperRegistry> const & helper_registry, |
3833 | 33 | QSharedPointer<StorageFrameworkClient> const & storage) | 33 | QSharedPointer<StorageFrameworkClient> const & storage) |
3834 | 34 | : q_ptr(keeper_task) | 34 | : q_ptr(keeper_task) |
3835 | 35 | , task_data_(task_data) | 35 | , task_data_(task_data) |
3836 | 36 | , helper_registry_(helper_registry) | 36 | , helper_registry_(helper_registry) |
3837 | 37 | , storage_(storage) | 37 | , storage_(storage) |
3838 | 38 | , error_(keeper::Error::OK) | ||
3839 | 38 | { | 39 | { |
3840 | 39 | } | 40 | } |
3841 | 40 | 41 | ||
3842 | @@ -49,8 +50,8 @@ | |||
3843 | 49 | if (urls.isEmpty()) | 50 | if (urls.isEmpty()) |
3844 | 50 | { | 51 | { |
3845 | 51 | task_data_.action = helper_->to_string(Helper::State::FAILED); | 52 | task_data_.action = helper_->to_string(Helper::State::FAILED); |
3848 | 52 | task_data_.error = "no helper information in registry"; | 53 | error_ = keeper::Error::HELPER_BAD_URL; |
3849 | 53 | qWarning() << "ERROR: uuid: " << task_data_.metadata.uuid() << " has no url"; | 54 | qWarning() << QStringLiteral("Error: uuid %1 has no url").arg(task_data_.metadata.get_uuid()); |
3850 | 54 | calculate_and_notify_state(Helper::State::FAILED); | 55 | calculate_and_notify_state(Helper::State::FAILED); |
3851 | 55 | return false; | 56 | return false; |
3852 | 56 | } | 57 | } |
3853 | @@ -65,6 +66,10 @@ | |||
3854 | 65 | std::bind(&KeeperTaskPrivate::on_helper_percent_done_changed, this, std::placeholders::_1) | 66 | std::bind(&KeeperTaskPrivate::on_helper_percent_done_changed, this, std::placeholders::_1) |
3855 | 66 | ); | 67 | ); |
3856 | 67 | 68 | ||
3857 | 69 | QObject::connect(helper_.data(), &Helper::error, [this](keeper::Error error){ | ||
3858 | 70 | error_ = error; | ||
3859 | 71 | }); | ||
3860 | 72 | |||
3861 | 68 | helper_->start(urls); | 73 | helper_->start(urls); |
3862 | 69 | return true; | 74 | return true; |
3863 | 70 | } | 75 | } |
3864 | @@ -120,22 +125,28 @@ | |||
3865 | 120 | { | 125 | { |
3866 | 121 | QVariantMap ret; | 126 | QVariantMap ret; |
3867 | 122 | 127 | ||
3873 | 123 | auto const uuid = task_data_.metadata.uuid(); | 128 | auto const uuid = task_data_.metadata.get_uuid(); |
3874 | 124 | 129 | ||
3875 | 125 | ret.insert(QStringLiteral("action"), task_data_.action); | 130 | ret.insert(keeper::Item::STATUS_KEY, task_data_.action); |
3876 | 126 | 131 | ret.insert(keeper::Item::DISPLAY_NAME_KEY, task_data_.metadata.get_display_name()); | |
3872 | 127 | ret.insert(QStringLiteral("display-name"), task_data_.metadata.display_name()); | ||
3877 | 128 | 132 | ||
3878 | 129 | auto const speed = helper_->speed(); | 133 | auto const speed = helper_->speed(); |
3880 | 130 | ret.insert(QStringLiteral("speed"), int32_t(speed)); | 134 | ret.insert(keeper::Item::SPEED_KEY, int32_t(speed)); |
3881 | 131 | 135 | ||
3882 | 132 | auto const percent_done = helper_->percent_done(); | 136 | auto const percent_done = helper_->percent_done(); |
3889 | 133 | ret.insert(QStringLiteral("percent-done"), double(percent_done)); | 137 | ret.insert(keeper::Item::PERCENT_DONE_KEY, double(percent_done)); |
3890 | 134 | 138 | ||
3891 | 135 | if (task_data_.action == "failed") | 139 | if (task_data_.action == "failed" || task_data_.action == "cancelled") |
3892 | 136 | ret.insert(QStringLiteral("error"), task_data_.error); | 140 | { |
3893 | 137 | 141 | auto error = error_; | |
3894 | 138 | ret.insert(QStringLiteral("uuid"), uuid); | 142 | if (task_data_.error != keeper::Error::OK) |
3895 | 143 | { | ||
3896 | 144 | error = task_data_.error; | ||
3897 | 145 | } | ||
3898 | 146 | ret.insert(keeper::Item::ERROR_KEY, QVariant::fromValue(error)); | ||
3899 | 147 | } | ||
3900 | 148 | |||
3901 | 149 | ret.insert(keeper::Item::UUID_KEY, uuid); | ||
3902 | 139 | 150 | ||
3903 | 140 | QJsonDocument doc(QJsonObject::fromVariantMap(ret)); | 151 | QJsonDocument doc(QJsonObject::fromVariantMap(ret)); |
3904 | 141 | qDebug() << QString(doc.toJson(QJsonDocument::Compact)); | 152 | qDebug() << QString(doc.toJson(QJsonDocument::Compact)); |
3905 | @@ -145,29 +156,60 @@ | |||
3906 | 145 | 156 | ||
3907 | 146 | void KeeperTaskPrivate::calculate_and_notify_state(Helper::State state) | 157 | void KeeperTaskPrivate::calculate_and_notify_state(Helper::State state) |
3908 | 147 | { | 158 | { |
3909 | 159 | recalculate_task_state(); | ||
3910 | 160 | Q_EMIT(q_ptr->task_state_changed(state)); | ||
3911 | 161 | } | ||
3912 | 162 | |||
3913 | 163 | void KeeperTaskPrivate::recalculate_task_state() | ||
3914 | 164 | { | ||
3915 | 148 | state_ = calculate_task_state(); | 165 | state_ = calculate_task_state(); |
3917 | 149 | Q_EMIT(q_ptr->task_state_changed(state)); | 166 | } |
3918 | 167 | |||
3919 | 168 | void KeeperTaskPrivate::cancel() | ||
3920 | 169 | { | ||
3921 | 170 | if (helper_) | ||
3922 | 171 | { | ||
3923 | 172 | helper_->stop(); | ||
3924 | 173 | } | ||
3925 | 150 | } | 174 | } |
3926 | 151 | 175 | ||
3927 | 152 | QVariantMap KeeperTaskPrivate::get_initial_state(KeeperTask::TaskData const &td) | 176 | QVariantMap KeeperTaskPrivate::get_initial_state(KeeperTask::TaskData const &td) |
3928 | 153 | { | 177 | { |
3929 | 154 | QVariantMap ret; | 178 | QVariantMap ret; |
3930 | 155 | 179 | ||
3932 | 156 | auto const uuid = td.metadata.uuid(); | 180 | auto const uuid = td.metadata.get_uuid(); |
3933 | 157 | 181 | ||
3935 | 158 | ret.insert(QStringLiteral("action"), td.action); | 182 | ret.insert(keeper::Item::STATUS_KEY, td.action); |
3936 | 159 | 183 | ||
3937 | 160 | // TODO review this when we add the restore tasks. | 184 | // TODO review this when we add the restore tasks. |
3938 | 161 | // TODO we maybe have different fields | 185 | // TODO we maybe have different fields |
3943 | 162 | ret.insert(QStringLiteral("display-name"), td.metadata.display_name()); | 186 | ret.insert(keeper::Item::DISPLAY_NAME_KEY, td.metadata.get_display_name()); |
3944 | 163 | ret.insert(QStringLiteral("speed"), 0); | 187 | ret.insert(keeper::Item::SPEED_KEY, 0); |
3945 | 164 | ret.insert(QStringLiteral("percent-done"), double(0.0)); | 188 | ret.insert(keeper::Item::PERCENT_DONE_KEY, double(0.0)); |
3946 | 165 | ret.insert(QStringLiteral("uuid"), uuid); | 189 | ret.insert(keeper::Item::UUID_KEY, uuid); |
3947 | 166 | 190 | ||
3948 | 167 | return ret; | 191 | return ret; |
3949 | 168 | } | 192 | } |
3950 | 169 | 193 | ||
3952 | 170 | KeeperTask::KeeperTask(TaskData const & task_data, | 194 | QString KeeperTaskPrivate::to_string(Helper::State state) |
3953 | 195 | { | ||
3954 | 196 | if (helper_) | ||
3955 | 197 | { | ||
3956 | 198 | return helper_->to_string(state); | ||
3957 | 199 | } | ||
3958 | 200 | else | ||
3959 | 201 | { | ||
3960 | 202 | qWarning() << "Asking for the string of a state when the helper is not initialized yet"; | ||
3961 | 203 | return "bug"; | ||
3962 | 204 | } | ||
3963 | 205 | } | ||
3964 | 206 | |||
3965 | 207 | keeper::Error KeeperTaskPrivate::error() const | ||
3966 | 208 | { | ||
3967 | 209 | return error_; | ||
3968 | 210 | } | ||
3969 | 211 | |||
3970 | 212 | KeeperTask::KeeperTask(TaskData & task_data, | ||
3971 | 171 | QSharedPointer<HelperRegistry> const & helper_registry, | 213 | QSharedPointer<HelperRegistry> const & helper_registry, |
3972 | 172 | QSharedPointer<StorageFrameworkClient> const & storage, | 214 | QSharedPointer<StorageFrameworkClient> const & storage, |
3973 | 173 | QObject *parent) | 215 | QObject *parent) |
3974 | @@ -188,16 +230,47 @@ | |||
3975 | 188 | bool KeeperTask::start() | 230 | bool KeeperTask::start() |
3976 | 189 | { | 231 | { |
3977 | 190 | Q_D(KeeperTask); | 232 | Q_D(KeeperTask); |
3978 | 233 | |||
3979 | 191 | return d->start(); | 234 | return d->start(); |
3980 | 192 | } | 235 | } |
3981 | 193 | 236 | ||
3982 | 194 | QVariantMap KeeperTask::state() const | 237 | QVariantMap KeeperTask::state() const |
3983 | 195 | { | 238 | { |
3984 | 196 | Q_D(const KeeperTask); | 239 | Q_D(const KeeperTask); |
3985 | 240 | |||
3986 | 197 | return d->state(); | 241 | return d->state(); |
3987 | 198 | } | 242 | } |
3988 | 199 | 243 | ||
3989 | 244 | void KeeperTask::recalculate_task_state() | ||
3990 | 245 | { | ||
3991 | 246 | Q_D(KeeperTask); | ||
3992 | 247 | |||
3993 | 248 | return d->recalculate_task_state(); | ||
3994 | 249 | } | ||
3995 | 250 | |||
3996 | 251 | |||
3997 | 200 | QVariantMap KeeperTask::get_initial_state(KeeperTask::TaskData const &td) | 252 | QVariantMap KeeperTask::get_initial_state(KeeperTask::TaskData const &td) |
3998 | 201 | { | 253 | { |
3999 | 202 | return KeeperTaskPrivate::get_initial_state(td); | 254 | return KeeperTaskPrivate::get_initial_state(td); |
4000 | 203 | } | 255 | } |
4001 | 256 | |||
4002 | 257 | void KeeperTask::cancel() | ||
4003 | 258 | { | ||
4004 | 259 | Q_D(KeeperTask); | ||
4005 | 260 | |||
4006 | 261 | return d->cancel(); | ||
4007 | 262 | } | ||
4008 | 263 | |||
4009 | 264 | QString KeeperTask::to_string(Helper::State state) | ||
4010 | 265 | { | ||
4011 | 266 | Q_D(KeeperTask); | ||
4012 | 267 | |||
4013 | 268 | return d->to_string(state); | ||
4014 | 269 | } | ||
4015 | 270 | |||
4016 | 271 | keeper::Error KeeperTask::error() const | ||
4017 | 272 | { | ||
4018 | 273 | Q_D(const KeeperTask); | ||
4019 | 274 | |||
4020 | 275 | return d->error(); | ||
4021 | 276 | } | ||
4022 | 204 | 277 | ||
4023 | === modified file 'src/service/keeper-task.h' | |||
4024 | --- src/service/keeper-task.h 2016-09-07 17:07:23 +0000 | |||
4025 | +++ src/service/keeper-task.h 2017-02-27 19:05:17 +0000 | |||
4026 | @@ -20,6 +20,7 @@ | |||
4027 | 20 | 20 | ||
4028 | 21 | #pragma once | 21 | #pragma once |
4029 | 22 | 22 | ||
4030 | 23 | #include "client/keeper-errors.h" | ||
4031 | 23 | #include "helper/metadata.h" | 24 | #include "helper/metadata.h" |
4032 | 24 | #include "helper/backup-helper.h" | 25 | #include "helper/backup-helper.h" |
4033 | 25 | #include "helper/helper.h" | 26 | #include "helper/helper.h" |
4034 | @@ -40,11 +41,11 @@ | |||
4035 | 40 | struct TaskData | 41 | struct TaskData |
4036 | 41 | { | 42 | { |
4037 | 42 | QString action; | 43 | QString action; |
4039 | 43 | QString error; | 44 | keeper::Error error; |
4040 | 44 | Metadata metadata; | 45 | Metadata metadata; |
4041 | 45 | }; | 46 | }; |
4042 | 46 | 47 | ||
4044 | 47 | KeeperTask(TaskData const & task_data, | 48 | KeeperTask(TaskData & task_data, |
4045 | 48 | QSharedPointer<HelperRegistry> const & helper_registry, | 49 | QSharedPointer<HelperRegistry> const & helper_registry, |
4046 | 49 | QSharedPointer<StorageFrameworkClient> const & storage, | 50 | QSharedPointer<StorageFrameworkClient> const & storage, |
4047 | 50 | QObject *parent = nullptr); | 51 | QObject *parent = nullptr); |
4048 | @@ -54,12 +55,19 @@ | |||
4049 | 54 | 55 | ||
4050 | 55 | bool start(); | 56 | bool start(); |
4051 | 56 | QVariantMap state() const; | 57 | QVariantMap state() const; |
4052 | 58 | void recalculate_task_state(); | ||
4053 | 57 | 59 | ||
4054 | 58 | static QVariantMap get_initial_state(KeeperTask::TaskData const &td); | 60 | static QVariantMap get_initial_state(KeeperTask::TaskData const &td); |
4055 | 59 | 61 | ||
4056 | 62 | void cancel(); | ||
4057 | 63 | |||
4058 | 64 | QString to_string(Helper::State state); | ||
4059 | 65 | |||
4060 | 66 | keeper::Error error() const; | ||
4061 | 60 | Q_SIGNALS: | 67 | Q_SIGNALS: |
4062 | 61 | void task_state_changed(Helper::State state); | 68 | void task_state_changed(Helper::State state); |
4063 | 62 | void task_socket_ready(int socket_descriptor); | 69 | void task_socket_ready(int socket_descriptor); |
4064 | 70 | void task_socket_error(keeper::Error error); | ||
4065 | 63 | 71 | ||
4066 | 64 | protected: | 72 | protected: |
4067 | 65 | KeeperTask(KeeperTaskPrivate & d, QObject *parent = nullptr); | 73 | KeeperTask(KeeperTaskPrivate & d, QObject *parent = nullptr); |
4068 | 66 | 74 | ||
4069 | === modified file 'src/service/keeper-user.cpp' | |||
4070 | --- src/service/keeper-user.cpp 2016-09-07 16:35:26 +0000 | |||
4071 | +++ src/service/keeper-user.cpp 2017-02-27 19:05:17 +0000 | |||
4072 | @@ -33,75 +33,67 @@ | |||
4073 | 33 | 33 | ||
4074 | 34 | KeeperUser::~KeeperUser() =default; | 34 | KeeperUser::~KeeperUser() =default; |
4075 | 35 | 35 | ||
4100 | 36 | namespace | 36 | keeper::Items |
4077 | 37 | { | ||
4078 | 38 | QVariantMap strings_to_variants(const QMap<QString,QString>& strings) | ||
4079 | 39 | { | ||
4080 | 40 | QVariantMap variants; | ||
4081 | 41 | |||
4082 | 42 | for (auto it=strings.begin(), end=strings.end(); it!=end; ++it) | ||
4083 | 43 | variants.insert(it.key(), QVariant::fromValue(it.value())); | ||
4084 | 44 | |||
4085 | 45 | return variants; | ||
4086 | 46 | } | ||
4087 | 47 | |||
4088 | 48 | QVariantDictMap choices_to_variant_dict_map(const QVector<Metadata>& choices) | ||
4089 | 49 | { | ||
4090 | 50 | QVariantDictMap ret; | ||
4091 | 51 | |||
4092 | 52 | for (auto const& metadata : choices) | ||
4093 | 53 | ret.insert(metadata.uuid(), strings_to_variants(metadata.get_public_properties())); | ||
4094 | 54 | |||
4095 | 55 | return ret; | ||
4096 | 56 | } | ||
4097 | 57 | } | ||
4098 | 58 | |||
4099 | 59 | QVariantDictMap | ||
4101 | 60 | KeeperUser::GetBackupChoices() | 37 | KeeperUser::GetBackupChoices() |
4102 | 61 | { | 38 | { |
4104 | 62 | return choices_to_variant_dict_map(keeper_.get_backup_choices()); | 39 | auto bus = connection(); |
4105 | 40 | auto& msg = message(); | ||
4106 | 41 | return keeper_.get_backup_choices_var_dict_map(bus, msg); | ||
4107 | 63 | } | 42 | } |
4108 | 64 | 43 | ||
4109 | 65 | void | 44 | void |
4111 | 66 | KeeperUser::StartBackup (const QStringList& keys) | 45 | KeeperUser::StartBackup (const QStringList& keys, QString const & storage) |
4112 | 67 | { | 46 | { |
4113 | 68 | Q_ASSERT(calledFromDBus()); | 47 | Q_ASSERT(calledFromDBus()); |
4114 | 69 | 48 | ||
4124 | 70 | auto const unhandled = keeper_.start_tasks(keys); | 49 | auto bus = connection(); |
4125 | 71 | 50 | auto& msg = message(); | |
4126 | 72 | if (!unhandled.empty()) | 51 | keeper_.start_tasks(keys, storage, bus, msg); |
4118 | 73 | { | ||
4119 | 74 | QString text = QStringLiteral("unhandled uuids:"); | ||
4120 | 75 | for (auto const& uuid : unhandled) | ||
4121 | 76 | text += ' ' + uuid; | ||
4122 | 77 | connection().send(message().createErrorReply(QDBusError::InvalidArgs, text)); | ||
4123 | 78 | } | ||
4127 | 79 | } | 52 | } |
4128 | 80 | 53 | ||
4129 | 81 | void | 54 | void |
4130 | 82 | KeeperUser::Cancel() | 55 | KeeperUser::Cancel() |
4131 | 83 | { | 56 | { |
4135 | 84 | // FIXME: writeme | 57 | keeper_.cancel(); |
4133 | 85 | |||
4134 | 86 | qDebug() << "hello world"; | ||
4136 | 87 | } | 58 | } |
4137 | 88 | 59 | ||
4140 | 89 | QVariantDictMap | 60 | keeper::Items |
4141 | 90 | KeeperUser::GetRestoreChoices() | 61 | KeeperUser::GetRestoreChoices(QString const & storage) |
4142 | 91 | { | 62 | { |
4144 | 92 | return choices_to_variant_dict_map(keeper_.get_restore_choices()); | 63 | Q_ASSERT(calledFromDBus()); |
4145 | 64 | |||
4146 | 65 | auto bus = connection(); | ||
4147 | 66 | auto& msg = message(); | ||
4148 | 67 | return keeper_.get_restore_choices(storage, bus, msg); | ||
4149 | 93 | } | 68 | } |
4150 | 94 | 69 | ||
4151 | 95 | void | 70 | void |
4153 | 96 | KeeperUser::StartRestore (const QStringList& keys) | 71 | KeeperUser::StartRestore (const QStringList& keys, QString const & storage) |
4154 | 97 | { | 72 | { |
4156 | 98 | // FIXME: writeme | 73 | Q_ASSERT(calledFromDBus()); |
4157 | 99 | 74 | ||
4159 | 100 | qDebug() << keys; | 75 | auto bus = connection(); |
4160 | 76 | auto& msg = message(); | ||
4161 | 77 | // if we start a restore right after a backup the uuid | ||
4162 | 78 | // will be found as a backup uuid. | ||
4163 | 79 | // Just clear the backup cache to avoid that. | ||
4164 | 80 | keeper_.invalidate_choices_cache(); | ||
4165 | 81 | keeper_.start_tasks(keys, storage, bus, msg); | ||
4166 | 101 | } | 82 | } |
4167 | 102 | 83 | ||
4169 | 103 | QVariantDictMap | 84 | keeper::Items |
4170 | 104 | KeeperUser::get_state() const | 85 | KeeperUser::get_state() const |
4171 | 105 | { | 86 | { |
4172 | 106 | return keeper_.get_state(); | 87 | return keeper_.get_state(); |
4173 | 107 | } | 88 | } |
4174 | 89 | |||
4175 | 90 | QStringList | ||
4176 | 91 | KeeperUser::GetStorageAccounts() | ||
4177 | 92 | { | ||
4178 | 93 | Q_ASSERT(calledFromDBus()); | ||
4179 | 94 | |||
4180 | 95 | auto bus = connection(); | ||
4181 | 96 | auto& msg = message(); | ||
4182 | 97 | |||
4183 | 98 | return keeper_.get_storage_accounts(bus, msg); | ||
4184 | 99 | } | ||
4185 | 108 | 100 | ||
4186 | === modified file 'src/service/keeper-user.h' | |||
4187 | --- src/service/keeper-user.h 2016-09-05 18:38:36 +0000 | |||
4188 | +++ src/service/keeper-user.h 2017-02-27 19:05:17 +0000 | |||
4189 | @@ -37,11 +37,11 @@ | |||
4190 | 37 | virtual ~KeeperUser(); | 37 | virtual ~KeeperUser(); |
4191 | 38 | Q_DISABLE_COPY(KeeperUser) | 38 | Q_DISABLE_COPY(KeeperUser) |
4192 | 39 | 39 | ||
4194 | 40 | Q_PROPERTY(QVariantDictMap State | 40 | Q_PROPERTY(keeper::Items State |
4195 | 41 | READ get_state | 41 | READ get_state |
4196 | 42 | NOTIFY state_changed) | 42 | NOTIFY state_changed) |
4197 | 43 | 43 | ||
4199 | 44 | QVariantDictMap get_state() const; | 44 | keeper::Items get_state() const; |
4200 | 45 | 45 | ||
4201 | 46 | Q_SIGNALS: | 46 | Q_SIGNALS: |
4202 | 47 | 47 | ||
4203 | @@ -49,14 +49,16 @@ | |||
4204 | 49 | 49 | ||
4205 | 50 | public Q_SLOTS: | 50 | public Q_SLOTS: |
4206 | 51 | 51 | ||
4209 | 52 | QVariantDictMap GetBackupChoices(); | 52 | keeper::Items GetBackupChoices(); |
4210 | 53 | void StartBackup(const QStringList&); | 53 | void StartBackup(const QStringList&, QString const & storage); |
4211 | 54 | 54 | ||
4214 | 55 | QVariantDictMap GetRestoreChoices(); | 55 | keeper::Items GetRestoreChoices(QString const & storage); |
4215 | 56 | void StartRestore(const QStringList&); | 56 | void StartRestore(const QStringList&, QString const & storage); |
4216 | 57 | 57 | ||
4217 | 58 | void Cancel(); | 58 | void Cancel(); |
4218 | 59 | 59 | ||
4219 | 60 | QStringList GetStorageAccounts(); | ||
4220 | 61 | |||
4221 | 60 | private: | 62 | private: |
4222 | 61 | 63 | ||
4223 | 62 | Keeper& keeper_; | 64 | Keeper& keeper_; |
4224 | 63 | 65 | ||
4225 | === modified file 'src/service/keeper.cpp' | |||
4226 | --- src/service/keeper.cpp 2016-09-07 16:35:26 +0000 | |||
4227 | +++ src/service/keeper.cpp 2017-02-27 19:05:17 +0000 | |||
4228 | @@ -32,78 +32,232 @@ | |||
4229 | 32 | #include <QVector> | 32 | #include <QVector> |
4230 | 33 | 33 | ||
4231 | 34 | #include <algorithm> // std::find_if | 34 | #include <algorithm> // std::find_if |
4235 | 35 | 35 | #include <unistd.h> | |
4236 | 36 | class KeeperPrivate | 36 | |
4237 | 37 | { | 37 | namespace |
4238 | 38 | { | ||
4239 | 39 | // QVariantMap strings_to_variants(const QMap<QString,QString>& strings) | ||
4240 | 40 | // { | ||
4241 | 41 | // QVariantMap variants; | ||
4242 | 42 | // | ||
4243 | 43 | // for (auto it=strings.begin(), end=strings.end(); it!=end; ++it) | ||
4244 | 44 | // variants.insert(it.key(), QVariant::fromValue(it.value())); | ||
4245 | 45 | // | ||
4246 | 46 | // return variants; | ||
4247 | 47 | // } | ||
4248 | 48 | |||
4249 | 49 | keeper::Items choices_to_variant_dict_map(QVector<Metadata> const & choices) | ||
4250 | 50 | { | ||
4251 | 51 | keeper::Items ret; | ||
4252 | 52 | |||
4253 | 53 | for (auto const& metadata : choices) | ||
4254 | 54 | { | ||
4255 | 55 | keeper::Item value(metadata); | ||
4256 | 56 | ret.insert(metadata.get_uuid(), value); | ||
4257 | 57 | } | ||
4258 | 58 | |||
4259 | 59 | return ret; | ||
4260 | 60 | } | ||
4261 | 61 | } | ||
4262 | 62 | |||
4263 | 63 | class KeeperPrivate : public QObject | ||
4264 | 64 | { | ||
4265 | 65 | Q_OBJECT | ||
4266 | 38 | public: | 66 | public: |
4267 | 39 | 67 | ||
4268 | 40 | KeeperPrivate(Keeper* keeper, | 68 | KeeperPrivate(Keeper* keeper, |
4269 | 41 | const QSharedPointer<HelperRegistry>& helper_registry, | 69 | const QSharedPointer<HelperRegistry>& helper_registry, |
4270 | 42 | const QSharedPointer<MetadataProvider>& backup_choices, | 70 | const QSharedPointer<MetadataProvider>& backup_choices, |
4273 | 43 | const QSharedPointer<MetadataProvider>& restore_choices) | 71 | const QSharedPointer<MetadataProvider>& restore_choices, |
4274 | 44 | : q_ptr(keeper) | 72 | QObject *parent = nullptr) |
4275 | 73 | : QObject(parent) | ||
4276 | 74 | , q_ptr(keeper) | ||
4277 | 45 | , storage_(new StorageFrameworkClient()) | 75 | , storage_(new StorageFrameworkClient()) |
4278 | 46 | , helper_registry_(helper_registry) | 76 | , helper_registry_(helper_registry) |
4279 | 47 | , backup_choices_(backup_choices) | 77 | , backup_choices_(backup_choices) |
4280 | 48 | , restore_choices_(restore_choices) | 78 | , restore_choices_(restore_choices) |
4281 | 49 | , task_manager_{helper_registry, storage_} | 79 | , task_manager_{helper_registry, storage_} |
4282 | 50 | { | 80 | { |
4283 | 81 | QObject::connect(&task_manager_, &TaskManager::finished, | ||
4284 | 82 | std::bind(&KeeperPrivate::on_task_manager_finished, this) | ||
4285 | 83 | ); | ||
4286 | 51 | } | 84 | } |
4287 | 52 | 85 | ||
4288 | 86 | enum class ChoicesType { BACKUP_CHOICES, RESTORES_CHOICES }; | ||
4289 | 87 | |||
4290 | 53 | ~KeeperPrivate() =default; | 88 | ~KeeperPrivate() =default; |
4291 | 54 | 89 | ||
4292 | 55 | Q_DISABLE_COPY(KeeperPrivate) | 90 | Q_DISABLE_COPY(KeeperPrivate) |
4293 | 56 | 91 | ||
4295 | 57 | QStringList start_tasks(QStringList const & uuids) | 92 | void start_tasks(QStringList const & uuids, |
4296 | 93 | QString const & storage, | ||
4297 | 94 | QDBusConnection bus, | ||
4298 | 95 | QDBusMessage const & msg) | ||
4299 | 58 | { | 96 | { |
4300 | 59 | auto unhandled = QSet<QString>::fromList(uuids); | ||
4301 | 60 | |||
4302 | 61 | auto get_tasks = [](const QVector<Metadata>& pool, QStringList const& keys){ | 97 | auto get_tasks = [](const QVector<Metadata>& pool, QStringList const& keys){ |
4303 | 62 | QMap<QString,Metadata> tasks; | 98 | QMap<QString,Metadata> tasks; |
4304 | 63 | for (auto const& key : keys) { | 99 | for (auto const& key : keys) { |
4306 | 64 | auto it = std::find_if(pool.begin(), pool.end(), [key](Metadata const & m){return m.uuid()==key;}); | 100 | auto it = std::find_if(pool.begin(), pool.end(), [key](Metadata const & m){return m.get_uuid()==key;}); |
4307 | 65 | if (it != pool.end()) | 101 | if (it != pool.end()) |
4308 | 66 | tasks[key] = *it; | 102 | tasks[key] = *it; |
4309 | 67 | } | 103 | } |
4310 | 68 | return tasks; | 104 | return tasks; |
4311 | 69 | }; | 105 | }; |
4312 | 70 | 106 | ||
4318 | 71 | auto tasks = get_tasks(get_backup_choices(), uuids); | 107 | // async part |
4319 | 72 | if (!tasks.empty()) | 108 | qDebug() << "Looking for backup options...."; |
4320 | 73 | { | 109 | connections_.connect_oneshot( |
4321 | 74 | if (task_manager_.start_backup(tasks.values())) | 110 | this, |
4322 | 75 | unhandled.subtract(QSet<QString>::fromList(tasks.keys())); | 111 | &KeeperPrivate::backup_choices_ready, |
4323 | 112 | std::function<void()>{[this, uuids, msg, bus, get_tasks, storage](){ | ||
4324 | 113 | auto tasks = get_tasks(cached_backup_choices_, uuids); | ||
4325 | 114 | if (!tasks.empty()) | ||
4326 | 115 | { | ||
4327 | 116 | auto unhandled = QSet<QString>::fromList(uuids); | ||
4328 | 117 | if (task_manager_.start_backup(tasks.values(), storage)) | ||
4329 | 118 | unhandled.subtract(QSet<QString>::fromList(tasks.keys())); | ||
4330 | 119 | |||
4331 | 120 | check_for_unhandled_tasks_and_reply(unhandled, bus, msg); | ||
4332 | 121 | } | ||
4333 | 122 | else // restore | ||
4334 | 123 | { | ||
4335 | 124 | qDebug() << "Looking for restore options...."; | ||
4336 | 125 | connections_.connect_oneshot( | ||
4337 | 126 | this, | ||
4338 | 127 | &KeeperPrivate::restore_choices_ready, | ||
4339 | 128 | std::function<void(keeper::Error)>{[this, uuids, msg, bus, get_tasks, storage](keeper::Error error){ | ||
4340 | 129 | qDebug() << "Choices ready"; | ||
4341 | 130 | auto unhandled = QSet<QString>::fromList(uuids); | ||
4342 | 131 | if (error == keeper::Error::OK) | ||
4343 | 132 | { | ||
4344 | 133 | auto restore_tasks = get_tasks(cached_restore_choices_, uuids); | ||
4345 | 134 | qDebug() << "After getting tasks..."; | ||
4346 | 135 | if (!restore_tasks.empty() && task_manager_.start_restore(restore_tasks.values(), storage)) | ||
4347 | 136 | unhandled.subtract(QSet<QString>::fromList(restore_tasks.keys())); | ||
4348 | 137 | } | ||
4349 | 138 | check_for_unhandled_tasks_and_reply(unhandled, bus, msg); | ||
4350 | 139 | }} | ||
4351 | 140 | ); | ||
4352 | 141 | get_choices(restore_choices_, KeeperPrivate::ChoicesType::RESTORES_CHOICES); | ||
4353 | 142 | } | ||
4354 | 143 | }} | ||
4355 | 144 | ); | ||
4356 | 145 | |||
4357 | 146 | get_choices(backup_choices_, KeeperPrivate::ChoicesType::BACKUP_CHOICES); | ||
4358 | 147 | msg.setDelayedReply(true); | ||
4359 | 148 | } | ||
4360 | 149 | |||
4361 | 150 | void emit_choices_ready(ChoicesType type, keeper::Error error) | ||
4362 | 151 | { | ||
4363 | 152 | switch(type) | ||
4364 | 153 | { | ||
4365 | 154 | case KeeperPrivate::ChoicesType::BACKUP_CHOICES: | ||
4366 | 155 | Q_EMIT(backup_choices_ready(error)); | ||
4367 | 156 | break; | ||
4368 | 157 | case KeeperPrivate::ChoicesType::RESTORES_CHOICES: | ||
4369 | 158 | Q_EMIT(restore_choices_ready(error)); | ||
4370 | 159 | break; | ||
4371 | 160 | } | ||
4372 | 161 | } | ||
4373 | 162 | |||
4374 | 163 | void get_choices(const QSharedPointer<MetadataProvider> & provider, ChoicesType type, QString const & storage = "") | ||
4375 | 164 | { | ||
4376 | 165 | bool check_empty = (type == KeeperPrivate::ChoicesType::BACKUP_CHOICES) | ||
4377 | 166 | ? cached_backup_choices_.isEmpty() : cached_restore_choices_.isEmpty(); | ||
4378 | 167 | if (check_empty) | ||
4379 | 168 | { | ||
4380 | 169 | connections_.connect_oneshot( | ||
4381 | 170 | provider.data(), | ||
4382 | 171 | &MetadataProvider::finished, | ||
4383 | 172 | std::function<void(keeper::Error)>{[this, provider, type](keeper::Error error){ | ||
4384 | 173 | qDebug() << "Get choices finished"; | ||
4385 | 174 | if (error == keeper::Error::OK) | ||
4386 | 175 | { | ||
4387 | 176 | switch (type) | ||
4388 | 177 | { | ||
4389 | 178 | case KeeperPrivate::ChoicesType::BACKUP_CHOICES: | ||
4390 | 179 | cached_backup_choices_ = provider->get_backups(); | ||
4391 | 180 | break; | ||
4392 | 181 | case KeeperPrivate::ChoicesType::RESTORES_CHOICES: | ||
4393 | 182 | cached_restore_choices_ = provider->get_backups(); | ||
4394 | 183 | break; | ||
4395 | 184 | } | ||
4396 | 185 | } | ||
4397 | 186 | emit_choices_ready(type, error); | ||
4398 | 187 | }} | ||
4399 | 188 | ); | ||
4400 | 189 | provider->get_backups_async(storage); | ||
4401 | 76 | } | 190 | } |
4402 | 77 | else | 191 | else |
4403 | 78 | { | 192 | { |
4407 | 79 | tasks = get_tasks(get_restore_choices(), uuids); | 193 | emit_choices_ready(type, keeper::Error::OK); |
4405 | 80 | if (!tasks.empty() && task_manager_.start_restore(tasks.values())) | ||
4406 | 81 | unhandled.subtract(QSet<QString>::fromList(tasks.keys())); | ||
4408 | 82 | } | 194 | } |
4433 | 83 | 195 | } | |
4434 | 84 | if (!unhandled.empty()) | 196 | |
4435 | 85 | qWarning() << "skipped tasks" << unhandled; | 197 | keeper::Items get_backup_choices_var_dict_map(QDBusConnection bus, |
4436 | 86 | 198 | QDBusMessage const & msg) | |
4437 | 87 | return QStringList::fromSet(unhandled); | 199 | { |
4438 | 88 | } | 200 | connections_.connect_oneshot( |
4439 | 89 | 201 | this, | |
4440 | 90 | QVector<Metadata> get_backup_choices() const | 202 | &KeeperPrivate::backup_choices_ready, |
4441 | 91 | { | 203 | std::function<void(keeper::Error)>{[this, msg, bus](keeper::Error error){ |
4442 | 92 | if (cached_backup_choices_.isEmpty()) | 204 | qDebug() << "Backup choices are ready"; |
4443 | 93 | cached_backup_choices_ = backup_choices_->get_backups(); | 205 | if (error == keeper::Error::OK) |
4444 | 94 | 206 | { | |
4445 | 95 | return cached_backup_choices_; | 207 | // reply now to the dbus call |
4446 | 96 | } | 208 | auto reply = msg.createReply(); |
4447 | 97 | 209 | reply << QVariant::fromValue(choices_to_variant_dict_map(cached_backup_choices_)); | |
4448 | 98 | QVector<Metadata> get_restore_choices() const | 210 | bus.send(reply); |
4449 | 99 | { | 211 | } |
4450 | 100 | if (cached_restore_choices_.isEmpty()) | 212 | else |
4451 | 101 | cached_restore_choices_ = restore_choices_->get_backups(); | 213 | { |
4452 | 102 | 214 | auto message = QStringLiteral("Error obtaining backup choices, keeper returned error: %1").arg(static_cast<int>(error)); | |
4453 | 103 | return cached_restore_choices_; | 215 | qWarning() << message; |
4454 | 104 | } | 216 | auto reply = msg.createErrorReply(QDBusError::Failed, message); |
4455 | 105 | 217 | reply << QVariant::fromValue(error); | |
4456 | 106 | QVariantDictMap get_state() const | 218 | bus.send(reply); |
4457 | 219 | } | ||
4458 | 220 | }} | ||
4459 | 221 | ); | ||
4460 | 222 | get_choices(backup_choices_, KeeperPrivate::ChoicesType::BACKUP_CHOICES); | ||
4461 | 223 | msg.setDelayedReply(true); | ||
4462 | 224 | return keeper::Items(); | ||
4463 | 225 | } | ||
4464 | 226 | |||
4465 | 227 | keeper::Items get_restore_choices_var_dict_map(QString const & storage, | ||
4466 | 228 | QDBusConnection bus, | ||
4467 | 229 | QDBusMessage const & msg) | ||
4468 | 230 | { | ||
4469 | 231 | qDebug() << "Getting restores for storage " << storage << " --------------------------------"; | ||
4470 | 232 | cached_restore_choices_.clear(); | ||
4471 | 233 | connections_.connect_oneshot( | ||
4472 | 234 | this, | ||
4473 | 235 | &KeeperPrivate::restore_choices_ready, | ||
4474 | 236 | std::function<void(keeper::Error)>{[this, msg, bus](keeper::Error error){ | ||
4475 | 237 | qDebug() << "Restore choices are ready"; | ||
4476 | 238 | if (error == keeper::Error::OK) | ||
4477 | 239 | { | ||
4478 | 240 | // reply now to the dbus call | ||
4479 | 241 | auto reply = msg.createReply(); | ||
4480 | 242 | reply << QVariant::fromValue(choices_to_variant_dict_map(cached_restore_choices_)); | ||
4481 | 243 | bus.send(reply); | ||
4482 | 244 | } | ||
4483 | 245 | else | ||
4484 | 246 | { | ||
4485 | 247 | auto message = QStringLiteral("Error obtaining restore choices, keeper returned error: %1").arg(static_cast<int>(error)); | ||
4486 | 248 | qWarning() << message; | ||
4487 | 249 | auto reply = msg.createErrorReply(QDBusError::Failed, message); | ||
4488 | 250 | reply << QVariant::fromValue(error); | ||
4489 | 251 | bus.send(reply); | ||
4490 | 252 | } | ||
4491 | 253 | }} | ||
4492 | 254 | ); | ||
4493 | 255 | get_choices(restore_choices_, KeeperPrivate::ChoicesType::RESTORES_CHOICES, storage); | ||
4494 | 256 | msg.setDelayedReply(true); | ||
4495 | 257 | return keeper::Items(); | ||
4496 | 258 | } | ||
4497 | 259 | |||
4498 | 260 | keeper::Items get_state() const | ||
4499 | 107 | { | 261 | { |
4500 | 108 | return task_manager_.get_state(); | 262 | return task_manager_.get_state(); |
4501 | 109 | } | 263 | } |
4502 | @@ -127,7 +281,18 @@ | |||
4503 | 127 | } | 281 | } |
4504 | 128 | ); | 282 | ); |
4505 | 129 | 283 | ||
4507 | 130 | qDebug() << "Asking for an storage framework socket to the task manager"; | 284 | connections_.connect_oneshot( |
4508 | 285 | &task_manager_, | ||
4509 | 286 | &TaskManager::socket_error, | ||
4510 | 287 | std::function<void(keeper::Error)>{ | ||
4511 | 288 | [bus,msg](keeper::Error error){ | ||
4512 | 289 | qDebug("BackupManager returned socket error: %d", static_cast<int>(error)); | ||
4513 | 290 | bus.send(msg.createErrorReply(QDBusError::InvalidArgs, "Error obtaining remote backup socket")); | ||
4514 | 291 | } | ||
4515 | 292 | } | ||
4516 | 293 | ); | ||
4517 | 294 | |||
4518 | 295 | qDebug() << "Asking for a storage framework socket from the task manager"; | ||
4519 | 131 | task_manager_.ask_for_uploader(n_bytes); | 296 | task_manager_.ask_for_uploader(n_bytes); |
4520 | 132 | 297 | ||
4521 | 133 | // tell the caller that we'll be responding async | 298 | // tell the caller that we'll be responding async |
4522 | @@ -135,7 +300,102 @@ | |||
4523 | 135 | return QDBusUnixFileDescriptor(0); | 300 | return QDBusUnixFileDescriptor(0); |
4524 | 136 | } | 301 | } |
4525 | 137 | 302 | ||
4526 | 303 | |||
4527 | 304 | QDBusUnixFileDescriptor start_restore(QDBusConnection bus, | ||
4528 | 305 | QDBusMessage const & msg) | ||
4529 | 306 | { | ||
4530 | 307 | qDebug() << "Keeper::StartRestore()"; | ||
4531 | 308 | |||
4532 | 309 | connections_.connect_oneshot( | ||
4533 | 310 | &task_manager_, | ||
4534 | 311 | &TaskManager::socket_ready, | ||
4535 | 312 | std::function<void(int)>{ | ||
4536 | 313 | [bus,msg](int fd){ | ||
4537 | 314 | qDebug("RestoreManager returned socket %d", fd); | ||
4538 | 315 | auto reply = msg.createReply(); | ||
4539 | 316 | reply << QVariant::fromValue(QDBusUnixFileDescriptor(fd)); | ||
4540 | 317 | close(fd); | ||
4541 | 318 | bus.send(reply); | ||
4542 | 319 | } | ||
4543 | 320 | } | ||
4544 | 321 | ); | ||
4545 | 322 | |||
4546 | 323 | connections_.connect_oneshot( | ||
4547 | 324 | &task_manager_, | ||
4548 | 325 | &TaskManager::socket_error, | ||
4549 | 326 | std::function<void(keeper::Error)>{ | ||
4550 | 327 | [bus,msg](keeper::Error error){ | ||
4551 | 328 | qDebug("RestoreManager returned socket error: %d", static_cast<int>(error)); | ||
4552 | 329 | bus.send(msg.createErrorReply(QDBusError::InvalidArgs, "Error obtaining remote restore socket")); | ||
4553 | 330 | } | ||
4554 | 331 | } | ||
4555 | 332 | ); | ||
4556 | 333 | |||
4557 | 334 | qDebug() << "Asking for a storage framework socket from the task manager"; | ||
4558 | 335 | task_manager_.ask_for_downloader(); | ||
4559 | 336 | |||
4560 | 337 | // tell the caller that we'll be responding async | ||
4561 | 338 | msg.setDelayedReply(true); | ||
4562 | 339 | return QDBusUnixFileDescriptor(0); | ||
4563 | 340 | } | ||
4564 | 341 | |||
4565 | 342 | void cancel() | ||
4566 | 343 | { | ||
4567 | 344 | task_manager_.cancel(); | ||
4568 | 345 | } | ||
4569 | 346 | |||
4570 | 347 | void invalidate_choices_cache() | ||
4571 | 348 | { | ||
4572 | 349 | cached_backup_choices_.clear(); | ||
4573 | 350 | } | ||
4574 | 351 | |||
4575 | 352 | QStringList get_storage_accounts(QDBusConnection bus, | ||
4576 | 353 | QDBusMessage const & msg) | ||
4577 | 354 | { | ||
4578 | 355 | connections_.connect_future( | ||
4579 | 356 | storage_->get_accounts(), | ||
4580 | 357 | std::function<void(QStringList const &)>{ | ||
4581 | 358 | [this, msg, bus](QStringList const& accounts){ | ||
4582 | 359 | qDebug() << "get_storage_accounts() finished"; | ||
4583 | 360 | // reply now to the dbus call | ||
4584 | 361 | auto reply = msg.createReply(); | ||
4585 | 362 | reply << QVariant::fromValue(accounts); | ||
4586 | 363 | bus.send(reply); | ||
4587 | 364 | } | ||
4588 | 365 | } | ||
4589 | 366 | ); | ||
4590 | 367 | msg.setDelayedReply(true); | ||
4591 | 368 | return QStringList(); | ||
4592 | 369 | } | ||
4593 | 370 | |||
4594 | 371 | Q_SIGNALS: | ||
4595 | 372 | void backup_choices_ready(keeper::Error error); | ||
4596 | 373 | void restore_choices_ready(keeper::Error error); | ||
4597 | 374 | |||
4598 | 138 | private: | 375 | private: |
4599 | 376 | void on_task_manager_finished() | ||
4600 | 377 | { | ||
4601 | 378 | // force a backup choices regeneration to avoid repeating uuids | ||
4602 | 379 | // between backups | ||
4603 | 380 | invalidate_choices_cache(); | ||
4604 | 381 | } | ||
4605 | 382 | |||
4606 | 383 | void check_for_unhandled_tasks_and_reply(QSet<QString> const & unhandled, | ||
4607 | 384 | QDBusConnection bus, | ||
4608 | 385 | QDBusMessage const & msg ) | ||
4609 | 386 | { | ||
4610 | 387 | if (!unhandled.empty()) | ||
4611 | 388 | { | ||
4612 | 389 | qWarning() << "skipped tasks" << unhandled; | ||
4613 | 390 | QString text = QStringLiteral("unhandled uuids:"); | ||
4614 | 391 | for (auto const& uuid : unhandled) | ||
4615 | 392 | text += ' ' + uuid; | ||
4616 | 393 | bus.send(msg.createErrorReply(QDBusError::InvalidArgs, text)); | ||
4617 | 394 | } | ||
4618 | 395 | |||
4619 | 396 | auto reply = msg.createReply(); | ||
4620 | 397 | bus.send(reply); | ||
4621 | 398 | } | ||
4622 | 139 | 399 | ||
4623 | 140 | Keeper * const q_ptr; | 400 | Keeper * const q_ptr; |
4624 | 141 | QSharedPointer<StorageFrameworkClient> storage_; | 401 | QSharedPointer<StorageFrameworkClient> storage_; |
4625 | @@ -160,12 +420,15 @@ | |||
4626 | 160 | 420 | ||
4627 | 161 | Keeper::~Keeper() = default; | 421 | Keeper::~Keeper() = default; |
4628 | 162 | 422 | ||
4631 | 163 | QStringList | 423 | void |
4632 | 164 | Keeper::start_tasks(QStringList const & uuids) | 424 | Keeper::start_tasks(QStringList const & uuids, |
4633 | 425 | QString const & storage, | ||
4634 | 426 | QDBusConnection bus, | ||
4635 | 427 | QDBusMessage const & msg) | ||
4636 | 165 | { | 428 | { |
4637 | 166 | Q_D(Keeper); | 429 | Q_D(Keeper); |
4638 | 167 | 430 | ||
4640 | 168 | return d->start_tasks(uuids); | 431 | d->start_tasks(uuids, storage, bus, msg); |
4641 | 169 | } | 432 | } |
4642 | 170 | 433 | ||
4643 | 171 | QDBusUnixFileDescriptor | 434 | QDBusUnixFileDescriptor |
4644 | @@ -178,26 +441,66 @@ | |||
4645 | 178 | return d->start_backup(bus, msg, n_bytes); | 441 | return d->start_backup(bus, msg, n_bytes); |
4646 | 179 | } | 442 | } |
4647 | 180 | 443 | ||
4665 | 181 | QVector<Metadata> | 444 | QDBusUnixFileDescriptor |
4666 | 182 | Keeper::get_backup_choices() | 445 | Keeper::StartRestore(QDBusConnection bus, |
4667 | 183 | { | 446 | QDBusMessage const & msg) |
4668 | 184 | Q_D(Keeper); | 447 | { |
4669 | 185 | 448 | Q_D(Keeper); | |
4670 | 186 | return d->get_backup_choices(); | 449 | |
4671 | 187 | } | 450 | return d->start_restore(bus, msg); |
4672 | 188 | 451 | } | |
4673 | 189 | QVector<Metadata> | 452 | |
4674 | 190 | Keeper::get_restore_choices() | 453 | keeper::Items |
4675 | 191 | { | 454 | Keeper::get_backup_choices_var_dict_map(QDBusConnection bus, |
4676 | 192 | Q_D(Keeper); | 455 | QDBusMessage const & msg) |
4677 | 193 | 456 | { | |
4678 | 194 | return d->get_restore_choices(); | 457 | Q_D(Keeper); |
4679 | 195 | } | 458 | |
4680 | 196 | 459 | return d->get_backup_choices_var_dict_map(bus, msg); | |
4681 | 197 | QVariantDictMap | 460 | } |
4682 | 461 | |||
4683 | 462 | keeper::Items | ||
4684 | 463 | Keeper::get_restore_choices(QString const & storage, | ||
4685 | 464 | QDBusConnection bus, | ||
4686 | 465 | QDBusMessage const & msg) | ||
4687 | 466 | { | ||
4688 | 467 | Q_D(Keeper); | ||
4689 | 468 | |||
4690 | 469 | return d->get_restore_choices_var_dict_map(storage, bus, msg); | ||
4691 | 470 | } | ||
4692 | 471 | |||
4693 | 472 | keeper::Items | ||
4694 | 198 | Keeper::get_state() const | 473 | Keeper::get_state() const |
4695 | 199 | { | 474 | { |
4696 | 200 | Q_D(const Keeper); | 475 | Q_D(const Keeper); |
4697 | 201 | 476 | ||
4698 | 202 | return d->get_state(); | 477 | return d->get_state(); |
4699 | 203 | } | 478 | } |
4700 | 479 | |||
4701 | 480 | void | ||
4702 | 481 | Keeper::cancel() | ||
4703 | 482 | { | ||
4704 | 483 | Q_D(Keeper); | ||
4705 | 484 | |||
4706 | 485 | return d->cancel(); | ||
4707 | 486 | } | ||
4708 | 487 | |||
4709 | 488 | void | ||
4710 | 489 | Keeper::invalidate_choices_cache() | ||
4711 | 490 | { | ||
4712 | 491 | Q_D(Keeper); | ||
4713 | 492 | |||
4714 | 493 | d->invalidate_choices_cache(); | ||
4715 | 494 | } | ||
4716 | 495 | |||
4717 | 496 | QStringList | ||
4718 | 497 | Keeper::get_storage_accounts(QDBusConnection bus, | ||
4719 | 498 | QDBusMessage const & message) | ||
4720 | 499 | { | ||
4721 | 500 | Q_D(Keeper); | ||
4722 | 501 | |||
4723 | 502 | return d->get_storage_accounts(bus,message); | ||
4724 | 503 | } | ||
4725 | 504 | |||
4726 | 505 | |||
4727 | 506 | #include "keeper.moc" | ||
4728 | 204 | 507 | ||
4729 | === modified file 'src/service/keeper.h' | |||
4730 | --- src/service/keeper.h 2016-09-07 16:47:55 +0000 | |||
4731 | +++ src/service/keeper.h 2017-02-27 19:05:17 +0000 | |||
4732 | @@ -52,16 +52,30 @@ | |||
4733 | 52 | 52 | ||
4734 | 53 | virtual ~Keeper(); | 53 | virtual ~Keeper(); |
4735 | 54 | 54 | ||
4738 | 55 | QVector<Metadata> get_backup_choices(); | 55 | keeper::Items get_backup_choices_var_dict_map(QDBusConnection bus, QDBusMessage const & msg); |
4739 | 56 | QVector<Metadata> get_restore_choices(); | 56 | keeper::Items get_restore_choices(QString const & storage, QDBusConnection bus, QDBusMessage const & msg); |
4740 | 57 | 57 | ||
4741 | 58 | QDBusUnixFileDescriptor StartBackup(QDBusConnection, | 58 | QDBusUnixFileDescriptor StartBackup(QDBusConnection, |
4742 | 59 | QDBusMessage const & message, | 59 | QDBusMessage const & message, |
4743 | 60 | quint64 nbytes); | 60 | quint64 nbytes); |
4744 | 61 | 61 | ||
4748 | 62 | QStringList start_tasks(QStringList const & uuids); | 62 | |
4749 | 63 | 63 | QDBusUnixFileDescriptor StartRestore(QDBusConnection, | |
4750 | 64 | QVariantDictMap get_state() const; | 64 | QDBusMessage const & message); |
4751 | 65 | |||
4752 | 66 | void start_tasks(QStringList const & uuids, | ||
4753 | 67 | QString const & storage, | ||
4754 | 68 | QDBusConnection bus, | ||
4755 | 69 | QDBusMessage const & msg); | ||
4756 | 70 | |||
4757 | 71 | keeper::Items get_state() const; | ||
4758 | 72 | |||
4759 | 73 | void cancel(); | ||
4760 | 74 | |||
4761 | 75 | void invalidate_choices_cache(); | ||
4762 | 76 | |||
4763 | 77 | QStringList get_storage_accounts(QDBusConnection, | ||
4764 | 78 | QDBusMessage const & message); | ||
4765 | 65 | 79 | ||
4766 | 66 | private: | 80 | private: |
4767 | 67 | QScopedPointer<KeeperPrivate> const d_ptr; | 81 | QScopedPointer<KeeperPrivate> const d_ptr; |
4768 | 68 | 82 | ||
4769 | === modified file 'src/service/main.cpp' | |||
4770 | --- src/service/main.cpp 2016-08-10 05:41:26 +0000 | |||
4771 | +++ src/service/main.cpp 2017-02-27 19:05:17 +0000 | |||
4772 | @@ -20,6 +20,7 @@ | |||
4773 | 20 | 20 | ||
4774 | 21 | #include "dbus-types.h" | 21 | #include "dbus-types.h" |
4775 | 22 | #include "helper/data-dir-registry.h" | 22 | #include "helper/data-dir-registry.h" |
4776 | 23 | #include "helper/helper.h" | ||
4777 | 23 | #include "service/backup-choices.h" | 24 | #include "service/backup-choices.h" |
4778 | 24 | #include "service/restore-choices.h" | 25 | #include "service/restore-choices.h" |
4779 | 25 | #include "service/keeper.h" | 26 | #include "service/keeper.h" |
4780 | @@ -45,7 +46,7 @@ | |||
4781 | 45 | 46 | ||
4782 | 46 | QCoreApplication app(argc, argv); | 47 | QCoreApplication app(argc, argv); |
4783 | 47 | DBusTypes::registerMetaTypes(); | 48 | DBusTypes::registerMetaTypes(); |
4785 | 48 | // Variant::registerMetaTypes(); | 49 | Helper::registerMetaTypes(); |
4786 | 49 | std::srand(unsigned(std::time(nullptr))); | 50 | std::srand(unsigned(std::time(nullptr))); |
4787 | 50 | 51 | ||
4788 | 51 | util::UnixSignalHandler handler([]{ | 52 | util::UnixSignalHandler handler([]{ |
4789 | 52 | 53 | ||
4790 | === added file 'src/service/manifest.cpp' | |||
4791 | --- src/service/manifest.cpp 1970-01-01 00:00:00 +0000 | |||
4792 | +++ src/service/manifest.cpp 2017-02-27 19:05:17 +0000 | |||
4793 | @@ -0,0 +1,248 @@ | |||
4794 | 1 | /* | ||
4795 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
4796 | 3 | * | ||
4797 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
4798 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
4799 | 6 | * by the Free Software Foundation. | ||
4800 | 7 | * | ||
4801 | 8 | * This program is distributed in the hope that it will be useful, but | ||
4802 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
4803 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
4804 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
4805 | 12 | * | ||
4806 | 13 | * You should have received a copy of the GNU General Public License along | ||
4807 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
4808 | 15 | * | ||
4809 | 16 | * Authors: | ||
4810 | 17 | * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> | ||
4811 | 18 | */ | ||
4812 | 19 | |||
4813 | 20 | #include "manifest.h" | ||
4814 | 21 | |||
4815 | 22 | #include "storage-framework/storage_framework_client.h" | ||
4816 | 23 | #include "util/connection-helper.h" | ||
4817 | 24 | |||
4818 | 25 | #include <QJsonArray> | ||
4819 | 26 | #include <QJsonDocument> | ||
4820 | 27 | #include <QJsonObject> | ||
4821 | 28 | #include <QSharedPointer> | ||
4822 | 29 | #include <QVector> | ||
4823 | 30 | |||
4824 | 31 | #include <fcntl.h> | ||
4825 | 32 | #include <sys/types.h> | ||
4826 | 33 | #include <sys/socket.h> | ||
4827 | 34 | |||
4828 | 35 | namespace sf = unity::storage::qt::client; | ||
4829 | 36 | |||
4830 | 37 | // JSON Keys | ||
4831 | 38 | namespace | ||
4832 | 39 | { | ||
4833 | 40 | constexpr const char ENTRIES_KEY[] = "entries"; | ||
4834 | 41 | constexpr const char MANIFEST_FILE_NAME[] = "manifest.json"; | ||
4835 | 42 | } | ||
4836 | 43 | |||
4837 | 44 | /*** | ||
4838 | 45 | **** | ||
4839 | 46 | ***/ | ||
4840 | 47 | |||
4841 | 48 | class ManifestPrivate | ||
4842 | 49 | { | ||
4843 | 50 | public: | ||
4844 | 51 | ManifestPrivate(QSharedPointer<StorageFrameworkClient> const & storage, QString const & dir, Manifest * manifest) | ||
4845 | 52 | : q_ptr{manifest} | ||
4846 | 53 | , storage_{storage} | ||
4847 | 54 | , dir_{dir} | ||
4848 | 55 | { | ||
4849 | 56 | } | ||
4850 | 57 | |||
4851 | 58 | ~ManifestPrivate() = default; | ||
4852 | 59 | |||
4853 | 60 | Q_DISABLE_COPY(ManifestPrivate) | ||
4854 | 61 | |||
4855 | 62 | void add_entry(Metadata const & entry) | ||
4856 | 63 | { | ||
4857 | 64 | entries_.push_back(entry); | ||
4858 | 65 | } | ||
4859 | 66 | |||
4860 | 67 | void store() | ||
4861 | 68 | { | ||
4862 | 69 | qDebug() << "Metadata asking storage framework for a socket"; | ||
4863 | 70 | auto json_data = to_json(); | ||
4864 | 71 | auto n_bytes = json_data.size(); | ||
4865 | 72 | |||
4866 | 73 | connections_.connect_future( | ||
4867 | 74 | storage_->get_new_uploader(n_bytes, dir_, MANIFEST_FILE_NAME), | ||
4868 | 75 | std::function<void(std::shared_ptr<Uploader> const&)>{ | ||
4869 | 76 | [this, json_data](std::shared_ptr<Uploader> const& uploader){ | ||
4870 | 77 | qDebug() << "Manifest uploader is" << static_cast<void*>(uploader.get()); | ||
4871 | 78 | if (uploader) | ||
4872 | 79 | { | ||
4873 | 80 | auto socket = uploader->socket(); | ||
4874 | 81 | socket->write(json_data); | ||
4875 | 82 | connections_.connect_oneshot( | ||
4876 | 83 | uploader.get(), | ||
4877 | 84 | &Uploader::commit_finished, | ||
4878 | 85 | std::function<void(bool)>{[this, uploader](bool success){ | ||
4879 | 86 | qDebug() << "Metadata commit finished"; | ||
4880 | 87 | if (!success) | ||
4881 | 88 | { | ||
4882 | 89 | finish_with_error(QStringLiteral("Error committing manifest file to storage-framework")); | ||
4883 | 90 | } | ||
4884 | 91 | else | ||
4885 | 92 | { | ||
4886 | 93 | uploader_committed_file_name_ = uploader->file_name(); | ||
4887 | 94 | finish(); | ||
4888 | 95 | } | ||
4889 | 96 | }} | ||
4890 | 97 | ); | ||
4891 | 98 | uploader->commit(); | ||
4892 | 99 | } | ||
4893 | 100 | else | ||
4894 | 101 | { | ||
4895 | 102 | finish_with_error(QStringLiteral("Error retrieving uploader for manifest file from storage-framework")); | ||
4896 | 103 | } | ||
4897 | 104 | } | ||
4898 | 105 | } | ||
4899 | 106 | ); | ||
4900 | 107 | } | ||
4901 | 108 | |||
4902 | 109 | void read() | ||
4903 | 110 | { | ||
4904 | 111 | connections_.connect_future( | ||
4905 | 112 | storage_->get_new_downloader(dir_, MANIFEST_FILE_NAME), | ||
4906 | 113 | std::function<void(std::shared_ptr<Downloader> const&)>{ | ||
4907 | 114 | [this](std::shared_ptr<Downloader> const& downloader){ | ||
4908 | 115 | if (downloader) | ||
4909 | 116 | { | ||
4910 | 117 | auto socket = downloader->socket(); | ||
4911 | 118 | if (socket->atEnd()) | ||
4912 | 119 | { | ||
4913 | 120 | if (!socket->waitForReadyRead(5000)) | ||
4914 | 121 | { | ||
4915 | 122 | qWarning() << "Manifest socket was not ready to read after timeout"; | ||
4916 | 123 | } | ||
4917 | 124 | } | ||
4918 | 125 | auto json_content = socket->readAll(); | ||
4919 | 126 | from_json(json_content); | ||
4920 | 127 | downloader->finish(); | ||
4921 | 128 | finish(); | ||
4922 | 129 | } | ||
4923 | 130 | else | ||
4924 | 131 | { | ||
4925 | 132 | finish_with_error(QStringLiteral("Error retrieving downloader for manifest file from storage-framework")); | ||
4926 | 133 | } | ||
4927 | 134 | } | ||
4928 | 135 | } | ||
4929 | 136 | ); | ||
4930 | 137 | } | ||
4931 | 138 | |||
4932 | 139 | QVector<Metadata> get_entries() | ||
4933 | 140 | { | ||
4934 | 141 | return entries_; | ||
4935 | 142 | } | ||
4936 | 143 | |||
4937 | 144 | QString error() const | ||
4938 | 145 | { | ||
4939 | 146 | return error_string_; | ||
4940 | 147 | } | ||
4941 | 148 | |||
4942 | 149 | QByteArray to_json() const | ||
4943 | 150 | { | ||
4944 | 151 | QJsonArray json_array; | ||
4945 | 152 | for (auto metadata : entries_) | ||
4946 | 153 | { | ||
4947 | 154 | json_array.append(metadata.json()); | ||
4948 | 155 | } | ||
4949 | 156 | QJsonObject json_root; | ||
4950 | 157 | json_root[ENTRIES_KEY] = json_array; | ||
4951 | 158 | QJsonDocument doc(json_root); | ||
4952 | 159 | |||
4953 | 160 | return doc.toJson(QJsonDocument::Compact); | ||
4954 | 161 | } | ||
4955 | 162 | |||
4956 | 163 | void from_json(QByteArray const & json) | ||
4957 | 164 | { | ||
4958 | 165 | auto doc_read = QJsonDocument::fromJson(json); | ||
4959 | 166 | |||
4960 | 167 | auto json_read_root = doc_read.object(); | ||
4961 | 168 | auto items = json_read_root[ENTRIES_KEY].toArray(); | ||
4962 | 169 | |||
4963 | 170 | QVector<Metadata> read_metadata; | ||
4964 | 171 | for( auto iter = items.begin(); iter != items.end(); ++iter) | ||
4965 | 172 | { | ||
4966 | 173 | entries_.push_back(Metadata((*iter).toObject())); | ||
4967 | 174 | } | ||
4968 | 175 | } | ||
4969 | 176 | |||
4970 | 177 | private: | ||
4971 | 178 | |||
4972 | 179 | void finish_with_error(QString const & message) | ||
4973 | 180 | { | ||
4974 | 181 | error_string_ = message; | ||
4975 | 182 | Q_EMIT(q_ptr->finished(false)); | ||
4976 | 183 | } | ||
4977 | 184 | |||
4978 | 185 | void finish() | ||
4979 | 186 | { | ||
4980 | 187 | error_string_ = ""; | ||
4981 | 188 | Q_EMIT(q_ptr->finished(true)); | ||
4982 | 189 | } | ||
4983 | 190 | |||
4984 | 191 | Manifest * const q_ptr; | ||
4985 | 192 | QSharedPointer<StorageFrameworkClient> storage_; | ||
4986 | 193 | QString dir_; | ||
4987 | 194 | |||
4988 | 195 | QVector<Metadata> entries_; | ||
4989 | 196 | QString error_string_; | ||
4990 | 197 | QString uploader_committed_file_name_; | ||
4991 | 198 | |||
4992 | 199 | ConnectionHelper connections_; | ||
4993 | 200 | }; | ||
4994 | 201 | |||
4995 | 202 | /*** | ||
4996 | 203 | **** | ||
4997 | 204 | ***/ | ||
4998 | 205 | |||
4999 | 206 | Manifest::Manifest(QSharedPointer<StorageFrameworkClient> const & storage, QString const & dir, QObject * parent) | ||
5000 | 207 | : QObject (parent) |
The diff has been truncated for viewing.