Skip to content

Commit f18b6e0

Browse files
committed
Put storage cache initalization in a transaction
Signed-off-by: Thomas Citharel <[email protected]>
1 parent 16b68fd commit f18b6e0

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

lib/private/Files/Cache/Storage.php

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@
2929
*/
3030
namespace OC\Files\Cache;
3131

32+
use OC\DB\Exceptions\DbalException;
33+
use OCP\AppFramework\Db\TTransactional;
34+
use OCP\DB\Exception;
3235
use OCP\DB\QueryBuilder\IQueryBuilder;
3336
use OCP\Files\Storage\IStorage;
37+
use OCP\IDBConnection;
3438
use Psr\Log\LoggerInterface;
3539

3640
/**
@@ -50,6 +54,8 @@ class Storage {
5054
private $storageId;
5155
private $numericId;
5256

57+
use TTransactional;
58+
5359
/**
5460
* @return StorageGlobal
5561
*/
@@ -65,29 +71,39 @@ public static function getGlobalCache() {
6571
* @param bool $isAvailable
6672
* @throws \RuntimeException
6773
*/
68-
public function __construct($storage, $isAvailable = true) {
74+
public function __construct($storage, bool $isAvailable = true) {
6975
if ($storage instanceof IStorage) {
7076
$this->storageId = $storage->getId();
7177
} else {
7278
$this->storageId = $storage;
7379
}
7480
$this->storageId = self::adjustStorageId($this->storageId);
7581

76-
if ($row = self::getStorageById($this->storageId)) {
77-
$this->numericId = (int)$row['numeric_id'];
78-
} else {
79-
$connection = \OC::$server->getDatabaseConnection();
80-
$available = $isAvailable ? 1 : 0;
81-
if ($connection->insertIfNotExist('*PREFIX*storages', ['id' => $this->storageId, 'available' => $available])) {
82-
$this->numericId = $connection->lastInsertId('*PREFIX*storages');
82+
$dbConnection = \OC::$server->get(IDBConnection::class);
83+
84+
$this->numericId = $this->atomic(function () use ($isAvailable, $dbConnection) {
85+
if ($row = self::getStorageById($this->storageId)) {
86+
return (int)$row['numeric_id'];
8387
} else {
84-
if ($row = self::getStorageById($this->storageId)) {
85-
$this->numericId = (int)$row['numeric_id'];
86-
} else {
87-
throw new \RuntimeException('Storage could neither be inserted nor be selected from the database: ' . $this->storageId);
88+
$qb = $dbConnection->getQueryBuilder();
89+
try {
90+
$qb->insert('storages')
91+
->values(['id' => $qb->createNamedParameter($this->storageId), 'available' => $qb->createNamedParameter($isAvailable ? 1 : 0)])
92+
->executeStatement();
93+
return $qb->getLastInsertId();
94+
} catch (DbalException $e) {
95+
if ($e->getReason() === Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
96+
// If a storage already exists with this ID, return it
97+
if ($row = self::getStorageById($this->storageId)) {
98+
return (int)$row['numeric_id'];
99+
} else {
100+
throw new \RuntimeException('Storage could neither be inserted nor be selected from the database: ' . $this->storageId);
101+
}
102+
}
103+
throw $e;
88104
}
89105
}
90-
}
106+
}, $dbConnection);
91107
}
92108

93109
/**

0 commit comments

Comments
 (0)