From 7824385376cc0a0058a04cac0874319583f39799 Mon Sep 17 00:00:00 2001 From: Jim Fulton Date: Thu, 30 Jun 2016 17:01:46 -0400 Subject: [PATCH] Define a new interface for storages that support the new commit protocol. This allows interface incompatibilities: - Future version of ZODB that requires the new protocol being configured with a storage that doesn't implement the new protocol - ZEO has a client that uses the old protocol can't use a storage that implements the new protocol. To be caught early. This commit also clarifies that the serial returned by ``undo()`` is ignored. --- src/ZODB/interfaces.py | 90 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/src/ZODB/interfaces.py b/src/ZODB/interfaces.py index 716cb0f99..7f6364af7 100644 --- a/src/ZODB/interfaces.py +++ b/src/ZODB/interfaces.py @@ -811,6 +811,92 @@ def tpc_vote(transaction): either from tpc_vote or store for objects passed to store. """ +class IMultiCommitStorage(IStorage): + """A multi-commit storage can commit multiple transactions at once. + + It's lilely that future versions of ZODB will require all storages + to provide this interface. + """ + + def store(oid, serial, data, version, transaction): + """Store data for the object id, oid. + + Arguments: + + oid + The object identifier. This is either a string + consisting of 8 nulls or a string previously returned by + new_oid. + + serial + The serial of the data that was read when the object was + loaded from the database. If the object was created in + the current transaction this will be a string consisting + of 8 nulls. + + data + The data record. This is opaque to the storage. + + version + This must be an empty string. It exists for backward compatibility. + + transaction + A transaction object. This should match the current + transaction for the storage, set by tpc_begin. + + None is returned. + + Several different exceptions may be raised when an error occurs. + + ConflictError + is raised when serial does not match the most recent serial + number for object oid and the conflict was not resolved by + the storage. + + StorageTransactionError + is raised when transaction does not match the current + transaction. + + StorageError or, more often, a subclass of it + is raised when an internal error occurs while the storage is + handling the store() call. + + """ + + def tpc_finish(transaction, func = lambda tid: None): + """Finish the transaction, making any transaction changes permanent. + + Changes must be made permanent at this point. + + This call raises a StorageTransactionError if the storage + isn't participating in two-phase commit. Failure of this + method is extremely serious. + + The second argument is a call-back function that must be + called while the storage transaction lock is held. It takes + the new transaction id generated by the transaction. + + The return value must be the committed tid. It is used to set the + serial for objects whose ids were passed to previous store calls + in the same transaction. + """ + + def tpc_vote(transaction): + """Provide a storage with an opportunity to veto a transaction + + This call raises a StorageTransactionError if the storage + isn't participating in two-phase commit or if it is commiting + a different transaction. + + If a transaction can be committed by a storage, then the + method should return. If a transaction cannot be committed, + then an exception should be raised. If this method returns + without an error, then there must not be an error if + tpc_finish or tpc_abort is called subsequently. + + The return value can be either None or a sequence of oids for which + a conflict was resolved. + """ class IStorageRestoreable(IStorage): """Copying Transactions @@ -948,8 +1034,8 @@ def undo(transaction_id, transaction): This method must only be called in the first phase of two-phase commit (after tpc_begin but before tpc_vote). It returns a serial (transaction id) and a sequence of object ids - for objects affected by the transaction. - + for objects affected by the transaction. The serial is ignored + and may be None. """ # Used by DB (Actually, by TransactionalUndo)