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.
Showing
Please register or sign in to comment