From afe47681178e4b2ee5524f7155d9a32e42d44e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 30 Nov 2008 23:35:02 +0100 Subject: [PATCH] Use one lock per database for issue627 --- CHANGELOG | 1 + trytond/pooler.py | 24 +++++++++++++++++++----- trytond/web_service/db.py | 6 +++++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6a091ea0d8..5fb3662828 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Use one lock per database * Improve netrpc communication speed * Add contextual domain on inherited views * Allow to use globals in domain and states diff --git a/trytond/pooler.py b/trytond/pooler.py index f5aeb2b977..54d1103c5a 100644 --- a/trytond/pooler.py +++ b/trytond/pooler.py @@ -5,6 +5,7 @@ import logging from threading import RLock _LOCK = RLock() +_LOCKS = {} _DB = {} _POOL = {} _POOL_WIZARD = {} @@ -15,6 +16,9 @@ def get_db_and_pool(db_name, update_module=False, wizard=False, report=False, restart = False _LOCK.acquire() + lock = _LOCKS.setdefault(db_name, RLock()) + _LOCK.release() + lock.acquire() try: if db_name in _DB: database = _DB[db_name] @@ -51,7 +55,7 @@ def get_db_and_pool(db_name, update_module=False, wizard=False, report=False, restart = not load_modules(database, pool, pool_wizard, pool_report, update_module, lang) finally: - _LOCK.release() + lock.release() if restart: restart_pool(db_name) @@ -63,16 +67,22 @@ def get_db_and_pool(db_name, update_module=False, wizard=False, report=False, def restart_pool(db_name, update_module=False, lang=None): _LOCK.acquire() + lock = _LOCKS.setdefault(db_name, RLock()) + _LOCK.release() + lock.acquire() try: del _POOL[db_name] del _POOL_WIZARD[db_name] del _POOL_REPORT[db_name] finally: - _LOCK.release() + lock.release() return get_db_and_pool(db_name, update_module=update_module, lang=lang) def close_db(db_name): _LOCK.acquire() + lock = _LOCKS.setdefault(db_name, RLock()) + _LOCK.release() + lock.acquire() try: if db_name in _DB: _DB[db_name].close() @@ -80,10 +90,14 @@ def close_db(db_name): if db_name in _POOL: del _POOL[db_name] finally: - _LOCK.release() + lock.release() -def get_db_only(db_name, verbose=True): +def get_db_only(db_name, verbose=True, blocking=True): _LOCK.acquire() + lock = _LOCKS.setdefault(db_name, RLock()) + _LOCK.release() + if not lock.acquire(blocking): + return None try: if db_name in _DB: database = _DB[db_name] @@ -94,7 +108,7 @@ def get_db_only(db_name, verbose=True): database = db_connect(db_name) _DB[db_name] = database finally: - _LOCK.release() + lock.release() return database def get_db(db_name): diff --git a/trytond/web_service/db.py b/trytond/web_service/db.py index cb077313cd..a708a14660 100644 --- a/trytond/web_service/db.py +++ b/trytond/web_service/db.py @@ -232,7 +232,11 @@ class DB(Service): "ORDER BY datname") res = [] for db_name, in cursor.fetchall(): - cursor2 = pooler.get_db_only(db_name, verbose=False).cursor() + database = pooler.get_db_only(db_name, verbose=False, + blocking=False) + if not database: + continue + cursor2 = database.cursor() if not cursor2.test(): cursor2.close() pooler.close_db(db_name)