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