Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

transactor.hxx

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/transactor.hxx
00005  *
00006  *   DESCRIPTION
00007  *      definition of the pqxx::transactor class.
00008  *   pqxx::transactor is a framework-style wrapper for safe transactions
00009  *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead.
00010  *
00011  * Copyright (c) 2001-2005, Jeroen T. Vermeulen <jtv@xs4all.nl>
00012  *
00013  * See COPYING for copyright license.  If you did not receive a file called
00014  * COPYING with this source code, please notify the distributor of this mistake,
00015  * or contact the author.
00016  *
00017  *-------------------------------------------------------------------------
00018  */
00019 #include "pqxx/libcompiler.h"
00020 
00021 #include "pqxx/connection_base"
00022 #include "pqxx/transaction"
00023 
00024 
00025 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
00026  */
00027 
00029 #define PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00030 
00031 namespace pqxx
00032 {
00033 
00035 
00064 template<typename TRANSACTION=transaction<read_committed> >
00065   class transactor :
00066     public PGSTD::unary_function<TRANSACTION, void>
00067 {
00068 public:
00069   explicit transactor(const PGSTD::string &TName="transactor") :        //[t4]
00070     m_Name(TName) { }
00071 
00073 
00084   void operator()(TRANSACTION &T);                                      //[t4]
00085 
00086   // Overridable member functions, called by connection_base::perform() if an
00087   // attempt to run transaction fails/succeeds, respectively, or if the
00088   // connection is lost at just the wrong moment, goes into an indeterminate
00089   // state.  Use these to patch up runtime state to match events, if needed, or
00090   // to report failure conditions.
00091 
00093 
00101   void on_abort(const char[]) throw () {}                               //[t13]
00102 
00104 
00108   void on_commit() {}                                                   //[t6]
00109 
00111 
00122   void on_doubt() throw () {}                                           //[t13]
00123 
00124 #ifdef PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00125 
00129 
00130 
00131   void OnCommit() {}
00133 
00134   void OnAbort(const char[]) throw () {}
00136 
00137   void OnDoubt() throw () {}
00139 #endif
00140 
00141   // TODO: Rename Name()--is there a compatible way?
00143   PGSTD::string Name() const { return m_Name; }                         //[t13]
00144 
00145 private:
00146   PGSTD::string m_Name;
00147 };
00148 
00149 
00150 }
00151 
00152 
00163 template<typename TRANSACTOR>
00164 inline void pqxx::connection_base::perform(const TRANSACTOR &T,
00165                                            int Attempts)
00166 {
00167   if (Attempts <= 0) return;
00168 
00169   bool Done = false;
00170 
00171   // Make attempts to perform T
00172   // TODO: Differentiate between db-related exceptions and other exceptions?
00173   do
00174   {
00175     --Attempts;
00176 
00177     // Work on a copy of T2 so we can restore the starting situation if need be
00178     TRANSACTOR T2(T);
00179     try
00180     {
00181       typename TRANSACTOR::argument_type X(*this, T2.Name());
00182       T2(X);
00183       X.commit();
00184       Done = true;
00185     }
00186     catch (const in_doubt_error &)
00187     {
00188       // Not sure whether transaction went through or not.  The last thing in
00189       // the world that we should do now is retry.
00190 #ifdef PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00191       T2.OnDoubt();
00192 #endif
00193       T2.on_doubt();
00194       throw;
00195     }
00196     catch (const PGSTD::exception &e)
00197     {
00198       // Could be any kind of error.
00199 #ifdef PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00200       T2.OnAbort(e.what());
00201 #endif
00202       T2.on_abort(e.what());
00203       if (Attempts <= 0) throw;
00204       continue;
00205     }
00206     catch (...)
00207     {
00208       // Don't try to forge ahead if we don't even know what happened
00209 #ifdef PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00210       T2.OnAbort("Unknown exception");
00211 #endif
00212       T2.on_abort("Unknown exception");
00213       throw;
00214     }
00215 
00216 #ifdef PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00217     T2.OnCommit();
00218 #endif
00219     T2.on_commit();
00220   } while (!Done);
00221 }
00222 
00223 

Generated on Mon Oct 3 20:28:59 2005 for libpqxx by  doxygen 1.4.2