Commit ec031cdf authored by Julien Muchembled's avatar Julien Muchembled

client: fix simultaneous (re)connections to the master

This fixes a reqression in commit c39d5c67,
which could leads to failures like:

2016-11-29 09:56:58,756 ERROR ZODB.Connection Couldn't load state for 0x4843
Traceback (most recent call last):
  File "ZODB/Connection.py", line 860, in setstate
    self._setstate(obj)
  File "ZODB/Connection.py", line 901, in _setstate
    p, serial = self._storage.load(obj._p_oid, '')
  File "neo/client/Storage.py", line 82, in load
    return self.app.load(oid)[:2]
  File "neo/client/app.py", line 352, in load
    data, tid, next_tid, _ = self._loadFromStorage(oid, tid, before_tid)
  File "neo/client/app.py", line 372, in _loadFromStorage
    for node, conn in self.cp.iterateForObject(oid, readable=True):
  File "neo/client/pool.py", line 91, in iterateForObject
    pt = self.app.pt
  File "neo/client/app.py", line 146, in __getattr__
    return self.__getattribute__(attr)
AttributeError: 'Application' object has no attribute 'pt'
parent 15472c62
...@@ -138,11 +138,11 @@ class Application(ThreadedApplication): ...@@ -138,11 +138,11 @@ class Application(ThreadedApplication):
def __getattr__(self, attr): def __getattr__(self, attr):
if attr in ('last_tid', 'pt'): if attr in ('last_tid', 'pt'):
if self._connecting_to_master_node.locked(): self._getMasterConnection()
if attr == 'last_tid': # XXX: There's still a risk that we get disconnected from the
return # master at this precise moment and for 'pt', we'd raise
else: # AttributeError. Should we catch it and loop until it
self._getMasterConnection() # succeeds?
return self.__getattribute__(attr) return self.__getattribute__(attr)
def log(self): def log(self):
......
...@@ -94,13 +94,14 @@ class PrimaryNotificationsHandler(MTEventHandler): ...@@ -94,13 +94,14 @@ class PrimaryNotificationsHandler(MTEventHandler):
def answerLastTransaction(self, conn, ltid): def answerLastTransaction(self, conn, ltid):
app = self.app app = self.app
if app.last_tid != ltid: app_last_tid = app.__dict__.get('last_tid', '')
if app_last_tid != ltid:
# Either we're connecting or we already know the last tid # Either we're connecting or we already know the last tid
# via invalidations. # via invalidations.
assert app.master_conn is None, app.master_conn assert app.master_conn is None, app.master_conn
app._cache_lock_acquire() app._cache_lock_acquire()
try: try:
if app.last_tid < ltid: if app_last_tid < ltid:
app._cache.clear_current() app._cache.clear_current()
# In the past, we tried not to invalidate the # In the past, we tried not to invalidate the
# Connection caches entirely, using the list of # Connection caches entirely, using the list of
......
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