Skip to content

Commit

Permalink
Merge pull request #4116 from nextcloud/swift-cache-token
Browse files Browse the repository at this point in the history
Cache swift authentication token in memcache
  • Loading branch information
rullzer authored Mar 29, 2017
2 parents 00839a5 + 6991b79 commit 626d03e
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 11 deletions.
2 changes: 1 addition & 1 deletion 3rdparty
Submodule 3rdparty updated 901 files
72 changes: 62 additions & 10 deletions lib/private/Files/ObjectStore/Swift.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use OpenCloud\Common\Exceptions\EndpointError;
use OpenCloud\Common\Service\Catalog;
use OpenCloud\Common\Service\CatalogItem;
use OpenCloud\Identity\Resource\Token;
use OpenCloud\ObjectStore\Service;
use OpenCloud\OpenStack;
use OpenCloud\Rackspace;
Expand All @@ -57,6 +58,8 @@ class Swift implements IObjectStore {
*/
private $container;

private $memcache;

public function __construct($params) {
if (isset($params['bucket'])) {
$params['container'] = $params['bucket'];
Expand All @@ -71,9 +74,15 @@ public function __construct($params) {

if (isset($params['apiKey'])) {
$this->client = new Rackspace($params['url'], $params);
$cacheKey = $this->params['username'] . '@' . $this->params['url'] . '/' . $this->params['bucket'];
} else {
$this->client = new OpenStack($params['url'], $params);
$cacheKey = $this->params['username'] . '@' . $this->params['url'] . '/' . $this->params['bucket'];
}

$cacheFactory = \OC::$server->getMemCacheFactory();
$this->memcache = $cacheFactory->create('swift::' . $cacheKey);

$this->params = $params;
}

Expand All @@ -82,19 +91,28 @@ protected function init() {
return;
}

try {
$this->client->authenticate();
} catch (ClientErrorResponseException $e) {
$statusCode = $e->getResponse()->getStatusCode();
if ($statusCode == 412) {
throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
} else if ($statusCode === 401) {
throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
} else {
throw new StorageAuthException('Unknown error', $e);
$this->importToken();

/** @var Token $token */
$token = $this->client->getTokenObject();

if (!$token || $token->hasExpired()) {
try {
$this->client->authenticate();
$this->exportToken();
} catch (ClientErrorResponseException $e) {
$statusCode = $e->getResponse()->getStatusCode();
if ($statusCode == 412) {
throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
} else if ($statusCode === 401) {
throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
} else {
throw new StorageAuthException('Unknown error', $e);
}
}
}


/** @var Catalog $catalog */
$catalog = $this->client->getCatalog();

Expand Down Expand Up @@ -137,6 +155,40 @@ protected function init() {
}
}

private function exportToken() {
$export = $this->client->exportCredentials();
$export['catalog'] = array_map(function (CatalogItem $item) {
return [
'name' => $item->getName(),
'endpoints' => $item->getEndpoints(),
'type' => $item->getType()
];
}, $export['catalog']->getItems());
$this->memcache->set('token', json_encode($export));
}

private function importToken() {
$cachedTokenString = $this->memcache->get('token');
if ($cachedTokenString) {
$cachedToken = json_decode($cachedTokenString, true);
$cachedToken['catalog'] = array_map(function (array $item) {
$itemClass = new \stdClass();
$itemClass->name = $item['name'];
$itemClass->endpoints = array_map(function (array $endpoint) {
return (object) $endpoint;
}, $item['endpoints']);
$itemClass->type = $item['type'];

return $itemClass;
}, $cachedToken['catalog']);
try {
$this->client->importCredentials($cachedToken);
} catch (\Exception $e) {
$this->client->setTokenObject(new Token());
}
}
}

/**
* @param Catalog $catalog
* @param $name
Expand Down

0 comments on commit 626d03e

Please sign in to comment.