Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

connectionitf.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/connectionitf.h
00005  *
00006  *   DESCRIPTION
00007  *      definition of the pqxx::ConnectionItf abstract base class.
00008  *   pqxx::ConnectionItf encapsulates a frontend to backend connection
00009  *
00010  * Copyright (c) 2001-2003, Jeroen T. Vermeulen <jtv@xs4all.nl>
00011  *
00012  *-------------------------------------------------------------------------
00013  */
00014 #ifndef PQXX_CONNECTIONITF_H
00015 #define PQXX_CONNECTIONITF_H
00016 
00017 #include <map>
00018 #include <memory>
00019 #include <stdexcept>
00020 
00021 #include "pqxx/transactor.h"
00022 #include "pqxx/util.h"
00023 
00024 
00025 /* Use of the libpqxx library starts here.
00026  *
00027  * Everything that can be done with a database through libpqxx must go through
00028  * a connection object derived from ConnectionItf.
00029  */
00030 
00031 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
00032  */
00033 
00034 namespace pqxx
00035 {
00036 class in_doubt_error;   // See pqxx/transactionitf.h
00037 class Result;
00038 class TransactionItf;
00039 class Trigger;
00040 
00042 
00046 struct PQXX_LIBEXPORT Noticer
00047 {
00048   virtual ~Noticer() {}
00049   virtual void operator()(const char Msg[]) throw () =0;
00050 };
00051 
00052 
00054 template<> inline PGSTD::string Classname(const TransactionItf *) 
00055 { 
00056   return "TransactionItf"; 
00057 }
00058 
00059 
00061 
00062 class PQXX_LIBEXPORT broken_connection : public PGSTD::runtime_error
00063 {
00064 public:
00065   broken_connection() : PGSTD::runtime_error("Connection to back end failed") {}
00066   explicit broken_connection(const PGSTD::string &whatarg) : 
00067     PGSTD::runtime_error(whatarg) {}
00068 };
00069 
00070 
00072 
00081 class PQXX_LIBEXPORT ConnectionItf
00082 {
00083 public:
00085 
00088   explicit ConnectionItf(const PGSTD::string &ConnInfo);                //[t2]
00089 
00091 
00095   explicit ConnectionItf(const char ConnInfo[]);                        //[t2]
00096 
00098   virtual ~ConnectionItf() =0;                                          //[t1]
00099 
00101   void Disconnect() const throw ();                                     //[t2]
00102 
00104   bool is_open() const;                                                 //[t1]
00105 
00107 
00115   template<typename TRANSACTOR> 
00116   void Perform(const TRANSACTOR &T, int Attempts=3);                    //[t4]
00117 
00119 
00122   std::auto_ptr<Noticer> SetNoticer(std::auto_ptr<Noticer> N);          //[t14]
00123   Noticer *GetNoticer() const throw () { return m_Noticer.get(); }      //[]
00124 
00126   void ProcessNotice(const char[]) throw ();                            //[t14]
00128   void ProcessNotice(const PGSTD::string &msg) throw ()                 //[t14]
00129         { ProcessNotice(msg.c_str()); }
00130 
00132   void Trace(FILE *);                                                   //[t3]
00133 
00135   void GetNotifs();                                                     //[t4]
00136 
00137   // Miscellaneous query functions (probably not needed very often)
00138  
00140   const char *DbName() const throw ()                                   //[t1]
00141         { Activate(); return PQdb(m_Conn); }
00142 
00144   const char *UserName() const throw ()                                 //[t1]
00145         { Activate(); return  PQuser(m_Conn); }
00146 
00148   const char *HostName() const throw ()                                 //[t1]
00149         { Activate(); return PQhost(m_Conn); }
00150 
00152   const char *Port() const throw ()                                     //[t1]
00153         { Activate(); return PQport(m_Conn); }
00154 
00156   const char *Options() const throw ()                                  //[t1]
00157         { return m_ConnInfo.c_str(); }
00158 
00160 
00167   int BackendPID() const                                                //[t1]
00168         { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00169 
00171 
00181   void Activate() const { if (!m_Conn) Connect(); }                     //[]
00182 
00184 
00192   void Deactivate() const;                                              //[]
00193 
00194 protected:
00196   void Connect() const;
00197 
00198 private:
00199   void SetupState() const;
00200   void InternalSetTrace() const;
00201   int Status() const { return PQstatus(m_Conn); }
00202   const char *ErrMsg() const;
00203   void Reset(const char OnReconnect[]=0);
00204 
00205   PGSTD::string m_ConnInfo;     
00206   mutable PGconn *m_Conn;       
00207   Unique<TransactionItf> m_Trans;
00208 
00209   std::auto_ptr<Noticer> m_Noticer;     
00210   FILE *m_Trace;                
00211 
00212   typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00213   TriggerList m_Triggers;       
00214 
00215   friend class TransactionItf;
00216   Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00217   void RegisterTransaction(const TransactionItf *);
00218   void UnregisterTransaction(const TransactionItf *) throw ();
00219   void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00220   void BeginCopyRead(const PGSTD::string &Table);
00221   bool ReadCopyLine(PGSTD::string &);
00222   void BeginCopyWrite(const PGSTD::string &Table);
00223   void WriteCopyLine(const PGSTD::string &);
00224   void EndCopy();
00225 
00226   friend class LargeObject;
00227   PGconn *RawConnection() const { return m_Conn; }
00228 
00229   friend class Trigger;
00230   void AddTrigger(Trigger *);
00231   void RemoveTrigger(Trigger *) throw ();
00232 
00233   // Not allowed:
00234   ConnectionItf(const ConnectionItf &);
00235   ConnectionItf &operator=(const ConnectionItf &);
00236 };
00237 
00238 
00239 }
00240 
00241 
00252 template<typename TRANSACTOR> 
00253 inline void pqxx::ConnectionItf::Perform(const TRANSACTOR &T,
00254                                          int Attempts)
00255 {
00256   if (Attempts <= 0) return;
00257 
00258   bool Done = false;
00259 
00260   // Make attempts to perform T
00261   // TODO: Differentiate between db-related exceptions and other exceptions?
00262   do
00263   {
00264     --Attempts;
00265 
00266     // Work on a copy of T2 so we can restore the starting situation if need be
00267     TRANSACTOR T2(T);
00268     try
00269     {
00270       typename TRANSACTOR::argument_type X(*this, T2.Name());
00271       T2(X);
00272       X.Commit();
00273       Done = true;
00274     }
00275     catch (const in_doubt_error &)
00276     {
00277       // Not sure whether transaction went through or not.  The last thing in
00278       // the world that we should do now is retry.
00279       T2.OnDoubt();
00280       throw;
00281     }
00282     catch (const PGSTD::exception &e)
00283     {
00284       // Could be any kind of error.  
00285       T2.OnAbort(e.what());
00286       if (Attempts <= 0) throw;
00287       continue;
00288     }
00289     catch (...)
00290     {
00291       // Don't try to forge ahead if we don't even know what happened
00292       T2.OnAbort("Unknown exception");
00293       throw;
00294     }
00295 
00296     T2.OnCommit();
00297   } while (!Done);
00298 }
00299 
00300 
00301 #endif
00302 

Generated on Sat Mar 15 20:47:39 2003 for libpqxx by doxygen1.3-rc3