Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zend Server and APC functionality #94

Closed
kategray opened this issue Jun 19, 2017 · 15 comments
Closed

Zend Server and APC functionality #94

kategray opened this issue Jun 19, 2017 · 15 comments

Comments

@kategray
Copy link
Contributor

kategray commented Jun 19, 2017

Zend Server tries to implement compatibility with apc by registering compatibility functions with the same name as the APC functions.

http://files.zend.com/help/Zend-Server-6/content/zend_data_cache_-_configuration_directives.htm

Specifically, the option is "zend_datacache.apc_compatibility". It looks like it gets aliased to zend_shm_cache_store, which mostly works. Unfortunately, it doesn't support the array form of apc_store(), so every call results in errors:

"apc_store() expects parameter 1 to be string, array given"

It looks like this is a problem that other projects have dealt with, and it looks like it's one that's been going on for 8 years or so, so I'm not expecting Zend to fix it anytime soon.

My inclination would be to add a check to see if the parameter to apcu_add() or apcu_store() is an array, and if so to call the apc function individually for each item in the array. It would maintain compatibility with APC, and fix the issues with Zend Server. It's a little bit of a hack, though, and I figured I'd ask before submitting a PR.

Alternatively, I could add support for Zend Data Cache to the Symfony Cache Component.

@stof
Copy link
Member

stof commented Jun 19, 2017

I don't think we ever call apc_store directly in Symfony anymore.
Can you give the stack trace of the error to see where it happens ?

@kategray
Copy link
Contributor Author

kategray commented Jun 19, 2017

