Commit 0a6fc266 authored by Vincent Petry's avatar Vincent Petry Committed by GitHub
Browse files

Merge pull request #26324 from owncloud/fed-statcache-404

Fix DAV stat cache to properly cache 404
parents 9fe34ef9 48093ef5
......@@ -47,7 +47,6 @@ use OCP\Files\StorageInvalidException;
use OCP\Files\StorageNotAvailableException;
use OCP\Util;
use Sabre\DAV\Client;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\Xml\Property\ResourceType;
use Sabre\HTTP\ClientException;
use Sabre\HTTP\ClientHttpException;
......@@ -207,7 +206,9 @@ class DAV extends Common {
[],
1
);
$id = md5('webdav' . $this->root . $path);
if ($response === false) {
return false;
}
$content = [];
$files = array_keys($response);
array_shift($files); //the first entry is the current directory
......@@ -225,13 +226,6 @@ class DAV extends Common {
$content[] = $file;
}
return IteratorDirectory::wrap($content);
} catch (ClientHttpException $e) {
if ($e->getHttpStatus() === 404) {
$this->statCache->clear($path . '/');
$this->statCache->set($path, false);
return false;
}
$this->convertException($e, $path);
} catch (\Exception $e) {
$this->convertException($e, $path);
}
......@@ -246,17 +240,13 @@ class DAV extends Common {
*
* @param string $path path to propfind
*
* @return array propfind response
* @return array|boolean propfind response or false if the entry was not found
*
* @throws NotFound
* @throws ClientHttpException
*/
protected function propfind($path) {
$path = $this->cleanPath($path);
$cachedResponse = $this->statCache->get($path);
if ($cachedResponse === false) {
// we know it didn't exist
throw new NotFound();
}
// we either don't know it, or we know it exists but need more details
if (is_null($cachedResponse) || $cachedResponse === true) {
$this->init();
......@@ -274,11 +264,15 @@ class DAV extends Common {
]
);
$this->statCache->set($path, $response);
} catch (NotFound $e) {
// remember that this path did not exist
$this->statCache->clear($path . '/');
$this->statCache->set($path, false);
throw $e;
} catch (ClientHttpException $e) {
if ($e->getHttpStatus() === 404) {
$this->statCache->clear($path . '/');
$this->statCache->set($path, false);
return false;
}
$this->convertException($e, $path);
} catch (\Exception $e) {
$this->convertException($e, $path);
}
} else {
$response = $cachedResponse;
......@@ -290,17 +284,15 @@ class DAV extends Common {
public function filetype($path) {
try {
$response = $this->propfind($path);
if ($response === false) {
return false;
}
$responseType = [];
if (isset($response["{DAV:}resourcetype"])) {
/** @var ResourceType[] $response */
$responseType = $response["{DAV:}resourcetype"]->getValue();
}
return (count($responseType) > 0 and $responseType[0] == "{DAV:}collection") ? 'dir' : 'file';
} catch (ClientHttpException $e) {
if ($e->getHttpStatus() === 404) {
return false;
}
$this->convertException($e, $path);
} catch (\Exception $e) {
$this->convertException($e, $path);
}
......@@ -319,13 +311,7 @@ class DAV extends Common {
return true;
}
// need to get from server
$this->propfind($path);
return true; //no 404 exception
} catch (ClientHttpException $e) {
if ($e->getHttpStatus() === 404) {
return false;
}
$this->convertException($e, $path);
return ($this->propfind($path) !== false);
} catch (\Exception $e) {
$this->convertException($e, $path);
}
......@@ -431,6 +417,9 @@ class DAV extends Common {
try {
// TODO: cacheable ?
$response = $this->client->propfind($this->encodePath($path), ['{DAV:}quota-available-bytes']);
if ($response === false) {
return FileInfo::SPACE_UNKNOWN;
}
if (isset($response['{DAV:}quota-available-bytes'])) {
return (int)$response['{DAV:}quota-available-bytes'];
} else {
......@@ -456,6 +445,9 @@ class DAV extends Common {
$this->client->proppatch($this->encodePath($path), ['{DAV:}lastmodified' => $mtime]);
// non-owncloud clients might not have accepted the property, need to recheck it
$response = $this->client->propfind($this->encodePath($path), ['{DAV:}getlastmodified'], 0);
if ($response === false) {
return false;
}
if (isset($response['{DAV:}getlastmodified'])) {
$remoteMtime = strtotime($response['{DAV:}getlastmodified']);
if ($remoteMtime !== $mtime) {
......@@ -578,15 +570,13 @@ class DAV extends Common {
public function stat($path) {
try {
$response = $this->propfind($path);
if ($response === false) {
return [];
}
return [
'mtime' => strtotime($response['{DAV:}getlastmodified']),
'size' => (int)isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0,
];
} catch (ClientHttpException $e) {
if ($e->getHttpStatus() === 404) {
return [];
}
$this->convertException($e, $path);
} catch (\Exception $e) {
$this->convertException($e, $path);
}
......@@ -597,6 +587,9 @@ class DAV extends Common {
public function getMimeType($path) {
try {
$response = $this->propfind($path);
if ($response === false) {
return false;
}
$responseType = [];
if (isset($response["{DAV:}resourcetype"])) {
/** @var ResourceType[] $response */
......@@ -610,11 +603,6 @@ class DAV extends Common {
} else {
return false;
}
} catch (ClientHttpException $e) {
if ($e->getHttpStatus() === 404) {
return false;
}
$this->convertException($e, $path);
} catch (\Exception $e) {
$this->convertException($e, $path);
}
......@@ -705,6 +693,9 @@ class DAV extends Common {
$this->init();
$path = $this->cleanPath($path);
$response = $this->propfind($path);
if ($response === false) {
return 0;
}
if (isset($response['{http://owncloud.org/ns}permissions'])) {
return $this->parsePermissions($response['{http://owncloud.org/ns}permissions']);
} else if ($this->is_dir($path)) {
......@@ -721,6 +712,9 @@ class DAV extends Common {
$this->init();
$path = $this->cleanPath($path);
$response = $this->propfind($path);
if ($response === false) {
return null;
}
if (isset($response['{DAV:}getetag'])) {
return trim($response['{DAV:}getetag'], '"');
}
......@@ -764,6 +758,13 @@ class DAV extends Common {
// force refresh for $path
$this->statCache->remove($path);
$response = $this->propfind($path);
if ($response === false) {
if ($path === '') {
// if root is gone it means the storage is not available
throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
}
return false;
}
if (isset($response['{DAV:}getetag'])) {
$cachedData = $this->getCache()->get($path);
$etag = null;
......@@ -786,7 +787,7 @@ class DAV extends Common {
return $remoteMtime > $time;
}
} catch (ClientHttpException $e) {
if ($e->getHttpStatus() === 404 || $e->getHttpStatus() === 405) {
if ($e->getHttpStatus() === 405) {
if ($path === '') {
// if root is gone it means the storage is not available
throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment