From 9770caedf38a54b810225fb192fd81ec43cc41c5 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 1 Mar 2013 15:32:03 +0100 Subject: [PATCH] [FIX] registry: another pass of cleanup for registry signaling Some important points to consider: - signaling should be done after any schema alteration (including module [un]installation), service registration (e.g. reports) - the changes need to be committed to the database *before* signaling, otherwise an obvious race condition occurs during reload by other workers - any call to restart_pool() must be considered a possible candidate for signaling, and the 2 above conditions must be checked The number of explicit calls was reduced by forcing the signaling at the end of Registry.new() in case `update_module` was passed as True. In that situation we always want to signal the changes - so all the redundant signaling calls can be centralized. We can also assume that the relevant changes have already been committed at that point, otherwise the registry update would not have worked in the first place. This means that there is no need for explicit signaling anymore everytime `restart_pool` is called with `update_module=True`. Some missing cr.commit() and explicit signaling calls were added or moved to the right place. As a reminder: signaling must be done *after* committing the changes, and usually *after* reloading the registry on the current worker. bzr revid: odo@openerp.com-20130301143203-e2csf5pkllwhmwqs --- openerp/addons/base/ir/ir_model.py | 8 ++++++-- openerp/addons/base/module/module.py | 2 -- openerp/addons/base/res/res_config.py | 1 - openerp/modules/loading.py | 1 + openerp/modules/registry.py | 3 +++ 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/openerp/addons/base/ir/ir_model.py b/openerp/addons/base/ir/ir_model.py index 16916fc8561..70056383090 100644 --- a/openerp/addons/base/ir/ir_model.py +++ b/openerp/addons/base/ir/ir_model.py @@ -169,7 +169,9 @@ class ir_model(osv.osv): if not context.get(MODULE_UNINSTALL_FLAG): # only reload pool for normal unlink. For module uninstall the # reload is done independently in openerp.modules.loading + cr.commit() # must be committed before reloading registry in new cursor pooler.restart_pool(cr.dbname) + openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) return res @@ -307,7 +309,6 @@ class ir_model_fields(osv.osv): if column_name and (result and result[0] == 'r'): cr.execute('ALTER table "%s" DROP column "%s" cascade' % (model._table, field.name)) model._columns.pop(field.name, None) - openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) return True def unlink(self, cr, user, ids, context=None): @@ -321,6 +322,9 @@ class ir_model_fields(osv.osv): self._drop_column(cr, user, ids, context) res = super(ir_model_fields, self).unlink(cr, user, ids, context) + if not context.get(MODULE_UNINSTALL_FLAG): + cr.commit() + openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) return res def create(self, cr, user, vals, context=None): @@ -469,7 +473,7 @@ class ir_model_fields(osv.osv): for col_name, col_prop, val in patch_struct[1]: setattr(obj._columns[col_name], col_prop, val) obj._auto_init(cr, ctx) - openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) + openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) return res class ir_model_constraint(Model): diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index a0d1eedef2b..5dcb1693c67 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -411,7 +411,6 @@ class module(osv.osv): if to_install_ids: self.button_install(cr, uid, to_install_ids, context=context) - openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) return dict(ACTION_DICT, name=_('Install')) def button_immediate_install(self, cr, uid, ids, context=None): @@ -500,7 +499,6 @@ class module(osv.osv): raise orm.except_orm(_('Error'), _("The `base` module cannot be uninstalled")) dep_ids = self.downstream_dependencies(cr, uid, ids, context=context) self.write(cr, uid, ids + dep_ids, {'state': 'to remove'}) - openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) return dict(ACTION_DICT, name=_('Uninstall')) def button_uninstall_cancel(self, cr, uid, ids, context=None): diff --git a/openerp/addons/base/res/res_config.py b/openerp/addons/base/res/res_config.py index a2368a9f508..0508030242c 100644 --- a/openerp/addons/base/res/res_config.py +++ b/openerp/addons/base/res/res_config.py @@ -360,7 +360,6 @@ class res_config_installer(osv.osv_memory): modules.search(cr, uid, [('name','in',to_install)]), 'to install', ['uninstalled'], context=context) cr.commit() - openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) new_db, self.pool = pooler.restart_pool(cr.dbname, update_module=True) res_config_installer() diff --git a/openerp/modules/loading.py b/openerp/modules/loading.py index a7696c5fe18..e3c69e25b73 100644 --- a/openerp/modules/loading.py +++ b/openerp/modules/loading.py @@ -34,6 +34,7 @@ import openerp import openerp.modules.db import openerp.modules.graph import openerp.modules.migration +import openerp.modules.registry import openerp.osv as osv import openerp.pooler as pooler import openerp.tools as tools diff --git a/openerp/modules/registry.py b/openerp/modules/registry.py index b06c500a24c..7ca155b012f 100644 --- a/openerp/modules/registry.py +++ b/openerp/modules/registry.py @@ -232,6 +232,9 @@ class RegistryManager(object): registry.ready = True + if update_module: + # only in case of update, otherwise we'll have an infinite reload loop! + cls.signal_registry_change(db_name) return registry @classmethod