Commit 189db11c authored by Vincent Pelletier's avatar Vincent Pelletier

SQLCatalog: Optimise and simplify transactional_cache_decorator.

Auto-generate cache_id, removing the risk of duplicating one.
Inline getInstanceID as it is its only caller left.
Avoid wrapping if getTransactionalVariable cannot be imported.
Avoid intermediate variables, at the cost of dupicating logic but
accelerating run-time.
Use functools.wraps .
Access _cache_sequence_number directly - these pieces of code are friends
anyway, we already set a volatile property on Catalog instance. Saves one
getattr and one call.
parent 66f13089
...@@ -40,6 +40,7 @@ from ZODB.POSException import ConflictError ...@@ -40,6 +40,7 @@ from ZODB.POSException import ConflictError
from Products.CMFCore import permissions from Products.CMFCore import permissions
from Products.PythonScripts.Utility import allow_class from Products.PythonScripts.Utility import allow_class
from functools import wraps
import time import time
import urllib import urllib
import string import string
...@@ -89,37 +90,37 @@ except ImportError: ...@@ -89,37 +90,37 @@ except ImportError:
LOG('SQLCatalog', WARNING, 'Count not import getTransactionalVariable, expect slowness.') LOG('SQLCatalog', WARNING, 'Count not import getTransactionalVariable, expect slowness.')
def getTransactionalVariable(): def getTransactionalVariable():
return {} return {}
def transactional_cache_decorator(method):
def getInstanceID(instance): return method
else:
def transactional_cache_decorator(method):
"""
Implements singleton-style caching.
Wrapped method must have no parameters (besides "self").
"""
cache_id = id(method)
@wraps(method)
def wrapper(self):
# XXX: getPhysicalPath is overkill for a unique cache identifier. # XXX: getPhysicalPath is overkill for a unique cache identifier.
# What I would like to use instead of it is: # What I would like to use instead of it is:
# (self._p_jar.db().database_name, self._p_oid) # (self._p_jar.db().database_name, self._p_oid)
# but database_name is not unique in at least ZODB 3.4 (Zope 2.8.8). # but database_name is not unique in at least ZODB 3.4 (Zope 2.8.8).
try: try:
instance_id = instance._v_physical_path instance_id = self._v_physical_path
except AttributeError: except AttributeError:
instance._v_physical_path = instance_id = instance.getPhysicalPath() self._v_physical_path = instance_id = self.getPhysicalPath()
return instance_id
class transactional_cache_decorator:
"""
Implements singleton-style caching.
Wrapped method must have no parameters (besides "self").
"""
def __init__(self, cache_id):
self.cache_id = cache_id
def __call__(self, method):
def wrapper(wrapped_self):
transactional_cache = getTransactionalVariable()
cache_id = str((self.cache_id,
wrapped_self.getCacheSequenceNumber(),
getInstanceID(wrapped_self),
))
try: try:
result = transactional_cache[cache_id] return getTransactionalVariable()[(
cache_id,
self._cache_sequence_number,
instance_id,
)]
except KeyError: except KeyError:
result = transactional_cache[cache_id] = method(wrapped_self) getTransactionalVariable()[(
cache_id,
self._cache_sequence_number,
instance_id,
)] = result = method(self)
return result return result
return wrapper return wrapper
...@@ -944,7 +945,7 @@ class Catalog(Folder, ...@@ -944,7 +945,7 @@ class Catalog(Folder,
def getSqlCatalogSchema(self): def getSqlCatalogSchema(self):
return self.sql_catalog_schema return self.sql_catalog_schema
@transactional_cache_decorator('SQLCatalog._getCatalogSchema') @transactional_cache_decorator
def _getCatalogSchema(self): def _getCatalogSchema(self):
method = getattr(self, self.sql_catalog_multi_schema, None) method = getattr(self, self.sql_catalog_multi_schema, None)
result = {} result = {}
...@@ -985,7 +986,7 @@ class Catalog(Folder, ...@@ -985,7 +986,7 @@ class Catalog(Folder,
return self._getCatalogSchema()[table] return self._getCatalogSchema()[table]
security.declarePublic('getColumnIds') security.declarePublic('getColumnIds')
@transactional_cache_decorator('SQLCatalog.getColumnIds') @transactional_cache_decorator
def getColumnIds(self): def getColumnIds(self):
""" """
Calls the show column method and returns dictionnary of Calls the show column method and returns dictionnary of
...@@ -1007,7 +1008,7 @@ class Catalog(Folder, ...@@ -1007,7 +1008,7 @@ class Catalog(Folder,
return sorted(keys) return sorted(keys)
security.declarePrivate('getColumnMap') security.declarePrivate('getColumnMap')
@transactional_cache_decorator('SQLCatalog.getColumnMap') @transactional_cache_decorator
def getColumnMap(self): def getColumnMap(self):
""" """
Calls the show column method and returns dictionnary of Calls the show column method and returns dictionnary of
...@@ -1022,7 +1023,7 @@ class Catalog(Folder, ...@@ -1022,7 +1023,7 @@ class Catalog(Folder,
return result return result
security.declarePublic('getResultColumnIds') security.declarePublic('getResultColumnIds')
@transactional_cache_decorator('SQLCatalog.getResultColumnIds') @transactional_cache_decorator
def getResultColumnIds(self): def getResultColumnIds(self):
""" """
Calls the show column method and returns dictionnary of Calls the show column method and returns dictionnary of
...@@ -1036,7 +1037,7 @@ class Catalog(Folder, ...@@ -1036,7 +1037,7 @@ class Catalog(Folder,
return sorted(keys) return sorted(keys)
security.declarePublic('getSortColumnIds') security.declarePublic('getSortColumnIds')
@transactional_cache_decorator('SQLCatalog.getSortColumnIds') @transactional_cache_decorator
def getSortColumnIds(self): def getSortColumnIds(self):
""" """
Calls the show column method and returns dictionnary of Calls the show column method and returns dictionnary of
...@@ -1713,7 +1714,7 @@ class Catalog(Folder, ...@@ -1713,7 +1714,7 @@ class Catalog(Folder,
""" """
return self.getCatalogMethodIds(valid_method_meta_type_list=('Script (Python)', )) return self.getCatalogMethodIds(valid_method_meta_type_list=('Script (Python)', ))
@transactional_cache_decorator('SQLCatalog._getSQLCatalogRelatedKeyList') @transactional_cache_decorator
def _getSQLCatalogRelatedKeySet(self): def _getSQLCatalogRelatedKeySet(self):
column_map = self.getColumnMap() column_map = self.getColumnMap()
column_set = set(column_map) column_set = set(column_map)
...@@ -1758,7 +1759,7 @@ class Catalog(Folder, ...@@ -1758,7 +1759,7 @@ class Catalog(Folder,
""" """
return self.sql_catalog_scriptable_keys return self.sql_catalog_scriptable_keys
@transactional_cache_decorator('SQLCatalog.getTableIndex') @transactional_cache_decorator
def _getTableIndex(self, table): def _getTableIndex(self, table):
table_index = {} table_index = {}
method = getattr(self, self.sql_catalog_index, '') method = getattr(self, self.sql_catalog_index, '')
...@@ -1830,7 +1831,7 @@ class Catalog(Folder, ...@@ -1830,7 +1831,7 @@ class Catalog(Folder,
def getSqlCatalogScriptableKeysList(self): def getSqlCatalogScriptableKeysList(self):
return self.sql_catalog_scriptable_keys return self.sql_catalog_scriptable_keys
@transactional_cache_decorator('SQLCatalog._getgetScriptableKeyDict') @transactional_cache_decorator
def _getgetScriptableKeyDict(self): def _getgetScriptableKeyDict(self):
result = {} result = {}
for scriptable_key_definition in self.getSqlCatalogScriptableKeysList(): for scriptable_key_definition in self.getSqlCatalogScriptableKeysList():
...@@ -2321,7 +2322,7 @@ class Catalog(Folder, ...@@ -2321,7 +2322,7 @@ class Catalog(Folder,
def getSqlCatalogSearchKeysList(self): def getSqlCatalogSearchKeysList(self):
return self.sql_catalog_search_keys return self.sql_catalog_search_keys
@transactional_cache_decorator('SQLCatalog._getSearchKeyDict') @transactional_cache_decorator
def _getSearchKeyDict(self): def _getSearchKeyDict(self):
result = {} result = {}
search_key_column_dict = { search_key_column_dict = {
...@@ -2588,7 +2589,7 @@ class Catalog(Folder, ...@@ -2588,7 +2589,7 @@ class Catalog(Folder,
return '' return ''
security.declarePublic('getOptimizerSwitchKeyList') security.declarePublic('getOptimizerSwitchKeyList')
@transactional_cache_decorator('SQLCatalog.getOptimizerSwitchKeyList') @transactional_cache_decorator
def getOptimizerSwitchKeyList(self): def getOptimizerSwitchKeyList(self):
return [ return [
pair.split('=', 1)[0] pair.split('=', 1)[0]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment