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 
00029 namespace pqxx
00030 {
00031 
00033 
00062 template<typename TRANSACTION=transaction<read_committed> >
00063   class transactor :
00064     public PGSTD::unary_function<TRANSACTION, void>
00065 {
00066 public:
00067   explicit transactor(const PGSTD::string &TName="transactor") :        //[t4]
00068     m_Name(TName) { }
00069 
00071 
00082   void operator()(TRANSACTION &T);                                      //[t4]
00083 
00084   // Overridable member functions, called by connection_base::perform() if an
00085   // attempt to run transaction fails/succeeds, respectively, or if the
00086   // connection is lost at just the wrong moment, goes into an indeterminate
00087   // state.  Use these to patch up runtime state to match events, if needed, or
00088   // to report failure conditions.
00089 
00091 
00099   void on_abort(const char[]) throw () {}                               //[t13]
00100 
00102 
00106   void on_commit() {}                                                   //[t6]
00107 
00109 
00120   void on_doubt() throw () {}                                           //[t13]
00121 
00122   // TODO: Rename Name()--is there a compatible way?
00124   PGSTD::string Name() const { return m_Name; }                         //[t13]
00125 
00126 private:
00127   PGSTD::string m_Name;
00128 };
00129 
00130 
00131 }
00132 
00133 
00134 template<typename TRANSACTOR>
00135 inline void pqxx::connection_base::perform(const TRANSACTOR &T,
00136                                            int Attempts)
00137 {
00138   if (Attempts <= 0) return;
00139 
00140   bool Done = false;
00141 
00142   // Make attempts to perform T
00143   // TODO: Differentiate between db-related exceptions and other exceptions?
00144   do
00145   {
00146     --Attempts;
00147 
00148     // Work on a copy of T2 so we can restore the starting situation if need be
00149     TRANSACTOR T2(T);
00150     try
00151     {
00152       typename TRANSACTOR::argument_type X(*this, T2.Name());
00153       T2(X);
00154       X.commit();
00155       Done = true;
00156     }
00157     catch (const in_doubt_error &)
00158     {
00159       // Not sure whether transaction went through or not.  The last thing in
00160       // the world that we should do now is retry.
00161       T2.on_doubt();
00162       throw;
00163     }
00164     catch (const PGSTD::exception &e)
00165     {
00166       // Could be any kind of error.
00167       T2.on_abort(e.what());
00168       if (Attempts <= 0) throw;
00169       continue;
00170     }
00171     catch (...)
00172     {
00173       // Don't try to forge ahead if we don't even know what happened
00174       T2.on_abort("Unknown exception");
00175       throw;
00176     }
00177 
00178     T2.on_commit();
00179   } while (!Done);
00180 }
00181 
00182 
00183 #include "pqxx/compiler-internal-post.hxx"

Generated on Thu Feb 1 17:12:08 2007 for libpqxx by  doxygen 1.5.1