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