From 695d0ec973e3c1252aaf613b1469fa662f506f8f Mon Sep 17 00:00:00 2001 From: Nicolas Delaby <nicolas@nexedi.com> Date: Fri, 9 Apr 2010 15:48:40 +0000 Subject: [PATCH] Fix the way to access memcached.Client instances stored on connection_pool. If the configuration of memcached.Client instances are different to each other inside the same thread, the first created one is allways returned. So this patch store the instances inside a intermediate dictionary with keys build with discriminatory criterions. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@34441 20353a03-c40f-0410-a6d1-a30d3c3de9de --- .../CachePlugins/DistributedRamCache.py | 33 +++++++++++-------- product/ERP5Type/Tool/MemcachedTool.py | 8 +++-- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/product/ERP5Type/CachePlugins/DistributedRamCache.py b/product/ERP5Type/CachePlugins/DistributedRamCache.py index e879b1bf7a..3ba03b0efe 100644 --- a/product/ERP5Type/CachePlugins/DistributedRamCache.py +++ b/product/ERP5Type/CachePlugins/DistributedRamCache.py @@ -39,12 +39,11 @@ import zope.interface from base64 import encodestring try: - import memcache from Products.ERP5Type.Tool.MemcachedTool import MemcachedDict, SharedDict except ImportError: LOG('DistributedRamCache', 0, 'unable to import memcache') -## global ditionary containing connection objects +## global dictionary containing connection objects connection_pool = local() _MARKER = [] @@ -69,22 +68,30 @@ class DistributedRamCache(BaseCache): ## cache storage is a memcached server and no need to init it pass - def getCacheStorage(self, **kw): - ## if we use one connection object this causes - ## "MemCached: while expecting 'STORED', got unexpected response 'END'" - ## messages in log files and can sometimes can block the thread. - ## For the moment we create a new conn object for every thread. + def _getMemcachedDict(self): + """return a threading safe MemcachedDict instance + """ + configuration_key = (self._servers, self._server_max_key_length, + self._server_max_value_length, + self._debug_level, self._key_prefix) try: - dictionary = connection_pool.memcached_dict + local_dict = connection_pool.local_dict except AttributeError: - dictionary = SharedDict( - MemcachedDict(self._servers.split('\n'), + local_dict = connection_pool.local_dict = {} + try: + dictionary = local_dict[configuration_key] + except KeyError: + dictionary = MemcachedDict(self._servers.split('\n'), server_max_key_length=self._server_max_key_length, - server_max_value_length=self._server_max_value_length), - prefix=self._key_prefix) - connection_pool.memcached_dict = dictionary + server_max_value_length=self._server_max_value_length) + local_dict[configuration_key] = dictionary return dictionary + def getCacheStorage(self, **kw): + """Follow MemcachedTool.getMemcachedDict implementation + """ + return SharedDict(self._getMemcachedDict(), prefix=self._key_prefix) + def _getCacheId(self, cache_id, scope): return '%s_%s' % (scope, cache_id) diff --git a/product/ERP5Type/Tool/MemcachedTool.py b/product/ERP5Type/Tool/MemcachedTool.py index 6d5faf0b9a..b7b9bc710f 100644 --- a/product/ERP5Type/Tool/MemcachedTool.py +++ b/product/ERP5Type/Tool/MemcachedTool.py @@ -279,15 +279,19 @@ if memcache is not None: Create it if does not exist. """ try: - dictionary = memcached_dict_pool.memcached_dict + local_dict = memcached_dict_pool.local_dict except AttributeError: + local_dict = memcached_dict_pool.local_dict = {} + try: + dictionary = local_dict[plugin_path] + except KeyError: memcached_plugin = self.restrictedTraverse(plugin_path, None) if memcached_plugin is None: raise ValueError, 'Memcached Plugin does not exists: %r' % (plugin_path,) dictionary = MemcachedDict((memcached_plugin.getUrlString(''),), server_max_key_length=memcached_plugin.getServerMaxKeyLength(), server_max_value_length=memcached_plugin.getServerMaxValueLength()) - memcached_dict_pool.memcached_dict = dictionary + local_dict[plugin_path] = dictionary return dictionary security.declareProtected(Permissions.AccessContentsInformation, 'getMemcachedDict') -- 2.30.9