00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
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 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 namespace pqxx
00037 {
00038 class in_doubt_error;   
00039 class Result;           
00040 class TransactionItf;   
00041 class Trigger;          
00042 
00043 extern "C" { typedef void (*NoticeProcessor)(void *arg, const char *msg); }
00044 
00045 
00047 template<> inline PGSTD::string Classname(const TransactionItf *) 
00048 { 
00049   return "TransactionItf"; 
00050 }
00051 
00052 
00054 
00055 class broken_connection : public PGSTD::runtime_error
00056 {
00057 public:
00058   broken_connection() : PGSTD::runtime_error("Connection to back end failed") {}
00059   explicit broken_connection(const PGSTD::string &whatarg) : 
00060     PGSTD::runtime_error(whatarg) {}
00061 };
00062 
00063 
00065 
00073 class PQXX_LIBEXPORT Connection
00074 {
00075 public:
00077 
00086   explicit Connection(const PGSTD::string &ConnInfo, 
00087                       bool Immediate=true);                             
00088 
00090   ~Connection();                                                        
00091 
00093   void Disconnect() const throw ();                                     
00094 
00096   bool IsOpen() const;                                                  
00097 
00099   template<typename TRANSACTOR> 
00100   void Perform(const TRANSACTOR &, int Attempts=3);                     
00101 
00103 
00107   NoticeProcessor SetNoticeProcessor(NoticeProcessor, void *arg);       
00108 
00110   void ProcessNotice(const char[]) throw ();                            
00112 
00113         { ProcessNotice(msg.c_str()); }
00114 
00116   void Trace(FILE *);                                                   
00118 
00119 
00120 
00122   void GetNotifs();                                                     
00123 
00124   
00125  
00127   const char *DbName() const throw ()                                   
00128         { Activate(); return PQdb(m_Conn); }
00129 
00131   const char *UserName() const throw ()                                 
00132         { Activate(); return  PQuser(m_Conn); }
00133 
00135   const char *HostName() const throw ()                                 
00136         { Activate(); return PQhost(m_Conn); }
00137 
00139   const char *Port() const throw ()                                     
00140         { Activate(); return PQport(m_Conn); }
00141 
00143   const char *Options() const throw ()                                  
00144         { return m_ConnInfo.c_str(); }
00145 
00147 
00154   int BackendPID() const                                                
00155         { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00156 
00158 
00168   void Activate() const { if (!m_Conn) Connect(); }                     
00169 
00171 
00179   void Deactivate() const;                                              
00180 
00181 private:
00182   void Connect() const;
00183   void SetupState() const;
00184   void InternalSetTrace() const;
00185   int Status() const { return PQstatus(m_Conn); }
00186   const char *ErrMsg() const;
00187   void Reset(const char OnReconnect[]=0);
00188 
00189   PGSTD::string m_ConnInfo;     
00190   mutable PGconn *m_Conn;       
00191   Unique<TransactionItf> m_Trans;
00192 
00194   mutable NoticeProcessor m_NoticeProcessor;
00195   void *m_NoticeProcessorArg;   
00196   FILE *m_Trace;                
00197 
00198   typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00199   TriggerList m_Triggers;
00200 
00201   friend class TransactionItf;
00202   Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00203   void RegisterTransaction(const TransactionItf *);
00204   void UnregisterTransaction(const TransactionItf *) throw ();
00205   void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00206   void BeginCopyRead(PGSTD::string Table);
00207   bool ReadCopyLine(PGSTD::string &);
00208   void BeginCopyWrite(PGSTD::string Table);
00209   void WriteCopyLine(PGSTD::string);
00210   void EndCopy();
00211 
00212   friend class Trigger;
00213   void AddTrigger(Trigger *);
00214   void RemoveTrigger(Trigger *) throw ();
00215 
00216   
00217   Connection(const Connection &);
00218   Connection &operator=(const Connection &);
00219 };
00220 
00221 
00222 
00233 template<typename TRANSACTOR> 
00234 inline void Connection::Perform(const TRANSACTOR &T,
00235                                 int Attempts)                           
00236 {
00237   if (Attempts <= 0) return;
00238 
00239   bool Done = false;
00240 
00241   
00242   
00243   do
00244   {
00245     --Attempts;
00246 
00247     
00248     TRANSACTOR T2(T);
00249     try
00250     {
00251       typename TRANSACTOR::argument_type X(*this, T2.Name());
00252       T2(X);
00253       X.Commit();
00254       Done = true;
00255     }
00256     catch (const in_doubt_error &)
00257     {
00258       
00259       
00260       T2.OnDoubt();
00261       throw;
00262     }
00263     catch (const PGSTD::exception &e)
00264     {
00265       
00266       T2.OnAbort(e.what());
00267       if (Attempts <= 0) throw;
00268       continue;
00269     }
00270     catch (...)
00271     {
00272       
00273       T2.OnAbort("Unknown exception");
00274       throw;
00275     }
00276 
00277     T2.OnCommit();
00278   } while (!Done);
00279 }
00280 
00281 
00282 }
00283 
00284 #endif
00285