[Zodb-checkins] CVS: ZODB3/ZEO - ClientStorage.py:1.65
Guido van Rossum
guido@python.org
Fri, 20 Sep 2002 13:38:05 -0400
Update of /cvs-repository/ZODB3/ZEO
In directory cvs.zope.org:/tmp/cvs-serv26301/ZEO
Modified Files:
ClientStorage.py
Log Message:
I set out making wait=1 work for fallback connections, i.e. the
ClientStorage constructor called with both wait=1 and
read_only_fallback=1 should return, indicating its readiness, when a
read-only connection was made. This is done by calling
connect(sync=1). Previously this waited for the ConnectThread to
finish, but that thread doesn't finish until it's made a read-write
connection, so a different mechanism is needed.
I ended up doing a major overhaul of the interfaces between
ClientStorage, ConnectionManager, ConnectThread/ConnectWrapper, and
even ManagedConnection. Changes:
ClientStorage.py:
ClientStorage:
- testConnection() now returns just the preferred flag; stubs are
cheap and I like to have the notifyConnected() signature be the
same for clients and servers.
- notifyConnected() now takes a connection (to match the signature
of this method in StorageServer), and creates a new stub. It also
takes care of the reconnect business if the client was already
connected, rather than the ClientManager. It stores the
connection as self._connection so it can close the previous one.
This is also reset by notifyDisconnected().
zrpc/client.py:
ConnectionManager:
- Changed self.thread_lock into a condition variable. It now also
protects self.connection. The condition is notified when
self.connection is set to a non-None value in connect_done();
connect(sync=1) waits for it. The self.connected variable is no
more; we test "self.connection is not None" instead.
- Tried to made close() reentrant. (There's a trick: you can't set
self.connection to None, conn.close() ends up calling close_conn()
which does this.)
- Renamed notify_closed() to close_conn(), for symmetry with the
StorageServer API.
- Added an is_connected() method so ConnectThread.try_connect()
doesn't have to dig inside the manager's guts to find out if the
manager is connected (important for the disposition of fallback
wrappers).
ConnectThread and ConnectWrapper:
- Follow above changes in the ClientStorage and ConnectionManager
APIs: don't close the manager's connection when reconnecting, but
leave that up to notifyConnected(); ConnectWrapper no longer
manages the stub.
- ConnectWrapper sets self.sock to None once it's created a
ManagedConnection -- from there on the connection is is charge of
closing the socket.
zrpc/connection.py:
ManagedServerConnection:
- Changed the order in which close() calls things; super_close()
should be last.
ManagedConnection:
- Ditto, and call the manager's close_conn() instead of
notify_closed().
tests/testZEO.py:
- In checkReconnectSwitch(), we can now open the client storage with
wait=1 and read_only_fallback=1.
=== ZODB3/ZEO/ClientStorage.py 1.64 => 1.65 ===
--- ZODB3/ZEO/ClientStorage.py:1.64 Fri Sep 20 09:35:07 2002
+++ ZODB3/ZEO/ClientStorage.py Fri Sep 20 13:37:34 2002
@@ -107,6 +107,7 @@
self._is_read_only = read_only
self._storage = storage
self._read_only_fallback = read_only_fallback
+ self._connection = None
self._info = {'length': 0, 'size': 0, 'name': 'ZEO Client',
'supportsUndo':0, 'supportsVersions': 0,
@@ -200,11 +201,9 @@
self._server._update()
def testConnection(self, conn):
- """Return a pair (stub, preferred).
+ """Test a connection.
- Where:
- - stub is an RPC stub
- - preferred is: 1 if the connection is an optimal match,
+ This returns: 1 if the connection is an optimal match,
0 if it is a suboptimal but acceptable match
It can also raise DisconnectedError or ReadOnlyError.
@@ -217,27 +216,33 @@
stub = ServerStub.StorageServer(conn)
try:
stub.register(str(self._storage), self._is_read_only)
- return (stub, 1)
+ return 1
except POSException.ReadOnlyError:
if not self._read_only_fallback:
raise
log2(INFO, "Got ReadOnlyError; trying again with read_only=1")
stub.register(str(self._storage), read_only=1)
- return (stub, 0)
+ return 0
- def notifyConnected(self, stub):
- """Start using the given RPC stub.
+ def notifyConnected(self, conn):
+ """Start using the given connection.
This is called by ConnectionManager after it has decided which
- connection should be used. The stub is one returned by a
- previous testConnection() call.
+ connection should be used.
"""
- log2(INFO, "Connected to storage")
+ if self._connection is not None:
+ log2(INFO, "Reconnected to storage")
+ else:
+ log2(INFO, "Connected to storage")
+ stub = ServerStub.StorageServer(conn)
self._oids = []
self._info.update(stub.get_info())
self.verify_cache(stub)
# XXX The stub should be saved here and set in endVerify() below.
+ if self._connection is not None:
+ self._connection.close()
+ self._connection = conn
self._server = stub
def verify_cache(self, server):
@@ -257,6 +262,7 @@
def notifyDisconnected(self):
log2(PROBLEM, "Disconnected from storage")
+ self._connection = None
self._server = disconnected_stub
def __len__(self):