diff --git a/bin/addons/base/ir/ir_model.py b/bin/addons/base/ir/ir_model.py index b5b063c7657..e591c1a762e 100644 --- a/bin/addons/base/ir/ir_model.py +++ b/bin/addons/base/ir/ir_model.py @@ -376,18 +376,18 @@ class ir_model_access(osv.osv): def write(self, cr, uid, *args, **argv): self.call_cache_clearing_methods() res = super(ir_model_access, self).write(cr, uid, *args, **argv) - self.check() # clear the cache of check function + self.check.clear_cache(cr.dbname) # clear the cache of check function return res def create(self, cr, uid, *args, **argv): res = super(ir_model_access, self).create(cr, uid, *args, **argv) - self.check() + self.check.clear_cache(cr.dbname) # clear the cache of check function return res def unlink(self, cr, uid, *args, **argv): self.call_cache_clearing_methods() res = super(ir_model_access, self).unlink(cr, uid, *args, **argv) - self.check() + self.check.clear_cache(cr.dbname) # clear the cache of check function return res ir_model_access() diff --git a/bin/addons/base/ir/ir_rule.py b/bin/addons/base/ir/ir_rule.py index 6c508f83662..40b40033a62 100644 --- a/bin/addons/base/ir/ir_rule.py +++ b/bin/addons/base/ir/ir_rule.py @@ -46,21 +46,19 @@ class ir_rule_group(osv.osv): def unlink(self, cr, uid, ids, context=None): res = super(ir_rule_group, self).unlink(cr, uid, ids, context=context) # Restart the cache on the domain_get method of ir.rule - self.pool.get('ir.rule').domain_get() + self.pool.get('ir.rule').domain_get.clear_cache(cr.dbname) return res def create(self, cr, user, vals, context=None): res = super(ir_rule_group, self).create(cr, user, vals, context=context) # Restart the cache on the domain_get method of ir.rule - self.pool.get('ir.rule').domain_get() + self.pool.get('ir.rule').domain_get.clear_cache(cr.dbname) return res def write(self, cr, uid, ids, vals, context=None): - if not context: - context={} res = super(ir_rule_group, self).write(cr, uid, ids, vals, context=context) # Restart the cache on the domain_get method of ir.rule - self.pool.get('ir.rule').domain_get() + self.pool.get('ir.rule').domain_get.clear_cache(cr.dbname) return res ir_rule_group() @@ -213,13 +211,13 @@ class ir_rule(osv.osv): def unlink(self, cr, uid, ids, context=None): res = super(ir_rule, self).unlink(cr, uid, ids, context=context) # Restart the cache on the domain_get method of ir.rule - self.domain_get() + self.domain_get.clear_cache(cr.dbname) return res def create(self, cr, user, vals, context=None): res = super(ir_rule, self).create(cr, user, vals, context=context) # Restart the cache on the domain_get method of ir.rule - self.domain_get() + self.domain_get.clear_cache(cr.dbname) return res def write(self, cr, uid, ids, vals, context=None): @@ -227,7 +225,7 @@ class ir_rule(osv.osv): context={} res = super(ir_rule, self).write(cr, uid, ids, vals, context=context) # Restart the cache on the domain_get method - self.domain_get() + self.domain_get.clear_cache(cr.dbname) return res ir_rule() diff --git a/bin/addons/base/res/res_company.py b/bin/addons/base/res/res_company.py index 660005b0107..628a8f8eccf 100644 --- a/bin/addons/base/res/res_company.py +++ b/bin/addons/base/res/res_company.py @@ -68,24 +68,21 @@ class res_company(osv.osv): descendance = self._get_partner_descendance(cr, uid, child_id, descendance) return descendance - def __init__(self, *args, **argv): - return super(res_company, self).__init__(*args, **argv) - # # This function restart the cache on the _get_company_children method # - def cache_restart(self, uid=None): - self._get_company_children() + def cache_restart(self, cr): + self._get_company_children.clear_cache(cr.dbname) - def create(self, *args, **argv): - self.cache_restart() - return super(res_company, self).create(*args, **argv) + def create(self, cr, *args, **argv): + self.cache_restart(cr) + return super(res_company, self).create(cr, *args, **argv) - def write(self, *args, **argv): - self.cache_restart() + def write(self, cr, *args, **argv): + self.cache_restart(cr) # Restart the cache on the company_get method - self.pool.get('ir.rule').domain_get() - return super(res_company, self).write(*args, **argv) + self.pool.get('ir.rule').domain_get.clear_cache(cr.dbname) + return super(res_company, self).write(cr, *args, **argv) def _get_euro(self, cr, uid, context={}): try: diff --git a/bin/addons/base/res/res_user.py b/bin/addons/base/res/res_user.py index b9c9c1ba1c6..96ccfa52b7b 100644 --- a/bin/addons/base/res/res_user.py +++ b/bin/addons/base/res/res_user.py @@ -47,8 +47,8 @@ class groups(osv.osv): _('The name of the group can not start with "-"')) res = super(groups, self).write(cr, uid, ids, vals, context=context) # Restart the cache on the company_get method - self.pool.get('ir.rule').domain_get() - self.pool.get('ir.model.access').check() + self.pool.get('ir.rule').domain_get.clear_cache(cr.dbname) + self.pool.get('ir.model.access').check.clear_cache(cr.dbname) return res def create(self, cr, uid, vals, context=None): @@ -165,9 +165,9 @@ class users(osv.osv): if ok: uid = 1 res = super(users, self).write(cr, uid, ids, values, *args, **argv) - self.company_get() + self.company_get.clear_cache(cr.dbname) # Restart the cache on the company_get method - self.pool.get('ir.rule').domain_get() + self.pool.get('ir.rule').domain_get.clear_cache(cr.dbname) return res def unlink(self, cr, uid, ids): diff --git a/bin/sql_db.py b/bin/sql_db.py index 92c55c2ad9d..49094a438f8 100644 --- a/bin/sql_db.py +++ b/bin/sql_db.py @@ -228,7 +228,7 @@ def db_connect(db_name, serialize=0): def close_db(db_name): PoolManager.close(db_name) - tools.cache.clean_cache_for_db(db_name) + tools.cache.clean_caches_for_db(db_name) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/bin/tools/misc.py b/bin/tools/misc.py index d27191616aa..6b366eec67f 100644 --- a/bin/tools/misc.py +++ b/bin/tools/misc.py @@ -549,26 +549,74 @@ class cache(object): self.multi = multi self.lasttime = time.time() self.cache = {} - + self.fun = None cache.__caches.append(self) - @classmethod - def clean_cache_for_db(cls, dbname): - def get_dbname_from_key(key): - for e in key: - if e[0] == 'dbname': - return e[1] - return None + + def _generate_keys(self, dbname, kwargs2): + """ + Generate keys depending of the arguments and the self.mutli value + """ + + def to_tuple(d): + i = d.items() + i.sort() + return tuple(i) - for cache in cls.__caches: - keys_to_del = [key for key in cache.cache if get_dbname_from_key(key) == dbname] - for key in keys_to_del: - del cache.cache[key] + if not self.multi: + key = (('dbname', dbname),) + to_tuple(kwargs2) + yield key, None + else: + multis = kwargs2[self.multi][:] + for id in multis: + kwargs2[self.multi] = [id] + key = (('dbname', dbname),) + to_tuple(kwargs2) + yield key, id + + def _unify_args(self, *args, **kwargs): + # Update named arguments with positional argument values (without self and cr) + kwargs2 = self.fun_default_values.copy() + kwargs2.update(kwargs) + kwargs2.update(dict(zip(self.fun_arg_names, args[self.skiparg-2:]))) + for k in kwargs2: + if isinstance(kwargs2[k], (list, dict, set)): + kwargs2[k] = tuple(kwargs2[k]) + elif not is_hashable(kwargs2[k]): + kwargs2[k] = repr(kwargs2[k]) + + return kwargs2 + + def clear(self, dbname, *args, **kwargs): + """clear the cache for database dbname + if *args and **kwargs are both empty, clear all the keys related to this database + """ + if not args and not kwargs: + keys_to_del = [key for key in self.cache if key[0][1] == dbname] + else: + kwargs2 = self._unify_args(*args, **kwargs) + keys_to_del = [key for key, _ in self._generate_keys(dbname, kwargs2) if key in self.cache] + + for key in keys_to_del: + del self.cache[key] + + @classmethod + def clean_caches_for_db(cls, dbname): + for c in cls.__caches: + c.clear(dbname) def __call__(self, fn): - arg_names = inspect.getargspec(fn)[0][self.skiparg:] + if self.fun is not None: + raise Exception("Can not use a cache instance on more than one function") + self.fun = fn - def cached_result(self2, cr=None, *args, **kwargs): + argspec = inspect.getargspec(fn) + self.fun_arg_names = argspec[0][self.skiparg:] + self.fun_default_values = {} + if argspec[3]: + self.fun_default_values = dict(zip(self.fun_arg_names[-len(argspec[3]):], argspec[3])) + debug(self.fun_default_values) + + def cached_result(self2, cr, *args, **kwargs): if time.time()-self.timeout > self.lasttime: self.lasttime = time.time() t = time.time()-self.timeout @@ -576,64 +624,36 @@ class cache(object): if self.cache[key][1]