enable locking for upload chunks

Signed-off-by: Robin Appelman <robin@icewind.nl>
upload-chunk-locking
Robin Appelman 2 years ago
parent b1be4346cd
commit 78b3a418af
No known key found for this signature in database
GPG Key ID: 42B69D8A64526EFB

@ -144,9 +144,24 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node implements \Sabre\DAV\ICol
}
$node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
// only allow 1 process to upload a file at once but still allow reading the file while writing the part file
/** @var LoggerInterface $logger */
$logger = \OC::$server->get(LoggerInterface::class);
// we get a shared lock on the file being uploaded and an exclusive lock on a virtual '.upload.part' file.
//
// The shared lock prevents writes or deletes during the upload while still allowing reading the file.
// The exclusive lock stops concurrent upload requests.
//
// Additionally, the shared lock will be changed into an exclusive one for the actual file write
$node->acquireLock(ILockingProvider::LOCK_SHARED);
$this->fileView->lockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
try {
$logger->debug("Getting lock for upload: $path");
$this->fileView->lockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
} catch (LockedException $e) {
$logger->error("Failed to acquire lock for upload: $path", ['exception' => $e]);
throw $e;
}
$result = $node->put($data);

@ -1957,7 +1957,7 @@ class View {
} catch (LockedException $e) {
// rethrow with the a human-readable path
throw new LockedException(
$this->getPathRelativeToFiles($absolutePath),
$this->getRelativePath($absolutePath),
$e,
$e->getExistingLock()
);
@ -2000,7 +2000,7 @@ class View {
try {
// rethrow with the a human-readable path
throw new LockedException(
$this->getPathRelativeToFiles($absolutePath),
$this->getRelativePath($absolutePath),
$e,
$e->getExistingLock()
);
@ -2115,7 +2115,7 @@ class View {
$pathSegments = explode('/', $path);
if (isset($pathSegments[2])) {
// E.g.: /username/files/path-to-file
return ($pathSegments[2] === 'files') && (count($pathSegments) > 3);
return ($pathSegments[2] === 'files' || $pathSegments[2] === 'uploads') && (count($pathSegments) > 3);
}
return strpos($path, '/appdata_') !== 0;

Loading…
Cancel
Save