diff options
author | Robin McCorkell <rmccorkell@karoshi.org.uk> | 2015-01-23 21:53:21 +0000 |
---|---|---|
committer | Robin McCorkell <rmccorkell@karoshi.org.uk> | 2015-07-20 16:27:26 +0100 |
commit | df19cabb44f9106484290a269ef6d4cb07b059d7 (patch) | |
tree | f3246817578ed3fc91c1bb05051582ac4386defd /lib/private/files/storage/wrapper | |
parent | 89d6439445da8e1cf133bc2e1b6db9709ce4af8b (diff) | |
download | nextcloud-server-df19cabb44f9106484290a269ef6d4cb07b059d7.tar.gz nextcloud-server-df19cabb44f9106484290a269ef6d4cb07b059d7.zip |
Store storage availability in database
Storage status is saved in the database. Failed storages are rechecked every
10 minutes, while working storages are rechecked every request.
Using the files_external app will recheck all external storages when the
settings page is viewed, or whenever an external storage is saved.
Diffstat (limited to 'lib/private/files/storage/wrapper')
-rw-r--r-- | lib/private/files/storage/wrapper/availability.php | 462 | ||||
-rw-r--r-- | lib/private/files/storage/wrapper/wrapper.php | 18 |
2 files changed, 480 insertions, 0 deletions
diff --git a/lib/private/files/storage/wrapper/availability.php b/lib/private/files/storage/wrapper/availability.php new file mode 100644 index 00000000000..37319a8f7d1 --- /dev/null +++ b/lib/private/files/storage/wrapper/availability.php @@ -0,0 +1,462 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@karoshi.org.uk> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ +namespace OC\Files\Storage\Wrapper; + +/** + * Availability checker for storages + * + * Throws a StorageNotAvailableException for storages with known failures + */ +class Availability extends Wrapper { + const RECHECK_TTL_SEC = 600; // 10 minutes + + /** + * @return bool + */ + private function updateAvailability() { + try { + $result = $this->test(); + } catch (\Exception $e) { + $result = false; + } + $this->setAvailability($result); + return $result; + } + + /** + * @return bool + */ + private function isAvailable() { + $availability = $this->getAvailability(); + if (!$availability['available']) { + // trigger a recheck if TTL reached + if ((time() - $availability['last_checked']) > self::RECHECK_TTL_SEC) { + return $this->updateAvailability(); + } + } + return $availability['available']; + } + + /** + * @throws \OCP\Files\StorageNotAvailableException + */ + private function checkAvailability() { + if (!$this->isAvailable()) { + throw new \OCP\Files\StorageNotAvailableException(); + } + } + + /** {@inheritdoc} */ + public function mkdir($path) { + $this->checkAvailability(); + try { + return parent::mkdir($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function rmdir($path) { + $this->checkAvailability(); + try { + return parent::rmdir($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function opendir($path) { + $this->checkAvailability(); + try { + return parent::opendir($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function is_dir($path) { + $this->checkAvailability(); + try { + return parent::is_dir($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function is_file($path) { + $this->checkAvailability(); + try { + return parent::is_file($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function stat($path) { + $this->checkAvailability(); + try { + return parent::stat($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function filetype($path) { + $this->checkAvailability(); + try { + return parent::filetype($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function filesize($path) { + $this->checkAvailability(); + try { + return parent::filesize($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function isCreatable($path) { + $this->checkAvailability(); + try { + return parent::isCreatable($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function isReadable($path) { + $this->checkAvailability(); + try { + return parent::isReadable($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function isUpdatable($path) { + $this->checkAvailability(); + try { + return parent::isUpdatable($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function isDeletable($path) { + $this->checkAvailability(); + try { + return parent::isDeletable($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function isSharable($path) { + $this->checkAvailability(); + try { + return parent::isSharable($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function getPermissions($path) { + $this->checkAvailability(); + try { + return parent::getPermissions($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function file_exists($path) { + $this->checkAvailability(); + try { + return parent::file_exists($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function filemtime($path) { + $this->checkAvailability(); + try { + return parent::filemtime($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function file_get_contents($path) { + $this->checkAvailability(); + try { + return parent::file_get_contents($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function file_put_contents($path, $data) { + $this->checkAvailability(); + try { + return parent::file_put_contents($path, $data); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function unlink($path) { + $this->checkAvailability(); + try { + return parent::unlink($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function rename($path1, $path2) { + $this->checkAvailability(); + try { + return parent::rename($path1, $path2); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function copy($path1, $path2) { + $this->checkAvailability(); + try { + return parent::copy($path1, $path2); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function fopen($path, $mode) { + $this->checkAvailability(); + try { + return parent::fopen($path, $mode); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function getMimeType($path) { + $this->checkAvailability(); + try { + return parent::getMimeType($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function hash($type, $path, $raw = false) { + $this->checkAvailability(); + try { + return parent::hash($type, $path, $raw); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function free_space($path) { + $this->checkAvailability(); + try { + return parent::free_space($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function search($query) { + $this->checkAvailability(); + try { + return parent::search($query); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function touch($path, $mtime = null) { + $this->checkAvailability(); + try { + return parent::touch($path, $mtime); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function getLocalFile($path) { + $this->checkAvailability(); + try { + return parent::getLocalFile($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function getLocalFolder($path) { + $this->checkAvailability(); + try { + return parent::getLocalFolder($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function hasUpdated($path, $time) { + $this->checkAvailability(); + try { + return parent::hasUpdated($path, $time); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function getOwner($path) { + $this->checkAvailability(); + try { + return parent::getOwner($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function getETag($path) { + $this->checkAvailability(); + try { + return parent::getETag($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function getDirectDownload($path) { + $this->checkAvailability(); + try { + return parent::getDirectDownload($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function copyFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) { + $this->checkAvailability(); + try { + return parent::copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function moveFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) { + $this->checkAvailability(); + try { + return parent::moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } + + /** {@inheritdoc} */ + public function getMetaData($path) { + $this->checkAvailability(); + try { + return parent::getMetaData($path); + } catch (\OCP\Files\StorageNotAvailableException $e) { + $this->setAvailability(false); + throw $e; + } + } +} diff --git a/lib/private/files/storage/wrapper/wrapper.php b/lib/private/files/storage/wrapper/wrapper.php index d1414880beb..b43dd4fe142 100644 --- a/lib/private/files/storage/wrapper/wrapper.php +++ b/lib/private/files/storage/wrapper/wrapper.php @@ -498,6 +498,24 @@ class Wrapper implements \OC\Files\Storage\Storage { } /** + * Get availability of the storage + * + * @return array [ available, last_checked ] + */ + public function getAvailability() { + return $this->storage->getAvailability(); + } + + /** + * Set availability of the storage + * + * @param bool $isAvailable + */ + public function setAvailability($isAvailable) { + $this->storage->setAvailability($isAvailable); + } + + /** * @param string $path the path of the target folder * @param string $fileName the name of the file itself * @return void |