Issue #2556025 by david_garcia, dawehner, -enzo-, Fabianx, catch: Make optimized class loader detection more generic to support class loaders other than ApcClassLoader

8.3.x
Nathaniel Catchpole 2016-10-30 19:27:27 +00:00
parent 9bdda95a2b
commit 561580c43f
3 changed files with 36 additions and 16 deletions

View File

@ -9,19 +9,20 @@ use Drupal\Core\PhpStorage\PhpStorageFactory;
use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\Cache;
use Drupal\Core\DrupalKernel; use Drupal\Core\DrupalKernel;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Composer\Autoload\ClassLoader;
/** /**
* Rebuilds all caches even when Drupal itself does not work. * Rebuilds all caches even when Drupal itself does not work.
* *
* @param \Composer\Autoload\ClassLoader $class_loader * @param $class_loader
* The class loader. * The class loader. Normally Composer's ClassLoader, as included by the
* front controller, but may also be decorated; e.g.,
* \Symfony\Component\ClassLoader\ApcClassLoader, \Symfony\Component\ClassLoader\WinCacheClassLoader, or \Symfony\Component\ClassLoader\XcacheClassLoader
* @param \Symfony\Component\HttpFoundation\Request $request * @param \Symfony\Component\HttpFoundation\Request $request
* The current request. * The current request.
* *
* @see rebuild.php * @see rebuild.php
*/ */
function drupal_rebuild(ClassLoader $class_loader, Request $request) { function drupal_rebuild($class_loader, Request $request) {
// Remove Drupal's error and exception handlers; they rely on a working // Remove Drupal's error and exception handlers; they rely on a working
// service container and other subsystems and will only cause a fatal error // service container and other subsystems and will only cause a fatal error
// that hides the actual error. // that hides the actual error.

View File

@ -23,6 +23,8 @@ use Drupal\Core\Site\Settings;
use Drupal\Core\Test\TestDatabase; use Drupal\Core\Test\TestDatabase;
use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\ClassLoader\ApcClassLoader; use Symfony\Component\ClassLoader\ApcClassLoader;
use Symfony\Component\ClassLoader\WinCacheClassLoader;
use Symfony\Component\ClassLoader\XcacheClassLoader;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
@ -1028,16 +1030,29 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
} }
} }
// If the class loader is still the same, possibly upgrade to the APC class // If the class loader is still the same, possibly
// loader. // upgrade to an optimized class loader.
if ($class_loader_class == get_class($this->classLoader) if ($class_loader_class == get_class($this->classLoader)
&& Settings::get('class_loader_auto_detect', TRUE) && Settings::get('class_loader_auto_detect', TRUE)) {
&& function_exists('apcu_fetch')) {
$prefix = Settings::getApcuPrefix('class_loader', $this->root); $prefix = Settings::getApcuPrefix('class_loader', $this->root);
$apc_loader = new ApcClassLoader($prefix, $this->classLoader); $loader = NULL;
$this->classLoader->unregister();
$apc_loader->register(); // We autodetect one of the following three optimized classloaders, if
$this->classLoader = $apc_loader; // their underlying extension exists.
if (function_exists('apcu_fetch')) {
$loader = new ApcClassLoader($prefix, $this->classLoader);
}
elseif (extension_loaded('wincache')) {
$loader = new WinCacheClassLoader($prefix, $this->classLoader);
}
elseif (extension_loaded('xcache')) {
$loader = new XcacheClassLoader($prefix, $this->classLoader);
}
if (!empty($loader)) {
$this->classLoader->unregister();
$loader->register();
$this->classLoader = $loader;
}
} }
} }

View File

@ -42,10 +42,14 @@ if (Settings::get('rebuild_access', FALSE) ||
((REQUEST_TIME - $request->query->get('timestamp')) < 300) && ((REQUEST_TIME - $request->query->get('timestamp')) < 300) &&
Crypt::hashEquals(Crypt::hmacBase64($request->query->get('timestamp'), Settings::get('hash_salt')), $request->query->get('token')) Crypt::hashEquals(Crypt::hmacBase64($request->query->get('timestamp'), Settings::get('hash_salt')), $request->query->get('token'))
)) { )) {
// Clear the APCu cache to ensure APCu class loader is reset. // Clear user cache for all major platforms.
if (function_exists('apcu_clear_cache')) { $user_caches = [
apcu_clear_cache(); 'apcu_clear_cache',
} 'wincache_ucache_clear',
'xcache_clear_cache',
];
array_walk(array_filter($user_caches, 'is_callable'), 'call_user_func');
drupal_rebuild($autoloader, $request); drupal_rebuild($autoloader, $request);
drupal_set_message('Cache rebuild complete.'); drupal_set_message('Cache rebuild complete.');
} }