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 
00118   // TODO: Define a default Noticer (mainly to help out Windows users)
00120   /** Return value is the previous handler.  Ownership of any previously set 
00121    * Noticer is also passed to the caller, so unless it is stored in another 
00122    * auto_ptr, it will be deleted from the caller's context.  
00123    * This may be important when running under Windows, where a DLL cannot free 
00124    * memory allocated by the main program.
00125    * If a Noticer is set when the ConnectionItf is destructed, it will also be
00126    * deleted.
00127    * @param N the new message handler; must not be null or equal to the old one
00128    */
00129   PGSTD::auto_ptr<Noticer> SetNoticer(PGSTD::auto_ptr<Noticer> N);      //[t14]
00130   Noticer *GetNoticer() const throw () { return m_Noticer.get(); }      //[]
00131 
00133   void ProcessNotice(const char[]) throw ();                            //[t14]
00135   void ProcessNotice(const PGSTD::string &msg) throw ()                 //[t14]
00136         { ProcessNotice(msg.c_str()); }
00137 
00139   void Trace(FILE *);                                                   //[t3]
00140 
00142   void GetNotifs();                                                     //[t4]
00143 
00144   // Miscellaneous query functions (probably not needed very often)
00145  
00147   const char *DbName() const throw ()                                   //[t1]
00148         { Activate(); return PQdb(m_Conn); }
00149 
00151   const char *UserName() const throw ()                                 //[t1]
00152         { Activate(); return  PQuser(m_Conn); }
00153 
00155   const char *HostName() const throw ()                                 //[t1]
00156         { Activate(); return PQhost(m_Conn); }
00157 
00159   const char *Port() const throw ()                                     //[t1]
00160         { Activate(); return PQport(m_Conn); }
00161 
00163   const char *Options() const throw ()                                  //[t1]
00164         { return m_ConnInfo.c_str(); }
00165 
00167 
00174   int BackendPID() const                                                //[t1]
00175         { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00176 
00178 
00188   void Activate() const { if (!m_Conn) Connect(); }                     //[]
00189 
00191 
00199   void Deactivate() const;                                              //[]
00200 
00202 
00208   void SetClientEncoding(const char Encoding[]);                        //[]
00209 
00210 protected:
00212   void Connect() const;
00213 
00214 private:
00215   void SetupState() const;
00216   void InternalSetTrace() const;
00217   int Status() const { return PQstatus(m_Conn); }
00218   const char *ErrMsg() const;
00219   void Reset(const char OnReconnect[]=0);
00220   void close() throw ();
00221 
00222   PGSTD::string m_ConnInfo;     
00223   mutable PGconn *m_Conn;       
00224   Unique<TransactionItf> m_Trans;
00225 
00226   PGSTD::auto_ptr<Noticer> m_Noticer;   
00227   FILE *m_Trace;                
00228 
00229   typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00230   TriggerList m_Triggers;       
00231 
00232   friend class TransactionItf;
00233   Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00234   void RegisterTransaction(const TransactionItf *);
00235   void UnregisterTransaction(const TransactionItf *) throw ();
00236   void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00237   void BeginCopyRead(const PGSTD::string &Table);
00238   bool ReadCopyLine(PGSTD::string &);
00239   void BeginCopyWrite(const PGSTD::string &Table);
00240   void WriteCopyLine(const PGSTD::string &);
00241   void EndCopy();
00242 
00243   friend class LargeObject;
00244   PGconn *RawConnection() const { return m_Conn; }
00245 
00246   friend class Trigger;
00247   void AddTrigger(Trigger *);
00248   void RemoveTrigger(Trigger *) throw ();
00249 
00250   // Not allowed:
00251   ConnectionItf(const ConnectionItf &);
00252   ConnectionItf &operator=(const ConnectionItf &);
00253 };
00254 
00255 
00256 }
00257 
00258 
00269 template<typename TRANSACTOR> 
00270 inline void pqxx::ConnectionItf::Perform(const TRANSACTOR &T,
00271                                          int Attempts)
00272 {
00273   if (Attempts <= 0) return;
00274 
00275   bool Done = false;
00276 
00277   // Make attempts to perform T
00278   // TODO: Differentiate between db-related exceptions and other exceptions?
00279   do
00280   {
00281     --Attempts;
00282 
00283     // Work on a copy of T2 so we can restore the starting situation if need be
00284     TRANSACTOR T2(T);
00285     try
00286     {
00287       typename TRANSACTOR::argument_type X(*this, T2.Name());
00288       T2(X);
00289       X.Commit();
00290       Done = true;
00291     }
00292     catch (const in_doubt_error &)
00293     {
00294       // Not sure whether transaction went through or not.  The last thing in
00295       // the world that we should do now is retry.
00296       T2.OnDoubt();
00297       throw;
00298     }
00299     catch (const PGSTD::exception &e)
00300     {
00301       // Could be any kind of error.  
00302       T2.OnAbort(e.what());
00303       if (Attempts <= 0) throw;
00304       continue;
00305     }
00306     catch (...)
00307     {
00308       // Don't try to forge ahead if we don't even know what happened
00309       T2.OnAbort("Unknown exception");
00310       throw;
00311     }
00312 
00313     T2.OnCommit();
00314   } while (!Done);
00315 }
00316 
00317 
00318 // Put this here so on Windows, any Noticer will be deleted in caller's context
00319 inline pqxx::ConnectionItf::~ConnectionItf()
00320 {
00321   close();
00322 }
00323 
00324 #endif
00325 

Generated on Thu Mar 27 19:34:39 2003 for libpqxx by doxygen1.3-rc3