diff options
author | Roeland Jago Douma <rullzer@users.noreply.github.com> | 2020-04-30 09:06:19 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-30 09:06:19 +0200 |
commit | a1c1b354fcb79153a78a658b758acd514089c9e1 (patch) | |
tree | d7e75df382a214e204fdb6cf49e9ec34f1b90274 | |
parent | 447277776992b54883f8f0b0d3bc05d8d01ffb7d (diff) | |
parent | 354c0996d83c853ee88dd1a26ce47e15f9866504 (diff) | |
download | nextcloud-server-a1c1b354fcb79153a78a658b758acd514089c9e1.tar.gz nextcloud-server-a1c1b354fcb79153a78a658b758acd514089c9e1.zip |
Merge pull request #18883 from adrb/optimize_swift_14116
Optimize Openstack Swift files download
-rw-r--r-- | lib/private/Files/ObjectStore/Swift.php | 37 | ||||
-rw-r--r-- | lib/private/Files/ObjectStore/SwiftFactory.php | 29 |
2 files changed, 48 insertions, 18 deletions
diff --git a/lib/private/Files/ObjectStore/Swift.php b/lib/private/Files/ObjectStore/Swift.php index 9a2aa82295e..e0d819f8a2a 100644 --- a/lib/private/Files/ObjectStore/Swift.php +++ b/lib/private/Files/ObjectStore/Swift.php @@ -25,6 +25,12 @@ namespace OC\Files\ObjectStore; +use GuzzleHttp\Client; +use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Exception\ConnectException; +use GuzzleHttp\Exception\RequestException; +use GuzzleHttp\Exception\BadResponseException; +use GuzzleHttp\HandlerStack; use function GuzzleHttp\Psr7\stream_for; use Icewind\Streams\RetryWrapper; use OCP\Files\NotFoundException; @@ -89,30 +95,33 @@ class Swift implements IObjectStore { /** * @param string $urn the unified resource name used to identify the object * @return resource stream with the read data - * @throws \Exception from openstack lib when something goes wrong + * @throws \Exception from openstack or GuzzleHttp libs when something goes wrong * @throws NotFoundException if file does not exist */ public function readObject($urn) { try { - $object = $this->getContainer()->getObject($urn); - - // we need to keep a reference to objectContent or - // the stream will be closed before we can do anything with it - $objectContent = $object->download(); - } catch (BadResponseError $e) { - if ($e->getResponse()->getStatusCode() === 404) { + $publicUri = $this->getContainer()->getObject($urn)->getPublicUri(); + $tokenId = $this->swiftFactory->getCachedTokenId(); + + $response = (new Client())->request('GET', $publicUri, + [ + 'stream' => true, + 'headers' => [ + 'X-Auth-Token' => $tokenId, + 'Cache-Control' => 'no-cache' + ], + ] + ); + + } catch (BadResponseException $e) { + if ($e->getResponse() && $e->getResponse()->getStatusCode() === 404) { throw new NotFoundException("object $urn not found in object store"); } else { throw $e; } } - $objectContent->rewind(); - - $stream = $objectContent->detach(); - // save the object content in the context of the stream to prevent it being gc'd until the stream is closed - stream_context_set_option($stream, 'swift', 'content', $objectContent); - return RetryWrapper::wrap($stream); + return RetryWrapper::wrap($response->getBody()->detach()); } /** diff --git a/lib/private/Files/ObjectStore/SwiftFactory.php b/lib/private/Files/ObjectStore/SwiftFactory.php index 58d10d446b7..9857e1def85 100644 --- a/lib/private/Files/ObjectStore/SwiftFactory.php +++ b/lib/private/Files/ObjectStore/SwiftFactory.php @@ -71,6 +71,25 @@ class SwiftFactory { $this->logger = $logger; } + /** + * Gets currently cached token id + * + * @return string + * @throws StorageAuthException + */ + public function getCachedTokenId() { + if ( !isset($this->params['cachedToken']) ) { + throw new StorageAuthException('Unauthenticated ObjectStore connection'); + } + + // Is it V2 token? + if ( isset($this->params['cachedToken']['token']) ) { + return $this->params['cachedToken']['token']['id']; + } + + return $this->params['cachedToken']['id']; + } + private function getCachedToken(string $cacheKey) { $cachedTokenString = $this->cache->get($cacheKey . '/token'); if ($cachedTokenString) { @@ -83,10 +102,10 @@ class SwiftFactory { private function cacheToken(Token $token, string $serviceUrl, string $cacheKey) { if ($token instanceof \OpenStack\Identity\v3\Models\Token) { // for v3 the catalog is cached as part of the token, so no need to cache $serviceUrl separately - $value = json_encode($token->export()); + $value = $token->export(); } else { /** @var \OpenStack\Identity\v2\Models\Token $token */ - $value = json_encode([ + $value = [ 'serviceUrl' => $serviceUrl, 'token' => [ 'issued_at' => $token->issuedAt->format('c'), @@ -94,9 +113,11 @@ class SwiftFactory { 'id' => $token->id, 'tenant' => $token->tenant ] - ]); + ]; } - $this->cache->set($cacheKey . '/token', $value); + + $this->params['cachedToken'] = $value; + $this->cache->set($cacheKey . '/token', json_encode($value)); } /** |