-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proper copy/move between multiple local storages #13360
Conversation
* @param string $targetInternalPath | ||
* @return bool | ||
*/ | ||
public function crossMove($sourceStorage, $sourceInternalPath, $targetInternalPath) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enforce type of $sourceStorage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add PHP docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename to "moveFromStorage" ?
Should we actually return false or still attempt to download the file then delete it remotely ?
I guess this is also a step forward to fix file id stability ? (at least when copying from local to local, not ext storages) |
* @var \OC\Files\Storage\Local $sourceStorage | ||
*/ | ||
$rootStorage = new Local(['datadir' => '/']); | ||
return $rootStorage->copy($sourceStorage->getSourcePath($sourceInternalPath), $this->getSourcePath($targetInternalPath)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add "getSourcePath()" to the Storage interface ?
I see that method is protected on the Local storage but public in SharedStorage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add "getSourcePath()" to the Storage interface
No, it only makes sense for some backends, and the Local and Shared versions both mean something different
No, the cache operations are uneffected |
Added more unit tests |
/** | ||
* @var \OCP\Files\Storage\ICrossCopyStorage | \OCP\Files\Storage $storage2 | ||
*/ | ||
if ($storage2->instanceOfStorage('\OCP\Files\Storage\ICrossCopyStorage') and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another idea is to have "Common" always implement "moveFromStorage" and "copyFromStorage" as a simple download + copy (streamcopy). Then have specializations like Local add an additional check and do the rename() instead.
This way the new interface + check might not even be needed ?
function testMoveBetweenStorageCrossNonLocal() { | ||
$storage1 = $this->getTestStorage(true, '\Test\Files\TemporaryNoLocal'); | ||
$storage2 = $this->getTestStorage(true, '\Test\Files\TemporaryNoLocal'); | ||
$this->moveBetweenStorages($storage1, $storage2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a test when moving from a "Local + Cross" storage to a "non Local non Cross" storage ?
And also the reverse way.
The reason I'd like to have the cross copy logic in "Common" is to have a fallback in any case. |
@PVince81 done, this also cleans up |
} | ||
} | ||
} else { | ||
$source = $sourceStorage->fopen($sourceInternalPath, 'r'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: will this go through the storage wrappers or bypass them ?
When we had this on $view level the fopen() was done on the view.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will use the storage wrappers
This is already a great improvement! Thanks for the changes 😄 Can you add a unit test for the cases where moving from a cross to non-cross, etc ? |
6c8a8ea
to
12ca5d3
Compare
* @var \OC\Files\Storage\Local $sourceStorage | ||
*/ | ||
$rootStorage = new Local(['datadir' => '/']); | ||
return $rootStorage->rename($sourceStorage->getSourcePath($sourceInternalPath), $this->getSourcePath($targetInternalPath)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm... what happens if $sourceStorage is a "local external storage mount" ?
I guess this should also work because it will rely on PHP's system rename
with the absolute paths, then ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
@DeepDiver1975 are we sure to want this in 8.0 ? If we only merge this PR, I have the feeling that there isn't much benefit apart from situations where people use the "Local" external storage. The benefit will only start to show itself as soon as the SharedStorage part (the next step) is implemented. (please correct me if wrong @icewind1991) So unless both are planned for 8.0, we should probably set this PR here to 8.1. What do you think ? |
$storage1->unlink($internalPath1); | ||
} | ||
} | ||
return $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure we should return here directly ?
This would prevent proxy/hooks to be triggered in the lines below.
12ca5d3
to
0f96cf7
Compare
Note that this will be easy to implement for the refactored shared storage by implementing it for the jail wrapper |
67cb749
to
c29419e
Compare
Refer to this link for build results (access rights to CI server needed): |
Will this clash / is this compatible with #15360 ? |
Note: this also needs to be tested with encryption (once #15578 is fixed) because it might be affected. Going to test this |
Note: I also tested moving from share to share as recipient when the owner is the same, and also when the owner is different. (because the same owner would be the same local storage) For "shared mounted" to "shared mounted", I tried with two different target storages and also the same (two different folders shared from the same user's personal ext storage) All looks fine 👍 |
I noticed that if I move a big file from "a" to "b" where both are on the same SFTP storage, but shared separately with me, it still takes a long time. I guess this PR doesn't cover such cases ? (because the underlying storage is the same, so moving the file from one place to the other should be faster) |
Ok, this PR is only for underlying local storages. A later step would be to do this for any type of storage. |
Yes, this PR doesn't optimize all cases with shared storages yet |
@DeepDiver1975 @LukasReschke @MorrisJobke please review |
A new inspection was created. |
Refer to this link for build results (access rights to CI server needed): |
I tested this with some of the above test cases and it works (and there are no errors in the log) 👍 |
Proper copy/move between multiple local storages
🍻 |
This allows storage backends to implement logic for efficient copying/moving between storage backends (i.e. from local storage to local storage)
Part of the work for https://github.com/owncloud/enterprise/issues/472
Next step is having the shared storage pass the copy/move operation to the underlying storage using the same interface so it trigers the local->local copy/move logic
cc @DeepDiver1975 @PVince81
Test plan @jnfrmarks @SergioBertolinSG