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-2006, 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/compiler-public.hxx"
00020 #include "pqxx/compiler-internal-pre.hxx"
00021 
00022 #include "pqxx/connection_base"
00023 #include "pqxx/transaction"
00024 
00025 
00026 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
00027  */
00028 
00030 #define PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00031 
00032 namespace pqxx
00033 {
00034 
00036 
00065 template<typename TRANSACTION=transaction<read_committed> >
00066   class transactor :
00067     public PGSTD::unary_function<TRANSACTION, void>
00068 {
00069 public:
00070   explicit transactor(const PGSTD::string &TName="transactor") :        //[t4]
00071     m_Name(TName) { }
00072 
00074 
00085   void operator()(TRANSACTION &T);                                      //[t4]
00086 
00087   // Overridable member functions, called by connection_base::perform() if an
00088   // attempt to run transaction fails/succeeds, respectively, or if the
00089   // connection is lost at just the wrong moment, goes into an indeterminate
00090   // state.  Use these to patch up runtime state to match events, if needed, or
00091   // to report failure conditions.
00092 
00094 
00102   void on_abort(const char[]) throw () {}                               //[t13]
00103 
00105 
00109   void on_commit() {}                                                   //[t6]
00110 
00112 
00123   void on_doubt() throw () {}                                           //[t13]
00124 
00125 #ifdef PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00126 
00130 
00131 
00132   void OnCommit() {}
00134 
00135   void OnAbort(const char[]) throw () {}
00137 
00138   void OnDoubt() throw () {}
00140 #endif
00141 
00142   // TODO: Rename Name()--is there a compatible way?
00144   PGSTD::string Name() const { return m_Name; }                         //[t13]
00145 
00146 private:
00147   PGSTD::string m_Name;
00148 };
00149 
00150 
00151 }
00152 
00153 
00164 template<typename TRANSACTOR>
00165 inline void pqxx::connection_base::perform(const TRANSACTOR &T,
00166                                            int Attempts)
00167 {
00168   if (Attempts <= 0) return;
00169 
00170   bool Done = false;
00171 
00172   // Make attempts to perform T
00173   // TODO: Differentiate between db-related exceptions and other exceptions?
00174   do
00175   {
00176     --Attempts;
00177 
00178     // Work on a copy of T2 so we can restore the starting situation if need be
00179     TRANSACTOR T2(T);
00180     try
00181     {
00182       typename TRANSACTOR::argument_type X(*this, T2.Name());
00183       T2(X);
00184       X.commit();
00185       Done = true;
00186     }
00187     catch (const in_doubt_error &)
00188     {
00189       // Not sure whether transaction went through or not.  The last thing in
00190       // the world that we should do now is retry.
00191 #ifdef PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00192       T2.OnDoubt();
00193 #endif
00194       T2.on_doubt();
00195       throw;
00196     }
00197     catch (const PGSTD::exception &e)
00198     {
00199       // Could be any kind of error.
00200 #ifdef PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00201       T2.OnAbort(e.what());
00202 #endif
00203       T2.on_abort(e.what());
00204       if (Attempts <= 0) throw;
00205       continue;
00206     }
00207     catch (...)
00208     {
00209       // Don't try to forge ahead if we don't even know what happened
00210 #ifdef PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00211       T2.OnAbort("Unknown exception");
00212 #endif
00213       T2.on_abort("Unknown exception");
00214       throw;
00215     }
00216 
00217 #ifdef PQXX_DEPRECATED_TRANSACTION_CALLBACKS
00218     T2.OnCommit();
00219 #endif
00220     T2.on_commit();
00221   } while (!Done);
00222 }
00223 
00224 
00225 #include "pqxx/compiler-internal-post.hxx"

Generated on Sat May 27 17:33:49 2006 for libpqxx by  doxygen 1.4.6