[Zodb-checkins] CVS: Packages/ZEO - zrpc.py:1.13
Jim Fulton
jim@digicool.com
Tue, 27 Mar 2001 18:43:33 -0500 (EST)
Update of /cvs-repository/Packages/ZEO
In directory korak:/tmp/cvs-serv13952
Modified Files:
zrpc.py
Log Message:
It is no longer necessary to symbolically link cPickle or
ZServer. ZServer is no longer necessary at all.
Fixed a race condition in __call__.
If an exception raised on the server which could not be
unpickled on the client could cause the client connection to
fail.
--- Updated File zrpc.py in package Packages/ZEO --
--- zrpc.py 2001/02/23 17:57:50 1.12
+++ zrpc.py 2001/03/27 23:43:32 1.13
@@ -87,8 +87,8 @@
__version__ = "$Revision$"[11:-2]
-from ZODB.cPickle import loads
-from ZODB import cPickle
+from cPickle import loads
+import cPickle
from thread import allocate_lock
from smac import SizedMessageAsyncConnection
import socket, string, struct, asyncore, sys, time, select
@@ -102,6 +102,9 @@
pickler.fast=1 # Don't use the memo
dump=pickler.dump
+class UnUnPickleableError(Exception):
+ "Couldn't unpickle a remote exception"
+
class asyncRPC(SizedMessageAsyncConnection):
__map=0
@@ -119,6 +122,10 @@
self.__r=None
l.acquire()
+ l=allocate_lock() # Response lock used to wait for call results
+ self.__call_la=l.acquire
+ self.__call_lr=l.release
+
def connect(self, tryonce=1, log_type='client'):
t=self._tmin
connection = self._connection
@@ -152,7 +159,7 @@
return 1
def finishConnect(self, s):
- SizedMessageAsyncConnection.__init__(self, s, s.getpeername(), {})
+ SizedMessageAsyncConnection.__init__(self, s, '', {})
# we are our own socket map!
def keys(self): return (self._fileno,)
@@ -190,30 +197,37 @@
def __call__(self, *args):
- args=dump(args,1)
- self.message_output(args)
-
- if self.__map: self.__Wakeup() # You dumb bastard
- else: self.readLoop()
-
- while 1:
- r=self._read()
- c=r[:1]
- if c=='R':
- if r=='RN.': return None # Common case!
- return loads(r[1:])
- if c=='E':
- r=loads(r[1:])
- if type(r) is TupleType: raise r[0], r[1]
- raise r
- oob=self._outOfBand
- if oob is not None:
- r=r[1:]
- if r=='N.': r=None # Common case!
- else: r=loads(r)
- oob(c, r)
- else:
- raise UnrecognizedResult, r
+ self.__call_la()
+ try:
+ self._last_args=args=dump(args,1)
+ self.message_output(args)
+
+ if self.__map: self.__Wakeup() # You dumb bastard
+ else: self.readLoop()
+
+ while 1:
+ r=self._read()
+ c=r[:1]
+ if c=='R':
+ if r=='RN.': return None # Common case!
+ return loads(r[1:])
+ if c=='E':
+ try: r=loads(r[1:])
+ except:
+ raise UnUnPickleableError(r[1:])
+ if type(r) is TupleType: raise r[0], r[1]
+ raise r
+ oob=self._outOfBand
+ if oob is not None:
+ r=r[1:]
+ if r=='N.': r=None # Common case!
+ else: r=loads(r)
+ oob(c, r)
+ else:
+ raise UnrecognizedResult, r
+ finally:
+ self._last_args=''
+ self.__call_lr()
def sendMessage(self, *args):
self.message_output(dump(args,1))