Files
Sun1602/LogCollector/SUNLogConsole/DB.cpp
T
2022-10-26 12:25:11 +08:00

353 lines
8.1 KiB
C++

/*------------------------------------------------------------------------------
* DB.cpp
*------------------------------------------------------------------------------
*
*------------------------------------------------------------------------------
* All rights reserved by Jin Hye Jin (jiny7749@hotmail.com)
**----------------------------------------------------------------------------*/
#include "stdafx.h"
#include "DB.h"
#include "LogCriticalSection.h"
/** ----------------------------------------------------------------------------
\brief
\param
\return
------------------------------------------------------------------------------*/
DatabasePool::DatabasePool(int max, TCHAR * dsn, TCHAR * id, TCHAR * passwd, TCHAR * szName)
:m_bConnected(FALSE),
m_nMaxConnection(max),
m_henv(SQL_NULL_HENV),
m_hSemaphore(NULL)
{
if (NULL == dsn ||
NULL == id ||
NULL == passwd)
{
_ASSERTE(!"DatabasePool");
}
m_pDBCS = new LogCriticalSection;
m_pDBInfo = new DBInfo[max]; // DB 정보를 담을 구조체(스레드 개수와 같게)
memset(m_pDBInfo, 0, sizeof(DBInfo) * max);
if (FAILED(StringCchCopy(m_szDsn, sizeof(m_szDsn), dsn)))
{
_ASSERTE(!"StringCchCopy");
}
if (FAILED(StringCchCopy(m_szID, sizeof(m_szID), id)))
{
_ASSERTE(!"StringCchCopy");
}
if (FAILED(StringCchCopy(m_szPasswd, sizeof(m_szPasswd), passwd)))
{
_ASSERTE(!"StringCchCopy");
}
if(szName)
{
/*
TCHAR szCurrentPath[MAX_PATH];
TCHAR szRealName[MAX_PATH];
GetModuleFileName( GetModuleHandle( NULL ), szCurrentPath, MAX_PATH );
*(_tcsrchr( szCurrentPath, _T('\\') ) ) = 0;
StringCchPrintf(szRealName, sizeof(szRealName), _T("%s\\%s"), szCurrentPath, szName);
*/
// create semaphore for resource locking
m_hSemaphore = CreateSemaphore( NULL, // No security attrib.
max, // initial
max, // max
szName);
}
else
{
TCHAR szTmpName[MAX_PATH] = _T("DBHandle");
TCHAR szSemaphoreName[MAX_PATH] = {0};
srand((UINT)time(NULL));
INT nIdx = rand() % 10000;
StringCchPrintf(szSemaphoreName, MAX_PATH, _T("%s%d"), szTmpName, nIdx);
// create semaphore for resource locking
m_hSemaphore = CreateSemaphore( NULL, // No security attrib.
max, // initial
max, // max
szSemaphoreName);
while(ERROR_ALREADY_EXISTS == ::GetLastError())
{
srand((UINT)time(NULL));
nIdx = rand() % 20000;
StringCchPrintf(szSemaphoreName, MAX_PATH, _T("%s%d"), szTmpName, nIdx);
// create semaphore for resource locking
m_hSemaphore = CreateSemaphore( NULL, // No security attrib.
max, // initial
max, // max
szSemaphoreName);
}
}
TRACE("Create Semaphore");
}
/** ----------------------------------------------------------------------------
\brief
\param
\return
------------------------------------------------------------------------------*/
DatabasePool::~DatabasePool()
{
for (int i = 0; i < m_nMaxConnection; i++)
{
if (m_pDBInfo[i].hSQLConnection)
{
SQLDisconnect(m_pDBInfo[i].hSQLConnection);
SQLFreeHandle(SQL_HANDLE_DBC, m_pDBInfo[i].hSQLConnection);
}
}
if (NULL != m_pDBCS)
{
delete m_pDBCS, m_pDBCS = NULL;
}
if (m_pDBInfo)
{
delete [] m_pDBInfo;
m_pDBInfo = NULL;
}
SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
CloseHandle(m_hSemaphore);
m_hSemaphore = NULL;
}
/** ----------------------------------------------------------------------------
\brief
\param
\return
------------------------------------------------------------------------------*/
int DatabasePool::DBConnect()
{
// make connection to database
if ( !AllocEnv(m_henv) )
{
return -1;
}
for (int i = 0; i < m_nMaxConnection; i++)
{
// 할당한 DB정보 구조체에 순서(id)와 DB핸들을 저장한다.
m_pDBInfo[i].id = i;
m_pDBInfo[i].fUse = FALSE; // set flag to "NOT USE"
m_pDBInfo[i].hSQLConnection = ConnectDSN(m_henv,
(TCHAR*)m_szDsn,
(TCHAR*)m_szID,
(TCHAR*)m_szPasswd);
if (m_pDBInfo[i].hSQLConnection == INVALID_HANDLE_VALUE)
{
m_bConnected = FALSE;
}
else
{
m_bConnected = TRUE;
}
}
return 0;
}
/** ----------------------------------------------------------------------------
\brief
\param
\return
------------------------------------------------------------------------------*/
BOOL AllocEnv(SQLHENV & henv)
{
// vars of ODBC connectivity
SQLRETURN retcode;
// Allocate the ODBC Environment and save handle.
retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
if ( !(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) )
{
// Connect failed, call SQLGetDiagRec for errors.
return FALSE;
}
// Let ODBC know this is an ODBC 3.0 application.
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC3,
SQL_IS_INTEGER);
if ( !(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) )
{
// Connect failed, call SQLGetDiagRec for errors.
return FALSE;
}
return TRUE;
}
/** ----------------------------------------------------------------------------
\brief
\param
\return
------------------------------------------------------------------------------*/
SQLHDBC ConnectDSN(SQLHENV & henv, TCHAR * szDSN, TCHAR * szUID, TCHAR * szAuthStr)
{
SQLHDBC connection = SQL_NULL_HDBC;
int retcode;
// Allocate an ODBC connection handle and connect.
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &connection);
if ( !(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) )
{
// Connect failed, call SQLGetDiagRec for errors.
return connection;
}
// connect to ODBC using supplied parameters
retcode = SQLConnect(connection,
(SQLTCHAR*)szDSN,
(SWORD)_tcslen((TCHAR*)&szDSN[0]),
(SQLTCHAR*)szUID,
(SWORD)_tcslen((TCHAR*)&szUID[0]),
(SQLTCHAR*)szAuthStr,
(SWORD)_tcslen((TCHAR*)&szAuthStr[0]));
if ( !(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) )
{
// Connect failed, call SQLGetDiagRec for errors.
return connection;
}
return connection;
}
/** ----------------------------------------------------------------------------
\brief
\param
\return
------------------------------------------------------------------------------*/
pDBInfo DatabasePool::GetDBHandle()
{
DWORD dwWaitResult = 0;
pDBInfo pinfo = NULL;
// wait while connections are available
dwWaitResult = WaitForSingleObject(m_hSemaphore, INFINITE);
//DWORD dwErr = ::GetLastError();
switch ( dwWaitResult )
{
case WAIT_OBJECT_0:
// OK. there's available connection.
__try
{
m_pDBCS->Enter();
// find unused connection
for (int i = 0; i < m_nMaxConnection; i++)
{
if (!m_pDBInfo[i].fUse)
{
m_pDBInfo[i].fUse = TRUE;
pinfo = &m_pDBInfo[i];
break;
}
}
}
__finally
{
m_pDBCS->Leave();
}
break;
case WAIT_TIMEOUT:
// Cannot obtain connection
return NULL;
}
return pinfo;
}
/** ----------------------------------------------------------------------------
\brief
\param
\return
------------------------------------------------------------------------------*/
void DatabasePool::ReleaseDBHandle(pDBInfo pinfo)
{
__try
{
m_pDBCS->Enter();
pinfo->fUse = FALSE;
long previous;
int err = ReleaseSemaphore(m_hSemaphore, // handle to semaphore
1, // increase count by one
&previous);
if (err == FALSE)
{
OutputDebugString(_T("ReleaseDBHandle Function FAIL!!"));
return;
}
}
__finally
{
m_pDBCS->Leave();
}
}
/** ----------------------------------------------------------------------------
\brief
\param
\return
------------------------------------------------------------------------------*/
SQLHSTMT AllocStatement(SQLHDBC & hdbc)
{
// memory allocation for DB handle
int retcode;
SQLHSTMT hstmt;
hstmt = SQL_NULL_HSTMT;
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) )
{
return hstmt;
}
return hstmt;
}
/** ----------------------------------------------------------------------------
\brief
\param
\return
------------------------------------------------------------------------------*/
void FreeStatement (SQLHSTMT hstmt)
{
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
}