server/lib/private/files/storage/wrapper/availability.php
Robin McCorkell df19cabb44 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.
2015-07-20 16:27:26 +01:00

462 lines
11 KiB
PHP

<?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;
}
}
}