| #ifndef QPID_BROKER_TXBUFFER_H |
| #define QPID_BROKER_TXBUFFER_H |
| |
| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| |
| #include "qpid/broker/BrokerImportExport.h" |
| #include "qpid/broker/TransactionalStore.h" |
| #include "qpid/broker/TxOp.h" |
| #include "qpid/broker/AsyncCompletion.h" |
| #include "qpid/sys/Mutex.h" |
| #include <algorithm> |
| #include <functional> |
| #include <vector> |
| |
| |
| namespace qpid { |
| namespace broker { |
| class TransactionObserver; |
| |
| /** |
| * Represents a single transaction. As such, an instance of this class |
| * will hold a list of operations representing the workload of the |
| * transaction. This work can be committed or rolled back. Committing |
| * is a two-stage process: first all the operations should be |
| * prepared, then if that succeeds they can be committed. |
| * |
| * In the 2pc case, a successful prepare may be followed by either a |
| * commit or a rollback. |
| * |
| * Atomicity of prepare is ensured by using a lower level |
| * transactional facility. This saves explicitly rolling back all the |
| * successfully prepared ops when one of them fails. i.e. we do not |
| * use 2pc internally, we instead ensure that prepare is atomic at a |
| * lower level. This makes individual prepare operations easier to |
| * code. |
| * |
| * Transactions on a messaging broker effect three types of 'action': |
| * (1) updates to persistent storage (2) updates to transient storage |
| * or cached data (3) network writes. |
| * |
| * Of these, (1) should always occur atomically during prepare to |
| * ensure that if the broker crashes while a transaction is being |
| * completed the persistent state (which is all that then remains) is |
| * consistent. (3) can only be done on commit, after a successful |
| * prepare. There is a little more flexibility with (2) but any |
| * changes made during prepare should be subject to the control of the |
| * TransactionalStore in use. |
| * |
| * TxBuffer inherits AsyncCompletion because transactions can be completed |
| * asynchronously if the broker is part of a HA cluster. |
| */ |
| class TxBuffer : public AsyncCompletion { |
| private: |
| typedef std::vector<TxOp::shared_ptr>::iterator op_iterator; |
| std::vector<TxOp::shared_ptr> ops; |
| boost::shared_ptr<TransactionObserver> observer; |
| std::auto_ptr<TransactionContext> txContext; |
| std::string error; |
| sys::Mutex errorLock; |
| |
| public: |
| QPID_BROKER_EXTERN TxBuffer(); |
| |
| /** |
| * Adds an operation to the transaction. |
| */ |
| QPID_BROKER_EXTERN void enlist(TxOp::shared_ptr op); |
| |
| /** |
| * Requests that all ops are prepared. This should |
| * primarily involve making sure that a persistent record |
| * of the operations is stored where necessary. |
| * |
| * Once prepared, a transaction can be committed (or in |
| * the 2pc case, rolled back). |
| * |
| * @returns true if all the operations prepared |
| * successfully, false if not. |
| */ |
| QPID_BROKER_EXTERN bool prepare(TransactionContext* const ctxt); |
| |
| /** |
| * Signals that the ops all prepared successfully and can |
| * now commit, i.e. the operation can now be fully carried |
| * out. |
| * |
| * Should only be called after a call to prepare() returns |
| * true. |
| */ |
| QPID_BROKER_EXTERN void commit(); |
| |
| /** |
| * Signals that all ops can be rolled back. |
| * |
| * Should only be called either after a call to prepare() |
| * returns true (2pc) or instead of a prepare call |
| * ('server-local') |
| */ |
| QPID_BROKER_EXTERN void rollback(); |
| |
| /** |
| * Start a local commit - may complete asynchronously. |
| */ |
| QPID_BROKER_EXTERN void startCommit(TransactionalStore* const store); |
| |
| /** End a commit, called via async completion. |
| *@return encoded result, not used here. |
| */ |
| QPID_BROKER_EXTERN std::string endCommit(TransactionalStore* const store); |
| |
| QPID_BROKER_EXTERN void setObserver(boost::shared_ptr<TransactionObserver> o) { |
| observer = o; |
| } |
| |
| QPID_BROKER_EXTERN boost::shared_ptr<TransactionObserver> getObserver() const { |
| return observer; |
| } |
| |
| /** Set an error to be raised from endCommit when the commit completes. |
| * Called from completer threads if we are doing async completion. |
| * This is the only TxBuffer function called outside the IO thread. |
| */ |
| QPID_BROKER_EXTERN void setError(const std::string& message); |
| }; |
| |
| }} // namespace qpid::broker |
| |
| |
| #endif /*!QPID_BROKER_TXBUFFER_H*/ |