[Zodb-checkins] CVS: ZODB3/ZEO - ClientStorage.py:1.73.2.23.2.3
Jeremy Hylton
jeremy at zope.com
Wed Jun 11 13:03:31 EDT 2003
Update of /cvs-repository/ZODB3/ZEO
In directory cvs.zope.org:/tmp/cvs-serv10860
Modified Files:
Tag: tim-loading_oids_status-branch
ClientStorage.py
Log Message:
Fix race condition in handling of invalidations.
Guarantee that an invalidation can't arrive between the status check
and the call _cache.store().
Refactor: move inc/dec status code into helper methods.
=== ZODB3/ZEO/ClientStorage.py 1.73.2.23.2.2 => 1.73.2.23.2.3 ===
--- ZODB3/ZEO/ClientStorage.py:1.73.2.23.2.2 Tue Jun 10 23:19:44 2003
+++ ZODB3/ZEO/ClientStorage.py Wed Jun 11 12:03:30 2003
@@ -628,7 +628,44 @@
if self._server is None:
raise ClientDisconnected()
- # XXX Race condition among load / invalid / store in cache
+ self._incLoadStatus(oid, version)
+
+ try:
+ p, s, v, pv, sv = self._server.zeoLoad(oid)
+ except:
+ self._lock.acquire()
+ try:
+ self._decLoadStatus(oid, version)
+ finally:
+ self._lock.release()
+ raise
+
+ self._lock.acquire()
+ try:
+ statv, statnv = self._decLoadStatus(oid, version)
+ if statv and statnv:
+ self._cache.checkSize(0)
+ self._cache.store(oid, p, s, v, pv, sv)
+ else:
+ if not statv:
+ self._cache.invalidate(oid, version)
+ if not statnv:
+ self._cache.invalidate(oid, '')
+ finally:
+ self._lock.release()
+
+ if v and version and v == version:
+ return pv, sv
+ else:
+ if s:
+ return p, s
+ raise KeyError, oid # no non-version data for this
+
+ def _incLoadStatus(self, oid, version):
+ """Increment the load count for oid, version pair.
+
+ Does its own locking.
+ """
pairs = (oid, version), (oid, "")
self._lock.acquire()
try:
@@ -643,38 +680,26 @@
finally:
self._lock.release()
- try:
- p, s, v, pv, sv = self._server.zeoLoad(oid)
- finally:
- statii = [] # will be pair [version status, non-version status]
- self._lock.acquire()
- try:
- for pair in pairs:
- count, status = self._loading_oids_status[pair]
- statii.append(status)
- count -= 1
- if count:
- self._loading_oids_status[pair] = count, status
- else:
- del self._loading_oids_status[pair]
- finally:
- self._lock.release()
-
- if statii[0] and statii[1]: # both OK
- self._cache.checkSize(0)
- self._cache.store(oid, p, s, v, pv, sv)
- else:
- if not statii[0]:
- self._cache.invalidate(oid, version)
- if not statii[1]:
- self._cache.invalidate(oid, '')
+ def _decLoadStatus(self, oid, version):
+ """Decrement load count and return statii.
- if v and version and v == version:
- return pv, sv
- else:
- if s:
- return p, s
- raise KeyError, oid # no non-version data for this
+ Statii is a 2-element list of booleans indicating whether
+ the object, version was invalidated during the load. The
+ first element is oid, version; the second element is oid, "".
+
+ Caller must hold self._lock.
+ """
+ statii = []
+ pairs = (oid, version), (oid, "")
+ for pair in pairs:
+ count, status = self._loading_oids_status[pair]
+ statii.append(status)
+ count -= 1
+ if count:
+ self._loading_oids_status[pair] = count, status
+ else:
+ del self._loading_oids_status[pair]
+ return statii
def modifiedInVersion(self, oid):
"""Storage API: return the version, if any, that modfied an object.
More information about the Zodb-checkins
mailing list