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 
00020 #include "pqxx/except.h"
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 Result;
00037 class TransactionItf;
00038 class Trigger;
00039 
00041 
00045 struct PQXX_LIBEXPORT Noticer
00046 {
00047   virtual ~Noticer() {}
00048   virtual void operator()(const char Msg[]) throw () =0;
00049 };
00050 
00051 
00053 template<> inline PGSTD::string Classname(const TransactionItf *) 
00054 { 
00055   return "TransactionItf"; 
00056 }
00057 
00058 
00060 
00069 class PQXX_LIBEXPORT ConnectionItf
00070 {
00071 public:
00073 
00076   explicit ConnectionItf(const PGSTD::string &ConnInfo);                //[t2]
00077 
00079 
00083   explicit ConnectionItf(const char ConnInfo[]);                        //[t2]
00084 
00086   virtual ~ConnectionItf() =0;                                          //[t1]
00087 
00089   void Disconnect() const throw ();                                     //[t2]
00090 
00092   bool is_open() const;                                                 //[t1]
00093 
00095 
00103   template<typename TRANSACTOR> 
00104   void Perform(const TRANSACTOR &T, int Attempts=3);                    //[t4]
00105 
00106   // TODO: Define a default Noticer (mainly to help out Windows users)
00108   /** Return value is the previous handler.  Ownership of any previously set 
00109    * Noticer is also passed to the caller, so unless it is stored in another 
00110    * auto_ptr, it will be deleted from the caller's context.  
00111    * This may be important when running under Windows, where a DLL cannot free 
00112    * memory allocated by the main program.
00113    * If a Noticer is set when the ConnectionItf is destructed, it will also be
00114    * deleted.
00115    * @param N the new message handler; must not be null or equal to the old one
00116    */
00117   PGSTD::auto_ptr<Noticer> SetNoticer(PGSTD::auto_ptr<Noticer> N);      //[t14]
00118   Noticer *GetNoticer() const throw () { return m_Noticer.get(); }      //[]
00119 
00121   void ProcessNotice(const char[]) throw ();                            //[t14]
00123   void ProcessNotice(const PGSTD::string &msg) throw ()                 //[t14]
00124         { ProcessNotice(msg.c_str()); }
00125 
00127   void Trace(FILE *);                                                   //[t3]
00128 
00130   void GetNotifs();                                                     //[t4]
00131 
00132   // Miscellaneous query functions (probably not needed very often)
00133  
00135   const char *DbName() const throw ()                                   //[t1]
00136         { Activate(); return PQdb(m_Conn); }
00137 
00139   const char *UserName() const throw ()                                 //[t1]
00140         { Activate(); return  PQuser(m_Conn); }
00141 
00143   const char *HostName() const throw ()                                 //[t1]
00144         { Activate(); return PQhost(m_Conn); }
00145 
00147   const char *Port() const throw ()                                     //[t1]
00148         { Activate(); return PQport(m_Conn); }
00149 
00151   const char *Options() const throw ()                                  //[t1]
00152         { return m_ConnInfo.c_str(); }
00153 
00155 
00162   int BackendPID() const                                                //[t1]
00163         { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00164 
00166 
00176   void Activate() const { if (!m_Conn) Connect(); }                     //[]
00177 
00179 
00187   void Deactivate() const;                                              //[]
00188 
00190 
00196   void SetClientEncoding(const char Encoding[]);                        //[]
00197 
00198 protected:
00200   void Connect() const;
00201 
00202 private:
00203   void SetupState() const;
00204   void InternalSetTrace() const;
00205   int Status() const { return PQstatus(m_Conn); }
00206   const char *ErrMsg() const;
00207   void Reset(const char OnReconnect[]=0);
00208   void close() throw ();
00209 
00210   PGSTD::string m_ConnInfo;     
00211   mutable PGconn *m_Conn;       
00212   Unique<TransactionItf> m_Trans;
00213 
00214   PGSTD::auto_ptr<Noticer> m_Noticer;   
00215   FILE *m_Trace;                
00216 
00217   typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00218   TriggerList m_Triggers;       
00219 
00220   friend class TransactionItf;
00221   Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00222   void RegisterTransaction(const TransactionItf *);
00223   void UnregisterTransaction(const TransactionItf *) throw ();
00224   void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00225   void BeginCopyRead(const PGSTD::string &Table);
00226   bool ReadCopyLine(PGSTD::string &);
00227   void BeginCopyWrite(const PGSTD::string &Table);
00228   void WriteCopyLine(const PGSTD::string &);
00229   void EndCopy();
00230 
00231   friend class LargeObject;
00232   PGconn *RawConnection() const { return m_Conn; }
00233 
00234   friend class Trigger;
00235   void AddTrigger(Trigger *);
00236   void RemoveTrigger(Trigger *) throw ();
00237 
00238   // Not allowed:
00239   ConnectionItf(const ConnectionItf &);
00240   ConnectionItf &operator=(const ConnectionItf &);
00241 };
00242 
00243 
00244 }
00245 
00246 
00257 template<typename TRANSACTOR> 
00258 inline void pqxx::ConnectionItf::Perform(const TRANSACTOR &T,
00259                                          int Attempts)
00260 {
00261   if (Attempts <= 0) return;
00262 
00263   bool Done = false;
00264 
00265   // Make attempts to perform T
00266   // TODO: Differentiate between db-related exceptions and other exceptions?
00267   do
00268   {
00269     --Attempts;
00270 
00271     // Work on a copy of T2 so we can restore the starting situation if need be
00272     TRANSACTOR T2(T);
00273     try
00274     {
00275       typename TRANSACTOR::argument_type X(*this, T2.Name());
00276       T2(X);
00277       X.Commit();
00278       Done = true;
00279     }
00280     catch (const in_doubt_error &)
00281     {
00282       // Not sure whether transaction went through or not.  The last thing in
00283       // the world that we should do now is retry.
00284       T2.OnDoubt();
00285       throw;
00286     }
00287     catch (const PGSTD::exception &e)
00288     {
00289       // Could be any kind of error.  
00290       T2.OnAbort(e.what());
00291       if (Attempts <= 0) throw;
00292       continue;
00293     }
00294     catch (...)
00295     {
00296       // Don't try to forge ahead if we don't even know what happened
00297       T2.OnAbort("Unknown exception");
00298       throw;
00299     }
00300 
00301     T2.OnCommit();
00302   } while (!Done);
00303 }
00304 
00305 
00306 // Put this here so on Windows, any Noticer will be deleted in caller's context
00307 inline pqxx::ConnectionItf::~ConnectionItf()
00308 {
00309   close();
00310 }
00311 
00312 #endif
00313 

Generated on Sat Mar 29 21:51:03 2003 for libpqxx by doxygen1.3-rc3