Merge lp:~xavi-garcia-mena/keeper/restore into lp:keeper/devel

Proposed by Xavi Garcia
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
Reviewer Review Type Date Requested Status
unity-api-1-bot continuous-integration Approve
Charles Kerr (community) Approve
Review via email: mp+310653@code.launchpad.net

Commit message

First version of restore.

Description of the change

This branch adds the first version of restore, with a fake restore helper to test it.

The branch adds the restore-task-restore, restore-helper and modifies the registry in order to add the restore entries.

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.

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

FAILED: Continuous integration, rev:121
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/115/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/1059/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1066
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/855/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/855/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/855
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/855/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/855/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/855/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/855/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/855
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/855/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/855
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/855/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/855/console

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

review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
122. By Xavi Garcia

commit just to test on jenkins as it does not fail on the destop

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

FAILED: Continuous integration, rev:122
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/116/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/1066/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1073
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/862/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/862/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/862
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/862/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/862/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/862/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/862/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/862/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/862/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/862/console

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

review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
123. By Xavi Garcia

more pointers to integration test

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

FAILED: Continuous integration, rev:123
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/117/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/1067/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1074
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/863/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/863/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/863/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/863/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/863/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/863/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/863/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/863/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/863
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/863/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
124. By Xavi Garcia

More tests, this is not intended to be the final solution

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

FAILED: Continuous integration, rev:124
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/119/
Executed test runs:

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

review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
125. By Xavi Garcia

test reading in separated thread

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
126. By Xavi Garcia

Added simple downloader test

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
127. By Xavi Garcia

a litle tidy up

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
128. By Xavi Garcia

Fix copyright issue

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
129. By Xavi Garcia

Changed the way we create the socket between keeper and restore helper

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
130. By Xavi Garcia

Removed test exec

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

PASSED: Continuous integration, rev:130
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/127/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1096
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1103
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/894
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/894/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/894
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/894/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/894
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/894/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/894
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/894/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/894
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/894/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/894
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/894/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
131. By Xavi Garcia

Modified back to original version, without QLocalServer

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
132. By Xavi Garcia

clean up the code a bit

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
133. By Xavi Garcia

More cleanup and decreased file sizes to transfers to avoid race conditions in slow boxes

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
134. By Xavi Garcia

Added extra log information

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
135. By Xavi Garcia

Changed sockets to be in a shared pointer

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

FAILED: Continuous integration, rev:135
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/133/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/1120/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1127
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/918
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/918/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/918/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/918
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/918/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/918/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/918
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/918/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/918
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/918/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
136. By Xavi Garcia

Closing socket after setting it to the dbus reply

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

PASSED: Continuous integration, rev:136
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/134/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1121
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1128
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/919
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/919/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/919
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/919/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/919
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/919/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/919
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/919/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/919
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/919/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/919
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/919/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:136
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/135/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1122
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1129
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/920
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/920
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/920
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/920
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/920
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/920
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/920/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
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

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

PASSED: Continuous integration, rev:138
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/136/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1137
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1144
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/935
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/935/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/935
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/935/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/935
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/935/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/935
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/935/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/935
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/935/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/935
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/935/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
139. By Xavi Garcia

Removed extra debug statements

140. By Xavi Garcia

Removed extra lines

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

PASSED: Continuous integration, rev:139
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/137/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1138
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1145
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/936
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/936/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/936
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/936/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/936
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/936/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/936
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/936/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/936
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/936/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/936
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/936/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:140
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/138/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1139
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1146
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/937
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/937/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/937
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/937/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/937
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/937/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/937
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/937/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/937
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/937/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/937
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/937/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Charles Kerr (charlesk) wrote :

inline: one bugfix, some questions, several meddling suggestions

review: Needs Information
lp:~xavi-garcia-mena/keeper/restore updated
141. By Xavi Garcia

Changed as suggested after review

Revision history for this message
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....

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

PASSED: Continuous integration, rev:141
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/139/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1149
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1156
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/944
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/944/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/944
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/944/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/944
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/944/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/944
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/944/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/944
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/944/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/944
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/944/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
lp:~xavi-garcia-mena/keeper/restore updated
142. By Xavi Garcia

Storage framework client bug fixed. A couple of variables needed to be captured

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

FAILED: Continuous integration, rev:142
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/140/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/1158/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1165
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/952
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/952/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/952/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/952
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/952/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/952/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/952
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/952/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/952/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Charles Kerr (charlesk) wrote :

Thanks for the cleanups Xavi!

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

PASSED: Continuous integration, rev:
https://jenkins.canonical.com/unity-api-1/job/lp-keeper-ci/142/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1198
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1205
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/991
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/991/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/991
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/991/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/991
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/991/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/991
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/991/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/991
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/991/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/991
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/991/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)

Preview Diff

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

Subscribers

People subscribed via source and target branches

to all changes: