Commit 5eef8d63 authored by Julien Muchembled's avatar Julien Muchembled

client: no need to create a NEOStorage instance for each ZODB connection

If any object is modified after the start of a transaction, the snapshot
TID of the NEOStorage is ignored because ZODB will use the TID of the first
received invalidation.
parent bce3bc78
...@@ -20,6 +20,7 @@ import ZODB.interfaces ...@@ -20,6 +20,7 @@ import ZODB.interfaces
from functools import wraps from functools import wraps
from neo.lib import logging from neo.lib import logging
from neo.lib.locking import Lock
from neo.lib.util import add64 from neo.lib.util import add64
from neo.lib.protocol import ZERO_TID from neo.lib.protocol import ZERO_TID
from .app import Application from .app import Application
...@@ -87,6 +88,17 @@ class Storage(BaseStorage.BaseStorage, ...@@ -87,6 +88,17 @@ class Storage(BaseStorage.BaseStorage,
'dynamic_master_list': dynamic_master_list, 'dynamic_master_list': dynamic_master_list,
'_app': _app, '_app': _app,
} }
snapshot_lock = Lock()
acquire = snapshot_lock.acquire
release = snapshot_lock.release
def _setSnapshotTid(tid):
acquire()
try:
if self._snapshot_tid <= tid:
self._snapshot_tid = add64(tid, 1)
finally:
release()
self._setSnapshotTid = _setSnapshotTid
@property @property
def _cache(self): def _cache(self):
...@@ -137,7 +149,7 @@ class Storage(BaseStorage.BaseStorage, ...@@ -137,7 +149,7 @@ class Storage(BaseStorage.BaseStorage,
# a temporary Storage object is used to commit. # a temporary Storage object is used to commit.
# See also testZODB.NEOZODBTests.checkMultipleUndoInOneTransaction # See also testZODB.NEOZODBTests.checkMultipleUndoInOneTransaction
if self._snapshot_tid: if self._snapshot_tid:
self._snapshot_tid = add64(tid, 1) self._setSnapshotTid(tid)
return tid return tid
@check_read_only @check_read_only
...@@ -221,7 +233,7 @@ class Storage(BaseStorage.BaseStorage, ...@@ -221,7 +233,7 @@ class Storage(BaseStorage.BaseStorage,
def sync(self, force=True): def sync(self, force=True):
# Increment by one, as we will use this as an excluded upper # Increment by one, as we will use this as an excluded upper
# bound (loadBefore). # bound (loadBefore).
self._snapshot_tid = add64(self.lastTransaction(), 1) self._setSnapshotTid(self.lastTransaction())
def copyTransactionsFrom(self, source, verbose=False): def copyTransactionsFrom(self, source, verbose=False):
""" Zope compliant API """ """ Zope compliant API """
......
...@@ -107,31 +107,3 @@ if 1: ...@@ -107,31 +107,3 @@ if 1:
pass pass
self._flush_invalidations() self._flush_invalidations()
#Connection.afterCompletion = afterCompletion #Connection.afterCompletion = afterCompletion
class _DB(object):
"""
Wrapper to DB instance that properly initialize Connection objects
with NEO storages.
It forces the connection to always create a new instance of the
storage, because we don't implement IMVCCStorage completely.
"""
def __new__(cls, db, connection):
if db._storage.__class__.__module__ != 'neo.client.Storage':
return db
self = object.__new__(cls)
self._db = db
self._connection = connection
return self
def __getattr__(self, attr):
result = getattr(self._db, attr)
if attr == 'storage':
self.storage = result = result.new_instance()
self._connection._db = self._db
return result
Connection_init = Connection.__init__
Connection.__init__ = lambda self, db, *args, **kw: \
Connection_init(self, _DB(db, self), *args, **kw)
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