I tried PHP 7 with APCu's 'seven' branch, but it did not work, because now the BC layer of apc has been removed from apcu.

So as we only support PHP 5.5 anyway and not PHP 5.4, we should switch all code to use apcu_* functions always.

Comments

Fabianx created an issue. See original summary.

dawehner’s picture

Status: Needs review » Active

+1

... there is no patch yet

andypost’s picture

According https://github.com/krakjoe/apcu/issues/104 there's no docs about API
so looks that extension should be build with apc support

fabianx’s picture

Priority: Major » Minor

Uhm, nevermind. The BC layer still exists, but needs to be configured (--enable-apcu-bc), but better to distinguish I think.

fabianx’s picture

catch’s picture

Issue tags: +8.0.1 target
amateescu’s picture

Status: Active » Needs review
StatusFileSize
new16.7 KB

Since we require PHP 5.5, this issue sounds like a very good idea :)

Status: Needs review » Needs work

The last submitted patch, 8: 2617568.patch, failed testing.

andypost’s picture

+++ b/core/lib/Drupal/Component/Utility/OpCodeCache.php
@@ -30,16 +30,6 @@ public static function invalidate($pathname) {
-    // If apcu extension is enabled in PHP 5.5 or greater it emulates apc.
-    // This is to provide an easy upgrade path if you are using apc's user
-    // caching however the emulation does not extend to opcode caching.
-    // Therefore we need to check if the function exists as well.
-    if (extension_loaded('apc') && function_exists('apc_delete_file')) {
-      // apc_delete_file() throws a PHP warning in case the specified file was
-      // not compiled yet.
-      // @see http://php.net/manual/en/function.apc-delete-file.php
-      @apc_delete_file($pathname);
-    }

Suppose this should be reverted

hussainweb’s picture

My guess is that the tests fail because it can't find APCUIterator. Is there any way to know the version of apcu on the testbots? It needs to be apcu 5.0.0 at least.

hussainweb’s picture

Okay, in the full log, I see the error:

16:24:27 Fatal error: Class 'APCUIterator' not found in /var/www/html/core/lib/Drupal/Core/Cache/ApcuBackend.php on line 212

It doesn't seem it is apcu 5.0.0. Do we have something on requirements with apcu? If we have to support apcu 4, I don't think we can do this in 8.0.1.

catch’s picture

Version: 8.0.x-dev » 8.1.x-dev
Priority: Minor » Normal
Issue tags: -8.0.1 target

We don't have any requirements set either way for APCu.

Any requirements change is going to be a minor release, so moving to 8.1.x for now.

We should consider a follow-up issue here to add hook_requirements() and detect the case where APCu is available but the backwards compatibility layer isn't enabled - or at least add that to drupal.org/requirements.

Also needs a DrupalCI issue for the APCu version change.

alexpott’s picture

So what is super interesting is that PHP7 is performing so well on testbot without APCu which was a massive performance boost. I think this will mean that we'll need to two versions of the APCBackend - one which supports the latest APCu on PHP7 and the one we have now.

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new18.44 KB
new3.68 KB

@andypost, apc_delete_file() does not exist in APCu 4.0.0, which is the first version compatible with PHP 5.5, so at this point it's just dead code :)

@alexpott, that sounds like a good way forward which would allow us to do this change even in 8.0.1.

How about something like this?

Status: Needs review » Needs work

The last submitted patch, 15: 2617568-15.patch, failed testing.

amateescu’s picture

Version: 8.1.x-dev » 8.0.x-dev
Status: Needs work » Needs review
StatusFileSize
new19.14 KB
new1011 bytes

Third time's the charm.

alexpott’s picture

+++ b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
@@ -50,7 +50,12 @@ public function __construct($root, $site_path, CacheTagsChecksumInterface $check
-    return new ApcuBackend($bin, $this->sitePrefix, $this->checksumProvider);
+    if (version_compare(phpversion('apcu'), '5.0.0', '>=')) {
+      return new ApcuBackend($bin, $this->sitePrefix, $this->checksumProvider);
+    }
+    else {
+      return new Apcu4Backend($bin, $this->sitePrefix, $this->checksumProvider);
+    }

Should we be doing this a runtime? Couldn't we add the classname to be used as an argument in a compiler pass? Otherwise we might as well do this in the getIterator() method of ApcuBackend.

amateescu’s picture

Otherwise we might as well do this in the getIterator() method of ApcuBackend.

That's exactly what I did initially, but then I thought that having it in the factory is cleaner and more explicit. No strong preference either way though :)

Status: Needs review » Needs work

The last submitted patch, 17: 2617568-17.patch, failed testing.

joelpittet’s picture

Status: Needs work » Needs review
amateescu’s picture

StatusFileSize
new20.04 KB
new3.88 KB

Now with less silliness :)

amateescu’s picture

StatusFileSize
new20.03 KB
new570 bytes

...

The last submitted patch, 22: 2617568-21.patch, failed testing.

The last submitted patch, 17: 2617568-17.patch, failed testing.

The last submitted patch, 8: 2617568.patch, failed testing.

The last submitted patch, 15: 2617568-15.patch, failed testing.

fabianx’s picture

Status: Needs review » Reviewed & tested by the community

#23 looks fantastic to me and no BC break either :).

To #18:

There is one backend thanks to the container for APCu - so this is called one time at service instantiation, which is perfectly fine to do at run-time.

The last submitted patch, 8: 2617568.patch, failed testing.

The last submitted patch, 17: 2617568-17.patch, failed testing.

The last submitted patch, 15: 2617568-15.patch, failed testing.

The last submitted patch, 22: 2617568-21.patch, failed testing.

andypost’s picture

+++ b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
@@ -50,7 +50,12 @@ public function __construct($root, $site_path, CacheTagsChecksumInterface $check
   public function get($bin) {
-    return new ApcuBackend($bin, $this->sitePrefix, $this->checksumProvider);
+    if (version_compare(phpversion('apcu'), '5.0.0', '>=')) {

Please move version check to constructor, it makes no sense to do that each time in get()

cilefen’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new20.7 KB
new1.61 KB
fabianx’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC, that is indeed cleaner.

neclimdul’s picture

This makes me very happy. Fits very nicely in the existing interfaces. +1

alexpott’s picture

Category: Task » Bug report
Status: Reviewed & tested by the community » Fixed

This is a bug - our APCu backend is broken on PHP7 - this patch fixes it. Committed b1b8cf5 and pushed to 8.0.x. Thanks!

alexpott’s picture

Committed b1b8cf5 and pushed to 8.0.x and 8.1.x. Thanks!

  • alexpott committed dfe0926 on 8.1.x
    Issue #2617568 by amateescu, cilefen, Fabianx: Rename apc_* functions...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

gapple’s picture

+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -428,7 +428,7 @@ public function boot() {
@@ -968,11 +968,11 @@ protected function initializeSettings(Request $request) {

@@ -968,11 +968,11 @@ protected function initializeSettings(Request $request) {
       }
     }
 
-    // If the class loader is still the same, possibly upgrade to the APC class
+    // If the class loader is still the same, possibly upgrade to the APCu class
     // loader.
     if ($class_loader_class == get_class($this->classLoader)
         && Settings::get('class_loader_auto_detect', TRUE)
-        && function_exists('apc_fetch')) {
+        && function_exists('apcu_fetch')) {
       $prefix = Settings::getApcuPrefix('class_loader', $this->root);
       $apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader($prefix, $this->classLoader);
       $this->classLoader->unregister();

This has caused a problem, since Symfony's ApcClassLoader's constructor checks extension_loaded('apc') and throws an exception if it fails. Consequently, if APCu is installed without backwards compatibility, Drupal is unable to run and always throws the exception Unable to use ApcClassLoader as APC is not enabled. in Symfony\Component\ClassLoader\ApcClassLoader->__construct().

#2646100: Exception on php7 + APCu without backwards compatibilty enabled was also created to report this issue, where I will attach a patch.