Commit 623ccca8 authored by Chris McDonough's avatar Chris McDonough

Merge from 2.7 branch:

Do logging only if Z_TOC_DEBUG environment variable is set.

Raise ConflictError from _p_resolveConflict instead of returning None if
conflict cannot be resolved.  I think someone changed the contract of
this method but the code hasn't caught up til now.
parent 090df24a
...@@ -16,23 +16,33 @@ Simple ZODB-based transient object implementation. ...@@ -16,23 +16,33 @@ Simple ZODB-based transient object implementation.
$Id$ $Id$
""" """
__version__='$Revision: 1.9 $'[11:-2]
from Persistence import Persistent from Persistence import Persistent
from Acquisition import Implicit from Acquisition import Implicit
import time, random, sys import time, random, sys, os
from TransienceInterfaces import ItemWithId, Transient, DictionaryLike,\ import thread
TTWDictionary, ImmutablyValuedMappingOfPickleableObjects,\ from Products.Transience.TransienceInterfaces import ItemWithId, Transient, \
DictionaryLike, TTWDictionary, ImmutablyValuedMappingOfPickleableObjects,\
TransientItemContainer TransientItemContainer
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
import Globals import Globals
import sys
import logging import logging
from ZODB.POSException import ConflictError
DEBUG = int(os.environ.get('Z_TOC_DEBUG', 0))
LOG = logging.getLogger('Zope.Transience')
def TLOG(*args):
sargs = []
sargs.append(str(thread.get_ident()))
sargs.append(str(time.time()))
for arg in args:
sargs.append(str(arg))
msg = ' '.join(sargs)
LOG.info(msg)
_notfound = [] _notfound = []
WRITEGRANULARITY=30 # Timing granularity for access write clustering, seconds WRITEGRANULARITY=30 # Timing granularity for access write clustering, seconds
LOG = logging.getLogger('Zope.Transience')
class TransientObject(Persistent, Implicit): class TransientObject(Persistent, Implicit):
""" Dictionary-like object that supports additional methods """ Dictionary-like object that supports additional methods
...@@ -151,19 +161,6 @@ class TransientObject(Persistent, Implicit): ...@@ -151,19 +161,6 @@ class TransientObject(Persistent, Implicit):
# #
def __setitem__(self, k, v): def __setitem__(self, k, v):
# if the key or value is a persistent instance,
# set up its _p_jar immediately
# XXX
# not sure why the below was here, so I'm taking it out
# because it apparently causes problems when a
# transaction is aborted (the connection attempts to
# invalidate an oid of None in "abort")
## if hasattr(v, '_p_jar') and v._p_jar is None:
## v._p_jar = self._p_jar
## v._p_changed = 1
## if hasattr(k, '_p_jar') and k._p_jar is None:
## k._p_jar = self._p_jar
## k._p_changed = 1
self._container[k] = v self._container[k] = v
self.setLastModified() self.setLastModified()
...@@ -193,7 +190,9 @@ class TransientObject(Persistent, Implicit): ...@@ -193,7 +190,9 @@ class TransientObject(Persistent, Implicit):
return 1 return 1
def _p_resolveConflict(self, saved, state1, state2): def _p_resolveConflict(self, saved, state1, state2):
LOG.debug('Resolving conflict in TransientObject') DEBUG and TLOG('entering TO _p_rc')
DEBUG and TLOG('states: sv: %s, s1: %s, s2: %s' % (
saved, state1, state2))
try: try:
states = [saved, state1, state2] states = [saved, state1, state2]
...@@ -201,18 +200,22 @@ class TransientObject(Persistent, Implicit): ...@@ -201,18 +200,22 @@ class TransientObject(Persistent, Implicit):
# because it's a terminal state. # because it's a terminal state.
for state in states: for state in states:
if state.has_key('_invalid'): if state.has_key('_invalid'):
LOG.debug('a state was invalid') DEBUG and TLOG('TO _p_rc: a state was invalid')
return state return state
# The only other times we can clearly resolve the conflict is if # The only other times we can clearly resolve the conflict is if
# the token, the id, or the creation time don't differ between # the token, the id, or the creation time don't differ between
# the three states, so we check that here. If any differ, we punt # the three states, so we check that here. If any differ, we punt
# by returning None. Returning None indicates that we can't # by raising ConflictError.
# resolve the conflict.
attrs = ['token', 'id', '_created'] attrs = ['token', 'id', '_created']
for attr in attrs: for attr in attrs:
if not (saved.get(attr)==state1.get(attr)==state2.get(attr)): svattr = saved.get(attr)
LOG.debug('cant resolve conflict') s1attr = state1.get(attr)
return None s2attr = state2.get(attr)
DEBUG and TLOG('TO _p_rc: attr %s: sv: %s s1: %s s2: %s' %
(attr, svattr, s1attr, s2attr))
if not svattr==s1attr==s2attr:
DEBUG and TLOG('TO _p_rc: cant resolve conflict')
raise ConflictError
# Now we need to do real work. # Now we need to do real work.
# #
...@@ -228,7 +231,7 @@ class TransientObject(Persistent, Implicit): ...@@ -228,7 +231,7 @@ class TransientObject(Persistent, Implicit):
# possible. # possible.
states.sort(lastmodified_sort) states.sort(lastmodified_sort)
if states[0].get('_last_modified'): if states[0].get('_last_modified'):
LOG.debug('returning last mod state') DEBUG and TLOG('TO _p_rc: returning last mod state')
return states[0] return states[0]
# If we can't determine which object to return on the basis # If we can't determine which object to return on the basis
...@@ -237,7 +240,7 @@ class TransientObject(Persistent, Implicit): ...@@ -237,7 +240,7 @@ class TransientObject(Persistent, Implicit):
# our parent). This will return an essentially arbitrary state if # our parent). This will return an essentially arbitrary state if
# all last_accessed values are equal. # all last_accessed values are equal.
states.sort(lastaccessed_sort) states.sort(lastaccessed_sort)
LOG.debug('returning last_accessed state') DEBUG and TLOG('TO _p_rc: returning last_accessed state')
return states[0] return states[0]
except: except:
LOG.info('Conflict resolution error in TransientObject', LOG.info('Conflict resolution error in TransientObject',
......
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