diff --git a/apps/settings/lib/Controller/CheckSetupController.php b/apps/settings/lib/Controller/CheckSetupController.php
index 89dfc7b617..407834cf9d 100644
--- a/apps/settings/lib/Controller/CheckSetupController.php
+++ b/apps/settings/lib/Controller/CheckSetupController.php
@@ -110,6 +110,8 @@ class CheckSetupController extends Controller {
private $iniGetWrapper;
/** @var IDBConnection */
private $connection;
+ /** @var OC\AppFramework\Maintenance\OptionalIndexManager */
+ private $indexManager;
public function __construct($AppName,
IRequest $request,
@@ -126,7 +128,8 @@ class CheckSetupController extends Controller {
MemoryInfo $memoryInfo,
ISecureRandom $secureRandom,
IniGetWrapper $iniGetWrapper,
- IDBConnection $connection) {
+ IDBConnection $connection,
+ OC\AppFramework\Maintenance\OptionalIndexManager $indexManager) {
parent::__construct($AppName, $request);
$this->config = $config;
$this->clientService = $clientService;
@@ -142,6 +145,7 @@ class CheckSetupController extends Controller {
$this->secureRandom = $secureRandom;
$this->iniGetWrapper = $iniGetWrapper;
$this->connection = $connection;
+ $this->indexManager = $indexManager;
}
/**
@@ -466,6 +470,11 @@ Raw output
$event = new GenericEvent($indexInfo);
$this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_INDEXES_EVENT, $event);
+ $indexes = $this->indexManager->getPending();
+ foreach ($indexes as $index) {
+ $indexInfo->addHintForMissingSubject($index->getTable(), $index->getName());
+ }
+
return $indexInfo->getListOfMissingIndexes();
}
diff --git a/core/Command/Db/AddMissingIndices.php b/core/Command/Db/AddMissingIndices.php
index 1acff55fa4..11155afb4f 100644
--- a/core/Command/Db/AddMissingIndices.php
+++ b/core/Command/Db/AddMissingIndices.php
@@ -33,6 +33,7 @@ declare(strict_types=1);
namespace OC\Core\Command\Db;
+use OC\AppFramework\Maintenance\OptionalIndexManager;
use OC\DB\Connection;
use OC\DB\SchemaWrapper;
use OCP\IDBConnection;
@@ -58,11 +59,17 @@ class AddMissingIndices extends Command {
/** @var EventDispatcherInterface */
private $dispatcher;
- public function __construct(Connection $connection, EventDispatcherInterface $dispatcher) {
+ /** @var OptionalIndexManager */
+ private $indexManager;
+
+ public function __construct(Connection $connection,
+ EventDispatcherInterface $dispatcher,
+ OptionalIndexManager $indexManager) {
parent::__construct();
$this->connection = $connection;
$this->dispatcher = $dispatcher;
+ $this->indexManager = $indexManager;
}
protected function configure() {
@@ -77,9 +84,21 @@ class AddMissingIndices extends Command {
// Dispatch event so apps can also update indexes if needed
$event = new GenericEvent($output);
$this->dispatcher->dispatch(IDBConnection::ADD_MISSING_INDEXES_EVENT, $event);
+
+ $this->addOptionalIndexed($output);
+
return 0;
}
+ private function addOptionalIndexed(OutputInterface $output): void {
+ $indexes = $this->indexManager->getPending();
+
+ foreach ($indexes as $index) {
+ $output->writeln('Adding additional ' . $index->getName() . ' index to the ' . $index->getTable() . ' this can take some time …');
+ $index->add();
+ }
+ }
+
/**
* add missing indices to the share table
*
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index f63d74b560..bc951a4009 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -66,6 +66,7 @@ return array(
'OCP\\AppFramework\\Http\\TooManyRequestsResponse' => $baseDir . '/lib/public/AppFramework/Http/TooManyRequestsResponse.php',
'OCP\\AppFramework\\Http\\ZipResponse' => $baseDir . '/lib/public/AppFramework/Http/ZipResponse.php',
'OCP\\AppFramework\\IAppContainer' => $baseDir . '/lib/public/AppFramework/IAppContainer.php',
+ 'OCP\\AppFramework\\Maintenance\\IOptionalIndex' => $baseDir . '/lib/public/AppFramework/Maintenance/IOptionalIndex.php',
'OCP\\AppFramework\\Middleware' => $baseDir . '/lib/public/AppFramework/Middleware.php',
'OCP\\AppFramework\\OCSController' => $baseDir . '/lib/public/AppFramework/OCSController.php',
'OCP\\AppFramework\\OCS\\OCSBadRequestException' => $baseDir . '/lib/public/AppFramework/OCS/OCSBadRequestException.php',
@@ -605,6 +606,7 @@ return array(
'OC\\AppFramework\\Http\\Output' => $baseDir . '/lib/private/AppFramework/Http/Output.php',
'OC\\AppFramework\\Http\\Request' => $baseDir . '/lib/private/AppFramework/Http/Request.php',
'OC\\AppFramework\\Logger' => $baseDir . '/lib/private/AppFramework/Logger.php',
+ 'OC\\AppFramework\\Maintenance\\OptionalIndexManager' => $baseDir . '/lib/private/AppFramework/Maintenance/OptionalIndexManager.php',
'OC\\AppFramework\\Middleware\\AdditionalScriptsMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php',
'OC\\AppFramework\\Middleware\\CompressionMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/CompressionMiddleware.php',
'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => $baseDir . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 9c861fd327..2a8ccde579 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -95,6 +95,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\AppFramework\\Http\\TooManyRequestsResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/TooManyRequestsResponse.php',
'OCP\\AppFramework\\Http\\ZipResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/ZipResponse.php',
'OCP\\AppFramework\\IAppContainer' => __DIR__ . '/../../..' . '/lib/public/AppFramework/IAppContainer.php',
+ 'OCP\\AppFramework\\Maintenance\\IOptionalIndex' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Maintenance/IOptionalIndex.php',
'OCP\\AppFramework\\Middleware' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Middleware.php',
'OCP\\AppFramework\\OCSController' => __DIR__ . '/../../..' . '/lib/public/AppFramework/OCSController.php',
'OCP\\AppFramework\\OCS\\OCSBadRequestException' => __DIR__ . '/../../..' . '/lib/public/AppFramework/OCS/OCSBadRequestException.php',
@@ -634,6 +635,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\AppFramework\\Http\\Output' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/Output.php',
'OC\\AppFramework\\Http\\Request' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/Request.php',
'OC\\AppFramework\\Logger' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Logger.php',
+ 'OC\\AppFramework\\Maintenance\\OptionalIndexManager' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Maintenance/OptionalIndexManager.php',
'OC\\AppFramework\\Middleware\\AdditionalScriptsMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php',
'OC\\AppFramework\\Middleware\\CompressionMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/CompressionMiddleware.php',
'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php',
diff --git a/lib/private/AppFramework/Bootstrap/RegistrationContext.php b/lib/private/AppFramework/Bootstrap/RegistrationContext.php
index 0859e606b7..82cb884db1 100644
--- a/lib/private/AppFramework/Bootstrap/RegistrationContext.php
+++ b/lib/private/AppFramework/Bootstrap/RegistrationContext.php
@@ -34,6 +34,7 @@ use Closure;
use OC\Support\CrashReport\Registry;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
+use OCP\AppFramework\Maintenance\IOptionalIndex;
use OCP\AppFramework\Middleware;
use OCP\AppFramework\Services\InitialStateProvider;
use OCP\Authentication\IAlternativeLogin;
@@ -94,6 +95,9 @@ class RegistrationContext {
/** @var ServiceRegistration[] */
private $notifierServices = [];
+ /** @var ServiceRegistration */
+ private $optionalIndexes = [];
+
/** @var ServiceRegistration<\OCP\Authentication\TwoFactorAuth\IProvider>[] */
private $twoFactorProviders = [];
@@ -221,6 +225,13 @@ class RegistrationContext {
);
}
+ public function registerOptionalIndex(string $class): void {
+ $this->context->registerOptionalIndex(
+ $this->appId,
+ $class
+ );
+ }
+
public function registerTwoFactorProvider(string $twoFactorProviderClass): void {
$this->context->registerTwoFactorProvider(
$this->appId,
@@ -298,6 +309,10 @@ class RegistrationContext {
$this->notifierServices[] = new ServiceRegistration($appId, $class);
}
+ public function registerOptionalIndex(string $appId, string $class): void {
+ $this->optionalIndexes[] = new ServiceRegistration($appId, $class);
+ }
+
public function registerTwoFactorProvider(string $appId, string $class): void {
$this->twoFactorProviders[] = new ServiceRegistration($appId, $class);
}
@@ -315,6 +330,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during capability registration of $appId: " . $e->getMessage(), [
'exception' => $e,
+
]);
}
}
@@ -331,6 +347,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during crash reporter registration of $appId: " . $e->getMessage(), [
'exception' => $e,
+
]);
}
}
@@ -347,6 +364,7 @@ class RegistrationContext {
$appId = $panel->getAppId();
$this->logger->error("Error during dashboard registration of $appId: " . $e->getMessage(), [
'exception' => $e,
+
]);
}
}
@@ -364,6 +382,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during event listener registration of $appId: " . $e->getMessage(), [
'exception' => $e,
+
]);
}
}
@@ -389,6 +408,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during service registration of $appId: " . $e->getMessage(), [
'exception' => $e,
+
]);
}
}
@@ -405,6 +425,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during service alias registration of $appId: " . $e->getMessage(), [
'exception' => $e,
+
]);
}
}
@@ -421,6 +442,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during service alias registration of $appId: " . $e->getMessage(), [
'exception' => $e,
+
]);
}
}
@@ -439,6 +461,7 @@ class RegistrationContext {
$appId = $middleware->getAppId();
$this->logger->error("Error during capability registration of $appId: " . $e->getMessage(), [
'exception' => $e,
+
]);
}
}
@@ -486,6 +509,13 @@ class RegistrationContext {
return $this->notifierServices;
}
+ /**
+ * @return ServiceRegistration[]
+ */
+ public function getOptionalIndexes(): array {
+ return $this->optionalIndexes;
+ }
+
/**
* @return ServiceRegistration<\OCP\Authentication\TwoFactorAuth\IProvider>[]
*/
diff --git a/lib/private/AppFramework/Maintenance/OptionalIndexManager.php b/lib/private/AppFramework/Maintenance/OptionalIndexManager.php
new file mode 100644
index 0000000000..82570046f0
--- /dev/null
+++ b/lib/private/AppFramework/Maintenance/OptionalIndexManager.php
@@ -0,0 +1,92 @@
+
+ *
+ * @author Roeland Jago Douma
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see .
+ *
+ */
+
+namespace OC\AppFramework\Maintenance;
+
+use OC\AppFramework\Bootstrap\Coordinator;
+use OCP\AppFramework\Maintenance\IOptionalIndex;
+use OCP\AppFramework\QueryException;
+use OCP\IServerContainer;
+use Psr\Log\LoggerInterface;
+
+class OptionalIndexManager {
+
+ /** @var IServerContainer */
+ private $serverContainer;
+
+ /** @var Coordinator */
+ private $coordinator;
+
+ /** @var LoggerInterface */
+ private $logger;
+
+ /** @var IOptionalIndex[] */
+ private $optionalIndexes;
+
+ public function __construct(
+ IServerContainer $serverContainer,
+ Coordinator $coordinator,
+ LoggerInterface $logger
+ ) {
+ $this->coordinator = $coordinator;
+ $this->serverContainer = $serverContainer;
+ $this->logger = $logger;
+ }
+
+ /**
+ * @return IOptionalIndex[]
+ */
+ public function getPending(): array {
+ if ($this->optionalIndexes !== null) {
+ return $this->optionalIndexes;
+ }
+
+ $context = $this->coordinator->getRegistrationContext();
+
+ foreach ($context->getOptionalIndexes() as $optionalIndex) {
+ try {
+ $class = $this->serverContainer->query($optionalIndex->getService());
+ } catch (QueryException $e) {
+ $this->logger->info('Could not initialize ' . $optionalIndex->getService() . ' for ' . $optionalIndex->getAppId());
+ continue;
+ }
+
+ if (!($class instanceof IOptionalIndex)) {
+ $this->logger->info($optionalIndex->getService() . ' is not an instance of ' . IOptionalIndex::class);
+ continue;
+ }
+
+ if ($class->exists()) {
+ $this->logger->debug($optionalIndex->getService() . ' is already added');
+ continue;
+ }
+
+ $this->optionalIndexes[] = $class;
+ }
+
+ return $this->optionalIndexes;
+ }
+}
diff --git a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
index 4819d4e211..c247040a29 100644
--- a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
+++ b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
@@ -32,6 +32,7 @@ namespace OCP\AppFramework\Bootstrap;
use OCP\AppFramework\IAppContainer;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Capabilities\ICapability;
+use OCP\AppFramework\Maintenance\IOptionalIndex;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Template\ICustomTemplateProvider;
use OCP\IContainer;
@@ -221,6 +222,15 @@ interface IRegistrationContext {
*/
public function registerNotifierService(string $notifierClass): void;
+ /**
+ * Register an optional index that is able to display and add indexes to the system
+ *
+ * @param string $class
+ * @psalm-param class-string $class
+ * @since 22.0.0
+ */
+ public function registerOptionalIndex(string $class): void;
+
/**
* Register a two-factor provider
*
diff --git a/lib/public/AppFramework/Maintenance/IOptionalIndex.php b/lib/public/AppFramework/Maintenance/IOptionalIndex.php
new file mode 100644
index 0000000000..6e3d0a8609
--- /dev/null
+++ b/lib/public/AppFramework/Maintenance/IOptionalIndex.php
@@ -0,0 +1,72 @@
+
+ *
+ * @author Roeland Jago Douma
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see .
+ *
+ */
+
+namespace OCP\AppFramework\Maintenance;
+
+/**
+ * @since 22.0.0
+ */
+interface IOptionalIndex {
+ /**
+ * Get the name of the optional index to display
+ *
+ * @since 22.0.0
+ * @return string
+ */
+ public function getName(): string;
+
+ /**
+ * Get the name of the table this operates on
+ *
+ * @since 22.0.0
+ * @return string
+ */
+ public function getTable(): string;
+
+ /**
+ * Does the optional index already exist
+ *
+ * @since 22.0.0
+ * @return bool
+ */
+ public function exists(): bool;
+
+ /**
+ * Adds the index
+ *
+ * @since 22.0.0
+ */
+ public function add(): void;
+
+ /**
+ * Get the SQL for the index creation so we can display this for admins
+ * to run the queries directly on their DB
+ *
+ * @since 22.0.0
+ * @return string
+ */
+ public function getSQL(): string;
+}