[Zodb-checkins] CVS: StandaloneZODB/ZEO - zrpc2.py:1.3.2.3
Jeremy Hylton
jeremy@zope.com
Tue, 15 Jan 2002 17:38:41 -0500
Update of /cvs-repository/StandaloneZODB/ZEO
In directory cvs.zope.org:/tmp/cvs-serv12065
Modified Files:
Tag: Standby-branch
zrpc2.py
Log Message:
Rework the is_async() logic to actually work in cases where it is true.
Implement the various classes that care using thr_async variable -- to
avoid confusion with other async things like
SizedMessageAsyncConnection and asynchronous messages.
As a comment in the Connection constructor explains:
# A Connection either uses asyncore directly or relies on an
# asyncore mainloop running in a separate thread. If
# thr_async is true, then the mainloop is running in a
# separate thread. If thr_async is true, then the asyncore
# trigger (self.trigger) is used to notify that thread of
# activity on the current thread.
Make sure that ManagedConnection sets thr_async and trigger properly,
based on the ConnectionManager.
=== StandaloneZODB/ZEO/zrpc2.py 1.3.2.2 => 1.3.2.3 ===
def __init__(self, sock, addr, obj=None):
- self.msgid = 0
self.obj = obj
self.marshal = Marshaller()
self.closed = 0
- self.async = 0
- self.trigger = None
- # The reply lock is used to block when a synchronous call is
- # waiting for a response
+ self.msgid = 0
self.__super_init(sock, addr)
- self._map = {self._fileno: self}
+ # A Connection either uses asyncore directly or relies on an
+ # asyncore mainloop running in a separate thread. If
+ # thr_async is true, then the mainloop is running in a
+ # separate thread. If thr_async is true, then the asyncore
+ # trigger (self.trigger) is used to notify that thread of
+ # activity on the current thread.
+ self.thr_async = 0
+ self.trigger = None
self._prepare_async()
+ self._map = {self._fileno: self}
self.__call_lock = thread.allocate_lock()
+ # The reply lock is used to block when a synchronous call is
+ # waiting for a response
self.__reply_lock = thread.allocate_lock()
self.__reply_lock.acquire()
+ # If the object implements the Handler interface (XXX checked
+ # by isinstance), it wants to know who the caller is.
if isinstance(obj, Handler):
self.set_caller = 1
else:
self.set_caller = 0
def __repr__(self):
- return "<%s %s>" % (self.__class__.__name__, self.addr)
+ return "<%s %s %s>" % (self.__class__.__name__, self.addr,
+ hex(id(self)))
def close(self):
if self.closed:
@@ -338,7 +347,7 @@
pass # XXX what is this supposed to do?
def _prepare_async(self):
- self._async = 0
+ self.thr_async = 0
ThreadedAsync.register_loop_callback(self.set_async)
# XXX If we are not in async mode, this will cause dead
# Connections to be leaked.
@@ -346,18 +355,21 @@
def set_async(self, map):
# XXX do we need a lock around this? I'm not sure there is
# any harm to a race with _do_io().
- self._async = 1
self.trigger = trigger.trigger()
+ self.thr_async = 1
def is_async(self):
- return self._async
+ if self.thr_async:
+ return 1
+ else:
+ return 0
def _do_io(self, wait=0): # XXX need better name
# XXX invariant? lock must be held when calling with wait==1
# otherwise, in non-async mode, there will be no poll
if __debug__:
- log("_do_io(wait=%d), async=%d" % (wait, self.is_async()),
+ log("_do_io(wait=%d), async=%s" % (wait, self.is_async()),
level=zLOG.DEBUG)
if self.is_async():
self.trigger.pull_trigger()
@@ -406,7 +418,7 @@
self._thread = None
self._connect_lock = threading.Lock()
self.trigger = None
- self.async = 0
+ self.thr_async = 0
self.closed = 0
ThreadedAsync.register_loop_callback(self.set_async)
@@ -464,8 +476,8 @@
def set_async(self, map):
# XXX need each connection started with async==0 to have a callback
- self.async = 1 # XXX needs to be set on the Connection
self.trigger = trigger.trigger()
+ self.thr_async = 1 # XXX needs to be set on the Connection
def connect(self, sync=0):
if self.connected == 1:
@@ -594,7 +606,9 @@
self.connection = c
return 1
except:
- # XXX zLOG the error
+ zLOG.LOG(_label, zLOG.ERROR,
+ "error connecting to server: %s" % str(addr),
+ error=sys.exc_info())
c.close()
return 0
@@ -622,29 +636,30 @@
def __init__(self, sock, addr, obj, mgr):
self.__mgr = mgr
- if self.__mgr.async:
- self.__async = 1
- self.trigger = self.__mgr.trigger
- else:
- self.__async = None
self.__super_init(sock, addr, obj)
+ self.check_mgr_async()
def close_trigger(self):
# the manager should actually close the trigger
del self.trigger
def _prepare_async(self):
- # Don't do the register_loop_callback that the superclass does
+ # Don't do the register_loop_callback; the manager handles it
pass
+ def check_mgr_async(self):
+ if not self.thr_async and self.__mgr.thr_async:
+ assert self.__mgr.trigger is not None, \
+ "manager (%s) has no trigger" % self.__mgr
+ self.thr_async = 1
+ self.trigger = self.__mgr.trigger
+ return 1
+ return 0
+
def is_async(self):
- if self.__async:
+ if self.thr_async:
return 1
- async = self.__mgr.async
- if async:
- self.__async = 1
- self.trigger = self.__mgr.trigger
- return async
+ return self.check_mgr_async()
def close(self):
self.__super_close()
@@ -726,4 +741,3 @@
return r
raise ZRPCError("Unsafe global: %s.%s" % (module, name))
-