32	apc_store([...])	<builtin>	
31	apcu_store([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/polyfill/src/Apcu/bootstrap.php:27	
30	Symfony\Component\Cache\Adapter\ApcuAdapter::doSave([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php:95	
29	Symfony\Component\Cache\Adapter\AbstractAdapter::commit()	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php:335	
28	Symfony\Component\Cache\Adapter\AbstractAdapter::save([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php:304	
27	Symfony\Component\Cache\Adapter\ChainAdapter::save([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/Cache/Adapter/ChainAdapter.php:199	
26	Symfony\Component\Cache\Adapter\PhpArrayAdapter::save([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php:298	
25	Symfony\Component\Cache\DoctrineProvider::doSave([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/Cache/DoctrineProvider.php:58	
24	Doctrine\Common\Cache\CacheProvider::save([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php:132	
23	Doctrine\Common\Annotations\CachedReader::saveToCache([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php:207	
22	Doctrine\Common\Annotations\CachedReader::getClassAnnotations([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php:80	
21	Doctrine\ORM\Mapping\Driver\AnnotationDriver::loadMetadataForClass([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php:63	
20	Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain::loadMetadataForClass([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php:102	
19	Doctrine\ORM\Mapping\ClassMetadataFactory::doLoadMetadata([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php:151	
18	Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory::loadMetadata([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php:332	
17	Doctrine\ORM\Mapping\ClassMetadataFactory::loadMetadata([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php:78	
16	Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory::getMetadataFor([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php:216	
15	Doctrine\ORM\EntityManager::getClassMetadata([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:281	
14	Doctrine\ORM\Repository\DefaultRepositoryFactory::getRepository([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php:44	
13	Doctrine\ORM\EntityManager::getRepository([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:698	
12	EntityManager5947a4308dcd8_546a8d27f194334ee012bfe64f629947b07e4919\__CG__\Doctrine\ORM\EntityManager::getRepository([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/var/cache/prod/jms_diextra/doctrine/EntityManager_5947a4308dcd8.php:165	
11	appProdProjectContainer::getMadeline_SiteConfigurationRepositoryService()	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/var/cache/prod/appProdProjectContainer.php:2345	
10	Symfony\Component\DependencyInjection\Container::get([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:311	
9	appProdProjectContainer::getMadeline_SiteConfigurationListenerService()	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/var/cache/prod/appProdProjectContainer.php:2332	
8	Symfony\Component\DependencyInjection\Container::get([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:311	
7	Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher::lazyLoad([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php:181	
6	Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher::getListeners([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php:127	
5	Symfony\Component\EventDispatcher\EventDispatcher::dispatch([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php:42	
4	Symfony\Component\HttpKernel\HttpKernel::handleRaw([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php:129	
3	Symfony\Component\HttpKernel\HttpKernel::handle([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php:68	
2	Symfony\Component\HttpKernel\Kernel::handle([...])	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php:168	
1	{main}	/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72/web/app.php:13

@kategray
Copy link
Contributor Author

I was able to resolve the issue by patching as described:

https://github.com/kategray/polyfill/commit/e4d9188d6e68835625328c4785529b72b039ba11

@kategray
Copy link
Contributor Author

symfony/polyfill                     v1.4.0             Symfony polyfills backporting features to lower PHP versions
symfony/swiftmailer-bundle           v2.6.2             Symfony SwiftmailerBundle
symfony/symfony                      v3.2.9             The Symfony PHP framework

@stof
Copy link
Member

stof commented Jun 19, 2017

hmm, we could indeed handle this case in your APCu polyfill. It would fix things for people using the APCu polyfill.

@nicolas-grekas should be handle this internally in the polyfill, or should we just skip the polyfill if we detect that the apc functions are not the real ones by the Zend Server buggy shim ?

@kategray
Copy link
Contributor Author

It looks like createSystemCache() in Symfony/Component/Cache/Adapter/AbstractAdapter.php is checking if APCU is supported. The actual check is

return function_exists('apcu_fetch') && ini_get('apc.enabled') && !('cli' === PHP_SAPI && !ini_get('apc.enable_cli'));
It returns true with the Zend Cache compatibility layer enabled (as it is by default).

@kategray
Copy link
Contributor Author

@stof I believe you can detect if it's the genuine APC by doing a version check like so:

kate@ubuntu:/usr/local/zend/var/apps/http/madeline.local/80/ddcb30-dirty_72$ php
<?php
var_dump(phpversion('apc'));
bool(false)

@stof
Copy link
Member

stof commented Jun 19, 2017

@kategray currently, it reports it as supported, yes, as our polyfill-apcu package accepts polyfilling APCu on top of the Zend Server APC polyfill.

APCuAdapter only cares about APCu, and Zend Server does not mess with it. So this is not the place to add support for the APC messed polyfill.
This is why I said we should fix it at the polyfill-apcu level: either handling the quirk on apc_store on Zend Server, or disabling the APCu polyfill entirely by considering that APC is not available.
@nicolas-grekas what do you think about that decision ? Handle broken APC polyfill or forbid it ?

@kategray
Copy link
Contributor Author

@stof I agree - that's why I made the changes on my fork in the polyfill-apcu level.

If you and @nicolas-grekas would like me to do a pull request for the patch in my fork (the one that converts arrays to individual calls, maintaining compatibility with apc's error handling for the array syntax), I'd be glad to do so.

If not, I'll go ahead and delete my fork.

@nicolas-grekas
Copy link
Member

We should handle that in the APCu polyfill yes.
We should just find a proper check to do that foreach only when ZS is used. Original APC should be used straight with arrays.

@kategray
Copy link
Contributor Author

So, have separate functions for zend's APC emulation, and select which one in the bootstrap?

@nicolas-grekas
Copy link
Member

Yep

@kategray
Copy link
Contributor Author

Would you like me to do that?

@nicolas-grekas
Copy link
Member

Please :) I'm almost AFK for two weeks on my side.

@kategray
Copy link
Contributor Author

I ended up adding a second bootstrap.php, just for zend. It was cleaner than having two sets of functions in the same bootstrap file.

I added a couple of unit tests - they pass on PHP 5.4 with APC. Unfortunately, Zend Cache flat-out refuses to work in the CLI, so I just disable the compatibility when running from the CLI.

fabpot added a commit that referenced this issue Aug 16, 2017
…Server's Data Cache (kategray)

This PR was merged into the 1.5-dev branch.

Discussion
----------

Fix apcu function when apc ones are polyfilled with Zend Server's Data Cache

Fixes #94
Detect if Zend Server's Data Cache is enabled, and work around it's lack of support for the array syntax.

Commits
-------

a283ded Fix apcu function when apc ones are polyfilled with Zend Server's Data Cache
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants