Due to work needs, we have found a lot of implementation code about the database connection pool. But find a lot of Java version. I tried to change it, the code is as follows: / ************** *********************************************************** *** ADO object's simple package ************************************************************** *********************************** / # ifndef _Data_base_h_ # define _Data_base_h_ # define catcherror (ptr, a) catch (_COM_ERROR & E) / {/ errorhandler (e, m_errstr); / PTR = null; / return a; /}
#define catcherrget catch (_COM_ERROR & E) / {/ Errorhandler (e, m_errstr); / Sprintf (M_ERRSTR, "% S / N ** for Field Name:% S", M_ERRSTR, FIELDNAME); / RETURN 0; /}
#import "C: / Program Files / Common Files / System / ADO / Msado25.tlb" / Rename ("EOF", "Endoffile")
Typedef _RecordSetPtr Recptr; typedef _ConnectionPtr CNNPTR
Class Database; Class Table;
Class Database {public: Bool rollback (); Bool CompitTrans (); Bool Begintrans (); Void Close (); cnnptr m_cnn; char m_ERRRSTR [500]; Database (); Bool Open (char * Username, char * pwd, char * * CnnStr); bool OpenTbl (int Mode, char * CmdStr, Table & Tbl); bool Execute (char * CmdStr, long * lRecordAffected, long Option); bool Execute (char * CmdStr, Table & Tbl); void GetErrorErrStr (char * errStr };
Class table {public: int getBinarylen (Char * FieldName); Bool getBinary (Char * FieldName, BYTE * PVALUE);
Bool setPageSize; Bool Move; Int getRecordcount (); Bool Get (Char * Fieldnam, DWORD & Value); Bool Get (Char * FieldName, Bool * PValue); Bool Get (Char * FieldName, Short & value); bool get (char * fieldname, byte & value); recptr m_rec; char m_ERRSTR [500]; int m_pagesize;
Table (); void getRrorerrstr (Char * errstr); int ity (); hResult movenext (); hResult moveprevious (); bool movefirst (); hResult movelast (); / * int AddNew (); int update (); int Add (char * FieldName, char * FieldValue); int Add (char * FieldName, int FieldValue); int Add (char * FieldName, float FieldValue); int Add (char * FieldName, double FieldValue); int Add (char * FieldName , long FieldValue); * / bool Get (char * FieldName, char * FieldValue); bool Get (char * FieldName, int & FieldValue); bool Get (char * FieldName, float & FieldValue); bool Get (char * FieldName, double & FieldValue Bool Get (Char * FieldName, Double & FieldValue, Int Scale); Bool Get (Char * FieldName, Long & FieldValue);}; # endif_data_base_h_ // Database.cpp # include
_VARIANT_T VTMISSING1 (DISP_E_PARAMNOTFOUND, VT_ERROR);
Static void errorhandler (_COM_ERROR & E, Char * Errstr) {sprintf (errstr, "error: / n"); sprintf (errstr, "% scode =% 08LX / N", errstr, e.error ()); Sprintf (Errstr , "% scode meaning =% s / n", errstr, (char *) E.ErrorMessage ()); sprintf (errstr, "% ssource =% s / n", errstr, (char *) e.Source () ); Sprintf (errstr, "% sdescription =% s", errstr, (char *) E.DESCRIPTION ());}
Database :: database () {m_cnn = null; sprintf (m_errstr, "null pointer");}
Void Database :: getRrorerrstr (char * errstr) {sprintf (errstr, "% s", m_ERRSTR);}
Void Table :: getRrorerrstr (Char * Errstr) {sprintf (errstr, "% s", m_errstr);}
Bool Database :: Open (Char * Username, Char * PWD, Char * CNNSTR) {// CNN-> Open (STRCNN, "SA", "SA", NULL); Try {HRESULT HR; HR = m_cnn.createInstance __UUIDOF (Connection)); M_CNN-> Open (cnnstr, username, pwd, null);} catcherror (m_cn, 0) Sprintf (M_ERRSTR, "Success"); Return 1;}
Bool Database :: OpenTBL (INT MODE, CHAR * CMDSTR, TABLE & TBL) {IF (m_cnn == null) {TBL.M_REC = NULL; Sprintf (M_ERRSTR, "Invalid Connection); RETURN 0;} Recptr T_REC = NULL; try {// t_Rec-> putref_ActiveConnection (m_Cnn); // vtMissing << - >> _ variant_t ((IDispatch *) m_Cnn, true) t_Rec.CreateInstance (__uuidof (Recordset)); t_Rec-> Open (CmdStr, _variant_t ( (IDispatch *) m_cnn, true, adopenStatic, adopoptimistic, mode);} catcherror (tbl.m_rec, 0)
TBL.M_REC = T_REC; Sprintf (M_ERRSTR, "Success"); Return 1;}
bool Database :: Execute (char * CmdStr, long * lRecordAffected, long Option) {VARIANT var; var.vt = VT_I4; try {m_Cnn-> Execute (CmdStr, & var, Option); * lRecordAffected = var.lVal;} catch (_COM_ERROR & E) {Errorhandler (E, M_ERRSTR);
CString Str; str.format ("Database Execution Error, Message: M_ERRSTR); OUTPUT_MSG (STR); Return 0;} Sprintf (M_ERRSTR," Success "); Return 1;}
Bool Database :: EXECUTE (CHAR * CMDSTR, TABLE & TBL) {// Trace (cmdstr); INT T = Strlen (cmdstr); RECPTR T_REC = NULL; try {t_rec = m_cnn-> Execute (cmdstr, null, 1); }
Catch (_COM_ERROR & E) {ErrorHandler (e, m_errstr);
CString Str; str.format ("Database execution error, message:% S / R / N", m_ERRSTR); OUTPUT_MSG (STR); Return 0;}
Sprintf (M_ERRSTR, "Success"); TBL.M_REC = T_REC; Sprintf (M_ERRSTR, "Success");
Return 1;}
Table :: Table () {m_rec = null; m_pagesize = -1;}
INT TABLE: ISEOF () {INT RS; if (m_rec == null) {sprintf (m_errstr, "invalid record"); return -1;} try {} catchers (m_rec, -2) )
Sprintf (M_ERRSTR, "Success"); Return Rs;
BOOL TABLE :: GET (Char * FieldName, Char * FieldValue) {Try {_variant_t vzzalue; vtvalue = m_rec-> fields-> getitem (fieldName) -> getValue (); if (vtvalue.vt == vt_null) {Sprintf (char *) FieldValue, ""); Return True;} VariantChangeType (& VtValue, & VtValue, 0, Vt_Byref | vt_bstr); Sprintf (FieldValue, "% S", (LPCSTR) ((_ BSTR_T) vtvalue.bstrval);}
Catcherrget
Sprintf (M_ERRSTR, "Success"); Return 1;}
bool Table :: Get (char * FieldName, int & FieldValue) {try {_variant_t vtValue; vtValue = m_Rec-> Fields-> GetItem (FieldName) -> GetValue (); VariantChangeType (& vtValue, & vtValue, 0, VT_I4); FieldValue = VtValue.intVal;
Catcherrget
Sprintf (M_ERRSTR, "Success"); Return 1;}
Bool Table :: Get (Char * FieldName, Float & FieldValue) {Try {_variant_t vzzalue; vtvalue = m_rec-> Fields-> GetItem (FieldName) -> getValue (); if (vtvalue.vt == vt_null) {FieldValue = 0 Return True;} VariantChangeType (& VtValue, & VtValue, 0, VT_R4); FieldValue = VtValue.fltval;
Catcherrget
Sprintf (M_ERRSTR, "Success"); Return 1;}
Bool Table :: Get (Char * FieldName, Double & FieldValue) {Try {_variant_t vzzalue; vtvalue = m_rec-> Fields-> GetItem (FieldName) -> getValue (); if (vtvalue.vt == vt_null) {FieldValue = 0 Return True;} VariantChangeType (& VtValue, & Vzzalue, 0, VT_R8);
FieldValue = vzzalue.dblval; // getDec (VtValue, FieldValue, 3);} catcherrget sprintf (m_errstr, "sucps"); return 1;}
HRESULT TABLE :: MoveNext () {hr = m_rec-> MoveNext ();} catch (_Error & e) {Errorhandler (e, m_errstr); // m_rec = null; return -2;} sprintf (m_ERRSTR) , "Success"); return HR;}
HRESULT TABLE :: MovePrevious () {hResult HR; try {hr = m_rec-> move {} (_COM_ERROR & E) {Errorhandler (e, m_errstr); // m_rec = null; return -2;} sprintf (m_errstr , "Success"); return HR;}
Bool table :: movefirst () {hr = m_rec-> movefirst ();} catch (_rm_error & e) {Errorhandler (e, m_ERRRSTR); // m_rec = null; return false;} sprintf (m_errstr, "Success"); return true;
HRESULT TABLE :: MoveLast () {HRESULT HR; try {hr = m_rec-> MoveLast ();} catch (_E, m_ERRRST); // m_rec = null; return -2;} sprintf (m_ERRSTR) , "Success"); return HR;}
Void Database :: Close () {m_cnn = null;} catch (_COM_ERROR E) {LPCTSTR LPSZ = E.ErrorMessage ();}}
Bool Table :: Get (Char * FieldName, Byte & Value) {_variant_t vzzalue; vtvalue = m_rec-> fields-> GetItem (FIELDNAME) -> getValue (); if (vtvalue.vt == vt_null) {Value = 0 Return True;} VariantChangeType (& VtValue, & VtValue, 0, vt_ui1); value = vtvalue.bval;} catcherrget sprintf (m_ERRSTR, "Success"); Return 1;
}
Bool Table :: Get (Char * FieldName, Short & Value) {_variant_t vzzalue; vtvalue = m_rec-> fields-> GetItem (FieldName) -> getValue ();
IF (vtvalue.vt == vt_null) {value = 0; Return True;} VariantChangeType (& VtValue, & VtValue, 0, vt_i2); value = vtvalue.ival;} catcherrget sprintf (m_ERRSTR, "Success"); return 1;}
Bool Table :: Get (Char * FieldName, Byte * PValue) {Try {_variant_t vzzalue; vtvalue = m_rec-> fields-> GetItem (FieldName) -> getValue (); if (vzzalue.vt == vt_null) {Sprintf (char *) PVALUE, ""); Return True;} VariantChangeType (& VtValue, & VtValue, 0, Vt_BSTR); Sprintf ((char *) PVALUE, "% s", (LPCSTR) ((_ BSTR_T) VtValue.Bstrval))) CatcherRget Sprintf (M_ERRSTR, "Success"); Return 1;}
Bool Table :: Get (Char * FieldName, DWORD & VALUE) {_variant_t vzzalue; vtvalue = m_rec-> fields-> getItem (FieldName) -> getValue (); if (vtvalue.vt == vt_null) {value = 0 Return True;}
VariantChangeType (& VtValue, & VtValue, 0, vt_i4); value = vtvalue.lval;} catcherrget sprintf (m_ERRSTR, "Success"); Return 1;
}
INT Table :: getRecordCount () {if (m_rec == null) Return 0; int RET = 0; if (! ISEOF ()) movefirst (); while (! @EOF ()) {RET ; moranext ();} return Ret;}
Bool Table :: Move (int index) {if (index == 0) return true; try {m_rec-> move (index);} catch (_COM_ERROR E) {lpctstr lpsz = E.ErrorMessage ();} sprintf (m_ERRSTR , "Success"); return 1;}
Bool Database :: beGintrans () {if (m_cnn == null) Return False;
Try {m_cnn-> beginTrans ();} catch (_com_error e) {lpctstr lpsz = E.ErrorMessage (); return false;} return true;} Return true;
Bool Database :: CommitTrans () {if (m_cnn == null) Return False; try {m_cn-> committrans ();} catch (_ERROR E) {LPCTSTR LPSZ = E.ErrorMessage (); return false;} return true; } BOOL TABLE: SETPAGESIZE (INT Size) {if (m_rec == null) Return False; if (getRecordcount () Bool Database :: Rollback () {if (m_cnn == null) Return False; try {m_cn-> rollbackTrans ();} catCH (_COM_ERROR E) {LPCTSTR LPSZ = E.ErrorMessage (); Return False;} Return True; } / * * Purpose:.. Get the binary filed value from data base * the memory of pValue must be allocated by the user * the length of pValue is known as before * / bool Table :: GetBinary (char * FieldName, BYTE * pValue ) {HRESULT hr = -1; try {_StreamPtr m_pStream; hr = m_pStream.CreateInstance (__ uuidof (Stream)); m_pStream-> PutType (adTypeBinary); _variant_t vtEmpty (DISP_E_PARAMNOTFOUND, VT_ERROR); _bstr_t bstrEmpty (L ""); hr = M_PStream-> Open (vTempty, AdmodeunkNown, AdoPenStreamunSpecified, Bstrempty, Bstrempty; HR = m_pstream-> Write (m_rec-> fields-> getitem (fieldname) -> value); m_pstream-> position = 0; _variant_t var (m_pstream-> read (adreadall); long ldatalength = m_pstream-> getSize (); BYTE * PBUFF = (Byte *) Globalalloc (gmem_fixed, ldatalength; if (var.vt == (vt_array | vt_ui1)) {HRESULT HR = -1; HR = SafearrayAccessData (Var.Parray, (void **) & PBuff) ; Memcpy (PVALUE, PBUFF, LDATALENGTH); GlobalFree ((hglobal);} else {globalfree (hglobal); return false;} m_pstream-> close (); } CatCH (_COM_ERROR E) {LPCTSTR LPSZ = E.ErrorMessage (); if (hr == 0) Return True; else returnaf; Return True;} INT Table :: getBinarylen (Char * FieldName) {INT NRET = 0; try {nret = m_rec-> fields-> getitem (fieldname) -> actualsize;} catch (_COM_ERROR E) {nret = 0;} Return nret;} // connObject.h: interface for the cconnobject class.//// #if! defined (afx_connobject_h__2818382c_8737_44d0_b319_1032c614efee__included _) # define afx_connobject_h__2818382c_8737_44d0_b319_1032c614efee__included_ #if _MSC_VER> 1000 # pragma overce # endif //_msc_ver> 1000 # include "database.h" Class cconnpool; class CConnObject {public: CConnObject (CConnPool * pool) {ASSERT (pool); pPool = pool; // conn = NULL; m_bInUse = FALSE; m_nLastEnd = 0; m_nLastBegin = 0; m_nUseCount = 0; m_nTotalUseTime = 0;} ~ CConnObject (); // Using itself, it cannot be turned off, handed over to the connection pool processing. Public: // Release the connection object to the connection pool Void Close (); Database conn; inf m_nlasten; // last use end time int m_nlastbegin; // last start time int m_nusecount; // Use cconnpool * ppool; int m_ntotalusetime; PUBLIC: // Get the total use time int gettotalusetime () {return m_ntotalusetime;}}; cconnobject :: ~ cconnobject () { } Void cconnobject :: close () {m_ntotalusetime = gettickcount () - m_nlastbegin; ppool-> close (this);} # endif /// connpool.h: interface for the cconnpool class.//// #if! defined (AFX_CONNPOOL_H__FD09CC72_3241_4A82_912F_06F92BE1CD54__included _) # Define AFX_CONNPOOL_H__FD09CC72_3241_4A82_912F_06F92BE1CD54__included_ #if _msc_ver> 1000 # prgma overce # endif //_msc_ver> 1000 #include #include "connobject.h" / ********************************************** database connection pool One connection pool corresponds to a library ************************************** // * * / class cconnpool {public: void mobile (); static void __stdcall TimerProc (HWND HWND, UINT MSG, UINT ID, DWORD DWTIME); // Get a connection cconnobject * getConnect (); // release a connection back connection pool vid close (cconnobject * pconn); // destroy the connection pool void destroy (); // Create a connection pool StrConn: Connection Strings Bool Init (CSTRING Strconn; Cconnpool (); virtual ~ cconnpool (); PUBLIC: UINT M_NTIMER; / / Timer CSIMPLEARRAY UINT M_NTIMEOUT; / / Connection Maximum Idle Time UINT M_CONNMAX; / / Connection Quantity UINT M_CONNMIN; / / Connection Number Dimension UINT M_NMAXCOUNT; / / Connection Maximum Usage UINT M_NMAXUSETIME; // Maximum Time CString M_StrConn; // Connection Strings Handle M_CS; / / Ensure that the code is not terminal when changing the connection pool state protected: // Create a new connection cconnobject * createNewConn (); #ndif //! defined (AFX_CONNPOOL_H__FD09CC72_3241_4A82_912F_06F92BE1CD54__included _) // CONNPOOL.CPP: Implementation of the cconnpool class.//// #include "stdafx.h" #include "htrdserver.h" #include "connpool.h" #include "const_def.h" #include "myevent.h" #ifdef _debug # undef this_filestatic char this_file [] = __ file __; # Define new debug_new # Endif //// construction / destruction // CConnpool :: cconnpool () { M_Connmin = conn_min; m_ntimeout = conn_timeout; m_nmaxusetime = conn_max_usetime; m_nmaxcount = 500; M_CS = CreateEvent (NULL, TRUE, TRUE, "DA8B4C9D-E4EF-4C9A-A6D2-941EE98400D2"); } Cconnpool :: ~ cconnpool () {destroy (); Bool cconnpool :: init (cstring strconn) {m_connmax = theApp.m_syssetting.m_nconncount; m_StrConn = StrConn; for (uint i = 0; i } Void cconnpool :: destroy () {for (int i = 0; i M_ListConn [I] -> conn.close (); // m_listconn [i] -> conn-> release (); Delete M_ListConn [i]; m_listconn.removeall (); KillTimer (NULL, M_NTIMER);} / * * Release connection When you need to protect data consistency, use a critical object * / void cconnpool :: close (cconnobject * pconn) {// recycle! CMYEVENT CS (M_CS); For (INT i = 0; I / / Decision is too much, whether the usage time is too much // If you use this connection, recreate if the connection (M_ListConn [i] -> m_nusecount || m_listconn [i] -> getTotalUsetime () > Conn_max_usetime) {OUTPUT_MSG ("There is too much database connection object, you need to reconnect / r / n"); M_ListConn [I] -> conn.close (); if (! M_listconn [i] -> conn.open "", ",", m_strconn.getBuffer (0))) {AFXMessageBox ("Re-Database Connection Objects!"); EXITPROCESS (0);} m_listconn [i] -> m_nlastbegin = 0; m_listconn [i ] -> m_nlasten = 0; m_listconn [i] -> m_ntotalusetime = 0; M_ListConn [i] -> m_nusecount = 0; } Return;}} #ifdef _debug AFXMESSAGEBOX ("The Connect Object Is No Mine!"); # ENDIF } / * * You need to protect data consistency when you get a connection, so use critical object * / cconnobject * cconnpool :: getConnect () {cmyevent cs (m_cs); CconnObject * pobj = null; for (int i = 0; i // The connection pool is full! Return null;} CconnObject * cconnpool :: CreateNewconn () {cconnobject * pconn = new cconnobject (this); if (! Pconn-> conn.open (",", ", _ bstr_t (m_strconn))) Return Null; Return PCONN;} Void CConnpool :: TimerProc (HWND HWND, UINT MSG, UINT ID, DWORD DWTIME) {// chtrdserverapp * PAPP = (chtrdserverapp *) AFXGetApp (); // assert (ppool); // ppool-> onTimer (); / * * Scheduling connection pool * / void cconnpool :: ONTIMER () {dWord dwtime = :: gettickcount (); for (int i = 0; i }}} Else if (m_listconn [i] -> gettotalusetime ()> = (int) m_nmaxusetime) {m_listconn [i] -> conn.close (); delete m_listconn [i]; m_listconn.removeat (i); trace (" One conn use too long / n ");}} / / Check the number of connections, add to the lower limit for (i = m_listconn.getsize (); i <(int) m_connmin; i ) {cconnobject * pobj = createNewConn (); assert (pobj); m_listconn.add (Pobj) }}