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

connection.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/connection.h
00005  *
00006  *   DESCRIPTION
00007  *      definition of the pqxx::Connection class.
00008  *   pqxx::Connection encapsulates a frontend to backend connection
00009  *
00010  * Copyright (c) 2001-2003, Jeroen T. Vermeulen <jtv@xs4all.nl>
00011  *
00012  *-------------------------------------------------------------------------
00013  */
00014 #ifndef PQXX_CONNECTION_H
00015 #define PQXX_CONNECTION_H
00016 
00017 #include <map>
00018 #include <stdexcept>
00019 
00020 #include "pqxx/transactor.h"
00021 #include "pqxx/util.h"
00022 
00023 
00024 /* Use of the libpqxx library starts here.
00025  *
00026  * Everything that can be done with a database through libpqxx must go through
00027  * a Connection object.
00028  */
00029 
00030 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
00031  */
00032 
00033 
00035 extern "C" void pqxxNoticeCaller(void *, const char *);
00036 
00037 namespace pqxx
00038 {
00039 class in_doubt_error;   // See pqxx/transactionitf.h
00040 class Result;
00041 class TransactionItf;
00042 class Trigger;
00043 
00045 extern "C" { typedef void (*NoticeProcessor)(void *arg, const char *msg); }
00046 
00048 struct Noticer
00049 {
00050   virtual ~Noticer() {}
00051   virtual void operator()(const char Msg[]) throw () =0;
00052 };
00053 
00054 
00056 template<> inline PGSTD::string Classname(const TransactionItf *) 
00057 { 
00058   return "TransactionItf"; 
00059 }
00060 
00061 
00063 
00064 class broken_connection : public PGSTD::runtime_error
00065 {
00066 public:
00067   broken_connection() : PGSTD::runtime_error("Connection to back end failed") {}
00068   explicit broken_connection(const PGSTD::string &whatarg) : 
00069     PGSTD::runtime_error(whatarg) {}
00070 };
00071 
00072 
00074 
00082 class PQXX_LIBEXPORT Connection
00083 {
00084 public:
00086 
00095   explicit Connection(const PGSTD::string &ConnInfo,
00096                       bool Immediate=true);                             //[t1]
00097 
00099 
00109   explicit Connection(const char ConnInfo[], bool Immediate=true);      //[t2]
00110 
00112 
00116   Connection();                                                         //[t43]
00117 
00119   ~Connection();                                                        //[t1]
00120 
00122   void Disconnect() const throw ();                                     //[t2]
00123 
00125   bool is_open() const;                                                 //[t1]
00126 
00128   bool IsOpen() const { return is_open(); }
00129 
00131   template<typename TRANSACTOR> 
00132   void Perform(const TRANSACTOR &, int Attempts=3);                     //[t4]
00133 
00135 
00138   NoticeProcessor SetNoticeProcessor(NoticeProcessor, void *arg);       //[t1]
00139 
00141 
00143   std::auto_ptr<Noticer> SetNoticer(std::auto_ptr<Noticer>);
00144   Noticer *GetNoticer() const throw () { return m_Noticer.get(); }
00145 
00147   void ProcessNotice(const char[]) throw ();                            //[t1]
00149   void ProcessNotice(const PGSTD::string &msg) throw ()                 //[t1]
00150         { ProcessNotice(msg.c_str()); }
00151 
00153   void Trace(FILE *);                                                   //[t3]
00155   void Untrace() { Trace(0); }
00156 
00157 
00159   void GetNotifs();                                                     //[t4]
00160 
00161   // Miscellaneous query functions (probably not needed very often)
00162  
00164   const char *DbName() const throw ()                                   //[t1]
00165         { Activate(); return PQdb(m_Conn); }
00166 
00168   const char *UserName() const throw ()                                 //[t1]
00169         { Activate(); return  PQuser(m_Conn); }
00170 
00172   const char *HostName() const throw ()                                 //[t1]
00173         { Activate(); return PQhost(m_Conn); }
00174 
00176   const char *Port() const throw ()                                     //[t1]
00177         { Activate(); return PQport(m_Conn); }
00178 
00180   const char *Options() const throw ()                                  //[t1]
00181         { return m_ConnInfo.c_str(); }
00182 
00184 
00191   int BackendPID() const                                                //[t1]
00192         { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00193 
00195 
00205   void Activate() const { if (!m_Conn) Connect(); }                     //[]
00206 
00208 
00216   void Deactivate() const;                                              //[]
00217 
00218 private:
00219   void Connect() const;
00220   void SetupState() const;
00221   void InternalSetTrace() const;
00222   int Status() const { return PQstatus(m_Conn); }
00223   const char *ErrMsg() const;
00224   void Reset(const char OnReconnect[]=0);
00225 
00226   PGSTD::string m_ConnInfo;     
00227   mutable PGconn *m_Conn;       
00228   Unique<TransactionItf> m_Trans;
00229 
00231   mutable NoticeProcessor m_NoticeProcessor;
00232   void *m_NoticeProcessorArg;   // Client-set argument to notice processor func
00233   std::auto_ptr<Noticer> m_Noticer;
00234   FILE *m_Trace;                // File to trace to, if any
00235 
00236   typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00237   TriggerList m_Triggers;
00238 
00239   friend class TransactionItf;
00240   Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00241   void RegisterTransaction(const TransactionItf *);
00242   void UnregisterTransaction(const TransactionItf *) throw ();
00243   void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00244   void BeginCopyRead(const PGSTD::string &Table);
00245   bool ReadCopyLine(PGSTD::string &);
00246   void BeginCopyWrite(const PGSTD::string &Table);
00247   void WriteCopyLine(const PGSTD::string &);
00248   void EndCopy();
00249 
00250   friend class Trigger;
00251   void AddTrigger(Trigger *);
00252   void RemoveTrigger(Trigger *) throw ();
00253 
00254   // Not allowed:
00255   Connection(const Connection &);
00256   Connection &operator=(const Connection &);
00257 };
00258 
00259 
00260 
00271 template<typename TRANSACTOR> 
00272 inline void Connection::Perform(const TRANSACTOR &T,
00273                                 int Attempts)                           //[t4]
00274 {
00275   if (Attempts <= 0) return;
00276 
00277   bool Done = false;
00278 
00279   // Make attempts to perform T
00280   // TODO: Differentiate between db-related exceptions and other exceptions?
00281   do
00282   {
00283     --Attempts;
00284 
00285     // Work on a copy of T2 so we can restore the starting situation if need be
00286     TRANSACTOR T2(T);
00287     try
00288     {
00289       typename TRANSACTOR::argument_type X(*this, T2.Name());
00290       T2(X);
00291       X.Commit();
00292       Done = true;
00293     }
00294     catch (const in_doubt_error &)
00295     {
00296       // Not sure whether transaction went through or not.  The last thing in
00297       // the world that we should do now is retry.
00298       T2.OnDoubt();
00299       throw;
00300     }
00301     catch (const PGSTD::exception &e)
00302     {
00303       // Could be any kind of error.  
00304       T2.OnAbort(e.what());
00305       if (Attempts <= 0) throw;
00306       continue;
00307     }
00308     catch (...)
00309     {
00310       // Don't try to forge ahead if we don't even know what happened
00311       T2.OnAbort("Unknown exception");
00312       throw;
00313     }
00314 
00315     T2.OnCommit();
00316   } while (!Done);
00317 }
00318 
00319 
00320 }
00321 
00322 #endif
00323 

Generated on Tue Feb 11 19:34:19 2003 for libpqxx by doxygen1.3-rc2