2013-04-26 02:00:18 +04:00
|
|
|
<?php
|
|
|
|
/**
|
2016-07-21 18:07:57 +03:00
|
|
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
|
|
|
*
|
2019-12-03 21:57:53 +03:00
|
|
|
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
2020-03-31 11:49:10 +03:00
|
|
|
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
|
2016-07-21 18:07:57 +03:00
|
|
|
* @author Joas Schilling <coding@schilljs.com>
|
2015-03-26 13:44:34 +03:00
|
|
|
* @author Jörn Friedrich Dreyer <jfd@butonic.de>
|
|
|
|
* @author Morris Jobke <hey@morrisjobke.de>
|
2016-07-21 19:13:36 +03:00
|
|
|
* @author Robin Appelman <robin@icewind.nl>
|
2016-01-12 17:02:16 +03:00
|
|
|
* @author Robin McCorkell <robin@mccorkell.me.uk>
|
2015-03-26 13:44:34 +03:00
|
|
|
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
|
|
|
* @author Vincent Petry <pvince81@owncloud.com>
|
|
|
|
*
|
|
|
|
* @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,
|
2019-12-03 21:57:53 +03:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
2015-03-26 13:44:34 +03:00
|
|
|
*
|
2013-04-26 02:00:18 +04:00
|
|
|
*/
|
2015-02-26 13:37:37 +03:00
|
|
|
|
2013-04-26 02:00:18 +04:00
|
|
|
namespace OC\Files\Cache;
|
|
|
|
|
2019-01-22 19:08:32 +03:00
|
|
|
use OCP\Files\Storage\IStorage;
|
|
|
|
|
2013-04-26 02:00:18 +04:00
|
|
|
/**
|
2015-05-05 17:06:28 +03:00
|
|
|
* Handle the mapping between the string and numeric storage ids
|
2013-04-26 02:00:18 +04:00
|
|
|
*
|
2015-05-05 17:06:28 +03:00
|
|
|
* Each storage has 2 different ids
|
|
|
|
* a string id which is generated by the storage backend and reflects the configuration of the storage (e.g. 'smb://user@host/share')
|
|
|
|
* and a numeric storage id which is referenced in the file cache
|
|
|
|
*
|
|
|
|
* A mapping between the two storage ids is stored in the database and accessible trough this class
|
2013-04-26 02:00:18 +04:00
|
|
|
*
|
|
|
|
* @package OC\Files\Cache
|
|
|
|
*/
|
|
|
|
class Storage {
|
2016-09-02 16:41:59 +03:00
|
|
|
/** @var StorageGlobal|null */
|
|
|
|
private static $globalCache = null;
|
2013-04-26 02:00:18 +04:00
|
|
|
private $storageId;
|
|
|
|
private $numericId;
|
|
|
|
|
2016-09-02 16:41:59 +03:00
|
|
|
/**
|
|
|
|
* @return StorageGlobal
|
|
|
|
*/
|
|
|
|
public static function getGlobalCache() {
|
|
|
|
if (is_null(self::$globalCache)) {
|
|
|
|
self::$globalCache = new StorageGlobal(\OC::$server->getDatabaseConnection());
|
|
|
|
}
|
|
|
|
return self::$globalCache;
|
|
|
|
}
|
|
|
|
|
2013-04-26 02:00:18 +04:00
|
|
|
/**
|
|
|
|
* @param \OC\Files\Storage\Storage|string $storage
|
2015-01-24 00:53:21 +03:00
|
|
|
* @param bool $isAvailable
|
2015-03-11 11:33:50 +03:00
|
|
|
* @throws \RuntimeException
|
2013-04-26 02:00:18 +04:00
|
|
|
*/
|
2015-01-24 00:53:21 +03:00
|
|
|
public function __construct($storage, $isAvailable = true) {
|
2019-01-22 19:08:32 +03:00
|
|
|
if ($storage instanceof IStorage) {
|
2013-04-26 02:00:18 +04:00
|
|
|
$this->storageId = $storage->getId();
|
|
|
|
} else {
|
|
|
|
$this->storageId = $storage;
|
|
|
|
}
|
2014-03-25 15:52:32 +04:00
|
|
|
$this->storageId = self::adjustStorageId($this->storageId);
|
2013-04-26 02:00:18 +04:00
|
|
|
|
2015-01-24 00:53:21 +03:00
|
|
|
if ($row = self::getStorageById($this->storageId)) {
|
2016-08-22 14:35:51 +03:00
|
|
|
$this->numericId = (int)$row['numeric_id'];
|
2013-04-26 02:00:18 +04:00
|
|
|
} else {
|
2016-01-07 12:26:00 +03:00
|
|
|
$connection = \OC::$server->getDatabaseConnection();
|
2015-09-11 00:01:02 +03:00
|
|
|
$available = $isAvailable ? 1 : 0;
|
|
|
|
if ($connection->insertIfNotExist('*PREFIX*storages', ['id' => $this->storageId, 'available' => $available])) {
|
2016-08-22 14:35:51 +03:00
|
|
|
$this->numericId = (int)$connection->lastInsertId('*PREFIX*storages');
|
2015-03-09 21:02:34 +03:00
|
|
|
} else {
|
2015-01-24 00:53:21 +03:00
|
|
|
if ($row = self::getStorageById($this->storageId)) {
|
2016-08-22 14:35:51 +03:00
|
|
|
$this->numericId = (int)$row['numeric_id'];
|
2015-03-09 21:07:22 +03:00
|
|
|
} else {
|
2019-09-24 14:55:37 +03:00
|
|
|
throw new \RuntimeException('Storage could neither be inserted nor be selected from the database: ' . $this->storageId);
|
2015-03-09 21:02:34 +03:00
|
|
|
}
|
|
|
|
}
|
2013-04-26 02:00:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-24 00:53:21 +03:00
|
|
|
/**
|
|
|
|
* @param string $storageId
|
2016-09-02 16:41:59 +03:00
|
|
|
* @return array
|
2015-01-24 00:53:21 +03:00
|
|
|
*/
|
|
|
|
public static function getStorageById($storageId) {
|
2016-09-02 16:41:59 +03:00
|
|
|
return self::getGlobalCache()->getStorageInfo($storageId);
|
2015-01-24 00:53:21 +03:00
|
|
|
}
|
|
|
|
|
2014-03-25 15:52:32 +04:00
|
|
|
/**
|
|
|
|
* Adjusts the storage id to use md5 if too long
|
|
|
|
* @param string $storageId storage id
|
2015-05-05 17:06:28 +03:00
|
|
|
* @return string unchanged $storageId if its length is less than 64 characters,
|
2014-03-25 15:52:32 +04:00
|
|
|
* else returns the md5 of $storageId
|
|
|
|
*/
|
|
|
|
public static function adjustStorageId($storageId) {
|
|
|
|
if (strlen($storageId) > 64) {
|
|
|
|
return md5($storageId);
|
|
|
|
}
|
|
|
|
return $storageId;
|
|
|
|
}
|
|
|
|
|
2014-06-06 13:39:35 +04:00
|
|
|
/**
|
2015-05-05 17:06:28 +03:00
|
|
|
* Get the numeric id for the storage
|
|
|
|
*
|
|
|
|
* @return int
|
2014-06-06 13:39:35 +04:00
|
|
|
*/
|
2013-04-26 02:00:18 +04:00
|
|
|
public function getNumericId() {
|
|
|
|
return $this->numericId;
|
|
|
|
}
|
|
|
|
|
2014-02-06 19:30:58 +04:00
|
|
|
/**
|
2015-05-05 17:06:28 +03:00
|
|
|
* Get the string id for the storage
|
|
|
|
*
|
|
|
|
* @param int $numericId
|
|
|
|
* @return string|null either the storage id string or null if the numeric id is not known
|
2014-02-06 19:30:58 +04:00
|
|
|
*/
|
2013-04-26 02:00:18 +04:00
|
|
|
public static function getStorageId($numericId) {
|
2013-10-29 03:26:35 +04:00
|
|
|
|
2013-06-07 16:11:05 +04:00
|
|
|
$sql = 'SELECT `id` FROM `*PREFIX*storages` WHERE `numeric_id` = ?';
|
2020-03-26 11:30:18 +03:00
|
|
|
$result = \OC_DB::executeAudited($sql, [$numericId]);
|
2013-04-26 02:00:18 +04:00
|
|
|
if ($row = $result->fetchRow()) {
|
|
|
|
return $row['id'];
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2013-10-29 03:26:35 +04:00
|
|
|
|
2014-02-06 19:30:58 +04:00
|
|
|
/**
|
2015-05-05 17:06:28 +03:00
|
|
|
* Get the numeric of the storage with the provided string id
|
|
|
|
*
|
|
|
|
* @param $storageId
|
|
|
|
* @return int|null either the numeric storage id or null if the storage id is not knwon
|
2014-02-06 19:30:58 +04:00
|
|
|
*/
|
2014-06-06 13:39:35 +04:00
|
|
|
public static function getNumericStorageId($storageId) {
|
2014-03-25 15:52:32 +04:00
|
|
|
$storageId = self::adjustStorageId($storageId);
|
2014-06-06 13:39:35 +04:00
|
|
|
|
2015-01-24 00:53:21 +03:00
|
|
|
if ($row = self::getStorageById($storageId)) {
|
2016-08-22 14:35:51 +03:00
|
|
|
return (int)$row['numeric_id'];
|
2013-10-29 03:26:35 +04:00
|
|
|
} else {
|
2014-06-06 13:39:35 +04:00
|
|
|
return null;
|
2013-10-29 03:26:35 +04:00
|
|
|
}
|
|
|
|
}
|
2014-01-22 02:58:48 +04:00
|
|
|
|
2015-01-24 00:53:21 +03:00
|
|
|
/**
|
|
|
|
* @return array|null [ available, last_checked ]
|
|
|
|
*/
|
|
|
|
public function getAvailability() {
|
|
|
|
if ($row = self::getStorageById($this->storageId)) {
|
|
|
|
return [
|
2018-01-27 01:46:40 +03:00
|
|
|
'available' => (int)$row['available'] === 1,
|
2015-01-24 00:53:21 +03:00
|
|
|
'last_checked' => $row['last_checked']
|
|
|
|
];
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param bool $isAvailable
|
2019-08-22 13:19:51 +03:00
|
|
|
* @param int $delay amount of seconds to delay reconsidering that storage further
|
2015-01-24 00:53:21 +03:00
|
|
|
*/
|
2019-08-22 13:19:51 +03:00
|
|
|
public function setAvailability($isAvailable, int $delay = 0) {
|
2015-01-24 00:53:21 +03:00
|
|
|
$sql = 'UPDATE `*PREFIX*storages` SET `available` = ?, `last_checked` = ? WHERE `id` = ?';
|
2015-09-11 00:01:02 +03:00
|
|
|
$available = $isAvailable ? 1 : 0;
|
2019-08-22 13:19:51 +03:00
|
|
|
\OC_DB::executeAudited($sql, [$available, time() + $delay, $this->storageId]);
|
2015-01-24 00:53:21 +03:00
|
|
|
}
|
|
|
|
|
2014-06-06 13:39:35 +04:00
|
|
|
/**
|
2015-05-05 17:06:28 +03:00
|
|
|
* Check if a string storage id is known
|
|
|
|
*
|
2014-06-06 13:39:35 +04:00
|
|
|
* @param string $storageId
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public static function exists($storageId) {
|
|
|
|
return !is_null(self::getNumericStorageId($storageId));
|
|
|
|
}
|
|
|
|
|
2014-01-22 02:58:48 +04:00
|
|
|
/**
|
|
|
|
* remove the entry for the storage
|
|
|
|
*
|
|
|
|
* @param string $storageId
|
|
|
|
*/
|
|
|
|
public static function remove($storageId) {
|
2014-03-25 15:52:32 +04:00
|
|
|
$storageId = self::adjustStorageId($storageId);
|
2014-10-13 17:52:48 +04:00
|
|
|
$numericId = self::getNumericStorageId($storageId);
|
2014-01-22 02:58:48 +04:00
|
|
|
$sql = 'DELETE FROM `*PREFIX*storages` WHERE `id` = ?';
|
2020-03-26 11:30:18 +03:00
|
|
|
\OC_DB::executeAudited($sql, [$storageId]);
|
2014-02-03 19:36:21 +04:00
|
|
|
|
2014-06-06 13:39:35 +04:00
|
|
|
if (!is_null($numericId)) {
|
|
|
|
$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `storage` = ?';
|
2020-03-26 11:30:18 +03:00
|
|
|
\OC_DB::executeAudited($sql, [$numericId]);
|
2014-06-06 13:39:35 +04:00
|
|
|
}
|
2014-01-22 02:58:48 +04:00
|
|
|
}
|
2013-04-26 02:00:18 +04:00
|
|
|
}
|