2929 */
3030namespace OC \Files \Cache ;
3131
32+ use OC \DB \Exceptions \DbalException ;
33+ use OCP \AppFramework \Db \TTransactional ;
34+ use OCP \DB \Exception ;
3235use OCP \DB \QueryBuilder \IQueryBuilder ;
3336use OCP \Files \Storage \IStorage ;
37+ use OCP \IDBConnection ;
3438use 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