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 <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.
00029  */
00030 
00031 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
00032  */
00033 
00034 
00036 extern "C" void pqxxNoticeCaller(void *, const char *);
00037 
00038 namespace pqxx
00039 {
00040 class in_doubt_error;   // See pqxx/transactionitf.h
00041 class Result;
00042 class TransactionItf;
00043 class Trigger;
00044 
00046 extern "C" { typedef void (*NoticeProcessor)(void *arg, const char *msg); }
00047 
00049 struct Noticer
00050 {
00051   virtual ~Noticer() {}
00052   virtual void operator()(const char Msg[]) throw () =0;
00053 };
00054 
00055 
00057 template<> inline PGSTD::string Classname(const TransactionItf *) 
00058 { 
00059   return "TransactionItf"; 
00060 }
00061 
00062 
00064 
00065 class broken_connection : public PGSTD::runtime_error
00066 {
00067 public:
00068   broken_connection() : PGSTD::runtime_error("Connection to back end failed") {}
00069   explicit broken_connection(const PGSTD::string &whatarg) : 
00070     PGSTD::runtime_error(whatarg) {}
00071 };
00072 
00073 
00075 
00083 class PQXX_LIBEXPORT Connection
00084 {
00085 public:
00087 
00096   explicit Connection(const PGSTD::string &ConnInfo,
00097                       bool Immediate=true);                             //[t1]
00098 
00100 
00110   explicit Connection(const char ConnInfo[], bool Immediate=true);      //[t2]
00111 
00113   ~Connection();                                                        //[t1]
00114 
00116   void Disconnect() const throw ();                                     //[t2]
00117 
00119   bool is_open() const;                                                 //[t1]
00120 
00122   bool IsOpen() const { return is_open(); }
00123 
00125   template<typename TRANSACTOR> 
00126   void Perform(const TRANSACTOR &, int Attempts=3);                     //[t4]
00127 
00129 
00132   NoticeProcessor SetNoticeProcessor(NoticeProcessor, void *arg);       //[t1]
00133 
00135 
00137   std::auto_ptr<Noticer> SetNoticer(std::auto_ptr<Noticer>);
00138   Noticer *GetNoticer() const throw () { return m_Noticer.get(); }
00139 
00141   void ProcessNotice(const char[]) throw ();                            //[t1]
00143   void ProcessNotice(const PGSTD::string &msg) throw ()                 //[t1]
00144         { ProcessNotice(msg.c_str()); }
00145 
00147   void Trace(FILE *);                                                   //[t3]
00149   void Untrace() { Trace(0); }
00150 
00151 
00153   void GetNotifs();                                                     //[t4]
00154 
00155   // Miscellaneous query functions (probably not needed very often)
00156  
00158   const char *DbName() const throw ()                                   //[t1]
00159         { Activate(); return PQdb(m_Conn); }
00160 
00162   const char *UserName() const throw ()                                 //[t1]
00163         { Activate(); return  PQuser(m_Conn); }
00164 
00166   const char *HostName() const throw ()                                 //[t1]
00167         { Activate(); return PQhost(m_Conn); }
00168 
00170   const char *Port() const throw ()                                     //[t1]
00171         { Activate(); return PQport(m_Conn); }
00172 
00174   const char *Options() const throw ()                                  //[t1]
00175         { return m_ConnInfo.c_str(); }
00176 
00178 
00185   int BackendPID() const                                                //[t1]
00186         { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00187 
00189 
00199   void Activate() const { if (!m_Conn) Connect(); }                     //[]
00200 
00202 
00210   void Deactivate() const;                                              //[]
00211 
00212 private:
00213   void Connect() const;
00214   void SetupState() const;
00215   void InternalSetTrace() const;
00216   int Status() const { return PQstatus(m_Conn); }
00217   const char *ErrMsg() const;
00218   void Reset(const char OnReconnect[]=0);
00219 
00220   PGSTD::string m_ConnInfo;     
00221   mutable PGconn *m_Conn;       
00222   Unique<TransactionItf> m_Trans;
00223 
00225   mutable NoticeProcessor m_NoticeProcessor;
00226   void *m_NoticeProcessorArg;   // Client-set argument to notice processor func
00227   std::auto_ptr<Noticer> m_Noticer;
00228   FILE *m_Trace;                // File to trace to, if any
00229 
00230   typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00231   TriggerList m_Triggers;
00232 
00233   friend class TransactionItf;
00234   Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00235   void RegisterTransaction(const TransactionItf *);
00236   void UnregisterTransaction(const TransactionItf *) throw ();
00237   void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00238   void BeginCopyRead(const PGSTD::string &Table);
00239   bool ReadCopyLine(PGSTD::string &);
00240   void BeginCopyWrite(const PGSTD::string &Table);
00241   void WriteCopyLine(const PGSTD::string &);
00242   void EndCopy();
00243 
00244   friend class Trigger;
00245   void AddTrigger(Trigger *);
00246   void RemoveTrigger(Trigger *) throw ();
00247 
00248   // Not allowed:
00249   Connection(const Connection &);
00250   Connection &operator=(const Connection &);
00251 };
00252 
00253 
00254 
00265 template<typename TRANSACTOR> 
00266 inline void Connection::Perform(const TRANSACTOR &T,
00267                                 int Attempts)                           //[t4]
00268 {
00269   if (Attempts <= 0) return;
00270 
00271   bool Done = false;
00272 
00273   // Make attempts to perform T
00274   // TODO: Differentiate between db-related exceptions and other exceptions?
00275   do
00276   {
00277     --Attempts;
00278 
00279     // Work on a copy of T2 so we can restore the starting situation if need be
00280     TRANSACTOR T2(T);
00281     try
00282     {
00283       typename TRANSACTOR::argument_type X(*this, T2.Name());
00284       T2(X);
00285       X.Commit();
00286       Done = true;
00287     }
00288     catch (const in_doubt_error &)
00289     {
00290       // Not sure whether transaction went through or not.  The last thing in
00291       // the world that we should do now is retry.
00292       T2.OnDoubt();
00293       throw;
00294     }
00295     catch (const PGSTD::exception &e)
00296     {
00297       // Could be any kind of error.  
00298       T2.OnAbort(e.what());
00299       if (Attempts <= 0) throw;
00300       continue;
00301     }
00302     catch (...)
00303     {
00304       // Don't try to forge ahead if we don't even know what happened
00305       T2.OnAbort("Unknown exception");
00306       throw;
00307     }
00308 
00309     T2.OnCommit();
00310   } while (!Done);
00311 }
00312 
00313 
00314 }
00315 
00316 #endif
00317 

Generated on Sat Feb 15 18:04:49 2003 for libpqxx by doxygen1.3-rc2