Commit a6980f6d authored by Guido van Rossum's avatar Guido van Rossum

Added subclassing hooks to ClientStorage and StorageServer

It is now easy to provide a subclass of a class that is
instantiated, by setting the corresponding hook class
variable.  E.g. if you subclass ZEOStorage, you should also
subclass StorageServer and set StorageServer.ZEOStorageClass
to your ZEOStorage subclass.
parent 461e58f7
......@@ -20,7 +20,7 @@ ClientStorageError -- exception raised by ClientStorage
UnrecognizedResult -- exception raised by ClientStorage
ClientDisconnected -- exception raised by ClientStorage
$Id: ClientStorage.py,v 1.73 2002/10/01 21:12:12 gvanrossum Exp $
$Id: ClientStorage.py,v 1.74 2002/10/04 16:46:23 gvanrossum Exp $
"""
# XXX TO DO
......@@ -98,6 +98,13 @@ class ClientStorage:
tpc_begin().
"""
# Classes we instantiate. A subclass might override.
TransactionBufferClass = TransactionBuffer
ClientCacheClass = ClientCache.ClientCache
ConnectionManagerClass = ConnectionManager
StorageServerStubClass = ServerStub.StorageServer
def __init__(self, addr, storage='1', cache_size=20000000,
name='', client=None, debug=0, var=None,
min_disconnect_poll=5, max_disconnect_poll=300,
......@@ -202,7 +209,7 @@ class ClientStorage:
'supportsUndo':0, 'supportsVersions': 0,
'supportsTransactionalUndo': 0}
self._tbuf = TransactionBuffer()
self._tbuf = self.TransactionBufferClass()
self._db = None
# _serials: stores (oid, serialno) as returned by server
......@@ -235,12 +242,12 @@ class ClientStorage:
# Decide whether to use non-temporary files
client = client or os.environ.get('ZEO_CLIENT')
self._cache = ClientCache.ClientCache(storage, cache_size,
client=client, var=var)
self._cache = self.ClientCacheClass(storage, cache_size,
client=client, var=var)
self._rpc_mgr = ConnectionManager(addr, self,
tmin=min_disconnect_poll,
tmax=max_disconnect_poll)
self._rpc_mgr = self.ConnectionManagerClass(addr, self,
tmin=min_disconnect_poll,
tmax=max_disconnect_poll)
if wait:
self._rpc_mgr.connect(sync=1)
......@@ -311,7 +318,7 @@ class ClientStorage:
"""
log2(INFO, "Testing connection %r" % conn)
# XXX Check the protocol version here?
stub = ServerStub.StorageServer(conn)
stub = self.StorageServerStubClass(conn)
try:
stub.register(str(self._storage), self._is_read_only)
return 1
......@@ -332,7 +339,7 @@ class ClientStorage:
log2(INFO, "Reconnected to storage")
else:
log2(INFO, "Connected to storage")
stub = ServerStub.StorageServer(conn)
stub = self.StorageServerStubClass(conn)
self._oids = []
self._info.update(stub.get_info())
self.verify_cache(stub)
......
......@@ -61,6 +61,12 @@ class StorageServer:
ZEOStorage instance only handles a single storage.
"""
# Classes we instantiate. A subclass might override.
DispatcherClass = Dispatcher
ZEOStorageClass = None # patched up later
ManagedServerConnectionClass = ManagedServerConnection
def __init__(self, addr, storages, read_only=0):
"""StorageServer constructor.
......@@ -103,8 +109,9 @@ class StorageServer:
s._waiting = []
self.read_only = read_only
self.connections = {}
self.dispatcher = Dispatcher(addr, factory=self.new_connection,
reuse_addr=1)
self.dispatcher = self.DispatcherClass(addr,
factory=self.new_connection,
reuse_addr=1)
def new_connection(self, sock, addr):
"""Internal: factory to create a new connection.
......@@ -113,8 +120,8 @@ class StorageServer:
whenever accept() returns a socket for a new incoming
connection.
"""
z = ZEOStorage(self, self.read_only)
c = ManagedServerConnection(sock, addr, z, self)
z = self.ZEOStorageClass(self, self.read_only)
c = self.ManagedServerConnectionClass(sock, addr, z, self)
log("new connection %s: %s" % (addr, `c`))
return c
......@@ -190,6 +197,12 @@ class StorageServer:
class ZEOStorage:
"""Proxy to underlying storage for a single remote client."""
# Classes we instantiate. A subclass might override.
ClientStorageStubClass = ClientStub.ClientStorage
DelayedCommitStrategyClass = None # patched up later
ImmediateCommitStrategyClass = None # patched up later
def __init__(self, server, read_only=0):
self.server = server
self.client = None
......@@ -199,7 +212,7 @@ class ZEOStorage:
self.read_only = read_only
def notifyConnected(self, conn):
self.client = ClientStub.ClientStorage(conn)
self.client = self.ClientStorageStubClass(conn)
def notifyDisconnected(self):
# When this storage closes, we must ensure that it aborts
......@@ -378,11 +391,11 @@ class ZEOStorage:
# (This doesn't require a lock because we're using asyncore)
if self.storage._transaction is None:
self.strategy = ImmediateCommitStrategy(self.storage,
self.client)
self.strategy = self.ImmediateCommitStrategyClass(self.storage,
self.client)
else:
self.strategy = DelayedCommitStrategy(self.storage,
self.wait)
self.strategy = self.DelayedCommitStrategyClass(self.storage,
self.wait)
t = Transaction()
t.id = id
......@@ -723,3 +736,8 @@ class SlowMethodThread(threading.Thread):
self.delay.error(sys.exc_info())
else:
self.delay.reply(result)
# Patch up class references
StorageServer.ZEOStorageClass = ZEOStorage
ZEOStorage.DelayedCommitStrategyClass = DelayedCommitStrategy
ZEOStorage.ImmediateCommitStrategyClass = ImmediateCommitStrategy
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